mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
Merge remote-tracking branch 'origin/main' into develop
# Conflicts: # frontend/appflowy_flutter/lib/plugins/database_view/application/database_view_service.dart # frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/base/link_to_page_widget.dart # frontend/appflowy_flutter/lib/plugins/trash/application/trash_bloc.dart # frontend/appflowy_flutter/lib/plugins/trash/application/trash_service.dart # frontend/appflowy_flutter/lib/workspace/application/app/app_bloc.dart # frontend/appflowy_flutter/lib/workspace/application/app/app_service.dart # frontend/appflowy_flutter/lib/workspace/application/menu/menu_bloc.dart # frontend/appflowy_flutter/lib/workspace/application/workspace/workspace_service.dart # frontend/appflowy_flutter/lib/workspace/presentation/home/menu/app/header/header.dart # frontend/appflowy_flutter/test/bloc_test/grid_test/filter/filter_util.dart # frontend/appflowy_flutter/test/bloc_test/grid_test/grid_bloc_test.dart # frontend/appflowy_flutter/test/bloc_test/grid_test/util.dart # frontend/appflowy_flutter/test/bloc_test/home_test/view_bloc_test.dart # frontend/rust-lib/flowy-database/src/services/database/database_editor.rs # frontend/rust-lib/flowy-database/src/services/persistence/migration/database_view_migration.rs
This commit is contained in:
@ -1,4 +1 @@
|
|||||||
frontend/appflowy_flutter/
|
.git
|
||||||
frontend/scripts/
|
|
||||||
frontend/rust-lib/target
|
|
||||||
shared-lib/target/
|
|
||||||
|
47
.github/workflows/docker_ci.yml
vendored
Normal file
47
.github/workflows/docker_ci.yml
vendored
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
name: Docker-CI
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
- release/*
|
||||||
|
paths:
|
||||||
|
- frontend/**
|
||||||
|
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
- release/*
|
||||||
|
paths:
|
||||||
|
- frontend/**
|
||||||
|
types:
|
||||||
|
- opened
|
||||||
|
- synchronize
|
||||||
|
- reopened
|
||||||
|
- unlocked
|
||||||
|
- ready_for_review
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-app:
|
||||||
|
if: github.event.pull_request.draft != true
|
||||||
|
concurrency:
|
||||||
|
group: docker_ci-${{ github.event.pull_request.number || github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout source code
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Build the app
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
set -eu -o pipefail
|
||||||
|
cd frontend/scripts/docker-buildfiles
|
||||||
|
docker-compose build --no-cache --progress=plain \
|
||||||
|
| while read line; do \
|
||||||
|
if [[ "$line" =~ ^Step[[:space:]] ]]; then \
|
||||||
|
echo "$(date -u '+%H:%M:%S') | $line"; \
|
||||||
|
else \
|
||||||
|
echo "$line"; \
|
||||||
|
fi; \
|
||||||
|
done \
|
3
.github/workflows/flutter_ci.yaml
vendored
3
.github/workflows/flutter_ci.yaml
vendored
@ -99,7 +99,8 @@ jobs:
|
|||||||
|
|
||||||
- name: Flutter Analyzer
|
- name: Flutter Analyzer
|
||||||
working-directory: frontend/appflowy_flutter
|
working-directory: frontend/appflowy_flutter
|
||||||
run: flutter analyze
|
run: |
|
||||||
|
flutter analyze .
|
||||||
|
|
||||||
- name: Run Flutter unit tests
|
- name: Run Flutter unit tests
|
||||||
working-directory: frontend
|
working-directory: frontend
|
||||||
|
11
.github/workflows/integration_test.yml
vendored
11
.github/workflows/integration_test.yml
vendored
@ -22,7 +22,7 @@ jobs:
|
|||||||
tests:
|
tests:
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [macos-latest]
|
os: [ubuntu-latest]
|
||||||
|
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
|
|
||||||
@ -105,11 +105,14 @@ jobs:
|
|||||||
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/runner.dart -d Linux --coverage
|
export DISPLAY=:99
|
||||||
|
sudo Xvfb -ac :99 -screen 0 1280x1024x24 > /dev/null 2>&1 &
|
||||||
|
sudo apt-get install network-manager
|
||||||
|
flutter test integration_test/runner.dart -d Linux --coverage --verbose
|
||||||
elif [ "$RUNNER_OS" == "macOS" ]; then
|
elif [ "$RUNNER_OS" == "macOS" ]; then
|
||||||
flutter test integration_test/runner.dart -d macOS --coverage
|
flutter test integration_test/runner.dart -d macOS --coverage --verbose
|
||||||
elif [ "$RUNNER_OS" == "Windows" ]; then
|
elif [ "$RUNNER_OS" == "Windows" ]; then
|
||||||
flutter test integration_test/runner.dart -d Windows --coverage
|
flutter test integration_test/runner.dart -d Windows --coverage --verbose
|
||||||
fi
|
fi
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|
||||||
|
@ -205,12 +205,17 @@ script = [
|
|||||||
]
|
]
|
||||||
script_runner = "@duckscript"
|
script_runner = "@duckscript"
|
||||||
|
|
||||||
[env.test-macos]
|
[env.test-macos-x86_64]
|
||||||
TEST_CRATE_TYPE = "cdylib"
|
TEST_CRATE_TYPE = "cdylib"
|
||||||
TEST_LIB_EXT = "dylib"
|
TEST_LIB_EXT = "dylib"
|
||||||
# For the moment, the DynamicLibrary only supports open x86_64 architectures binary.
|
# For the moment, the DynamicLibrary only supports open x86_64 architectures binary.
|
||||||
TEST_COMPILE_TARGET = "x86_64-apple-darwin"
|
TEST_COMPILE_TARGET = "x86_64-apple-darwin"
|
||||||
|
|
||||||
|
[env.test-macos-arm64]
|
||||||
|
TEST_CRATE_TYPE = "cdylib"
|
||||||
|
TEST_LIB_EXT = "dylib"
|
||||||
|
TEST_COMPILE_TARGET = "aarch64-apple-darwin"
|
||||||
|
|
||||||
[env.test-linux]
|
[env.test-linux]
|
||||||
TEST_CRATE_TYPE = "cdylib"
|
TEST_CRATE_TYPE = "cdylib"
|
||||||
TEST_LIB_EXT = "so"
|
TEST_LIB_EXT = "so"
|
||||||
|
@ -14,9 +14,7 @@ analyzer:
|
|||||||
exclude:
|
exclude:
|
||||||
- "**/*.g.dart"
|
- "**/*.g.dart"
|
||||||
- "**/*.freezed.dart"
|
- "**/*.freezed.dart"
|
||||||
- "packages/appflowy_editor/**"
|
|
||||||
- "packages/editor/**"
|
|
||||||
# - "packages/flowy_infra_ui/**"
|
|
||||||
linter:
|
linter:
|
||||||
# The lint rules applied to this project can be customized in the
|
# The lint rules applied to this project can be customized in the
|
||||||
# section below to disable rules from the `package:flutter_lints/flutter.yaml`
|
# section below to disable rules from the `package:flutter_lints/flutter.yaml`
|
||||||
@ -30,8 +28,7 @@ linter:
|
|||||||
# `// ignore_for_file: name_of_lint` syntax on the line or in the file
|
# `// ignore_for_file: name_of_lint` syntax on the line or in the file
|
||||||
# producing the lint.
|
# producing the lint.
|
||||||
rules:
|
rules:
|
||||||
# avoid_print: false # Uncomment to disable the `avoid_print` rule
|
- require_trailing_commas
|
||||||
# prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
|
|
||||||
|
|
||||||
# Additional information about this file can be found at
|
# Additional information about this file can be found at
|
||||||
# https://dart.dev/guides/language/analysis-options
|
# https://dart.dev/guides/language/analysis-options
|
||||||
|
@ -1,112 +1 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 761.68 143.1"><title>Asset 16</title><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><path d="M271,40.73h18v6.7c4.37-4.68,12.64-8.42,21.69-8.42C330,39,342.5,54,342.5,74.74c0,21.38-14.67,37.92-37.14,37.92-6.24,0-12.32-1.09-16.38-3.44v32.93H271Zm18,22.78v28.4c4.84,3.12,8.89,4,14.82,4,12.48,0,19.66-9,19.66-20.75,0-11.24-6.55-19.35-18.41-19.35C299,55.86,293.35,58.67,289,63.51Z" style="fill:#fff"/><path d="M226.66,39.4c-22.48,0-37.14,16.54-37.14,37.91,0,20.76,12.47,35.74,31.83,35.74,9,0,17.31-3.75,21.68-8.43v6.72h18V52.42C247.68,42.36,232.89,39.4,226.66,39.4ZM243,88.55c-4.37,4.83-10,7.64-16.07,7.64-11.85,0-18.41-8.11-18.41-19.34,0-11.7,7.18-20.76,19.66-20.76,5.93,0,10,.94,14.82,4.07Z" style="fill:#fff"/><path d="M350.16,40.73h17.95v6.7c4.36-4.68,12.63-8.42,21.68-8.42,19.35,0,31.84,15,31.84,35.73,0,21.38-14.67,37.92-37.14,37.92-6.24,0-12.33-1.09-16.38-3.44v32.93H350.16Zm17.95,22.78v28.4c4.83,3.12,8.89,4,14.82,4,12.48,0,19.66-9,19.66-20.75,0-11.24-6.55-19.35-18.41-19.35C378.09,55.86,372.47,58.67,368.11,63.51Z" style="fill:#fff"/><path d="M473.63,20.6a20.34,20.34,0,0,0-11.08-3.75c-8.11,0-12.32,4.22-12.32,13.89v10h12.64V57.58H450.23v53.36h-18V29.34c0-19.51,9.36-29.34,25-29.34,7.18,0,13.73,1.72,18.41,4.68h15.92V84.26c0,8,2,11.39,6.08,11.39a12.6,12.6,0,0,0,7.49-2.81l3.75,13.73c-4.06,3.28-10.15,5.93-18.57,5.93-10.77,0-16.7-6.55-16.7-20.91Z" style="fill:#fff"/><path d="M547.12,39c23.25,0,38.23,15.76,38.23,36.82s-15,36.83-38.23,36.83S508.9,96.9,508.9,75.83,523.87,39,547.12,39Zm0,57c11.08,0,19.2-8,19.2-20.13,0-11.86-8.27-20-19.2-20-10.61,0-19,7.8-19,20C528.09,87.54,536.2,96,547.12,96Z" style="fill:#fff"/><path d="M674.14,111.25H658.07l-15-39c-1.1-2.65-1.56-5.61-2.34-8.27a50.32,50.32,0,0,1-2.5,8.59l-14.82,38.69h-15.3L585.35,40.73h19.2L615.78,79a73.76,73.76,0,0,1,2,9.37A91.46,91.46,0,0,1,620.46,79l13.11-38.22h15.91L663.06,78.8a98.26,98.26,0,0,1,2.65,9.67c.63-3.28,1.41-6.71,2.18-10.14l10.3-37.6h18.1Z" style="fill:#fff"/><path d="M734.06,110.94c-10.3,25.12-16.85,31.21-27.15,31.21-6.4,0-11.08-2.5-15.14-5.46l5.78-13.58c1.87,1.09,4.52,2.5,7.33,2.5,4.53,0,7.8-3.59,10.77-10.92l1.56-3.75L684.75,40.73h21.54l16.38,38.38c1.4,3.43,2.34,6.71,3.43,10.14A71.08,71.08,0,0,1,728.6,79l12.64-38.22h20.44Z" style="fill:#fff"/><path d="M140.91,87.45c-4,21.87-21.71,41-42.18,51.75-2.57,1.35-3.58,2.12-6.47,2.3h41.49a7,7,0,0,0,7.2-7V87.45Z" style="fill:#f7931e"/><path d="M95.68,140.24a15.15,15.15,0,0,1-2.52,0Z" style="fill:#ffce00"/><path d="M54.36,45.23c-.63.51-1.25,1-1.89,1.44C42,54.06,9.9,78,2.65,67.71-4.46,57.58,3,28.86,21.49,15c.35-.28.71-.53,1.06-.78,20-14.09,35-12.13,42.28-1.81C71.63,22.13,64,37.31,54.36,45.23Z" style="fill:#8427e0"/><path d="M132.72,67.41c-9.91,7-25.55-1.17-33.32-11.14-.31-.4-.61-.81-.91-1.22-7.38-10.51-31.34-42.57-21-49.82s39.94.67,53.45,19.9c.3.43.59.85.87,1.27C144.91,45.8,142.81,60.31,132.72,67.41Z" style="fill:#00b5ff"/><path d="M119.45,130.66c-.34.26-.69.52-1,.76-20,14.09-35,12.12-42.28,1.82-6.79-9.68.8-24.85,10.46-32.78.62-.52,1.26-1,1.9-1.45C99,91.62,131.06,67.67,138.31,78,145.42,88.1,137.93,116.83,119.45,130.66Z" style="fill:#ffbd00"/><path d="M63.51,140.45c-10.32,7.24-39.94-.67-53.45-19.91-.28-.38-.54-.77-.8-1.16a0,0,0,0,0,0,0c-13.19-19.44-11.1-34-1-41.08,9.9-7,25.55,1.15,33.31,11.12.31.4.62.82.91,1.23C49.86,101.14,73.82,133.2,63.51,140.45Z" style="fill:#e3006d"/><path d="M54.36,45.23C40,51.53,9.65,64.64,5.08,54.12,1.25,45.3,8.34,27.25,21.49,15c.35-.28.71-.53,1.06-.78,20-14.09,35-12.13,42.28-1.81C71.63,22.13,64,37.31,54.36,45.23Z" style="fill:#9327ff"/><path d="M132.72,67.41c-9.91,7-25.55-1.17-33.32-11.14C93,41.57,80.68,12.49,91,8c9.26-4,28.65,4,40.83,18.37C144.91,45.8,142.81,60.31,132.72,67.41Z" style="fill:#00c8ff"/><path d="M119.45,130.66c-.34.26-.69.52-1,.76-20,14.09-35,12.12-42.28,1.82-6.79-9.68.8-24.85,10.46-32.78,14.32-6.3,44.72-19.42,49.29-8.91C139.71,100.38,132.62,118.44,119.45,130.66Z" style="fill:#ffce00"/><path d="M50,137.65c-9.23,4-28.57-3.94-40.75-18.27a0,0,0,0,0,0,0c-13.19-19.44-11.1-34-1-41.08,9.9-7,25.55,1.15,33.31,11.12C48,104.11,60.28,133.2,50,137.65Z" style="fill:#fb006d"/></g></g></svg>
|
||||||
<svg
|
|
||||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
|
||||||
xmlns:cc="http://creativecommons.org/ns#"
|
|
||||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
|
||||||
xmlns:svg="http://www.w3.org/2000/svg"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
id="svg873"
|
|
||||||
version="1.1"
|
|
||||||
fill="none"
|
|
||||||
viewBox="0 0 92 17"
|
|
||||||
height="17"
|
|
||||||
width="92">
|
|
||||||
<metadata
|
|
||||||
id="metadata877">
|
|
||||||
<rdf:RDF>
|
|
||||||
<cc:Work
|
|
||||||
rdf:about="">
|
|
||||||
<dc:format>image/svg+xml</dc:format>
|
|
||||||
<dc:type
|
|
||||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
|
||||||
<dc:title></dc:title>
|
|
||||||
</cc:Work>
|
|
||||||
</rdf:RDF>
|
|
||||||
</metadata>
|
|
||||||
<g
|
|
||||||
id="g866"
|
|
||||||
clip-path="url(#clip0)">
|
|
||||||
<path
|
|
||||||
style="fill:#ffffff"
|
|
||||||
id="path834"
|
|
||||||
fill="black"
|
|
||||||
d="M32.7324 4.84144H34.892V5.63601C35.4179 5.08166 36.4132 4.63818 37.5212 4.63818C39.8498 4.63818 41.3709 6.4121 41.3709 8.88818C41.3709 11.4197 39.6057 13.3969 36.8827 13.3969C36.1315 13.3969 35.3991 13.2675 34.9108 12.9904V16.9078H32.7512V4.84144H32.7324ZM34.9108 7.53927V10.9208C35.493 11.2904 35.9812 11.4012 36.6949 11.4012C38.1972 11.4012 39.0611 10.3295 39.0611 8.94362C39.0611 7.61318 38.2723 6.65231 36.8451 6.65231C36.1127 6.63384 35.4366 6.96644 34.9108 7.53927Z" />
|
|
||||||
<path
|
|
||||||
style="fill:#ffffff"
|
|
||||||
id="path836"
|
|
||||||
fill="black"
|
|
||||||
d="M27.3804 4.6748C24.6573 4.6748 22.8921 6.6335 22.8921 9.1835C22.8921 11.6596 24.3944 13.4335 26.7419 13.4335C27.8311 13.4335 28.8264 12.99 29.371 12.4357V13.2302H31.5306V6.22698C29.9156 5.02589 28.1315 4.6748 27.3804 4.6748ZM29.3522 10.5324C28.8264 11.1052 28.1503 11.4378 27.4179 11.4378C25.9907 11.4378 25.2019 10.477 25.2019 9.14654C25.2019 7.76067 26.0658 6.67046 27.5681 6.67046C28.2818 6.67046 28.77 6.78133 29.3522 7.15089V10.5324Z" />
|
|
||||||
<path
|
|
||||||
style="fill:#ffffff"
|
|
||||||
id="path838"
|
|
||||||
fill="black"
|
|
||||||
d="M42.291 4.84144H44.4506V5.63601C44.9765 5.08166 45.9718 4.63818 47.0797 4.63818C49.4084 4.63818 50.9295 6.4121 50.9295 8.88818C50.9295 11.4197 49.1642 13.3969 46.4412 13.3969C45.6901 13.3969 44.9577 13.2675 44.4694 12.9904V16.9078H42.3098V4.84144H42.291ZM44.4694 7.53927V10.9208C45.0516 11.2904 45.5398 11.4012 46.2535 11.4012C47.7558 11.4012 48.6196 10.3295 48.6196 8.94362C48.6196 7.61318 47.8309 6.65231 46.4037 6.65231C45.6713 6.63384 44.9952 6.96644 44.4694 7.53927Z" />
|
|
||||||
<path
|
|
||||||
style="fill:#ffffff"
|
|
||||||
id="path840"
|
|
||||||
fill="black"
|
|
||||||
d="M57.2019 2.43913C56.8826 2.21739 56.3756 1.99565 55.8685 1.99565C54.892 1.99565 54.3849 2.49457 54.3849 3.64022V4.82283H55.9061V6.83696H54.3849V13.175H52.2065V3.49239C52.2065 1.18261 53.3333 0 55.23 0C56.0939 0 56.8826 0.203261 57.446 0.554348H59.3615V10.0152C59.3615 10.9576 59.6056 11.3641 60.0939 11.3641C60.4507 11.3641 60.7324 11.2163 60.9953 11.0315L61.446 12.6576C60.9577 13.0457 60.2253 13.3598 59.2112 13.3598C57.9155 13.3598 57.2019 12.5837 57.2019 10.8837V2.43913Z" />
|
|
||||||
<path
|
|
||||||
style="fill:#ffffff"
|
|
||||||
id="path842"
|
|
||||||
fill="black"
|
|
||||||
d="M66.0846 4.63818C68.9015 4.63818 70.7043 6.50449 70.7043 9.01753C70.7043 11.5121 68.9015 13.3969 66.0846 13.3969C63.2677 13.3969 61.4648 11.5306 61.4648 9.01753C61.4648 6.50449 63.2864 4.63818 66.0846 4.63818ZM66.0846 11.4012C67.4179 11.4012 68.3944 10.4588 68.3944 9.01753C68.3944 7.61318 67.3991 6.65231 66.0846 6.65231C64.8076 6.65231 63.7935 7.57623 63.7935 9.01753C63.7935 10.4034 64.77 11.4012 66.0846 11.4012Z" />
|
|
||||||
<path
|
|
||||||
style="fill:#ffffff"
|
|
||||||
id="path844"
|
|
||||||
fill="black"
|
|
||||||
d="M81.4271 13.2307H79.4928L77.69 8.59264C77.5586 8.27851 77.5022 7.92742 77.4083 7.61329C77.3332 7.98286 77.2393 8.29699 77.1079 8.6296L75.305 13.2307H73.4647L70.7041 4.84155H73.014L74.3661 9.38721C74.4975 9.79373 74.5351 10.1079 74.6102 10.4959C74.7041 10.1448 74.7604 9.84916 74.9295 9.38721L76.5069 4.84155H78.4224L80.0562 9.36873C80.1877 9.73829 80.2816 10.1263 80.3755 10.5144C80.4506 10.1263 80.5445 9.71981 80.6384 9.31329L81.8778 4.84155H84.0562L81.4271 13.2307Z" />
|
|
||||||
<path
|
|
||||||
style="fill:#ffffff"
|
|
||||||
id="path846"
|
|
||||||
fill="black"
|
|
||||||
d="M88.6574 13.1936C87.4179 16.187 86.6292 16.9077 85.371 16.9077C84.601 16.9077 84.0377 16.612 83.5494 16.2609L84.2442 14.6533C84.4696 14.7827 84.7888 14.949 85.1269 14.949C85.6715 14.949 86.0658 14.524 86.4226 13.6555L86.6104 13.212L82.6855 4.85986H85.2959L87.2677 9.42399C87.4367 9.83052 87.5494 10.2186 87.6808 10.6251C87.756 10.237 87.8311 9.83052 87.9813 9.40552L89.5024 4.85986H91.9625L88.6574 13.1936Z" />
|
|
||||||
<path
|
|
||||||
id="path848"
|
|
||||||
fill="#F7931E"
|
|
||||||
d="M17.0142 10.4033C16.5259 13.0088 14.3851 15.2816 11.925 16.5566C11.6245 16.7229 11.2677 16.8153 10.9297 16.8338H16.1503C16.6574 16.8338 17.0142 16.4642 17.0142 16.0022V10.4033Z" />
|
|
||||||
<path
|
|
||||||
id="path850"
|
|
||||||
fill="#8427E0"
|
|
||||||
d="M6.57258 5.37743C6.49746 5.43286 6.42235 5.4883 6.34723 5.54373C5.07023 6.43069 1.20169 9.27634 0.319059 8.0383C-0.544791 6.83721 0.375397 3.43721 2.59136 1.79264C2.62892 1.75569 2.68526 1.73721 2.72281 1.70025C5.14535 0.0187313 6.94817 0.258949 7.8308 1.47851C8.65709 2.62417 7.7369 4.43504 6.57258 5.37743Z" />
|
|
||||||
<path
|
|
||||||
id="path852"
|
|
||||||
fill="#00B5FF"
|
|
||||||
d="M16.0373 8.02043C14.8354 8.85195 12.9575 7.89108 12.0185 6.69C11.981 6.63456 11.9434 6.59761 11.9059 6.54217C11.0045 5.28565 8.11244 1.47913 9.35188 0.629126C10.5913 -0.239352 14.1782 0.703039 15.812 2.99434C15.8495 3.04978 15.8871 3.08674 15.9246 3.14217C17.5021 5.45195 17.258 7.17043 16.0373 8.02043Z" />
|
|
||||||
<path
|
|
||||||
id="path854"
|
|
||||||
fill="#FFBD00"
|
|
||||||
d="M14.4226 15.5219C14.385 15.5589 14.3475 15.5773 14.2911 15.6143C11.8686 17.2958 10.0658 17.0556 9.18315 15.836C8.35686 14.6904 9.27705 12.8795 10.4414 11.9371C10.5165 11.8817 10.5916 11.8263 10.6667 11.7708C11.9437 10.9023 15.8123 8.03821 16.6761 9.27625C17.5587 10.4773 16.6573 13.8773 14.4226 15.5219Z" />
|
|
||||||
<path
|
|
||||||
id="path856"
|
|
||||||
fill="#E3006D"
|
|
||||||
d="M7.66182 16.6859C6.42238 17.5544 2.85431 16.612 1.22051 14.3207C1.18295 14.2838 1.14539 14.2283 1.12661 14.1914C-0.469635 11.8816 -0.206725 10.1446 1.01393 9.31311C2.21581 8.48159 4.09374 9.44246 5.03271 10.6435C5.07027 10.699 5.10783 10.7359 5.14539 10.7914C6.02802 12.0294 8.92004 15.8359 7.66182 16.6859Z" />
|
|
||||||
<path
|
|
||||||
id="path858"
|
|
||||||
fill="#9327FF"
|
|
||||||
d="M6.57283 5.37743C4.84513 6.13504 1.16438 7.68721 0.619779 6.43069C0.150295 5.37743 1.01415 3.23395 2.59161 1.79264C2.62917 1.75569 2.68551 1.73721 2.72307 1.70025C5.1456 0.0187312 6.94842 0.258949 7.83105 1.47851C8.65734 2.62417 7.73715 4.43504 6.57283 5.37743Z" />
|
|
||||||
<path
|
|
||||||
id="path860"
|
|
||||||
fill="#00C8FF"
|
|
||||||
d="M16.0374 8.01967C14.8355 8.8512 12.9576 7.89033 12.0186 6.68924C11.2487 4.9338 9.76511 1.47837 11.0045 0.960978C12.1313 0.480543 14.4599 1.44141 15.9435 3.14141C17.5022 5.4512 17.2581 7.16967 16.0374 8.01967Z" />
|
|
||||||
<path
|
|
||||||
id="path862"
|
|
||||||
fill="#FFCE00"
|
|
||||||
d="M14.4226 15.5217C14.385 15.5586 14.3475 15.5771 14.2911 15.6141C11.8686 17.2956 10.0658 17.0554 9.18315 15.8358C8.35686 14.6901 9.27705 12.8793 10.4414 11.9369C12.1691 11.1793 15.8498 9.6271 16.3944 10.8836C16.8827 11.9369 16.0188 14.0804 14.4226 15.5217Z" />
|
|
||||||
<path
|
|
||||||
id="path864"
|
|
||||||
fill="#FB006D"
|
|
||||||
d="M6.0468 16.3533C4.92004 16.8338 2.5914 15.8914 1.12661 14.1914C-0.469635 11.8816 -0.206725 10.1446 1.01393 9.31311C2.21581 8.48159 4.09374 9.44246 5.03271 10.6435C5.80266 12.3805 7.28623 15.8359 6.0468 16.3533Z" />
|
|
||||||
</g>
|
|
||||||
<defs
|
|
||||||
id="defs871">
|
|
||||||
<clipPath
|
|
||||||
id="clip0">
|
|
||||||
<rect
|
|
||||||
id="rect868"
|
|
||||||
fill="white"
|
|
||||||
height="17"
|
|
||||||
width="92" />
|
|
||||||
</clipPath>
|
|
||||||
</defs>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 7.5 KiB After Width: | Height: | Size: 4.1 KiB |
@ -70,7 +70,8 @@
|
|||||||
"name": "Debug-Informationen",
|
"name": "Debug-Informationen",
|
||||||
"success": "Debug-Informationen in die Zwischenablage kopiert!",
|
"success": "Debug-Informationen in die Zwischenablage kopiert!",
|
||||||
"fail": "Debug-Informationen können nicht in die Zwischenablage kopiert werden"
|
"fail": "Debug-Informationen können nicht in die Zwischenablage kopiert werden"
|
||||||
}
|
},
|
||||||
|
"shortcuts": "Abkürzungen"
|
||||||
},
|
},
|
||||||
"menuAppHeader": {
|
"menuAppHeader": {
|
||||||
"addPageTooltip": "Schnell eine Seite innerhalb hinzufügen",
|
"addPageTooltip": "Schnell eine Seite innerhalb hinzufügen",
|
||||||
@ -90,11 +91,13 @@
|
|||||||
"inlineCode": "Inline-Code",
|
"inlineCode": "Inline-Code",
|
||||||
"quote": "Zitat",
|
"quote": "Zitat",
|
||||||
"header": "Überschrift",
|
"header": "Überschrift",
|
||||||
"highlight": "Hervorhebung"
|
"highlight": "Hervorhebung",
|
||||||
|
"color": "Farbe"
|
||||||
},
|
},
|
||||||
"tooltip": {
|
"tooltip": {
|
||||||
"lightMode": "In den hellen Modus wechseln",
|
"lightMode": "In den hellen Modus wechseln",
|
||||||
"darkMode": "In den dunklen Modus wechseln"
|
"darkMode": "In den dunklen Modus wechseln",
|
||||||
|
"openAsPage": "Als Seite öffnen"
|
||||||
},
|
},
|
||||||
"contactsPage": {
|
"contactsPage": {
|
||||||
"title": "Kontakte",
|
"title": "Kontakte",
|
||||||
@ -145,6 +148,12 @@
|
|||||||
"sideBar": {
|
"sideBar": {
|
||||||
"openSidebar": "Open sidebar",
|
"openSidebar": "Open sidebar",
|
||||||
"closeSidebar": "Close sidebar"
|
"closeSidebar": "Close sidebar"
|
||||||
|
},
|
||||||
|
"moreAction": {
|
||||||
|
"small": "klein",
|
||||||
|
"medium": "mittel",
|
||||||
|
"large": "groß",
|
||||||
|
"fontSize": "Schriftgröße",
|
||||||
|
"import": "Importieren"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -282,6 +282,7 @@
|
|||||||
"dateFormatISO": "Year-Month-Day",
|
"dateFormatISO": "Year-Month-Day",
|
||||||
"dateFormatLocal": "Month/Day/Year",
|
"dateFormatLocal": "Month/Day/Year",
|
||||||
"dateFormatUS": "Year/Month/Day",
|
"dateFormatUS": "Year/Month/Day",
|
||||||
|
"dateFormatDayMonthYear": "Day/Month/Year",
|
||||||
"timeFormat": "Time format",
|
"timeFormat": "Time format",
|
||||||
"invalidTimeFormat": "Invalid format",
|
"invalidTimeFormat": "Invalid format",
|
||||||
"timeFormatTwelveHour": "12 hour",
|
"timeFormatTwelveHour": "12 hour",
|
||||||
@ -290,7 +291,7 @@
|
|||||||
"optionTitle": "Options",
|
"optionTitle": "Options",
|
||||||
"addOption": "Add option",
|
"addOption": "Add option",
|
||||||
"editProperty": "Edit property",
|
"editProperty": "Edit property",
|
||||||
"newColumn": "New column",
|
"newProperty": "New property",
|
||||||
"deleteFieldPromptMessage": "Are you sure? This property will be deleted"
|
"deleteFieldPromptMessage": "Are you sure? This property will be deleted"
|
||||||
},
|
},
|
||||||
"sort": {
|
"sort": {
|
||||||
@ -383,7 +384,9 @@
|
|||||||
"pickFromFiles": "Pick from files",
|
"pickFromFiles": "Pick from files",
|
||||||
"couldNotFetchImage": "Could not fetch image",
|
"couldNotFetchImage": "Could not fetch image",
|
||||||
"imageSavingFailed": "Image Saving Failed",
|
"imageSavingFailed": "Image Saving Failed",
|
||||||
"addIcon": "Add Icon"
|
"addIcon": "Add Icon",
|
||||||
|
"coverRemoveAlert": "It will be removed from cover after it is deleted.",
|
||||||
|
"alertDialogConfirmation": "Are you sure, you want to continue?"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -271,7 +271,7 @@
|
|||||||
"optionTitle": "Aukerak",
|
"optionTitle": "Aukerak",
|
||||||
"addOption": "Gehitu aukera",
|
"addOption": "Gehitu aukera",
|
||||||
"editProperty": "Editatu propietatea",
|
"editProperty": "Editatu propietatea",
|
||||||
"newColumn": "Zutabe berria",
|
"newProperty": "Zutabe berria",
|
||||||
"deleteFieldPromptMessage": "Ziur al zaude? Propietate hau ezabatu egingo da"
|
"deleteFieldPromptMessage": "Ziur al zaude? Propietate hau ezabatu egingo da"
|
||||||
},
|
},
|
||||||
"sort": {
|
"sort": {
|
||||||
|
@ -195,7 +195,7 @@
|
|||||||
"optionTitle": "Options",
|
"optionTitle": "Options",
|
||||||
"addOption": "Ajouter une option",
|
"addOption": "Ajouter une option",
|
||||||
"editProperty": "Modifier la propriété",
|
"editProperty": "Modifier la propriété",
|
||||||
"newColumn": "Nouvelle colonne",
|
"newProperty": "Nouvelle colonne",
|
||||||
"deleteFieldPromptMessage": "Vous voulez supprimer cette propriété ?"
|
"deleteFieldPromptMessage": "Vous voulez supprimer cette propriété ?"
|
||||||
},
|
},
|
||||||
"row": {
|
"row": {
|
||||||
|
@ -191,7 +191,7 @@
|
|||||||
"optionTitle": "옵션",
|
"optionTitle": "옵션",
|
||||||
"addOption": "옵션 추가",
|
"addOption": "옵션 추가",
|
||||||
"editProperty": "속성 편집",
|
"editProperty": "속성 편집",
|
||||||
"newColumn": "열 추가",
|
"newProperty": "열 추가",
|
||||||
"deleteFieldPromptMessage": "해당 속성을 삭제 하시겠습니까?"
|
"deleteFieldPromptMessage": "해당 속성을 삭제 하시겠습니까?"
|
||||||
},
|
},
|
||||||
"row": {
|
"row": {
|
||||||
|
@ -287,7 +287,7 @@
|
|||||||
"optionTitle": "Opções",
|
"optionTitle": "Opções",
|
||||||
"addOption": "Adicioar opção",
|
"addOption": "Adicioar opção",
|
||||||
"editProperty": "Editar propriedade",
|
"editProperty": "Editar propriedade",
|
||||||
"newColumn": "Nova coluna",
|
"newProperty": "Nova coluna",
|
||||||
"deleteFieldPromptMessage": "Tem certeza? Esta propriedade será excluída"
|
"deleteFieldPromptMessage": "Tem certeza? Esta propriedade será excluída"
|
||||||
},
|
},
|
||||||
"sort": {
|
"sort": {
|
||||||
|
@ -146,5 +146,4 @@
|
|||||||
"openSidebar": "Open sidebar",
|
"openSidebar": "Open sidebar",
|
||||||
"closeSidebar": "Close sidebar"
|
"closeSidebar": "Close sidebar"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -130,7 +130,14 @@
|
|||||||
"signIn": "Войти",
|
"signIn": "Войти",
|
||||||
"signOut": "Выйти",
|
"signOut": "Выйти",
|
||||||
"complete": "Завершить",
|
"complete": "Завершить",
|
||||||
"save": "Сохранить"
|
"save": "Сохранить",
|
||||||
|
"generate": "Сгенерировать",
|
||||||
|
"esc": "ESC",
|
||||||
|
"keep": "Оставить",
|
||||||
|
"tryAgain": "Повторить",
|
||||||
|
"discard": "Отменить",
|
||||||
|
"replace": "Заменить",
|
||||||
|
"insertBelow": "Вставить ниже"
|
||||||
},
|
},
|
||||||
"label": {
|
"label": {
|
||||||
"welcome": "Добро пожаловать!",
|
"welcome": "Добро пожаловать!",
|
||||||
@ -189,7 +196,14 @@
|
|||||||
"browser": "Обзор",
|
"browser": "Обзор",
|
||||||
"create": "Создать",
|
"create": "Создать",
|
||||||
"folderPath": "Путь к вашей папке",
|
"folderPath": "Путь к вашей папке",
|
||||||
"locationCannotBeEmpty": "Путь не может быть пустым"
|
"locationCannotBeEmpty": "Путь не может быть пустым",
|
||||||
|
"pathCopiedSnackbar": "File storage path copied to clipboard!"
|
||||||
|
},
|
||||||
|
"user": {
|
||||||
|
"name": "Имя",
|
||||||
|
"icon": "Иконка",
|
||||||
|
"selectAnIcon": "Выбрать иконку",
|
||||||
|
"pleaseInputYourOpenAIKey": "Введите токен OpenAI"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"grid": {
|
"grid": {
|
||||||
@ -265,7 +279,8 @@
|
|||||||
"dateFormatISO": "Год-Месяц-День",
|
"dateFormatISO": "Год-Месяц-День",
|
||||||
"dateFormatLocal": "Месяц/День/Год",
|
"dateFormatLocal": "Месяц/День/Год",
|
||||||
"dateFormatUS": "Год/Месяц/День",
|
"dateFormatUS": "Год/Месяц/День",
|
||||||
"timeFormat": "Форматировать время",
|
"dateFormatDayMonthYear": "День/Mесяц/Год",
|
||||||
|
"timeFormat": "Формат времени",
|
||||||
"invalidTimeFormat": "Неверный формат",
|
"invalidTimeFormat": "Неверный формат",
|
||||||
"timeFormatTwelveHour": "12 часов",
|
"timeFormatTwelveHour": "12 часов",
|
||||||
"timeFormatTwentyFourHour": "24 часа",
|
"timeFormatTwentyFourHour": "24 часа",
|
||||||
@ -273,7 +288,7 @@
|
|||||||
"optionTitle": "Варианты",
|
"optionTitle": "Варианты",
|
||||||
"addOption": "Добавить",
|
"addOption": "Добавить",
|
||||||
"editProperty": "Редактировать свойство",
|
"editProperty": "Редактировать свойство",
|
||||||
"newColumn": "Добавить колонку",
|
"newProperty": "Добавить колонку",
|
||||||
"deleteFieldPromptMessage": "Вы уверены? Свойство будет удалено"
|
"deleteFieldPromptMessage": "Вы уверены? Свойство будет удалено"
|
||||||
},
|
},
|
||||||
"sort": {
|
"sort": {
|
||||||
@ -309,7 +324,8 @@
|
|||||||
"checklist": {
|
"checklist": {
|
||||||
"panelTitle": "Добавить элемент"
|
"panelTitle": "Добавить элемент"
|
||||||
},
|
},
|
||||||
"menuName": "Сетка"
|
"menuName": "Сетка",
|
||||||
|
"referencedGridPrefix": "Просмотр"
|
||||||
},
|
},
|
||||||
"document": {
|
"document": {
|
||||||
"menuName": "Документ",
|
"menuName": "Документ",
|
||||||
@ -319,30 +335,79 @@
|
|||||||
},
|
},
|
||||||
"slashMenu": {
|
"slashMenu": {
|
||||||
"board": {
|
"board": {
|
||||||
"selectABoardToLinkTo": "Выбрать доску для связи с"
|
"selectABoardToLinkTo": "Выбрать доску для связи с",
|
||||||
|
"createANewBoard": "Создать доску"
|
||||||
},
|
},
|
||||||
"grid": {
|
"grid": {
|
||||||
"selectAGridToLinkTo": "Выберите сетку для связи с"
|
"selectAGridToLinkTo": "Выберите сетку для связи с",
|
||||||
|
"createANewGrid": "Создать сетку"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"plugins": {
|
"plugins": {
|
||||||
"referencedBoard": "Связанные доски",
|
"referencedBoard": "Связанные доски",
|
||||||
"referencedGrid": "Связанные сетки"
|
"referencedGrid": "Связанные сетки",
|
||||||
|
"autoGeneratorMenuItemName": "Генератор OpenAI",
|
||||||
|
"autoGeneratorTitleName": "OpenAI: попросить ИИ написать что угодно...",
|
||||||
|
"autoGeneratorLearnMore": "Узнать больше",
|
||||||
|
"autoGeneratorGenerate": "Генерировать",
|
||||||
|
"autoGeneratorHintText": "Спросить OpenAI ...",
|
||||||
|
"autoGeneratorCantGetOpenAIKey": "Не могу получить токен OpenAI",
|
||||||
|
"smartEdit": "ИИ ассистенты",
|
||||||
|
"openAI": "OpenAI",
|
||||||
|
"smartEditFixSpelling": "Исправить правописание",
|
||||||
|
"warning": "⚠️ Ответы ИИ могут быть неправильными или неточными.",
|
||||||
|
"smartEditSummarize": "Выделить суть",
|
||||||
|
"smartEditCouldNotFetchResult": "Не могу получить ответ от OpenAI",
|
||||||
|
"smartEditCouldNotFetchKey": "Не могу получить токен OpenAI",
|
||||||
|
"smartEditDisabled": "Подключить OpenAI",
|
||||||
|
"discardResponse": "Хотите убрать ответы ИИ?",
|
||||||
|
"cover": {
|
||||||
|
"changeCover": "Сменить обложку",
|
||||||
|
"colors": "Цвета",
|
||||||
|
"images": "Изображения",
|
||||||
|
"clearAll": "Очистить",
|
||||||
|
"abstract": "Абстракные",
|
||||||
|
"addCover": "Добавить обложку",
|
||||||
|
"addLocalImage": "Добавить изображение с диска",
|
||||||
|
"invalidImageUrl": "Некорректная ссылка на изображение",
|
||||||
|
"failedToAddImageToGallery": "Ошибка добавления изображения в галерею",
|
||||||
|
"enterImageUrl": "Введите ссылку на изображение",
|
||||||
|
"add": "Добавить",
|
||||||
|
"back": "Назад",
|
||||||
|
"saveToGallery": "Сохранить в галерею",
|
||||||
|
"removeIcon": "Удалить иконку",
|
||||||
|
"pasteImageUrl": "Вставить ссылку на изображение",
|
||||||
|
"or": "ИЛИ",
|
||||||
|
"pickFromFiles": "Выбрать с диска",
|
||||||
|
"couldNotFetchImage": "Не удалось получить изображение",
|
||||||
|
"imageSavingFailed": "Не удалось сохранить изображение",
|
||||||
|
"addIcon": "Добавить иконку",
|
||||||
|
"coverRemoveAlert": "Изображение будет удалено с обложки",
|
||||||
|
"alertDialogConfirmation": "Вы хотите продолжить?"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"board": {
|
"board": {
|
||||||
"column": {
|
"column": {
|
||||||
"create_new_card": "Создать"
|
"create_new_card": "Создать"
|
||||||
},
|
},
|
||||||
"menuName": "Доска"
|
"menuName": "Доска",
|
||||||
|
"referencedBoardPrefix": "Просмотр"
|
||||||
},
|
},
|
||||||
"calendar": {
|
"calendar": {
|
||||||
"menuName": "Календарь",
|
"menuName": "Календарь",
|
||||||
|
"defaultNewCalendarTitle": "Безымянный",
|
||||||
"navigation": {
|
"navigation": {
|
||||||
"today": "Сегодня",
|
"today": "Сегодня",
|
||||||
"jumpToday": "Перейти к сегодняшнему дню",
|
"jumpToday": "Перейти к сегодняшнему дню",
|
||||||
"previousMonth": "Предыдущий месяц",
|
"previousMonth": "Предыдущий месяц",
|
||||||
"nextMonth": "Следующий месяц"
|
"nextMonth": "Следующий месяц"
|
||||||
|
},
|
||||||
|
"settings": {
|
||||||
|
"showWeekNumbers": "Показывать номера недель",
|
||||||
|
"showWeekends": "Показывать выходные",
|
||||||
|
"firstDayOfWeek": "Первый день недели",
|
||||||
|
"layoutDateField": "Вид календаря"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -195,7 +195,7 @@
|
|||||||
"optionTitle": "Alternativ",
|
"optionTitle": "Alternativ",
|
||||||
"addOption": "Lägg till alternativ",
|
"addOption": "Lägg till alternativ",
|
||||||
"editProperty": "Redigera egenskap",
|
"editProperty": "Redigera egenskap",
|
||||||
"newColumn": "Ny kolumn",
|
"newProperty": "Ny kolumn",
|
||||||
"deleteFieldPromptMessage": "Är du säker? Denna egenskap kommer att raderas."
|
"deleteFieldPromptMessage": "Är du säker? Denna egenskap kommer att raderas."
|
||||||
},
|
},
|
||||||
"row": {
|
"row": {
|
||||||
|
@ -195,7 +195,7 @@
|
|||||||
"optionTitle": "标签",
|
"optionTitle": "标签",
|
||||||
"addOption": "添加标签",
|
"addOption": "添加标签",
|
||||||
"editProperty": "编辑列属性",
|
"editProperty": "编辑列属性",
|
||||||
"newColumn": "增加一列",
|
"newProperty": "增加一列",
|
||||||
"deleteFieldPromptMessage": "确定要删除这个属性吗? "
|
"deleteFieldPromptMessage": "确定要删除这个属性吗? "
|
||||||
},
|
},
|
||||||
"row": {
|
"row": {
|
||||||
|
@ -290,7 +290,7 @@
|
|||||||
"optionTitle": "選項",
|
"optionTitle": "選項",
|
||||||
"addOption": "新增選項",
|
"addOption": "新增選項",
|
||||||
"editProperty": "編輯內容",
|
"editProperty": "編輯內容",
|
||||||
"newColumn": "新欄位",
|
"newProperty": "新欄位",
|
||||||
"deleteFieldPromptMessage": "你確定嗎?這個內容將被刪除"
|
"deleteFieldPromptMessage": "你確定嗎?這個內容將被刪除"
|
||||||
},
|
},
|
||||||
"sort": {
|
"sort": {
|
||||||
|
@ -35,7 +35,9 @@ void main() {
|
|||||||
setUpAll(() async => await service.setUpAll());
|
setUpAll(() async => await service.setUpAll());
|
||||||
setUp(() async => await service.setUp());
|
setUp(() async => await service.setUp());
|
||||||
|
|
||||||
testWidgets('integration test unzips the proper workspace and loads it correctly.', (tester) async {
|
testWidgets(
|
||||||
|
'integration test unzips the proper workspace and loads it correctly.',
|
||||||
|
(tester) async {
|
||||||
await tester.initializeAppFlowy();
|
await tester.initializeAppFlowy();
|
||||||
expect(find.byType(AppFlowyBoard), findsOneWidget);
|
expect(find.byType(AppFlowyBoard), findsOneWidget);
|
||||||
});
|
});
|
||||||
|
@ -31,7 +31,8 @@ void main() {
|
|||||||
setUpAll(() async => await service.setUpAll());
|
setUpAll(() async => await service.setUpAll());
|
||||||
setUp(() async => await service.setUp());
|
setUp(() async => await service.setUp());
|
||||||
|
|
||||||
testWidgets('/board shortcut creates a new board and view of the board', (tester) async {
|
testWidgets('/board shortcut creates a new board and view of the board',
|
||||||
|
(tester) async {
|
||||||
await tester.initializeAppFlowy();
|
await tester.initializeAppFlowy();
|
||||||
|
|
||||||
// Needs tab to obtain focus for the app flowy editor.
|
// Needs tab to obtain focus for the app flowy editor.
|
||||||
@ -44,7 +45,8 @@ void main() {
|
|||||||
// does not contain any EditableText widgets.
|
// does not contain any EditableText widgets.
|
||||||
// to interact with the app during an integration test,
|
// to interact with the app during an integration test,
|
||||||
// simulate physical keyboard events.
|
// simulate physical keyboard events.
|
||||||
await FlowyTestKeyboard.simulateKeyDownEvent([
|
await FlowyTestKeyboard.simulateKeyDownEvent(
|
||||||
|
[
|
||||||
LogicalKeyboardKey.slash,
|
LogicalKeyboardKey.slash,
|
||||||
LogicalKeyboardKey.keyB,
|
LogicalKeyboardKey.keyB,
|
||||||
LogicalKeyboardKey.keyO,
|
LogicalKeyboardKey.keyO,
|
||||||
@ -52,16 +54,21 @@ void main() {
|
|||||||
LogicalKeyboardKey.keyR,
|
LogicalKeyboardKey.keyR,
|
||||||
LogicalKeyboardKey.keyD,
|
LogicalKeyboardKey.keyD,
|
||||||
LogicalKeyboardKey.arrowDown,
|
LogicalKeyboardKey.arrowDown,
|
||||||
], tester: tester);
|
],
|
||||||
|
tester: tester,
|
||||||
|
);
|
||||||
|
|
||||||
// Checks whether the options in the selection menu
|
// Checks whether the options in the selection menu
|
||||||
// for /board exist.
|
// for /board exist.
|
||||||
expect(find.byType(SelectionMenuItemWidget), findsAtLeastNWidgets(2));
|
expect(find.byType(SelectionMenuItemWidget), findsAtLeastNWidgets(2));
|
||||||
|
|
||||||
// Finalizes the slash command that creates the board.
|
// Finalizes the slash command that creates the board.
|
||||||
await FlowyTestKeyboard.simulateKeyDownEvent([
|
await FlowyTestKeyboard.simulateKeyDownEvent(
|
||||||
|
[
|
||||||
LogicalKeyboardKey.enter,
|
LogicalKeyboardKey.enter,
|
||||||
], tester: tester);
|
],
|
||||||
|
tester: tester,
|
||||||
|
);
|
||||||
|
|
||||||
// Checks whether new board is referenced and properly on the page.
|
// Checks whether new board is referenced and properly on the page.
|
||||||
expect(find.byType(BuiltInPageWidget), findsOneWidget);
|
expect(find.byType(BuiltInPageWidget), findsOneWidget);
|
||||||
@ -75,7 +82,8 @@ void main() {
|
|||||||
expect(find.text(viewOfBoardLabel), findsNWidgets(2));
|
expect(find.text(viewOfBoardLabel), findsNWidgets(2));
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('/grid shortcut creates a new grid and view of the grid', (tester) async {
|
testWidgets('/grid shortcut creates a new grid and view of the grid',
|
||||||
|
(tester) async {
|
||||||
await tester.initializeAppFlowy();
|
await tester.initializeAppFlowy();
|
||||||
|
|
||||||
// Needs tab to obtain focus for the app flowy editor.
|
// Needs tab to obtain focus for the app flowy editor.
|
||||||
@ -88,14 +96,17 @@ void main() {
|
|||||||
// does not contain any EditableText widgets.
|
// does not contain any EditableText widgets.
|
||||||
// to interact with the app during an integration test,
|
// to interact with the app during an integration test,
|
||||||
// simulate physical keyboard events.
|
// simulate physical keyboard events.
|
||||||
await FlowyTestKeyboard.simulateKeyDownEvent([
|
await FlowyTestKeyboard.simulateKeyDownEvent(
|
||||||
|
[
|
||||||
LogicalKeyboardKey.slash,
|
LogicalKeyboardKey.slash,
|
||||||
LogicalKeyboardKey.keyG,
|
LogicalKeyboardKey.keyG,
|
||||||
LogicalKeyboardKey.keyR,
|
LogicalKeyboardKey.keyR,
|
||||||
LogicalKeyboardKey.keyI,
|
LogicalKeyboardKey.keyI,
|
||||||
LogicalKeyboardKey.keyD,
|
LogicalKeyboardKey.keyD,
|
||||||
LogicalKeyboardKey.arrowDown,
|
LogicalKeyboardKey.arrowDown,
|
||||||
], tester: tester);
|
],
|
||||||
|
tester: tester,
|
||||||
|
);
|
||||||
|
|
||||||
// Checks whether the options in the selection menu
|
// Checks whether the options in the selection menu
|
||||||
// for /grid exist.
|
// for /grid exist.
|
||||||
|
@ -61,6 +61,8 @@ class TestWorkspaceService {
|
|||||||
InputFileStream(await workspace.zip.then((value) => value.path));
|
InputFileStream(await workspace.zip.then((value) => value.path));
|
||||||
final archive = ZipDecoder().decodeBuffer(inputStream);
|
final archive = ZipDecoder().decodeBuffer(inputStream);
|
||||||
extractArchiveToDisk(
|
extractArchiveToDisk(
|
||||||
archive, await TestWorkspace._parent.then((value) => value.path));
|
archive,
|
||||||
|
await TestWorkspace._parent.then((value) => value.path),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,8 +2,10 @@ import 'package:flutter/services.dart';
|
|||||||
import 'package:flutter_test/flutter_test.dart' as flutter_test;
|
import 'package:flutter_test/flutter_test.dart' as flutter_test;
|
||||||
|
|
||||||
class FlowyTestKeyboard {
|
class FlowyTestKeyboard {
|
||||||
static Future<void> simulateKeyDownEvent(List<LogicalKeyboardKey> keys,
|
static Future<void> simulateKeyDownEvent(
|
||||||
{required flutter_test.WidgetTester tester}) async {
|
List<LogicalKeyboardKey> keys, {
|
||||||
|
required flutter_test.WidgetTester tester,
|
||||||
|
}) async {
|
||||||
for (final LogicalKeyboardKey key in keys) {
|
for (final LogicalKeyboardKey key in keys) {
|
||||||
await flutter_test.simulateKeyDownEvent(key);
|
await flutter_test.simulateKeyDownEvent(key);
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
|
@ -16,9 +16,10 @@ typedef FolderNotificationCallback = void Function(
|
|||||||
|
|
||||||
class FolderNotificationParser
|
class FolderNotificationParser
|
||||||
extends NotificationParser<FolderNotification, FlowyError> {
|
extends NotificationParser<FolderNotification, FlowyError> {
|
||||||
FolderNotificationParser(
|
FolderNotificationParser({
|
||||||
{String? id, required FolderNotificationCallback callback})
|
String? id,
|
||||||
: super(
|
required FolderNotificationCallback callback,
|
||||||
|
}) : super(
|
||||||
id: id,
|
id: id,
|
||||||
callback: callback,
|
callback: callback,
|
||||||
tyParser: (ty) => FolderNotification.valueOf(ty),
|
tyParser: (ty) => FolderNotification.valueOf(ty),
|
||||||
|
@ -16,9 +16,10 @@ typedef DatabaseNotificationCallback = void Function(
|
|||||||
|
|
||||||
class DatabaseNotificationParser
|
class DatabaseNotificationParser
|
||||||
extends NotificationParser<DatabaseNotification, FlowyError> {
|
extends NotificationParser<DatabaseNotification, FlowyError> {
|
||||||
DatabaseNotificationParser(
|
DatabaseNotificationParser({
|
||||||
{String? id, required DatabaseNotificationCallback callback})
|
String? id,
|
||||||
: super(
|
required DatabaseNotificationCallback callback,
|
||||||
|
}) : super(
|
||||||
id: id,
|
id: id,
|
||||||
callback: callback,
|
callback: callback,
|
||||||
tyParser: (ty) => DatabaseNotification.valueOf(ty),
|
tyParser: (ty) => DatabaseNotification.valueOf(ty),
|
||||||
@ -27,7 +28,9 @@ class DatabaseNotificationParser
|
|||||||
}
|
}
|
||||||
|
|
||||||
typedef DatabaseNotificationHandler = Function(
|
typedef DatabaseNotificationHandler = Function(
|
||||||
DatabaseNotification ty, Either<Uint8List, FlowyError> result);
|
DatabaseNotification ty,
|
||||||
|
Either<Uint8List, FlowyError> result,
|
||||||
|
);
|
||||||
|
|
||||||
class DatabaseNotificationListener {
|
class DatabaseNotificationListener {
|
||||||
StreamSubscription<SubscribeObject>? _subscription;
|
StreamSubscription<SubscribeObject>? _subscription;
|
||||||
|
@ -9,11 +9,12 @@ class NotificationParser<T, E> {
|
|||||||
T? Function(int) tyParser;
|
T? Function(int) tyParser;
|
||||||
E Function(Uint8List) errorParser;
|
E Function(Uint8List) errorParser;
|
||||||
|
|
||||||
NotificationParser(
|
NotificationParser({
|
||||||
{this.id,
|
this.id,
|
||||||
required this.callback,
|
required this.callback,
|
||||||
required this.errorParser,
|
required this.errorParser,
|
||||||
required this.tyParser});
|
required this.tyParser,
|
||||||
|
});
|
||||||
void parse(SubscribeObject subject) {
|
void parse(SubscribeObject subject) {
|
||||||
if (id != null) {
|
if (id != null) {
|
||||||
if (subject.id != id) {
|
if (subject.id != id) {
|
||||||
|
@ -16,9 +16,10 @@ typedef UserNotificationCallback = void Function(
|
|||||||
|
|
||||||
class UserNotificationParser
|
class UserNotificationParser
|
||||||
extends NotificationParser<UserNotification, FlowyError> {
|
extends NotificationParser<UserNotification, FlowyError> {
|
||||||
UserNotificationParser(
|
UserNotificationParser({
|
||||||
{required String id, required UserNotificationCallback callback})
|
required String id,
|
||||||
: super(
|
required UserNotificationCallback callback,
|
||||||
|
}) : super(
|
||||||
id: id,
|
id: id,
|
||||||
callback: callback,
|
callback: callback,
|
||||||
tyParser: (ty) => UserNotification.valueOf(ty),
|
tyParser: (ty) => UserNotification.valueOf(ty),
|
||||||
@ -27,7 +28,9 @@ class UserNotificationParser
|
|||||||
}
|
}
|
||||||
|
|
||||||
typedef UserNotificationHandler = Function(
|
typedef UserNotificationHandler = Function(
|
||||||
UserNotification ty, Either<Uint8List, FlowyError> result);
|
UserNotification ty,
|
||||||
|
Either<Uint8List, FlowyError> result,
|
||||||
|
);
|
||||||
|
|
||||||
class UserNotificationListener {
|
class UserNotificationListener {
|
||||||
StreamSubscription<SubscribeObject>? _subscription;
|
StreamSubscription<SubscribeObject>? _subscription;
|
||||||
|
@ -73,7 +73,8 @@ class CellController<T, D> extends Equatable {
|
|||||||
/// For example:
|
/// For example:
|
||||||
/// user input: 12
|
/// user input: 12
|
||||||
/// cell display: $12
|
/// cell display: $12
|
||||||
_cellListener?.start(onCellChanged: (result) {
|
_cellListener?.start(
|
||||||
|
onCellChanged: (result) {
|
||||||
result.fold(
|
result.fold(
|
||||||
(_) {
|
(_) {
|
||||||
_cellCache.remove(_cacheKey);
|
_cellCache.remove(_cacheKey);
|
||||||
@ -81,11 +82,14 @@ class CellController<T, D> extends Equatable {
|
|||||||
},
|
},
|
||||||
(err) => Log.error(err),
|
(err) => Log.error(err),
|
||||||
);
|
);
|
||||||
});
|
},
|
||||||
|
);
|
||||||
|
|
||||||
/// 2.Listen on the field event and load the cell data if needed.
|
/// 2.Listen on the field event and load the cell data if needed.
|
||||||
_fieldListener.start(onFieldChanged: (result) {
|
_fieldListener.start(
|
||||||
result.fold((fieldPB) {
|
onFieldChanged: (result) {
|
||||||
|
result.fold(
|
||||||
|
(fieldPB) {
|
||||||
/// reloadOnFieldChanged should be true if you need to load the data when the corresponding field is changed
|
/// reloadOnFieldChanged should be true if you need to load the data when the corresponding field is changed
|
||||||
/// For example:
|
/// For example:
|
||||||
/// ¥12 -> $12
|
/// ¥12 -> $12
|
||||||
@ -93,8 +97,11 @@ class CellController<T, D> extends Equatable {
|
|||||||
_loadData();
|
_loadData();
|
||||||
}
|
}
|
||||||
_onCellFieldChanged?.call();
|
_onCellFieldChanged?.call();
|
||||||
}, (err) => Log.error(err));
|
},
|
||||||
});
|
(err) => Log.error(err),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Listen on the cell content or field changes
|
/// Listen on the cell content or field changes
|
||||||
@ -130,7 +137,8 @@ class CellController<T, D> extends Equatable {
|
|||||||
/// Return the TypeOptionPB that can be parsed into corresponding class using the [parser].
|
/// Return the TypeOptionPB that can be parsed into corresponding class using the [parser].
|
||||||
/// [PD] is the type that the parser return.
|
/// [PD] is the type that the parser return.
|
||||||
Future<Either<PD, FlowyError>> getTypeOption<PD, P extends TypeOptionParser>(
|
Future<Either<PD, FlowyError>> getTypeOption<PD, P extends TypeOptionParser>(
|
||||||
P parser) {
|
P parser,
|
||||||
|
) {
|
||||||
return _fieldBackendSvc
|
return _fieldBackendSvc
|
||||||
.getFieldTypeOptionData(fieldType: fieldType)
|
.getFieldTypeOptionData(fieldType: fieldType)
|
||||||
.then((result) {
|
.then((result) {
|
||||||
|
@ -19,7 +19,9 @@ class CellListener {
|
|||||||
void start({required void Function(UpdateFieldNotifiedValue) onCellChanged}) {
|
void start({required void Function(UpdateFieldNotifiedValue) onCellChanged}) {
|
||||||
_updateCellNotifier?.addPublishListener(onCellChanged);
|
_updateCellNotifier?.addPublishListener(onCellChanged);
|
||||||
_listener = DatabaseNotificationListener(
|
_listener = DatabaseNotificationListener(
|
||||||
objectId: "$rowId:$fieldId", handler: _handler);
|
objectId: "$rowId:$fieldId",
|
||||||
|
handler: _handler,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _handler(DatabaseNotification ty, Either<Uint8List, FlowyError> result) {
|
void _handler(DatabaseNotification ty, Either<Uint8List, FlowyError> result) {
|
||||||
|
@ -187,8 +187,10 @@ class DatabaseController {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Either<Unit, FlowyError>> moveGroup(
|
Future<Either<Unit, FlowyError>> moveGroup({
|
||||||
{required String fromGroupId, required String toGroupId}) {
|
required String fromGroupId,
|
||||||
|
required String toGroupId,
|
||||||
|
}) {
|
||||||
return _databaseViewBackendSvc.moveGroup(
|
return _databaseViewBackendSvc.moveGroup(
|
||||||
fromGroupId: fromGroupId,
|
fromGroupId: fromGroupId,
|
||||||
toGroupId: toGroupId,
|
toGroupId: toGroupId,
|
||||||
@ -196,7 +198,8 @@ class DatabaseController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> updateCalenderLayoutSetting(
|
Future<void> updateCalenderLayoutSetting(
|
||||||
CalendarLayoutSettingsPB layoutSetting) async {
|
CalendarLayoutSettingsPB layoutSetting,
|
||||||
|
) async {
|
||||||
await _databaseViewBackendSvc
|
await _databaseViewBackendSvc
|
||||||
.updateLayoutSetting(calendarLayoutSetting: layoutSetting)
|
.updateLayoutSetting(calendarLayoutSetting: layoutSetting)
|
||||||
.then((result) {
|
.then((result) {
|
||||||
@ -234,16 +237,20 @@ class DatabaseController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _listenOnRowsChanged() {
|
void _listenOnRowsChanged() {
|
||||||
final callbacks =
|
final callbacks = DatabaseViewCallbacks(
|
||||||
DatabaseViewCallbacks(onRowsChanged: (rows, rowByRowId, reason) {
|
onRowsChanged: (rows, rowByRowId, reason) {
|
||||||
_databaseCallbacks?.onRowsChanged?.call(rows, rowByRowId, reason);
|
_databaseCallbacks?.onRowsChanged?.call(rows, rowByRowId, reason);
|
||||||
}, onRowsDeleted: (ids) {
|
},
|
||||||
|
onRowsDeleted: (ids) {
|
||||||
_databaseCallbacks?.onRowsDeleted?.call(ids);
|
_databaseCallbacks?.onRowsDeleted?.call(ids);
|
||||||
}, onRowsUpdated: (ids) {
|
},
|
||||||
|
onRowsUpdated: (ids) {
|
||||||
_databaseCallbacks?.onRowsUpdated?.call(ids);
|
_databaseCallbacks?.onRowsUpdated?.call(ids);
|
||||||
}, onRowsCreated: (ids) {
|
},
|
||||||
|
onRowsCreated: (ids) {
|
||||||
_databaseCallbacks?.onRowsCreated?.call(ids);
|
_databaseCallbacks?.onRowsCreated?.call(ids);
|
||||||
});
|
},
|
||||||
|
);
|
||||||
_viewCache.addListener(callbacks);
|
_viewCache.addListener(callbacks);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -261,7 +268,8 @@ class DatabaseController {
|
|||||||
void _listenOnGroupChanged() {
|
void _listenOnGroupChanged() {
|
||||||
groupListener.start(
|
groupListener.start(
|
||||||
onNumOfGroupsChanged: (result) {
|
onNumOfGroupsChanged: (result) {
|
||||||
result.fold((changeset) {
|
result.fold(
|
||||||
|
(changeset) {
|
||||||
if (changeset.updateGroups.isNotEmpty) {
|
if (changeset.updateGroups.isNotEmpty) {
|
||||||
_groupCallbacks?.onUpdateGroup?.call(changeset.updateGroups);
|
_groupCallbacks?.onUpdateGroup?.call(changeset.updateGroups);
|
||||||
}
|
}
|
||||||
@ -273,30 +281,45 @@ class DatabaseController {
|
|||||||
for (final insertedGroup in changeset.insertedGroups) {
|
for (final insertedGroup in changeset.insertedGroups) {
|
||||||
_groupCallbacks?.onInsertGroup?.call(insertedGroup);
|
_groupCallbacks?.onInsertGroup?.call(insertedGroup);
|
||||||
}
|
}
|
||||||
}, (r) => Log.error(r));
|
},
|
||||||
|
(r) => Log.error(r),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
onGroupByNewField: (result) {
|
onGroupByNewField: (result) {
|
||||||
result.fold((groups) {
|
result.fold(
|
||||||
|
(groups) {
|
||||||
_groupCallbacks?.onGroupByField?.call(groups);
|
_groupCallbacks?.onGroupByField?.call(groups);
|
||||||
}, (r) => Log.error(r));
|
},
|
||||||
|
(r) => Log.error(r),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _listenOnLayoutChanged() {
|
void _listenOnLayoutChanged() {
|
||||||
layoutListener.start(onLayoutChanged: (result) {
|
layoutListener.start(
|
||||||
result.fold((l) {
|
onLayoutChanged: (result) {
|
||||||
|
result.fold(
|
||||||
|
(l) {
|
||||||
_layoutCallbacks?.onLayoutChanged(l);
|
_layoutCallbacks?.onLayoutChanged(l);
|
||||||
}, (r) => Log.error(r));
|
},
|
||||||
});
|
(r) => Log.error(r),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _listenOnCalendarLayoutChanged() {
|
void _listenOnCalendarLayoutChanged() {
|
||||||
calendarLayoutListener.start(onCalendarLayoutChanged: (result) {
|
calendarLayoutListener.start(
|
||||||
result.fold((l) {
|
onCalendarLayoutChanged: (result) {
|
||||||
|
result.fold(
|
||||||
|
(l) {
|
||||||
_calendarLayoutCallbacks?.onCalendarLayoutChanged(l);
|
_calendarLayoutCallbacks?.onCalendarLayoutChanged(l);
|
||||||
}, (r) => Log.error(r));
|
},
|
||||||
});
|
(r) => Log.error(r),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,8 +73,9 @@ class DatabaseViewBackendService {
|
|||||||
return DatabaseEventMoveGroup(payload).send();
|
return DatabaseEventMoveGroup(payload).send();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Either<List<FieldPB>, FlowyError>> getFields(
|
Future<Either<List<FieldPB>, FlowyError>> getFields({
|
||||||
{List<FieldIdPB>? fieldIds}) {
|
List<FieldIdPB>? fieldIds,
|
||||||
|
}) {
|
||||||
var payload = GetFieldPayloadPB.create()..viewId = viewId;
|
var payload = GetFieldPayloadPB.create()..viewId = viewId;
|
||||||
|
|
||||||
if (fieldIds != null) {
|
if (fieldIds != null) {
|
||||||
@ -86,15 +87,17 @@ class DatabaseViewBackendService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<Either<LayoutSettingPB, FlowyError>> getLayoutSetting(
|
Future<Either<LayoutSettingPB, FlowyError>> getLayoutSetting(
|
||||||
DatabaseLayoutPB layoutType) {
|
DatabaseLayoutPB layoutType,
|
||||||
|
) {
|
||||||
final payload = DatabaseLayoutIdPB.create()
|
final payload = DatabaseLayoutIdPB.create()
|
||||||
..viewId = viewId
|
..viewId = viewId
|
||||||
..layout = layoutType;
|
..layout = layoutType;
|
||||||
return DatabaseEventGetLayoutSetting(payload).send();
|
return DatabaseEventGetLayoutSetting(payload).send();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Either<Unit, FlowyError>> updateLayoutSetting(
|
Future<Either<Unit, FlowyError>> updateLayoutSetting({
|
||||||
{CalendarLayoutSettingsPB? calendarLayoutSetting}) {
|
CalendarLayoutSettingsPB? calendarLayoutSetting,
|
||||||
|
}) {
|
||||||
final layoutSetting = LayoutSettingPB.create();
|
final layoutSetting = LayoutSettingPB.create();
|
||||||
if (calendarLayoutSetting != null) {
|
if (calendarLayoutSetting != null) {
|
||||||
layoutSetting.calendar = calendarLayoutSetting;
|
layoutSetting.calendar = calendarLayoutSetting;
|
||||||
|
@ -17,7 +17,9 @@ class FieldCellBloc extends Bloc<FieldCellEvent, FieldCellState> {
|
|||||||
required FieldCellContext cellContext,
|
required FieldCellContext cellContext,
|
||||||
}) : _fieldListener = SingleFieldListener(fieldId: cellContext.field.id),
|
}) : _fieldListener = SingleFieldListener(fieldId: cellContext.field.id),
|
||||||
_fieldBackendSvc = FieldBackendService(
|
_fieldBackendSvc = FieldBackendService(
|
||||||
viewId: cellContext.viewId, fieldId: cellContext.field.id),
|
viewId: cellContext.viewId,
|
||||||
|
fieldId: cellContext.field.id,
|
||||||
|
),
|
||||||
super(FieldCellState.initial(cellContext)) {
|
super(FieldCellState.initial(cellContext)) {
|
||||||
on<FieldCellEvent>(
|
on<FieldCellEvent>(
|
||||||
(event, emit) async {
|
(event, emit) async {
|
||||||
@ -49,7 +51,8 @@ class FieldCellBloc extends Bloc<FieldCellEvent, FieldCellState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _startListening() {
|
void _startListening() {
|
||||||
_fieldListener.start(onFieldChanged: (result) {
|
_fieldListener.start(
|
||||||
|
onFieldChanged: (result) {
|
||||||
if (isClosed) {
|
if (isClosed) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -57,7 +60,8 @@ class FieldCellBloc extends Bloc<FieldCellEvent, FieldCellState> {
|
|||||||
(field) => add(FieldCellEvent.didReceiveFieldUpdate(field)),
|
(field) => add(FieldCellEvent.didReceiveFieldUpdate(field)),
|
||||||
(err) => Log.error(err),
|
(err) => Log.error(err),
|
||||||
);
|
);
|
||||||
});
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -255,7 +255,8 @@ class FieldController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_filtersListener.start(onFilterChanged: (result) {
|
_filtersListener.start(
|
||||||
|
onFilterChanged: (result) {
|
||||||
result.fold(
|
result.fold(
|
||||||
(FilterChangesetNotificationPB changeset) {
|
(FilterChangesetNotificationPB changeset) {
|
||||||
final List<FilterInfo> filters = filterInfos;
|
final List<FilterInfo> filters = filterInfos;
|
||||||
@ -272,7 +273,8 @@ class FieldController {
|
|||||||
},
|
},
|
||||||
(err) => Log.error(err),
|
(err) => Log.error(err),
|
||||||
);
|
);
|
||||||
});
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _listenOnSortChanged() {
|
void _listenOnSortChanged() {
|
||||||
@ -347,7 +349,8 @@ class FieldController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_sortsListener.start(onSortChanged: (result) {
|
_sortsListener.start(
|
||||||
|
onSortChanged: (result) {
|
||||||
result.fold(
|
result.fold(
|
||||||
(SortChangesetNotificationPB changeset) {
|
(SortChangesetNotificationPB changeset) {
|
||||||
final List<SortInfo> newSortInfos = sortInfos;
|
final List<SortInfo> newSortInfos = sortInfos;
|
||||||
@ -360,22 +363,26 @@ class FieldController {
|
|||||||
},
|
},
|
||||||
(err) => Log.error(err),
|
(err) => Log.error(err),
|
||||||
);
|
);
|
||||||
});
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _listenOnSettingChanges() {
|
void _listenOnSettingChanges() {
|
||||||
//Listen on setting changes
|
//Listen on setting changes
|
||||||
_settingListener.start(onSettingUpdated: (result) {
|
_settingListener.start(
|
||||||
|
onSettingUpdated: (result) {
|
||||||
result.fold(
|
result.fold(
|
||||||
(setting) => _updateSetting(setting),
|
(setting) => _updateSetting(setting),
|
||||||
(r) => Log.error(r),
|
(r) => Log.error(r),
|
||||||
);
|
);
|
||||||
});
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _listenOnFieldChanges() {
|
void _listenOnFieldChanges() {
|
||||||
//Listen on field's changes
|
//Listen on field's changes
|
||||||
_fieldListener.start(onFieldsChanged: (result) {
|
_fieldListener.start(
|
||||||
|
onFieldsChanged: (result) {
|
||||||
result.fold(
|
result.fold(
|
||||||
(changeset) {
|
(changeset) {
|
||||||
_deleteFields(changeset.deletedFields);
|
_deleteFields(changeset.deletedFields);
|
||||||
@ -388,7 +395,8 @@ class FieldController {
|
|||||||
},
|
},
|
||||||
(err) => Log.error(err),
|
(err) => Log.error(err),
|
||||||
);
|
);
|
||||||
});
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _updateSetting(DatabaseViewSettingPB setting) {
|
void _updateSetting(DatabaseViewSettingPB setting) {
|
||||||
|
@ -36,11 +36,13 @@ class FieldEditorBloc extends Bloc<FieldEditorEvent, FieldEditorState> {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
didReceiveFieldChanged: (FieldPB field) {
|
didReceiveFieldChanged: (FieldPB field) {
|
||||||
emit(state.copyWith(
|
emit(
|
||||||
|
state.copyWith(
|
||||||
field: Some(field),
|
field: Some(field),
|
||||||
name: field.name,
|
name: field.name,
|
||||||
canDelete: field.isPrimary,
|
canDelete: field.isPrimary,
|
||||||
));
|
),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
deleteField: () {
|
deleteField: () {
|
||||||
state.field.fold(
|
state.field.fold(
|
||||||
|
@ -17,8 +17,9 @@ class SingleFieldListener {
|
|||||||
|
|
||||||
SingleFieldListener({required this.fieldId});
|
SingleFieldListener({required this.fieldId});
|
||||||
|
|
||||||
void start(
|
void start({
|
||||||
{required void Function(UpdateFieldNotifiedValue) onFieldChanged}) {
|
required void Function(UpdateFieldNotifiedValue) onFieldChanged,
|
||||||
|
}) {
|
||||||
_updateFieldNotifier?.addPublishListener(onFieldChanged);
|
_updateFieldNotifier?.addPublishListener(onFieldChanged);
|
||||||
_listener = DatabaseNotificationListener(
|
_listener = DatabaseNotificationListener(
|
||||||
objectId: fieldId,
|
objectId: fieldId,
|
||||||
@ -60,8 +61,9 @@ class FieldsListener {
|
|||||||
DatabaseNotificationListener? _listener;
|
DatabaseNotificationListener? _listener;
|
||||||
FieldsListener({required this.viewId});
|
FieldsListener({required this.viewId});
|
||||||
|
|
||||||
void start(
|
void start({
|
||||||
{required void Function(UpdateFieldsNotifiedValue) onFieldsChanged}) {
|
required void Function(UpdateFieldsNotifiedValue) onFieldsChanged,
|
||||||
|
}) {
|
||||||
updateFieldsNotifier?.addPublishListener(onFieldsChanged);
|
updateFieldsNotifier?.addPublishListener(onFieldsChanged);
|
||||||
_listener = DatabaseNotificationListener(
|
_listener = DatabaseNotificationListener(
|
||||||
objectId: viewId,
|
objectId: viewId,
|
||||||
|
@ -15,16 +15,25 @@ class DateTypeOptionBloc
|
|||||||
(event, emit) async {
|
(event, emit) async {
|
||||||
event.map(
|
event.map(
|
||||||
didSelectDateFormat: (_DidSelectDateFormat value) {
|
didSelectDateFormat: (_DidSelectDateFormat value) {
|
||||||
emit(state.copyWith(
|
emit(
|
||||||
typeOption: _updateTypeOption(dateFormat: value.format)));
|
state.copyWith(
|
||||||
|
typeOption: _updateTypeOption(dateFormat: value.format),
|
||||||
|
),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
didSelectTimeFormat: (_DidSelectTimeFormat value) {
|
didSelectTimeFormat: (_DidSelectTimeFormat value) {
|
||||||
emit(state.copyWith(
|
emit(
|
||||||
typeOption: _updateTypeOption(timeFormat: value.format)));
|
state.copyWith(
|
||||||
|
typeOption: _updateTypeOption(timeFormat: value.format),
|
||||||
|
),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
includeTime: (_IncludeTime value) {
|
includeTime: (_IncludeTime value) {
|
||||||
emit(state.copyWith(
|
emit(
|
||||||
typeOption: _updateTypeOption(includeTime: value.includeTime)));
|
state.copyWith(
|
||||||
|
typeOption: _updateTypeOption(includeTime: value.includeTime),
|
||||||
|
),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
@ -7,16 +7,20 @@ class NumberFormatBloc extends Bloc<NumberFormatEvent, NumberFormatState> {
|
|||||||
NumberFormatBloc() : super(NumberFormatState.initial()) {
|
NumberFormatBloc() : super(NumberFormatState.initial()) {
|
||||||
on<NumberFormatEvent>(
|
on<NumberFormatEvent>(
|
||||||
(event, emit) async {
|
(event, emit) async {
|
||||||
event.map(setFilter: (_SetFilter value) {
|
event.map(
|
||||||
|
setFilter: (_SetFilter value) {
|
||||||
final List<NumberFormat> formats = List.from(NumberFormat.values);
|
final List<NumberFormat> formats = List.from(NumberFormat.values);
|
||||||
if (value.filter.isNotEmpty) {
|
if (value.filter.isNotEmpty) {
|
||||||
formats.retainWhere((element) => element
|
formats.retainWhere(
|
||||||
|
(element) => element
|
||||||
.title()
|
.title()
|
||||||
.toLowerCase()
|
.toLowerCase()
|
||||||
.contains(value.filter.toLowerCase()));
|
.contains(value.filter.toLowerCase()),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
emit(state.copyWith(formats: formats, filter: value.filter));
|
emit(state.copyWith(formats: formats, filter: value.filter));
|
||||||
});
|
},
|
||||||
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -59,9 +59,11 @@ class SelectOptionTypeOptionEvent with _$SelectOptionTypeOptionEvent {
|
|||||||
const factory SelectOptionTypeOptionEvent.endAddingOption() =
|
const factory SelectOptionTypeOptionEvent.endAddingOption() =
|
||||||
_EndAddingOption;
|
_EndAddingOption;
|
||||||
const factory SelectOptionTypeOptionEvent.updateOption(
|
const factory SelectOptionTypeOptionEvent.updateOption(
|
||||||
SelectOptionPB option) = _UpdateOption;
|
SelectOptionPB option,
|
||||||
|
) = _UpdateOption;
|
||||||
const factory SelectOptionTypeOptionEvent.deleteOption(
|
const factory SelectOptionTypeOptionEvent.deleteOption(
|
||||||
SelectOptionPB option) = _DeleteOption;
|
SelectOptionPB option,
|
||||||
|
) = _DeleteOption;
|
||||||
}
|
}
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
|
@ -158,7 +158,9 @@ abstract class IFieldTypeOptionLoader {
|
|||||||
Future<Either<TypeOptionPB, FlowyError>> load();
|
Future<Either<TypeOptionPB, FlowyError>> load();
|
||||||
|
|
||||||
Future<Either<Unit, FlowyError>> switchToField(
|
Future<Either<Unit, FlowyError>> switchToField(
|
||||||
String fieldId, FieldType fieldType) {
|
String fieldId,
|
||||||
|
FieldType fieldType,
|
||||||
|
) {
|
||||||
final payload = UpdateFieldTypePayloadPB.create()
|
final payload = UpdateFieldTypePayloadPB.create()
|
||||||
..viewId = viewId
|
..viewId = viewId
|
||||||
..fieldId = fieldId
|
..fieldId = fieldId
|
||||||
|
@ -107,7 +107,8 @@ class FilterListener {
|
|||||||
case DatabaseNotification.DidUpdateFilter:
|
case DatabaseNotification.DidUpdateFilter:
|
||||||
result.fold(
|
result.fold(
|
||||||
(payload) => handleChangeset(
|
(payload) => handleChangeset(
|
||||||
FilterChangesetNotificationPB.fromBuffer(payload)),
|
FilterChangesetNotificationPB.fromBuffer(payload),
|
||||||
|
),
|
||||||
(error) {},
|
(error) {},
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
@ -97,7 +97,8 @@ class FilterBackendService {
|
|||||||
filter.end = $fixnum.Int64(end);
|
filter.end = $fixnum.Int64(end);
|
||||||
} else {
|
} else {
|
||||||
throw Exception(
|
throw Exception(
|
||||||
"Start and end should not be null if the timestamp is null");
|
"Start and end should not be null if the timestamp is null",
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,8 +15,9 @@ class DatabaseCalendarLayoutListener {
|
|||||||
DatabaseNotificationListener? _listener;
|
DatabaseNotificationListener? _listener;
|
||||||
DatabaseCalendarLayoutListener(this.viewId);
|
DatabaseCalendarLayoutListener(this.viewId);
|
||||||
|
|
||||||
void start(
|
void start({
|
||||||
{required void Function(NewLayoutFieldValue) onCalendarLayoutChanged}) {
|
required void Function(NewLayoutFieldValue) onCalendarLayoutChanged,
|
||||||
|
}) {
|
||||||
_newLayoutFieldNotifier?.addPublishListener(onCalendarLayoutChanged);
|
_newLayoutFieldNotifier?.addPublishListener(onCalendarLayoutChanged);
|
||||||
_listener = DatabaseNotificationListener(
|
_listener = DatabaseNotificationListener(
|
||||||
objectId: viewId,
|
objectId: viewId,
|
||||||
|
@ -102,11 +102,16 @@ class RowCache {
|
|||||||
final rowInfo = _rowList.get(reorderRow.rowId);
|
final rowInfo = _rowList.get(reorderRow.rowId);
|
||||||
if (rowInfo != null) {
|
if (rowInfo != null) {
|
||||||
_rowList.moveRow(
|
_rowList.moveRow(
|
||||||
reorderRow.rowId, reorderRow.oldIndex, reorderRow.newIndex);
|
reorderRow.rowId,
|
||||||
_rowChangeReasonNotifier.receive(RowsChangedReason.reorderSingleRow(
|
reorderRow.oldIndex,
|
||||||
|
reorderRow.newIndex,
|
||||||
|
);
|
||||||
|
_rowChangeReasonNotifier.receive(
|
||||||
|
RowsChangedReason.reorderSingleRow(
|
||||||
reorderRow,
|
reorderRow,
|
||||||
rowInfo,
|
rowInfo,
|
||||||
));
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -325,7 +330,9 @@ class RowsChangedReason with _$RowsChangedReason {
|
|||||||
const factory RowsChangedReason.initial() = InitialListState;
|
const factory RowsChangedReason.initial() = InitialListState;
|
||||||
const factory RowsChangedReason.reorderRows() = _ReorderRows;
|
const factory RowsChangedReason.reorderRows() = _ReorderRows;
|
||||||
const factory RowsChangedReason.reorderSingleRow(
|
const factory RowsChangedReason.reorderSingleRow(
|
||||||
ReorderSingleRowPB reorderRow, RowInfo rowInfo) = _ReorderSingleRow;
|
ReorderSingleRowPB reorderRow,
|
||||||
|
RowInfo rowInfo,
|
||||||
|
) = _ReorderSingleRow;
|
||||||
}
|
}
|
||||||
|
|
||||||
class InsertedIndex {
|
class InsertedIndex {
|
||||||
|
@ -23,10 +23,12 @@ class RowController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void addListener({OnRowChanged? onRowChanged}) {
|
void addListener({OnRowChanged? onRowChanged}) {
|
||||||
_onRowChangedListeners.add(_rowCache.addListener(
|
_onRowChangedListeners.add(
|
||||||
|
_rowCache.addListener(
|
||||||
rowId: rowId,
|
rowId: rowId,
|
||||||
onCellUpdated: onRowChanged,
|
onCellUpdated: onRowChanged,
|
||||||
));
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void dispose() {
|
void dispose() {
|
||||||
|
@ -85,10 +85,12 @@ class RowList {
|
|||||||
insert(index, builder(insertRow.row));
|
insert(index, builder(insertRow.row));
|
||||||
|
|
||||||
if (!isContains) {
|
if (!isContains) {
|
||||||
insertIndexs.add(InsertedIndex(
|
insertIndexs.add(
|
||||||
|
InsertedIndex(
|
||||||
index: index,
|
index: index,
|
||||||
rowId: insertRow.row.id,
|
rowId: insertRow.row.id,
|
||||||
));
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return insertIndexs;
|
return insertIndexs;
|
||||||
|
@ -67,7 +67,8 @@ class DatabaseGroupEvent with _$DatabaseGroupEvent {
|
|||||||
FieldType fieldType,
|
FieldType fieldType,
|
||||||
) = _DatabaseGroupEvent;
|
) = _DatabaseGroupEvent;
|
||||||
const factory DatabaseGroupEvent.didReceiveFieldUpdate(
|
const factory DatabaseGroupEvent.didReceiveFieldUpdate(
|
||||||
List<FieldInfo> fields) = _DidReceiveFieldUpdate;
|
List<FieldInfo> fields,
|
||||||
|
) = _DidReceiveFieldUpdate;
|
||||||
}
|
}
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
@ -78,7 +79,9 @@ class DatabaseGroupState with _$DatabaseGroupState {
|
|||||||
}) = _DatabaseGroupState;
|
}) = _DatabaseGroupState;
|
||||||
|
|
||||||
factory DatabaseGroupState.initial(
|
factory DatabaseGroupState.initial(
|
||||||
String viewId, List<FieldInfo> fieldContexts) =>
|
String viewId,
|
||||||
|
List<FieldInfo> fieldContexts,
|
||||||
|
) =>
|
||||||
DatabaseGroupState(
|
DatabaseGroupState(
|
||||||
viewId: viewId,
|
viewId: viewId,
|
||||||
fieldContexts: fieldContexts,
|
fieldContexts: fieldContexts,
|
||||||
|
@ -13,11 +13,13 @@ class DatabasePropertyBloc
|
|||||||
final FieldController _fieldController;
|
final FieldController _fieldController;
|
||||||
Function(List<FieldInfo>)? _onFieldsFn;
|
Function(List<FieldInfo>)? _onFieldsFn;
|
||||||
|
|
||||||
DatabasePropertyBloc(
|
DatabasePropertyBloc({
|
||||||
{required String viewId, required FieldController fieldController})
|
required String viewId,
|
||||||
: _fieldController = fieldController,
|
required FieldController fieldController,
|
||||||
|
}) : _fieldController = fieldController,
|
||||||
super(
|
super(
|
||||||
DatabasePropertyState.initial(viewId, fieldController.fieldInfos)) {
|
DatabasePropertyState.initial(viewId, fieldController.fieldInfos),
|
||||||
|
) {
|
||||||
on<DatabasePropertyEvent>(
|
on<DatabasePropertyEvent>(
|
||||||
(event, emit) async {
|
(event, emit) async {
|
||||||
await event.map(
|
await event.map(
|
||||||
@ -68,9 +70,12 @@ class DatabasePropertyBloc
|
|||||||
class DatabasePropertyEvent with _$DatabasePropertyEvent {
|
class DatabasePropertyEvent with _$DatabasePropertyEvent {
|
||||||
const factory DatabasePropertyEvent.initial() = _Initial;
|
const factory DatabasePropertyEvent.initial() = _Initial;
|
||||||
const factory DatabasePropertyEvent.setFieldVisibility(
|
const factory DatabasePropertyEvent.setFieldVisibility(
|
||||||
String fieldId, bool visibility) = _SetFieldVisibility;
|
String fieldId,
|
||||||
|
bool visibility,
|
||||||
|
) = _SetFieldVisibility;
|
||||||
const factory DatabasePropertyEvent.didReceiveFieldUpdate(
|
const factory DatabasePropertyEvent.didReceiveFieldUpdate(
|
||||||
List<FieldInfo> fields) = _DidReceiveFieldUpdate;
|
List<FieldInfo> fields,
|
||||||
|
) = _DidReceiveFieldUpdate;
|
||||||
const factory DatabasePropertyEvent.moveField(int fromIndex, int toIndex) =
|
const factory DatabasePropertyEvent.moveField(int fromIndex, int toIndex) =
|
||||||
_MoveField;
|
_MoveField;
|
||||||
}
|
}
|
||||||
|
@ -11,9 +11,11 @@ class DatabaseSettingBloc
|
|||||||
: super(DatabaseSettingState.initial()) {
|
: super(DatabaseSettingState.initial()) {
|
||||||
on<DatabaseSettingEvent>(
|
on<DatabaseSettingEvent>(
|
||||||
(event, emit) async {
|
(event, emit) async {
|
||||||
event.map(performAction: (_PerformAction value) {
|
event.map(
|
||||||
|
performAction: (_PerformAction value) {
|
||||||
emit(state.copyWith(selectedAction: Some(value.action)));
|
emit(state.copyWith(selectedAction: Some(value.action)));
|
||||||
});
|
},
|
||||||
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -22,7 +24,8 @@ class DatabaseSettingBloc
|
|||||||
@freezed
|
@freezed
|
||||||
class DatabaseSettingEvent with _$DatabaseSettingEvent {
|
class DatabaseSettingEvent with _$DatabaseSettingEvent {
|
||||||
const factory DatabaseSettingEvent.performAction(
|
const factory DatabaseSettingEvent.performAction(
|
||||||
DatabaseSettingAction action) = _PerformAction;
|
DatabaseSettingAction action,
|
||||||
|
) = _PerformAction;
|
||||||
}
|
}
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
|
@ -28,12 +28,14 @@ class SettingController {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Listen on the setting changes
|
// Listen on the setting changes
|
||||||
_listener.start(onSettingUpdated: (result) {
|
_listener.start(
|
||||||
|
onSettingUpdated: (result) {
|
||||||
result.fold(
|
result.fold(
|
||||||
(newSetting) => updateSetting(newSetting),
|
(newSetting) => updateSetting(newSetting),
|
||||||
(err) => _onError?.call(err),
|
(err) => _onError?.call(err),
|
||||||
);
|
);
|
||||||
});
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void startListening({
|
void startListening({
|
||||||
|
@ -69,9 +69,11 @@ class DatabaseViewCache {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (changeset.insertedRows.isNotEmpty) {
|
if (changeset.insertedRows.isNotEmpty) {
|
||||||
_callbacks?.onRowsCreated?.call(changeset.insertedRows
|
_callbacks?.onRowsCreated?.call(
|
||||||
|
changeset.insertedRows
|
||||||
.map((insertedRow) => insertedRow.row.id)
|
.map((insertedRow) => insertedRow.row.id)
|
||||||
.toList());
|
.toList(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
(err) => Log.error(err),
|
(err) => Log.error(err),
|
||||||
|
@ -105,23 +105,31 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
didCreateRow: (group, row, int? index) {
|
didCreateRow: (group, row, int? index) {
|
||||||
emit(state.copyWith(
|
emit(
|
||||||
editingRow: Some(BoardEditingRow(
|
state.copyWith(
|
||||||
|
editingRow: Some(
|
||||||
|
BoardEditingRow(
|
||||||
group: group,
|
group: group,
|
||||||
row: row,
|
row: row,
|
||||||
index: index,
|
index: index,
|
||||||
)),
|
),
|
||||||
));
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
_groupItemStartEditing(group, row, true);
|
_groupItemStartEditing(group, row, true);
|
||||||
},
|
},
|
||||||
startEditingRow: (group, row) {
|
startEditingRow: (group, row) {
|
||||||
emit(state.copyWith(
|
emit(
|
||||||
editingRow: Some(BoardEditingRow(
|
state.copyWith(
|
||||||
|
editingRow: Some(
|
||||||
|
BoardEditingRow(
|
||||||
group: group,
|
group: group,
|
||||||
row: row,
|
row: row,
|
||||||
index: null,
|
index: null,
|
||||||
)),
|
),
|
||||||
));
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
_groupItemStartEditing(group, row, true);
|
_groupItemStartEditing(group, row, true);
|
||||||
},
|
},
|
||||||
endEditingRow: (rowId) {
|
endEditingRow: (rowId) {
|
||||||
@ -175,10 +183,12 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
|
|||||||
groupControllers.clear();
|
groupControllers.clear();
|
||||||
boardController.clear();
|
boardController.clear();
|
||||||
|
|
||||||
boardController.addGroups(groups
|
boardController.addGroups(
|
||||||
|
groups
|
||||||
.where((group) => fieldController.getField(group.fieldId) != null)
|
.where((group) => fieldController.getField(group.fieldId) != null)
|
||||||
.map((group) => initializeGroupData(group))
|
.map((group) => initializeGroupData(group))
|
||||||
.toList());
|
.toList(),
|
||||||
|
);
|
||||||
|
|
||||||
for (final group in groups) {
|
for (final group in groups) {
|
||||||
final controller = initializeGroupController(group);
|
final controller = initializeGroupController(group);
|
||||||
@ -334,7 +344,8 @@ class BoardState with _$BoardState {
|
|||||||
class GridLoadingState with _$GridLoadingState {
|
class GridLoadingState with _$GridLoadingState {
|
||||||
const factory GridLoadingState.loading() = _Loading;
|
const factory GridLoadingState.loading() = _Loading;
|
||||||
const factory GridLoadingState.finish(
|
const factory GridLoadingState.finish(
|
||||||
Either<Unit, FlowyError> successOrFail) = _Finish;
|
Either<Unit, FlowyError> successOrFail,
|
||||||
|
) = _Finish;
|
||||||
}
|
}
|
||||||
|
|
||||||
class GridFieldEquatable extends Equatable {
|
class GridFieldEquatable extends Equatable {
|
||||||
|
@ -41,7 +41,8 @@ class GroupController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void startListening() {
|
void startListening() {
|
||||||
_listener.start(onGroupChanged: (result) {
|
_listener.start(
|
||||||
|
onGroupChanged: (result) {
|
||||||
result.fold(
|
result.fold(
|
||||||
(GroupRowsNotificationPB changeset) {
|
(GroupRowsNotificationPB changeset) {
|
||||||
for (final deletedRow in changeset.deletedRows) {
|
for (final deletedRow in changeset.deletedRows) {
|
||||||
@ -78,7 +79,8 @@ class GroupController {
|
|||||||
},
|
},
|
||||||
(err) => Log.error(err),
|
(err) => Log.error(err),
|
||||||
);
|
);
|
||||||
});
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> dispose() async {
|
Future<void> dispose() async {
|
||||||
|
@ -10,9 +10,11 @@ class BoardSettingBloc extends Bloc<BoardSettingEvent, BoardSettingState> {
|
|||||||
: super(BoardSettingState.initial()) {
|
: super(BoardSettingState.initial()) {
|
||||||
on<BoardSettingEvent>(
|
on<BoardSettingEvent>(
|
||||||
(event, emit) async {
|
(event, emit) async {
|
||||||
event.when(performAction: (action) {
|
event.when(
|
||||||
|
performAction: (action) {
|
||||||
emit(state.copyWith(selectedAction: Some(action)));
|
emit(state.copyWith(selectedAction: Some(action)));
|
||||||
});
|
},
|
||||||
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -80,8 +80,8 @@ class _BoardContentState extends State<BoardContent> {
|
|||||||
late AppFlowyBoardScrollController scrollManager;
|
late AppFlowyBoardScrollController scrollManager;
|
||||||
final cardConfiguration = CardConfiguration<String>();
|
final cardConfiguration = CardConfiguration<String>();
|
||||||
|
|
||||||
final config = AppFlowyBoardConfig(
|
final config = const AppFlowyBoardConfig(
|
||||||
groupBackgroundColor: HexColor.fromHex('#F7F8FC'),
|
groupBackgroundColor: Color(0xffF7F8FC),
|
||||||
);
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -292,9 +292,10 @@ class _BoardContentState extends State<BoardContent> {
|
|||||||
color: Theme.of(context).dividerColor,
|
color: Theme.of(context).dividerColor,
|
||||||
width: 1.0,
|
width: 1.0,
|
||||||
);
|
);
|
||||||
|
final isLightMode = Theme.of(context).brightness == Brightness.light;
|
||||||
return BoxDecoration(
|
return BoxDecoration(
|
||||||
color: Theme.of(context).colorScheme.surface,
|
color: Theme.of(context).colorScheme.surface,
|
||||||
border: Border.fromBorderSide(borderSide),
|
border: isLightMode ? Border.fromBorderSide(borderSide) : null,
|
||||||
borderRadius: const BorderRadius.all(Radius.circular(6)),
|
borderRadius: const BorderRadius.all(Radius.circular(6)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -349,15 +350,6 @@ class _ToolbarBlocAdaptor extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension HexColor on Color {
|
|
||||||
static Color fromHex(String hexString) {
|
|
||||||
final buffer = StringBuffer();
|
|
||||||
if (hexString.length == 6 || hexString.length == 7) buffer.write('ff');
|
|
||||||
buffer.write(hexString.replaceFirst('#', ''));
|
|
||||||
return Color(int.parse(buffer.toString(), radix: 16));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget? _buildHeaderIcon(GroupData customData) {
|
Widget? _buildHeaderIcon(GroupData customData) {
|
||||||
Widget? widget;
|
Widget? widget;
|
||||||
switch (customData.fieldType) {
|
switch (customData.fieldType) {
|
||||||
|
@ -7,6 +7,7 @@ import 'package:appflowy/plugins/database_view/grid/presentation/widgets/toolbar
|
|||||||
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/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';
|
||||||
@ -104,8 +105,12 @@ class _SettingItem extends StatelessWidget {
|
|||||||
return SizedBox(
|
return SizedBox(
|
||||||
height: 30,
|
height: 30,
|
||||||
child: FlowyButton(
|
child: FlowyButton(
|
||||||
|
hoverColor: AFThemeExtension.of(context).lightGreyHover,
|
||||||
isSelected: isSelected,
|
isSelected: isSelected,
|
||||||
text: FlowyText.medium(action.title()),
|
text: FlowyText.medium(
|
||||||
|
action.title(),
|
||||||
|
color: AFThemeExtension.of(context).textColor,
|
||||||
|
),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
context
|
context
|
||||||
.read<BoardSettingBloc>()
|
.read<BoardSettingBloc>()
|
||||||
|
@ -71,6 +71,7 @@ class _SettingButtonState extends State<_SettingButton> {
|
|||||||
margin: EdgeInsets.zero,
|
margin: EdgeInsets.zero,
|
||||||
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,
|
||||||
|
@ -67,16 +67,20 @@ class CalendarBloc extends Bloc<CalendarEvent, CalendarState> {
|
|||||||
if (index != -1) {
|
if (index != -1) {
|
||||||
allEvents[index] = eventData;
|
allEvents[index] = eventData;
|
||||||
}
|
}
|
||||||
emit(state.copyWith(
|
emit(
|
||||||
|
state.copyWith(
|
||||||
allEvents: allEvents,
|
allEvents: allEvents,
|
||||||
updateEvent: eventData,
|
updateEvent: eventData,
|
||||||
));
|
),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
didReceiveNewEvent: (CalendarEventData<CalendarDayEvent> event) {
|
didReceiveNewEvent: (CalendarEventData<CalendarDayEvent> event) {
|
||||||
emit(state.copyWith(
|
emit(
|
||||||
|
state.copyWith(
|
||||||
allEvents: [...state.allEvents, event],
|
allEvents: [...state.allEvents, event],
|
||||||
newEvent: event,
|
newEvent: event,
|
||||||
));
|
),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
didDeleteEvents: (List<String> deletedRowIds) {
|
didDeleteEvents: (List<String> deletedRowIds) {
|
||||||
var events = [...state.allEvents];
|
var events = [...state.allEvents];
|
||||||
@ -155,7 +159,8 @@ class CalendarBloc extends Bloc<CalendarEvent, CalendarState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _updateCalendarLayoutSetting(
|
Future<void> _updateCalendarLayoutSetting(
|
||||||
CalendarLayoutSettingsPB layoutSetting) async {
|
CalendarLayoutSettingsPB layoutSetting,
|
||||||
|
) async {
|
||||||
return _databaseController.updateCalenderLayoutSetting(layoutSetting);
|
return _databaseController.updateCalenderLayoutSetting(layoutSetting);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -198,7 +203,8 @@ class CalendarBloc extends Bloc<CalendarEvent, CalendarState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
CalendarEventData<CalendarDayEvent>? _calendarEventDataFromEventPB(
|
CalendarEventData<CalendarDayEvent>? _calendarEventDataFromEventPB(
|
||||||
CalendarEventPB eventPB) {
|
CalendarEventPB eventPB,
|
||||||
|
) {
|
||||||
final fieldInfo = fieldInfoByFieldId[eventPB.titleFieldId];
|
final fieldInfo = fieldInfoByFieldId[eventPB.titleFieldId];
|
||||||
if (fieldInfo != null) {
|
if (fieldInfo != null) {
|
||||||
final cellId = CellIdentifier(
|
final cellId = CellIdentifier(
|
||||||
@ -214,7 +220,6 @@ class CalendarBloc extends Bloc<CalendarEvent, CalendarState> {
|
|||||||
|
|
||||||
final date = DateTime.fromMillisecondsSinceEpoch(
|
final date = DateTime.fromMillisecondsSinceEpoch(
|
||||||
eventPB.timestamp.toInt() * 1000,
|
eventPB.timestamp.toInt() * 1000,
|
||||||
isUtc: true,
|
|
||||||
);
|
);
|
||||||
return CalendarEventData(
|
return CalendarEventData(
|
||||||
title: eventPB.title,
|
title: eventPB.title,
|
||||||
@ -267,7 +272,8 @@ class CalendarBloc extends Bloc<CalendarEvent, CalendarState> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
final onCalendarLayoutFieldChanged = CalendarLayoutCallbacks(
|
final onCalendarLayoutFieldChanged = CalendarLayoutCallbacks(
|
||||||
onCalendarLayoutChanged: _didReceiveNewLayoutField);
|
onCalendarLayoutChanged: _didReceiveNewLayoutField,
|
||||||
|
);
|
||||||
|
|
||||||
_databaseController.addListener(
|
_databaseController.addListener(
|
||||||
onDatabaseChanged: onDatabaseChanged,
|
onDatabaseChanged: onDatabaseChanged,
|
||||||
@ -299,7 +305,8 @@ class CalendarEvent with _$CalendarEvent {
|
|||||||
|
|
||||||
// Called after loading the calendar layout setting from the backend
|
// Called after loading the calendar layout setting from the backend
|
||||||
const factory CalendarEvent.didReceiveCalendarSettings(
|
const factory CalendarEvent.didReceiveCalendarSettings(
|
||||||
CalendarLayoutSettingsPB settings) = _ReceiveCalendarSettings;
|
CalendarLayoutSettingsPB settings,
|
||||||
|
) = _ReceiveCalendarSettings;
|
||||||
|
|
||||||
// Called after loading all the current evnets
|
// Called after loading all the current evnets
|
||||||
const factory CalendarEvent.didLoadAllEvents(Events events) =
|
const factory CalendarEvent.didLoadAllEvents(Events events) =
|
||||||
@ -307,11 +314,13 @@ class CalendarEvent with _$CalendarEvent {
|
|||||||
|
|
||||||
// Called when specific event was updated
|
// Called when specific event was updated
|
||||||
const factory CalendarEvent.didUpdateEvent(
|
const factory CalendarEvent.didUpdateEvent(
|
||||||
CalendarEventData<CalendarDayEvent> event) = _DidUpdateEvent;
|
CalendarEventData<CalendarDayEvent> event,
|
||||||
|
) = _DidUpdateEvent;
|
||||||
|
|
||||||
// Called after creating a new event
|
// Called after creating a new event
|
||||||
const factory CalendarEvent.didReceiveNewEvent(
|
const factory CalendarEvent.didReceiveNewEvent(
|
||||||
CalendarEventData<CalendarDayEvent> event) = _DidReceiveNewEvent;
|
CalendarEventData<CalendarDayEvent> event,
|
||||||
|
) = _DidReceiveNewEvent;
|
||||||
|
|
||||||
// Called when deleting events
|
// Called when deleting events
|
||||||
const factory CalendarEvent.didDeleteEvents(List<String> rowIds) =
|
const factory CalendarEvent.didDeleteEvents(List<String> rowIds) =
|
||||||
@ -323,13 +332,15 @@ class CalendarEvent with _$CalendarEvent {
|
|||||||
|
|
||||||
// Called when updating the calendar's layout settings
|
// Called when updating the calendar's layout settings
|
||||||
const factory CalendarEvent.updateCalendarLayoutSetting(
|
const factory CalendarEvent.updateCalendarLayoutSetting(
|
||||||
CalendarLayoutSettingsPB layoutSetting) = _UpdateCalendarLayoutSetting;
|
CalendarLayoutSettingsPB layoutSetting,
|
||||||
|
) = _UpdateCalendarLayoutSetting;
|
||||||
|
|
||||||
const factory CalendarEvent.didReceiveDatabaseUpdate(DatabasePB database) =
|
const factory CalendarEvent.didReceiveDatabaseUpdate(DatabasePB database) =
|
||||||
_ReceiveDatabaseUpdate;
|
_ReceiveDatabaseUpdate;
|
||||||
|
|
||||||
const factory CalendarEvent.didReceiveNewLayoutField(
|
const factory CalendarEvent.didReceiveNewLayoutField(
|
||||||
CalendarLayoutSettingsPB layoutSettings) = _DidReceiveNewLayoutField;
|
CalendarLayoutSettingsPB layoutSettings,
|
||||||
|
) = _DidReceiveNewLayoutField;
|
||||||
}
|
}
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
@ -361,7 +372,8 @@ class CalendarState with _$CalendarState {
|
|||||||
class DatabaseLoadingState with _$DatabaseLoadingState {
|
class DatabaseLoadingState with _$DatabaseLoadingState {
|
||||||
const factory DatabaseLoadingState.loading() = _Loading;
|
const factory DatabaseLoadingState.loading() = _Loading;
|
||||||
const factory DatabaseLoadingState.finish(
|
const factory DatabaseLoadingState.finish(
|
||||||
Either<Unit, FlowyError> successOrFail) = _Finish;
|
Either<Unit, FlowyError> successOrFail,
|
||||||
|
) = _Finish;
|
||||||
}
|
}
|
||||||
|
|
||||||
class CalendarEditingRow {
|
class CalendarEditingRow {
|
||||||
|
@ -22,7 +22,6 @@ class CalendarSettingBloc
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
@ -33,7 +32,8 @@ class CalendarSettingState with _$CalendarSettingState {
|
|||||||
}) = _CalendarSettingState;
|
}) = _CalendarSettingState;
|
||||||
|
|
||||||
factory CalendarSettingState.initial(
|
factory CalendarSettingState.initial(
|
||||||
CalendarLayoutSettingsPB? layoutSettings) =>
|
CalendarLayoutSettingsPB? layoutSettings,
|
||||||
|
) =>
|
||||||
CalendarSettingState(
|
CalendarSettingState(
|
||||||
selectedAction: none(),
|
selectedAction: none(),
|
||||||
layoutSetting: layoutSettings == null ? none() : Some(layoutSettings),
|
layoutSetting: layoutSettings == null ? none() : Some(layoutSettings),
|
||||||
@ -43,9 +43,11 @@ class CalendarSettingState with _$CalendarSettingState {
|
|||||||
@freezed
|
@freezed
|
||||||
class CalendarSettingEvent with _$CalendarSettingEvent {
|
class CalendarSettingEvent with _$CalendarSettingEvent {
|
||||||
const factory CalendarSettingEvent.performAction(
|
const factory CalendarSettingEvent.performAction(
|
||||||
CalendarSettingAction action) = _PerformAction;
|
CalendarSettingAction action,
|
||||||
|
) = _PerformAction;
|
||||||
const factory CalendarSettingEvent.updateLayoutSetting(
|
const factory CalendarSettingEvent.updateLayoutSetting(
|
||||||
CalendarLayoutSettingsPB setting) = _UpdateLayoutSetting;
|
CalendarLayoutSettingsPB setting,
|
||||||
|
) = _UpdateLayoutSetting;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum CalendarSettingAction {
|
enum CalendarSettingAction {
|
||||||
|
@ -62,17 +62,18 @@ class CalendarDayCard extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}).toList();
|
}).toList();
|
||||||
|
|
||||||
final child = Padding(
|
final child = Column(
|
||||||
padding: const EdgeInsets.all(8.0),
|
|
||||||
child: Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
_Header(
|
Padding(
|
||||||
|
padding: const EdgeInsets.all(8.0),
|
||||||
|
child: _Header(
|
||||||
date: date,
|
date: date,
|
||||||
isInMonth: isInMonth,
|
isInMonth: isInMonth,
|
||||||
isToday: isToday,
|
isToday: isToday,
|
||||||
onCreate: () => onCreateEvent(date),
|
onCreate: () => onCreateEvent(date),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
VSpace(GridSize.typeOptionSeparatorHeight),
|
VSpace(GridSize.typeOptionSeparatorHeight),
|
||||||
Flexible(
|
Flexible(
|
||||||
child: ListView.separated(
|
child: ListView.separated(
|
||||||
@ -80,12 +81,13 @@ class CalendarDayCard extends StatelessWidget {
|
|||||||
return children[index];
|
return children[index];
|
||||||
},
|
},
|
||||||
itemCount: children.length,
|
itemCount: children.length,
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 8.0),
|
||||||
separatorBuilder: (BuildContext context, int index) =>
|
separatorBuilder: (BuildContext context, int index) =>
|
||||||
VSpace(GridSize.typeOptionSeparatorHeight),
|
VSpace(GridSize.typeOptionSeparatorHeight),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
));
|
);
|
||||||
|
|
||||||
return Container(
|
return Container(
|
||||||
color: backgroundColor,
|
color: backgroundColor,
|
||||||
@ -93,8 +95,11 @@ class CalendarDayCard extends StatelessWidget {
|
|||||||
cursor: SystemMouseCursors.click,
|
cursor: SystemMouseCursors.click,
|
||||||
onEnter: (p) => notifyEnter(context, true),
|
onEnter: (p) => notifyEnter(context, true),
|
||||||
onExit: (p) => notifyEnter(context, false),
|
onExit: (p) => notifyEnter(context, false),
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 8.0),
|
||||||
child: child,
|
child: child,
|
||||||
),
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
@ -148,6 +153,15 @@ class _DayEventCell extends StatelessWidget {
|
|||||||
onTap: onClick,
|
onTap: onClick,
|
||||||
child: Container(
|
child: Container(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
border: Border.fromBorderSide(
|
||||||
|
BorderSide(
|
||||||
|
color: Theme.of(context).dividerColor,
|
||||||
|
width: 1.0,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
borderRadius: Corners.s6Border,
|
||||||
|
),
|
||||||
child: child,
|
child: child,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -73,9 +73,11 @@ class _CalendarPageState extends State<CalendarPage> {
|
|||||||
listenWhen: (p, c) => p.updateEvent != c.updateEvent,
|
listenWhen: (p, c) => p.updateEvent != c.updateEvent,
|
||||||
listener: (context, state) {
|
listener: (context, state) {
|
||||||
if (state.updateEvent != null) {
|
if (state.updateEvent != null) {
|
||||||
_eventController.removeWhere((element) =>
|
_eventController.removeWhere(
|
||||||
|
(element) =>
|
||||||
state.updateEvent!.event!.eventId ==
|
state.updateEvent!.event!.eventId ==
|
||||||
element.event!.eventId);
|
element.event!.eventId,
|
||||||
|
);
|
||||||
_eventController.add(state.updateEvent!);
|
_eventController.add(state.updateEvent!);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -18,6 +18,8 @@ import 'package:protobuf/protobuf.dart';
|
|||||||
|
|
||||||
import 'calendar_setting.dart';
|
import 'calendar_setting.dart';
|
||||||
|
|
||||||
|
/// Widget that displays a list of settings that alters the appearance of the
|
||||||
|
/// calendar
|
||||||
class CalendarLayoutSetting extends StatefulWidget {
|
class CalendarLayoutSetting extends StatefulWidget {
|
||||||
final CalendarSettingContext settingContext;
|
final CalendarSettingContext settingContext;
|
||||||
final Function(CalendarLayoutSettingsPB? layoutSettings) onUpdated;
|
final Function(CalendarLayoutSettingsPB? layoutSettings) onUpdated;
|
||||||
@ -96,18 +98,15 @@ class _CalendarLayoutSettingState extends State<CalendarLayoutSetting> {
|
|||||||
fieldId: settings.layoutFieldId,
|
fieldId: settings.layoutFieldId,
|
||||||
popoverMutex: popoverMutex,
|
popoverMutex: popoverMutex,
|
||||||
onUpdated: (fieldId) {
|
onUpdated: (fieldId) {
|
||||||
_updateLayoutSettings(context,
|
_updateLayoutSettings(
|
||||||
onUpdated: widget.onUpdated, layoutFieldId: fieldId);
|
context,
|
||||||
|
onUpdated: widget.onUpdated,
|
||||||
|
layoutFieldId: fieldId,
|
||||||
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
default:
|
default:
|
||||||
return ShowWeekends(
|
return const SizedBox();
|
||||||
showWeekends: settings.showWeekends,
|
|
||||||
onUpdated: (showWeekends) {
|
|
||||||
_updateLayoutSettings(context,
|
|
||||||
onUpdated: widget.onUpdated, showWeekends: showWeekends);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}).toList();
|
}).toList();
|
||||||
|
|
||||||
@ -129,7 +128,8 @@ class _CalendarLayoutSettingState extends State<CalendarLayoutSetting> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
List<CalendarLayoutSettingAction> _availableCalendarSettings(
|
List<CalendarLayoutSettingAction> _availableCalendarSettings(
|
||||||
CalendarLayoutSettingsPB layoutSettings) {
|
CalendarLayoutSettingsPB layoutSettings,
|
||||||
|
) {
|
||||||
List<CalendarLayoutSettingAction> settings = [
|
List<CalendarLayoutSettingAction> settings = [
|
||||||
CalendarLayoutSettingAction.layoutField,
|
CalendarLayoutSettingAction.layoutField,
|
||||||
// CalendarLayoutSettingAction.layoutType,
|
// CalendarLayoutSettingAction.layoutType,
|
||||||
@ -220,8 +220,9 @@ class LayoutDateField extends StatelessWidget {
|
|||||||
popupBuilder: (context) {
|
popupBuilder: (context) {
|
||||||
return BlocProvider(
|
return BlocProvider(
|
||||||
create: (context) => getIt<DatabasePropertyBloc>(
|
create: (context) => getIt<DatabasePropertyBloc>(
|
||||||
param1: viewId, param2: fieldController)
|
param1: viewId,
|
||||||
..add(const DatabasePropertyEvent.initial()),
|
param2: fieldController,
|
||||||
|
)..add(const DatabasePropertyEvent.initial()),
|
||||||
child: BlocBuilder<DatabasePropertyBloc, DatabasePropertyState>(
|
child: BlocBuilder<DatabasePropertyBloc, DatabasePropertyState>(
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
final items = state.fieldContexts
|
final items = state.fieldContexts
|
||||||
@ -264,7 +265,8 @@ class LayoutDateField extends StatelessWidget {
|
|||||||
child: FlowyButton(
|
child: FlowyButton(
|
||||||
margin: const EdgeInsets.symmetric(vertical: 2.0, horizontal: 10.0),
|
margin: const EdgeInsets.symmetric(vertical: 2.0, horizontal: 10.0),
|
||||||
text: FlowyText.medium(
|
text: FlowyText.medium(
|
||||||
LocaleKeys.calendar_settings_layoutDateField.tr()),
|
LocaleKeys.calendar_settings_layoutDateField.tr(),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@ -368,7 +370,8 @@ class FirstDayOfWeek extends StatelessWidget {
|
|||||||
child: FlowyButton(
|
child: FlowyButton(
|
||||||
margin: const EdgeInsets.symmetric(vertical: 2.0, horizontal: 10.0),
|
margin: const EdgeInsets.symmetric(vertical: 2.0, horizontal: 10.0),
|
||||||
text: FlowyText.medium(
|
text: FlowyText.medium(
|
||||||
LocaleKeys.calendar_settings_firstDayOfWeek.tr()),
|
LocaleKeys.calendar_settings_firstDayOfWeek.tr(),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -15,8 +15,8 @@ import 'package:styled_widget/styled_widget.dart';
|
|||||||
import 'calendar_layout_setting.dart';
|
import 'calendar_layout_setting.dart';
|
||||||
|
|
||||||
/// The highest-level widget shown in the popover triggered by clicking the
|
/// The highest-level widget shown in the popover triggered by clicking the
|
||||||
/// "Settings" button. By default, shows [AllCalendarSettings] but upon
|
/// "Settings" button. Shows [AllCalendarSettings] by default, but replaces its
|
||||||
/// selecting a category, replaces contents with contents of the submenu.
|
/// contents with the submenu when a category is selected.
|
||||||
class CalendarSetting extends StatelessWidget {
|
class CalendarSetting extends StatelessWidget {
|
||||||
final CalendarSettingContext settingContext;
|
final CalendarSettingContext settingContext;
|
||||||
final CalendarLayoutSettingsPB? layoutSettings;
|
final CalendarLayoutSettingsPB? layoutSettings;
|
||||||
|
@ -45,10 +45,12 @@ class CheckboxFilterEditorBloc
|
|||||||
didReceiveFilter: (FilterPB filter) {
|
didReceiveFilter: (FilterPB filter) {
|
||||||
final filterInfo = state.filterInfo.copyWith(filter: filter);
|
final filterInfo = state.filterInfo.copyWith(filter: filter);
|
||||||
final checkboxFilter = filterInfo.checkboxFilter()!;
|
final checkboxFilter = filterInfo.checkboxFilter()!;
|
||||||
emit(state.copyWith(
|
emit(
|
||||||
|
state.copyWith(
|
||||||
filterInfo: filterInfo,
|
filterInfo: filterInfo,
|
||||||
filter: checkboxFilter,
|
filter: checkboxFilter,
|
||||||
));
|
),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@ -79,7 +81,8 @@ class CheckboxFilterEditorEvent with _$CheckboxFilterEditorEvent {
|
|||||||
const factory CheckboxFilterEditorEvent.didReceiveFilter(FilterPB filter) =
|
const factory CheckboxFilterEditorEvent.didReceiveFilter(FilterPB filter) =
|
||||||
_DidReceiveFilter;
|
_DidReceiveFilter;
|
||||||
const factory CheckboxFilterEditorEvent.updateCondition(
|
const factory CheckboxFilterEditorEvent.updateCondition(
|
||||||
CheckboxFilterConditionPB condition) = _UpdateCondition;
|
CheckboxFilterConditionPB condition,
|
||||||
|
) = _UpdateCondition;
|
||||||
const factory CheckboxFilterEditorEvent.delete() = _Delete;
|
const factory CheckboxFilterEditorEvent.delete() = _Delete;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,10 +46,12 @@ class ChecklistFilterEditorBloc
|
|||||||
didReceiveFilter: (FilterPB filter) {
|
didReceiveFilter: (FilterPB filter) {
|
||||||
final filterInfo = state.filterInfo.copyWith(filter: filter);
|
final filterInfo = state.filterInfo.copyWith(filter: filter);
|
||||||
final checklistFilter = filterInfo.checklistFilter()!;
|
final checklistFilter = filterInfo.checklistFilter()!;
|
||||||
emit(state.copyWith(
|
emit(
|
||||||
|
state.copyWith(
|
||||||
filterInfo: filterInfo,
|
filterInfo: filterInfo,
|
||||||
filter: checklistFilter,
|
filter: checklistFilter,
|
||||||
));
|
),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@ -82,7 +84,8 @@ class ChecklistFilterEditorEvent with _$ChecklistFilterEditorEvent {
|
|||||||
const factory ChecklistFilterEditorEvent.didReceiveFilter(FilterPB filter) =
|
const factory ChecklistFilterEditorEvent.didReceiveFilter(FilterPB filter) =
|
||||||
_DidReceiveFilter;
|
_DidReceiveFilter;
|
||||||
const factory ChecklistFilterEditorEvent.updateCondition(
|
const factory ChecklistFilterEditorEvent.updateCondition(
|
||||||
ChecklistFilterConditionPB condition) = _UpdateCondition;
|
ChecklistFilterConditionPB condition,
|
||||||
|
) = _UpdateCondition;
|
||||||
const factory ChecklistFilterEditorEvent.delete() = _Delete;
|
const factory ChecklistFilterEditorEvent.delete() = _Delete;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,11 +14,13 @@ class GridFilterMenuBloc
|
|||||||
void Function(List<FieldInfo>)? _onFieldFn;
|
void Function(List<FieldInfo>)? _onFieldFn;
|
||||||
|
|
||||||
GridFilterMenuBloc({required this.viewId, required this.fieldController})
|
GridFilterMenuBloc({required this.viewId, required this.fieldController})
|
||||||
: super(GridFilterMenuState.initial(
|
: super(
|
||||||
|
GridFilterMenuState.initial(
|
||||||
viewId,
|
viewId,
|
||||||
fieldController.filterInfos,
|
fieldController.filterInfos,
|
||||||
fieldController.fieldInfos,
|
fieldController.fieldInfos,
|
||||||
)) {
|
),
|
||||||
|
) {
|
||||||
on<GridFilterMenuEvent>(
|
on<GridFilterMenuEvent>(
|
||||||
(event, emit) async {
|
(event, emit) async {
|
||||||
event.when(
|
event.when(
|
||||||
@ -82,7 +84,8 @@ class GridFilterMenuBloc
|
|||||||
class GridFilterMenuEvent with _$GridFilterMenuEvent {
|
class GridFilterMenuEvent with _$GridFilterMenuEvent {
|
||||||
const factory GridFilterMenuEvent.initial() = _Initial;
|
const factory GridFilterMenuEvent.initial() = _Initial;
|
||||||
const factory GridFilterMenuEvent.didReceiveFilters(
|
const factory GridFilterMenuEvent.didReceiveFilters(
|
||||||
List<FilterInfo> filters) = _DidReceiveFilters;
|
List<FilterInfo> filters,
|
||||||
|
) = _DidReceiveFilters;
|
||||||
const factory GridFilterMenuEvent.didReceiveFields(List<FieldInfo> fields) =
|
const factory GridFilterMenuEvent.didReceiveFields(List<FieldInfo> fields) =
|
||||||
_DidReceiveFields;
|
_DidReceiveFields;
|
||||||
const factory GridFilterMenuEvent.toggleMenu() = _SetMenuVisibility;
|
const factory GridFilterMenuEvent.toggleMenu() = _SetMenuVisibility;
|
||||||
|
@ -61,10 +61,12 @@ class SelectOptionFilterEditorBloc
|
|||||||
didReceiveFilter: (FilterPB filter) {
|
didReceiveFilter: (FilterPB filter) {
|
||||||
final filterInfo = state.filterInfo.copyWith(filter: filter);
|
final filterInfo = state.filterInfo.copyWith(filter: filter);
|
||||||
final selectOptionFilter = filterInfo.selectOptionFilter()!;
|
final selectOptionFilter = filterInfo.selectOptionFilter()!;
|
||||||
emit(state.copyWith(
|
emit(
|
||||||
|
state.copyWith(
|
||||||
filterInfo: filterInfo,
|
filterInfo: filterInfo,
|
||||||
filter: selectOptionFilter,
|
filter: selectOptionFilter,
|
||||||
));
|
),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
updateFilterDescription: (String desc) {
|
updateFilterDescription: (String desc) {
|
||||||
emit(state.copyWith(filterDesc: desc));
|
emit(state.copyWith(filterDesc: desc));
|
||||||
@ -112,13 +114,17 @@ class SelectOptionFilterEditorBloc
|
|||||||
class SelectOptionFilterEditorEvent with _$SelectOptionFilterEditorEvent {
|
class SelectOptionFilterEditorEvent with _$SelectOptionFilterEditorEvent {
|
||||||
const factory SelectOptionFilterEditorEvent.initial() = _Initial;
|
const factory SelectOptionFilterEditorEvent.initial() = _Initial;
|
||||||
const factory SelectOptionFilterEditorEvent.didReceiveFilter(
|
const factory SelectOptionFilterEditorEvent.didReceiveFilter(
|
||||||
FilterPB filter) = _DidReceiveFilter;
|
FilterPB filter,
|
||||||
|
) = _DidReceiveFilter;
|
||||||
const factory SelectOptionFilterEditorEvent.updateCondition(
|
const factory SelectOptionFilterEditorEvent.updateCondition(
|
||||||
SelectOptionConditionPB condition) = _UpdateCondition;
|
SelectOptionConditionPB condition,
|
||||||
|
) = _UpdateCondition;
|
||||||
const factory SelectOptionFilterEditorEvent.updateContent(
|
const factory SelectOptionFilterEditorEvent.updateContent(
|
||||||
List<String> optionIds) = _UpdateContent;
|
List<String> optionIds,
|
||||||
|
) = _UpdateContent;
|
||||||
const factory SelectOptionFilterEditorEvent.updateFilterDescription(
|
const factory SelectOptionFilterEditorEvent.updateFilterDescription(
|
||||||
String desc) = _UpdateDesc;
|
String desc,
|
||||||
|
) = _UpdateDesc;
|
||||||
const factory SelectOptionFilterEditorEvent.delete() = _Delete;
|
const factory SelectOptionFilterEditorEvent.delete() = _Delete;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,15 +43,22 @@ class SelectOptionFilterListBloc<T>
|
|||||||
didReceiveOptions: (newOptions) {
|
didReceiveOptions: (newOptions) {
|
||||||
List<SelectOptionPB> options = List.from(newOptions);
|
List<SelectOptionPB> options = List.from(newOptions);
|
||||||
options.retainWhere(
|
options.retainWhere(
|
||||||
(element) => element.name.contains(state.predicate));
|
(element) => element.name.contains(state.predicate),
|
||||||
|
);
|
||||||
|
|
||||||
final visibleOptions = options.map((option) {
|
final visibleOptions = options.map((option) {
|
||||||
return VisibleSelectOption(
|
return VisibleSelectOption(
|
||||||
option, state.selectedOptionIds.contains(option.id));
|
option,
|
||||||
|
state.selectedOptionIds.contains(option.id),
|
||||||
|
);
|
||||||
}).toList();
|
}).toList();
|
||||||
|
|
||||||
emit(state.copyWith(
|
emit(
|
||||||
options: options, visibleOptions: visibleOptions));
|
state.copyWith(
|
||||||
|
options: options,
|
||||||
|
visibleOptions: visibleOptions,
|
||||||
|
),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
filterOption: (optionName) {
|
filterOption: (optionName) {
|
||||||
_updateSelectOptions(predicate: optionName, emit: emit);
|
_updateSelectOptions(predicate: optionName, emit: emit);
|
||||||
@ -71,11 +78,13 @@ class SelectOptionFilterListBloc<T>
|
|||||||
selectedOptionIds ?? state.selectedOptionIds,
|
selectedOptionIds ?? state.selectedOptionIds,
|
||||||
);
|
);
|
||||||
|
|
||||||
emit(state.copyWith(
|
emit(
|
||||||
|
state.copyWith(
|
||||||
predicate: predicate ?? state.predicate,
|
predicate: predicate ?? state.predicate,
|
||||||
visibleOptions: visibleOptions,
|
visibleOptions: visibleOptions,
|
||||||
selectedOptionIds: selectedOptionIds ?? state.selectedOptionIds,
|
selectedOptionIds: selectedOptionIds ?? state.selectedOptionIds,
|
||||||
));
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
List<VisibleSelectOption> _makeVisibleOptions(
|
List<VisibleSelectOption> _makeVisibleOptions(
|
||||||
@ -105,11 +114,14 @@ class SelectOptionFilterListBloc<T>
|
|||||||
class SelectOptionFilterListEvent with _$SelectOptionFilterListEvent {
|
class SelectOptionFilterListEvent with _$SelectOptionFilterListEvent {
|
||||||
const factory SelectOptionFilterListEvent.initial() = _Initial;
|
const factory SelectOptionFilterListEvent.initial() = _Initial;
|
||||||
const factory SelectOptionFilterListEvent.selectOption(
|
const factory SelectOptionFilterListEvent.selectOption(
|
||||||
SelectOptionPB option) = _SelectOption;
|
SelectOptionPB option,
|
||||||
|
) = _SelectOption;
|
||||||
const factory SelectOptionFilterListEvent.unselectOption(
|
const factory SelectOptionFilterListEvent.unselectOption(
|
||||||
SelectOptionPB option) = _UnSelectOption;
|
SelectOptionPB option,
|
||||||
|
) = _UnSelectOption;
|
||||||
const factory SelectOptionFilterListEvent.didReceiveOptions(
|
const factory SelectOptionFilterListEvent.didReceiveOptions(
|
||||||
List<SelectOptionPB> options) = _DidReceiveOptions;
|
List<SelectOptionPB> options,
|
||||||
|
) = _DidReceiveOptions;
|
||||||
const factory SelectOptionFilterListEvent.filterOption(String optionName) =
|
const factory SelectOptionFilterListEvent.filterOption(String optionName) =
|
||||||
_SelectOptionFilter;
|
_SelectOptionFilter;
|
||||||
}
|
}
|
||||||
|
@ -54,10 +54,12 @@ class TextFilterEditorBloc
|
|||||||
didReceiveFilter: (FilterPB filter) {
|
didReceiveFilter: (FilterPB filter) {
|
||||||
final filterInfo = state.filterInfo.copyWith(filter: filter);
|
final filterInfo = state.filterInfo.copyWith(filter: filter);
|
||||||
final textFilter = filterInfo.textFilter()!;
|
final textFilter = filterInfo.textFilter()!;
|
||||||
emit(state.copyWith(
|
emit(
|
||||||
|
state.copyWith(
|
||||||
filterInfo: filterInfo,
|
filterInfo: filterInfo,
|
||||||
filter: textFilter,
|
filter: textFilter,
|
||||||
));
|
),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@ -88,7 +90,8 @@ class TextFilterEditorEvent with _$TextFilterEditorEvent {
|
|||||||
const factory TextFilterEditorEvent.didReceiveFilter(FilterPB filter) =
|
const factory TextFilterEditorEvent.didReceiveFilter(FilterPB filter) =
|
||||||
_DidReceiveFilter;
|
_DidReceiveFilter;
|
||||||
const factory TextFilterEditorEvent.updateCondition(
|
const factory TextFilterEditorEvent.updateCondition(
|
||||||
TextFilterConditionPB condition) = _UpdateCondition;
|
TextFilterConditionPB condition,
|
||||||
|
) = _UpdateCondition;
|
||||||
const factory TextFilterEditorEvent.updateContent(String content) =
|
const factory TextFilterEditorEvent.updateContent(String content) =
|
||||||
_UpdateContent;
|
_UpdateContent;
|
||||||
const factory TextFilterEditorEvent.delete() = _Delete;
|
const factory TextFilterEditorEvent.delete() = _Delete;
|
||||||
|
@ -8,9 +8,11 @@ class GridAccessoryMenuBloc
|
|||||||
final String viewId;
|
final String viewId;
|
||||||
|
|
||||||
GridAccessoryMenuBloc({required this.viewId})
|
GridAccessoryMenuBloc({required this.viewId})
|
||||||
: super(GridAccessoryMenuState.initial(
|
: super(
|
||||||
|
GridAccessoryMenuState.initial(
|
||||||
viewId,
|
viewId,
|
||||||
)) {
|
),
|
||||||
|
) {
|
||||||
on<GridAccessoryMenuEvent>(
|
on<GridAccessoryMenuEvent>(
|
||||||
(event, emit) async {
|
(event, emit) async {
|
||||||
event.when(
|
event.when(
|
||||||
|
@ -39,16 +39,20 @@ class GridBloc extends Bloc<GridEvent, GridState> {
|
|||||||
emit(state.copyWith(grid: Some(grid)));
|
emit(state.copyWith(grid: Some(grid)));
|
||||||
},
|
},
|
||||||
didReceiveFieldUpdate: (fields) {
|
didReceiveFieldUpdate: (fields) {
|
||||||
emit(state.copyWith(
|
emit(
|
||||||
|
state.copyWith(
|
||||||
fields: GridFieldEquatable(fields),
|
fields: GridFieldEquatable(fields),
|
||||||
));
|
),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
didReceiveRowUpdate: (newRowInfos, reason) {
|
didReceiveRowUpdate: (newRowInfos, reason) {
|
||||||
emit(state.copyWith(
|
emit(
|
||||||
|
state.copyWith(
|
||||||
rowInfos: newRowInfos,
|
rowInfos: newRowInfos,
|
||||||
rowCount: newRowInfos.length,
|
rowCount: newRowInfos.length,
|
||||||
reason: reason,
|
reason: reason,
|
||||||
));
|
),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@ -146,7 +150,8 @@ class GridState with _$GridState {
|
|||||||
class GridLoadingState with _$GridLoadingState {
|
class GridLoadingState with _$GridLoadingState {
|
||||||
const factory GridLoadingState.loading() = _Loading;
|
const factory GridLoadingState.loading() = _Loading;
|
||||||
const factory GridLoadingState.finish(
|
const factory GridLoadingState.finish(
|
||||||
Either<Unit, FlowyError> successOrFail) = _Finish;
|
Either<Unit, FlowyError> successOrFail,
|
||||||
|
) = _Finish;
|
||||||
}
|
}
|
||||||
|
|
||||||
class GridFieldEquatable extends Equatable {
|
class GridFieldEquatable extends Equatable {
|
||||||
|
@ -40,7 +40,9 @@ class GridHeaderBloc extends Bloc<GridHeaderEvent, GridHeaderState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _moveField(
|
Future<void> _moveField(
|
||||||
_MoveField value, Emitter<GridHeaderState> emit) async {
|
_MoveField value,
|
||||||
|
Emitter<GridHeaderState> emit,
|
||||||
|
) async {
|
||||||
final fields = List<FieldInfo>.from(state.fields);
|
final fields = List<FieldInfo>.from(state.fields);
|
||||||
fields.insert(value.toIndex, fields.removeAt(value.fromIndex));
|
fields.insert(value.toIndex, fields.removeAt(value.fromIndex));
|
||||||
emit(state.copyWith(fields: fields));
|
emit(state.copyWith(fields: fields));
|
||||||
@ -69,7 +71,10 @@ class GridHeaderEvent with _$GridHeaderEvent {
|
|||||||
const factory GridHeaderEvent.didReceiveFieldUpdate(List<FieldInfo> fields) =
|
const factory GridHeaderEvent.didReceiveFieldUpdate(List<FieldInfo> fields) =
|
||||||
_DidReceiveFieldUpdate;
|
_DidReceiveFieldUpdate;
|
||||||
const factory GridHeaderEvent.moveField(
|
const factory GridHeaderEvent.moveField(
|
||||||
FieldPB field, int fromIndex, int toIndex) = _MoveField;
|
FieldPB field,
|
||||||
|
int fromIndex,
|
||||||
|
int toIndex,
|
||||||
|
) = _MoveField;
|
||||||
}
|
}
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
|
@ -35,11 +35,13 @@ class RowBloc extends Bloc<RowEvent, RowState> {
|
|||||||
final cells = cellByFieldId.values
|
final cells = cellByFieldId.values
|
||||||
.map((e) => GridCellEquatable(e.fieldInfo))
|
.map((e) => GridCellEquatable(e.fieldInfo))
|
||||||
.toList();
|
.toList();
|
||||||
emit(state.copyWith(
|
emit(
|
||||||
|
state.copyWith(
|
||||||
cellByFieldId: cellByFieldId,
|
cellByFieldId: cellByFieldId,
|
||||||
cells: UnmodifiableListView(cells),
|
cells: UnmodifiableListView(cells),
|
||||||
changeReason: reason,
|
changeReason: reason,
|
||||||
));
|
),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@ -68,8 +70,9 @@ class RowEvent with _$RowEvent {
|
|||||||
const factory RowEvent.initial() = _InitialRow;
|
const factory RowEvent.initial() = _InitialRow;
|
||||||
const factory RowEvent.createRow() = _CreateRow;
|
const factory RowEvent.createRow() = _CreateRow;
|
||||||
const factory RowEvent.didReceiveCells(
|
const factory RowEvent.didReceiveCells(
|
||||||
CellByFieldId cellsByFieldId, RowsChangedReason reason) =
|
CellByFieldId cellsByFieldId,
|
||||||
_DidReceiveCells;
|
RowsChangedReason reason,
|
||||||
|
) = _DidReceiveCells;
|
||||||
}
|
}
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
|
@ -59,7 +59,8 @@ class RowDetailEvent with _$RowDetailEvent {
|
|||||||
const factory RowDetailEvent.initial() = _Initial;
|
const factory RowDetailEvent.initial() = _Initial;
|
||||||
const factory RowDetailEvent.deleteField(String fieldId) = _DeleteField;
|
const factory RowDetailEvent.deleteField(String fieldId) = _DeleteField;
|
||||||
const factory RowDetailEvent.didReceiveCellDatas(
|
const factory RowDetailEvent.didReceiveCellDatas(
|
||||||
List<CellIdentifier> gridCells) = _DidReceiveCellDatas;
|
List<CellIdentifier> gridCells,
|
||||||
|
) = _DidReceiveCellDatas;
|
||||||
}
|
}
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
|
@ -84,7 +84,8 @@ class CreateSortBloc extends Bloc<CreateSortEvent, CreateSortState> {
|
|||||||
final result = await _sortBackendSvc.insertSort(
|
final result = await _sortBackendSvc.insertSort(
|
||||||
fieldId: field.id,
|
fieldId: field.id,
|
||||||
fieldType: field.fieldType,
|
fieldType: field.fieldType,
|
||||||
condition: SortConditionPB.Ascending);
|
condition: SortConditionPB.Ascending,
|
||||||
|
);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -100,7 +100,9 @@ class SortEditorEvent with _$SortEditorEvent {
|
|||||||
const factory SortEditorEvent.didReceiveSorts(List<SortInfo> sortInfos) =
|
const factory SortEditorEvent.didReceiveSorts(List<SortInfo> sortInfos) =
|
||||||
_DidReceiveSorts;
|
_DidReceiveSorts;
|
||||||
const factory SortEditorEvent.setCondition(
|
const factory SortEditorEvent.setCondition(
|
||||||
SortInfo sortInfo, SortConditionPB condition) = _SetCondition;
|
SortInfo sortInfo,
|
||||||
|
SortConditionPB condition,
|
||||||
|
) = _SetCondition;
|
||||||
const factory SortEditorEvent.deleteSort(SortInfo sortInfo) = _DeleteSort;
|
const factory SortEditorEvent.deleteSort(SortInfo sortInfo) = _DeleteSort;
|
||||||
const factory SortEditorEvent.deleteAllSorts() = _DeleteAllSorts;
|
const factory SortEditorEvent.deleteAllSorts() = _DeleteAllSorts;
|
||||||
}
|
}
|
||||||
|
@ -14,11 +14,13 @@ class SortMenuBloc extends Bloc<SortMenuEvent, SortMenuState> {
|
|||||||
void Function(List<FieldInfo>)? _onFieldFn;
|
void Function(List<FieldInfo>)? _onFieldFn;
|
||||||
|
|
||||||
SortMenuBloc({required this.viewId, required this.fieldController})
|
SortMenuBloc({required this.viewId, required this.fieldController})
|
||||||
: super(SortMenuState.initial(
|
: super(
|
||||||
|
SortMenuState.initial(
|
||||||
viewId,
|
viewId,
|
||||||
fieldController.sortInfos,
|
fieldController.sortInfos,
|
||||||
fieldController.fieldInfos,
|
fieldController.fieldInfos,
|
||||||
)) {
|
),
|
||||||
|
) {
|
||||||
on<SortMenuEvent>(
|
on<SortMenuEvent>(
|
||||||
(event, emit) async {
|
(event, emit) async {
|
||||||
event.when(
|
event.when(
|
||||||
|
@ -117,7 +117,8 @@ class FlowyGrid extends StatefulWidget {
|
|||||||
|
|
||||||
class _FlowyGridState extends State<FlowyGrid> {
|
class _FlowyGridState extends State<FlowyGrid> {
|
||||||
final _scrollController = GridScrollController(
|
final _scrollController = GridScrollController(
|
||||||
scrollGroupController: LinkedScrollControllerGroup());
|
scrollGroupController: LinkedScrollControllerGroup(),
|
||||||
|
);
|
||||||
late ScrollController headerScrollController;
|
late ScrollController headerScrollController;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -325,7 +326,8 @@ class _GridRowsState extends State<_GridRows> {
|
|||||||
cellBuilder: cellBuilder,
|
cellBuilder: cellBuilder,
|
||||||
dataController: dataController,
|
dataController: dataController,
|
||||||
);
|
);
|
||||||
});
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,9 +8,9 @@ class GridScrollController {
|
|||||||
|
|
||||||
final List<ScrollController> _linkHorizontalControllers = [];
|
final List<ScrollController> _linkHorizontalControllers = [];
|
||||||
|
|
||||||
GridScrollController(
|
GridScrollController({
|
||||||
{required LinkedScrollControllerGroup scrollGroupController})
|
required LinkedScrollControllerGroup scrollGroupController,
|
||||||
: _scrollGroupController = scrollGroupController,
|
}) : _scrollGroupController = scrollGroupController,
|
||||||
verticalController = ScrollController(),
|
verticalController = ScrollController(),
|
||||||
horizontalController = scrollGroupController.addAndGet();
|
horizontalController = scrollGroupController.addAndGet();
|
||||||
|
|
||||||
|
@ -28,10 +28,7 @@ class GridSize {
|
|||||||
vertical: GridSize.cellVPadding,
|
vertical: GridSize.cellVPadding,
|
||||||
);
|
);
|
||||||
|
|
||||||
static EdgeInsets get typeOptionContentInsets => const EdgeInsets.symmetric(
|
static EdgeInsets get typeOptionContentInsets => const EdgeInsets.all(4);
|
||||||
horizontal: 6,
|
|
||||||
vertical: 2,
|
|
||||||
);
|
|
||||||
|
|
||||||
static EdgeInsets get footerContentInsets => EdgeInsets.fromLTRB(
|
static EdgeInsets get footerContentInsets => EdgeInsets.fromLTRB(
|
||||||
GridSize.leadingHeaderPadding,
|
GridSize.leadingHeaderPadding,
|
||||||
|
@ -24,7 +24,8 @@ class GridAccessoryMenu extends StatelessWidget {
|
|||||||
listenWhen: (p, c) => p.isVisible != c.isVisible,
|
listenWhen: (p, c) => p.isVisible != c.isVisible,
|
||||||
listener: (context, state) => context
|
listener: (context, state) => context
|
||||||
.read<GridAccessoryMenuBloc>()
|
.read<GridAccessoryMenuBloc>()
|
||||||
.add(const GridAccessoryMenuEvent.toggleMenu())),
|
.add(const GridAccessoryMenuEvent.toggleMenu()),
|
||||||
|
),
|
||||||
BlocListener<SortMenuBloc, SortMenuState>(
|
BlocListener<SortMenuBloc, SortMenuState>(
|
||||||
listenWhen: (p, c) => p.isVisible != c.isVisible,
|
listenWhen: (p, c) => p.isVisible != c.isVisible,
|
||||||
listener: (context, state) => context
|
listener: (context, state) => context
|
||||||
|
@ -100,7 +100,9 @@ class _CheckboxFilterEditorState extends State<CheckboxFilterEditor> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildFilterPanel(
|
Widget _buildFilterPanel(
|
||||||
BuildContext context, CheckboxFilterEditorState state) {
|
BuildContext context,
|
||||||
|
CheckboxFilterEditorState state,
|
||||||
|
) {
|
||||||
return SizedBox(
|
return SizedBox(
|
||||||
height: 20,
|
height: 20,
|
||||||
child: Row(
|
child: Row(
|
||||||
|
@ -70,9 +70,11 @@ class _ChecklistFilterChoicechipState extends State<ChecklistFilterChoicechip> {
|
|||||||
class ChecklistFilterEditor extends StatefulWidget {
|
class ChecklistFilterEditor extends StatefulWidget {
|
||||||
final ChecklistFilterEditorBloc bloc;
|
final ChecklistFilterEditorBloc bloc;
|
||||||
final PopoverMutex popoverMutex;
|
final PopoverMutex popoverMutex;
|
||||||
const ChecklistFilterEditor(
|
const ChecklistFilterEditor({
|
||||||
{required this.bloc, required this.popoverMutex, Key? key})
|
required this.bloc,
|
||||||
: super(key: key);
|
required this.popoverMutex,
|
||||||
|
Key? key,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
ChecklistState createState() => ChecklistState();
|
ChecklistState createState() => ChecklistState();
|
||||||
|
@ -65,8 +65,10 @@ 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(
|
||||||
color: AFThemeExtension.of(context).textColor),
|
"home/arrow_left",
|
||||||
|
color: AFThemeExtension.of(context).textColor,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 2),
|
padding: const EdgeInsets.symmetric(horizontal: 2),
|
||||||
|
@ -110,7 +110,10 @@ class _SelectOptionFilterEditorState extends State<SelectOptionFilterEditor> {
|
|||||||
selectedOptionIds: state.filter.optionIds,
|
selectedOptionIds: state.filter.optionIds,
|
||||||
onSelectedOptions: (optionIds) {
|
onSelectedOptions: (optionIds) {
|
||||||
context.read<SelectOptionFilterEditorBloc>().add(
|
context.read<SelectOptionFilterEditorBloc>().add(
|
||||||
SelectOptionFilterEditorEvent.updateContent(optionIds));
|
SelectOptionFilterEditorEvent.updateContent(
|
||||||
|
optionIds,
|
||||||
|
),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -132,7 +135,9 @@ class _SelectOptionFilterEditorState extends State<SelectOptionFilterEditor> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildFilterPanel(
|
Widget _buildFilterPanel(
|
||||||
BuildContext context, SelectOptionFilterEditorState state) {
|
BuildContext context,
|
||||||
|
SelectOptionFilterEditorState state,
|
||||||
|
) {
|
||||||
return SizedBox(
|
return SizedBox(
|
||||||
height: 20,
|
height: 20,
|
||||||
child: Row(
|
child: Row(
|
||||||
@ -144,7 +149,8 @@ class _SelectOptionFilterEditorState extends State<SelectOptionFilterEditor> {
|
|||||||
popoverMutex: popoverMutex,
|
popoverMutex: popoverMutex,
|
||||||
onCondition: (condition) {
|
onCondition: (condition) {
|
||||||
context.read<SelectOptionFilterEditorBloc>().add(
|
context.read<SelectOptionFilterEditorBloc>().add(
|
||||||
SelectOptionFilterEditorEvent.updateCondition(condition));
|
SelectOptionFilterEditorEvent.updateCondition(condition),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
const Spacer(),
|
const Spacer(),
|
||||||
|
@ -147,7 +147,9 @@ class _TextFilterEditorState extends State<TextFilterEditor> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildFilterTextField(
|
Widget _buildFilterTextField(
|
||||||
BuildContext context, TextFilterEditorState state) {
|
BuildContext context,
|
||||||
|
TextFilterEditorState state,
|
||||||
|
) {
|
||||||
return FlowyTextField(
|
return FlowyTextField(
|
||||||
text: state.filter.content,
|
text: state.filter.content,
|
||||||
hintText: LocaleKeys.grid_settings_typeAValue.tr(),
|
hintText: LocaleKeys.grid_settings_typeAValue.tr(),
|
||||||
|
@ -18,8 +18,10 @@ 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(
|
||||||
color: AFThemeExtension.of(context).textColor),
|
"home/arrow_left",
|
||||||
|
color: AFThemeExtension.of(context).textColor,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
return SizedBox(
|
return SizedBox(
|
||||||
|
@ -117,7 +117,10 @@ class _FilterTextFieldDelegate extends SliverPersistentHeaderDelegate {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(
|
Widget build(
|
||||||
BuildContext context, double shrinkOffset, bool overlapsContent) {
|
BuildContext context,
|
||||||
|
double shrinkOffset,
|
||||||
|
bool overlapsContent,
|
||||||
|
) {
|
||||||
return Container(
|
return Container(
|
||||||
padding: const EdgeInsets.only(top: 4),
|
padding: const EdgeInsets.only(top: 4),
|
||||||
height: fixHeight,
|
height: fixHeight,
|
||||||
|
@ -99,13 +99,16 @@ class _GridHeaderCellContainer extends StatelessWidget {
|
|||||||
top: borderSide,
|
top: borderSide,
|
||||||
right: borderSide,
|
right: borderSide,
|
||||||
bottom: borderSide,
|
bottom: borderSide,
|
||||||
));
|
),
|
||||||
|
);
|
||||||
|
|
||||||
return Container(
|
return Container(
|
||||||
width: width,
|
width: width,
|
||||||
decoration: decoration,
|
decoration: decoration,
|
||||||
child: ConstrainedBox(
|
child: ConstrainedBox(
|
||||||
constraints: const BoxConstraints.expand(), child: child),
|
constraints: const BoxConstraints.expand(),
|
||||||
|
child: child,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -149,10 +152,12 @@ class FieldCellButton extends StatelessWidget {
|
|||||||
final VoidCallback onTap;
|
final VoidCallback onTap;
|
||||||
final FieldPB field;
|
final FieldPB field;
|
||||||
final int? maxLines;
|
final int? maxLines;
|
||||||
|
final BorderRadius? radius;
|
||||||
const FieldCellButton({
|
const FieldCellButton({
|
||||||
required this.field,
|
required this.field,
|
||||||
required this.onTap,
|
required this.onTap,
|
||||||
this.maxLines = 1,
|
this.maxLines = 1,
|
||||||
|
this.radius = BorderRadius.zero,
|
||||||
Key? key,
|
Key? key,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
@ -169,7 +174,7 @@ class FieldCellButton extends StatelessWidget {
|
|||||||
leftIcon: FlowySvg(
|
leftIcon: FlowySvg(
|
||||||
name: field.fieldType.iconName(),
|
name: field.fieldType.iconName(),
|
||||||
),
|
),
|
||||||
radius: BorderRadius.zero,
|
radius: radius,
|
||||||
text: FlowyText.medium(
|
text: FlowyText.medium(
|
||||||
text,
|
text,
|
||||||
maxLines: maxLines,
|
maxLines: maxLines,
|
||||||
|
@ -101,7 +101,8 @@ class _FieldOperationList extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Column(children: [
|
return Column(
|
||||||
|
children: [
|
||||||
Flex(
|
Flex(
|
||||||
direction: Axis.horizontal,
|
direction: Axis.horizontal,
|
||||||
children: [
|
children: [
|
||||||
@ -119,7 +120,8 @@ class _FieldOperationList extends StatelessWidget {
|
|||||||
const Spacer(),
|
const Spacer(),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
]);
|
],
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _actionCell(FieldAction action) {
|
Widget _actionCell(FieldAction action) {
|
||||||
|
@ -90,11 +90,13 @@ class _SwitchFieldButton extends StatelessWidget {
|
|||||||
mutex: popoverMutex,
|
mutex: popoverMutex,
|
||||||
offset: const Offset(8, 0),
|
offset: const Offset(8, 0),
|
||||||
popupBuilder: (popOverContext) {
|
popupBuilder: (popOverContext) {
|
||||||
return FieldTypeList(onSelectField: (newFieldType) {
|
return FieldTypeList(
|
||||||
|
onSelectField: (newFieldType) {
|
||||||
context
|
context
|
||||||
.read<FieldTypeOptionEditBloc>()
|
.read<FieldTypeOptionEditBloc>()
|
||||||
.add(FieldTypeOptionEditEvent.switchToField(newFieldType));
|
.add(FieldTypeOptionEditEvent.switchToField(newFieldType));
|
||||||
});
|
},
|
||||||
|
);
|
||||||
},
|
},
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 12.0),
|
padding: const EdgeInsets.symmetric(horizontal: 12.0),
|
||||||
|
@ -39,7 +39,9 @@ class _GridHeaderSliverAdaptorState extends State<GridHeaderSliverAdaptor> {
|
|||||||
return BlocProvider(
|
return BlocProvider(
|
||||||
create: (context) {
|
create: (context) {
|
||||||
final bloc = getIt<GridHeaderBloc>(
|
final bloc = getIt<GridHeaderBloc>(
|
||||||
param1: widget.viewId, param2: widget.fieldController);
|
param1: widget.viewId,
|
||||||
|
param2: widget.fieldController,
|
||||||
|
);
|
||||||
bloc.add(const GridHeaderEvent.initial());
|
bloc.add(const GridHeaderEvent.initial());
|
||||||
return bloc;
|
return bloc;
|
||||||
},
|
},
|
||||||
@ -98,10 +100,16 @@ class _GridHeaderState extends State<_GridHeader> {
|
|||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
final cells = state.fields
|
final cells = state.fields
|
||||||
.where((field) => field.visibility)
|
.where((field) => field.visibility)
|
||||||
.map((field) =>
|
.map(
|
||||||
FieldCellContext(viewId: widget.viewId, field: field.field))
|
(field) =>
|
||||||
.map((ctx) =>
|
FieldCellContext(viewId: widget.viewId, field: field.field),
|
||||||
GridFieldCell(key: _getKeyById(ctx.field.id), cellContext: ctx))
|
)
|
||||||
|
.map(
|
||||||
|
(ctx) => GridFieldCell(
|
||||||
|
key: _getKeyById(ctx.field.id),
|
||||||
|
cellContext: ctx,
|
||||||
|
),
|
||||||
|
)
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
return Container(
|
return Container(
|
||||||
@ -124,8 +132,12 @@ class _GridHeaderState extends State<_GridHeader> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _onReorder(List<GridFieldCell> cells, int oldIndex, BuildContext context,
|
void _onReorder(
|
||||||
int newIndex) {
|
List<GridFieldCell> cells,
|
||||||
|
int oldIndex,
|
||||||
|
BuildContext context,
|
||||||
|
int newIndex,
|
||||||
|
) {
|
||||||
if (cells.length > oldIndex) {
|
if (cells.length > oldIndex) {
|
||||||
final field = cells[oldIndex].cellContext.field;
|
final field = cells[oldIndex].cellContext.field;
|
||||||
context
|
context
|
||||||
@ -177,7 +189,7 @@ class CreateFieldButton extends StatelessWidget {
|
|||||||
constraints: BoxConstraints.loose(const Size(240, 600)),
|
constraints: BoxConstraints.loose(const Size(240, 600)),
|
||||||
child: FlowyButton(
|
child: FlowyButton(
|
||||||
radius: BorderRadius.zero,
|
radius: BorderRadius.zero,
|
||||||
text: FlowyText.medium(LocaleKeys.grid_field_newColumn.tr()),
|
text: FlowyText.medium(LocaleKeys.grid_field_newProperty.tr()),
|
||||||
hoverColor: AFThemeExtension.of(context).greyHover,
|
hoverColor: AFThemeExtension.of(context).greyHover,
|
||||||
onTap: () {},
|
onTap: () {},
|
||||||
leftIcon: const FlowySvg(name: 'home/add'),
|
leftIcon: const FlowySvg(name: 'home/add'),
|
||||||
@ -197,12 +209,17 @@ class SliverHeaderDelegateImplementation
|
|||||||
final String gridId;
|
final String gridId;
|
||||||
final List<FieldPB> fields;
|
final List<FieldPB> fields;
|
||||||
|
|
||||||
SliverHeaderDelegateImplementation(
|
SliverHeaderDelegateImplementation({
|
||||||
{required this.gridId, required this.fields});
|
required this.gridId,
|
||||||
|
required this.fields,
|
||||||
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(
|
Widget build(
|
||||||
BuildContext context, double shrinkOffset, bool overlapsContent) {
|
BuildContext context,
|
||||||
|
double shrinkOffset,
|
||||||
|
bool overlapsContent,
|
||||||
|
) {
|
||||||
return _GridHeader(viewId: gridId);
|
return _GridHeader(viewId: gridId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,7 +81,8 @@ TypeOptionWidgetBuilder makeTypeOptionWidgetBuilder({
|
|||||||
fieldType: fieldType,
|
fieldType: fieldType,
|
||||||
dataController: dataController,
|
dataController: dataController,
|
||||||
),
|
),
|
||||||
popoverMutex);
|
popoverMutex,
|
||||||
|
);
|
||||||
case FieldType.SingleSelect:
|
case FieldType.SingleSelect:
|
||||||
return SingleSelectTypeOptionWidgetBuilder(
|
return SingleSelectTypeOptionWidgetBuilder(
|
||||||
makeTypeOptionContextWithDataController<SingleSelectTypeOptionPB>(
|
makeTypeOptionContextWithDataController<SingleSelectTypeOptionPB>(
|
||||||
|
@ -4,7 +4,8 @@ import 'builder.dart';
|
|||||||
|
|
||||||
class ChecklistTypeOptionWidgetBuilder extends TypeOptionWidgetBuilder {
|
class ChecklistTypeOptionWidgetBuilder extends TypeOptionWidgetBuilder {
|
||||||
ChecklistTypeOptionWidgetBuilder(
|
ChecklistTypeOptionWidgetBuilder(
|
||||||
ChecklistTypeOptionContext typeOptionContext);
|
ChecklistTypeOptionContext typeOptionContext,
|
||||||
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget? build(BuildContext context) => null;
|
Widget? build(BuildContext context) => null;
|
||||||
|
@ -299,6 +299,8 @@ extension DateFormatExtension on DateFormat {
|
|||||||
return LocaleKeys.grid_field_dateFormatLocal.tr();
|
return LocaleKeys.grid_field_dateFormatLocal.tr();
|
||||||
case DateFormat.US:
|
case DateFormat.US:
|
||||||
return LocaleKeys.grid_field_dateFormatUS.tr();
|
return LocaleKeys.grid_field_dateFormatUS.tr();
|
||||||
|
case DateFormat.DayMonthYear:
|
||||||
|
return LocaleKeys.grid_field_dateFormatDayMonthYear.tr();
|
||||||
default:
|
default:
|
||||||
throw UnimplementedError;
|
throw UnimplementedError;
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ import 'package:appflowy/plugins/database_view/application/field/type_option/num
|
|||||||
import 'package:appflowy/plugins/database_view/application/field/type_option/type_option_context.dart';
|
import 'package:appflowy/plugins/database_view/application/field/type_option/type_option_context.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/format.pbenum.dart';
|
import 'package:appflowy_backend/protobuf/flowy-database/format.pbenum.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
@ -28,10 +29,13 @@ class NumberTypeOptionWidgetBuilder extends TypeOptionWidgetBuilder {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget? build(BuildContext context) {
|
Widget? build(BuildContext context) {
|
||||||
return Column(children: [
|
return Column(
|
||||||
|
children: [
|
||||||
VSpace(GridSize.typeOptionSeparatorHeight),
|
VSpace(GridSize.typeOptionSeparatorHeight),
|
||||||
|
const TypeOptionSeparator(),
|
||||||
_widget,
|
_widget,
|
||||||
]);
|
],
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,41 +53,49 @@ class NumberTypeOptionWidget extends TypeOptionWidget {
|
|||||||
return BlocProvider(
|
return BlocProvider(
|
||||||
create: (context) =>
|
create: (context) =>
|
||||||
NumberTypeOptionBloc(typeOptionContext: typeOptionContext),
|
NumberTypeOptionBloc(typeOptionContext: typeOptionContext),
|
||||||
child: SizedBox(
|
|
||||||
height: GridSize.popoverItemHeight,
|
|
||||||
child: BlocConsumer<NumberTypeOptionBloc, NumberTypeOptionState>(
|
child: BlocConsumer<NumberTypeOptionBloc, NumberTypeOptionState>(
|
||||||
listener: (context, state) =>
|
listener: (context, state) =>
|
||||||
typeOptionContext.typeOption = state.typeOption,
|
typeOptionContext.typeOption = state.typeOption,
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
final button = SizedBox(
|
final selectNumUnitButton = SizedBox(
|
||||||
height: GridSize.popoverItemHeight,
|
height: GridSize.popoverItemHeight,
|
||||||
child: FlowyButton(
|
child: FlowyButton(
|
||||||
|
hoverColor: AFThemeExtension.of(context).lightGreyHover,
|
||||||
margin: GridSize.typeOptionContentInsets,
|
margin: GridSize.typeOptionContentInsets,
|
||||||
rightIcon: svgWidget(
|
rightIcon: svgWidget(
|
||||||
"grid/more",
|
"grid/more",
|
||||||
color: Theme.of(context).iconTheme.color,
|
color: AFThemeExtension.of(context).textColor,
|
||||||
),
|
),
|
||||||
text: Row(
|
text: FlowyText.regular(
|
||||||
children: [
|
state.typeOption.format.title(),
|
||||||
FlowyText.medium(LocaleKeys.grid_field_numberFormat.tr()),
|
color: AFThemeExtension.of(context).textColor,
|
||||||
const Spacer(),
|
|
||||||
FlowyText.regular(state.typeOption.format.title()),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
return AppFlowyPopover(
|
final numFormatTitle = Container(
|
||||||
|
padding: const EdgeInsets.only(left: 6),
|
||||||
|
height: GridSize.popoverItemHeight,
|
||||||
|
alignment: Alignment.centerLeft,
|
||||||
|
child: FlowyText.medium(
|
||||||
|
LocaleKeys.grid_field_numberFormat.tr(),
|
||||||
|
color: AFThemeExtension.of(context).textColor,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 12),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
numFormatTitle,
|
||||||
|
AppFlowyPopover(
|
||||||
mutex: popoverMutex,
|
mutex: popoverMutex,
|
||||||
triggerActions:
|
triggerActions:
|
||||||
PopoverTriggerFlags.hover | PopoverTriggerFlags.click,
|
PopoverTriggerFlags.hover | PopoverTriggerFlags.click,
|
||||||
offset: const Offset(8, 0),
|
offset: const Offset(8, 0),
|
||||||
constraints: BoxConstraints.loose(const Size(460, 440)),
|
constraints: BoxConstraints.loose(const Size(460, 440)),
|
||||||
margin: EdgeInsets.zero,
|
margin: EdgeInsets.zero,
|
||||||
child: Padding(
|
child: selectNumUnitButton,
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 12.0),
|
|
||||||
child: button,
|
|
||||||
),
|
|
||||||
popupBuilder: (BuildContext popoverContext) {
|
popupBuilder: (BuildContext popoverContext) {
|
||||||
return NumberFormatList(
|
return NumberFormatList(
|
||||||
onSelected: (format) {
|
onSelected: (format) {
|
||||||
@ -95,10 +107,12 @@ class NumberTypeOptionWidget extends TypeOptionWidget {
|
|||||||
selectedFormat: state.typeOption.format,
|
selectedFormat: state.typeOption.format,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -108,9 +122,11 @@ typedef SelectNumberFormatCallback = Function(NumberFormat format);
|
|||||||
class NumberFormatList extends StatelessWidget {
|
class NumberFormatList extends StatelessWidget {
|
||||||
final SelectNumberFormatCallback onSelected;
|
final SelectNumberFormatCallback onSelected;
|
||||||
final NumberFormat selectedFormat;
|
final NumberFormat selectedFormat;
|
||||||
const NumberFormatList(
|
const NumberFormatList({
|
||||||
{required this.selectedFormat, required this.onSelected, Key? key})
|
required this.selectedFormat,
|
||||||
: super(key: key);
|
required this.onSelected,
|
||||||
|
Key? key,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -131,7 +147,8 @@ class NumberFormatList extends StatelessWidget {
|
|||||||
format: format,
|
format: format,
|
||||||
onSelected: (format) {
|
onSelected: (format) {
|
||||||
onSelected(format);
|
onSelected(format);
|
||||||
});
|
},
|
||||||
|
);
|
||||||
}).toList();
|
}).toList();
|
||||||
|
|
||||||
final list = ListView.separated(
|
final list = ListView.separated(
|
||||||
|
@ -71,9 +71,11 @@ class OptionTitle extends StatelessWidget {
|
|||||||
return BlocBuilder<SelectOptionTypeOptionBloc, SelectOptionTypeOptionState>(
|
return BlocBuilder<SelectOptionTypeOptionBloc, SelectOptionTypeOptionState>(
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
List<Widget> children = [
|
List<Widget> children = [
|
||||||
FlowyText.medium(
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(left: 9),
|
||||||
|
child: FlowyText.medium(
|
||||||
LocaleKeys.grid_field_optionTitle.tr(),
|
LocaleKeys.grid_field_optionTitle.tr(),
|
||||||
color: Theme.of(context).hintColor,
|
),
|
||||||
)
|
)
|
||||||
];
|
];
|
||||||
if (state.options.isNotEmpty && !state.isEditingOption) {
|
if (state.options.isNotEmpty && !state.isEditingOption) {
|
||||||
|
@ -66,7 +66,8 @@ class SelectOptionTypeOptionEditor extends StatelessWidget {
|
|||||||
if (showOptions) {
|
if (showOptions) {
|
||||||
cells.add(const TypeOptionSeparator());
|
cells.add(const TypeOptionSeparator());
|
||||||
cells.add(
|
cells.add(
|
||||||
SelectOptionColorList(selectedColor: state.option.color));
|
SelectOptionColorList(selectedColor: state.option.color),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return SizedBox(
|
return SizedBox(
|
||||||
@ -126,9 +127,11 @@ class _DeleteTag extends StatelessWidget {
|
|||||||
class _OptionNameTextField extends StatelessWidget {
|
class _OptionNameTextField extends StatelessWidget {
|
||||||
final String name;
|
final String name;
|
||||||
final bool autoFocus;
|
final bool autoFocus;
|
||||||
const _OptionNameTextField(
|
const _OptionNameTextField({
|
||||||
{required this.name, required this.autoFocus, Key? key})
|
required this.name,
|
||||||
: super(key: key);
|
required this.autoFocus,
|
||||||
|
Key? key,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -157,7 +160,9 @@ class SelectOptionColorList extends StatelessWidget {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final cells = SelectOptionColorPB.values.map((color) {
|
final cells = SelectOptionColorPB.values.map((color) {
|
||||||
return _SelectOptionColorCell(
|
return _SelectOptionColorCell(
|
||||||
color: color, isSelected: selectedColor == color);
|
color: color,
|
||||||
|
isSelected: selectedColor == color,
|
||||||
|
);
|
||||||
}).toList();
|
}).toList();
|
||||||
|
|
||||||
return Column(
|
return Column(
|
||||||
@ -195,9 +200,11 @@ class SelectOptionColorList extends StatelessWidget {
|
|||||||
class _SelectOptionColorCell extends StatelessWidget {
|
class _SelectOptionColorCell extends StatelessWidget {
|
||||||
final SelectOptionColorPB color;
|
final SelectOptionColorPB color;
|
||||||
final bool isSelected;
|
final bool isSelected;
|
||||||
const _SelectOptionColorCell(
|
const _SelectOptionColorCell({
|
||||||
{required this.color, required this.isSelected, Key? key})
|
required this.color,
|
||||||
: super(key: key);
|
required this.isSelected,
|
||||||
|
Key? key,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
@ -68,11 +68,13 @@ class _GridRowState extends State<GridRow> {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
return Row(children: [
|
return Row(
|
||||||
|
children: [
|
||||||
const _RowLeading(),
|
const _RowLeading(),
|
||||||
content,
|
content,
|
||||||
const _RowTrailing(),
|
const _RowTrailing(),
|
||||||
]);
|
],
|
||||||
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -129,9 +131,11 @@ class _RowLeadingState extends State<_RowLeading> {
|
|||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
const _InsertButton(),
|
const _InsertButton(),
|
||||||
_MenuButton(openMenu: () {
|
_MenuButton(
|
||||||
|
openMenu: () {
|
||||||
popoverController.show();
|
popoverController.show();
|
||||||
}),
|
},
|
||||||
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -221,7 +225,8 @@ class RowContent extends StatelessWidget {
|
|||||||
mainAxisAlignment: MainAxisAlignment.start,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
children: _makeCells(context, state.cellByFieldId),
|
children: _makeCells(context, state.cellByFieldId),
|
||||||
));
|
),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -116,7 +116,10 @@ class _FilterTextFieldDelegate extends SliverPersistentHeaderDelegate {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(
|
Widget build(
|
||||||
BuildContext context, double shrinkOffset, bool overlapsContent) {
|
BuildContext context,
|
||||||
|
double shrinkOffset,
|
||||||
|
bool overlapsContent,
|
||||||
|
) {
|
||||||
return Container(
|
return Container(
|
||||||
padding: const EdgeInsets.only(top: 4),
|
padding: const EdgeInsets.only(top: 4),
|
||||||
height: fixHeight,
|
height: fixHeight,
|
||||||
|
@ -76,13 +76,15 @@ class _SortList extends StatelessWidget {
|
|||||||
return BlocBuilder<SortEditorBloc, SortEditorState>(
|
return BlocBuilder<SortEditorBloc, SortEditorState>(
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
final List<Widget> children = state.sortInfos
|
final List<Widget> children = state.sortInfos
|
||||||
.map((info) => Padding(
|
.map(
|
||||||
|
(info) => Padding(
|
||||||
padding: const EdgeInsets.symmetric(vertical: 6),
|
padding: const EdgeInsets.symmetric(vertical: 6),
|
||||||
child: _SortItem(
|
child: _SortItem(
|
||||||
sortInfo: info,
|
sortInfo: info,
|
||||||
popoverMutex: popoverMutex,
|
popoverMutex: popoverMutex,
|
||||||
),
|
),
|
||||||
))
|
),
|
||||||
|
)
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
return Column(
|
return Column(
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user