diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml
index 40f51c8132..d3dd050e2c 100644
--- a/.github/workflows/ci.yaml
+++ b/.github/workflows/ci.yaml
@@ -18,7 +18,7 @@ jobs:
- os: ubuntu-latest
flutter_profile: development-linux-x86
- os: macos-latest
- flutter_profile: development-mac
+ flutter_profile: development-mac-x86_64
runs-on: ${{ matrix.os }}
steps:
@@ -34,6 +34,7 @@ jobs:
with:
channel: 'stable'
cache: true
+ flutter-version: '3.0.0'
- name: Cache Cargo
uses: actions/cache@v2
diff --git a/.github/workflows/dart_lint.yml b/.github/workflows/dart_lint.yml
index 81460cec1c..ca0536906e 100644
--- a/.github/workflows/dart_lint.yml
+++ b/.github/workflows/dart_lint.yml
@@ -23,7 +23,7 @@ jobs:
uses: actions/checkout@v2
- uses: subosito/flutter-action@v1
with:
- flutter-version: '2.10.0'
+ flutter-version: '3.0.0'
channel: "stable"
- name: Deps Flutter
run: flutter packages pub get
diff --git a/.github/workflows/dart_test.yml b/.github/workflows/dart_test.yml
index db479d2905..9938f02091 100644
--- a/.github/workflows/dart_test.yml
+++ b/.github/workflows/dart_test.yml
@@ -25,6 +25,7 @@ jobs:
- uses: subosito/flutter-action@v2
with:
channel: 'stable'
+ flutter-version: '3.0.0'
cache: true
- name: Cache Cargo
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 93dedaa43d..a2c9c7b133 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -50,6 +50,7 @@ jobs:
uses: subosito/flutter-action@v2
with:
channel: 'stable'
+ flutter-version: '3.0.0'
- name: Pre build
working-directory: frontend
@@ -98,6 +99,7 @@ jobs:
uses: subosito/flutter-action@v2
with:
channel: 'stable'
+ flutter-version: '3.0.0'
- name: Pre build
working-directory: frontend
@@ -111,7 +113,7 @@ jobs:
working-directory: frontend
run: |
flutter config --enable-macos-desktop
- cargo make --env APP_VERSION=${{ github.ref_name }} --profile production-mac-x86 appflowy
+ cargo make --env APP_VERSION=${{ github.ref_name }} --profile production-mac-x86_64 appflowy
- name: Archive macOS app
working-directory: ${{ env.MACOS_APP_RELEASE_PATH }}
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a5ac013c35..5ee49d36f3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,40 @@
# Release Notes
+## Version 0.0.4 - 2022-06-06
+- Drag to adjust the width of a column
+- Upgrade to Flutter 3.0
+- Native support for M1 chip
+- Date supports time formats
+- New property: URL
+- Keyboard shortcuts support for Grid: press Enter to leave the edit mode; control c/v to copy-paste cell values
+
+### Bug Fixes
+- Fixed some bugs
+
+
+## Version 0.0.4 - beta.3 - 2022-05-02
+- Drag to reorder app/ view/ field
+- Row record open as a page
+- Auto resize the height of the row in the grid
+- Support more number formats
+- Search column options, supporting Single select, Multi-select, and number format
+
+
+
+
+### Bug Fixes & Improvements
+- Improved row/cell data cache
+- Fixed some bugs
+
+
+## Version 0.0.4 - beta.2 - 2022-04-11
+
+ - Support properties: Text, Number, Date, Checkbox, Select, Multi-select
+ - Insert / delete rows
+ - Add / delete / hide columns
+ - Edit property
+ 
+
## Version 0.0.4 - beta.1 - 2022-04-08
v0.0.4 - beta.1 is pre-release
diff --git a/frontend/.vscode/launch.json b/frontend/.vscode/launch.json
index 66fc02b1a1..4328389d39 100644
--- a/frontend/.vscode/launch.json
+++ b/frontend/.vscode/launch.json
@@ -5,40 +5,60 @@
"version": "0.2.0",
"configurations": [
{
- "name": "app_flowy",
+ // This task builds the Rust and Dart code of AppFlowy.
+ "name": "AF: Build All",
"request": "launch",
"program": "./lib/main.dart",
"type": "dart",
- "preLaunchTask": "build_flowy_sdk",
+ "preLaunchTask": "AF: build_flowy_sdk",
"env":{
"RUST_LOG":"info"
},
"cwd": "${workspaceRoot}/app_flowy"
},
{
- "name": "app_flowy(trace)",
+ // This task only builds the Dart code of AppFlowy.
+ "name": "AF: Build Dart Only",
+ "request": "launch",
+ "program": "${workspaceRoot}/lib/main.dart",
+ "type": "dart",
+ "env": {
+ "RUST_LOG": "debug"
+ },
+ "cwd": "${workspaceRoot}"
+ },
+ {
+ // This task builds will:
+ // - call the clean task,
+ // - rebuild all the generated Files (including freeze and language files)
+ // - rebuild the the Rust and Dart code of AppFlowy.
+ "name": "AF: Clean + Rebuild All",
"request": "launch",
"program": "./lib/main.dart",
"type": "dart",
- "preLaunchTask": "build_flowy_sdk",
+ "preLaunchTask": "AF: Clean + Rebuild All",
+ "env":{
+ "RUST_LOG":"info"
+ },
+ "cwd": "${workspaceRoot}/app_flowy"
+ },
+
+ {
+ "name": "AF: Build All (rustlog: trace)",
+ "request": "launch",
+ "program": "./lib/main.dart",
+ "type": "dart",
+ "preLaunchTask": "AF: build_flowy_sdk",
"env":{
"RUST_LOG":"trace"
},
"cwd": "${workspaceRoot}/app_flowy"
},
{
- "name": "app_flowy (profile mode)",
+ "name": "AF: app_flowy (profile mode)",
"request": "launch",
"type": "dart",
"flutterMode": "profile"
},
- {
- "name": "Generate Language Files",
- "request": "launch",
- "program": "./lib/main.dart",
- "type": "dart",
- "preLaunchTask": "Generate Language Files",
- "cwd": "${workspaceRoot}/app_flowy/"
- },
]
-}
\ No newline at end of file
+}
diff --git a/frontend/.vscode/tasks.json b/frontend/.vscode/tasks.json
index e902e3dfd5..aec5955c19 100644
--- a/frontend/.vscode/tasks.json
+++ b/frontend/.vscode/tasks.json
@@ -10,13 +10,35 @@
// ${cwd}: the current working directory of the spawned process
"tasks": [
{
- "label": "build_flowy_sdk",
+ "label": "AF: Clean + Rebuild All",
+ "type": "shell",
+ "dependsOrder": "sequence",
+ "dependsOn": [
+ "AF: Clean",
+ "AF: Flutter Pub",
+ "AF: Flutter Package Get",
+ "AF: Generate Language Files",
+ "AF: Generate Freezed Files",
+ "AF: build_flowy_sdk"
+ ],
+ "group": {
+ "kind": "build",
+ "isDefault": true,
+ },
+ "presentation": {
+ "reveal": "always",
+ "panel": "new"
+ }
+
+ },
+ {
+ "label": "AF: build_flowy_sdk",
"type": "shell",
"command": "sh ./scripts/build_sdk.sh",
"windows": {
"options": {
"env": {
- "FLOWY_DEV_ENV": "Windows",
+ "FLOWY_DEV_ENV": "Windows"
},
"shell": {
"executable": "cmd.exe",
@@ -31,27 +53,67 @@
"linux": {
"options": {
"env": {
- "FLOWY_DEV_ENV": "Linux-x86",
+ "FLOWY_DEV_ENV": "Linux-x86"
}
- },
+ }
},
"osx": {
"options": {
"env": {
- "FLOWY_DEV_ENV": "macOS",
+ "FLOWY_DEV_ENV": "macOS"
}
- },
+ }
},
"group": "build",
"options": {
"cwd": "${workspaceFolder}"
- },
- // "problemMatcher": [
- // "$rustc"
- // ],
+ }
},
{
- "label": "Generate Language Files",
+ "label": "AF: Code Gen",
+ "type": "shell",
+ "dependsOrder": "sequence",
+ "dependsOn": [
+ "AF: Flutter Pub",
+ "AF: Flutter Package Get",
+ "AF: Generate Language Files",
+ "AF: Generate Freezed Files"
+ ],
+ "group": {
+ "kind": "build",
+ "isDefault": true,
+ },
+ "presentation": {
+ "reveal": "always",
+ "panel": "new"
+ }
+ },
+ {
+ "label": "AF: Flutter Pub",
+ "type": "shell",
+ "command": "flutter pub get",
+ "options": {
+ "cwd": "${workspaceFolder}/app_flowy"
+ }
+ },
+ {
+ "label": "AF: Flutter Package Get",
+ "type": "shell",
+ "command": "flutter packages pub get",
+ "options": {
+ "cwd": "${workspaceFolder}/app_flowy"
+ }
+ },
+ {
+ "label": "AF: Generate Freezed Files",
+ "type": "shell",
+ "command": "flutter pub run build_runner build --delete-conflicting-outputs",
+ "options": {
+ "cwd": "${workspaceFolder}/app_flowy"
+ }
+ },
+ {
+ "label": "AF: Generate Language Files",
"type": "shell",
"command": "sh ./scripts/generate_language_files.sh",
"windows": {
@@ -69,10 +131,10 @@
"group": "build",
"options": {
"cwd": "${workspaceFolder}"
- },
+ }
},
{
- "label": "Clean",
+ "label": "AF: Clean",
"type": "shell",
"command": "sh ./scripts/clean.sh",
"windows": {
@@ -90,7 +152,19 @@
"group": "build",
"options": {
"cwd": "${workspaceFolder}"
- },
+ }
+ },
+ {
+ "label": "AF: flutter build aar",
+ "type": "flutter",
+ "command": "flutter",
+ "args": [
+ "build",
+ "aar"
+ ],
+ "group": "build",
+ "problemMatcher": [],
+ "detail": "app_flowy"
}
]
-}
\ No newline at end of file
+}
diff --git a/frontend/Makefile.toml b/frontend/Makefile.toml
index 7c82e17ba7..42708d7c32 100644
--- a/frontend/Makefile.toml
+++ b/frontend/Makefile.toml
@@ -7,6 +7,7 @@ extend = [
{ path = "scripts/makefile/docker.toml" },
{ path = "scripts/makefile/env.toml" },
{ path = "scripts/makefile/flutter.toml" },
+ { path = "scripts/makefile/tool.toml" },
]
[config]
@@ -44,7 +45,15 @@ APP_ENVIRONMENT = "local"
FLUTTER_FLOWY_SDK_PATH="app_flowy/packages/flowy_sdk"
PROTOBUF_DERIVE_CACHE="../shared-lib/flowy-derive/src/derive_cache/derive_cache.rs"
-[env.development-mac]
+[env.development-mac-arm64]
+RUST_LOG = "info"
+TARGET_OS = "macos"
+RUST_COMPILE_TARGET = "aarch64-apple-darwin"
+BUILD_FLAG = "debug"
+FLUTTER_OUTPUT_DIR = "Debug"
+PRODUCT_EXT = "app"
+
+[env.development-mac-x86_64]
RUST_LOG = "info"
TARGET_OS = "macos"
RUST_COMPILE_TARGET = "x86_64-apple-darwin"
@@ -52,21 +61,23 @@ BUILD_FLAG = "debug"
FLUTTER_OUTPUT_DIR = "Debug"
PRODUCT_EXT = "app"
-[env.production-mac-aarch64]
+[env.production-mac-arm64]
BUILD_FLAG = "release"
TARGET_OS = "macos"
RUST_COMPILE_TARGET = "aarch64-apple-darwin"
FLUTTER_OUTPUT_DIR = "Release"
PRODUCT_EXT = "app"
APP_ENVIRONMENT = "production"
+BUILD_ARCHS = "arm64"
-[env.production-mac-x86]
+[env.production-mac-x86_64]
BUILD_FLAG = "release"
TARGET_OS = "macos"
RUST_COMPILE_TARGET = "x86_64-apple-darwin"
FLUTTER_OUTPUT_DIR = "Release"
PRODUCT_EXT = "app"
APP_ENVIRONMENT = "production"
+BUILD_ARCHS = "x86_64"
[env.development-windows-x86]
TARGET_OS = "windows"
@@ -137,6 +148,7 @@ script = [
echo PRODUCT_EXT: ${PRODUCT_EXT}
echo APP_ENVIRONMENT: ${APP_ENVIRONMENT}
echo ${platforms}
+ echo ${BUILD_ARCHS}
'''
]
script_runner = "@shell"
diff --git a/frontend/app_flowy/.vscode/launch.json b/frontend/app_flowy/.vscode/launch.json
deleted file mode 100644
index b271a1e6a1..0000000000
--- a/frontend/app_flowy/.vscode/launch.json
+++ /dev/null
@@ -1,36 +0,0 @@
-{
- // Use IntelliSense to learn about possible attributes.
- // Hover to view descriptions of existing attributes.
- // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
- "version": "0.2.0",
- "configurations": [
- {
- "name": "app_flowy",
- "request": "launch",
- "program": "${workspaceRoot}/lib/main.dart",
- "type": "dart",
- "preLaunchTask": "build_flowy_sdk",
- "env": {
- "RUST_LOG": "debug"
- },
- "cwd": "${workspaceRoot}"
- },
- {
- "name": "app_flowy(trace)",
- "request": "launch",
- "program": "${workspaceRoot}/lib/main.dart",
- "type": "dart",
- "preLaunchTask": "build_flowy_sdk",
- "env": {
- "RUST_LOG": "trace"
- },
- "cwd": "${workspaceRoot}"
- },
- {
- "name": "app_flowy (profile mode)",
- "request": "launch",
- "type": "dart",
- "flutterMode": "profile"
- },
- ]
-}
\ No newline at end of file
diff --git a/frontend/app_flowy/.vscode/settings.json b/frontend/app_flowy/.vscode/settings.json
deleted file mode 100644
index 13845cc225..0000000000
--- a/frontend/app_flowy/.vscode/settings.json
+++ /dev/null
@@ -1,26 +0,0 @@
-{
- "[dart]": {
- "editor.formatOnSave": true,
- "editor.formatOnType": true,
- "editor.rulers": [
- 120
- ],
- "editor.selectionHighlight": false,
- "editor.suggest.snippetsPreventQuickSuggestions": false,
- "editor.suggestSelection": "first",
- "editor.tabCompletion": "onlySnippets",
- "editor.wordBasedSuggestions": false
- },
- "svgviewer.enableautopreview": true,
- "svgviewer.previewcolumn": "Active",
- "svgviewer.showzoominout": true,
- "editor.wordWrapColumn": 120,
- "editor.minimap.maxColumn": 140,
- "prettier.printWidth": 140,
- "editor.wordWrap": "wordWrapColumn",
- "dart.lineLength": 120,
- "files.associations": {
- "*.log.*": "log"
- },
- "editor.formatOnSave": true,
-}
\ No newline at end of file
diff --git a/frontend/app_flowy/.vscode/tasks.json b/frontend/app_flowy/.vscode/tasks.json
deleted file mode 100644
index f46aac1085..0000000000
--- a/frontend/app_flowy/.vscode/tasks.json
+++ /dev/null
@@ -1,129 +0,0 @@
-{
- "version": "2.0.0",
- // https://code.visualstudio.com/docs/editor/tasks
- // https://gist.github.com/deadalusai/9e13e36d61ec7fb72148
- // ${workspaceRoot}: the root folder of the team
- // ${file}: the current opened file
- // ${fileBasename}: the current opened file's basename
- // ${fileDirname}: the current opened file's dirname
- // ${fileExtname}: the current opened file's extension
- // ${cwd}: the current working directory of the spawned process
- "tasks": [
- {
- "label": "build_flowy_sdk",
- "type": "shell",
- "command": "sh ./scripts/build_sdk.sh",
- "windows": {
- "options": {
- "env": {
- "FLOWY_DEV_ENV": "Windows",
- },
- "shell": {
- "executable": "cmd.exe",
- "args": [
- "/d",
- "/c",
- ".\\scripts\\build_sdk.cmd"
- ]
- }
- }
- },
- "linux": {
- "options": {
- "env": {
- "FLOWY_DEV_ENV": "Linux-x86",
- }
- },
- },
- "osx": {
- "options": {
- "env": {
- "FLOWY_DEV_ENV": "macOS",
- }
- },
- },
- "group": "build",
- "options": {
- "cwd": "${workspaceFolder}/../"
- },
- // "problemMatcher": [
- // "$rustc"
- // ],
- },
- {
- "label": "Code Gen",
- "type": "shell",
- "dependsOn": [
- "Flutter Pub",
- "Flutter Package Get",
- "Generate Language Files",
- "Generate Freezed Files"
- ],
- "group": {
- "kind": "build",
- "isDefault": true,
- },
- "dependsOrder": "sequence",
- "presentation": {
- "reveal": "always",
- "panel": "new"
- },
- },
- {
- "label": "Flutter Pub",
- "type": "shell",
- "command": "flutter pub get",
- },
- {
- "label": "Flutter Package Get",
- "type": "shell",
- "command": "flutter packages pub get",
- },
- {
- "label": "Generate Freezed Files",
- "type": "shell",
- "command": "flutter pub run build_runner build --delete-conflicting-outputs",
- },
- {
- "label": "Generate Language Files",
- "type": "shell",
- "command": "sh ./scripts/generate_language_files.sh",
- "windows": {
- "options": {
- "shell": {
- "executable": "cmd.exe",
- "args": [
- "/d",
- "/c",
- ".\\scripts\\generate_language_files.cmd"
- ]
- }
- }
- },
- "group": "build",
- "options": {
- "cwd": "${workspaceFolder}/../"
- },
- },
- {
- "label": "Clean",
- "type": "shell",
- "command": "sh ./scripts/clean.sh",
- "windows": {
- "options": {
- "shell": {
- "executable": "cmd.exe",
- "args": [
- "/d",
- "/c",
- ".\\scripts\\clean.cmd"
- ]
- }
- }
- },
- "options": {
- "cwd": "${workspaceFolder}/../"
- },
- }
- ]
-}
\ No newline at end of file
diff --git a/frontend/app_flowy/assets/images/grid/field/url.svg b/frontend/app_flowy/assets/images/grid/field/url.svg
new file mode 100644
index 0000000000..f00f5c7aa2
--- /dev/null
+++ b/frontend/app_flowy/assets/images/grid/field/url.svg
@@ -0,0 +1,3 @@
+
diff --git a/frontend/app_flowy/assets/translations/en.json b/frontend/app_flowy/assets/translations/en.json
index cb081c4ab8..521321d54f 100644
--- a/frontend/app_flowy/assets/translations/en.json
+++ b/frontend/app_flowy/assets/translations/en.json
@@ -96,6 +96,12 @@
"lightMode": "Switch to Light mode",
"darkMode": "Switch to Dark mode"
},
+ "notifications": {
+ "export": {
+ "markdown": "Exported Note To Markdown",
+ "path": "Documents/flowy"
+ }
+ },
"contactsPage": {
"title": "Contacts",
"whatsHappening": "What's happening this week?",
@@ -160,6 +166,7 @@
"numberFieldName": "Numbers",
"singleSelectFieldName": "Select",
"multiSelectFieldName": "Multiselect",
+ "urlFieldName": "URL",
"numberFormat": " Number format",
"dateFormat": " Date format",
"includeTime": " Include time",
@@ -168,6 +175,7 @@
"dateFormatLocal": "Month/Month/Day",
"dateFormatUS": "Month/Month/Day",
"timeFormat": " Time format",
+ "invalidTimeFormat": "Invalid format",
"timeFormatTwelveHour": "12 hour",
"timeFormatTwentyFourHour": "24 hour",
"addSelectOption": "Add an option",
@@ -178,7 +186,8 @@
"row": {
"duplicate": "Duplicate",
"delete": "Delete",
- "textPlaceholder": "Empty"
+ "textPlaceholder": "Empty",
+ "copyProperty": "Copied property to clipboard"
},
"selectOption": {
"create": "Create",
@@ -200,5 +209,9 @@
},
"document":{
"menuName":"Doc"
+ "date": {
+ "timeHintTextInTwelveHour": "12:00 AM",
+ "timeHintTextInTwentyFourHour": "12:00"
+ }
}
}
diff --git a/frontend/app_flowy/assets/translations/pt-BR.json b/frontend/app_flowy/assets/translations/pt-BR.json
index e2f0b27032..8ae5818b60 100644
--- a/frontend/app_flowy/assets/translations/pt-BR.json
+++ b/frontend/app_flowy/assets/translations/pt-BR.json
@@ -7,11 +7,11 @@
"letsGoButtonText": "Vamos lá",
"title": "Título",
"signUp": {
- "buttonText": "Inscreve-se",
- "title": "Inscrever-se @:appName",
+ "buttonText": "Se inscreva",
+ "title": "Se inscreva no @:appName",
"getStartedText": "Começar",
- "emptyPasswordError": "Senha não pode ser em branco.",
- "repeatPasswordEmptyError": "Confirmar a senha não pode ser em branco.",
+ "emptyPasswordError": "Senha não pode estar em branco.",
+ "repeatPasswordEmptyError": "Confirmar a senha não pode estar em branco.",
"unmatchedPasswordError": "As senhas não conferem.",
"alreadyHaveAnAccount": "Já possui uma conta?",
"emailHint": "Email",
@@ -19,14 +19,14 @@
"repeatPasswordHint": "Confirme a senha"
},
"signIn": {
- "loginTitle": "Login to @:appName",
+ "loginTitle": "Entre no @:appName",
"loginButtonText": "Login",
"buttonText": "Entre",
"forgotPassword": "Esqueceu a senha?",
"emailHint": "Email",
"passwordHint": "Senha",
"dontHaveAnAccount": "Não possui uma conta?",
- "repeatPasswordEmptyError": "Confirmar a senha não pode ser em branco.",
+ "repeatPasswordEmptyError": "Confirmar a senha não pode estar em branco.",
"unmatchedPasswordError": "As senhas não conferem."
},
"workspace": {
@@ -67,7 +67,7 @@
"whatsNew": "O que há de novo?",
"help": "Ajuda & Suporte",
"debug": {
- "name": "Informação de debug",
+ "name": "Informação de depuração",
"success": "Copiar informação de debug para o clipboard!",
"fail": "Falha em copiar a informação de debug para o clipboard"
}
@@ -104,7 +104,7 @@
},
"button": {
"OK": "OK",
- "Cancel": "Canelar",
+ "Cancel": "Cancelar",
"signIn": "Entrar",
"signOut": "Sair",
"complete": "Completar",
@@ -143,4 +143,5 @@
}
}
}
-
\ No newline at end of file
+
+
diff --git a/frontend/app_flowy/assets/translations/pt-PT.json b/frontend/app_flowy/assets/translations/pt-PT.json
new file mode 100644
index 0000000000..3aa37ee230
--- /dev/null
+++ b/frontend/app_flowy/assets/translations/pt-PT.json
@@ -0,0 +1,146 @@
+{
+ "appName": "AppFlowy",
+ "defaultUsername": "Me",
+ "welcomeText": "Bem vindo ao @:appName",
+ "githubStarText": "Star on GitHub",
+ "subscribeNewsletterText": "Inscreve-te ao Newsletter",
+ "letsGoButtonText": "Bora",
+ "title": "Título",
+ "signUp": {
+ "buttonText": "Inscreve-te",
+ "title": "Inscreve-te ao @:appName",
+ "getStartedText": "Começar",
+ "emptyPasswordError": "A palavra-passe não pode estar em branco.",
+ "repeatPasswordEmptyError": "Confirmar a palavra-passe não pode estar em branco.",
+ "unmatchedPasswordError": "As palavras-passes não coincidem.",
+ "alreadyHaveAnAccount": "Já possuis uma conta?",
+ "emailHint": "Email",
+ "passwordHint": "Password",
+ "repeatPasswordHint": "Confirma a tua password"
+ },
+ "signIn": {
+ "loginTitle": "Entre no @:appName",
+ "loginButtonText": "Login",
+ "buttonText": "Entre",
+ "forgotPassword": "Esqueceste-te da tua palavra-passe?",
+ "emailHint": "Email",
+ "passwordHint": "Palavra-passe",
+ "dontHaveAnAccount": "Não possuis uma conta?",
+ "repeatPasswordEmptyError": "Confirmar a palavra-passe não pode estar em branco.",
+ "unmatchedPasswordError": "As palavras-passes não conferem."
+ },
+ "workspace": {
+ "create": "Cria um ambiente de trabalho",
+ "hint": "ambiente de trabalho",
+ "notFoundError": "Ambiente de trabalho não encontrada"
+ },
+ "shareAction": {
+ "buttonText": "Partilhar",
+ "workInProgress": "Em breve",
+ "markdown": "Markdown",
+ "copyLink": "Copiar o link"
+ },
+ "disclosureAction": {
+ "rename": "Renomear",
+ "delete": "Apagar",
+ "duplicate": "Duplicar"
+ },
+ "blankPageTitle": "Página em branco",
+ "newPageText": "Nova página",
+ "trash": {
+ "text": "Lixo",
+ "restoreAll": "Restaurar todos",
+ "deleteAll": "Apagar todos",
+ "pageHeader": {
+ "fileName": "Nome do ficheiro",
+ "lastModified": "Última modificação",
+ "created": "Criado"
+ }
+ },
+ "deletePagePrompt": {
+ "text": "Esta página está no lixo",
+ "restore": "Restaurar a página",
+ "deletePermanent": "Apagar permanentemente"
+ },
+ "dialogCreatePageNameHint": "Nome da página",
+ "questionBubble": {
+ "whatsNew": "O que há de novo?",
+ "help": "Ajuda & Suporte",
+ "debug": {
+ "name": "Informação de depuração",
+ "success": "Copiar informação de depuração para o clipboard!",
+ "fail": "Falha em copiar a informação de depuração para o clipboard"
+ }
+ },
+ "menuAppHeader": {
+ "addPageTooltip": "Adiciona uma nova página.",
+ "defaultNewPageName": "Sem título",
+ "renameDialog": "Renomear"
+ },
+ "toolbar": {
+ "undo": "Desfazer",
+ "redo": "Refazer",
+ "bold": "Negrito",
+ "italic": "Itálico",
+ "underline": "Sublinhado",
+ "strike": "Riscado",
+ "numList": "Lista numerada",
+ "bulletList": "Lista com marcadores",
+ "checkList": "Lista de verificação",
+ "inlineCode": "Embutir código",
+ "quote": "Citação em bloco",
+ "header": "Cabeçalho",
+ "highlight": "Realçar"
+ },
+ "tooltip": {
+ "lightMode": "Mudar para o modo Claro.",
+ "darkMode": "Mudar para o modo Escuro."
+ },
+ "contactsPage": {
+ "title": "Conctatos",
+ "whatsHappening": "O que está a acontecer nesta semana?",
+ "addContact": "Adicionar um conctato",
+ "editContact": "Editar um conctato"
+ },
+ "button": {
+ "OK": "OK",
+ "Cancel": "Cancelar",
+ "signIn": "Entrar",
+ "signOut": "Sair",
+ "complete": "Completar",
+ "save": "Guardar"
+ },
+ "label": {
+ "welcome": "Bem vindo!",
+ "firstName": "Nome",
+ "middleName": "Nome do Meio",
+ "lastName": "Apelido",
+ "stepX": "Passo {X}"
+ },
+ "oAuth": {
+ "err": {
+ "failedTitle": "Erro ao conectar à sua conta.",
+ "failedMsg": "Verifica se concluiste o processo de login no teu navegador."
+ },
+ "google": {
+ "title": "GOOGLE SIGN-IN",
+ "instruction1": "Para importar os teus Conctatos do Google, tens de autorizar esta aplicação usando o teu navegador web.",
+ "instruction2": "Copia este código para a tua área de transferências clicando no ícone ou selecionando o texto:",
+ "instruction3": "Navega até o link a seguir no seu navegador e digite o código acima:",
+ "instruction4": "Clica no botão abaixo ao concluir a inscrição:"
+ }
+ },
+ "settings": {
+ "title": "Definições",
+ "menu": {
+ "appearance": "Aparência",
+ "language": "Idioma",
+ "open": "Abrir as Definições"
+ },
+ "appearance": {
+ "lightLabel": "Modo Claro",
+ "darkLabel": "Modo Escuro"
+ }
+ }
+ }
+
diff --git a/frontend/app_flowy/assets/translations/ru-RU.json b/frontend/app_flowy/assets/translations/ru-RU.json
index d729c0a737..65e61347e6 100644
--- a/frontend/app_flowy/assets/translations/ru-RU.json
+++ b/frontend/app_flowy/assets/translations/ru-RU.json
@@ -141,6 +141,68 @@
"lightLabel": "Светлая тема",
"darkLabel": "Тёмная тема"
}
+ },
+ "grid": {
+ "settings": {
+ "filter": "Фильтр",
+ "sortBy": "Сортировать",
+ "Properties": "Свойства"
+ },
+ "field": {
+ "hide": "Скрыть",
+ "insertLeft": "Вставить слева",
+ "insertRight": "Вставить справа",
+ "duplicate": "Дублировать",
+ "delete": "Удалить",
+ "textFieldName": "Текст",
+ "checkboxFieldName": "Checkbox",
+ "dateFieldName": "Дата",
+ "numberFieldName": "Число",
+ "singleSelectFieldName": "Выбор",
+ "multiSelectFieldName": "Выбор многих",
+ "urlFieldName": "URL",
+ "numberFormat": " Формат числа",
+ "dateFormat": " Формат даты",
+ "includeTime": " Время",
+ "dateFormatFriendly": "День Месяц, Год",
+ "dateFormatISO": "Год-Месяц-День",
+ "dateFormatLocal": "Год/Месяц/День",
+ "dateFormatUS": "Год/Месяц/День",
+ "timeFormat": " Форматировать время",
+ "invalidTimeFormat": "Неверный формат",
+ "timeFormatTwelveHour": "12 часов",
+ "timeFormatTwentyFourHour": "24 часа",
+ "addSelectOption": "Добавить вариант",
+ "optionTitle": "Варианты",
+ "addOption": "Добавить",
+ "editProperty": "Редактировать свойство"
+ },
+ "row": {
+ "duplicate": "Дублировать",
+ "delete": "Удалить",
+ "textPlaceholder": "Пусто",
+ "copyProperty": "Свойство скопировано"
+ },
+ "selectOption": {
+ "create": "Создать",
+ "purpleColor": "Фиолетовый",
+ "pinkColor": "Розовый",
+ "lightPinkColor": "Светло-розовый",
+ "orangeColor": "Оранжевый",
+ "yellowColor": "Желтый",
+ "limeColor": "Ярко-зелёный",
+ "greenColor": "Зелёный",
+ "aquaColor": "Морской волны",
+ "blueColor": "Синий",
+ "deleteTag": "Удалить вариант",
+ "colorPannelTitle": "Цвета",
+ "pannelTitle": "Выберите или создайте вариант",
+ "searchOption": "Поиск"
+ },
+ "date": {
+ "timeHintTextInTwelveHour": "12:00 AM",
+ "timeHintTextInTwentyFourHour": "12:00"
+ }
}
}
\ No newline at end of file
diff --git a/frontend/app_flowy/lib/core/frameless_window.dart b/frontend/app_flowy/lib/core/frameless_window.dart
new file mode 100644
index 0000000000..a7d6417cd3
--- /dev/null
+++ b/frontend/app_flowy/lib/core/frameless_window.dart
@@ -0,0 +1,67 @@
+import 'package:flutter/services.dart';
+import 'package:flutter/material.dart';
+import 'dart:io' show Platform;
+
+class CocoaWindowChannel {
+ CocoaWindowChannel._();
+
+ final MethodChannel _channel = const MethodChannel("flutter/cocoaWindow");
+
+ static final CocoaWindowChannel instance = CocoaWindowChannel._();
+
+ Future setWindowPosition(Offset offset) async {
+ await _channel.invokeMethod("setWindowPosition", [offset.dx, offset.dy]);
+ }
+
+ Future> getWindowPosition() async {
+ final raw = await _channel.invokeMethod("getWindowPosition");
+ final arr = raw as List;
+ final List result = arr.map((s) => s as double).toList();
+ return result;
+ }
+
+ Future zoom() async {
+ await _channel.invokeMethod("zoom");
+ }
+}
+
+class MoveWindowDetector extends StatefulWidget {
+ const MoveWindowDetector({Key? key, this.child}) : super(key: key);
+
+ final Widget? child;
+
+ @override
+ _MoveWindowDetectorState createState() => _MoveWindowDetectorState();
+}
+
+class _MoveWindowDetectorState extends State {
+ double winX = 0;
+ double winY = 0;
+
+ @override
+ Widget build(BuildContext context) {
+ if (!Platform.isMacOS) {
+ return widget.child ?? Container();
+ }
+ return GestureDetector(
+ // https://stackoverflow.com/questions/52965799/flutter-gesturedetector-not-working-with-containers-in-stack
+ behavior: HitTestBehavior.translucent,
+ onDoubleTap: () async {
+ await CocoaWindowChannel.instance.zoom();
+ },
+ onPanStart: (DragStartDetails details) {
+ winX = details.globalPosition.dx;
+ winY = details.globalPosition.dy;
+ },
+ onPanUpdate: (DragUpdateDetails details) async {
+ final windowPos = await CocoaWindowChannel.instance.getWindowPosition();
+ final double dx = windowPos[0];
+ final double dy = windowPos[1];
+ final deltaX = details.globalPosition.dx - winX;
+ final deltaY = details.globalPosition.dy - winY;
+ await CocoaWindowChannel.instance.setWindowPosition(Offset(dx + deltaX, dy - deltaY));
+ },
+ child: widget.child,
+ );
+ }
+}
diff --git a/frontend/app_flowy/lib/startup/deps_resolver.dart b/frontend/app_flowy/lib/startup/deps_resolver.dart
index 8bc5d4dd41..b378d6ee7b 100644
--- a/frontend/app_flowy/lib/startup/deps_resolver.dart
+++ b/frontend/app_flowy/lib/startup/deps_resolver.dart
@@ -15,10 +15,8 @@ import 'package:app_flowy/workspace/presentation/home/home_stack.dart';
import 'package:app_flowy/workspace/presentation/home/menu/menu.dart';
import 'package:flowy_sdk/protobuf/flowy-folder-data-model/app.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart';
-import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart' show EditFieldContext;
-import 'package:flowy_sdk/protobuf/flowy-grid/date_type_option.pb.dart';
-import 'package:flowy_sdk/protobuf/flowy-grid/number_type_option.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-user-data-model/user_profile.pb.dart';
+import 'package:fluttertoast/fluttertoast.dart';
import 'package:get_it/get_it.dart';
class DependencyResolver {
@@ -49,6 +47,8 @@ void _resolveUserDeps(GetIt getIt) {
}
void _resolveHomeDeps(GetIt getIt) {
+ getIt.registerSingleton(FToast());
+
getIt.registerSingleton(MenuSharedState());
getIt.registerFactoryParam(
@@ -157,21 +157,14 @@ void _resolveGridDeps(GetIt getIt) {
),
);
- getIt.registerFactoryParam(
- (gridId, fieldLoader) => FieldEditorBloc(
- gridId: gridId,
- fieldLoader: fieldLoader,
- ),
- );
-
getIt.registerFactoryParam(
(context, _) => TextCellBloc(
cellContext: context,
),
);
- getIt.registerFactoryParam(
- (context, _) => SelectionCellBloc(
+ getIt.registerFactoryParam(
+ (context, _) => SelectOptionCellBloc(
cellContext: context,
),
);
@@ -195,18 +188,6 @@ void _resolveGridDeps(GetIt getIt) {
),
);
- getIt.registerFactoryParam(
- (context, _) => FieldEditorPannelBloc(context),
- );
-
- getIt.registerFactoryParam(
- (typeOption, _) => DateTypeOptionBloc(typeOption: typeOption),
- );
-
- getIt.registerFactoryParam(
- (typeOption, _) => NumberTypeOptionBloc(typeOption: typeOption),
- );
-
getIt.registerFactoryParam(
(gridId, cache) => GridPropertyBloc(gridId: gridId, fieldCache: cache),
);
diff --git a/frontend/app_flowy/lib/startup/tasks/app_widget.dart b/frontend/app_flowy/lib/startup/tasks/app_widget.dart
index 1747cfd8ec..9961142c6d 100644
--- a/frontend/app_flowy/lib/startup/tasks/app_widget.dart
+++ b/frontend/app_flowy/lib/startup/tasks/app_widget.dart
@@ -67,40 +67,42 @@ class ApplicationWidget extends StatelessWidget {
}) : super(key: key);
@override
- Widget build(BuildContext context) => ChangeNotifierProvider.value(
- value: settingModel,
- builder: (context, _) {
- const ratio = 1.73;
- const minWidth = 600.0;
- setWindowMinSize(const Size(minWidth, minWidth / ratio));
- settingModel.readLocaleWhenAppLaunch(context);
- AppTheme theme = context.select(
- (value) => value.theme,
- );
- Locale locale = context.select(
- (value) => value.locale,
- );
+ Widget build(BuildContext context) {
+ return ChangeNotifierProvider.value(
+ value: settingModel,
+ builder: (context, _) {
+ const ratio = 1.73;
+ const minWidth = 600.0;
+ setWindowMinSize(const Size(minWidth, minWidth / ratio));
+ settingModel.readLocaleWhenAppLaunch(context);
+ AppTheme theme = context.select(
+ (value) => value.theme,
+ );
+ Locale locale = context.select(
+ (value) => value.locale,
+ );
- return MultiProvider(
- providers: [
- Provider.value(value: theme),
- Provider.value(value: locale),
- ],
- builder: (context, _) {
- return MaterialApp(
- builder: overlayManagerBuilder(),
- debugShowCheckedModeBanner: false,
- theme: theme.themeData,
- localizationsDelegates: context.localizationDelegates,
- supportedLocales: context.supportedLocales,
- locale: locale,
- navigatorKey: AppGlobals.rootNavKey,
- home: child,
- );
- },
- );
- },
- );
+ return MultiProvider(
+ providers: [
+ Provider.value(value: theme),
+ Provider.value(value: locale),
+ ],
+ builder: (context, _) {
+ return MaterialApp(
+ builder: overlayManagerBuilder(),
+ debugShowCheckedModeBanner: false,
+ theme: theme.themeData,
+ localizationsDelegates: context.localizationDelegates,
+ supportedLocales: context.supportedLocales,
+ locale: locale,
+ navigatorKey: AppGlobals.rootNavKey,
+ home: child,
+ );
+ },
+ );
+ },
+ );
+ }
}
class AppGlobals {
diff --git a/frontend/app_flowy/lib/user/presentation/skip_log_in_screen.dart b/frontend/app_flowy/lib/user/presentation/skip_log_in_screen.dart
index bad8000643..4a78815beb 100644
--- a/frontend/app_flowy/lib/user/presentation/skip_log_in_screen.dart
+++ b/frontend/app_flowy/lib/user/presentation/skip_log_in_screen.dart
@@ -88,8 +88,9 @@ class _SkipLogInScreenState extends State {
}
_launchURL(String url) async {
- if (await canLaunch(url)) {
- await launch(url);
+ final uri = Uri.parse(url);
+ if (await canLaunchUrl(uri)) {
+ await launchUrl(uri);
} else {
throw 'Could not launch $url';
}
diff --git a/frontend/app_flowy/lib/workspace/application/app/app_bloc.dart b/frontend/app_flowy/lib/workspace/application/app/app_bloc.dart
index 663e630a6a..e5eabe98e4 100644
--- a/frontend/app_flowy/lib/workspace/application/app/app_bloc.dart
+++ b/frontend/app_flowy/lib/workspace/application/app/app_bloc.dart
@@ -1,3 +1,5 @@
+import 'dart:collection';
+
import 'package:app_flowy/plugin/plugin.dart';
import 'package:app_flowy/startup/startup.dart';
import 'package:app_flowy/workspace/application/app/app_listener.dart';
diff --git a/frontend/app_flowy/lib/workspace/application/doc/doc_service.dart b/frontend/app_flowy/lib/workspace/application/doc/doc_service.dart
index a0498491f9..6ad08814f4 100644
--- a/frontend/app_flowy/lib/workspace/application/doc/doc_service.dart
+++ b/frontend/app_flowy/lib/workspace/application/doc/doc_service.dart
@@ -12,14 +12,14 @@ class DocumentService {
await FolderEventSetLatestView(ViewId(value: docId)).send();
final payload = TextBlockId(value: docId);
- return BlockEventGetBlockData(payload).send();
+ return TextBlockEventGetBlockData(payload).send();
}
Future> composeDelta({required String docId, required String data}) {
final payload = TextBlockDelta.create()
..blockId = docId
..deltaStr = data;
- return BlockEventApplyDelta(payload).send();
+ return TextBlockEventApplyDelta(payload).send();
}
Future> closeDocument({required String docId}) {
diff --git a/frontend/app_flowy/lib/workspace/application/doc/share_bloc.dart b/frontend/app_flowy/lib/workspace/application/doc/share_bloc.dart
index c8fd8a2b96..e24411fdc0 100644
--- a/frontend/app_flowy/lib/workspace/application/doc/share_bloc.dart
+++ b/frontend/app_flowy/lib/workspace/application/doc/share_bloc.dart
@@ -1,3 +1,6 @@
+import 'dart:async';
+import 'dart:io';
+import 'package:app_flowy/startup/tasks/rust_sdk.dart';
import 'package:app_flowy/workspace/application/doc/share_service.dart';
import 'package:app_flowy/workspace/application/markdown/delta_markdown.dart';
import 'package:flowy_sdk/protobuf/flowy-text-block/entities.pb.dart';
@@ -33,8 +36,30 @@ class DocShareBloc extends Bloc {
ExportData _convertDeltaToMarkdown(ExportData value) {
final result = deltaToMarkdown(value.data);
value.data = result;
+ writeFile(result);
return value;
}
+
+ Future get _exportDir async {
+ Directory documentsDir = await appFlowyDocumentDirectory();
+
+ return documentsDir;
+ }
+
+ Future get _localPath async {
+ final dir = await _exportDir;
+ return dir.path;
+ }
+
+ Future get _localFile async {
+ final path = await _localPath;
+ return File('$path/${view.name}.md');
+ }
+
+ Future writeFile(String md) async {
+ final file = await _localFile;
+ return file.writeAsString(md);
+ }
}
@freezed
diff --git a/frontend/app_flowy/lib/workspace/application/doc/share_service.dart b/frontend/app_flowy/lib/workspace/application/doc/share_service.dart
index cc3afe1314..7e5545f109 100644
--- a/frontend/app_flowy/lib/workspace/application/doc/share_service.dart
+++ b/frontend/app_flowy/lib/workspace/application/doc/share_service.dart
@@ -10,7 +10,7 @@ class ShareService {
..viewId = docId
..exportType = type;
- return BlockEventExportDocument(request).send();
+ return TextBlockEventExportDocument(request).send();
}
Future> exportText(String docId) {
diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/cell_service.dart b/frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/cell_service.dart
index 07be14efa2..68f8eada78 100644
--- a/frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/cell_service.dart
+++ b/frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/cell_service.dart
@@ -10,13 +10,13 @@ import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/cell_entities.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/date_type_option.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-grid/url_type_option.pb.dart';
import 'package:flutter/foundation.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
-
import 'package:app_flowy/workspace/application/grid/cell/cell_listener.dart';
import 'package:app_flowy/workspace/application/grid/cell/select_option_service.dart';
import 'package:app_flowy/workspace/application/grid/field/field_service.dart';
-
+import 'dart:convert' show utf8;
part 'cell_service.freezed.dart';
part 'data_loader.dart';
part 'context_builder.dart';
diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/context_builder.dart b/frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/context_builder.dart
index c7faff5311..3041c563d9 100644
--- a/frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/context_builder.dart
+++ b/frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/context_builder.dart
@@ -1,8 +1,9 @@
part of 'cell_service.dart';
-typedef GridCellContext = _GridCellContext;
+typedef GridCellContext = _GridCellContext;
typedef GridSelectOptionCellContext = _GridCellContext;
-typedef GridDateCellContext = _GridCellContext;
+typedef GridDateCellContext = _GridCellContext;
+typedef GridURLCellContext = _GridCellContext;
class GridCellContextBuilder {
final GridCellCache _cellCache;
@@ -16,61 +17,100 @@ class GridCellContextBuilder {
_GridCellContext build() {
switch (_gridCell.field.fieldType) {
case FieldType.Checkbox:
+ final cellDataLoader = GridCellDataLoader(
+ gridCell: _gridCell,
+ parser: StringCellDataParser(),
+ );
return GridCellContext(
gridCell: _gridCell,
cellCache: _cellCache,
- cellDataLoader: CellDataLoader(gridCell: _gridCell),
+ cellDataLoader: cellDataLoader,
cellDataPersistence: CellDataPersistence(gridCell: _gridCell),
);
case FieldType.DateTime:
+ final cellDataLoader = GridCellDataLoader(
+ gridCell: _gridCell,
+ parser: DateCellDataParser(),
+ config: const GridCellDataConfig(reloadOnFieldChanged: true),
+ );
+
return GridDateCellContext(
gridCell: _gridCell,
cellCache: _cellCache,
- cellDataLoader: DateCellDataLoader(gridCell: _gridCell),
+ cellDataLoader: cellDataLoader,
cellDataPersistence: DateCellDataPersistence(gridCell: _gridCell),
);
case FieldType.Number:
+ final cellDataLoader = GridCellDataLoader(
+ gridCell: _gridCell,
+ parser: StringCellDataParser(),
+ config: const GridCellDataConfig(reloadOnCellChanged: true, reloadOnFieldChanged: true),
+ );
return GridCellContext(
gridCell: _gridCell,
cellCache: _cellCache,
- cellDataLoader: CellDataLoader(gridCell: _gridCell, reloadOnCellChanged: true),
+ cellDataLoader: cellDataLoader,
cellDataPersistence: CellDataPersistence(gridCell: _gridCell),
);
case FieldType.RichText:
+ final cellDataLoader = GridCellDataLoader(
+ gridCell: _gridCell,
+ parser: StringCellDataParser(),
+ );
return GridCellContext(
gridCell: _gridCell,
cellCache: _cellCache,
- cellDataLoader: CellDataLoader(gridCell: _gridCell),
+ cellDataLoader: cellDataLoader,
cellDataPersistence: CellDataPersistence(gridCell: _gridCell),
);
case FieldType.MultiSelect:
case FieldType.SingleSelect:
+ final cellDataLoader = GridCellDataLoader(
+ gridCell: _gridCell,
+ parser: SelectOptionCellDataParser(),
+ config: const GridCellDataConfig(reloadOnFieldChanged: true),
+ );
+
return GridSelectOptionCellContext(
gridCell: _gridCell,
cellCache: _cellCache,
- cellDataLoader: SelectOptionCellDataLoader(gridCell: _gridCell),
+ cellDataLoader: cellDataLoader,
+ cellDataPersistence: CellDataPersistence(gridCell: _gridCell),
+ );
+
+ case FieldType.URL:
+ final cellDataLoader = GridCellDataLoader(
+ gridCell: _gridCell,
+ parser: URLCellDataParser(),
+ );
+ return GridURLCellContext(
+ gridCell: _gridCell,
+ cellCache: _cellCache,
+ cellDataLoader: cellDataLoader,
cellDataPersistence: CellDataPersistence(gridCell: _gridCell),
);
- default:
- throw UnimplementedError;
}
+ throw UnimplementedError;
}
}
+// T: the type of the CellData
+// D: the type of the data that will be save to disk
// ignore: must_be_immutable
class _GridCellContext extends Equatable {
final GridCell gridCell;
final GridCellCache cellCache;
final GridCellCacheKey _cacheKey;
- final _GridCellDataLoader cellDataLoader;
+ final IGridCellDataLoader cellDataLoader;
final _GridCellDataPersistence cellDataPersistence;
final FieldService _fieldService;
late final CellListener _cellListener;
- late final ValueNotifier _cellDataNotifier;
+ late final ValueNotifier? _cellDataNotifier;
bool isListening = false;
VoidCallback? _onFieldChangedFn;
- Timer? _delayOperation;
+ Timer? _loadDataOperation;
+ Timer? _saveDataOperation;
_GridCellContext({
required this.gridCell,
@@ -100,7 +140,7 @@ class _GridCellContext extends Equatable {
FieldType get fieldType => gridCell.field.fieldType;
- VoidCallback? startListening({required void Function(T) onCellChanged}) {
+ VoidCallback? startListening({required void Function(T?) onCellChanged}) {
if (isListening) {
Log.error("Already started. It seems like you should call clone first");
return null;
@@ -124,52 +164,64 @@ class _GridCellContext extends Equatable {
}
onCellChangedFn() {
- final value = _cellDataNotifier.value;
- if (value is T) {
- onCellChanged(value);
- }
+ onCellChanged(_cellDataNotifier?.value);
if (cellDataLoader.config.reloadOnCellChanged) {
_loadData();
}
}
- _cellDataNotifier.addListener(onCellChangedFn);
+ _cellDataNotifier?.addListener(onCellChangedFn);
return onCellChangedFn;
}
void removeListener(VoidCallback fn) {
- _cellDataNotifier.removeListener(fn);
+ _cellDataNotifier?.removeListener(fn);
}
- T? getCellData() {
+ T? getCellData({bool loadIfNoCache = true}) {
final data = cellCache.get(_cacheKey);
- if (data == null) {
+ if (data == null && loadIfNoCache) {
_loadData();
}
return data;
}
- Future, FlowyError>> getTypeOptionData() {
- return _fieldService.getTypeOptionData(fieldType: fieldType);
+ Future> getTypeOptionData() {
+ return _fieldService.getFieldTypeOptionData(fieldType: fieldType);
}
- Future |