chore: Merge branch 'main' into release/0.0.9.1

This commit is contained in:
nathan 2023-01-13 09:58:25 +08:00
commit 1b295c0ab6
654 changed files with 8077 additions and 4021 deletions

View file

@ -15,6 +15,7 @@ on:
env:
CARGO_TERM_COLOR: always
FLUTTER_VERSION: "3.3.9"
jobs:
tests:
@ -30,7 +31,7 @@ jobs:
- uses: subosito/flutter-action@v2
with:
channel: "stable"
flutter-version: "3.0.5"
flutter-version: ${{ env.FLUTTER_VERSION }}
cache: true
- name: Run FlowyEditor tests

View file

@ -1,86 +0,0 @@
# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.
name: Flutter lint
on:
push:
branches:
- "main"
- "release/*"
paths:
- "frontend/app_flowy/**"
pull_request:
branches:
- "main"
- "release/*"
paths:
- "frontend/app_flowy/**"
env:
CARGO_TERM_COLOR: always
jobs:
flutter-analyze:
name: flutter analyze
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- uses: subosito/flutter-action@v1
with:
flutter-version: "3.0.5"
channel: "stable"
- uses: actions-rs/toolchain@v1
with:
toolchain: "stable-2022-04-07"
- name: Cache Cargo
id: cache-cargo
uses: actions/cache@v2
with:
path: |
~/.cargo
key: ${{ runner.os }}-cargo-${{ steps.rust_toolchain.outputs.rustc_hash }}-${{ hashFiles('./frontend/rust-lib/Cargo.toml') }}
- name: Cache Rust
id: cache-rust-target
uses: actions/cache@v2
with:
path: |
frontend/rust-lib/target
shared-lib/target
key: ${{ runner.os }}-rust-rust-lib-share-lib-${{ steps.rust_toolchain.outputs.rustc_hash }}-${{ hashFiles('./frontend/rust-lib/Cargo.toml') }}
- if: steps.cache-cargo.outputs.cache-hit != 'true'
name: Rust Deps
working-directory: frontend
run: |
cargo install cargo-make
- name: Cargo make flowy dev
working-directory: frontend
run: |
cargo make appflowy-deps-tools
- name: Flutter Deps
run: flutter packages pub get
working-directory: frontend/app_flowy
- name: Build FlowySDK
working-directory: frontend
run: |
cargo make --profile development-linux-x86_64 appflowy-sdk-dev
- name: Flutter Code Generation
working-directory: frontend/app_flowy
run: |
flutter packages pub run easy_localization:generate -f keys -o locale_keys.g.dart -S assets/translations -s en.json
flutter packages pub run build_runner build --delete-conflicting-outputs
- name: Run Flutter Analyzer
working-directory: frontend/app_flowy
run: flutter analyze

View file

@ -1,80 +0,0 @@
name: Frontend test
on:
push:
branches:
- "main"
- "release/*"
paths:
- "frontend/app_flowy/**"
pull_request:
branches:
- "main"
- "release/*"
paths:
- "frontend/app_flowy/**"
env:
CARGO_TERM_COLOR: always
jobs:
tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions-rs/toolchain@v1
with:
toolchain: "stable-2022-04-07"
- uses: subosito/flutter-action@v2
with:
channel: "stable"
flutter-version: "3.0.5"
cache: true
- name: Cache Cargo
uses: actions/cache@v2
with:
path: |
~/.cargo
key: ${{ runner.os }}-cargo-${{ steps.rust_toolchain.outputs.rustc_hash }}-${{ hashFiles('./frontend/rust-lib/Cargo.toml') }}
- name: Cache Rust
id: cache-rust-target
uses: actions/cache@v2
with:
path: |
frontend/rust-lib/target
shared-lib/target
key: ${{ runner.os }}-rust-rust-lib-share-lib-${{ steps.rust_toolchain.outputs.rustc_hash }}-${{ hashFiles('./frontend/rust-lib/Cargo.toml') }}
- if: steps.cache-cargo.outputs.cache-hit != 'true'
name: Rust Deps
working-directory: frontend
run: |
cargo install cargo-make
cargo make appflowy-deps-tools
- name: Flutter Deps
working-directory: frontend/app_flowy
run: |
flutter config --enable-linux-desktop
- name: Build Test lib
working-directory: frontend
run: |
cargo make --profile test-linux build-test-lib
- name: Flutter Code Generation
working-directory: frontend/app_flowy
run: |
flutter packages pub get
flutter packages pub run easy_localization:generate -f keys -o locale_keys.g.dart -S assets/translations -s en.json
flutter packages pub run build_runner build --delete-conflicting-outputs
- name: Run bloc tests
working-directory: frontend/app_flowy
run: |
flutter pub get
flutter test

View file

@ -1,89 +1,87 @@
name: CI
name: Flutter-CI
on:
push:
branches:
- "main"
- "release/*"
paths:
- "frontend/**"
pull_request:
branches:
- "main"
- "release/*"
paths:
- "frontend/**"
env:
FLUTTER_VERSION: "3.3.9"
RUST_TOOLCHAIN: "1.65"
jobs:
build:
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
include:
- os: ubuntu-latest
flutter_profile: development-linux-x86_64
target: x86_64-unknown-linux-gnu
- os: macos-latest
flutter_profile: development-mac-x86_64
target: x86_64-apple-darwin
- os: windows-latest
flutter_profile: development-windows-x86
target: x86_64-pc-windows-msvc
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v2
- name: Checkout source code
uses: actions/checkout@v2
- id: rust_toolchain
- name: Install Rust toolchain
id: rust_toolchain
uses: actions-rs/toolchain@v1
with:
toolchain: "stable-2022-04-07"
toolchain: ${{ env.RUST_TOOLCHAIN }}
target: ${{ matrix.target }}
override: true
profile: minimal
- id: flutter
- name: Install flutter
id: flutter
uses: subosito/flutter-action@v2
with:
channel: "stable"
flutter-version: ${{ env.FLUTTER_VERSION }}
cache: true
flutter-version: "3.0.5"
- name: Cache Cargo
id: cache-cargo
uses: actions/cache@v2
- uses: Swatinem/rust-cache@v2
with:
path: |
~/.cargo
key: ${{ runner.os }}-cargo-${{ steps.rust_toolchain.outputs.rustc_hash }}-${{ hashFiles('./frontend/rust-lib/Cargo.toml') }}
prefix-key: ${{ matrix.job.os }}
- name: Cache Rust
uses: actions/cache@v2
with:
path: |
frontend/rust-lib/target
shared-lib/target
key: ${{ runner.os }}-rust-rust-lib-share-lib-${{ steps.rust_toolchain.outputs.rustc_hash }}-${{ hashFiles('./frontend/rust-lib/Cargo.toml') }}
- name: Setup Environment
- name: Install prerequisites
working-directory: frontend
run: |
cargo install --force cargo-make
cargo install --force duckscript_cli
if [ "$RUNNER_OS" == "Linux" ]; then
sudo wget -qO /etc/apt/trusted.gpg.d/dart_linux_signing_key.asc https://dl-ssl.google.com/linux/linux_signing_key.pub
sudo wget -qO /etc/apt/sources.list.d/dart_stable.list https://storage.googleapis.com/download.dartlang.org/linux/debian/dart_stable.list
sudo apt-get update
sudo apt-get install -y dart curl build-essential libsqlite3-dev libssl-dev clang cmake ninja-build pkg-config libgtk-3-dev
sudo apt-get install -y dart curl build-essential libssl-dev clang cmake ninja-build pkg-config libgtk-3-dev
sudo apt-get install keybinder-3.0
elif [ "$RUNNER_OS" == "Windows" ]; then
vcpkg integrate install
elif [ "$RUNNER_OS" == "macOS" ]; then
echo 'do nothing'
fi
cargo make appflowy-deps-tools
shell: bash
- if: steps.cache-cargo.outputs.cache-hit != 'true'
name: Deps
working-directory: frontend
run: |
cargo install cargo-make
cargo install duckscript_cli
- name: Cargo make appflowy-deps-tools
working-directory: frontend
run: |
cargo make appflowy-deps-tools
- name: Config Flutter
- name: Enable Flutter Desktop
run: |
if [ "$RUNNER_OS" == "Linux" ]; then
flutter config --enable-linux-desktop
@ -94,7 +92,16 @@ jobs:
fi
shell: bash
- name: Build
- name: Build AppFlowy
working-directory: frontend
run: |
cargo make --profile ${{ matrix.flutter_profile }} appflowy-dev
- name: Flutter Analyzer
working-directory: frontend/app_flowy
run: flutter analyze
- name: Run Flutter unit tests
working-directory: frontend
run: |
cargo make dart_unit_test

View file

@ -35,7 +35,7 @@ jobs:
- uses: subosito/flutter-action@v2
with:
channel: "stable"
flutter-version: "3.0.5"
flutter-version: "3.3.9"
cache: true
- name: Cache Cargo

View file

@ -5,6 +5,10 @@ on:
tags:
- '*'
env:
FLUTTER_VERSION: "3.3.9"
RUST_TOOLCHAIN: "1.65"
jobs:
create-release:
runs-on: ubuntu-latest
@ -31,268 +35,48 @@ jobs:
release_name: v${{ github.ref }}
body_path: ${{ env.RELEASE_NOTES_PATH }}
build-linux-x86:
runs-on: ubuntu-latest
needs: create-release
env:
LINUX_APP_RELEASE_PATH: frontend/app_flowy/product/${{ github.ref_name }}/linux/Release
LINUX_ZIP_NAME: AppFlowy-linux-x86.tar.gz
LINUX_PACKAGE_NAME: AppFlowy_${{ github.ref_name }}_linux-amd64.deb
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Setup environment - Rust and Cargo
uses: actions-rs/toolchain@v1
with:
toolchain: 'stable-2022-04-07'
- name: Setup environment - Flutter
uses: subosito/flutter-action@v2
with:
channel: 'stable'
flutter-version: '3.0.5'
- name: Pre build
working-directory: frontend
run: |
sudo wget -qO /etc/apt/trusted.gpg.d/dart_linux_signing_key.asc https://dl-ssl.google.com/linux/linux_signing_key.pub
sudo apt-get update
sudo apt-get install -y build-essential libsqlite3-dev libssl-dev clang cmake ninja-build pkg-config libgtk-3-dev
sudo apt-get install keybinder-3.0
source $HOME/.cargo/env
cargo install --force cargo-make
cargo install --force duckscript_cli
cargo make appflowy-deps-tools
- name: Build Linux app
working-directory: frontend
run: |
flutter config --enable-linux-desktop
cargo make --env APP_VERSION=${{ github.ref_name }} --profile production-linux-x86_64 appflowy
- name: Configuring Linux Package
working-directory: frontend
run: |
mkdir -p ../${{ env.LINUX_APP_RELEASE_PATH }}/package/opt
mkdir -p ../${{ env.LINUX_APP_RELEASE_PATH }}/package/usr/share/applications
cp -r ./scripts/linux_installer ../${{ env.LINUX_APP_RELEASE_PATH }}/package/DEBIAN
cd ../${{ env.LINUX_APP_RELEASE_PATH }}/package/DEBIAN
grep -rl "\[CHANGE_THIS\]" ./control | xargs sed -i "s/\[CHANGE_THIS\]/${{ github.ref_name }}/"
chmod 0755 {postinst,postrm}
- name: Build Linux package
working-directory: ${{ env.LINUX_APP_RELEASE_PATH }}
run: |
mv AppFlowy package/opt/
cd package
# Update Exec & icon path in desktop entry
grep -rl "\[CHANGE_THIS\]" ./opt/AppFlowy/appflowy.desktop.temp | xargs sed -i "s/\[CHANGE_THIS\]/\/opt/"
# Add desktop entry in package
mv ./opt/AppFlowy/appflowy.desktop.temp ./usr/share/applications/appflowy.desktop
# Build
cd ../ && dpkg-deb --build --root-owner-group -Z xz package ${{ env.LINUX_PACKAGE_NAME }}
- name: Upload Release Asset
id: upload-release-asset
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ needs.create-release.outputs.upload_url }}
asset_path: ${{ env.LINUX_APP_RELEASE_PATH }}/${{ env.LINUX_ZIP_NAME }}
asset_name: ${{ env.LINUX_ZIP_NAME }}
asset_content_type: application/octet-stream
- name: Upload Release Asset Install Package
id: upload-release-asset-install-package
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ needs.create-release.outputs.upload_url }}
asset_path: ${{ env.LINUX_APP_RELEASE_PATH }}/${{ env.LINUX_PACKAGE_NAME }}
asset_name: ${{ env.LINUX_PACKAGE_NAME }}
asset_content_type: application/octet-stream
build-linux-x86-alt:
runs-on: ubuntu-18.04
needs: create-release
env:
LINUX_APP_RELEASE_PATH: frontend/app_flowy/product/${{ github.ref_name }}/linux/Release
LINUX_PACKAGE_NAME: AppFlowy_${{ github.ref_name }}_linux-amd64-alt.deb
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Setup environment - Rust and Cargo
uses: actions-rs/toolchain@v1
with:
toolchain: 'stable-2022-04-07'
- name: Setup environment - Flutter
uses: subosito/flutter-action@v2
with:
channel: 'stable'
flutter-version: '3.0.5'
- name: Pre build
working-directory: frontend
run: |
sudo wget -qO /etc/apt/trusted.gpg.d/dart_linux_signing_key.asc https://dl-ssl.google.com/linux/linux_signing_key.pub
sudo apt-get update
sudo apt-get install -y build-essential libsqlite3-dev libssl-dev clang cmake ninja-build pkg-config libgtk-3-dev
sudo apt-get install keybinder-3.0
source $HOME/.cargo/env
cargo install --force cargo-make
cargo install --force duckscript_cli
cargo make appflowy-deps-tools
- name: Build Linux app
working-directory: frontend
run: |
flutter config --enable-linux-desktop
cargo make --env APP_VERSION=${{ github.ref_name }} --profile production-linux-x86_64 appflowy
- name: Configuring Linux Package
working-directory: frontend
run: |
mkdir -p ../${{ env.LINUX_APP_RELEASE_PATH }}/package/opt
mkdir -p ../${{ env.LINUX_APP_RELEASE_PATH }}/package/usr/share/applications
cp -r ./scripts/linux_installer ../${{ env.LINUX_APP_RELEASE_PATH }}/package/DEBIAN
cd ../${{ env.LINUX_APP_RELEASE_PATH }}/package/DEBIAN
grep -rl "\[CHANGE_THIS\]" ./control | xargs sed -i "s/\[CHANGE_THIS\]/${{ github.ref_name }}/"
chmod 0755 {postinst,postrm}
- name: Build Linux package
working-directory: ${{ env.LINUX_APP_RELEASE_PATH }}
run: |
mv AppFlowy package/opt/
cd package
# Update Exec & icon path in desktop entry
grep -rl "\[CHANGE_THIS\]" ./opt/AppFlowy/appflowy.desktop.temp | xargs sed -i "s/\[CHANGE_THIS\]/\/opt/"
# Add desktop entry in package
mv ./opt/AppFlowy/appflowy.desktop.temp ./usr/share/applications/appflowy.desktop
# Build
cd ../ && dpkg-deb --build --root-owner-group -Z xz package ${{ env.LINUX_PACKAGE_NAME }}
- name: Upload Alternative Release Asset Install Package
id: upload-release-asset-install-package
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ needs.create-release.outputs.upload_url }}
asset_path: ${{ env.LINUX_APP_RELEASE_PATH }}/${{ env.LINUX_PACKAGE_NAME }}
asset_name: ${{ env.LINUX_PACKAGE_NAME }}
asset_content_type: application/octet-stream
build-macos-x86_64:
runs-on: macos-latest
needs: create-release
env:
MACOS_APP_RELEASE_PATH: frontend/app_flowy/product/${{ github.ref_name }}/macos/Release
MACOS_X86_ZIP_NAME: Appflowy-macos-x86_64.zip
MACOS_DMG_NAME: Appflowy-macos-x86_64-installer
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Setup environment - Rust and Cargo
uses: actions-rs/toolchain@v1
with:
toolchain: 'stable-2022-04-07'
- name: Setup environment - Flutter
uses: subosito/flutter-action@v2
with:
channel: 'stable'
flutter-version: '3.0.5'
- name: Pre build
working-directory: frontend
run: |
source $HOME/.cargo/env
cargo install --force cargo-make
cargo install --force duckscript_cli
cargo make appflowy-deps-tools
- name: Build macOS app for x86_64
working-directory: frontend
run: |
flutter config --enable-macos-desktop
cargo make --env APP_VERSION=${{ github.ref_name }} --profile production-mac-x86_64 appflowy
- name: Create MacOS dmg
run: |
brew install create-dmg
create-dmg \
--volname ${{ env.MACOS_DMG_NAME }} \
--hide-extension "AppFlowy.app" \
--background frontend/scripts/dmg_assets/AppFlowyInstallerBackground.jpg \
--window-size 600 450 \
--icon-size 94 \
--icon "AppFlowy.app" 141 249 \
--app-drop-link 458 249 \
"${{ env.MACOS_APP_RELEASE_PATH }}/${{ env.MACOS_DMG_NAME }}.dmg" \
"${{ env.MACOS_APP_RELEASE_PATH }}/AppFlowy.app"
- name: Archive macOS app
working-directory: ${{ env.MACOS_APP_RELEASE_PATH }}
run: zip --symlinks -qr ${{ env.MACOS_X86_ZIP_NAME }} AppFlowy.app
- name: Upload Release Asset
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ needs.create-release.outputs.upload_url }}
asset_path: ${{ env.MACOS_APP_RELEASE_PATH }}/${{ env.MACOS_X86_ZIP_NAME }}
asset_name: ${{ env.MACOS_X86_ZIP_NAME }}
asset_content_type: application/octet-stream
- name: Upload DMG Release Asset
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ needs.create-release.outputs.upload_url }}
asset_path: ${{ env.MACOS_APP_RELEASE_PATH }}/${{ env.MACOS_DMG_NAME }}.dmg
asset_name: ${{ env.MACOS_DMG_NAME }}.dmg
asset_content_type: application/octet-stream
build-windows-x86_64:
runs-on: windows-latest
build-for-windows:
name: ${{ matrix.job.target }} (${{ matrix.job.os }})
needs: create-release
env:
WINDOWS_APP_RELEASE_PATH: frontend\app_flowy\product\${{ github.ref_name }}\windows
WINDOWS_ZIP_NAME: AppFlowy-windows-x86_64.zip
WINDOWS_INSTALLER_NAME: AppFlowy-${{ github.ref_name }}-windows-x86_64
WINDOWS_ZIP_NAME: AppFlowy_${{ github.ref_name }}_windows-x86_64.zip
WINDOWS_INSTALLER_NAME: AppFlowy_${{ github.ref_name }}_windows-x86_64
runs-on: ${{ matrix.job.os }}
strategy:
fail-fast: false
matrix:
job:
- { target: x86_64-pc-windows-msvc, os: windows-2019 }
steps:
- name: Checkout
- name: Checkout source code
uses: actions/checkout@v3
- name: Setup environment - Rust and Cargo
uses: actions-rs/toolchain@v1
with:
toolchain: 'stable-2022-04-07'
- name: Setup environment - Flutter
- name: Install flutter
uses: subosito/flutter-action@v2
with:
channel: 'stable'
flutter-version: '3.0.5'
channel: "stable"
flutter-version: ${{ env.FLUTTER_VERSION }}
cache: true
- name: Pre build
- name: Install Rust toolchain
uses: actions-rs/toolchain@v1
with:
toolchain: ${{ env.RUST_TOOLCHAIN }}
target: ${{ matrix.job.target }}
override: true
components: rustfmt
profile: minimal
- uses: Swatinem/rust-cache@v2
with:
prefix-key: ${{ matrix.job.os }}
- name: Install prerequisites
working-directory: frontend
run: |
vcpkg integrate install
cargo install --force cargo-make
cargo install --force duckscript_cli
cargo make appflowy-deps-tools
- name: Build Windows app
working-directory: frontend
@ -300,11 +84,12 @@ jobs:
flutter config --enable-windows-desktop
cargo make --env APP_VERSION=${{ github.ref_name }} --profile production-windows-x86 appflowy
- uses: vimtor/action-zip@v1
- name: Archive Asset
uses: vimtor/action-zip@v1
with:
files: ${{ env.WINDOWS_APP_RELEASE_PATH }}\
dest: ${{ env.WINDOWS_APP_RELEASE_PATH }}\${{ env.WINDOWS_ZIP_NAME }}
- name: Copy installer config & icon file
working-directory: frontend
run: |
@ -315,7 +100,7 @@ jobs:
run: |
iscc /F${{ env.WINDOWS_INSTALLER_NAME }} inno_setup_config.iss /DAppVersion=${{ github.ref_name }}
- name: Upload Release Asset
- name: Upload Asset
id: upload-release-asset
uses: actions/upload-release-asset@v1
env:
@ -336,3 +121,221 @@ jobs:
asset_path: ${{ env.WINDOWS_APP_RELEASE_PATH }}\Output\${{ env.WINDOWS_INSTALLER_NAME }}.exe
asset_name: ${{ env.WINDOWS_INSTALLER_NAME }}.exe
asset_content_type: application/octet-stream
build-for-macOS:
name: ${{ matrix.job.target }} (${{ matrix.job.os }}) [${{ matrix.job.extra-build-args }}]
runs-on: ${{ matrix.job.os }}
needs: create-release
env:
MACOS_APP_RELEASE_PATH: frontend/app_flowy/product/${{ github.ref_name }}/macos/Release
MACOS_X86_ZIP_NAME: AppFlowy_${{ github.ref_name }}_macos-x86_64.zip
MACOS_DMG_NAME: AppFlowy_${{ github.ref_name }}_macos-x86_64
strategy:
fail-fast: false
matrix:
job:
- { target: x86_64-apple-darwin, os: macos-10.15, extra-build-args: "" }
steps:
- name: Checkout source code
uses: actions/checkout@v3
- name: Install flutter
uses: subosito/flutter-action@v2
with:
channel: "stable"
flutter-version: ${{ env.FLUTTER_VERSION }}
cache: true
- name: Install Rust toolchain
uses: actions-rs/toolchain@v1
with:
toolchain: ${{ env.RUST_TOOLCHAIN }}
target: ${{ matrix.job.target }}
override: true
components: rustfmt
profile: minimal
- uses: Swatinem/rust-cache@v2
with:
prefix-key: ${{ matrix.job.os }}
- name: Install prerequisites
working-directory: frontend
run: |
cargo install --force cargo-make
cargo install --force duckscript_cli
- name: Build AppFlowy
working-directory: frontend
run: |
flutter config --enable-macos-desktop
cargo make --env APP_VERSION=${{ github.ref_name }} --profile production-mac-x86_64 appflowy
- name: Create macOS dmg
run: |
brew install create-dmg
create-dmg \
--volname ${{ env.MACOS_DMG_NAME }} \
--hide-extension "AppFlowy.app" \
--background frontend/scripts/dmg_assets/AppFlowyInstallerBackground.jpg \
--window-size 600 450 \
--icon-size 94 \
--icon "AppFlowy.app" 141 249 \
--app-drop-link 458 249 \
"${{ env.MACOS_APP_RELEASE_PATH }}/${{ env.MACOS_DMG_NAME }}.dmg" \
"${{ env.MACOS_APP_RELEASE_PATH }}/AppFlowy.app"
- name: Archive Asset
working-directory: ${{ env.MACOS_APP_RELEASE_PATH }}
run: zip --symlinks -qr ${{ env.MACOS_X86_ZIP_NAME }} AppFlowy.app
- name: Upload Asset
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ needs.create-release.outputs.upload_url }}
asset_path: ${{ env.MACOS_APP_RELEASE_PATH }}/${{ env.MACOS_X86_ZIP_NAME }}
asset_name: ${{ env.MACOS_X86_ZIP_NAME }}
asset_content_type: application/octet-stream
- name: Upload DMG Asset
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ needs.create-release.outputs.upload_url }}
asset_path: ${{ env.MACOS_APP_RELEASE_PATH }}/${{ env.MACOS_DMG_NAME }}.dmg
asset_name: ${{ env.MACOS_DMG_NAME }}.dmg
asset_content_type: application/octet-stream
build-for-linux:
name: ${{ matrix.job.target }} (${{ matrix.job.os }}) [${{ matrix.job.extra-build-args }}]
runs-on: ${{ matrix.job.os }}
needs: create-release
env:
LINUX_APP_RELEASE_PATH: frontend/app_flowy/product/${{ github.ref_name }}/linux/Release
LINUX_ZIP_NAME: AppFlowy_${{ matrix.job.target }}_${{ matrix.job.os }}.tar.gz
LINUX_PACKAGE_NAME: AppFlowy_${{ github.ref_name }}_${{ matrix.job.os }}.deb
strategy:
fail-fast: false
matrix:
job:
- { arch: x86_64, target: x86_64-unknown-linux-gnu, os: ubuntu-20.04, extra-build-args: "", }
- { arch: x86_64, target: x86_64-unknown-linux-gnu, os: ubuntu-18.04, extra-build-args: "", }
steps:
- name: Checkout source code
uses: actions/checkout@v3
- name: Install flutter
uses: subosito/flutter-action@v2
with:
channel: "stable"
flutter-version: ${{ env.FLUTTER_VERSION }}
cache: true
- name: Install Rust toolchain
uses: actions-rs/toolchain@v1
with:
toolchain: ${{ env.RUST_TOOLCHAIN }}
target: ${{ matrix.job.target }}
override: true
components: rustfmt
profile: minimal
- uses: Swatinem/rust-cache@v2
with:
prefix-key: ${{ matrix.job.os }}
- name: Install prerequisites
working-directory: frontend
run: |
sudo wget -qO /etc/apt/trusted.gpg.d/dart_linux_signing_key.asc https://dl-ssl.google.com/linux/linux_signing_key.pub
sudo apt-get update
sudo apt-get install -y build-essential libsqlite3-dev libssl-dev clang cmake ninja-build pkg-config libgtk-3-dev
sudo apt-get install keybinder-3.0
source $HOME/.cargo/env
cargo install --force cargo-make
cargo install --force duckscript_cli
- name: Build AppFlowy
working-directory: frontend
run: |
flutter config --enable-linux-desktop
cargo make --env APP_VERSION=${{ github.ref_name }} --profile production-linux-x86_64 appflowy
- name: Archive Assert
working-directory: ${{ env.LINUX_APP_RELEASE_PATH }}
run: tar -czf ${{ env.LINUX_ZIP_NAME }} *
- name: Configuring Linux Package
working-directory: frontend
run: |
mkdir -p ../${{ env.LINUX_APP_RELEASE_PATH }}/package/opt
mkdir -p ../${{ env.LINUX_APP_RELEASE_PATH }}/package/usr/share/applications
cp -r ./scripts/linux_installer ../${{ env.LINUX_APP_RELEASE_PATH }}/package/DEBIAN
cd ../${{ env.LINUX_APP_RELEASE_PATH }}/package/DEBIAN
grep -rl "\[CHANGE_THIS\]" ./control | xargs sed -i "s/\[CHANGE_THIS\]/${{ github.ref_name }}/"
chmod 0755 {postinst,postrm}
- name: Build Linux package
working-directory: ${{ env.LINUX_APP_RELEASE_PATH }}
run: |
mv AppFlowy package/opt/
cd package
# Update Exec & icon path in desktop entry
grep -rl "\[CHANGE_THIS\]" ./opt/AppFlowy/appflowy.desktop.temp | xargs sed -i "s/\[CHANGE_THIS\]/\/opt/"
# Add desktop entry in package
mv ./opt/AppFlowy/appflowy.desktop.temp ./usr/share/applications/appflowy.desktop
# Build
cd ../ && dpkg-deb --build --root-owner-group -Z xz package ${{ env.LINUX_PACKAGE_NAME }}
- name: Upload Asset
id: upload-release-asset
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ needs.create-release.outputs.upload_url }}
asset_path: ${{ env.LINUX_APP_RELEASE_PATH }}/${{ env.LINUX_ZIP_NAME }}
asset_name: ${{ env.LINUX_ZIP_NAME }}
asset_content_type: application/octet-stream
- name: Upload Asset Install Package
id: upload-release-asset-install-package
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ needs.create-release.outputs.upload_url }}
asset_path: ${{ env.LINUX_APP_RELEASE_PATH }}/${{ env.LINUX_PACKAGE_NAME }}
asset_name: ${{ env.LINUX_PACKAGE_NAME }}
asset_content_type: application/octet-stream
build-for-docker:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Login to Docker Hub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKER_HUB_USERNAME }}
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: Build and push
uses: docker/build-push-action@v2
with:
context: .
file: ./frontend/scripts/docker-buildfiles/Dockerfile
builder: ${{ steps.buildx.outputs.name }}
push: true
tags: ${{ secrets.DOCKER_HUB_USERNAME }}/appflowy_client:${{ github.ref_name }}
cache-from: type=registry,ref=${{ secrets.DOCKER_HUB_USERNAME }}/af_build_cache:buildcache
cache-to: type=registry,ref=${{ secrets.DOCKER_HUB_USERNAME }}/af_build_cache:buildcache,mode=max

View file

@ -1,35 +0,0 @@
name: release_docker
on:
push:
branches:
- 'main'
tags:
- '*'
jobs:
build-docker-image:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Login to Docker Hub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKER_HUB_USERNAME }}
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: Build and push
uses: docker/build-push-action@v2
with:
context: .
file: ./frontend/scripts/docker-buildfiles/Dockerfile
builder: ${{ steps.buildx.outputs.name }}
push: true
tags: ${{ secrets.DOCKER_HUB_USERNAME }}/appflowy_client:${{ github.ref_name }}
cache-from: type=registry,ref=${{ secrets.DOCKER_HUB_USERNAME }}/af_build_cache:buildcache
cache-to: type=registry,ref=${{ secrets.DOCKER_HUB_USERNAME }}/af_build_cache:buildcache,mode=max

86
.github/workflows/rust_ci.yaml vendored Normal file
View file

@ -0,0 +1,86 @@
name: Rust-CI
on:
push:
branches:
- "main"
- "release/*"
paths:
- "frontend/rust-lib/**"
- "shared-lib/**"
pull_request:
branches:
- "main"
- "release/*"
paths:
- "frontend/rust-lib/**"
- "shared-lib/**"
env:
CARGO_TERM_COLOR: always
RUST_TOOLCHAIN: "1.65"
FLUTTER_VERSION: "3.3.9"
jobs:
test-on-ubuntu:
runs-on: ubuntu-latest
steps:
- name: Checkout source code
uses: actions/checkout@v2
- name: Install Rust toolchain
id: rust_toolchain
uses: actions-rs/toolchain@v1
with:
toolchain: ${{ env.RUST_TOOLCHAIN }}
override: true
components: rustfmt, clippy
profile: minimal
- name: Install flutter
id: flutter
uses: subosito/flutter-action@v2
with:
channel: "stable"
flutter-version: ${{ env.FLUTTER_VERSION }}
cache: true
- name: Install prerequisites
working-directory: frontend
run: |
cargo install --force cargo-make
cargo install --force duckscript_cli
- uses: Swatinem/rust-cache@v2
with:
prefix-key: ${{ matrix.job.os }}
- name: Build FlowySDK
working-directory: frontend
run: |
cargo make --profile development-linux-x86_64 appflowy-sdk-dev
- name: rustfmt rust-lib
run: cargo fmt --all -- --check
working-directory: frontend/rust-lib/
- name: clippy rust-lib
run: cargo clippy --features="rev-sqlite"
working-directory: frontend/rust-lib
- name: Run rust-lib tests
working-directory: frontend/rust-lib
run: RUST_LOG=info cargo test --no-default-features --features="sync,rev-sqlite"
- name: rustfmt shared-lib
run: cargo fmt --all -- --check
working-directory: shared-lib
- name: clippy shared-lib
run: cargo clippy -- -D warnings
working-directory: shared-lib
- name: Run shared-lib tests
working-directory: shared-lib
run: RUST_LOG=info cargo test --no-default-features

View file

@ -11,52 +11,48 @@ on:
env:
CARGO_TERM_COLOR: always
FLUTTER_VERSION: "3.3.9"
RUST_TOOLCHAIN: "1.65"
jobs:
tests:
runs-on: ubuntu-latest
steps:
- name: Checkout
- name: Checkout source code
uses: actions/checkout@v2
- id: rust_toolchain
- name: Install Rust toolchain
id: rust_toolchain
uses: actions-rs/toolchain@v1
with:
toolchain: 'stable-2022-04-07'
toolchain: ${{ env.RUST_TOOLCHAIN }}
target: ${{ matrix.job.target }}
override: true
profile: minimal
- name: Cache Cargo
uses: actions/cache@v2
with:
path: |
~/.cargo
key: ${{ runner.os }}-cargo-${{ steps.rust_toolchain.outputs.rustc_hash }}-${{ hashFiles('./frontend/rust-lib/Cargo.toml') }}
- name: Cache Rust
uses: actions/cache@v2
with:
path: |
frontend/rust-lib/target
shared-lib/target
key: ${{ runner.os }}-rust-rust-lib-share-lib-${{ steps.rust_toolchain.outputs.rustc_hash }}-${{ hashFiles('./frontend/rust-lib/Cargo.toml') }}
- name: Install cargo-make
working-directory: frontend
run: |
cargo install cargo-make
- name: Setup environment - Flutter
- name: Install flutter
id: flutter
uses: subosito/flutter-action@v2
with:
channel: 'stable'
flutter-version: '3.0.5'
channel: "stable"
flutter-version: ${{ env.FLUTTER_VERSION }}
cache: true
- name: Install prerequisites
working-directory: frontend
run: |
cargo install --force cargo-make
cargo install --force duckscript_cli
- uses: Swatinem/rust-cache@v2
with:
prefix-key: ${{ matrix.job.os }}
- name: Install code-coverage tools
working-directory: frontend
run: |
sudo wget -qO /etc/apt/trusted.gpg.d/dart_linux_signing_key.asc https://dl-ssl.google.com/linux/linux_signing_key.pub
sudo apt-get update
sudo apt-get install -y build-essential libsqlite3-dev libssl-dev clang cmake ninja-build pkg-config libgtk-3-dev
sudo apt-get install keybinder-3.0
cargo install grcov
rustup component add llvm-tools-preview

View file

@ -1,61 +0,0 @@
name: Rust lint
on:
push:
branches:
- "main"
- "release/*"
paths:
- "frontend/rust-lib/**"
- "shared-lib/**"
pull_request:
branches:
- "main"
- "release/*"
paths:
- "frontend/rust-lib/**"
- "shared-lib/**"
env:
CARGO_TERM_COLOR: always
jobs:
rust-fmt:
name: Rustfmt
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions-rs/toolchain@v1
with:
toolchain: 'stable-2022-04-07'
override: true
- uses: subosito/flutter-action@v1
with:
flutter-version: '3.0.5'
channel: "stable"
- name: Rust Deps
working-directory: frontend
run: |
cargo install cargo-make
cargo make appflowy-deps-tools
- name: Build FlowySDK
working-directory: frontend
run: |
cargo make --profile development-linux-x86_64 appflowy-sdk-dev
- run: rustup component add rustfmt
working-directory: frontend/rust-lib
- name: rustfmt
run: cargo fmt --all -- --check
working-directory: frontend/rust-lib/
- run: rustup component add clippy
working-directory: frontend/rust-lib
- name: clippy
run: cargo clippy --no-default-features
working-directory: frontend/rust-lib

View file

@ -1,60 +0,0 @@
name: Backend test
on:
push:
branches:
- "main"
- "release/*"
paths:
- "frontend/rust-lib/**"
- "shared-lib/**"
pull_request:
branches:
- "main"
- "release/*"
paths:
- "frontend/rust-lib/**"
- "shared-lib/**"
env:
CARGO_TERM_COLOR: always
jobs:
tests:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- id: rust_toolchain
uses: actions-rs/toolchain@v1
with:
toolchain: 'stable-2022-04-07'
- name: Cache Cargo
uses: actions/cache@v2
with:
path: |
~/.cargo
key: ${{ runner.os }}-cargo-${{ steps.rust_toolchain.outputs.rustc_hash }}-${{ hashFiles('./frontend/rust-lib/Cargo.toml') }}
- name: Cache Rust
uses: actions/cache@v2
with:
path: |
frontend/rust-lib/target
shared-lib/target
key: ${{ runner.os }}-rust-rust-lib-share-lib-${{ steps.rust_toolchain.outputs.rustc_hash }}-${{ hashFiles('./frontend/rust-lib/Cargo.toml') }}
- name: Install cargo-make
working-directory: frontend
run: cargo install cargo-make
- name: Run rust-lib tests
working-directory: frontend/rust-lib
run: RUST_LOG=info cargo test --no-default-features --features="sync"
- name: Run shared-lib tests
working-directory: shared-lib
run: RUST_LOG=info cargo test --no-default-features

View file

@ -1,13 +1,13 @@
#https://github.com/sagiegurari/cargo-make
extend = [
{ path = "scripts/makefile/desktop.toml" },
{ path = "scripts/makefile/protobuf.toml" },
{ path = "scripts/makefile/tests.toml" },
{ path = "scripts/makefile/docker.toml" },
{ path = "scripts/makefile/env.toml" },
{ path = "scripts/makefile/flutter.toml" },
{ path = "scripts/makefile/tool.toml" },
{ path = "scripts/makefile/desktop.toml" },
{ path = "scripts/makefile/protobuf.toml" },
{ path = "scripts/makefile/tests.toml" },
{ path = "scripts/makefile/docker.toml" },
{ path = "scripts/makefile/env.toml" },
{ path = "scripts/makefile/flutter.toml" },
{ path = "scripts/makefile/tool.toml" },
]
[config]
@ -23,11 +23,11 @@ CARGO_MAKE_CRATE_FS_NAME = "dart_ffi"
CARGO_MAKE_CRATE_NAME = "dart-ffi"
LIB_NAME = "dart_ffi"
CURRENT_APP_VERSION = "0.0.9.1"
FEATURES = "flutter"
FLUTTER_DESKTOP_FEATURES = "flutter,rev-sqlite"
PRODUCT_NAME = "AppFlowy"
# CRATE_TYPE: https://doc.rust-lang.org/reference/linkage.html
# If you update the macOS's CRATE_TYPE, don't forget to update the
# flowy_sdk.podspec
# appflowy_backend.podspec
# for staticlib:
# s.static_framework = true
# s.vendored_libraries = "libdart_ffi.a"
@ -42,7 +42,7 @@ PRODUCT_NAME = "AppFlowy"
CRATE_TYPE = "staticlib"
LIB_EXT = "a"
APP_ENVIRONMENT = "local"
FLUTTER_FLOWY_SDK_PATH = "app_flowy/packages/flowy_sdk"
FLUTTER_FLOWY_SDK_PATH = "app_flowy/packages/appflowy_backend"
# Test default config
TEST_CRATE_TYPE = "cdylib"
TEST_LIB_EXT = "dylib"
@ -150,7 +150,7 @@ script = ['''
echo BUILD_FLAG: ${BUILD_FLAG}
echo TARGET_OS: ${TARGET_OS}
echo RUST_COMPILE_TARGET: ${RUST_COMPILE_TARGET}
echo FEATURES: ${FEATURES}
echo FEATURES: ${FLUTTER_DESKTOP_FEATURES}
echo PRODUCT_EXT: ${PRODUCT_EXT}
echo APP_ENVIRONMENT: ${APP_ENVIRONMENT}
echo ${platforms}
@ -181,7 +181,7 @@ FEATURES = "flutter,openssl_vendored"
[tasks.setup-crate-type]
private = true
script = [
"""
"""
toml = readfile ${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/rust-lib/${CARGO_MAKE_CRATE_NAME}/Cargo.toml
val = replace ${toml} "staticlib" ${CRATE_TYPE}
result = writefile ${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/rust-lib/${CARGO_MAKE_CRATE_NAME}/Cargo.toml ${val}
@ -193,7 +193,7 @@ script_runner = "@duckscript"
[tasks.restore-crate-type]
private = true
script = [
"""
"""
toml = readfile ${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/rust-lib/${CARGO_MAKE_CRATE_NAME}/Cargo.toml
val = replace ${toml} ${CRATE_TYPE} "staticlib"
result = writefile ${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/rust-lib/${CARGO_MAKE_CRATE_NAME}/Cargo.toml ${val}
@ -221,7 +221,7 @@ TEST_COMPILE_TARGET = "x86_64-pc-windows-msvc"
[tasks.setup-test-crate-type]
private = true
script = [
"""
"""
toml = readfile ${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/rust-lib/${CARGO_MAKE_CRATE_NAME}/Cargo.toml
val = replace ${toml} "staticlib" ${TEST_CRATE_TYPE}
result = writefile ${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/rust-lib/${CARGO_MAKE_CRATE_NAME}/Cargo.toml ${val}
@ -233,7 +233,7 @@ script_runner = "@duckscript"
[tasks.restore-test-crate-type]
private = true
script = [
"""
"""
toml = readfile ${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/rust-lib/${CARGO_MAKE_CRATE_NAME}/Cargo.toml
val = replace ${toml} ${TEST_CRATE_TYPE} "staticlib"
result = writefile ${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/rust-lib/${CARGO_MAKE_CRATE_NAME}/Cargo.toml ${val}
@ -249,5 +249,3 @@ script = ["""
cargo build -vv --features=dart
"""]
script_runner = "@shell"

View file

@ -193,6 +193,7 @@
"grid": {
"settings": {
"filter": "Filter",
"sort": "Sort",
"sortBy": "Sort by",
"Properties": "Properties",
"group": "Group",
@ -273,6 +274,12 @@
"newColumn": "New column",
"deleteFieldPromptMessage": "Are you sure? This property will be deleted"
},
"sort": {
"ascending": "Ascending",
"descending": "Descending",
"deleteSort": "Delete sort",
"addSort": "Add sort"
},
"row": {
"duplicate": "Duplicate",
"delete": "Delete",
@ -313,5 +320,8 @@
"column": {
"create_new_card": "New"
}
},
"calendar": {
"menuName": "Calendar"
}
}

View file

@ -3,7 +3,7 @@ PODS:
- Flutter
- flowy_infra_ui (0.0.1):
- Flutter
- flowy_sdk (0.0.1):
- appflowy_backend (0.0.1):
- Flutter
- Flutter (1.0.0)
- flutter_inappwebview (0.0.1):
@ -28,7 +28,7 @@ PODS:
DEPENDENCIES:
- flowy_editor (from `.symlinks/plugins/flowy_editor/ios`)
- flowy_infra_ui (from `.symlinks/plugins/flowy_infra_ui/ios`)
- flowy_sdk (from `.symlinks/plugins/flowy_sdk/ios`)
- appflowy_backend (from `.symlinks/plugins/appflowy_backend/ios`)
- Flutter (from `Flutter`)
- flutter_inappwebview (from `.symlinks/plugins/flutter_inappwebview/ios`)
- flutter_keyboard_visibility (from `.symlinks/plugins/flutter_keyboard_visibility/ios`)
@ -46,8 +46,8 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/flowy_editor/ios"
flowy_infra_ui:
:path: ".symlinks/plugins/flowy_infra_ui/ios"
flowy_sdk:
:path: ".symlinks/plugins/flowy_sdk/ios"
appflowy_backend:
:path: ".symlinks/plugins/appflowy_backend/ios"
Flutter:
:path: Flutter
flutter_inappwebview:
@ -66,7 +66,7 @@ EXTERNAL SOURCES:
SPEC CHECKSUMS:
flowy_editor: bf8d58894ddb03453bd4d8521c57267ad638b837
flowy_infra_ui: 146c88346fd55d2ee6a41ae35059a5bf095cfbb3
flowy_sdk: c416222c639e678828776789bf0c1a1d0d59df3c
appflowy_backend: c416222c639e678828776789bf0c1a1d0d59df3c
Flutter: 50d75fe2f02b26cc09d224853bb45737f8b3214a
flutter_inappwebview: bfd58618f49dc62f2676de690fc6dcda1d6c3721
flutter_keyboard_visibility: 0339d06371254c3eb25eeb90ba8d17dca8f9c069

View file

@ -1,18 +1,21 @@
import 'dart:async';
import 'dart:typed_data';
import 'package:flowy_sdk/protobuf/dart-notify/protobuf.dart';
import 'package:appflowy_backend/protobuf/dart-notify/protobuf.dart';
import 'package:dartz/dartz.dart';
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-folder/dart_notification.pb.dart';
import 'package:flowy_sdk/rust_stream.dart';
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-folder/dart_notification.pb.dart';
import 'package:appflowy_backend/rust_stream.dart';
import 'notification_helper.dart';
// Folder
typedef FolderNotificationCallback = void Function(FolderNotification, Either<Uint8List, FlowyError>);
typedef FolderNotificationCallback = void Function(
FolderNotification, Either<Uint8List, FlowyError>);
class FolderNotificationParser extends NotificationParser<FolderNotification, FlowyError> {
FolderNotificationParser({String? id, required FolderNotificationCallback callback})
class FolderNotificationParser
extends NotificationParser<FolderNotification, FlowyError> {
FolderNotificationParser(
{String? id, required FolderNotificationCallback callback})
: super(
id: id,
callback: callback,
@ -21,15 +24,18 @@ class FolderNotificationParser extends NotificationParser<FolderNotification, Fl
);
}
typedef FolderNotificationHandler = Function(FolderNotification ty, Either<Uint8List, FlowyError> result);
typedef FolderNotificationHandler = Function(
FolderNotification ty, Either<Uint8List, FlowyError> result);
class FolderNotificationListener {
StreamSubscription<SubscribeObject>? _subscription;
FolderNotificationParser? _parser;
FolderNotificationListener({required String objectId, required FolderNotificationHandler handler})
FolderNotificationListener(
{required String objectId, required FolderNotificationHandler handler})
: _parser = FolderNotificationParser(id: objectId, callback: handler) {
_subscription = RustStreamReceiver.listen((observable) => _parser?.parse(observable));
_subscription =
RustStreamReceiver.listen((observable) => _parser?.parse(observable));
}
Future<void> stop() async {

View file

@ -1,10 +1,10 @@
import 'dart:async';
import 'dart:typed_data';
import 'package:flowy_sdk/protobuf/dart-notify/protobuf.dart';
import 'package:appflowy_backend/protobuf/dart-notify/protobuf.dart';
import 'package:dartz/dartz.dart';
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/dart_notification.pb.dart';
import 'package:flowy_sdk/rust_stream.dart';
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/dart_notification.pb.dart';
import 'package:appflowy_backend/rust_stream.dart';
import 'notification_helper.dart';

View file

@ -1,9 +1,9 @@
import 'dart:async';
import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:flowy_sdk/log.dart';
import 'package:flowy_sdk/dispatch/dispatch.dart';
import 'package:flowy_sdk/protobuf/flowy-net/network_state.pb.dart';
import 'package:appflowy_backend/log.dart';
import 'package:appflowy_backend/dispatch/dispatch.dart';
import 'package:appflowy_backend/protobuf/flowy-net/network_state.pb.dart';
import 'package:flutter/services.dart';
class NetworkListener {

View file

@ -1,5 +1,5 @@
import 'dart:typed_data';
import 'package:flowy_sdk/protobuf/dart-notify/protobuf.dart';
import 'package:appflowy_backend/protobuf/dart-notify/protobuf.dart';
import 'package:dartz/dartz.dart';
class NotificationParser<T, E> {
@ -9,7 +9,11 @@ class NotificationParser<T, E> {
T? Function(int) tyParser;
E Function(Uint8List) errorParser;
NotificationParser({this.id, required this.callback, required this.errorParser, required this.tyParser});
NotificationParser(
{this.id,
required this.callback,
required this.errorParser,
required this.tyParser});
void parse(SubscribeObject subject) {
if (id != null) {
if (subject.id != id) {

View file

@ -1,18 +1,21 @@
import 'dart:async';
import 'dart:typed_data';
import 'package:flowy_sdk/protobuf/dart-notify/protobuf.dart';
import 'package:flowy_sdk/protobuf/flowy-user/protobuf.dart';
import 'package:appflowy_backend/protobuf/dart-notify/protobuf.dart';
import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart';
import 'package:dartz/dartz.dart';
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
import 'package:flowy_sdk/rust_stream.dart';
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
import 'package:appflowy_backend/rust_stream.dart';
import 'notification_helper.dart';
// User
typedef UserNotificationCallback = void Function(UserNotification, Either<Uint8List, FlowyError>);
typedef UserNotificationCallback = void Function(
UserNotification, Either<Uint8List, FlowyError>);
class UserNotificationParser extends NotificationParser<UserNotification, FlowyError> {
UserNotificationParser({required String id, required UserNotificationCallback callback})
class UserNotificationParser
extends NotificationParser<UserNotification, FlowyError> {
UserNotificationParser(
{required String id, required UserNotificationCallback callback})
: super(
id: id,
callback: callback,
@ -21,15 +24,18 @@ class UserNotificationParser extends NotificationParser<UserNotification, FlowyE
);
}
typedef UserNotificationHandler = Function(UserNotification ty, Either<Uint8List, FlowyError> result);
typedef UserNotificationHandler = Function(
UserNotification ty, Either<Uint8List, FlowyError> result);
class UserNotificationListener {
StreamSubscription<SubscribeObject>? _subscription;
UserNotificationParser? _parser;
UserNotificationListener({required String objectId, required UserNotificationHandler handler})
UserNotificationListener(
{required String objectId, required UserNotificationHandler handler})
: _parser = UserNotificationParser(id: objectId, callback: handler) {
_subscription = RustStreamReceiver.listen((observable) => _parser?.parse(observable));
_subscription =
RustStreamReceiver.listen((observable) => _parser?.parse(observable));
}
Future<void> stop() async {

View file

@ -7,10 +7,10 @@ import 'package:app_flowy/plugins/grid/application/row/row_service.dart';
import 'package:appflowy_board/appflowy_board.dart';
import 'package:dartz/dartz.dart';
import 'package:equatable/equatable.dart';
import 'package:flowy_sdk/log.dart';
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/protobuf.dart';
import 'package:appflowy_backend/log.dart';
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/protobuf.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';

View file

@ -4,11 +4,11 @@ import 'package:app_flowy/plugins/grid/application/view/grid_view_cache.dart';
import 'package:app_flowy/plugins/grid/application/field/field_controller.dart';
import 'package:app_flowy/plugins/grid/application/grid_service.dart';
import 'package:app_flowy/plugins/grid/application/row/row_cache.dart';
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
import 'dart:async';
import 'package:dartz/dartz.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/protobuf.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/protobuf.dart';
import 'board_listener.dart';
@ -108,19 +108,19 @@ class BoardDataController {
Future<Either<Unit, FlowyError>> openGrid() async {
final result = await _gridFFIService.openGrid();
return result.fold(
(grid) async {
_onGridChanged?.call(grid);
final result = await fieldController.loadFields(fieldIds: grid.fields);
return result.fold(
(l) {
_loadGroups();
_viewCache.rowCache.initializeRows(grid.rows);
return left(l);
},
(err) => right(err),
);
return fieldController.loadFields(fieldIds: grid.fields).then((result) {
return result.fold(
(l) => Future(() async {
await _loadGroups();
_viewCache.rowCache.initializeRows(grid.rows);
return left(l);
}),
(err) => right(err),
);
});
},
(err) => right(err),
);
@ -132,6 +132,7 @@ class BoardDataController {
}
Future<void> dispose() async {
await _viewCache.dispose();
await _gridFFIService.closeGrid();
await fieldController.dispose();
}

View file

@ -2,11 +2,11 @@ import 'dart:typed_data';
import 'package:app_flowy/core/grid_notification.dart';
import 'package:flowy_infra/notifier.dart';
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/dart_notification.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/dart_notification.pb.dart';
import 'package:dartz/dartz.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/group.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/group_changeset.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/group.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/group_changeset.pb.dart';
typedef GroupUpdateValue = Either<GroupViewChangesetPB, FlowyError>;
typedef GroupByNewFieldValue = Either<List<GroupPB>, FlowyError>;

View file

@ -64,7 +64,7 @@ class BoardCheckboxCellState with _$BoardCheckboxCellState {
required bool isSelected,
}) = _CheckboxCellState;
factory BoardCheckboxCellState.initial(GridCellController context) {
factory BoardCheckboxCellState.initial(GridTextCellController context) {
return BoardCheckboxCellState(
isSelected: _isSelected(context.getCellData()));
}

View file

@ -1,6 +1,6 @@
import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart';
import 'package:app_flowy/plugins/grid/application/field/field_controller.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/date_type_option_entities.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/date_type_option_entities.pb.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'dart:async';

View file

@ -60,7 +60,7 @@ class BoardNumberCellState with _$BoardNumberCellState {
required String content,
}) = _BoardNumberCellState;
factory BoardNumberCellState.initial(GridCellController context) =>
factory BoardNumberCellState.initial(GridTextCellController context) =>
BoardNumberCellState(
content: context.getCellData() ?? "",
);

View file

@ -1,5 +1,5 @@
import 'dart:async';
import 'package:flowy_sdk/protobuf/flowy-grid/select_type_option.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/select_type_option.pb.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart';

View file

@ -6,7 +6,7 @@ import 'dart:async';
part 'board_text_cell_bloc.freezed.dart';
class BoardTextCellBloc extends Bloc<BoardTextCellEvent, BoardTextCellState> {
final GridCellController cellController;
final GridTextCellController cellController;
void Function()? _onCellChangedFn;
BoardTextCellBloc({
required this.cellController,
@ -71,7 +71,7 @@ class BoardTextCellState with _$BoardTextCellState {
required bool enableEdit,
}) = _BoardTextCellState;
factory BoardTextCellState.initial(GridCellController context) =>
factory BoardTextCellState.initial(GridTextCellController context) =>
BoardTextCellState(
content: context.getCellData() ?? "",
enableEdit: false,

View file

@ -1,5 +1,5 @@
import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/url_type_option_entities.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/url_type_option_entities.pb.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'dart:async';

View file

@ -3,7 +3,7 @@ import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_servic
import 'package:app_flowy/plugins/grid/application/row/row_cache.dart';
import 'package:app_flowy/plugins/grid/application/row/row_service.dart';
import 'package:equatable/equatable.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/row_entities.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/row_entities.pb.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'dart:async';

View file

@ -3,7 +3,7 @@ import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_servic
import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_field_notifier.dart';
import 'package:app_flowy/plugins/grid/application/field/field_controller.dart';
import 'package:app_flowy/plugins/grid/application/row/row_cache.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/row_entities.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/row_entities.pb.dart';
import 'package:flutter/foundation.dart';
typedef OnCardChanged = void Function(GridCellMap, RowsChangedReason);

View file

@ -1,4 +1,4 @@
import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/field_entities.pb.dart';
class BoardGroupService {
final String gridId;

View file

@ -1,6 +1,6 @@
import 'package:flowy_sdk/log.dart';
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/protobuf.dart';
import 'package:appflowy_backend/log.dart';
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/protobuf.dart';
import 'group_listener.dart';
typedef OnGroupError = void Function(FlowyError);

View file

@ -2,11 +2,11 @@ import 'dart:typed_data';
import 'package:app_flowy/core/grid_notification.dart';
import 'package:flowy_infra/notifier.dart';
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/dart_notification.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/group.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/dart_notification.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/group.pb.dart';
import 'package:dartz/dartz.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/group_changeset.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/group_changeset.pb.dart';
typedef UpdateGroupNotifiedValue = Either<GroupRowsNotificationPB, FlowyError>;

View file

@ -1,7 +1,7 @@
import 'package:app_flowy/plugins/util.dart';
import 'package:app_flowy/workspace/presentation/home/home_stack.dart';
import 'package:app_flowy/workspace/presentation/widgets/left_bar_item.dart';
import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
import 'package:app_flowy/startup/plugin/plugin.dart';
import 'package:flutter/material.dart';

View file

@ -15,12 +15,11 @@ import 'package:flowy_infra/image.dart';
import 'package:flowy_infra_ui/style_widget/text.dart';
import 'package:flowy_infra_ui/flowy_infra_ui_web.dart';
import 'package:flowy_infra_ui/widget/error_page.dart';
import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/row_entities.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/field_entities.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/row_entities.pb.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../../grid/application/row/row_cache.dart';
import '../application/board_bloc.dart';
import 'card/card.dart';
import 'card/card_cell_builder.dart';
@ -289,7 +288,7 @@ class _BoardContentState extends State<BoardContent> {
rowPB: rowPB,
);
final dataController = GridRowDataController(
final dataController = RowDataController(
rowInfo: rowInfo,
fieldController: fieldController,
rowCache: rowCache,

View file

@ -35,7 +35,7 @@ class _BoardTextCellState extends State<BoardTextCell> {
@override
void initState() {
final cellController =
widget.cellControllerBuilder.build() as GridCellController;
widget.cellControllerBuilder.build() as GridTextCellController;
_cellBloc = BoardTextCellBloc(cellController: cellController)
..add(const BoardTextCellEvent.initial());
_controller = TextEditingController(text: _cellBloc.state.content);

View file

@ -1,5 +1,5 @@
import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/field_entities.pb.dart';
import 'package:flutter/material.dart';
import 'board_cell.dart';

View file

@ -13,6 +13,7 @@ import 'package:flowy_infra_ui/style_widget/text.dart';
import 'package:flowy_infra_ui/widget/spacing.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:styled_widget/styled_widget.dart';
import 'board_toolbar.dart';
@ -181,6 +182,6 @@ class _BoardSettingListPopoverState extends State<BoardSettingListPopover> {
onAction: (action, settingContext) {
setState(() => _action = action);
},
);
).padding(all: 6.0);
}
}

View file

@ -1,4 +1,5 @@
import 'package:app_flowy/plugins/grid/application/field/field_controller.dart';
import 'package:app_flowy/plugins/grid/presentation/layout/sizes.dart';
import 'package:appflowy_popover/appflowy_popover.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flowy_infra/theme_extension.dart';
@ -67,12 +68,12 @@ class _SettingButtonState extends State<_SettingButton> {
direction: PopoverDirection.leftWithTopAligned,
triggerActions: PopoverTriggerFlags.none,
constraints: BoxConstraints.loose(const Size(260, 400)),
margin: EdgeInsets.zero,
child: FlowyTextButton(
LocaleKeys.settings_title.tr(),
fontSize: 14,
fillColor: Colors.transparent,
hoverColor: AFThemeExtension.of(context).lightGreyHover,
padding: const EdgeInsets.symmetric(vertical: 2, horizontal: 6),
padding: GridSize.typeOptionContentInsets,
onPressed: () {
popoverController.show();
},

View file

@ -0,0 +1,111 @@
import 'package:app_flowy/generated/locale_keys.g.dart';
import 'package:app_flowy/startup/plugin/plugin.dart';
import 'package:app_flowy/workspace/presentation/home/home_stack.dart';
import 'package:app_flowy/workspace/presentation/widgets/left_bar_item.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
import 'package:flutter/material.dart';
import '../util.dart';
class CalendarPluginBuilder extends PluginBuilder {
@override
Plugin build(dynamic data) {
if (data is ViewPB) {
return CalendarPlugin(pluginType: pluginType, view: data);
} else {
throw FlowyPluginException.invalidData;
}
}
@override
String get menuName => LocaleKeys.calendar_menuName.tr();
@override
String get menuIcon => "editor/date";
@override
PluginType get pluginType => PluginType.calendar;
@override
ViewDataFormatPB get dataFormatType => ViewDataFormatPB.DatabaseFormat;
@override
ViewLayoutTypePB? get layoutType => ViewLayoutTypePB.Calendar;
}
class CalendarPluginConfig implements PluginConfig {
@override
bool get creatable => false;
}
class CalendarPlugin extends Plugin {
@override
final ViewPluginNotifier notifier;
final PluginType _pluginType;
CalendarPlugin({
required ViewPB view,
required PluginType pluginType,
}) : _pluginType = pluginType,
notifier = ViewPluginNotifier(view: view);
@override
PluginDisplay get display => CalendarPluginDisplay(notifier: notifier);
@override
PluginId get id => notifier.view.id;
@override
PluginType get ty => _pluginType;
}
class CalendarPluginDisplay extends PluginDisplay {
final ViewPluginNotifier notifier;
CalendarPluginDisplay({required this.notifier, Key? key});
ViewPB get view => notifier.view;
@override
Widget get leftBarItem => ViewLeftBarItem(view: view);
@override
Widget buildWidget(PluginContext context) {
notifier.isDeleted.addListener(() {
notifier.isDeleted.value.fold(() => null, (deletedView) {
if (deletedView.hasIndex()) {
context.onDeleted(view, deletedView.index);
}
});
});
return BlankPage(key: ValueKey(view.id));
// return BoardPage(key: ValueKey(view.id), view: view);
}
@override
List<NavigationItem> get navigationItems => [this];
}
// mark for removal
class BlankPage extends StatefulWidget {
const BlankPage({Key? key}) : super(key: key);
@override
State<BlankPage> createState() => _BlankPageState();
}
class _BlankPageState extends State<BlankPage> {
@override
Widget build(BuildContext context) {
return SizedBox.expand(
child: Container(
color: Theme.of(context).colorScheme.surface,
child: Padding(
padding: const EdgeInsets.all(10),
child: Container(),
),
),
);
}
}

View file

@ -4,10 +4,10 @@ import 'package:app_flowy/workspace/application/view/view_listener.dart';
import 'package:app_flowy/plugins/document/application/doc_service.dart';
import 'package:appflowy_editor/appflowy_editor.dart'
show EditorState, Document, Transaction;
import 'package:flowy_sdk/protobuf/flowy-folder/trash.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart';
import 'package:flowy_sdk/log.dart';
import 'package:appflowy_backend/protobuf/flowy-folder/trash.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
import 'package:appflowy_backend/log.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:dartz/dartz.dart';

View file

@ -1,9 +1,9 @@
import 'package:dartz/dartz.dart';
import 'package:flowy_sdk/dispatch/dispatch.dart';
import 'package:appflowy_backend/dispatch/dispatch.dart';
import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-document/entities.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-document/entities.pb.dart';
class DocumentService {
Future<Either<DocumentSnapshotPB, FlowyError>> openDocument({

View file

@ -1,9 +1,9 @@
import 'dart:convert';
import 'dart:io';
import 'package:app_flowy/plugins/document/application/share_service.dart';
import 'package:flowy_sdk/protobuf/flowy-document/entities.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-document/entities.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:dartz/dartz.dart';

View file

@ -1,9 +1,9 @@
import 'dart:async';
import 'package:dartz/dartz.dart';
import 'package:flowy_sdk/dispatch/dispatch.dart';
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-document/protobuf.dart';
import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart';
import 'package:appflowy_backend/dispatch/dispatch.dart';
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-document/protobuf.dart';
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
class ShareService {
Future<Either<ExportDataPB, FlowyError>> export(

View file

@ -10,7 +10,7 @@ import 'package:app_flowy/startup/plugin/plugin.dart';
import 'package:app_flowy/workspace/presentation/home/home_stack.dart';
import 'package:app_flowy/workspace/presentation/widgets/left_bar_item.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

View file

@ -1,7 +1,7 @@
import 'package:appflowy_editor/appflowy_editor.dart';
import 'package:appflowy_editor_plugins/appflowy_editor_plugins.dart';
import 'package:flowy_infra_ui/widget/error_page.dart';
import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:intl/intl.dart';

View file

@ -11,10 +11,10 @@ import 'package:clipboard/clipboard.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:file_picker/file_picker.dart';
import 'package:flowy_infra_ui/widget/rounded_button.dart';
import 'package:flowy_sdk/log.dart';
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-document/entities.pb.dart';
import 'package:appflowy_backend/log.dart';
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-document/entities.pb.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

View file

@ -1,7 +1,7 @@
import 'package:app_flowy/core/grid_notification.dart';
import 'package:dartz/dartz.dart';
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/dart_notification.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/dart_notification.pb.dart';
import 'package:flowy_infra/notifier.dart';
import 'dart:async';
import 'dart:typed_data';

View file

@ -1,15 +1,15 @@
part of 'cell_service.dart';
typedef GridCellController = IGridCellController<String, String>;
typedef GridCheckboxCellController = IGridCellController<String, String>;
typedef GridNumberCellController = IGridCellController<String, String>;
typedef GridTextCellController = GridCellController<String, String>;
typedef GridCheckboxCellController = GridCellController<String, String>;
typedef GridNumberCellController = GridCellController<String, String>;
typedef GridSelectOptionCellController
= IGridCellController<SelectOptionCellDataPB, String>;
= GridCellController<SelectOptionCellDataPB, String>;
typedef GridChecklistCellController
= IGridCellController<SelectOptionCellDataPB, String>;
= GridCellController<SelectOptionCellDataPB, String>;
typedef GridDateCellController
= IGridCellController<DateCellDataPB, CalendarData>;
typedef GridURLCellController = IGridCellController<URLCellDataPB, String>;
= GridCellController<DateCellDataPB, CalendarData>;
typedef GridURLCellController = GridCellController<URLCellDataPB, String>;
abstract class GridCellControllerBuilderDelegate {
GridCellFieldNotifier buildFieldNotifier();
@ -27,7 +27,7 @@ class GridCellControllerBuilder {
}) : _cellCache = cellCache,
_cellId = cellId;
IGridCellController build() {
GridCellController build() {
final cellFieldNotifier = delegate.buildFieldNotifier();
switch (_cellId.fieldType) {
case FieldType.Checkbox:
@ -35,12 +35,12 @@ class GridCellControllerBuilder {
cellId: _cellId,
parser: StringCellDataParser(),
);
return GridCellController(
return GridTextCellController(
cellId: _cellId,
cellCache: _cellCache,
cellDataLoader: cellDataLoader,
fieldNotifier: cellFieldNotifier,
cellDataPersistence: CellDataPersistence(cellId: _cellId),
cellDataPersistence: TextCellDataPersistence(cellId: _cellId),
);
case FieldType.DateTime:
final cellDataLoader = GridCellDataLoader(
@ -67,19 +67,19 @@ class GridCellControllerBuilder {
cellCache: _cellCache,
cellDataLoader: cellDataLoader,
fieldNotifier: cellFieldNotifier,
cellDataPersistence: CellDataPersistence(cellId: _cellId),
cellDataPersistence: TextCellDataPersistence(cellId: _cellId),
);
case FieldType.RichText:
final cellDataLoader = GridCellDataLoader(
cellId: _cellId,
parser: StringCellDataParser(),
);
return GridCellController(
return GridTextCellController(
cellId: _cellId,
cellCache: _cellCache,
cellDataLoader: cellDataLoader,
fieldNotifier: cellFieldNotifier,
cellDataPersistence: CellDataPersistence(cellId: _cellId),
cellDataPersistence: TextCellDataPersistence(cellId: _cellId),
);
case FieldType.MultiSelect:
case FieldType.SingleSelect:
@ -95,7 +95,7 @@ class GridCellControllerBuilder {
cellCache: _cellCache,
cellDataLoader: cellDataLoader,
fieldNotifier: cellFieldNotifier,
cellDataPersistence: CellDataPersistence(cellId: _cellId),
cellDataPersistence: TextCellDataPersistence(cellId: _cellId),
);
case FieldType.URL:
@ -108,7 +108,7 @@ class GridCellControllerBuilder {
cellCache: _cellCache,
cellDataLoader: cellDataLoader,
fieldNotifier: cellFieldNotifier,
cellDataPersistence: CellDataPersistence(cellId: _cellId),
cellDataPersistence: TextCellDataPersistence(cellId: _cellId),
);
}
throw UnimplementedError;
@ -123,14 +123,14 @@ class GridCellControllerBuilder {
/// Generic D represents the type of data that will be saved to the disk
///
// ignore: must_be_immutable
class IGridCellController<T, D> extends Equatable {
class GridCellController<T, D> extends Equatable {
final GridCellIdentifier cellId;
final GridCellCache _cellsCache;
final GridCellCacheKey _cacheKey;
final FieldService _fieldService;
final GridCellFieldNotifier _fieldNotifier;
final GridCellDataLoader<T> _cellDataLoader;
final IGridCellDataPersistence<D> _cellDataPersistence;
final GridCellDataPersistence<D> _cellDataPersistence;
CellListener? _cellListener;
CellDataNotifier<T?>? _cellDataNotifier;
@ -141,12 +141,12 @@ class IGridCellController<T, D> extends Equatable {
Timer? _saveDataOperation;
bool _isDispose = false;
IGridCellController({
GridCellController({
required this.cellId,
required GridCellCache cellCache,
required GridCellFieldNotifier fieldNotifier,
required GridCellDataLoader<T> cellDataLoader,
required IGridCellDataPersistence<D> cellDataPersistence,
required GridCellDataPersistence<D> cellDataPersistence,
}) : _cellsCache = cellCache,
_cellDataLoader = cellDataLoader,
_cellDataPersistence = cellDataPersistence,

View file

@ -5,14 +5,14 @@ abstract class IGridCellDataConfig {
bool get reloadOnFieldChanged;
}
abstract class IGridCellDataParser<T> {
abstract class GridCellDataParser<T> {
T? parserData(List<int> data);
}
class GridCellDataLoader<T> {
final CellService service = CellService();
final GridCellIdentifier cellId;
final IGridCellDataParser<T> parser;
final GridCellDataParser<T> parser;
final bool reloadOnFieldChanged;
GridCellDataLoader({
@ -43,7 +43,7 @@ class GridCellDataLoader<T> {
}
}
class StringCellDataParser implements IGridCellDataParser<String> {
class StringCellDataParser implements GridCellDataParser<String> {
@override
String? parserData(List<int> data) {
final s = utf8.decode(data);
@ -51,7 +51,7 @@ class StringCellDataParser implements IGridCellDataParser<String> {
}
}
class DateCellDataParser implements IGridCellDataParser<DateCellDataPB> {
class DateCellDataParser implements GridCellDataParser<DateCellDataPB> {
@override
DateCellDataPB? parserData(List<int> data) {
if (data.isEmpty) {
@ -62,7 +62,7 @@ class DateCellDataParser implements IGridCellDataParser<DateCellDataPB> {
}
class SelectOptionCellDataParser
implements IGridCellDataParser<SelectOptionCellDataPB> {
implements GridCellDataParser<SelectOptionCellDataPB> {
@override
SelectOptionCellDataPB? parserData(List<int> data) {
if (data.isEmpty) {
@ -72,7 +72,7 @@ class SelectOptionCellDataParser
}
}
class URLCellDataParser implements IGridCellDataParser<URLCellDataPB> {
class URLCellDataParser implements GridCellDataParser<URLCellDataPB> {
@override
URLCellDataPB? parserData(List<int> data) {
if (data.isEmpty) {

View file

@ -2,14 +2,14 @@ part of 'cell_service.dart';
/// Save the cell data to disk
/// You can extend this class to do custom operations. For example, the DateCellDataPersistence.
abstract class IGridCellDataPersistence<D> {
abstract class GridCellDataPersistence<D> {
Future<Option<FlowyError>> save(D data);
}
class CellDataPersistence implements IGridCellDataPersistence<String> {
class TextCellDataPersistence implements GridCellDataPersistence<String> {
final GridCellIdentifier cellId;
CellDataPersistence({
TextCellDataPersistence({
required this.cellId,
});
final CellService _cellService = CellService();
@ -33,8 +33,7 @@ class CalendarData with _$CalendarData {
_CalendarData;
}
class DateCellDataPersistence
implements IGridCellDataPersistence<CalendarData> {
class DateCellDataPersistence implements GridCellDataPersistence<CalendarData> {
final GridCellIdentifier cellId;
DateCellDataPersistence({
required this.cellId,

View file

@ -2,14 +2,14 @@ import 'dart:async';
import 'dart:collection';
import 'package:dartz/dartz.dart';
import 'package:equatable/equatable.dart';
import 'package:flowy_sdk/dispatch/dispatch.dart';
import 'package:flowy_sdk/log.dart';
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/cell_entities.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/date_type_option_entities.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/select_type_option.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/url_type_option_entities.pb.dart';
import 'package:appflowy_backend/dispatch/dispatch.dart';
import 'package:appflowy_backend/log.dart';
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/cell_entities.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/date_type_option_entities.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/field_entities.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/select_type_option.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/url_type_option_entities.pb.dart';
import 'package:flutter/foundation.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:app_flowy/plugins/grid/application/cell/cell_listener.dart';

View file

@ -65,7 +65,7 @@ class CheckboxCellState with _$CheckboxCellState {
required bool isSelected,
}) = _CheckboxCellState;
factory CheckboxCellState.initial(GridCellController context) {
factory CheckboxCellState.initial(GridTextCellController context) {
return CheckboxCellState(isSelected: _isSelected(context.getCellData()));
}
}

View file

@ -1,5 +1,5 @@
import 'package:flowy_sdk/log.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/select_type_option.pb.dart';
import 'package:appflowy_backend/log.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/select_type_option.pb.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'dart:async';

View file

@ -2,8 +2,8 @@ import 'dart:async';
import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart';
import 'package:dartz/dartz.dart';
import 'package:flowy_sdk/log.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/select_type_option.pb.dart';
import 'package:appflowy_backend/log.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/select_type_option.pb.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';

View file

@ -2,11 +2,11 @@ import 'package:app_flowy/generated/locale_keys.g.dart';
import 'package:app_flowy/plugins/grid/application/field/field_service.dart';
import 'package:easy_localization/easy_localization.dart'
show StringTranslateExtension;
import 'package:flowy_sdk/log.dart';
import 'package:flowy_sdk/protobuf/flowy-error/code.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/date_type_option.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/date_type_option_entities.pb.dart';
import 'package:appflowy_backend/log.dart';
import 'package:appflowy_backend/protobuf/flowy-error/code.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/date_type_option.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/date_type_option_entities.pb.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:table_calendar/table_calendar.dart';
@ -41,8 +41,8 @@ class DateCalBloc extends Bloc<DateCalEvent, DateCalState> {
},
didReceiveCellUpdate: (DateCellDataPB? cellData) {
final calData = calDataFromCellData(cellData);
final time =
calData.foldRight("", (dateData, previous) => dateData.time);
final time = calData.foldRight(
"", (dateData, previous) => dateData.time ?? '');
emit(state.copyWith(calData: calData, time: time));
},
setIncludeTime: (includeTime) async {
@ -224,7 +224,8 @@ class DateCalState with _$DateCalState {
DateCellDataPB? cellData,
) {
Option<CalendarData> calData = calDataFromCellData(cellData);
final time = calData.foldRight("", (dateData, previous) => dateData.time);
final time =
calData.foldRight("", (dateData, previous) => dateData.time ?? '');
return DateCalState(
dateTypeOptionPB: dateTypeOptionPB,
format: CalendarFormat.month,

View file

@ -1,5 +1,5 @@
import 'package:app_flowy/plugins/grid/application/field/field_controller.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/date_type_option_entities.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/date_type_option_entities.pb.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'dart:async';

View file

@ -1,4 +1,4 @@
import 'package:flowy_sdk/log.dart';
import 'package:appflowy_backend/log.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'dart:async';
@ -82,7 +82,7 @@ class NumberCellState with _$NumberCellState {
required String cellContent,
}) = _NumberCellState;
factory NumberCellState.initial(GridCellController context) {
factory NumberCellState.initial(GridTextCellController context) {
return NumberCellState(
cellContent: context.getCellData() ?? "",
);

View file

@ -1,5 +1,5 @@
import 'dart:async';
import 'package:flowy_sdk/protobuf/flowy-grid/select_type_option.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/select_type_option.pb.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart';

View file

@ -1,8 +1,8 @@
import 'dart:async';
import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart';
import 'package:dartz/dartz.dart';
import 'package:flowy_sdk/log.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/select_type_option.pb.dart';
import 'package:appflowy_backend/log.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/select_type_option.pb.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'select_option_service.dart';

View file

@ -1,9 +1,9 @@
import 'package:dartz/dartz.dart';
import 'package:flowy_sdk/dispatch/dispatch.dart';
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/cell_entities.pb.dart';
import 'package:appflowy_backend/dispatch/dispatch.dart';
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/cell_entities.pb.dart';
import 'package:app_flowy/plugins/grid/application/field/type_option/type_option_service.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/select_type_option.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/select_type_option.pb.dart';
import 'cell_service/cell_service.dart';
class SelectOptionFFIService {

View file

@ -6,7 +6,7 @@ import 'cell_service/cell_service.dart';
part 'text_cell_bloc.freezed.dart';
class TextCellBloc extends Bloc<TextCellEvent, TextCellState> {
final GridCellController cellController;
final GridTextCellController cellController;
void Function()? _onCellChangedFn;
TextCellBloc({
required this.cellController,
@ -66,7 +66,8 @@ class TextCellState with _$TextCellState {
required String content,
}) = _TextCellState;
factory TextCellState.initial(GridCellController context) => TextCellState(
factory TextCellState.initial(GridTextCellController context) =>
TextCellState(
content: context.getCellData() ?? "",
);
}

View file

@ -1,4 +1,4 @@
import 'package:flowy_sdk/protobuf/flowy-grid/url_type_option_entities.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/url_type_option_entities.pb.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'dart:async';

View file

@ -1,4 +1,4 @@
import 'package:flowy_sdk/protobuf/flowy-grid/url_type_option_entities.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/url_type_option_entities.pb.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'dart:async';

View file

@ -1,5 +1,5 @@
import 'package:flowy_sdk/log.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
import 'package:appflowy_backend/log.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/field_entities.pb.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'dart:async';

View file

@ -1,7 +1,7 @@
import 'package:app_flowy/plugins/grid/application/field/field_listener.dart';
import 'package:app_flowy/plugins/grid/application/field/field_service.dart';
import 'package:flowy_sdk/log.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
import 'package:appflowy_backend/log.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/field_entities.pb.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'dart:async';

View file

@ -5,14 +5,19 @@ import 'package:app_flowy/plugins/grid/application/filter/filter_service.dart';
import 'package:app_flowy/plugins/grid/application/grid_service.dart';
import 'package:app_flowy/plugins/grid/application/setting/setting_listener.dart';
import 'package:app_flowy/plugins/grid/application/setting/setting_service.dart';
import 'package:app_flowy/plugins/grid/application/sort/sort_listener.dart';
import 'package:app_flowy/plugins/grid/application/sort/sort_service.dart';
import 'package:app_flowy/plugins/grid/presentation/widgets/filter/filter_info.dart';
import 'package:app_flowy/plugins/grid/presentation/widgets/sort/sort_info.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/filter_changeset.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/sort_entities.pb.dart';
import 'package:dartz/dartz.dart';
import 'package:flowy_sdk/log.dart';
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/group.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/setting_entities.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/util.pb.dart';
import 'package:appflowy_backend/log.dart';
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/field_entities.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/group.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/setting_entities.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/util.pb.dart';
import 'package:flutter/foundation.dart';
import '../row/row_cache.dart';
@ -46,21 +51,39 @@ class _GridFilterNotifier extends ChangeNotifier {
List<FilterInfo> get filters => _filters;
}
class _GridSortNotifier extends ChangeNotifier {
List<SortInfo> _sorts = [];
set sorts(List<SortInfo> sorts) {
_sorts = sorts;
notifyListeners();
}
void notify() {
notifyListeners();
}
List<SortInfo> get sorts => _sorts;
}
typedef OnReceiveUpdateFields = void Function(List<FieldInfo>);
typedef OnReceiveFields = void Function(List<FieldInfo>);
typedef OnReceiveFilters = void Function(List<FilterInfo>);
typedef OnReceiveSorts = void Function(List<SortInfo>);
class GridFieldController {
final String gridId;
// Listeners
final GridFieldsListener _fieldListener;
final SettingListener _settingListener;
final FiltersListener _filterListener;
final FiltersListener _filtersListener;
final SortsListener _sortsListener;
// FFI services
final GridFFIService _gridFFIService;
final SettingFFIService _settingFFIService;
final FilterFFIService _filterFFIService;
final SortFFIService _sortFFIService;
// Field callbacks
final Map<OnReceiveFields, VoidCallback> _fieldCallbacks = {};
@ -78,9 +101,16 @@ class GridFieldController {
_GridFilterNotifier? _filterNotifier = _GridFilterNotifier();
final Map<String, FilterPB> _filterPBByFieldId = {};
// Sort callbacks
final Map<OnReceiveSorts, VoidCallback> _sortCallbacks = {};
_GridSortNotifier? _sortNotifier = _GridSortNotifier();
final Map<String, SortPB> _sortPBByFieldId = {};
// Getters
List<FieldInfo> get fieldInfos => [..._fieldNotifier?.fieldInfos ?? []];
List<FilterInfo> get filterInfos => [..._filterNotifier?.filters ?? []];
List<SortInfo> get sortInfos => [..._sortNotifier?.sorts ?? []];
FieldInfo? getField(String fieldId) {
final fields = _fieldNotifier?.fieldInfos
.where((element) => element.id == fieldId)
@ -105,12 +135,26 @@ class GridFieldController {
return filters.first;
}
SortInfo? getSort(String sortId) {
final sorts = _sortNotifier?.sorts
.where((element) => element.sortId == sortId)
.toList() ??
[];
if (sorts.isEmpty) {
return null;
}
assert(sorts.length == 1);
return sorts.first;
}
GridFieldController({required this.gridId})
: _fieldListener = GridFieldsListener(gridId: gridId),
_settingListener = SettingListener(gridId: gridId),
_filterListener = FiltersListener(viewId: gridId),
_gridFFIService = GridFFIService(gridId: gridId),
_filterFFIService = FilterFFIService(viewId: gridId),
_filtersListener = FiltersListener(viewId: gridId),
_gridFFIService = GridFFIService(gridId: gridId),
_sortFFIService = SortFFIService(viewId: gridId),
_sortsListener = SortsListener(viewId: gridId),
_settingFFIService = SettingFFIService(viewId: gridId) {
//Listen on field's changes
_listenOnFieldChanges();
@ -121,9 +165,12 @@ class GridFieldController {
//Listen on the fitler changes
_listenOnFilterChanges();
//Listen on the sort changes
_listenOnSortChanged();
_settingFFIService.getSetting().then((result) {
result.fold(
(setting) => _updateSettingConfiguration(setting),
(setting) => _updateSetting(setting),
(err) => Log.error(err),
);
});
@ -131,68 +178,95 @@ class GridFieldController {
void _listenOnFilterChanges() {
//Listen on the fitler changes
_filterListener.start(onFilterChanged: (result) {
deleteFilterFromChangeset(
List<FilterInfo> filters,
FilterChangesetNotificationPB changeset,
) {
final deleteFilterIds = changeset.deleteFilters.map((e) => e.id).toList();
if (deleteFilterIds.isNotEmpty) {
filters.retainWhere(
(element) => !deleteFilterIds.contains(element.filter.id),
);
_filterPBByFieldId
.removeWhere((key, value) => deleteFilterIds.contains(value.id));
}
}
insertFilterFromChangeset(
List<FilterInfo> filters,
FilterChangesetNotificationPB changeset,
) {
for (final newFilter in changeset.insertFilters) {
final filterIndex =
filters.indexWhere((element) => element.filter.id == newFilter.id);
if (filterIndex == -1) {
final fieldInfo = _findFieldInfo(
fieldInfos: fieldInfos,
fieldId: newFilter.fieldId,
fieldType: newFilter.fieldType,
);
if (fieldInfo != null) {
_filterPBByFieldId[fieldInfo.id] = newFilter;
filters.add(FilterInfo(gridId, newFilter, fieldInfo));
}
}
}
}
updateFilterFromChangeset(
List<FilterInfo> filters,
FilterChangesetNotificationPB changeset,
) {
for (final updatedFilter in changeset.updateFilters) {
final filterIndex = filters.indexWhere(
(element) => element.filter.id == updatedFilter.filterId,
);
// Remove the old filter
if (filterIndex != -1) {
filters.removeAt(filterIndex);
_filterPBByFieldId
.removeWhere((key, value) => value.id == updatedFilter.filterId);
}
// Insert the filter if there is a fitler and its field info is
// not null
if (updatedFilter.hasFilter()) {
final fieldInfo = _findFieldInfo(
fieldInfos: fieldInfos,
fieldId: updatedFilter.filter.fieldId,
fieldType: updatedFilter.filter.fieldType,
);
if (fieldInfo != null) {
// Insert the filter with the position: filterIndex, otherwise,
// append it to the end of the list.
final filterInfo =
FilterInfo(gridId, updatedFilter.filter, fieldInfo);
if (filterIndex != -1) {
filters.insert(filterIndex, filterInfo);
} else {
filters.add(filterInfo);
}
_filterPBByFieldId[fieldInfo.id] = updatedFilter.filter;
}
}
}
}
_filtersListener.start(onFilterChanged: (result) {
result.fold(
(changeset) {
(FilterChangesetNotificationPB changeset) {
final List<FilterInfo> filters = filterInfos;
// Deletes the filters
final deleteFilterIds =
changeset.deleteFilters.map((e) => e.id).toList();
if (deleteFilterIds.isNotEmpty) {
filters.retainWhere(
(element) => !deleteFilterIds.contains(element.filter.id),
);
_filterPBByFieldId.removeWhere(
(key, value) => deleteFilterIds.contains(value.id));
}
deleteFilterFromChangeset(filters, changeset);
// Inserts the new filter if it's not exist
for (final newFilter in changeset.insertFilters) {
final filterIndex = filters
.indexWhere((element) => element.filter.id == newFilter.id);
if (filterIndex == -1) {
final fieldInfo = _findFieldInfoForFilter(fieldInfos, newFilter);
if (fieldInfo != null) {
_filterPBByFieldId[fieldInfo.id] = newFilter;
filters.add(FilterInfo(gridId, newFilter, fieldInfo));
}
}
}
insertFilterFromChangeset(filters, changeset);
for (final updatedFilter in changeset.updateFilters) {
final filterIndex = filters.indexWhere(
(element) => element.filter.id == updatedFilter.filterId,
);
// Remove the old filter
if (filterIndex != -1) {
filters.removeAt(filterIndex);
_filterPBByFieldId.removeWhere(
(key, value) => value.id == updatedFilter.filterId);
}
updateFilterFromChangeset(filters, changeset);
// Insert the filter if there is a fitler and its field info is
// not null
if (updatedFilter.hasFilter()) {
final fieldInfo = _findFieldInfoForFilter(
fieldInfos,
updatedFilter.filter,
);
if (fieldInfo != null) {
// Insert the filter with the position: filterIndex, otherwise,
// append it to the end of the list.
final filterInfo =
FilterInfo(gridId, updatedFilter.filter, fieldInfo);
if (filterIndex != -1) {
filters.insert(filterIndex, filterInfo);
} else {
filters.add(filterInfo);
}
_filterPBByFieldId[fieldInfo.id] = updatedFilter.filter;
}
}
}
_updateFieldInfos();
_filterNotifier?.filters = filters;
},
@ -201,11 +275,99 @@ class GridFieldController {
});
}
void _listenOnSortChanged() {
deleteSortFromChangeset(
List<SortInfo> newSortInfos,
SortChangesetNotificationPB changeset,
) {
final deleteSortIds = changeset.deleteSorts.map((e) => e.id).toList();
if (deleteSortIds.isNotEmpty) {
newSortInfos.retainWhere(
(element) => !deleteSortIds.contains(element.sortId),
);
_sortPBByFieldId
.removeWhere((key, value) => deleteSortIds.contains(value.id));
}
}
insertSortFromChangeset(
List<SortInfo> newSortInfos,
SortChangesetNotificationPB changeset,
) {
for (final newSortPB in changeset.insertSorts) {
final sortIndex = newSortInfos
.indexWhere((element) => element.sortId == newSortPB.id);
if (sortIndex == -1) {
final fieldInfo = _findFieldInfo(
fieldInfos: fieldInfos,
fieldId: newSortPB.fieldId,
fieldType: newSortPB.fieldType,
);
if (fieldInfo != null) {
_sortPBByFieldId[newSortPB.fieldId] = newSortPB;
newSortInfos.add(SortInfo(sortPB: newSortPB, fieldInfo: fieldInfo));
}
}
}
}
updateSortFromChangeset(
List<SortInfo> newSortInfos,
SortChangesetNotificationPB changeset,
) {
for (final updatedSort in changeset.updateSorts) {
final sortIndex = newSortInfos.indexWhere(
(element) => element.sortId == updatedSort.id,
);
// Remove the old filter
if (sortIndex != -1) {
newSortInfos.removeAt(sortIndex);
}
final fieldInfo = _findFieldInfo(
fieldInfos: fieldInfos,
fieldId: updatedSort.fieldId,
fieldType: updatedSort.fieldType,
);
if (fieldInfo != null) {
final newSortInfo = SortInfo(
sortPB: updatedSort,
fieldInfo: fieldInfo,
);
if (sortIndex != -1) {
newSortInfos.insert(sortIndex, newSortInfo);
} else {
newSortInfos.add(newSortInfo);
}
_sortPBByFieldId[updatedSort.fieldId] = updatedSort;
}
}
}
_sortsListener.start(onSortChanged: (result) {
result.fold(
(SortChangesetNotificationPB changeset) {
final List<SortInfo> newSortInfos = sortInfos;
deleteSortFromChangeset(newSortInfos, changeset);
insertSortFromChangeset(newSortInfos, changeset);
updateSortFromChangeset(newSortInfos, changeset);
_updateFieldInfos();
_sortNotifier?.sorts = newSortInfos;
},
(err) => Log.error(err),
);
});
}
void _listenOnSettingChanges() {
//Listen on setting changes
_settingListener.start(onSettingUpdated: (result) {
result.fold(
(setting) => _updateSettingConfiguration(setting),
(setting) => _updateSetting(setting),
(r) => Log.error(r),
);
});
@ -229,14 +391,18 @@ class GridFieldController {
});
}
void _updateSettingConfiguration(GridSettingPB setting) {
void _updateSetting(GridSettingPB setting) {
_groupConfigurationByFieldId.clear();
for (final configuration in setting.groupConfigurations.items) {
_groupConfigurationByFieldId[configuration.fieldId] = configuration;
}
for (final configuration in setting.filters.items) {
_filterPBByFieldId[configuration.fieldId] = configuration;
for (final filter in setting.filters.items) {
_filterPBByFieldId[filter.fieldId] = filter;
}
for (final sort in setting.sorts.items) {
_sortPBByFieldId[sort.fieldId] = sort;
}
_updateFieldInfos();
@ -247,6 +413,7 @@ class GridFieldController {
for (var field in _fieldNotifier!.fieldInfos) {
field._isGroupField = _groupConfigurationByFieldId[field.id] != null;
field._hasFilter = _filterPBByFieldId[field.id] != null;
field._hasSort = _sortPBByFieldId[field.id] != null;
}
_fieldNotifier?.notify();
}
@ -254,8 +421,9 @@ class GridFieldController {
Future<void> dispose() async {
await _fieldListener.stop();
await _filterListener.stop();
await _filtersListener.stop();
await _settingListener.stop();
await _sortsListener.stop();
for (final callback in _fieldCallbacks.values) {
_fieldNotifier?.removeListener(callback);
@ -266,8 +434,15 @@ class GridFieldController {
for (final callback in _filterCallbacks.values) {
_filterNotifier?.removeListener(callback);
}
for (final callback in _sortCallbacks.values) {
_sortNotifier?.removeListener(callback);
}
_filterNotifier?.dispose();
_filterNotifier = null;
_sortNotifier?.dispose();
_sortNotifier = null;
}
Future<Either<Unit, FlowyError>> loadFields({
@ -280,6 +455,7 @@ class GridFieldController {
_fieldNotifier?.fieldInfos =
newFields.map((field) => FieldInfo(field: field)).toList();
_loadFilters();
_loadSorts();
_updateFieldInfos();
return left(unit);
},
@ -294,14 +470,17 @@ class GridFieldController {
(filterPBs) {
final List<FilterInfo> filters = [];
for (final filterPB in filterPBs) {
final fieldInfo = _findFieldInfoForFilter(fieldInfos, filterPB);
final fieldInfo = _findFieldInfo(
fieldInfos: fieldInfos,
fieldId: filterPB.fieldId,
fieldType: filterPB.fieldType,
);
if (fieldInfo != null) {
final filterInfo = FilterInfo(gridId, filterPB, fieldInfo);
filters.add(filterInfo);
}
}
_updateFieldInfos();
_filterNotifier?.filters = filters;
return left(unit);
},
@ -310,10 +489,38 @@ class GridFieldController {
});
}
Future<Either<Unit, FlowyError>> _loadSorts() async {
return _sortFFIService.getAllSorts().then((result) {
return result.fold(
(sortPBs) {
final List<SortInfo> sortInfos = [];
for (final sortPB in sortPBs) {
final fieldInfo = _findFieldInfo(
fieldInfos: fieldInfos,
fieldId: sortPB.fieldId,
fieldType: sortPB.fieldType,
);
if (fieldInfo != null) {
final sortInfo = SortInfo(sortPB: sortPB, fieldInfo: fieldInfo);
sortInfos.add(sortInfo);
}
}
_updateFieldInfos();
_sortNotifier?.sorts = sortInfos;
return left(unit);
},
(err) => right(err),
);
});
}
void addListener({
OnReceiveFields? onFields,
OnReceiveUpdateFields? onFieldsUpdated,
OnReceiveFilters? onFilters,
OnReceiveSorts? onSorts,
bool Function()? listenWhen,
}) {
if (onFieldsUpdated != null) {
@ -350,10 +557,23 @@ class GridFieldController {
_filterCallbacks[onFilters] = callback;
_filterNotifier?.addListener(callback);
}
if (onSorts != null) {
callback() {
if (listenWhen != null && listenWhen() == false) {
return;
}
onSorts(sortInfos);
}
_sortCallbacks[onSorts] = callback;
_sortNotifier?.addListener(callback);
}
}
void removeListener({
OnReceiveFields? onFieldsListener,
OnReceiveSorts? onSortsListener,
OnReceiveFilters? onFiltersListener,
OnReceiveUpdateFields? onChangesetListener,
}) {
@ -369,6 +589,13 @@ class GridFieldController {
_filterNotifier?.removeListener(callback);
}
}
if (onSortsListener != null) {
final callback = _sortCallbacks.remove(onSortsListener);
if (callback != null) {
_sortNotifier?.removeListener(callback);
}
}
}
void _deleteFields(List<FieldIdPB> deletedFields) {
@ -425,7 +652,8 @@ class GridFieldController {
}
}
class GridRowFieldNotifierImpl extends IGridRowFieldNotifier {
class GridRowFieldNotifierImpl extends RowChangesetNotifierForward
with RowCacheDelegate {
final GridFieldController _cache;
OnReceiveUpdateFields? _onChangesetFn;
OnReceiveFields? _onFieldFn;
@ -466,11 +694,13 @@ class GridRowFieldNotifierImpl extends IGridRowFieldNotifier {
}
}
FieldInfo? _findFieldInfoForFilter(
List<FieldInfo> fieldInfos, FilterPB filter) {
FieldInfo? _findFieldInfo({
required List<FieldInfo> fieldInfos,
required String fieldId,
required FieldType fieldType,
}) {
final fieldIndex = fieldInfos.indexWhere((element) {
return element.id == filter.fieldId &&
element.fieldType == filter.fieldType;
return element.id == fieldId && element.fieldType == fieldType;
});
if (fieldIndex != -1) {
return fieldInfos[fieldIndex];
@ -485,6 +715,8 @@ class FieldInfo {
bool _hasFilter = false;
bool _hasSort = false;
String get id => _field.id;
FieldType get fieldType => _field.fieldType;
@ -529,5 +761,18 @@ class FieldInfo {
}
}
bool get canCreateSort {
if (_hasSort) return false;
switch (_field.fieldType) {
case FieldType.RichText:
case FieldType.Checkbox:
case FieldType.Number:
return true;
default:
return false;
}
}
FieldInfo({required FieldPB field}) : _field = field;
}

View file

@ -1,4 +1,4 @@
import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/field_entities.pb.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'dart:async';
import 'package:dartz/dartz.dart';

View file

@ -1,11 +1,11 @@
import 'package:app_flowy/core/grid_notification.dart';
import 'package:dartz/dartz.dart';
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/dart_notification.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/dart_notification.pb.dart';
import 'package:flowy_infra/notifier.dart';
import 'dart:async';
import 'dart:typed_data';
import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/field_entities.pb.dart';
typedef UpdateFieldNotifiedValue = Either<FieldPB, FlowyError>;

View file

@ -1,8 +1,8 @@
import 'package:dartz/dartz.dart';
import 'package:flowy_sdk/dispatch/dispatch.dart';
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/grid_entities.pb.dart';
import 'package:appflowy_backend/dispatch/dispatch.dart';
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/field_entities.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/grid_entities.pb.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
part 'field_service.freezed.dart';

View file

@ -1,4 +1,4 @@
import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/field_entities.pb.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'dart:async';

View file

@ -1,11 +1,11 @@
import 'package:app_flowy/core/grid_notification.dart';
import 'package:dartz/dartz.dart';
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/dart_notification.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/dart_notification.pb.dart';
import 'package:flowy_infra/notifier.dart';
import 'dart:async';
import 'dart:typed_data';
import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/field_entities.pb.dart';
typedef UpdateFieldNotifiedValue = Either<GridFieldChangesetPB, FlowyError>;

View file

@ -1,5 +1,5 @@
import 'package:flowy_sdk/protobuf/flowy-grid/date_type_option.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/date_type_option_entities.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/date_type_option.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/date_type_option_entities.pb.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'dart:async';

View file

@ -1,4 +1,4 @@
import 'package:flowy_sdk/protobuf/flowy-grid/select_type_option.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/select_type_option.pb.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'dart:async';

View file

@ -1,6 +1,6 @@
import 'package:flowy_sdk/log.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/multi_select_type_option.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/select_type_option.pb.dart';
import 'package:appflowy_backend/log.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/multi_select_type_option.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/select_type_option.pb.dart';
import 'dart:async';
import 'select_option_type_option_bloc.dart';
import 'type_option_context.dart';

View file

@ -1,5 +1,5 @@
import 'package:flowy_sdk/protobuf/flowy-grid/format.pbenum.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/number_type_option.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/format.pbenum.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/number_type_option.pb.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'dart:async';

View file

@ -1,4 +1,4 @@
import 'package:flowy_sdk/protobuf/flowy-grid/format.pbenum.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/format.pbenum.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'dart:async';

View file

@ -1,4 +1,4 @@
import 'package:flowy_sdk/protobuf/flowy-grid/select_type_option.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/select_type_option.pb.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'dart:async';

View file

@ -1,6 +1,6 @@
import 'package:flowy_sdk/log.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/select_type_option.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/single_select_type_option.pb.dart';
import 'package:appflowy_backend/log.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/select_type_option.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/single_select_type_option.pb.dart';
import 'dart:async';
import 'package:protobuf/protobuf.dart';
import 'select_option_type_option_bloc.dart';

View file

@ -1,15 +1,15 @@
import 'package:flowy_sdk/dispatch/dispatch.dart';
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/checkbox_type_option.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/checklist_type_option.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/date_type_option.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
import 'package:appflowy_backend/dispatch/dispatch.dart';
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/checkbox_type_option.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/checklist_type_option.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/date_type_option.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/field_entities.pb.dart';
import 'package:dartz/dartz.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/multi_select_type_option.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/number_type_option.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/single_select_type_option.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/text_type_option.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/url_type_option.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/multi_select_type_option.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/number_type_option.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/single_select_type_option.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/text_type_option.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/url_type_option.pb.dart';
import 'package:protobuf/protobuf.dart';
import 'type_option_data_controller.dart';

View file

@ -1,11 +1,11 @@
import 'package:app_flowy/plugins/grid/application/field/field_controller.dart';
import 'package:flowy_infra/notifier.dart';
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/field_entities.pb.dart';
import 'package:app_flowy/plugins/grid/application/field/field_service.dart';
import 'package:dartz/dartz.dart';
import 'package:protobuf/protobuf.dart' hide FieldInfo;
import 'package:flowy_sdk/log.dart';
import 'package:appflowy_backend/log.dart';
import 'type_option_context.dart';

View file

@ -1,8 +1,8 @@
import 'package:dartz/dartz.dart';
import 'package:flowy_sdk/dispatch/dispatch.dart';
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/cell_entities.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/select_type_option.pb.dart';
import 'package:appflowy_backend/dispatch/dispatch.dart';
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/cell_entities.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/select_type_option.pb.dart';
class TypeOptionFFIService {
final String gridId;

View file

@ -1,6 +1,6 @@
import 'package:app_flowy/plugins/grid/presentation/widgets/filter/filter_info.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/checkbox_filter.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/util.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/checkbox_filter.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/util.pb.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'dart:async';

View file

@ -1,6 +1,6 @@
import 'package:app_flowy/plugins/grid/presentation/widgets/filter/filter_info.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/checklist_filter.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/util.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/checklist_filter.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/util.pb.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'dart:async';

View file

@ -1,13 +1,13 @@
import 'package:app_flowy/plugins/grid/application/field/field_controller.dart';
import 'package:dartz/dartz.dart';
import 'package:flowy_sdk/protobuf/flowy-error/errors.pbserver.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/checkbox_filter.pbenum.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/checklist_filter.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/date_filter.pbenum.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/number_filter.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/select_option_filter.pbenum.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/text_filter.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-error/errors.pbserver.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/checkbox_filter.pbenum.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/checklist_filter.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/date_filter.pbenum.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/field_entities.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/number_filter.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/select_option_filter.pbenum.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/text_filter.pb.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'dart:async';

View file

@ -2,11 +2,11 @@ import 'dart:typed_data';
import 'package:app_flowy/core/grid_notification.dart';
import 'package:flowy_infra/notifier.dart';
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/dart_notification.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/filter_changeset.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/dart_notification.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/filter_changeset.pb.dart';
import 'package:dartz/dartz.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/util.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/util.pb.dart';
typedef UpdateFilterNotifiedValue
= Either<FilterChangesetNotificationPB, FlowyError>;

View file

@ -1,17 +1,17 @@
import 'package:dartz/dartz.dart';
import 'package:flowy_sdk/dispatch/dispatch.dart';
import 'package:flowy_sdk/log.dart';
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/checkbox_filter.pbserver.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/checklist_filter.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/date_filter.pbserver.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/grid_entities.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/number_filter.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/select_option_filter.pbserver.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/setting_entities.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/text_filter.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/util.pb.dart';
import 'package:appflowy_backend/dispatch/dispatch.dart';
import 'package:appflowy_backend/log.dart';
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/checkbox_filter.pbserver.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/checklist_filter.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/date_filter.pbserver.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/field_entities.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/grid_entities.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/number_filter.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/select_option_filter.pbserver.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/setting_entities.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/text_filter.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/util.pb.dart';
import 'package:fixnum/fixnum.dart' as $fixnum;
class FilterFFIService {
@ -197,8 +197,6 @@ class FilterFFIService {
required String filterId,
required FieldType fieldType,
}) {
TextFilterConditionPB.DoesNotContain.value;
final deleteFilterPayload = DeleteFilterPayloadPB.create()
..fieldId = fieldId
..filterId = filterId

View file

@ -1,7 +1,7 @@
import 'package:app_flowy/plugins/grid/presentation/widgets/filter/choicechip/select_option/select_option_loader.dart';
import 'package:app_flowy/plugins/grid/presentation/widgets/filter/filter_info.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/select_option_filter.pbserver.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/util.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/select_option_filter.pbserver.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/util.pb.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'dart:async';

View file

@ -1,8 +1,8 @@
import 'dart:async';
import 'package:app_flowy/plugins/grid/presentation/widgets/filter/choicechip/select_option/select_option_loader.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/select_type_option.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/field_entities.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/select_type_option.pb.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';

View file

@ -1,6 +1,6 @@
import 'package:app_flowy/plugins/grid/presentation/widgets/filter/filter_info.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/text_filter.pbserver.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/util.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/text_filter.pbserver.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/util.pb.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'dart:async';

View file

@ -0,0 +1,47 @@
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
part 'grid_accessory_bloc.freezed.dart';
class GridAccessoryMenuBloc
extends Bloc<GridAccessoryMenuEvent, GridAccessoryMenuState> {
final String viewId;
GridAccessoryMenuBloc({required this.viewId})
: super(GridAccessoryMenuState.initial(
viewId,
)) {
on<GridAccessoryMenuEvent>(
(event, emit) async {
event.when(
initial: () {},
toggleMenu: () {
emit(state.copyWith(isVisible: !state.isVisible));
},
);
},
);
}
}
@freezed
class GridAccessoryMenuEvent with _$GridAccessoryMenuEvent {
const factory GridAccessoryMenuEvent.initial() = _Initial;
const factory GridAccessoryMenuEvent.toggleMenu() = _MenuVisibleChange;
}
@freezed
class GridAccessoryMenuState with _$GridAccessoryMenuState {
const factory GridAccessoryMenuState({
required String viewId,
required bool isVisible,
}) = _GridAccessoryMenuState;
factory GridAccessoryMenuState.initial(
String viewId,
) =>
GridAccessoryMenuState(
viewId: viewId,
isVisible: false,
);
}

View file

@ -1,9 +1,9 @@
import 'dart:async';
import 'package:dartz/dartz.dart';
import 'package:equatable/equatable.dart';
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/protobuf.dart';
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/protobuf.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'field/field_controller.dart';

View file

@ -1,7 +1,7 @@
import 'package:app_flowy/plugins/grid/presentation/widgets/filter/filter_info.dart';
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/grid_entities.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/grid_entities.pb.dart';
import 'dart:async';
import 'package:dartz/dartz.dart';
import 'view/grid_view_cache.dart';

View file

@ -1,6 +1,6 @@
import 'package:app_flowy/plugins/grid/application/field/field_service.dart';
import 'package:flowy_sdk/log.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
import 'package:appflowy_backend/log.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/field_entities.pb.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'dart:async';

View file

@ -1,11 +1,11 @@
import 'package:dartz/dartz.dart';
import 'package:flowy_sdk/dispatch/dispatch.dart';
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/grid_entities.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/group.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/row_entities.pb.dart';
import 'package:appflowy_backend/dispatch/dispatch.dart';
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/field_entities.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/grid_entities.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/group.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/row_entities.pb.dart';
class GridFFIService {
final String gridId;

View file

@ -1,6 +1,6 @@
import 'package:app_flowy/plugins/grid/application/row/row_service.dart';
import 'package:flowy_sdk/log.dart';
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
import 'package:appflowy_backend/log.dart';
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'dart:async';

View file

@ -13,11 +13,11 @@ part 'row_bloc.freezed.dart';
class RowBloc extends Bloc<RowEvent, RowState> {
final RowFFIService _rowService;
final GridRowDataController _dataController;
final RowDataController _dataController;
RowBloc({
required RowInfo rowInfo,
required GridRowDataController dataController,
required RowDataController dataController,
}) : _rowService = RowFFIService(gridId: rowInfo.gridId),
_dataController = dataController,
super(RowState.initial(rowInfo, dataController.loadData())) {

View file

@ -1,9 +1,9 @@
import 'dart:collection';
import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart';
import 'package:app_flowy/plugins/grid/application/field/field_controller.dart';
import 'package:flowy_sdk/dispatch/dispatch.dart';
import 'package:flowy_sdk/log.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/protobuf.dart';
import 'package:appflowy_backend/dispatch/dispatch.dart';
import 'package:appflowy_backend/log.dart';
import 'package:appflowy_backend/protobuf/flowy-grid/protobuf.dart';
import 'package:flutter/foundation.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
@ -12,10 +12,13 @@ part 'row_cache.freezed.dart';
typedef RowUpdateCallback = void Function();
abstract class IGridRowFieldNotifier {
UnmodifiableListView<FieldInfo> get fields;
abstract class RowChangesetNotifierForward {
void onRowFieldsChanged(VoidCallback callback);
void onRowFieldChanged(void Function(FieldInfo) callback);
}
abstract class RowCacheDelegate {
UnmodifiableListView<FieldInfo> get fields;
void onRowDispose();
}
@ -33,8 +36,8 @@ class GridRowCache {
final RowList _rowList = RowList();
final GridCellCache _cellCache;
final IGridRowFieldNotifier _fieldNotifier;
final _RowChangesetNotifier _rowChangeReasonNotifier;
final RowCacheDelegate _delegate;
final RowChangesetNotifier _rowChangeReasonNotifier;
UnmodifiableListView<RowInfo> get visibleRows {
var visibleRows = [..._rowList.rows];
@ -46,10 +49,11 @@ class GridRowCache {
GridRowCache({
required this.gridId,
required this.rows,
required IGridRowFieldNotifier notifier,
required RowChangesetNotifierForward notifier,
required RowCacheDelegate delegate,
}) : _cellCache = GridCellCache(gridId: gridId),
_rowChangeReasonNotifier = _RowChangesetNotifier(),
_fieldNotifier = notifier {
_rowChangeReasonNotifier = RowChangesetNotifier(),
_delegate = delegate {
//
notifier.onRowFieldsChanged(() => _rowChangeReasonNotifier
.receive(const RowsChangedReason.fieldDidChange()));
@ -65,7 +69,7 @@ class GridRowCache {
}
Future<void> dispose() async {
_fieldNotifier.onRowDispose();
_delegate.onRowDispose();
_rowChangeReasonNotifier.dispose();
await _cellCache.dispose();
}
@ -81,6 +85,23 @@ class GridRowCache {
_showRows(changeset.visibleRows);
}
void reorderAllRows(List<String> rowIds) {
_rowList.reorderWithRowIds(rowIds);
_rowChangeReasonNotifier.receive(const RowsChangedReason.reorderRows());
}
void reorderSingleRow(ReorderSingleRowPB reorderRow) {
final rowInfo = _rowList.get(reorderRow.rowId);
if (rowInfo != null) {
_rowList.moveRow(
reorderRow.rowId, reorderRow.oldIndex, reorderRow.newIndex);
_rowChangeReasonNotifier.receive(RowsChangedReason.reorderSingleRow(
reorderRow,
rowInfo,
));
}
}
void _deleteRows(List<String> deletedRowIds) {
for (final rowId in deletedRowIds) {
final deletedRow = _rowList.remove(rowId);
@ -208,7 +229,7 @@ class GridRowCache {
GridCellMap _makeGridCells(String rowId, RowPB? row) {
// ignore: prefer_collection_literals
var cellDataMap = GridCellMap();
for (final field in _fieldNotifier.fields) {
for (final field in _delegate.fields) {
if (field.visibility) {
cellDataMap[field.id] = GridCellIdentifier(
rowId: rowId,
@ -247,16 +268,16 @@ class GridRowCache {
RowInfo buildGridRow(RowPB rowPB) {
return RowInfo(
gridId: gridId,
fields: _fieldNotifier.fields,
fields: _delegate.fields,
rowPB: rowPB,
);
}
}
class _RowChangesetNotifier extends ChangeNotifier {
class RowChangesetNotifier extends ChangeNotifier {
RowsChangedReason reason = const InitialListState();
_RowChangesetNotifier();
RowChangesetNotifier();
void receive(RowsChangedReason newReason) {
reason = newReason;
@ -266,6 +287,8 @@ class _RowChangesetNotifier extends ChangeNotifier {
update: (_) => notifyListeners(),
fieldDidChange: (_) => notifyListeners(),
initial: (_) {},
reorderRows: (_) => notifyListeners(),
reorderSingleRow: (_) => notifyListeners(),
);
}
}
@ -292,6 +315,9 @@ class RowsChangedReason with _$RowsChangedReason {
const factory RowsChangedReason.update(UpdatedIndexMap indexs) = _Update;
const factory RowsChangedReason.fieldDidChange() = _FieldDidChange;
const factory RowsChangedReason.initial() = InitialListState;
const factory RowsChangedReason.reorderRows() = _ReorderRows;
const factory RowsChangedReason.reorderSingleRow(
ReorderSingleRowPB reorderRow, RowInfo rowInfo) = _ReorderSingleRow;
}
class InsertedIndex {

View file

@ -7,13 +7,13 @@ import 'row_cache.dart';
typedef OnRowChanged = void Function(GridCellMap, RowsChangedReason);
class GridRowDataController extends GridCellBuilderDelegate {
class RowDataController extends GridCellBuilderDelegate {
final RowInfo rowInfo;
final List<VoidCallback> _onRowChangedListeners = [];
final GridFieldController _fieldController;
final GridRowCache _rowCache;
GridRowDataController({
RowDataController({
required this.rowInfo,
required GridFieldController fieldController,
required GridRowCache rowCache,

View file

@ -7,7 +7,7 @@ import 'row_data_controller.dart';
part 'row_detail_bloc.freezed.dart';
class RowDetailBloc extends Bloc<RowDetailEvent, RowDetailState> {
final GridRowDataController dataController;
final RowDataController dataController;
RowDetailBloc({
required this.dataController,

Some files were not shown because too many files have changed in this diff Show more