Compare commits

...
101 Commits
Author SHA1 Message Date
Lucas.Xu 565485265b chore: prerelease 0.1.2 (#2134) 2023-03-29 15:14:28 +08:00
Lucas.Xu f6f615a54c chore: release 0.1.2 (#2129) 2023-03-28 18:37:08 +08:00
Nathan.fooo 17d88f2ad3 fix: update calendar selected range (#2123) 2023-03-28 14:34:00 +08:00
Nathan.fooo 8f66246e25 fix: modify same database by duplicate view (#2121) 2023-03-28 13:00:20 +08:00
Lucas.Xuandvedon 063ec186bb Rename project and upgrade windows project (#2072)
* chore: rename product name

* chore: upgrade windows project to latest template

---------

Co-authored-by: vedon <vedon.fu@gmail.com>
2023-03-22 13:12:16 +08:00
Annie ec444d4a00 chore: add release changes 2023-03-21 20:22:16 +08:00
Lucas.Xu 95475cb870 Fix some known issue for release/0.1.1 (#2061)
* fix: only show discard dialog when prompt text is not empty

* fix: auto completion node widget text overflow

* chore: update bundle name and copyright
2023-03-21 15:33:19 +08:00
Lucas.Xu 0520855925 chore: update languages file (#2034) 2023-03-20 18:43:31 +08:00
Lucas.Xu 61704f6d4a Fix release v0.1.1 known issues. (#2025)
* feat: optimize the smart edit user-experience

* chore: update language files

* feat: show discard dialog when users tap blank are that out of ai plugins

* fix: toolbar_service test fail
2023-03-20 13:49:20 +08:00
Nathan.fooo b85990e453 feat: migration database (#2009)
* feat: migration database

* ci: fix tauri ci

* feat: migrate database view

* ci: fix ci
2023-03-18 07:21:28 +08:00
Lucas.Xu b0d525a48f Merge pull request #2004 from AppFlowy-IO/chore/0.1.1
release 0.1.1
2023-03-17 13:54:56 +08:00
Nathan.fooo bf048ffc0d fix: paser workspce pb (#2005) 2023-03-17 13:47:27 +08:00
Lucas.Xu 1f44d4de33 fix(test): test replaceTexts, textNodes.length > texts.length 2023-03-16 21:14:45 +08:00
Lucas.Xu 653f88033e feat: improve the smart edit user-experience 2023-03-16 18:40:20 +08:00
Lucas.Xu 0c88c7ce2f fix: windows package build error 2023-03-16 15:24:45 +08:00
Lucas.Xu f38688b17e chore: update release version to 0.1.1 2023-03-16 14:26:22 +08:00
Lucas.Xu 1a3701feaf feat: #2003 Entering an OpenAI key should auto-save 2023-03-16 14:26:05 +08:00
Lucas.Xu 1b86587875 chore: update language files 2023-03-16 14:25:39 +08:00
Lucas.Xu 120db6805f feat: open gitbook openAI link when tapping learn more button (#2002) 2023-03-16 12:35:20 +08:00
Lucas.Xu 6b14983f2b fix: #1997 Exception trhown after inserting '/' slash in middle of text (#1998) 2023-03-15 17:48:56 +08:00
Lucas.Xu 9a4cde07b6 Merge pull request #1991 from AppFlowy-IO/fix_0_1_1
Fix release/0.1.1 known issues.
2023-03-14 17:17:47 +08:00
Lucas.Xu d6d591f359 fix: select all shouldn't include the cover plugin 2023-03-14 16:41:37 +08:00
Lucas.Xu 0570615414 fix: #1975 Set a height limit for the AI prompt window where it displays the results 2023-03-14 15:57:26 +08:00
Lucas.Xu 609bf2a4ce fix: #1968 UI inconsistency 2023-03-14 11:44:02 +08:00
Lucas.Xu 75231e606c fix: flutter analyze 2023-03-13 22:28:56 +08:00
Lucas.Xu dd9c3dd2a3 fix: #1967 the summarize feature generates duplicate answers 2023-03-13 21:35:36 +08:00
Lucas.Xu 4821d7ea65 fix: #1966 the loading icon too close to the edge 2023-03-13 17:53:22 +08:00
Lucas.Xu 874d1e86c2 fix: #1964 Text on the UI 2023-03-13 17:44:59 +08:00
Lucas.Xu b7ec7ce32e fix: #1962 Disable but still show the AI assistants icon in the toolbar menu when an OpenAI key is not provided 2023-03-13 17:28:10 +08:00
Lucas.Xu 0141538be8 fix: #1973 Using the mouse to highlight text very easy to miss the first letter 2023-03-13 14:35:11 +08:00
Lucas.Xu dcf48ceb50 fix: #1976 Adding a cover image via upload doesn't work 2023-03-13 14:30:52 +08:00
Yijing HuangandLucas.Xu 972ef2149c fix(appflowy_flutter): fix cover image overflow #1916 (#1952)
* fix(appflowy_flutter): fix cover image overflow #1916

* fix(appflowy_flutter): use OverflowBox to fix #1916

* chore: fix misspelling

* fix: prevent the image being overstretched

---------

Co-authored-by: Lucas.Xu <lucas.xu@appflowy.io>
2023-03-11 21:15:34 +08:00
668e1196d1 chore: config tauri web driver test (#1947)
* chore: setup tauri test

* chore: update test

* chore: update test

* chore: update test

* chore: update test

* refactor: test folder location

* chore: remove deps

* ci: fix build

---------

Co-authored-by: appflowy <annie@appflowy.io>
Co-authored-by: nathan <nathan@appflowy.io>
2023-03-11 13:07:31 +08:00
Richard Shiue 688d55e00f fix: #1942 utc timestamp being parsed as local time (#1953) 2023-03-10 17:33:25 +08:00
Lucas.Xu 40c23b7c7d Merge pull request #1951 from hyj1204/fix/double_click_title_issue_1324
fix(appflowy_flutter): fix double click title issue #1324
2023-03-10 10:25:46 +07:00
Nathan.fooo 5b4043b805 fix: SelectOptionCellBloc registeration error (#1948) 2023-03-10 09:40:19 +08:00
Yijing Huang 2368f5dc4a fix(appflowy_flutter): fix double click title issue #1324
double click the title to select all the text on it
2023-03-10 00:24:31 +08:00
GouravShDev 0dac41b114 chore: add node tests (#1943) 2023-03-09 14:33:12 +08:00
Lucas.Xu b89c69f294 fix: #1778 (#1946)
* fix: [FR] The text formatting toolbar should appear after the selection #1778

* chore: format code
2023-03-09 14:32:49 +08:00
Richard Shiue 77ff2e987a chore: include time per cell (#1901)
* style: autoformat

* chore: add include_time to cell data

* chore: remove include_time from date field type options

* chore: fix tests

* chore: custom deserializer for date cell data

* chore: add more tests

* chore: simplify date calculation logic

* chore: move include time to per-cell setting in UI

* test: add another text str test

* chore: adapt changes from upstream
2023-03-09 14:25:33 +08:00
Lucas.XuandYijing Huang 5e8f6a53a0 relicense appflowy editor (#1938)
* revert:"fix: remove keyword when click selection menu item"

This reverts commit 5782dec45c.

* revert(appflowy_editor):revert "feat: double asterisks/underscores to bold text"

This reverts commit c0964fad5d.

* revert(appflowy_editor):revert "fix: workaround infinity formatting"

This reverts commit 6a902a2b21.
The Appflowy folder under the frontend had been removed before reverting.

* chore(appflow_editor):update test variable after reverting

* chore(appflowy_editor): comment out the test for reverting

* chore(appflowy_editor): update variable type after reverting

* chore(appflowy_editor): remove unused import after reverting

* feat(appflowy_editor): double asterisk to bold text

* test(appflowy_editor): test double asterisk to bold text

* fix(appflowy_editor): delete slash after a selection menu item is selected

* test(appflowy_editor): test selection menu widget after clicking

* feat(appflowy_editor):  double asterisk to bold text and remove slash after clicking selection menu item   (#1935)

* feat(appflowy_editor): double asterisk to bold text

* test(appflowy_editor): test double asterisk to bold text

* fix(appflowy_editor): delete slash after a selection menu item is selected

* test(appflowy_editor): test selection menu widget after clicking

* feat(appflowy_editor): double underscore to bold text

* test(appflowy_editor): test double underscore to bold text

* chore(appflowy_editor): put checkbox testing back

* chore: format code

---------

Co-authored-by: Yijing Huang <hyj891204@gmail.com>
2023-03-09 14:15:22 +08:00
qinluhe 1d28bed281 feat: Initialize appflowy block data and render block list (#1940) 2023-03-09 13:52:48 +08:00
Lucas.Xu 21199c04ac Fix/1936 (#1939)
* fix: [Bug] Code block jump skip blank line

* fix: auto completion interaction

* Revert "fix: [Bug] Code block jump skip blank line"

This reverts commit 5a252bcb18.

* fix: [Bug] Code block jump skip blank line

* fix: number list parse error
2023-03-09 10:10:31 +08:00
Nathan.fooo d3823eb076 refactor: moving grid widgets used by other database view to upper level folder
* refactor: export UIs in flowy_infra_ui

* refactor: move cells to upper level folder

* refactor: move cell blocs
2023-03-09 09:51:04 +08:00
Nathan.fooo 7106195d8a Feat/calendar with backend data (#1930)
* chore: enable calendar view

* chore: update database group listener

* refactor: remove board data controller

* refactor: remove group backend service

* refactor: remove calendar controller

* chore: create default calendar setting

* chore: send calednar setting notifications

* refactor: rename the card in kanban board, prepare to reuse in calendar

* refactor: support custom card cell

* chore: return calendar events

* refactor: remove groupId in card, make card more generic

* chore: display cell

* chore: display three cards in calendar

* chore: create calendar card

* refactor: create row with data

* chore: support create event

* ci: fix tauri build

* chore: disable create calendar
2023-03-08 21:19:44 +08:00
90da54d12f feat: integrate database controller (tauri)
* feat: using controllers in react hooks WIP (#1915)

* chore: add edit / create field test

* chore: add delete field test

* chore: change log class arguments

* chore: delete/create row

* chore: set tracing log to debug level

* fix: filter notification with id

* chore: add get single select type option data

* fix: high cpu usage

* chore: format code

* chore: update tokio version

* chore: config tokio runtime subscriber

* chore: add profiling feature

* chore: setup auto login

* chore: fix tauri build

* chore: (unstable) using controllers

* fix: initially authenticated and serializable fix

* fix: ci warning

* ci: compile error

* fix: new folder trash overflow

* fix: min width for nav panel

* fix: nav panel and main panel animation on hide menu

* fix: highlight active page

* fix: post merge fixes

* fix: post merge fix

* fix: remove warnings

* fix: change IDatabaseField fix eslint errors

* chore: create cell component for each field type

* chore: move cell hook into custom cell component

* chore: refactor row hook

* chore: add tauri clean

---------

Co-authored-by: nathan <nathan@appflowy.io>
Co-authored-by: Nathan.fooo <86001920+appflowy@users.noreply.github.com>

* ci: fix wanrings

---------

Co-authored-by: Askarbek Zadauly <ascarbek@gmail.com>
2023-03-08 10:59:52 +08:00
Lucas.Xu e73870e6e2 fix: auto generator bugs (#1934) 2023-03-08 08:58:28 +08:00
Anderson Cardoso 9e235c578e chore: Update 3: Brazilian Portuguese Localization (#1907)
- Fix typos;
- Fix inconsistencies;
- Removed duplicated block strings.

Note: There are some word by word texts that I still need to figure out how to adapt properly; though, do believe most of strings are good to go!

Please review!
2023-03-07 09:35:04 +08:00
Lucas.Xu 7ff4cecd09 feat: add cover migration for document (#1929)
* feat: add cover migration for document

* fix: should not delete the cover when selecting all

* fix: chinese characters for openai
2023-03-07 09:33:59 +08:00
GouravShDev 675c833f07 feat: add test for appflowy_editor attributes (#1931) 2023-03-07 09:33:35 +08:00
Aman Negi d3ee346cb7 docs(appflowy_flutter) : Update Documentation (#1910)
* docs(appflowy_flutter): Update Documentation

- Added basic information so that new contributors can easily get started with contributions.

* docs(appflowy_flutter): Fix doc issues

- Fixed the wrong Flutter version chip
- Added contributions types
2023-03-06 14:10:10 +08:00
GouravShDev 99f0fad74c feat: add test for appflowy_editor path (#1926) 2023-03-06 10:37:10 +08:00
Nathan.fooo 45045beeb9 chore: rename document test (#1925) 2023-03-05 19:19:40 +08:00
Nathan.fooo 7e7cee4bf4 chore: add tauri database group test (#1924)
* chore: add tauri database group test

* chore: add more tests

* chore: enable run all tests

* chore: rename test folder
2023-03-05 16:26:27 +08:00
Nathan.fooo 8e22ef2230 chore: observer app change (#1922) 2023-03-05 16:13:06 +08:00
Nathan.fooo 6aa9ba28d6 Feat/tauri folder (#1921)
* refactor: folders item

* fix: show get stared page if it's not login

* chore: expose debug pages
2023-03-04 16:15:24 +08:00
Nathan.fooo 205b0fc4a5 Fix/tauri login state (#1919)
* fix: redux serializableCheck

* chore: read login state

* fix: show loading page while checking user state

* chore: cell data parser
2023-03-04 11:03:16 +08:00
Nathan.fooo 3f0d3d802a fix: dart test (#1920) 2023-03-04 08:59:40 +08:00
Nathan.fooo 0f3c6d6a04 Feat/appflowy tauri 3 (#1914) 2023-03-03 20:38:31 +08:00
Nathan.fooo 59a1910b3c Refactor/database classes (#1913) 2023-03-03 18:31:30 +08:00
Muhammad RizwanandLucas.Xu f1316acfcc Implement cover plugin 1868 (#1897)
* implement_cover_plugin_#1868

* code cleanup

* fix: CI issue fix

* fix: cover plugin implementation finalized

* fix: localization fixes

* fix: added add cover button

* chore: optimize the cover plugin code

* feat: auto hide the add button and cover buttons when leaving

---------

Co-authored-by: Lucas.Xu <lucas.xu@appflowy.io>
2023-03-02 19:34:22 +08:00
Lucas.Xu fd41459a30 fix: smart edit bugs (#1911) 2023-03-02 19:34:08 +08:00
Lucas.Xu a1a5675875 fix: openai for summarize doesn't work when mutliple selecting (#1904) 2023-03-01 17:38:14 +08:00
Nathan.foooandAskarbek Zadauly f6957fb160 Feat/appflowy tauri 2 (#1902)
* chore: rename classes to models

* refactor: add effects and reducers folder

* chore: update user data storage path

* chore: subscribe callback

* chore: nav items persist, board layout (#1879)

* chore: load workspace items, load folders and pages from workspace, load raw document data, load raw grid data

* chore: clear folders and pages before load, new folder event

* chore: update folder name backend call

* chore: folder expand animation

* chore: hide arrow on empty folder

* chore: Board page layout, board store, board sample data

* chore: board block item

* chore: test db id

* chore: persist new page, persist page rename, create workspace on read error

* chore: boardblockitem details btn

* chore: boardblockitem multiselect data and colors

* chore: board item drag

* chore: drag start on move

* chore: remove databaseId

* chore: remove databaseId

* chore: import service classes into auth hook

* chore: sign out option

* chore: login page event

* chore: signup event

* chore: make workspace hook to use service

* chore: page and folder hooks use backend services

* chore: new folder use backend service

* chore: error handler page

* chore: try catch hooks to show error page

* chore: install i18n package and use flutters i18n files

* fix: signin signup margin

* chore: fix compile errors

* chore: remove unused codes

* chore: open workspace after user register

* chore: open workspace after user register

* chore: add create grid demo

* chore: load the cell data

* chore: print the cell data

* chore: fix project errors

* fix: tauri UI issues (#1899)

* chore: load workspace items, load folders and pages from workspace, load raw document data, load raw grid data

* chore: clear folders and pages before load, new folder event

* chore: update folder name backend call

* chore: folder expand animation

* chore: hide arrow on empty folder

* chore: Board page layout, board store, board sample data

* chore: board block item

* chore: test db id

* chore: persist new page, persist page rename, create workspace on read error

* chore: boardblockitem details btn

* chore: boardblockitem multiselect data and colors

* chore: board item drag

* chore: drag start on move

* chore: remove databaseId

* chore: remove databaseId

* chore: import service classes into auth hook

* chore: sign out option

* chore: login page event

* chore: signup event

* chore: make workspace hook to use service

* chore: page and folder hooks use backend services

* chore: new folder use backend service

* chore: error handler page

* chore: try catch hooks to show error page

* chore: install i18n package and use flutters i18n files

* fix: signin signup margin

* fix: new page overflow with folder

* fix: sign out button

* fix: sign out icon

* chore: floating navigation panel

* refactor: notify with error

* chore: config window size

* fix: test demo error

* chore: update tests

---------

Co-authored-by: Askarbek Zadauly <ascarbek@gmail.com>
2023-02-28 22:42:41 +08:00
Lucas.Xu 085ef8f668 Feature/smart edit v2 (#1880)
* feat: add edit api to openai client

* feat: add translation

* chore: format code

* feat: add smart edit plugin

* fix: close http.client when dispose

* fix: insert openai result to wrong position

* feat: optimize the replace text logic

* test: add test for normalize and getTextInSelection function

* chore: update error message
2023-02-28 14:34:13 +08:00
0x7c01 1945b0fe05 fix: homeMenuResizer position when menu is drawer. (#1896) 2023-02-28 14:33:50 +08:00
Aman NegiandLucas.Xu 2451d3188c feat(shortcuts): Add Shortcuts to Help Menu (#1870)
* feat(shortcuts): Add Shortcuts to Help Menu

- Added option of shorcuts in help menu
- Clicking on the shortcut leads to the `Shortcuts.md` file

* fix: l10n and todos

---------

Co-authored-by: Lucas.Xu <lucas.xu@appflowy.io>
2023-02-28 10:38:57 +08:00
Nathan.fooo 4a81fed6e4 fix: group with not support field test (#1890) 2023-02-27 19:00:00 +08:00
dependabot[bot] bf8e36a08b chore(deps): bump openssl-src in /frontend/rust-lib (#1886)
Bumps [openssl-src](https://github.com/alexcrichton/openssl-src-rs) from 111.24.0+1.1.1s to 111.25.0+1.1.1t.
- [Release notes](https://github.com/alexcrichton/openssl-src-rs/releases)
- [Commits](https://github.com/alexcrichton/openssl-src-rs/commits)

---
updated-dependencies:
- dependency-name: openssl-src
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-27 15:40:36 +08:00
Nathan.fooo 61fd608200 Feat/view map database (#1885)
* refactor: rename structs

* chore: read database id from view

* chore: fix open database error because of create a database view for database id

* chore: fix tests

* chore: rename datbase id to view id in flutter

* refactor: move grid and board to database view folder

* refactor: rename functions

* refactor: move calender to datbase view folder

* refactor: rename app_flowy to appflowy_flutter

* chore: reanming

* chore: fix freeze gen

* chore: remove todos

* refactor: view process events

* chore: add link database test

* chore: just open view if there is opened database
2023-02-26 16:27:17 +08:00
6877607c5e chore: calendar plugin backend database data (#1884)
* chore: implement CalendarBloc

* chore: enable save and read the calendar setting

* style: more precise variable name

* chore: backend calendar settings

* chore: protobuf for layout settings

* chore: update test

* chore: Enumerate the LayoutTypePB enum type to get the supported layout types

* fix: deserialize object type is not the same as serialize object type

* chore: add set/get calendar settings event

* ci: fix wanrings

---------

Co-authored-by: nathan <nathan@appflowy.io>
Co-authored-by: vedon <vedon.fu@gmail.com>
2023-02-24 16:59:14 +08:00
Lucas.Xu 01a388c1c4 chore: abstract appflowy editor build function to widget (#1878)
* chore: abstract appflowy editor build function to widget

* feat: refactor the editor state to optional
2023-02-24 09:16:51 +08:00
Kristen McWilliam f4dea31560 fix(network_monitor): add missing case for other network type (#1854)
* fix(network_monitor): add missing case for `other` network type

Missing case causing static analysis error that is blocking the build.

* chore: update depdendency minor versions
2023-02-23 17:07:59 +08:00
Lucas.Xu b356354cd8 feat: support delete consecutive nodes on backend (#1877) 2023-02-21 19:27:52 +08:00
Nathan.fooo f76d722b4c Feat/database view (#1875)
* chore: rename structs

* chore: add todos

* chore: hidden database id

* refactor: add database folder, prepare to extract the view

* refactor: rename grid-model to datbase-model

* ci: fix warnings
2023-02-21 15:47:51 +08:00
Lucas.Xu 346a09b2ae feat: optimize the open ai input status and clear the auto completion… (#1865)
* feat: optimize the open ai input status and clear the auto completion node when exiting the doc

* fix: import error on appflowy editor
2023-02-21 13:25:46 +08:00
Lucas.Xu 3fd4371d2c fix: error happens when parsing readme content (#1873) 2023-02-20 18:28:09 +08:00
Nathan.fooo 8a2f5fe789 Feat/tauri database effects (#1863)
* feat: config database view effects

* chore: add tests

* chore: config jest

* chore: config jest windows

* ci: wanrings

* chore: config folder effect
2023-02-19 14:59:04 +08:00
Lucas.Xu 7c3a823078 feat: add openai service (#1858)
* feat: add openai service

* feat: add openai auto completion plugin

* feat: add visible icon for open ai input field

* chore: optimize user experience

* feat: add auto completion node plugin

* feat: support keep and discard the auto generated text

* fix: can't delete the auto completion node

* feat: disable ai plugins if open ai key is null

* fix: wrong auto completion node card color

* fix: make sure the previous text node is pure when using auto generator
2023-02-16 10:17:08 +08:00
Lucas.Xu 2f9823d12a fix: wrong icon color for grid and board plugin (#1862) 2023-02-15 19:44:18 +08:00
Mayur Mahajan ea9d8d03ad Improve Editing and Navigating shortcuts with Ctrl/Meta (#1845)
* feat: handler for deleting a word

* chore: typo

* test: ctrl and backspace to delete word

* feat: add ctrl alt arrows to select words

* fix: remove print statement

* fix: remove additional shortcut

* fix: handle nodes empty case

* test: edge cases with delete word

* fix: press meta on macos
2023-02-15 14:26:18 +08:00
Kristen McWilliam 64902f763b Add generated Flutter files to gitignore (#1855)
* chore: add generated files to gitignore

* chore: remove gitignored files
2023-02-15 09:46:31 +08:00
Nathan.fooo c1de3ba01b ci: disable eslint (#1857) 2023-02-14 10:28:01 +08:00
Lucas.Xu 72e155f5b9 feat: add open ai key to database (#1852)
* feat: add open ai key to database

* chore: refactor code
2023-02-14 10:04:36 +08:00
Kristen McWilliam 7207e35349 chore: Catch platform errors (#1853)
* refactor(Log): allow passing error and stacktrace to logs

This allows us to log errors and stacktraces in a more structured way.

* feat: catch platform errors

Adds handling for platform errors that are not caught by the
Flutter framework. Doing so will log the error properly and
prevent the app from crashing.
2023-02-14 09:46:25 +08:00
Nathan.foooandAnnie 51041f6860 CI: Appflowy tauri ci (#1851)
* chore: add notification parser

* chore: rename classes to models

* refactor: add effects and reducers folder

* chore: update eslint version

* chore: run npx eslint --fix src

* fix: ParserOptions.project error by ignore linting the  .eslintrc.cjs

* ci: add tauri lint

* ci: disable ubuntu and windows tauri ci

* ci: install

---------

Co-authored-by: Annie <anqi.annie.wang@gmail.com>
2023-02-13 19:24:16 +08:00
Mohammad Zolfaghariandnathan 59cb4a890a fix: empty url group bug (#1755)
* fix: empty url group bug

moving a row to empty url (no status) group would change the row's
url to the group id which is not empty, its a random string.
fixed it with puting a check to fill the url with the empty string
when the group id is equal to empty url group id

* fix: move empty group check to `insert_url_cell`

because evereywhere using `insert_url_cell` we want to check that.

* chore: cargo fmt

---------

Co-authored-by: nathan <nathan@appflowy.io>
2023-02-13 18:55:03 +08:00
Mayur Mahajan 91b942d319 Pressing tab on a todo creates a sub-todo (#1847)
* feat: add tab for lists

* test: tab for lists
2023-02-13 14:47:52 +08:00
Mayur Mahajan 9c8753b191 feat: add new purple theme (#1693)
* feat: add new purple theme

* refactor: change theme color

* fix: contrast issue

* refactor: change the primary btn color
2023-02-13 10:19:02 +08:00
Lucas.Xu 2f803959e7 feat: #1832 Support to import data from Markdown or Text to Document … (#1840)
* feat: #1832 Support to import data from Markdown or Text to Document page

* feat: #1832 Support to import data from Markdown or Text to Document page
2023-02-13 09:51:24 +08:00
Сергей Ворон 592b918175 chore: Update ru-RU.json (#1843) 2023-02-13 09:48:43 +08:00
Nathan.fooo 6bb1c4e89c feat: run rustfmt with custom defined fmt configuration (#1848)
* chore: update rustfmt

* chore: apply rustfmt format
2023-02-13 09:29:49 +08:00
Nathan.fooo e2496e734c docs: udpate user events (#1846) 2023-02-13 08:21:25 +08:00
Kristen McWilliam 6c895ad4fe Refactor: app window logic (#1842)
* feat: add TargetPlatform `isDesktop` helper

Safe and convenient way to check if the current platform is a desktop platform.

* refactor: move window logic to separate class

This is much cleaner and better encapsulated. Sets up an area for
further window management in the future.

Does not try to initialize on mobile or web, which would crash.

* fix: isDesktop doc comment

* fix: set window title

Currently only displays "app_flowy" as the window title. This commit
sets the window title to "AppFlowy" as part of the init process.
2023-02-11 14:16:38 +08:00
Nathan.fooo 8588afcda6 feat: support create document with initial data (#1841) 2023-02-10 22:24:34 +08:00
1ad08ba59d Feat/appflowy tauri UI (#1835)
* chore: create folders

* chore: setup taliwindcss (#1742)

* chore: create folders

* chore: setup taliwindcss

---------

Co-authored-by: nathan <nathan@appflowy.io>
Co-authored-by: Nathan.fooo <86001920+appflowy@users.noreply.github.com>

* feat: greater to blockquote

* fix: local variable 'text' isn't used

* feat: #1061 Support markdown to create a blockquote

* fix: #1732 the actions of an image look different than the ones of a code block

* fix: command of double tilde to strikethrough

* feat: callout (#1732)

* feat: add callout plugin

* refactor: add SelectionMenuItem.node factory

makes calloutMenuItem more readable

* feat: add color picker

* feat: add popover to callout

* feat: add emoji to callout

* fix: store tint name

* fix: remove leading underscores

* fix: revert export of editor_entry

* refactor: move color tint names to appflowy_editor

* fix: #1732 only re-insert text node if it's parent is text node too while deleting

* docs: doc comment for SelectionMenuItem.node

* fix: disable callout plugin

should be re-enabled after #1753 is done

* fix: typo

---------

Co-authored-by: Lucas.Xu <lucas.xu@appflowy.io>

* Feat/http server adapt (#1754)

* integrate board plugin into document (#1675)

* fix: cursor doesn't blink when opening selection menu

* feat: add board plugin

* feat: integrate board plugin into document

* feat: add i10n and fix known bugs

* feat: support jump to board page on document

* feat: disable editor scroll only when the board plugin is selected

* chore: dart fix

* chore: remove unused files

* fix: dart lint

* Feat/database view (#1765)

* chore: rename flowy-database to flowy-sqlite

* refactor: rename flowy-grid to flowy-database

* refactor: rename grid to database

* refactor: rename GridEvent to DatabaseEvent

* refactor: rename grid_id to database_id

* refactor: rename dart code

* fix: #1763 [Bug] Mouse unable to click a certain area

* fix: potential async errors (#1772)

* feat: Skeleton task (#1775)

* chore: change tauri dev npm script

* chore: setup prettier

* chore: add protobuf type

* chore: move test calls to separate component

* chore: serve assets from app_flowy folder

* chore: import poppins font

* chore: install eslint, remove errors

* placeholder components

* chore: import colors from UI kit, footer panel

* chore: reorganise components

* chore: redux toolkit, navigation folders and files, navigation hooks

* fix: on add folder others close

* fix: tauri_dev task

* fix: restore grid notification

* chore: navigation items events (#1784)

* chore: change tauri dev npm script

* chore: setup prettier

* chore: add protobuf type

* chore: move test calls to separate component

* chore: serve assets from app_flowy folder

* chore: import poppins font

* chore: install eslint, remove errors

* placeholder components

* chore: import colors from UI kit, footer panel

* chore: reorganise components

* chore: redux toolkit, navigation folders and files, navigation hooks

* fix: on add folder others close

* fix: tauri_dev task

* fix: restore grid notification

* chore: shared button

* chore: folder/file popup, rename/duplicate/delete items

* chore: new page types popup

* fix: navitem pages padding

* fix: page click mishandle

* fix: folder click mishandle

* chore: add other page types

* fix: stop propagating on button click

* fix: one alt

* fix: renaming change bg

* refactor: brake Navigation Panel into smaller components

* chore: header panel folder

* chore: focus and select all on rename popup

* chore: add classname to popup

* chore: navigation panel resize

* Feat/appflowy tauri (#1831)

* feat:grid view structure

* feat:add store and refactor grid page

* chore: import icons, resize grid items, change grid items style, add field type icons, reorganize grid toolbar

* feat: auth screens(login, signup and confirm-account) ui done

* chore: add tailwind class sorter and formatted all files

* chore: group svgs into single folder

* chore: resolve warnings in svg files

* fix: use exported fieldType enum

* fix: resolve FieldType referances

* chore: auth pages fixes, replace links, replace buttons, svg fixes, navigate between pages, navigate to homepage on main button click

---------

Co-authored-by: ascarbek <ascarbek@gmail.com>

* ci: wanrings

---------

Co-authored-by: Mikias Tilahun Abebe <mikiastilahun@gmail.com>
Co-authored-by: Andreas Bichinger <andreas.bichinger@gmail.com>
Co-authored-by: Lucas.Xu <lucas.xu@appflowy.io>
Co-authored-by: Askarbek Zadauly <ascarbek@gmail.com>
2023-02-10 16:26:14 +08:00
Nathan.fooo cbd351453d ci: add tauri ci (#1833)
* ci: add tauri ci

* ci: update install windows scripts

* Update tauri_ci.yaml

* Update tauri_ci.yaml

* ci: update
2023-02-10 14:30:34 +08:00
Richard Shiue 72768a2f77 fix: app version (#1828) 2023-02-09 20:24:43 +08:00
Kristen McWilliamandLucas.Xu 6b8c7d7bc6 fix: use window_manager to set minimum window size (#1791)
* fix: use window_manager to set minimum window size

Resolves #762
Resolves #1559

* refactor: only init WidgetsFlutterBinding once

* fix: set window minimum size

Was meant to be setMinimumSize not setSize

* fix: windows manager crash on macOS

---------

Co-authored-by: Lucas.Xu <lucas.xu@appflowy.io>
2023-02-09 14:42:18 +08:00
Lucas.Xu 84ea888c73 fix: update the color of the selection menu item 2023-02-09 13:40:03 +08:00
Mayur Mahajan 95ec607482 [FR] Shortcut for toggling checkbox (#1817)
* feat: shortcut for toggling checkbox

* refactor: separate checkbox event handler

* test: chechbox event handler

* chore: remove unused imports

* refactor: command to ctrl and enter

* refactor: handler to use transactions

* test: checkbox event handler

* chore: remove unused import

* refactor: simplify handler logic
2023-02-09 13:39:25 +08:00
2639 changed files with 81757 additions and 56987 deletions

No files matched your search

+1 -1
View File
@@ -1,4 +1,4 @@
frontend/app_flowy/
frontend/appflowy_flutter/
frontend/scripts/
frontend/rust-lib/target
shared-lib/target/
+2 -2
View File
@@ -11,7 +11,7 @@ on:
- "main"
- "release/*"
paths:
- "frontend/app_flowy/packages/appflowy_editor/**"
- "frontend/appflowy_flutter/packages/appflowy_editor/**"
env:
CARGO_TERM_COLOR: always
@@ -35,7 +35,7 @@ jobs:
cache: true
- name: Run FlowyEditor tests
working-directory: frontend/app_flowy/packages/appflowy_editor
working-directory: frontend/appflowy_flutter/packages/appflowy_editor
run: |
flutter pub get
flutter format --set-exit-if-changed .
+1 -1
View File
@@ -98,7 +98,7 @@ jobs:
cargo make --profile ${{ matrix.flutter_profile }} appflowy-dev
- name: Flutter Analyzer
working-directory: frontend/app_flowy
working-directory: frontend/appflowy_flutter
run: flutter analyze
- name: Run Flutter unit tests
+4 -4
View File
@@ -6,14 +6,14 @@ on:
- "main"
- "release/*"
paths:
- "frontend/app_flowy/**"
- "frontend/appflowy_flutter/**"
pull_request:
branches:
- "main"
- "release/*"
paths:
- "frontend/app_flowy/**"
- "frontend/appflowy_flutter/**"
env:
CARGO_TERM_COLOR: always
@@ -100,14 +100,14 @@ jobs:
shell: bash
- name: Flutter Code Generation
working-directory: frontend/app_flowy
working-directory: frontend/appflowy_flutter
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 AppFlowy tests
working-directory: frontend/app_flowy
working-directory: frontend/appflowy_flutter
run: |
if [ "$RUNNER_OS" == "Linux" ]; then
flutter test integration_test -d Linux --coverage
+13 -3
View File
@@ -39,7 +39,7 @@ jobs:
name: ${{ matrix.job.target }} (${{ matrix.job.os }})
needs: create-release
env:
WINDOWS_APP_RELEASE_PATH: frontend\app_flowy\product\${{ github.ref_name }}\windows
WINDOWS_APP_RELEASE_PATH: frontend\appflowy_flutter\product\${{ github.ref_name }}\windows
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 }}
@@ -129,7 +129,7 @@ jobs:
runs-on: ${{ matrix.job.os }}
needs: create-release
env:
MACOS_APP_RELEASE_PATH: frontend/app_flowy/product/${{ github.ref_name }}/macos/Release
MACOS_APP_RELEASE_PATH: frontend/appflowy_flutter/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:
@@ -217,7 +217,7 @@ jobs:
runs-on: ${{ matrix.job.os }}
needs: create-release
env:
LINUX_APP_RELEASE_PATH: frontend/app_flowy/product/${{ github.ref_name }}/linux/Release
LINUX_APP_RELEASE_PATH: frontend/appflowy_flutter/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
# PKG_CONFIG_SYSROOT_DIR: /
@@ -324,6 +324,7 @@ jobs:
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
@@ -352,3 +353,12 @@ jobs:
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
notify-discord:
runs-on: ubuntu-latest
needs: [build-for-linux, build-for-windows, build-for-macOS]
steps:
- name: Notify Discord
run: |
curl -H "Content-Type: application/json" -d '{"username": "release@appflowy", "content": "🎉 AppFlowy ${{ github.ref_name }} is available. https://github.com/LucasXu0/AppFlowy/releases/tag/'${{ github.ref_name }}'"}' "https://discord.com/api/webhooks/${{ secrets.DISCORD }}"
shell: bash
+82
View File
@@ -0,0 +1,82 @@
name: Tauri-CI
on:
pull_request:
paths:
- "frontend/rust-lib/**"
- "frontend/appflowy_tauri/**"
env:
NODE_VERSION: "16"
RUST_TOOLCHAIN: "1.65"
jobs:
tauri-build:
strategy:
fail-fast: false
matrix:
# platform: [macos-latest, ubuntu-20.04, windows-latest]
platform: [macos-latest]
runs-on: ${{ matrix.platform }}
steps:
- uses: actions/checkout@v3
- name: setup node
uses: actions/setup-node@v3
with:
node-version: ${{ env.NODE_VERSION }}
- name: Install Rust toolchain
id: rust_toolchain
uses: actions-rs/toolchain@v1
with:
toolchain: ${{ env.RUST_TOOLCHAIN }}
override: true
profile: minimal
- uses: Swatinem/rust-cache@v2
with:
prefix-key: ${{ matrix.platform }}
- name: install dependencies (windows only)
if: matrix.platform == 'windows-latest'
working-directory: frontend
run: |
cargo install --force cargo-make
cargo install --force duckscript_cli
vcpkg integrate install
cargo make appflowy-tauri-deps-tools
- name: install dependencies (ubuntu only)
if: matrix.platform == 'ubuntu-20.04'
working-directory: frontend
run: |
sudo apt-get update
sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libappindicator3-dev librsvg2-dev patchelf
cargo install --force cargo-make
cargo make appflowy-tauri-deps-tools
- name: install dependencies (macOS only)
if: matrix.platform == 'macos-latest'
working-directory: frontend
run: |
cargo install --force cargo-make
cargo make appflowy-tauri-deps-tools
# - name: lint
# working-directory: frontend/appflowy_tauri
# run: |
# yarn --frozen-lockfile
# yarn test:prettier
# yarn test:code
- name: build
working-directory: frontend/appflowy_tauri
run: |
mkdir dist
npm install
cargo make --cwd .. tauri_build
yarn && yarn build
- uses: tauri-apps/tauri-action@v0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+1 -1
View File
@@ -3,7 +3,7 @@ on:
push:
branches: [ main ]
paths:
- "frontend/app_flowy/assets/translations/en.json"
- "frontend/appflowy_flutter/assets/translations/en.json"
jobs:
Discord-Notify:
+1 -1
View File
@@ -29,7 +29,7 @@ node_modules
# Commit the highest level pubspec.lock, but ignore the others
pubspec.lock
!frontend/app_flowy/pubspec.lock
!frontend/appflowy_flutter/pubspec.lock
# ignore tool used for commit linting
.githooks/gitlint
+1 -1
View File
@@ -10,7 +10,7 @@
<env name="flowy_tool" value="${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/scripts/flowy-tool/Cargo.toml" />
<env name="rust_lib" value="${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/rust-lib/" />
<env name="shared_lib" value="${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/../shared_lib" />
<env name="flutter_lib" value="${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/app_flowy/packages" />
<env name="flutter_lib" value="${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/appflowy_flutter/packages" />
<env name="derive_meta" value="${shared_lib}/flowy-derive/src/derive_cache/derive_cache.rs" />
<env name="flutter_package_lib" value="${flutter_lib}/flowy_sdk/lib" />
</envs>
+1 -1
View File
@@ -1,6 +1,6 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="dart-event" type="CargoCommandRunConfiguration" factoryName="Cargo Command">
<option name="command" value="run --manifest-path $PROJECT_DIR$/scripts/flowy-tool/Cargo.toml -- dart-event --rust_source=$PROJECT_DIR$/rust-lib/ --output=$PROJECT_DIR$/app_flowy/packages/flowy_sdk/lib/dispatch/dart_event.dart" />
<option name="command" value="run --manifest-path $PROJECT_DIR$/scripts/flowy-tool/Cargo.toml -- dart-event --rust_source=$PROJECT_DIR$/rust-lib/ --output=$PROJECT_DIR$/appflowy_flutter/packages/flowy_sdk/lib/dispatch/dart_event.dart" />
<option name="workingDirectory" value="file://$PROJECT_DIR$" />
<option name="channel" value="DEFAULT" />
<option name="allFeatures" value="false" />
+19
View File
@@ -1,5 +1,24 @@
# Release Notes
## Version 0.1.2 - 03/28/2023
### Bug Fixes
- Fix: update calendar selected range.
- Fix: duplicate view.
## Version 0.1.1 - 03/21/2023
### New features
- AppFlowy brings the power of OpenAI into your AppFlowy pages. Ask AI to write anything for you in AppFlowy.
- Support adding a cover image to your page, making your pages beautiful.
- More shortcuts become available. Click on '?' at the bottom right to access our shortcut guide.
### Bug Fixes
- Fix some bugs
## Version 0.1.0 - 02/09/2023
### New features
+6 -6
View File
@@ -15,7 +15,7 @@
"RUST_LOG": "trace",
// "RUST_LOG": "debug"
},
"cwd": "${workspaceRoot}/app_flowy"
"cwd": "${workspaceRoot}/appflowy_flutter"
},
{
// This task only builds the Dart code of AppFlowy.
@@ -26,7 +26,7 @@
"env": {
"RUST_LOG": "debug"
},
"cwd": "${workspaceRoot}/app_flowy"
"cwd": "${workspaceRoot}/appflowy_flutter"
},
{
// This task builds will:
@@ -41,7 +41,7 @@
"env": {
"RUST_LOG": "trace"
},
"cwd": "${workspaceRoot}/app_flowy"
"cwd": "${workspaceRoot}/appflowy_flutter"
},
{
"name": "AF-desktop: Debug Rust",
@@ -55,7 +55,7 @@
// "program": "./lib/main.dart",
// "type": "dart",
// "flutterMode": "profile",
// "cwd": "${workspaceRoot}/app_flowy"
// "cwd": "${workspaceRoot}/appflowy_flutter"
// },
{
// This task builds the Rust and Dart code of AppFlowy for android.
@@ -67,7 +67,7 @@
"env": {
"RUST_LOG": "info"
},
"cwd": "${workspaceRoot}/app_flowy"
"cwd": "${workspaceRoot}/appflowy_flutter"
},
{
// This task builds will:
@@ -82,7 +82,7 @@
"env": {
"RUST_LOG": "info"
},
"cwd": "${workspaceRoot}/app_flowy"
"cwd": "${workspaceRoot}/appflowy_flutter"
},
{
// https://tauri.app/v1/guides/debugging/vs-code
+2 -1
View File
@@ -24,9 +24,10 @@
"svgviewer.showzoominout": true,
"editor.wordWrapColumn": 80,
"editor.minimap.maxColumn": 140,
"prettier.printWidth": 140,
"editor.wordWrap": "wordWrapColumn",
"dart.lineLength": 80,
"typescript.validate.enable": true,
"javascript.validate.enable": true,
"files.associations": {
"*.log.*": "log"
},
+18 -13
View File
@@ -96,7 +96,7 @@
"type": "shell",
"command": "flutter clean",
"options": {
"cwd": "${workspaceFolder}/app_flowy"
"cwd": "${workspaceFolder}/appflowy_flutter"
}
},
{
@@ -104,7 +104,7 @@
"type": "shell",
"command": "flutter pub get",
"options": {
"cwd": "${workspaceFolder}/app_flowy"
"cwd": "${workspaceFolder}/appflowy_flutter"
}
},
{
@@ -112,7 +112,7 @@
"type": "shell",
"command": "flutter packages pub get",
"options": {
"cwd": "${workspaceFolder}/app_flowy"
"cwd": "${workspaceFolder}/appflowy_flutter"
}
},
{
@@ -120,7 +120,7 @@
"type": "shell",
"command": "flutter pub run build_runner build --delete-conflicting-outputs",
"options": {
"cwd": "${workspaceFolder}/app_flowy"
"cwd": "${workspaceFolder}/appflowy_flutter"
}
},
{
@@ -163,14 +163,14 @@
],
"group": "build",
"problemMatcher": [],
"detail": "app_flowy"
"detail": "appflowy_flutter"
},
{
"label": "AF: Tauri UI Dev",
"type": "shell",
"isBackground": true,
"command": "npm run dev",
"problemMatcher": ["$tsc"],
"command": "yarn",
"args": ["dev"],
"options": {
"cwd": "${workspaceFolder}/appflowy_tauri"
}
@@ -179,7 +179,6 @@
"label": "AF: Tauri UI Build",
"type": "shell",
"command": "npm run build",
"problemMatcher": ["$tsc"],
"options": {
"cwd": "${workspaceFolder}/appflowy_tauri"
}
@@ -187,8 +186,7 @@
{
"label": "AF: Tauri Dev",
"type": "shell",
"command": "npm run tauri dev",
"problemMatcher": ["$tsc"],
"command": "npm run tauri:dev",
"options": {
"cwd": "${workspaceFolder}/appflowy_tauri"
}
@@ -199,8 +197,7 @@
"command": "cargo make tauri_clean",
"options": {
"cwd": "${workspaceFolder}"
},
"problemMatcher": ["$tsc"]
}
},
{
"label": "AF: Tauri Clean + Dev",
@@ -213,6 +210,14 @@
"options": {
"cwd": "${workspaceFolder}"
}
}
},
{
"label": "AF: Tauri ESLint",
"type": "shell",
"command": "npx eslint --fix src",
"options": {
"cwd": "${workspaceFolder}/appflowy_tauri"
}
},
]
}
+8 -9
View File
@@ -18,13 +18,13 @@ on_error_task = "catch"
run_task = { name = ["restore-crate-type"] }
[env]
RUST_LOG = "debug"
RUST_LOG = "info"
CARGO_MAKE_EXTEND_WORKSPACE_MAKEFILE = true
CARGO_MAKE_CRATE_FS_NAME = "dart_ffi"
CARGO_MAKE_CRATE_NAME = "dart-ffi"
LIB_NAME = "dart_ffi"
CURRENT_APP_VERSION = "0.1.0"
FLUTTER_DESKTOP_FEATURES = "flutter,rev-sqlite"
CURRENT_APP_VERSION = "0.1.2"
FLUTTER_DESKTOP_FEATURES = "dart,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
@@ -43,12 +43,11 @@ PRODUCT_NAME = "AppFlowy"
CRATE_TYPE = "staticlib"
LIB_EXT = "a"
APP_ENVIRONMENT = "local"
FLUTTER_FLOWY_SDK_PATH = "app_flowy/packages/appflowy_backend"
FLUTTER_FLOWY_SDK_PATH = "appflowy_flutter/packages/appflowy_backend"
TAURI_BACKEND_SERVICE_PATH = "appflowy_tauri/src/services/backend"
# Test default config
TEST_CRATE_TYPE = "cdylib"
TEST_LIB_EXT = "dylib"
TEST_RUST_LOG = "info"
TEST_BUILD_FLAG = "debug"
TEST_COMPILE_TARGET = "x86_64-apple-darwin"
@@ -134,7 +133,7 @@ CRATE_TYPE = "cdylib"
FLUTTER_OUTPUT_DIR = "Debug"
LIB_EXT = "so"
LINUX_ARCH = "arm64"
FLUTTER_DESKTOP_FEATURES = "flutter,rev-sqlite,openssl_vendored"
FLUTTER_DESKTOP_FEATURES = "dart,rev-sqlite,openssl_vendored"
[env.production-linux-aarch64]
BUILD_FLAG = "release"
@@ -145,7 +144,7 @@ FLUTTER_OUTPUT_DIR = "Release"
LIB_EXT = "so"
LINUX_ARCH = "arm64"
APP_ENVIRONMENT = "production"
FLUTTER_DESKTOP_FEATURES = "flutter,rev-sqlite,openssl_vendored"
FLUTTER_DESKTOP_FEATURES = "dart,rev-sqlite,openssl_vendored"
[tasks.echo_env]
script = ['''
@@ -173,14 +172,14 @@ BUILD_FLAG = "debug"
TARGET_OS = "android"
CRATE_TYPE = "cdylib"
FLUTTER_OUTPUT_DIR = "Debug"
FLUTTER_DESKTOP_FEATURES = "flutter,rev-sqlite,openssl_vendored"
FLUTTER_DESKTOP_FEATURES = "dart,rev-sqlite,openssl_vendored"
[env.production-android]
BUILD_FLAG = "release"
TARGET_OS = "android"
CRATE_TYPE = "cdylib"
FLUTTER_OUTPUT_DIR = "Release"
FLUTTER_DESKTOP_FEATURES = "flutter,rev-sqlite,openssl_vendored"
FLUTTER_DESKTOP_FEATURES = "dart,rev-sqlite,openssl_vendored"
[tasks.setup-crate-type]
private = true
-21
View File
@@ -1,21 +0,0 @@
# app_flowy
A new Flutter project.
## Getting Started
This project is a starting point for a Flutter application.
A few resources to get you started if this is your first Flutter project:
- [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab)
- [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook)
For help getting started with Flutter, view our
[online documentation](https://flutter.dev/docs), which offers tutorials,
samples, guidance on mobile development, and a full API reference.
## release check
1. [entitlements](https://flutter.dev/desktop#setting-up-entitlements)
2. [symbols stripped](https://flutter.dev/docs/development/platform-integration/c-interop)
@@ -1,327 +0,0 @@
{
"appName": "AppFlowy",
"defaultUsername": "Я",
"welcomeText": "Добро пожаловать в @:appName",
"githubStarText": "Поставить звезду на GitHub",
"subscribeNewsletterText": "Подписаться на рассылку",
"letsGoButtonText": "Начнём",
"title": "Заголовок",
"signUp": {
"buttonText": "Зарегистрироваться",
"title": "Регистрация в @:appName",
"getStartedText": "Начать",
"emptyPasswordError": "Пароль не может быть пустым",
"repeatPasswordEmptyError": "Повтор пароля не может быть пустым",
"unmatchedPasswordError": "Пароли не совпадают",
"alreadyHaveAnAccount": "Уже есть аккаунт?",
"emailHint": "Электронная почта",
"passwordHint": "Пароль",
"repeatPasswordHint": "Повторите пароль"
},
"signIn": {
"loginTitle": "Войти в @:appName",
"loginButtonText": "Войти",
"buttonText": "Авторизация",
"forgotPassword": "Забыли пароль?",
"emailHint": "Электронная почта",
"passwordHint": "Пароль",
"dontHaveAnAccount": "Нет аккаунта?",
"repeatPasswordEmptyError": "Повтор пароля не может быть пустым",
"unmatchedPasswordError": "Пароли не совпадают"
},
"workspace": {
"create": "Создать рабочее пространство",
"hint": "рабочее пространство",
"notFoundError": "Нет такого рабочего пространства"
},
"shareAction": {
"buttonText": "Поделиться",
"workInProgress": "В разработке",
"markdown": "Markdown",
"copyLink": "Скопировать ссылку"
},
"moreAction": {
"small": "маленький",
"medium": "средний",
"large": "большой",
"fontSize": "Размер шрифта"
},
"disclosureAction": {
"rename": "Переименовать",
"delete": "Удалить",
"duplicate": "Дублировать"
},
"blankPageTitle": "Пустая страница",
"newPageText": "Новая страница",
"trash": {
"text": "Корзина",
"restoreAll": "Восстановить всё",
"deleteAll": "Очистить",
"pageHeader": {
"fileName": "Имя",
"lastModified": "Последнее изменение",
"created": "Создан"
}
},
"deletePagePrompt": {
"text": "Эта страница в Корзине",
"restore": "Восстановить страницу",
"deletePermanent": "Удалить навсегда"
},
"dialogCreatePageNameHint": "Имя страницы",
"questionBubble": {
"whatsNew": "Что нового?",
"help": "Помощь",
"debug": {
"name": "Отладочная информация",
"success": "Скопировано в буфер обмена!",
"fail": "Не получилось скопировать"
}
},
"menuAppHeader": {
"addPageTooltip": "Быстро добавить новую страницу",
"defaultNewPageName": "Без заголовка",
"renameDialog": "Переименовать"
},
"toolbar": {
"undo": "Отменить",
"redo": "Повторить",
"bold": "Жирный",
"italic": "Курсив",
"underline": "Подчёркнутый",
"strike": "Зачёркнутый",
"numList": "Нумерованный список",
"bulletList": "Маркированный список",
"checkList": "Список To-Do",
"inlineCode": "Код",
"quote": "Цитата",
"header": "Заголовок",
"highlight": "Выделение",
"color": "Цвет"
},
"tooltip": {
"lightMode": "Переключить на светлую тему",
"darkMode": "Переключить на тёмную тему",
"openAsPage": "Открыть как страницу",
"addNewRow": "Добавить новую строку",
"openMenu": "Открыть меню"
},
"sideBar": {
"closeSidebar": "Закрыть боковое меню",
"openSidebar": "Открыть боковое меню"
},
"notifications": {
"export": {
"markdown": "Заметка экспортирована в Markdown",
"path": "Документы/flowy"
}
},
"contactsPage": {
"title": "Контакты",
"whatsHappening": "Что происходит на этой неделе?",
"addContact": "Новый контакт",
"editContact": "Редактировать"
},
"button": {
"OK": "OK",
"Cancel": "Отмена",
"signIn": "Войти",
"signOut": "Выйти",
"complete": "Завершить",
"save": "Сохранить"
},
"label": {
"welcome": "Добро пожаловать!",
"firstName": "Имя",
"middleName": "Отчество",
"lastName": "Фамилия",
"stepX": "Этап {X}"
},
"oAuth": {
"err": {
"failedTitle": "Ошибка подключения к аккаунту.",
"failedMsg": "Убедитесь, что вы завершили вход в своём браузере."
},
"google": {
"title": "Вход через Google",
"instruction1": "Чтобы импортировать ваши Google Контакты, вам нужно будет авторизовать приложение через браузер.",
"instruction2": "Скопируйте этот код в буфер обмена (нажав кнопку или выделив текст):",
"instruction3": "Пройдите по ссылке и введите этот код:",
"instruction4": "Нажмите на кнопку ниже, когда завершите вход:"
}
},
"settings": {
"title": "Настройки",
"menu": {
"appearance": "Внешний вид",
"language": "Язык",
"user": "Пользователь",
"files": "Файлы",
"open": "Открыть настройки"
},
"appearance": {
"themeMode": {
"label": "Режим темы",
"light": "Светлая",
"dark": "Тёмная",
"system": "Системная"
},
"theme":"Тема"
},
"files": {
"defaultLocation": "Где хранить ваши данные",
"doubleTapToCopy": "Нажмите дважды, чтобы скопировать путь",
"restoreLocation": "Восстановить путь AppFlowy по умолчанию",
"customizeLocation": "Открыть другую папку",
"restartApp": "Пожалуйста, перезапустите приложение, чтобы изменения вступили в силу.",
"exportDatabase": "Экспорт базы данных",
"selectFiles": "Выбрать файлы, которые необходимо экспортировать",
"createNewFolder": "Создать новую папку",
"createNewFolderDesc": "Указать, где хранить свои данные ...",
"open": "Открыть",
"openFolder": "Открыть существующую папку",
"openFolderDesc": "Чтение и запись в существующую папку AppFlowy ...",
"folderHintText": "имя папки",
"location": "Создание новой папки",
"locationDesc": "Выбрать имя папки данных AppFlowy",
"browser": "Обзор",
"create": "Создать",
"folderPath": "Путь к вашей папке",
"locationCannotBeEmpty": "Путь не может быть пустым"
}
},
"grid": {
"settings": {
"filter": "Фильтр",
"sort": "Сортировать",
"sortBy": "Сортировать по",
"Properties": "Свойства",
"group": "Группировать",
"addFilter": "Добавить фильтр",
"deleteFilter": "Удалить фильтр",
"filterBy": "Фильтровать по...",
"typeAValue": "Введите значение..."
},
"textFilter": {
"contains": "Содержит",
"doesNotContain": "Не содержит",
"endsWith": "Заканчивается на",
"startWith": "Начинается с",
"is": "Является",
"isNot": "Не является",
"isEmpty": "Пусто",
"isNotEmpty": "Не пусто",
"choicechipPrefix": {
"isNot": "Не является",
"startWith": "Начинается с",
"endWith": "Заканчивается на",
"isEmpty": "пусто",
"isNotEmpty": "не пусто"
}
},
"checkboxFilter": {
"isChecked": "Отмечено",
"isUnchecked": "Не отмечено",
"choicechipPrefix": {
"is": "является"
}
},
"checklistFilter": {
"isComplete": "завершено",
"isIncomplted": "не завершено"
},
"singleSelectOptionFilter": {
"is": "Является",
"isNot": "Не является",
"isEmpty": "Пусто",
"isNotEmpty": "Не пусто"
},
"multiSelectOptionFilter": {
"contains": "Содержит",
"doesNotContain": "Не содержит",
"isEmpty": "Пусто",
"isNotEmpty": "Не пусто"
},
"field": {
"hide": "Скрыть",
"insertLeft": "Вставить слева",
"insertRight": "Вставить справа",
"duplicate": "Дублировать",
"delete": "Удалить",
"textFieldName": "Текст",
"checkboxFieldName": "Чекбокс",
"dateFieldName": "Дата",
"numberFieldName": "Число",
"singleSelectFieldName": "Выбор",
"multiSelectFieldName": "Выбор нескольких",
"urlFieldName": "URL",
"checklistFieldName": "Контрольный список",
"numberFormat": "Формат числа",
"dateFormat": "Формат даты",
"includeTime": "Время",
"dateFormatFriendly": "День Месяц, Год",
"dateFormatISO": "Год-Месяц-День",
"dateFormatLocal": "Месяц/День/Год",
"dateFormatUS": "Год/Месяц/День",
"timeFormat": "Форматировать время",
"invalidTimeFormat": "Неверный формат",
"timeFormatTwelveHour": "12 часов",
"timeFormatTwentyFourHour": "24 часа",
"addSelectOption": "Добавить вариант",
"optionTitle": "Варианты",
"addOption": "Добавить",
"editProperty": "Редактировать свойство",
"newColumn": "Добавить колонку",
"deleteFieldPromptMessage": "Вы уверены? Свойство будет удалено"
},
"sort": {
"ascending": "По возрастанию",
"descending": "По убыванию",
"deleteSort": "Удалить сортировку",
"addSort": "Добавить сортировку"
},
"row": {
"duplicate": "Дублировать",
"delete": "Удалить",
"textPlaceholder": "Пусто",
"copyProperty": "Свойство скопировано",
"count": "Количество",
"newRow": "Новая строка"
},
"selectOption": {
"create": "Создать",
"purpleColor": "Фиолетовый",
"pinkColor": "Розовый",
"lightPinkColor": "Светло-розовый",
"orangeColor": "Оранжевый",
"yellowColor": "Желтый",
"limeColor": "Ярко-зелёный",
"greenColor": "Зелёный",
"aquaColor": "Бирюзовый",
"blueColor": "Синий",
"deleteTag": "Удалить вариант",
"colorPanelTitle": "Цвета",
"panelTitle": "Выберите или создайте вариант",
"searchOption": "Поиск"
},
"checklist": {
"panelTitle": "Добавить элемент"
},
"menuName": "Сетка"
},
"document": {
"menuName": "Документ",
"date": {
"timeHintTextInTwelveHour": "01:00 PM",
"timeHintTextInTwentyFourHour": "13:00"
}
},
"board": {
"column": {
"create_new_card": "Создать"
}
},
"calendar": {
"menuName": "Календарь"
}
}
@@ -1,151 +0,0 @@
import 'dart:collection';
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: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:appflowy_backend/protobuf/flowy-database/protobuf.dart';
import 'board_listener.dart';
typedef OnFieldsChanged = void Function(UnmodifiableListView<FieldInfo>);
typedef OnGridChanged = void Function(DatabasePB);
typedef DidLoadGroups = void Function(List<GroupPB>);
typedef OnUpdatedGroup = void Function(List<GroupPB>);
typedef OnDeletedGroup = void Function(List<String>);
typedef OnInsertedGroup = void Function(InsertedGroupPB);
typedef OnResetGroups = void Function(List<GroupPB>);
typedef OnRowsChanged = void Function(
List<RowInfo>,
RowsChangedReason,
);
typedef OnError = void Function(FlowyError);
class BoardDataController {
final String viewId;
final DatabaseFFIService _databaseFFIService;
final GridFieldController fieldController;
final BoardListener _listener;
late DatabaseViewCache _viewCache;
OnFieldsChanged? _onFieldsChanged;
OnGridChanged? _onGridChanged;
DidLoadGroups? _didLoadGroup;
OnRowsChanged? _onRowsChanged;
OnError? _onError;
List<RowInfo> get rowInfos => _viewCache.rowInfos;
GridRowCache get rowCache => _viewCache.rowCache;
BoardDataController({required ViewPB view})
: viewId = view.id,
_listener = BoardListener(view.id),
_databaseFFIService = DatabaseFFIService(databaseId: view.id),
fieldController = GridFieldController(databaseId: view.id) {
//
_viewCache = DatabaseViewCache(
databaseId: view.id,
fieldController: fieldController,
);
_viewCache.addListener(onRowsChanged: (reason) {
_onRowsChanged?.call(rowInfos, reason);
});
}
void addListener({
required OnGridChanged onGridChanged,
OnFieldsChanged? onFieldsChanged,
required DidLoadGroups didLoadGroups,
OnRowsChanged? onRowsChanged,
required OnUpdatedGroup onUpdatedGroup,
required OnDeletedGroup onDeletedGroup,
required OnInsertedGroup onInsertedGroup,
required OnResetGroups onResetGroups,
required OnError? onError,
}) {
_onGridChanged = onGridChanged;
_onFieldsChanged = onFieldsChanged;
_didLoadGroup = didLoadGroups;
_onRowsChanged = onRowsChanged;
_onError = onError;
fieldController.addListener(onFields: (fields) {
_onFieldsChanged?.call(UnmodifiableListView(fields));
});
_listener.start(
onBoardChanged: (result) {
result.fold(
(changeset) {
if (changeset.updateGroups.isNotEmpty) {
onUpdatedGroup.call(changeset.updateGroups);
}
if (changeset.deletedGroups.isNotEmpty) {
onDeletedGroup.call(changeset.deletedGroups);
}
for (final insertedGroup in changeset.insertedGroups) {
onInsertedGroup.call(insertedGroup);
}
},
(e) => _onError?.call(e),
);
},
onGroupByNewField: (result) {
result.fold(
(groups) => onResetGroups(groups),
(e) => _onError?.call(e),
);
},
);
}
Future<Either<Unit, FlowyError>> openGrid() async {
final result = await _databaseFFIService.openGrid();
return result.fold(
(grid) async {
_onGridChanged?.call(grid);
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),
);
}
Future<Either<RowPB, FlowyError>> createBoardCard(String groupId,
{String? startRowId}) {
return _databaseFFIService.createBoardCard(groupId, startRowId);
}
Future<void> dispose() async {
await _viewCache.dispose();
await _databaseFFIService.closeGrid();
await fieldController.dispose();
}
Future<void> _loadGroups() async {
final result = await _databaseFFIService.loadGroups();
return Future(
() => result.fold(
(groups) {
_didLoadGroup?.call(groups.items);
},
(err) => _onError?.call(err),
),
);
}
}
@@ -1,49 +0,0 @@
import 'package:app_flowy/plugins/board/presentation/card/card_cell_builder.dart';
import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart';
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:appflowy_backend/protobuf/flowy-database/row_entities.pb.dart';
import 'package:flutter/foundation.dart';
typedef OnCardChanged = void Function(GridCellMap, RowsChangedReason);
class CardDataController extends BoardCellBuilderDelegate {
final RowPB rowPB;
final GridFieldController _fieldController;
final GridRowCache _rowCache;
final List<VoidCallback> _onCardChangedListeners = [];
CardDataController({
required this.rowPB,
required GridFieldController fieldController,
required GridRowCache rowCache,
}) : _fieldController = fieldController,
_rowCache = rowCache;
GridCellMap loadData() {
return _rowCache.loadGridCells(rowPB.id);
}
void addListener({OnCardChanged? onRowChanged}) {
_onCardChangedListeners.add(_rowCache.addListener(
rowId: rowPB.id,
onCellUpdated: onRowChanged,
));
}
void dispose() {
for (final fn in _onCardChangedListeners) {
_rowCache.removeRowListener(fn);
}
}
@override
GridCellFieldNotifier buildFieldNotifier() {
return GridCellFieldNotifier(
notifier: GridCellFieldNotifierImpl(_fieldController));
}
@override
GridCellCache get cellCache => _rowCache.cellCache;
}
@@ -1,51 +0,0 @@
import 'dart:typed_data';
import 'package:app_flowy/core/grid_notification.dart';
import 'package:flowy_infra/notifier.dart';
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-database/notification.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-database/group.pb.dart';
import 'package:dartz/dartz.dart';
import 'package:appflowy_backend/protobuf/flowy-database/group_changeset.pb.dart';
typedef UpdateGroupNotifiedValue = Either<GroupRowsNotificationPB, FlowyError>;
class GroupListener {
final GroupPB group;
PublishNotifier<UpdateGroupNotifiedValue>? _groupNotifier = PublishNotifier();
DatabaseNotificationListener? _listener;
GroupListener(this.group);
void start({
required void Function(UpdateGroupNotifiedValue) onGroupChanged,
}) {
_groupNotifier?.addPublishListener(onGroupChanged);
_listener = DatabaseNotificationListener(
objectId: group.groupId,
handler: _handler,
);
}
void _handler(
DatabaseNotification ty,
Either<Uint8List, FlowyError> result,
) {
switch (ty) {
case DatabaseNotification.DidUpdateGroupRow:
result.fold(
(payload) => _groupNotifier?.value =
left(GroupRowsNotificationPB.fromBuffer(payload)),
(error) => _groupNotifier?.value = right(error),
);
break;
default:
break;
}
}
Future<void> stop() async {
await _listener?.stop();
_groupNotifier?.dispose();
_groupNotifier = null;
}
}
@@ -1,38 +0,0 @@
import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart';
import 'package:app_flowy/plugins/grid/application/cell/checklist_cell_bloc.dart';
import 'package:app_flowy/plugins/grid/presentation/widgets/cell/checklist_cell/checklist_progress_bar.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
class BoardChecklistCell extends StatefulWidget {
final GridCellControllerBuilder cellControllerBuilder;
const BoardChecklistCell({required this.cellControllerBuilder, Key? key})
: super(key: key);
@override
State<BoardChecklistCell> createState() => _BoardChecklistCellState();
}
class _BoardChecklistCellState extends State<BoardChecklistCell> {
late ChecklistCellBloc _cellBloc;
@override
void initState() {
final cellController =
widget.cellControllerBuilder.build() as GridChecklistCellController;
_cellBloc = ChecklistCellBloc(cellController: cellController);
_cellBloc.add(const ChecklistCellEvent.initial());
super.initState();
}
@override
Widget build(BuildContext context) {
return BlocProvider.value(
value: _cellBloc,
child: BlocBuilder<ChecklistCellBloc, ChecklistCellState>(
builder: (context, state) =>
ChecklistProgressBar(percent: state.percent),
),
);
}
}
@@ -1,89 +0,0 @@
import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart';
import 'package:appflowy_backend/protobuf/flowy-database/field_entities.pb.dart';
import 'package:flutter/material.dart';
import 'board_cell.dart';
import 'board_checkbox_cell.dart';
import 'board_checklist_cell.dart';
import 'board_date_cell.dart';
import 'board_number_cell.dart';
import 'board_select_option_cell.dart';
import 'board_text_cell.dart';
import 'board_url_cell.dart';
abstract class BoardCellBuilderDelegate
extends GridCellControllerBuilderDelegate {
GridCellCache get cellCache;
}
class BoardCellBuilder {
final BoardCellBuilderDelegate delegate;
BoardCellBuilder(this.delegate);
Widget buildCell(
String groupId,
GridCellIdentifier cellId,
EditableCellNotifier cellNotifier,
) {
final cellControllerBuilder = GridCellControllerBuilder(
delegate: delegate,
cellId: cellId,
cellCache: delegate.cellCache,
);
final key = cellId.key();
switch (cellId.fieldType) {
case FieldType.Checkbox:
return BoardCheckboxCell(
groupId: groupId,
cellControllerBuilder: cellControllerBuilder,
key: key,
);
case FieldType.DateTime:
return BoardDateCell(
groupId: groupId,
cellControllerBuilder: cellControllerBuilder,
key: key,
);
case FieldType.SingleSelect:
return BoardSelectOptionCell(
groupId: groupId,
cellControllerBuilder: cellControllerBuilder,
key: key,
);
case FieldType.MultiSelect:
return BoardSelectOptionCell(
groupId: groupId,
cellControllerBuilder: cellControllerBuilder,
editableNotifier: cellNotifier,
key: key,
);
case FieldType.Checklist:
return BoardChecklistCell(
cellControllerBuilder: cellControllerBuilder,
key: key,
);
case FieldType.Number:
return BoardNumberCell(
groupId: groupId,
cellControllerBuilder: cellControllerBuilder,
key: key,
);
case FieldType.RichText:
return BoardTextCell(
groupId: groupId,
cellControllerBuilder: cellControllerBuilder,
editableNotifier: cellNotifier,
key: key,
);
case FieldType.URL:
return BoardUrlCell(
groupId: groupId,
cellControllerBuilder: cellControllerBuilder,
key: key,
);
}
throw UnimplementedError;
}
}
@@ -1,162 +0,0 @@
import 'package:app_flowy/generated/locale_keys.g.dart';
import 'package:app_flowy/plugins/grid/presentation/layout/sizes.dart';
import 'package:calendar_view/calendar_view.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flowy_infra/image.dart';
import 'package:flowy_infra/size.dart';
import 'package:flowy_infra/theme_extension.dart';
import 'package:flowy_infra_ui/style_widget/button.dart';
import 'package:flowy_infra_ui/style_widget/icon_button.dart';
import 'package:flowy_infra_ui/style_widget/text.dart';
import 'package:flutter/material.dart';
import 'package:styled_widget/styled_widget.dart';
import 'layout/sizes.dart';
import 'toolbar/calendar_toolbar.dart';
class CalendarPage extends StatelessWidget {
const CalendarPage({super.key});
@override
Widget build(BuildContext context) {
return const CalendarContent();
}
}
class CalendarContent extends StatefulWidget {
const CalendarContent({super.key});
@override
State<CalendarContent> createState() => _CalendarContentState();
}
class _CalendarContentState extends State<CalendarContent> {
late EventController _eventController;
GlobalKey<MonthViewState>? _calendarState;
@override
void initState() {
_eventController = EventController();
_calendarState = GlobalKey<MonthViewState>();
super.initState();
}
@override
Widget build(BuildContext context) {
return CalendarControllerProvider(
controller: _eventController,
child: Column(
children: [
// const _ToolbarBlocAdaptor(),
_toolbar(),
_buildCalendar(_eventController),
],
),
);
}
Widget _toolbar() {
return const CalendarToolbar();
}
Widget _buildCalendar(EventController eventController) {
return Expanded(
child: MonthView(
key: _calendarState,
controller: _eventController,
cellAspectRatio: 1.75,
borderColor: Theme.of(context).dividerColor,
headerBuilder: _headerNavigatorBuilder,
weekDayBuilder: _headerWeekDayBuilder,
cellBuilder: _calendarDayBuilder,
),
);
}
Widget _headerNavigatorBuilder(DateTime currentMonth) {
return Row(
children: [
FlowyText.medium(
DateFormat('MMMM y', context.locale.toLanguageTag())
.format(currentMonth),
),
const Spacer(),
FlowyIconButton(
width: CalendarSize.navigatorButtonWidth,
height: CalendarSize.navigatorButtonHeight,
icon: svgWidget('home/arrow_left'),
tooltipText: LocaleKeys.calendar_navigation_previousMonth.tr(),
hoverColor: AFThemeExtension.of(context).lightGreyHover,
onPressed: () => _calendarState?.currentState?.previousPage(),
),
FlowyTextButton(
LocaleKeys.calendar_navigation_today.tr(),
fillColor: Colors.transparent,
fontWeight: FontWeight.w500,
tooltip: LocaleKeys.calendar_navigation_jumpToday.tr(),
padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 4),
hoverColor: AFThemeExtension.of(context).lightGreyHover,
onPressed: () =>
_calendarState?.currentState?.animateToMonth(DateTime.now()),
),
FlowyIconButton(
width: CalendarSize.navigatorButtonWidth,
height: CalendarSize.navigatorButtonHeight,
icon: svgWidget('home/arrow_right'),
tooltipText: LocaleKeys.calendar_navigation_nextMonth.tr(),
hoverColor: AFThemeExtension.of(context).lightGreyHover,
onPressed: () => _calendarState?.currentState?.nextPage(),
),
],
);
}
Widget _headerWeekDayBuilder(day) {
final symbols = DateFormat.EEEE(context.locale.toLanguageTag()).dateSymbols;
final weekDayString = symbols.WEEKDAYS[day];
return Center(
child: Padding(
padding: CalendarSize.daysOfWeekInsets,
child: FlowyText.medium(
weekDayString,
color: Theme.of(context).hintColor,
),
),
);
}
Widget _calendarDayBuilder(date, event, isToday, isInMonth) {
Color dayTextColor = Theme.of(context).colorScheme.onSurface;
Color cellBackgroundColor = Theme.of(context).colorScheme.surface;
String dayString = date.day == 1
? DateFormat('MMM d', context.locale.toLanguageTag()).format(date)
: date.day.toString();
if (isToday) {
dayTextColor = Theme.of(context).colorScheme.onPrimary;
}
if (!isInMonth) {
dayTextColor = Theme.of(context).disabledColor;
cellBackgroundColor = AFThemeExtension.of(context).lightGreyHover;
}
Widget day = Container(
decoration: BoxDecoration(
color: isToday ? Theme.of(context).colorScheme.primary : null,
borderRadius: Corners.s6Border,
),
padding: GridSize.typeOptionContentInsets,
child: FlowyText.medium(
dayString,
color: dayTextColor,
),
);
return Container(
color: cellBackgroundColor,
child: Align(
alignment: Alignment.topRight,
child: day.padding(all: 6.0),
),
);
}
}
@@ -1,378 +0,0 @@
part of 'cell_service.dart';
typedef GridTextCellController = GridCellController<String, String>;
typedef GridCheckboxCellController = GridCellController<String, String>;
typedef GridNumberCellController = GridCellController<String, String>;
typedef GridSelectOptionCellController
= GridCellController<SelectOptionCellDataPB, String>;
typedef GridChecklistCellController
= GridCellController<SelectOptionCellDataPB, String>;
typedef GridDateCellController
= GridCellController<DateCellDataPB, CalendarData>;
typedef GridURLCellController = GridCellController<URLCellDataPB, String>;
abstract class GridCellControllerBuilderDelegate {
GridCellFieldNotifier buildFieldNotifier();
}
class GridCellControllerBuilder {
final GridCellIdentifier _cellId;
final GridCellCache _cellCache;
final GridCellControllerBuilderDelegate delegate;
GridCellControllerBuilder({
required this.delegate,
required GridCellIdentifier cellId,
required GridCellCache cellCache,
}) : _cellCache = cellCache,
_cellId = cellId;
GridCellController build() {
final cellFieldNotifier = delegate.buildFieldNotifier();
switch (_cellId.fieldType) {
case FieldType.Checkbox:
final cellDataLoader = GridCellDataLoader(
cellId: _cellId,
parser: StringCellDataParser(),
);
return GridTextCellController(
cellId: _cellId,
cellCache: _cellCache,
cellDataLoader: cellDataLoader,
fieldNotifier: cellFieldNotifier,
cellDataPersistence: TextCellDataPersistence(cellId: _cellId),
);
case FieldType.DateTime:
final cellDataLoader = GridCellDataLoader(
cellId: _cellId,
parser: DateCellDataParser(),
reloadOnFieldChanged: true,
);
return GridDateCellController(
cellId: _cellId,
cellCache: _cellCache,
cellDataLoader: cellDataLoader,
fieldNotifier: cellFieldNotifier,
cellDataPersistence: DateCellDataPersistence(cellId: _cellId),
);
case FieldType.Number:
final cellDataLoader = GridCellDataLoader(
cellId: _cellId,
parser: StringCellDataParser(),
reloadOnFieldChanged: true,
);
return GridNumberCellController(
cellId: _cellId,
cellCache: _cellCache,
cellDataLoader: cellDataLoader,
fieldNotifier: cellFieldNotifier,
cellDataPersistence: TextCellDataPersistence(cellId: _cellId),
);
case FieldType.RichText:
final cellDataLoader = GridCellDataLoader(
cellId: _cellId,
parser: StringCellDataParser(),
);
return GridTextCellController(
cellId: _cellId,
cellCache: _cellCache,
cellDataLoader: cellDataLoader,
fieldNotifier: cellFieldNotifier,
cellDataPersistence: TextCellDataPersistence(cellId: _cellId),
);
case FieldType.MultiSelect:
case FieldType.SingleSelect:
case FieldType.Checklist:
final cellDataLoader = GridCellDataLoader(
cellId: _cellId,
parser: SelectOptionCellDataParser(),
reloadOnFieldChanged: true,
);
return GridSelectOptionCellController(
cellId: _cellId,
cellCache: _cellCache,
cellDataLoader: cellDataLoader,
fieldNotifier: cellFieldNotifier,
cellDataPersistence: TextCellDataPersistence(cellId: _cellId),
);
case FieldType.URL:
final cellDataLoader = GridCellDataLoader(
cellId: _cellId,
parser: URLCellDataParser(),
);
return GridURLCellController(
cellId: _cellId,
cellCache: _cellCache,
cellDataLoader: cellDataLoader,
fieldNotifier: cellFieldNotifier,
cellDataPersistence: TextCellDataPersistence(cellId: _cellId),
);
}
throw UnimplementedError;
}
}
/// IGridCellController is used to manipulate the cell and receive notifications.
/// * Read/Write cell data
/// * Listen on field/cell notifications.
///
/// Generic T represents the type of the cell data.
/// Generic D represents the type of data that will be saved to the disk
///
// ignore: must_be_immutable
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 GridCellDataPersistence<D> _cellDataPersistence;
CellListener? _cellListener;
CellDataNotifier<T?>? _cellDataNotifier;
bool isListening = false;
VoidCallback? _onFieldChangedFn;
Timer? _loadDataOperation;
Timer? _saveDataOperation;
bool _isDispose = false;
GridCellController({
required this.cellId,
required GridCellCache cellCache,
required GridCellFieldNotifier fieldNotifier,
required GridCellDataLoader<T> cellDataLoader,
required GridCellDataPersistence<D> cellDataPersistence,
}) : _cellsCache = cellCache,
_cellDataLoader = cellDataLoader,
_cellDataPersistence = cellDataPersistence,
_fieldNotifier = fieldNotifier,
_fieldService = FieldService(
databaseId: cellId.databaseId,
fieldId: cellId.fieldInfo.id,
),
_cacheKey = GridCellCacheKey(
rowId: cellId.rowId,
fieldId: cellId.fieldInfo.id,
);
String get databaseId => cellId.databaseId;
String get rowId => cellId.rowId;
String get fieldId => cellId.fieldInfo.id;
FieldInfo get fieldInfo => cellId.fieldInfo;
FieldType get fieldType => cellId.fieldInfo.fieldType;
/// Listen on the cell content or field changes
///
/// An optional [listenWhenOnCellChanged] can be implemented for more
/// granular control over when [listener] is called.
/// [listenWhenOnCellChanged] will be invoked on each [onCellChanged]
/// get called.
/// [listenWhenOnCellChanged] takes the previous `value` and current
/// `value` and must return a [bool] which determines whether or not
/// the [onCellChanged] function will be invoked.
/// [onCellChanged] is optional and if omitted, it will default to `true`.
///
VoidCallback? startListening({
required void Function(T?) onCellChanged,
bool Function(T? oldValue, T? newValue)? listenWhenOnCellChanged,
VoidCallback? onCellFieldChanged,
}) {
if (isListening) {
Log.error("Already started. It seems like you should call clone first");
return null;
}
isListening = true;
_cellDataNotifier = CellDataNotifier(
value: _cellsCache.get(_cacheKey),
listenWhen: listenWhenOnCellChanged,
);
_cellListener =
CellListener(rowId: cellId.rowId, fieldId: cellId.fieldInfo.id);
/// 1.Listen on user edit event and load the new cell data if needed.
/// For example:
/// user input: 12
/// cell display: $12
_cellListener?.start(onCellChanged: (result) {
result.fold(
(_) {
_cellsCache.remove(_cacheKey);
_loadData();
},
(err) => Log.error(err),
);
});
/// 2.Listen on the field event and load the cell data if needed.
_onFieldChangedFn = () {
if (onCellFieldChanged != null) {
onCellFieldChanged();
}
/// reloadOnFieldChanged should be true if you need to load the data when the corresponding field is changed
/// For example:
/// ¥12 -> $12
if (_cellDataLoader.reloadOnFieldChanged) {
_loadData();
}
};
_fieldNotifier.register(_cacheKey, _onFieldChangedFn!);
/// Notify the listener, the cell data was changed.
onCellChangedFn() => onCellChanged(_cellDataNotifier?.value);
_cellDataNotifier?.addListener(onCellChangedFn);
// Return the function pointer that can be used when calling removeListener.
return onCellChangedFn;
}
void removeListener(VoidCallback fn) {
_cellDataNotifier?.removeListener(fn);
}
/// Return the cell data.
/// The cell data will be read from the Cache first, and load from disk if it does not exist.
/// You can set [loadIfNotExist] to false (default is true) to disable loading the cell data.
T? getCellData({bool loadIfNotExist = true}) {
final data = _cellsCache.get(_cacheKey);
if (data == null && loadIfNotExist) {
_loadData();
}
return data;
}
/// Return the TypeOptionPB that can be parsed into corresponding class using the [parser].
/// [PD] is the type that the parser return.
Future<Either<PD, FlowyError>>
getFieldTypeOption<PD, P extends TypeOptionDataParser>(P parser) {
return _fieldService
.getFieldTypeOptionData(fieldType: fieldType)
.then((result) {
return result.fold(
(data) => left(parser.fromBuffer(data.typeOptionData)),
(err) => right(err),
);
});
}
/// Save the cell data to disk
/// You can set [deduplicate] to true (default is false) to reduce the save operation.
/// It's useful when you call this method when user editing the [TextField].
/// The default debounce interval is 300 milliseconds.
Future<void> saveCellData(
D data, {
bool deduplicate = false,
void Function(Option<FlowyError>)? onFinish,
}) async {
_loadDataOperation?.cancel();
if (deduplicate) {
_saveDataOperation?.cancel();
_saveDataOperation = Timer(const Duration(milliseconds: 300), () async {
final result = await _cellDataPersistence.save(data);
onFinish?.call(result);
});
} else {
final result = await _cellDataPersistence.save(data);
onFinish?.call(result);
}
}
void _loadData() {
_saveDataOperation?.cancel();
_loadDataOperation?.cancel();
_loadDataOperation = Timer(const Duration(milliseconds: 10), () {
_cellDataLoader.loadData().then((data) {
if (data != null) {
_cellsCache.insert(_cacheKey, GridCell(object: data));
} else {
_cellsCache.remove(_cacheKey);
}
_cellDataNotifier?.value = data;
});
});
}
Future<void> dispose() async {
if (_isDispose) {
Log.error("$this should only dispose once");
return;
}
_isDispose = true;
await _cellListener?.stop();
_loadDataOperation?.cancel();
_saveDataOperation?.cancel();
_cellDataNotifier?.dispose();
_cellDataNotifier = null;
if (_onFieldChangedFn != null) {
_fieldNotifier.unregister(_cacheKey, _onFieldChangedFn!);
await _fieldNotifier.dispose();
_onFieldChangedFn = null;
}
}
@override
List<Object> get props =>
[_cellsCache.get(_cacheKey) ?? "", cellId.rowId + cellId.fieldInfo.id];
}
class GridCellFieldNotifierImpl extends IGridCellFieldNotifier {
final GridFieldController _fieldController;
OnReceiveUpdateFields? _onChangesetFn;
GridCellFieldNotifierImpl(GridFieldController cache)
: _fieldController = cache;
@override
void onCellDispose() {
if (_onChangesetFn != null) {
_fieldController.removeListener(onChangesetListener: _onChangesetFn!);
_onChangesetFn = null;
}
}
@override
void onCellFieldChanged(void Function(FieldInfo) callback) {
_onChangesetFn = (List<FieldInfo> filedInfos) {
for (final field in filedInfos) {
callback(field);
}
};
_fieldController.addListener(
onFieldsUpdated: _onChangesetFn,
);
}
}
class CellDataNotifier<T> extends ChangeNotifier {
T _value;
bool Function(T? oldValue, T? newValue)? listenWhen;
CellDataNotifier({required T value, this.listenWhen}) : _value = value;
set value(T newValue) {
if (listenWhen?.call(_value, newValue) ?? false) {
_value = newValue;
notifyListeners();
} else {
if (_value != newValue) {
_value = newValue;
notifyListeners();
}
}
}
T get value => _value;
}
@@ -1,64 +0,0 @@
import 'package:app_flowy/plugins/grid/application/field/field_controller.dart';
import 'package:flutter/foundation.dart';
import 'cell_service.dart';
abstract class IGridCellFieldNotifier {
void onCellFieldChanged(void Function(FieldInfo) callback);
void onCellDispose();
}
/// DatabasePB's cell helper wrapper that enables each cell will get notified when the corresponding field was changed.
/// You Register an onFieldChanged callback to listen to the cell changes, and unregister if you don't want to listen.
class GridCellFieldNotifier {
final IGridCellFieldNotifier notifier;
/// fieldId: {objectId: callback}
final Map<String, Map<String, List<VoidCallback>>> _fieldListenerByFieldId =
{};
GridCellFieldNotifier({required this.notifier}) {
notifier.onCellFieldChanged(
(field) {
final map = _fieldListenerByFieldId[field.id];
if (map != null) {
for (final callbacks in map.values) {
for (final callback in callbacks) {
callback();
}
}
}
},
);
}
///
void register(GridCellCacheKey cacheKey, VoidCallback onFieldChanged) {
var map = _fieldListenerByFieldId[cacheKey.fieldId];
if (map == null) {
_fieldListenerByFieldId[cacheKey.fieldId] = {};
map = _fieldListenerByFieldId[cacheKey.fieldId];
map![cacheKey.rowId] = [onFieldChanged];
} else {
var objects = map[cacheKey.rowId];
if (objects == null) {
map[cacheKey.rowId] = [onFieldChanged];
} else {
objects.add(onFieldChanged);
}
}
}
void unregister(GridCellCacheKey cacheKey, VoidCallback fn) {
var callbacks = _fieldListenerByFieldId[cacheKey.fieldId]?[cacheKey.rowId];
final index = callbacks?.indexWhere((callback) => callback == fn);
if (index != null && index != -1) {
callbacks?.removeAt(index);
}
}
Future<void> dispose() async {
notifier.onCellDispose();
_fieldListenerByFieldId.clear();
}
}
@@ -1,47 +0,0 @@
import 'package:app_flowy/core/grid_notification.dart';
import 'package:dartz/dartz.dart';
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-database/notification.pb.dart';
import 'package:flowy_infra/notifier.dart';
import 'dart:async';
import 'dart:typed_data';
import 'package:appflowy_backend/protobuf/flowy-database/field_entities.pb.dart';
typedef UpdateFieldNotifiedValue = Either<DatabaseFieldChangesetPB, FlowyError>;
class DatabaseFieldsListener {
final String databaseId;
PublishNotifier<UpdateFieldNotifiedValue>? updateFieldsNotifier =
PublishNotifier();
DatabaseNotificationListener? _listener;
DatabaseFieldsListener({required this.databaseId});
void start(
{required void Function(UpdateFieldNotifiedValue) onFieldsChanged}) {
updateFieldsNotifier?.addPublishListener(onFieldsChanged);
_listener = DatabaseNotificationListener(
objectId: databaseId,
handler: _handler,
);
}
void _handler(DatabaseNotification ty, Either<Uint8List, FlowyError> result) {
switch (ty) {
case DatabaseNotification.DidUpdateFields:
result.fold(
(payload) => updateFieldsNotifier?.value =
left(DatabaseFieldChangesetPB.fromBuffer(payload)),
(error) => updateFieldsNotifier?.value = right(error),
);
break;
default:
break;
}
}
Future<void> stop() async {
await _listener?.stop();
updateFieldsNotifier?.dispose();
updateFieldsNotifier = null;
}
}
@@ -1,86 +0,0 @@
import 'package:app_flowy/plugins/grid/presentation/widgets/filter/filter_info.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-database/grid_entities.pb.dart';
import 'dart:async';
import 'package:dartz/dartz.dart';
import 'view/grid_view_cache.dart';
import 'field/field_controller.dart';
import 'prelude.dart';
import 'row/row_cache.dart';
typedef OnFieldsChanged = void Function(List<FieldInfo>);
typedef OnFiltersChanged = void Function(List<FilterInfo>);
typedef OnGridChanged = void Function(DatabasePB);
typedef OnRowsChanged = void Function(
List<RowInfo> rowInfos,
RowsChangedReason,
);
typedef ListenOnRowChangedCondition = bool Function();
class GridController {
final String databaseId;
final DatabaseFFIService _gridFFIService;
final GridFieldController fieldController;
late DatabaseViewCache _viewCache;
OnRowsChanged? _onRowChanged;
OnGridChanged? _onGridChanged;
List<RowInfo> get rowInfos => _viewCache.rowInfos;
GridRowCache get rowCache => _viewCache.rowCache;
GridController({required ViewPB view})
: databaseId = view.id,
_gridFFIService = DatabaseFFIService(databaseId: view.id),
fieldController = GridFieldController(databaseId: view.id) {
_viewCache = DatabaseViewCache(
databaseId: databaseId,
fieldController: fieldController,
);
_viewCache.addListener(onRowsChanged: (reason) {
_onRowChanged?.call(rowInfos, reason);
});
}
void addListener({
OnGridChanged? onGridChanged,
OnRowsChanged? onRowsChanged,
OnFieldsChanged? onFieldsChanged,
OnFiltersChanged? onFiltersChanged,
}) {
_onGridChanged = onGridChanged;
_onRowChanged = onRowsChanged;
fieldController.addListener(
onFields: onFieldsChanged,
onFilters: onFiltersChanged,
);
}
// Loads the rows from each block
Future<Either<Unit, FlowyError>> openGrid() async {
return _gridFFIService.openGrid().then((result) {
return result.fold(
(grid) async {
_onGridChanged?.call(grid);
_viewCache.rowCache.initializeRows(grid.rows);
final result = await fieldController.loadFields(
fieldIds: grid.fields,
);
return result;
},
(err) => right(err),
);
});
}
Future<void> createRow() async {
await _gridFFIService.createRow();
}
Future<void> dispose() async {
await _gridFFIService.closeGrid();
await fieldController.dispose();
}
}
@@ -1,65 +0,0 @@
import 'package:dartz/dartz.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-database/field_entities.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-database/grid_entities.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-database/group.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-database/row_entities.pb.dart';
class DatabaseFFIService {
final String databaseId;
DatabaseFFIService({
required this.databaseId,
});
Future<Either<DatabasePB, FlowyError>> openGrid() async {
await FolderEventSetLatestView(ViewIdPB(value: databaseId)).send();
final payload = DatabaseIdPB(value: databaseId);
return DatabaseEventGetDatabase(payload).send();
}
Future<Either<RowPB, FlowyError>> createRow({Option<String>? startRowId}) {
var payload = CreateRowPayloadPB.create()..databaseId = databaseId;
startRowId?.fold(() => null, (id) => payload.startRowId = id);
return DatabaseEventCreateRow(payload).send();
}
Future<Either<RowPB, FlowyError>> createBoardCard(
String groupId,
String? startRowId,
) {
CreateBoardCardPayloadPB payload = CreateBoardCardPayloadPB.create()
..databaseId = databaseId
..groupId = groupId;
if (startRowId != null) {
payload.startRowId = startRowId;
}
return DatabaseEventCreateBoardCard(payload).send();
}
Future<Either<List<FieldPB>, FlowyError>> getFields(
{List<FieldIdPB>? fieldIds}) {
var payload = GetFieldPayloadPB.create()..databaseId = databaseId;
if (fieldIds != null) {
payload.fieldIds = RepeatedFieldIdPB(items: fieldIds);
}
return DatabaseEventGetFields(payload).send().then((result) {
return result.fold((l) => left(l.items), (r) => right(r));
});
}
Future<Either<Unit, FlowyError>> closeGrid() {
final request = ViewIdPB(value: databaseId);
return FolderEventCloseView(request).send();
}
Future<Either<RepeatedGroupPB, FlowyError>> loadGroups() {
final payload = DatabaseIdPB(value: databaseId);
return DatabaseEventGetGroup(payload).send();
}
}
@@ -1,28 +0,0 @@
export 'grid_bloc.dart';
export 'row/row_bloc.dart';
export 'row/row_service.dart';
export 'grid_service.dart';
export 'grid_header_bloc.dart';
// FieldPB
export 'field/field_service.dart';
export 'field/field_action_sheet_bloc.dart';
export 'field/field_editor_bloc.dart';
export 'field/field_type_option_edit_bloc.dart';
// FieldPB Type Option
export 'field/type_option/date_bloc.dart';
export 'field/type_option/number_bloc.dart';
export 'field/type_option/single_select_type_option.dart';
// CellPB
export 'cell/text_cell_bloc.dart';
export 'cell/number_cell_bloc.dart';
export 'cell/select_option_cell_bloc.dart';
export 'cell/date_cell_bloc.dart';
export 'cell/checkbox_cell_bloc.dart';
export 'cell/cell_service/cell_service.dart';
// Setting
export 'setting/setting_bloc.dart';
export 'setting/property_bloc.dart';
@@ -1,49 +0,0 @@
import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_field_notifier.dart';
import 'package:flutter/material.dart';
import '../../presentation/widgets/cell/cell_builder.dart';
import '../cell/cell_service/cell_service.dart';
import '../field/field_controller.dart';
import 'row_cache.dart';
typedef OnRowChanged = void Function(GridCellMap, RowsChangedReason);
class RowDataController extends GridCellBuilderDelegate {
final RowInfo rowInfo;
final List<VoidCallback> _onRowChangedListeners = [];
final GridFieldController _fieldController;
final GridRowCache _rowCache;
RowDataController({
required this.rowInfo,
required GridFieldController fieldController,
required GridRowCache rowCache,
}) : _fieldController = fieldController,
_rowCache = rowCache;
GridCellMap loadData() {
return _rowCache.loadGridCells(rowInfo.rowPB.id);
}
void addListener({OnRowChanged? onRowChanged}) {
_onRowChangedListeners.add(_rowCache.addListener(
rowId: rowInfo.rowPB.id,
onCellUpdated: onRowChanged,
));
}
void dispose() {
for (final fn in _onRowChangedListeners) {
_rowCache.removeRowListener(fn);
}
}
// GridCellBuilderDelegate implementation
@override
GridCellFieldNotifier buildFieldNotifier() {
return GridCellFieldNotifier(
notifier: GridCellFieldNotifierImpl(_fieldController));
}
@override
GridCellCache get cellCache => _rowCache.cellCache;
}
@@ -1,95 +0,0 @@
import 'package:dartz/dartz.dart';
import 'package:appflowy_backend/dispatch/dispatch.dart';
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-database/grid_entities.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-database/group_changeset.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-database/row_entities.pb.dart';
class RowFFIService {
final String databaseId;
RowFFIService({
required this.databaseId,
});
Future<Either<RowPB, FlowyError>> createRow(String rowId) {
final payload = CreateRowPayloadPB.create()
..databaseId = databaseId
..startRowId = rowId;
return DatabaseEventCreateRow(payload).send();
}
Future<Either<OptionalRowPB, FlowyError>> getRow(String rowId) {
final payload = RowIdPB.create()
..databaseId = databaseId
..rowId = rowId;
return DatabaseEventGetRow(payload).send();
}
Future<Either<Unit, FlowyError>> deleteRow(String rowId) {
final payload = RowIdPB.create()
..databaseId = databaseId
..rowId = rowId;
return DatabaseEventDeleteRow(payload).send();
}
Future<Either<Unit, FlowyError>> duplicateRow(String rowId) {
final payload = RowIdPB.create()
..databaseId = databaseId
..rowId = rowId;
return DatabaseEventDuplicateRow(payload).send();
}
}
class MoveRowFFIService {
final String viewId;
MoveRowFFIService({
required this.viewId,
});
Future<Either<Unit, FlowyError>> moveRow({
required String fromRowId,
required String toRowId,
}) {
var payload = MoveRowPayloadPB.create()
..viewId = viewId
..fromRowId = fromRowId
..toRowId = toRowId;
return DatabaseEventMoveRow(payload).send();
}
Future<Either<Unit, FlowyError>> moveGroupRow({
required String fromRowId,
required String toGroupId,
required String? toRowId,
}) {
var payload = MoveGroupRowPayloadPB.create()
..viewId = viewId
..fromRowId = fromRowId
..toGroupId = toGroupId;
if (toRowId != null) {
payload.toRowId = toRowId;
}
return DatabaseEventMoveGroupRow(payload).send();
}
Future<Either<Unit, FlowyError>> moveGroup({
required String fromGroupId,
required String toGroupId,
}) {
final payload = MoveGroupPayloadPB.create()
..viewId = viewId
..fromGroupId = fromGroupId
..toGroupId = toGroupId;
return DatabaseEventMoveGroup(payload).send();
}
}
@@ -1,48 +0,0 @@
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'dart:async';
import 'package:dartz/dartz.dart';
part 'setting_bloc.freezed.dart';
class GridSettingBloc extends Bloc<GridSettingEvent, GridSettingState> {
final String databaseId;
GridSettingBloc({required this.databaseId})
: super(GridSettingState.initial()) {
on<GridSettingEvent>(
(event, emit) async {
event.map(performAction: (_PerformAction value) {
emit(state.copyWith(selectedAction: Some(value.action)));
});
},
);
}
@override
Future<void> close() async {
return super.close();
}
}
@freezed
class GridSettingEvent with _$GridSettingEvent {
const factory GridSettingEvent.performAction(GridSettingAction action) =
_PerformAction;
}
@freezed
class GridSettingState with _$GridSettingState {
const factory GridSettingState({
required Option<GridSettingAction> selectedAction,
}) = _GridSettingState;
factory GridSettingState.initial() => GridSettingState(
selectedAction: none(),
);
}
enum GridSettingAction {
showFilters,
sortBy,
showProperties,
}
@@ -1,73 +0,0 @@
/// The data structor representing each selection of flowy table.
enum FlowyTableSelectionType {
item,
row,
col,
}
class FlowyTableSelectionItem {
final FlowyTableSelectionType type;
final int? row;
final int? column;
const FlowyTableSelectionItem({
required this.type,
this.row,
this.column,
});
@override
String toString() {
return '$type($row, $column)';
}
@override
bool operator ==(Object other) {
if (identical(this, other)) {
return true;
}
return other is FlowyTableSelectionItem &&
type == other.type &&
row == other.row &&
column == other.column;
}
@override
int get hashCode => type.hashCode ^ row.hashCode ^ column.hashCode;
}
class FlowyTableSelection {
Set<FlowyTableSelectionItem> _items = {};
Set<FlowyTableSelectionItem> get items => _items;
FlowyTableSelection(
this._items,
);
FlowyTableSelection.combine(
FlowyTableSelection lhs, FlowyTableSelection rhs) {
this..combine(lhs)..combine(rhs);
}
FlowyTableSelection operator +(FlowyTableSelection other) {
return this..combine(other);
}
void combine(FlowyTableSelection other) {
var totalItems = items..union(other.items);
final rows = totalItems
.where((ele) => ele.type == FlowyTableSelectionType.row)
.map((e) => e.row)
.toSet();
final cols = totalItems
.where((ele) => ele.type == FlowyTableSelectionType.col)
.map((e) => e.column)
.toSet();
totalItems.removeWhere((ele) {
return ele.type == FlowyTableSelectionType.item &&
(rows.contains(ele.row) || cols.contains(ele.column));
});
_items = totalItems;
}
}
@@ -1,7 +0,0 @@
export 'cell_builder.dart';
export 'text_cell.dart';
export 'number_cell.dart';
export 'date_cell/date_cell.dart';
export 'checkbox_cell.dart';
export 'select_option_cell/select_option_cell.dart';
export 'url_cell/url_cell.dart';
@@ -1,9 +0,0 @@
import 'package:app_flowy/util/file_picker/file_picker_service.dart';
import 'package:file_picker/file_picker.dart' as fp;
class FilePicker implements FilePickerService {
@override
Future<String?> getDirectoryPath({String? title}) {
return fp.FilePicker.platform.getDirectoryPath();
}
}
@@ -1,16 +0,0 @@
import 'package:file_picker/file_picker.dart';
class FilePickerResult {
const FilePickerResult(this.files);
/// Picked files.
final List<PlatformFile> files;
}
/// Abstract file picker as a service to implement dependency injection.
abstract class FilePickerService {
Future<String?> getDirectoryPath({
String? title,
}) async =>
throw UnimplementedError('getDirectoryPath() has not been implemented.');
}
@@ -1,62 +0,0 @@
import 'package:app_flowy/startup/plugin/plugin.dart';
import 'package:app_flowy/workspace/presentation/widgets/pop_up_action.dart';
import 'package:appflowy_popover/appflowy_popover.dart';
import 'package:flowy_infra/image.dart';
import 'package:flowy_infra_ui/style_widget/icon_button.dart';
import 'package:flutter/material.dart';
import 'package:styled_widget/styled_widget.dart';
class AddButton extends StatelessWidget {
final Function(PluginBuilder) onSelected;
const AddButton({
Key? key,
required this.onSelected,
}) : super(key: key);
@override
Widget build(BuildContext context) {
final List<PopoverAction> actions = [];
actions.addAll(
pluginBuilders()
.map((pluginBuilder) =>
AddButtonActionWrapper(pluginBuilder: pluginBuilder))
.toList(),
);
return PopoverActionList<PopoverAction>(
direction: PopoverDirection.bottomWithLeftAligned,
actions: actions,
buildChild: (controller) {
return FlowyIconButton(
width: 22,
onPressed: () => controller.show(),
icon: svgWidget(
"home/add",
color: Theme.of(context).colorScheme.onSurface,
).padding(horizontal: 3, vertical: 3),
);
},
onSelected: (action, controller) {
if (action is AddButtonActionWrapper) {
onSelected(action.pluginBuilder);
}
controller.close();
},
);
}
}
class AddButtonActionWrapper extends ActionCell {
final PluginBuilder pluginBuilder;
AddButtonActionWrapper({required this.pluginBuilder});
@override
Widget? leftIcon(Color iconColor) =>
svgWidget(pluginBuilder.menuIcon, color: iconColor);
@override
String get name => pluginBuilder.menuName;
}
@@ -1,31 +0,0 @@
//
// Generated file. Do not edit.
//
// clang-format off
#include "generated_plugin_registrant.h"
#include <flowy_infra_ui/flowy_infra_u_i_plugin.h>
#include <hotkey_manager/hotkey_manager_plugin.h>
#include <rich_clipboard_linux/rich_clipboard_plugin.h>
#include <url_launcher_linux/url_launcher_plugin.h>
#include <window_size/window_size_plugin.h>
void fl_register_plugins(FlPluginRegistry* registry) {
g_autoptr(FlPluginRegistrar) flowy_infra_ui_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "FlowyInfraUIPlugin");
flowy_infra_u_i_plugin_register_with_registrar(flowy_infra_ui_registrar);
g_autoptr(FlPluginRegistrar) hotkey_manager_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "HotkeyManagerPlugin");
hotkey_manager_plugin_register_with_registrar(hotkey_manager_registrar);
g_autoptr(FlPluginRegistrar) rich_clipboard_linux_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "RichClipboardPlugin");
rich_clipboard_plugin_register_with_registrar(rich_clipboard_linux_registrar);
g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin");
url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar);
g_autoptr(FlPluginRegistrar) window_size_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "WindowSizePlugin");
window_size_plugin_register_with_registrar(window_size_registrar);
}
@@ -1,15 +0,0 @@
//
// Generated file. Do not edit.
//
// clang-format off
#ifndef GENERATED_PLUGIN_REGISTRANT_
#define GENERATED_PLUGIN_REGISTRANT_
#include <flutter_linux/flutter_linux.h>
// Registers Flutter plugins.
void fl_register_plugins(FlPluginRegistry* registry);
#endif // GENERATED_PLUGIN_REGISTRANT_
@@ -1,28 +0,0 @@
#
# Generated file, do not edit.
#
list(APPEND FLUTTER_PLUGIN_LIST
flowy_infra_ui
hotkey_manager
rich_clipboard_linux
url_launcher_linux
window_size
)
list(APPEND FLUTTER_FFI_PLUGIN_LIST
)
set(PLUGIN_BUNDLED_LIBRARIES)
foreach(plugin ${FLUTTER_PLUGIN_LIST})
add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin})
target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin)
list(APPEND PLUGIN_BUNDLED_LIBRARIES $<TARGET_FILE:${plugin}_plugin>)
list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries})
endforeach(plugin)
foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST})
add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin})
list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries})
endforeach(ffi_plugin)
@@ -1,32 +0,0 @@
//
// Generated file. Do not edit.
//
import FlutterMacOS
import Foundation
import appflowy_backend
import connectivity_plus_macos
import device_info_plus_macos
import flowy_infra_ui
import hotkey_manager
import package_info_plus_macos
import path_provider_macos
import rich_clipboard_macos
import shared_preferences_macos
import url_launcher_macos
import window_size
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
AppFlowyBackendPlugin.register(with: registry.registrar(forPlugin: "AppFlowyBackendPlugin"))
ConnectivityPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlugin"))
DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin"))
FlowyInfraUIPlugin.register(with: registry.registrar(forPlugin: "FlowyInfraUIPlugin"))
HotkeyManagerPlugin.register(with: registry.registrar(forPlugin: "HotkeyManagerPlugin"))
FLTPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FLTPackageInfoPlusPlugin"))
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
RichClipboardPlugin.register(with: registry.registrar(forPlugin: "RichClipboardPlugin"))
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
WindowSizePlugin.register(with: registry.registrar(forPlugin: "WindowSizePlugin"))
}
@@ -1,12 +0,0 @@
//
// Generated file. Do not edit.
//
import FlutterMacOS
import Foundation
import appflowy_backend
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
AppFlowyBackendPlugin.register(with: registry.registrar(forPlugin: "AppFlowyBackendPlugin"))
}
@@ -1,14 +0,0 @@
//
// Generated file. Do not edit.
//
// clang-format off
#include "generated_plugin_registrant.h"
#include <appflowy_backend/app_flowy_backend_plugin.h>
void RegisterPlugins(flutter::PluginRegistry* registry) {
AppFlowyBackendPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("AppFlowyBackendPlugin"));
}
@@ -1,15 +0,0 @@
//
// Generated file. Do not edit.
//
// clang-format off
#ifndef GENERATED_PLUGIN_REGISTRANT_
#define GENERATED_PLUGIN_REGISTRANT_
#include <flutter/plugin_registry.h>
// Registers Flutter plugins.
void RegisterPlugins(flutter::PluginRegistry* registry);
#endif // GENERATED_PLUGIN_REGISTRANT_
@@ -1,24 +0,0 @@
#
# Generated file, do not edit.
#
list(APPEND FLUTTER_PLUGIN_LIST
appflowy_backend
)
list(APPEND FLUTTER_FFI_PLUGIN_LIST
)
set(PLUGIN_BUNDLED_LIBRARIES)
foreach(plugin ${FLUTTER_PLUGIN_LIST})
add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin})
target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin)
list(APPEND PLUGIN_BUNDLED_LIBRARIES $<TARGET_FILE:${plugin}_plugin>)
list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries})
endforeach(plugin)
foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST})
add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin})
list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries})
endforeach(ffi_plugin)
@@ -1,82 +0,0 @@
#include "include/appflowy_backend/app_flowy_backend_plugin.h"
// This must be included before many other Windows headers.
#include <windows.h>
// For getPlatformVersion; remove unless needed for your plugin implementation.
#include <VersionHelpers.h>
#include <flutter/method_channel.h>
#include <flutter/plugin_registrar_windows.h>
#include <flutter/standard_method_codec.h>
#include <map>
#include <memory>
#include <sstream>
namespace {
class AppFlowyBackendPlugin : public flutter::Plugin {
public:
static void RegisterWithRegistrar(flutter::PluginRegistrarWindows *registrar);
AppFlowyBackendPlugin();
virtual ~AppFlowyBackendPlugin();
private:
// Called when a method is called on this plugin's channel from Dart.
void HandleMethodCall(
const flutter::MethodCall<flutter::EncodableValue> &method_call,
std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>> result);
};
// static
void AppFlowyBackendPlugin::RegisterWithRegistrar(
flutter::PluginRegistrarWindows *registrar) {
auto channel =
std::make_unique<flutter::MethodChannel<flutter::EncodableValue>>(
registrar->messenger(), "appflowy_backend",
&flutter::StandardMethodCodec::GetInstance());
auto plugin = std::make_unique<AppFlowyBackendPlugin>();
channel->SetMethodCallHandler(
[plugin_pointer = plugin.get()](const auto &call, auto result) {
plugin_pointer->HandleMethodCall(call, std::move(result));
});
registrar->AddPlugin(std::move(plugin));
}
AppFlowyBackendPlugin::AppFlowyBackendPlugin() {}
AppFlowyBackendPlugin::~AppFlowyBackendPlugin() {}
void AppFlowyBackendPlugin::HandleMethodCall(
const flutter::MethodCall<flutter::EncodableValue> &method_call,
std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>> result) {
if (method_call.method_name().compare("getPlatformVersion") == 0) {
std::ostringstream version_stream;
version_stream << "Windows ";
if (IsWindows10OrGreater()) {
version_stream << "10+";
} else if (IsWindows8OrGreater()) {
version_stream << "8";
} else if (IsWindows7OrGreater()) {
version_stream << "7";
}
result->Success(flutter::EncodableValue(version_stream.str()));
} else {
result->NotImplemented();
}
}
} // namespace
void AppFlowyBackendPluginRegisterWithRegistrar(
FlutterDesktopPluginRegistrarRef registrar) {
AppFlowyBackendPlugin::RegisterWithRegistrar(
flutter::PluginRegistrarManager::GetInstance()
->GetRegistrar<flutter::PluginRegistrarWindows>(registrar));
}
@@ -1,12 +0,0 @@
#include "include/appflowy_backend/appflowy_backend_plugin_c_api.h"
#include <flutter/plugin_registrar_windows.h>
#include "app_flowy_backend_plugin.h"
void AppFlowyBackendPluginCApiRegisterWithRegistrar(
FlutterDesktopPluginRegistrarRef registrar) {
appflowy_backend::AppFlowyBackendPlugin::RegisterWithRegistrar(
flutter::PluginRegistrarManager::GetInstance()
->GetRegistrar<flutter::PluginRegistrarWindows>(registrar));
}
@@ -1,23 +0,0 @@
//
// Generated file. Do not edit.
//
// clang-format off
#include "generated_plugin_registrant.h"
#include <flowy_infra_ui/flowy_infra_u_i_plugin.h>
#include <rich_clipboard_linux/rich_clipboard_plugin.h>
#include <url_launcher_linux/url_launcher_plugin.h>
void fl_register_plugins(FlPluginRegistry* registry) {
g_autoptr(FlPluginRegistrar) flowy_infra_ui_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "FlowyInfraUIPlugin");
flowy_infra_u_i_plugin_register_with_registrar(flowy_infra_ui_registrar);
g_autoptr(FlPluginRegistrar) rich_clipboard_linux_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "RichClipboardPlugin");
rich_clipboard_plugin_register_with_registrar(rich_clipboard_linux_registrar);
g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin");
url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar);
}
@@ -1,15 +0,0 @@
//
// Generated file. Do not edit.
//
// clang-format off
#ifndef GENERATED_PLUGIN_REGISTRANT_
#define GENERATED_PLUGIN_REGISTRANT_
#include <flutter_linux/flutter_linux.h>
// Registers Flutter plugins.
void fl_register_plugins(FlPluginRegistry* registry);
#endif // GENERATED_PLUGIN_REGISTRANT_
@@ -1,26 +0,0 @@
#
# Generated file, do not edit.
#
list(APPEND FLUTTER_PLUGIN_LIST
flowy_infra_ui
rich_clipboard_linux
url_launcher_linux
)
list(APPEND FLUTTER_FFI_PLUGIN_LIST
)
set(PLUGIN_BUNDLED_LIBRARIES)
foreach(plugin ${FLUTTER_PLUGIN_LIST})
add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin})
target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin)
list(APPEND PLUGIN_BUNDLED_LIBRARIES $<TARGET_FILE:${plugin}_plugin>)
list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries})
endforeach(plugin)
foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST})
add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin})
list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries})
endforeach(ffi_plugin)
@@ -1,20 +0,0 @@
//
// Generated file. Do not edit.
//
import FlutterMacOS
import Foundation
import flowy_infra_ui
import path_provider_macos
import rich_clipboard_macos
import shared_preferences_macos
import url_launcher_macos
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
FlowyInfraUIPlugin.register(with: registry.registrar(forPlugin: "FlowyInfraUIPlugin"))
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
RichClipboardPlugin.register(with: registry.registrar(forPlugin: "RichClipboardPlugin"))
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
}
@@ -1,17 +0,0 @@
//
// Generated file. Do not edit.
//
// clang-format off
#include "generated_plugin_registrant.h"
#include <flowy_infra_ui/flowy_infra_u_i_plugin.h>
#include <url_launcher_windows/url_launcher_windows.h>
void RegisterPlugins(flutter::PluginRegistry* registry) {
FlowyInfraUIPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("FlowyInfraUIPlugin"));
UrlLauncherWindowsRegisterWithRegistrar(
registry->GetRegistrarForPlugin("UrlLauncherWindows"));
}
@@ -1,15 +0,0 @@
//
// Generated file. Do not edit.
//
// clang-format off
#ifndef GENERATED_PLUGIN_REGISTRANT_
#define GENERATED_PLUGIN_REGISTRANT_
#include <flutter/plugin_registry.h>
// Registers Flutter plugins.
void RegisterPlugins(flutter::PluginRegistry* registry);
#endif // GENERATED_PLUGIN_REGISTRANT_
@@ -1,25 +0,0 @@
#
# Generated file, do not edit.
#
list(APPEND FLUTTER_PLUGIN_LIST
flowy_infra_ui
url_launcher_windows
)
list(APPEND FLUTTER_FFI_PLUGIN_LIST
)
set(PLUGIN_BUNDLED_LIBRARIES)
foreach(plugin ${FLUTTER_PLUGIN_LIST})
add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin})
target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin)
list(APPEND PLUGIN_BUNDLED_LIBRARIES $<TARGET_FILE:${plugin}_plugin>)
list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries})
endforeach(plugin)
foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST})
add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin})
list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries})
endforeach(ffi_plugin)
@@ -1,39 +0,0 @@
import 'package:flutter/material.dart';
import 'toolbar_item.dart';
class ToolbarItemWidget extends StatelessWidget {
const ToolbarItemWidget({
Key? key,
required this.item,
required this.isHighlight,
required this.onPressed,
}) : super(key: key);
final ToolbarItem item;
final VoidCallback onPressed;
final bool isHighlight;
@override
Widget build(BuildContext context) {
return SizedBox(
width: 28,
height: 28,
child: Tooltip(
preferBelow: false,
message: item.tooltipsMessage,
child: MouseRegion(
cursor: SystemMouseCursors.click,
child: IconButton(
hoverColor: Colors.transparent,
highlightColor: Colors.transparent,
padding: EdgeInsets.zero,
icon: item.iconBuilder(isHighlight),
iconSize: 28,
onPressed: onPressed,
),
),
),
);
}
}
@@ -1,33 +0,0 @@
import 'package:appflowy_editor/appflowy_editor.dart';
import 'package:flutter_test/flutter_test.dart';
void main() async {
group('path.dart', () {
test('test path equality', () {
var p1 = [0, 0];
var p2 = [0];
expect(p1 > p2, true);
expect(p1 >= p2, true);
expect(p1 < p2, false);
expect(p1 <= p2, false);
p1 = [1, 1, 2];
p2 = [1, 1, 3];
expect(p2 > p1, true);
expect(p2 >= p1, true);
expect(p2 < p1, false);
expect(p2 <= p1, false);
p1 = [2, 0, 1];
p2 = [2, 0, 1];
expect(p2 > p1, false);
expect(p1 > p2, false);
expect(p2 >= p1, true);
expect(p2 <= p1, true);
expect(p1.equals(p2), true);
});
});
}
@@ -1,277 +0,0 @@
import 'package:appflowy_editor/appflowy_editor.dart';
import 'package:appflowy_editor/src/extensions/text_node_extensions.dart';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
import '../../infra/test_editor.dart';
void main() async {
setUpAll(() {
TestWidgetsFlutterBinding.ensureInitialized();
});
group('markdown_syntax_to_styled_text_handler.dart', () {
group('convert double asterisks to bold', () {
Future<void> insertAsterisk(
EditorWidgetTester editor, {
int repeat = 1,
}) async {
for (var i = 0; i < repeat; i++) {
await editor.pressLogicKey(
LogicalKeyboardKey.asterisk,
isShiftPressed: true,
);
}
}
testWidgets('**AppFlowy** to bold AppFlowy', (tester) async {
const text = '**AppFlowy*';
final editor = tester.editor..insertTextNode('');
await editor.startTesting();
await editor.updateSelection(
Selection.single(path: [0], startOffset: 0),
);
final textNode = editor.nodeAtPath([0]) as TextNode;
for (var i = 0; i < text.length; i++) {
await editor.insertText(textNode, text[i], i);
}
await insertAsterisk(editor);
final allBold = textNode.allSatisfyBoldInSelection(
Selection.single(
path: [0],
startOffset: 0,
endOffset: textNode.toPlainText().length,
),
);
expect(allBold, true);
expect(textNode.toPlainText(), 'AppFlowy');
});
testWidgets('App**Flowy** to bold AppFlowy', (tester) async {
const text = 'App**Flowy*';
final editor = tester.editor..insertTextNode('');
await editor.startTesting();
await editor.updateSelection(
Selection.single(path: [0], startOffset: 0),
);
final textNode = editor.nodeAtPath([0]) as TextNode;
for (var i = 0; i < text.length; i++) {
await editor.insertText(textNode, text[i], i);
}
await insertAsterisk(editor);
final allBold = textNode.allSatisfyBoldInSelection(
Selection.single(
path: [0],
startOffset: 3,
endOffset: textNode.toPlainText().length,
),
);
expect(allBold, true);
expect(textNode.toPlainText(), 'AppFlowy');
});
testWidgets('***AppFlowy** to bold *AppFlowy', (tester) async {
const text = '***AppFlowy*';
final editor = tester.editor..insertTextNode('');
await editor.startTesting();
await editor.updateSelection(
Selection.single(path: [0], startOffset: 0),
);
final textNode = editor.nodeAtPath([0]) as TextNode;
for (var i = 0; i < text.length; i++) {
await editor.insertText(textNode, text[i], i);
}
await insertAsterisk(editor);
final allBold = textNode.allSatisfyBoldInSelection(
Selection.single(
path: [0],
startOffset: 1,
endOffset: textNode.toPlainText().length,
),
);
expect(allBold, true);
expect(textNode.toPlainText(), '*AppFlowy');
});
testWidgets('**AppFlowy** application to bold AppFlowy only',
(tester) async {
const boldText = '**AppFlowy*';
final editor = tester.editor..insertTextNode('');
await editor.startTesting();
await editor.updateSelection(
Selection.single(path: [0], startOffset: 0),
);
final textNode = editor.nodeAtPath([0]) as TextNode;
for (var i = 0; i < boldText.length; i++) {
await editor.insertText(textNode, boldText[i], i);
}
await insertAsterisk(editor);
final boldTextLength = boldText.replaceAll('*', '').length;
final appFlowyBold = textNode.allSatisfyBoldInSelection(
Selection.single(
path: [0],
startOffset: 0,
endOffset: boldTextLength,
),
);
expect(appFlowyBold, true);
expect(textNode.toPlainText(), 'AppFlowy');
});
testWidgets('**** nothing changes', (tester) async {
const text = '***';
final editor = tester.editor..insertTextNode('');
await editor.startTesting();
await editor.updateSelection(
Selection.single(path: [0], startOffset: 0),
);
final textNode = editor.nodeAtPath([0]) as TextNode;
for (var i = 0; i < text.length; i++) {
await editor.insertText(textNode, text[i], i);
}
await insertAsterisk(editor);
final allBold = textNode.allSatisfyBoldInSelection(
Selection.single(
path: [0],
startOffset: 0,
endOffset: textNode.toPlainText().length,
),
);
expect(allBold, false);
expect(textNode.toPlainText(), text);
});
});
group('convert double underscores to bold', () {
Future<void> insertUnderscore(
EditorWidgetTester editor, {
int repeat = 1,
}) async {
for (var i = 0; i < repeat; i++) {
await editor.pressLogicKey(
LogicalKeyboardKey.underscore,
isShiftPressed: true,
);
}
}
testWidgets('__AppFlowy__ to bold AppFlowy', (tester) async {
const text = '__AppFlowy_';
final editor = tester.editor..insertTextNode('');
await editor.startTesting();
await editor.updateSelection(
Selection.single(path: [0], startOffset: 0),
);
final textNode = editor.nodeAtPath([0]) as TextNode;
for (var i = 0; i < text.length; i++) {
await editor.insertText(textNode, text[i], i);
}
await insertUnderscore(editor);
final allBold = textNode.allSatisfyBoldInSelection(
Selection.single(
path: [0],
startOffset: 0,
endOffset: textNode.toPlainText().length,
),
);
expect(allBold, true);
expect(textNode.toPlainText(), 'AppFlowy');
});
testWidgets('App__Flowy__ to bold AppFlowy', (tester) async {
const text = 'App__Flowy_';
final editor = tester.editor..insertTextNode('');
await editor.startTesting();
await editor.updateSelection(
Selection.single(path: [0], startOffset: 0),
);
final textNode = editor.nodeAtPath([0]) as TextNode;
for (var i = 0; i < text.length; i++) {
await editor.insertText(textNode, text[i], i);
}
await insertUnderscore(editor);
final allBold = textNode.allSatisfyBoldInSelection(
Selection.single(
path: [0],
startOffset: 3,
endOffset: textNode.toPlainText().length,
),
);
expect(allBold, true);
expect(textNode.toPlainText(), 'AppFlowy');
});
testWidgets('___AppFlowy__ to bold _AppFlowy', (tester) async {
const text = '___AppFlowy_';
final editor = tester.editor..insertTextNode('');
await editor.startTesting();
await editor.updateSelection(
Selection.single(path: [0], startOffset: 0),
);
final textNode = editor.nodeAtPath([0]) as TextNode;
for (var i = 0; i < text.length; i++) {
await editor.insertText(textNode, text[i], i);
}
await insertUnderscore(editor);
final allBold = textNode.allSatisfyBoldInSelection(
Selection.single(
path: [0],
startOffset: 1,
endOffset: textNode.toPlainText().length,
),
);
expect(allBold, true);
expect(textNode.toPlainText(), '_AppFlowy');
});
testWidgets('__AppFlowy__ application to bold AppFlowy only',
(tester) async {
const boldText = '__AppFlowy_';
final editor = tester.editor..insertTextNode('');
await editor.startTesting();
await editor.updateSelection(
Selection.single(path: [0], startOffset: 0),
);
final textNode = editor.nodeAtPath([0]) as TextNode;
for (var i = 0; i < boldText.length; i++) {
await editor.insertText(textNode, boldText[i], i);
}
await insertUnderscore(editor);
final boldTextLength = boldText.replaceAll('_', '').length;
final appFlowyBold = textNode.allSatisfyBoldInSelection(
Selection.single(
path: [0],
startOffset: 0,
endOffset: boldTextLength,
),
);
expect(appFlowyBold, true);
expect(textNode.toPlainText(), 'AppFlowy');
});
testWidgets('____ nothing changes', (tester) async {
const text = '___';
final editor = tester.editor..insertTextNode('');
await editor.startTesting();
await editor.updateSelection(
Selection.single(path: [0], startOffset: 0),
);
final textNode = editor.nodeAtPath([0]) as TextNode;
for (var i = 0; i < text.length; i++) {
await editor.insertText(textNode, text[i], i);
}
await insertUnderscore(editor);
final allBold = textNode.allSatisfyBoldInSelection(
Selection.single(
path: [0],
startOffset: 0,
endOffset: textNode.toPlainText().length,
),
);
expect(allBold, false);
expect(textNode.toPlainText(), text);
});
});
});
}
@@ -1,11 +0,0 @@
//
// Generated file. Do not edit.
//
// clang-format off
#include "generated_plugin_registrant.h"
void fl_register_plugins(FlPluginRegistry* registry) {
}
@@ -1,15 +0,0 @@
//
// Generated file. Do not edit.
//
// clang-format off
#ifndef GENERATED_PLUGIN_REGISTRANT_
#define GENERATED_PLUGIN_REGISTRANT_
#include <flutter_linux/flutter_linux.h>
// Registers Flutter plugins.
void fl_register_plugins(FlPluginRegistry* registry);
#endif // GENERATED_PLUGIN_REGISTRANT_
@@ -1,23 +0,0 @@
#
# Generated file, do not edit.
#
list(APPEND FLUTTER_PLUGIN_LIST
)
list(APPEND FLUTTER_FFI_PLUGIN_LIST
)
set(PLUGIN_BUNDLED_LIBRARIES)
foreach(plugin ${FLUTTER_PLUGIN_LIST})
add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin})
target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin)
list(APPEND PLUGIN_BUNDLED_LIBRARIES $<TARGET_FILE:${plugin}_plugin>)
list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries})
endforeach(plugin)
foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST})
add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin})
list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries})
endforeach(ffi_plugin)
@@ -1,10 +0,0 @@
//
// Generated file. Do not edit.
//
import FlutterMacOS
import Foundation
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
}
@@ -1,11 +0,0 @@
//
// Generated file. Do not edit.
//
// clang-format off
#include "generated_plugin_registrant.h"
void RegisterPlugins(flutter::PluginRegistry* registry) {
}
@@ -1,15 +0,0 @@
//
// Generated file. Do not edit.
//
// clang-format off
#ifndef GENERATED_PLUGIN_REGISTRANT_
#define GENERATED_PLUGIN_REGISTRANT_
#include <flutter/plugin_registry.h>
// Registers Flutter plugins.
void RegisterPlugins(flutter::PluginRegistry* registry);
#endif // GENERATED_PLUGIN_REGISTRANT_
@@ -1,23 +0,0 @@
#
# Generated file, do not edit.
#
list(APPEND FLUTTER_PLUGIN_LIST
)
list(APPEND FLUTTER_FFI_PLUGIN_LIST
)
set(PLUGIN_BUNDLED_LIBRARIES)
foreach(plugin ${FLUTTER_PLUGIN_LIST})
add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin})
target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin)
list(APPEND PLUGIN_BUNDLED_LIBRARIES $<TARGET_FILE:${plugin}_plugin>)
list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries})
endforeach(plugin)
foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST})
add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin})
list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries})
endforeach(ffi_plugin)
@@ -1,224 +0,0 @@
# Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile
packages:
async:
dependency: transitive
description:
name: async
url: "https://pub.dartlang.org"
source: hosted
version: "2.9.0"
boolean_selector:
dependency: transitive
description:
name: boolean_selector
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.0"
characters:
dependency: transitive
description:
name: characters
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.1"
clock:
dependency: transitive
description:
name: clock
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.1"
collection:
dependency: transitive
description:
name: collection
url: "https://pub.dartlang.org"
source: hosted
version: "1.16.0"
crypto:
dependency: transitive
description:
name: crypto
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.2"
fake_async:
dependency: transitive
description:
name: fake_async
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.1"
flutter:
dependency: "direct main"
description: flutter
source: sdk
version: "0.0.0"
flutter_lints:
dependency: "direct dev"
description:
name: flutter_lints
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.1"
flutter_svg:
dependency: "direct main"
description:
name: flutter_svg
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.6"
flutter_test:
dependency: "direct dev"
description: flutter
source: sdk
version: "0.0.0"
lints:
dependency: transitive
description:
name: lints
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.1"
matcher:
dependency: transitive
description:
name: matcher
url: "https://pub.dartlang.org"
source: hosted
version: "0.12.12"
material_color_utilities:
dependency: transitive
description:
name: material_color_utilities
url: "https://pub.dartlang.org"
source: hosted
version: "0.1.5"
meta:
dependency: transitive
description:
name: meta
url: "https://pub.dartlang.org"
source: hosted
version: "1.8.0"
path:
dependency: transitive
description:
name: path
url: "https://pub.dartlang.org"
source: hosted
version: "1.8.2"
path_drawing:
dependency: transitive
description:
name: path_drawing
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.1"
path_parsing:
dependency: transitive
description:
name: path_parsing
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.1"
petitparser:
dependency: transitive
description:
name: petitparser
url: "https://pub.dartlang.org"
source: hosted
version: "5.1.0"
sky_engine:
dependency: transitive
description: flutter
source: sdk
version: "0.0.99"
source_span:
dependency: transitive
description:
name: source_span
url: "https://pub.dartlang.org"
source: hosted
version: "1.9.0"
stack_trace:
dependency: transitive
description:
name: stack_trace
url: "https://pub.dartlang.org"
source: hosted
version: "1.10.0"
stream_channel:
dependency: transitive
description:
name: stream_channel
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.0"
string_scanner:
dependency: transitive
description:
name: string_scanner
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.1"
term_glyph:
dependency: transitive
description:
name: term_glyph
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.1"
test_api:
dependency: transitive
description:
name: test_api
url: "https://pub.dartlang.org"
source: hosted
version: "0.4.12"
textstyle_extensions:
dependency: "direct main"
description:
name: textstyle_extensions
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0-nullsafety"
time:
dependency: "direct main"
description:
name: time
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.3"
typed_data:
dependency: transitive
description:
name: typed_data
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.1"
uuid:
dependency: "direct main"
description:
name: uuid
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.7"
vector_math:
dependency: transitive
description:
name: vector_math
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.2"
xml:
dependency: transitive
description:
name: xml
url: "https://pub.dartlang.org"
source: hosted
version: "6.1.0"
sdks:
dart: ">=2.18.0 <3.0.0"
flutter: ">=3.3.0"
@@ -1,11 +0,0 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "Infra UI Example",
"type": "dart",
"request": "launch",
"program": "example/lib/main.dart"
},
]
}
@@ -1,10 +0,0 @@
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled and should not be manually edited.
version:
revision: fa5883b78e566877613ad1ccb48dd92075cb5c23
channel: dev
project_type: app
@@ -1,15 +0,0 @@
//
// Generated file. Do not edit.
//
// clang-format off
#include "generated_plugin_registrant.h"
#include <flowy_infra_ui/flowy_infra_u_i_plugin.h>
void fl_register_plugins(FlPluginRegistry* registry) {
g_autoptr(FlPluginRegistrar) flowy_infra_ui_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "FlowyInfraUIPlugin");
flowy_infra_u_i_plugin_register_with_registrar(flowy_infra_ui_registrar);
}
@@ -1,15 +0,0 @@
//
// Generated file. Do not edit.
//
// clang-format off
#ifndef GENERATED_PLUGIN_REGISTRANT_
#define GENERATED_PLUGIN_REGISTRANT_
#include <flutter_linux/flutter_linux.h>
// Registers Flutter plugins.
void fl_register_plugins(FlPluginRegistry* registry);
#endif // GENERATED_PLUGIN_REGISTRANT_
@@ -1,24 +0,0 @@
#
# Generated file, do not edit.
#
list(APPEND FLUTTER_PLUGIN_LIST
flowy_infra_ui
)
list(APPEND FLUTTER_FFI_PLUGIN_LIST
)
set(PLUGIN_BUNDLED_LIBRARIES)
foreach(plugin ${FLUTTER_PLUGIN_LIST})
add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin})
target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin)
list(APPEND PLUGIN_BUNDLED_LIBRARIES $<TARGET_FILE:${plugin}_plugin>)
list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries})
endforeach(plugin)
foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST})
add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin})
list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries})
endforeach(ffi_plugin)
@@ -1,12 +0,0 @@
//
// Generated file. Do not edit.
//
import FlutterMacOS
import Foundation
import flowy_infra_ui
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
FlowyInfraUIPlugin.register(with: registry.registrar(forPlugin: "FlowyInfraUIPlugin"))
}
@@ -1,341 +0,0 @@
# Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile
packages:
animations:
dependency: transitive
description:
name: animations
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.7"
appflowy_popover:
dependency: transitive
description:
path: "../../appflowy_popover"
relative: true
source: path
version: "0.0.1"
async:
dependency: transitive
description:
name: async
url: "https://pub.dartlang.org"
source: hosted
version: "2.9.0"
boolean_selector:
dependency: transitive
description:
name: boolean_selector
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.0"
characters:
dependency: transitive
description:
name: characters
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.1"
clock:
dependency: transitive
description:
name: clock
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.1"
collection:
dependency: transitive
description:
name: collection
url: "https://pub.dartlang.org"
source: hosted
version: "1.16.0"
crypto:
dependency: transitive
description:
name: crypto
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.2"
cupertino_icons:
dependency: "direct main"
description:
name: cupertino_icons
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.5"
dartz:
dependency: transitive
description:
name: dartz
url: "https://pub.dartlang.org"
source: hosted
version: "0.10.1"
equatable:
dependency: transitive
description:
name: equatable
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.5"
fake_async:
dependency: transitive
description:
name: fake_async
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.1"
flowy_infra:
dependency: transitive
description:
path: "../../flowy_infra"
relative: true
source: path
version: "0.0.1"
flowy_infra_ui:
dependency: "direct main"
description:
path: ".."
relative: true
source: path
version: "0.0.1"
flowy_infra_ui_platform_interface:
dependency: transitive
description:
path: "../flowy_infra_ui_platform_interface"
relative: true
source: path
version: "0.0.1"
flowy_infra_ui_web:
dependency: transitive
description:
path: "../flowy_infra_ui_web"
relative: true
source: path
version: "0.0.1"
flutter:
dependency: "direct main"
description: flutter
source: sdk
version: "0.0.0"
flutter_lints:
dependency: "direct dev"
description:
name: flutter_lints
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.1"
flutter_svg:
dependency: transitive
description:
name: flutter_svg
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.6"
flutter_test:
dependency: "direct dev"
description: flutter
source: sdk
version: "0.0.0"
flutter_web_plugins:
dependency: transitive
description: flutter
source: sdk
version: "0.0.0"
js:
dependency: transitive
description:
name: js
url: "https://pub.dartlang.org"
source: hosted
version: "0.6.4"
lint:
dependency: transitive
description:
name: lint
url: "https://pub.dartlang.org"
source: hosted
version: "1.10.0"
lints:
dependency: transitive
description:
name: lints
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.1"
loading_indicator:
dependency: transitive
description:
name: loading_indicator
url: "https://pub.dartlang.org"
source: hosted
version: "3.1.0"
matcher:
dependency: transitive
description:
name: matcher
url: "https://pub.dartlang.org"
source: hosted
version: "0.12.12"
material_color_utilities:
dependency: transitive
description:
name: material_color_utilities
url: "https://pub.dartlang.org"
source: hosted
version: "0.1.5"
meta:
dependency: transitive
description:
name: meta
url: "https://pub.dartlang.org"
source: hosted
version: "1.8.0"
nested:
dependency: transitive
description:
name: nested
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.0"
path:
dependency: transitive
description:
name: path
url: "https://pub.dartlang.org"
source: hosted
version: "1.8.2"
path_drawing:
dependency: transitive
description:
name: path_drawing
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.1"
path_parsing:
dependency: transitive
description:
name: path_parsing
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.1"
petitparser:
dependency: transitive
description:
name: petitparser
url: "https://pub.dartlang.org"
source: hosted
version: "5.1.0"
plugin_platform_interface:
dependency: transitive
description:
name: plugin_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.3"
provider:
dependency: "direct main"
description:
name: provider
url: "https://pub.dartlang.org"
source: hosted
version: "6.0.5"
sky_engine:
dependency: transitive
description: flutter
source: sdk
version: "0.0.99"
source_span:
dependency: transitive
description:
name: source_span
url: "https://pub.dartlang.org"
source: hosted
version: "1.9.0"
stack_trace:
dependency: transitive
description:
name: stack_trace
url: "https://pub.dartlang.org"
source: hosted
version: "1.10.0"
stream_channel:
dependency: transitive
description:
name: stream_channel
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.0"
string_scanner:
dependency: transitive
description:
name: string_scanner
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.1"
styled_widget:
dependency: transitive
description:
name: styled_widget
url: "https://pub.dartlang.org"
source: hosted
version: "0.3.1+2"
term_glyph:
dependency: transitive
description:
name: term_glyph
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.1"
test_api:
dependency: transitive
description:
name: test_api
url: "https://pub.dartlang.org"
source: hosted
version: "0.4.12"
textstyle_extensions:
dependency: transitive
description:
name: textstyle_extensions
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0-nullsafety"
time:
dependency: transitive
description:
name: time
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.3"
typed_data:
dependency: transitive
description:
name: typed_data
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.1"
uuid:
dependency: transitive
description:
name: uuid
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.7"
vector_math:
dependency: transitive
description:
name: vector_math
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.2"
xml:
dependency: transitive
description:
name: xml
url: "https://pub.dartlang.org"
source: hosted
version: "6.1.0"
sdks:
dart: ">=2.18.0 <3.0.0"
flutter: ">=3.3.0"
@@ -1,14 +0,0 @@
//
// Generated file. Do not edit.
//
// clang-format off
#include "generated_plugin_registrant.h"
#include <flowy_infra_ui/flowy_infra_u_i_plugin.h>
void RegisterPlugins(flutter::PluginRegistry* registry) {
FlowyInfraUIPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("FlowyInfraUIPlugin"));
}
@@ -1,15 +0,0 @@
//
// Generated file. Do not edit.
//
// clang-format off
#ifndef GENERATED_PLUGIN_REGISTRANT_
#define GENERATED_PLUGIN_REGISTRANT_
#include <flutter/plugin_registry.h>
// Registers Flutter plugins.
void RegisterPlugins(flutter::PluginRegistry* registry);
#endif // GENERATED_PLUGIN_REGISTRANT_
@@ -1,24 +0,0 @@
#
# Generated file, do not edit.
#
list(APPEND FLUTTER_PLUGIN_LIST
flowy_infra_ui
)
list(APPEND FLUTTER_FFI_PLUGIN_LIST
)
set(PLUGIN_BUNDLED_LIBRARIES)
foreach(plugin ${FLUTTER_PLUGIN_LIST})
add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin})
target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin)
list(APPEND PLUGIN_BUNDLED_LIBRARIES $<TARGET_FILE:${plugin}_plugin>)
list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries})
endforeach(plugin)
foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST})
add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin})
list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries})
endforeach(ffi_plugin)
@@ -1,161 +0,0 @@
# Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile
packages:
async:
dependency: transitive
description:
name: async
url: "https://pub.dartlang.org"
source: hosted
version: "2.9.0"
boolean_selector:
dependency: transitive
description:
name: boolean_selector
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.0"
characters:
dependency: transitive
description:
name: characters
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.1"
clock:
dependency: transitive
description:
name: clock
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.1"
collection:
dependency: transitive
description:
name: collection
url: "https://pub.dartlang.org"
source: hosted
version: "1.16.0"
fake_async:
dependency: transitive
description:
name: fake_async
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.1"
flutter:
dependency: "direct main"
description: flutter
source: sdk
version: "0.0.0"
flutter_lints:
dependency: "direct dev"
description:
name: flutter_lints
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.1"
flutter_test:
dependency: "direct dev"
description: flutter
source: sdk
version: "0.0.0"
lints:
dependency: transitive
description:
name: lints
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.1"
matcher:
dependency: transitive
description:
name: matcher
url: "https://pub.dartlang.org"
source: hosted
version: "0.12.12"
material_color_utilities:
dependency: transitive
description:
name: material_color_utilities
url: "https://pub.dartlang.org"
source: hosted
version: "0.1.5"
meta:
dependency: transitive
description:
name: meta
url: "https://pub.dartlang.org"
source: hosted
version: "1.8.0"
path:
dependency: transitive
description:
name: path
url: "https://pub.dartlang.org"
source: hosted
version: "1.8.2"
plugin_platform_interface:
dependency: "direct main"
description:
name: plugin_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.3"
sky_engine:
dependency: transitive
description: flutter
source: sdk
version: "0.0.99"
source_span:
dependency: transitive
description:
name: source_span
url: "https://pub.dartlang.org"
source: hosted
version: "1.9.0"
stack_trace:
dependency: transitive
description:
name: stack_trace
url: "https://pub.dartlang.org"
source: hosted
version: "1.10.0"
stream_channel:
dependency: transitive
description:
name: stream_channel
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.0"
string_scanner:
dependency: transitive
description:
name: string_scanner
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.1"
term_glyph:
dependency: transitive
description:
name: term_glyph
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.1"
test_api:
dependency: transitive
description:
name: test_api
url: "https://pub.dartlang.org"
source: hosted
version: "0.4.12"
vector_math:
dependency: transitive
description:
name: vector_math
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.2"
sdks:
dart: ">=2.17.0 <3.0.0"
flutter: ">=1.17.0"
@@ -1,180 +0,0 @@
# Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile
packages:
async:
dependency: transitive
description:
name: async
url: "https://pub.dartlang.org"
source: hosted
version: "2.9.0"
boolean_selector:
dependency: transitive
description:
name: boolean_selector
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.0"
characters:
dependency: transitive
description:
name: characters
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.1"
clock:
dependency: transitive
description:
name: clock
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.1"
collection:
dependency: transitive
description:
name: collection
url: "https://pub.dartlang.org"
source: hosted
version: "1.16.0"
fake_async:
dependency: transitive
description:
name: fake_async
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.1"
flowy_infra_ui_platform_interface:
dependency: "direct main"
description:
path: "../flowy_infra_ui_platform_interface"
relative: true
source: path
version: "0.0.1"
flutter:
dependency: transitive
description: flutter
source: sdk
version: "0.0.0"
flutter_lints:
dependency: "direct dev"
description:
name: flutter_lints
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.1"
flutter_test:
dependency: "direct dev"
description: flutter
source: sdk
version: "0.0.0"
flutter_web_plugins:
dependency: "direct main"
description: flutter
source: sdk
version: "0.0.0"
js:
dependency: transitive
description:
name: js
url: "https://pub.dartlang.org"
source: hosted
version: "0.6.4"
lints:
dependency: transitive
description:
name: lints
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.1"
matcher:
dependency: transitive
description:
name: matcher
url: "https://pub.dartlang.org"
source: hosted
version: "0.12.12"
material_color_utilities:
dependency: transitive
description:
name: material_color_utilities
url: "https://pub.dartlang.org"
source: hosted
version: "0.1.5"
meta:
dependency: transitive
description:
name: meta
url: "https://pub.dartlang.org"
source: hosted
version: "1.8.0"
path:
dependency: transitive
description:
name: path
url: "https://pub.dartlang.org"
source: hosted
version: "1.8.2"
plugin_platform_interface:
dependency: transitive
description:
name: plugin_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.3"
sky_engine:
dependency: transitive
description: flutter
source: sdk
version: "0.0.99"
source_span:
dependency: transitive
description:
name: source_span
url: "https://pub.dartlang.org"
source: hosted
version: "1.9.0"
stack_trace:
dependency: transitive
description:
name: stack_trace
url: "https://pub.dartlang.org"
source: hosted
version: "1.10.0"
stream_channel:
dependency: transitive
description:
name: stream_channel
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.0"
string_scanner:
dependency: transitive
description:
name: string_scanner
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.1"
term_glyph:
dependency: transitive
description:
name: term_glyph
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.1"
test_api:
dependency: transitive
description:
name: test_api
url: "https://pub.dartlang.org"
source: hosted
version: "0.4.12"
vector_math:
dependency: transitive
description:
name: vector_math
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.2"
sdks:
dart: ">=2.17.0 <3.0.0"
flutter: ">=1.17.0"
@@ -1,327 +0,0 @@
# Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile
packages:
animations:
dependency: "direct main"
description:
name: animations
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.7"
appflowy_popover:
dependency: "direct main"
description:
path: "../appflowy_popover"
relative: true
source: path
version: "0.0.1"
async:
dependency: "direct main"
description:
name: async
url: "https://pub.dartlang.org"
source: hosted
version: "2.9.0"
boolean_selector:
dependency: transitive
description:
name: boolean_selector
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.0"
characters:
dependency: transitive
description:
name: characters
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.1"
clock:
dependency: transitive
description:
name: clock
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.1"
collection:
dependency: transitive
description:
name: collection
url: "https://pub.dartlang.org"
source: hosted
version: "1.16.0"
crypto:
dependency: transitive
description:
name: crypto
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.2"
dartz:
dependency: "direct main"
description:
name: dartz
url: "https://pub.dartlang.org"
source: hosted
version: "0.10.1"
equatable:
dependency: "direct main"
description:
name: equatable
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.5"
fake_async:
dependency: transitive
description:
name: fake_async
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.1"
flowy_infra:
dependency: "direct main"
description:
path: "../flowy_infra"
relative: true
source: path
version: "0.0.1"
flowy_infra_ui_platform_interface:
dependency: "direct main"
description:
path: flowy_infra_ui_platform_interface
relative: true
source: path
version: "0.0.1"
flowy_infra_ui_web:
dependency: "direct main"
description:
path: flowy_infra_ui_web
relative: true
source: path
version: "0.0.1"
flutter:
dependency: "direct main"
description: flutter
source: sdk
version: "0.0.0"
flutter_lints:
dependency: "direct dev"
description:
name: flutter_lints
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.1"
flutter_svg:
dependency: transitive
description:
name: flutter_svg
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.6"
flutter_test:
dependency: "direct dev"
description: flutter
source: sdk
version: "0.0.0"
flutter_web_plugins:
dependency: transitive
description: flutter
source: sdk
version: "0.0.0"
js:
dependency: transitive
description:
name: js
url: "https://pub.dartlang.org"
source: hosted
version: "0.6.4"
lint:
dependency: transitive
description:
name: lint
url: "https://pub.dartlang.org"
source: hosted
version: "1.10.0"
lints:
dependency: transitive
description:
name: lints
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.1"
loading_indicator:
dependency: "direct main"
description:
name: loading_indicator
url: "https://pub.dartlang.org"
source: hosted
version: "3.1.0"
matcher:
dependency: transitive
description:
name: matcher
url: "https://pub.dartlang.org"
source: hosted
version: "0.12.12"
material_color_utilities:
dependency: transitive
description:
name: material_color_utilities
url: "https://pub.dartlang.org"
source: hosted
version: "0.1.5"
meta:
dependency: transitive
description:
name: meta
url: "https://pub.dartlang.org"
source: hosted
version: "1.8.0"
nested:
dependency: transitive
description:
name: nested
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.0"
path:
dependency: transitive
description:
name: path
url: "https://pub.dartlang.org"
source: hosted
version: "1.8.2"
path_drawing:
dependency: transitive
description:
name: path_drawing
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.1"
path_parsing:
dependency: transitive
description:
name: path_parsing
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.1"
petitparser:
dependency: transitive
description:
name: petitparser
url: "https://pub.dartlang.org"
source: hosted
version: "5.1.0"
plugin_platform_interface:
dependency: transitive
description:
name: plugin_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.3"
provider:
dependency: "direct main"
description:
name: provider
url: "https://pub.dartlang.org"
source: hosted
version: "6.0.5"
sky_engine:
dependency: transitive
description: flutter
source: sdk
version: "0.0.99"
source_span:
dependency: transitive
description:
name: source_span
url: "https://pub.dartlang.org"
source: hosted
version: "1.9.0"
stack_trace:
dependency: transitive
description:
name: stack_trace
url: "https://pub.dartlang.org"
source: hosted
version: "1.10.0"
stream_channel:
dependency: transitive
description:
name: stream_channel
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.0"
string_scanner:
dependency: transitive
description:
name: string_scanner
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.1"
styled_widget:
dependency: "direct main"
description:
name: styled_widget
url: "https://pub.dartlang.org"
source: hosted
version: "0.3.1+2"
term_glyph:
dependency: transitive
description:
name: term_glyph
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.1"
test_api:
dependency: transitive
description:
name: test_api
url: "https://pub.dartlang.org"
source: hosted
version: "0.4.12"
textstyle_extensions:
dependency: "direct main"
description:
name: textstyle_extensions
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0-nullsafety"
time:
dependency: transitive
description:
name: time
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.3"
typed_data:
dependency: transitive
description:
name: typed_data
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.1"
uuid:
dependency: transitive
description:
name: uuid
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.7"
vector_math:
dependency: transitive
description:
name: vector_math
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.2"
xml:
dependency: transitive
description:
name: xml
url: "https://pub.dartlang.org"
source: hosted
version: "6.1.0"
sdks:
dart: ">=2.18.0 <3.0.0"
flutter: ">=3.3.0"
@@ -1,22 +0,0 @@
cmake_minimum_required(VERSION 3.14)
project(runner LANGUAGES CXX)
add_executable(${BINARY_NAME} WIN32
"flutter_window.cpp"
"main.cpp"
"utils.cpp"
"win32_window.cpp"
"${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc"
"Runner.rc"
"runner.exe.manifest"
)
apply_standard_settings(${BINARY_NAME})
target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX")
target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app)
target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}")
add_dependencies(${BINARY_NAME} flutter_assemble)
# === Flutter Library ===
#set(DART_FFI "${CMAKE_CURRENT_SOURCE_DIR}/dart_ffi/dart_ffi.dll")
#set(DART_FFI ${DART_FFI} PARENT_SCOPE)
@@ -30,6 +30,8 @@
.pub-cache/
.pub/
/build/
generated*
Generated*
# Web related
lib/generated_plugin_registrant.dart
+30
View File
@@ -0,0 +1,30 @@
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled.
version:
revision: 135454af32477f815a7525073027a3ff9eff1bfd
channel: stable
project_type: app
# Tracks metadata for the flutter migrate command
migration:
platforms:
- platform: root
create_revision: 135454af32477f815a7525073027a3ff9eff1bfd
base_revision: 135454af32477f815a7525073027a3ff9eff1bfd
- platform: windows
create_revision: 135454af32477f815a7525073027a3ff9eff1bfd
base_revision: 135454af32477f815a7525073027a3ff9eff1bfd
# User provided section
# List of Local paths (relative to this file) that should be
# ignored by the migrate tool.
#
# Files that are not part of the templates will be ignored by default.
unmanaged_files:
- 'lib/main.dart'
- 'ios/Runner.xcodeproj/project.pbxproj'
File renamed without changes.
+48
View File
@@ -0,0 +1,48 @@
<h1 align="center" style="margin:0"> AppFlowy_Flutter</h1>
<div align="center">
<img src="https://img.shields.io/badge/Flutter-v3.3.10-blue"/>
<img src="https://img.shields.io/badge/Rust-v1.65-orange"/>
</div>
> Documentation for Contributors
This Repository contains the codebase for the frontend of the application, currently we use Flutter as our frontend framework.
### Platforms Supported Using Flutter 💻
- Linux
- macOS
- Windows
> We later expect to extend support to Android and iOS devices using Flutter.
### Am I Eligible to Contribute?
Yes! You are eligible to contribute, check out the ways in which you can [contribute to AppFlowy](https://appflowy.gitbook.io/docs/essential-documentation/contribute-to-appflowy/contributing-to-appflowy). Some of the ways in which you can contribute are:
- Non-Coding Contributions
- Documentation
- Feature Requests and Feedbacks
- Report Bugs
- Improve Translations
- Coding Contributions
To contribute to `AppFlowy_Flutter` codebase specifically (coding contribution) we suggest you to have basic knowledge of Flutter. In case you are new to Flutter, we may suggest you to learn the basics and then try to contribute, get started with Flutter [here](https://flutter.dev/docs/get-started/codelab).
### What OS Should I Use for Development?
We support all OS for Development i.e Linux, macOS and Windows. However, most of us promote macOS and Linux over Windows. We have detailed [docs](https://appflowy.gitbook.io/docs/essential-documentation/contribute-to-appflowy/software-contributions/environment-setup) on How to Setup `AppFlowy_Flutter` in your local system in each OS.
### Getting Started ❇
We have a detailed documentation, on how to [get started](https://appflowy.gitbook.io/docs/essential-documentation/contribute-to-appflowy/contributing-to-appflowy) with the project, and make your first contribution. However, we do have some specific picks for you.
- [Code Architecture](https://appflowy.gitbook.io/docs/essential-documentation/contribute-to-appflowy/architecture/frontend/frontend/codemap)
- [Making Your First PR](https://appflowy.gitbook.io/docs/essential-documentation/contribute-to-appflowy/software-contributions/submitting-code/submitting-your-first-pull-request)
- [The Style Guide](https://appflowy.gitbook.io/docs/essential-documentation/contribute-to-appflowy/software-contributions/submitting-code/style-guides)
- [How to run/debug the application](https://appflowy.gitbook.io/docs/essential-documentation/contribute-to-appflowy/software-contributions/launcher-and-tasks)
### Need Help?
- New to GitHub? Follow [these](https://appflowy.gitbook.io/docs/essential-documentation/contribute-to-appflowy/software-contributions/submitting-code/setting-up-your-repositories) steps to get started
- Stuck Somewhere? Join the [Discord](https://discord.gg/9Q2xaN37tV) Group and we are there to help you!
<!--
## release check
1. [entitlements](https://flutter.dev/desktop#setting-up-entitlements)
2. [symbols stripped](https://flutter.dev/docs/development/platform-integration/c-interop) -->
@@ -45,7 +45,7 @@ android {
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "com.example.app_flowy"
applicationId "io.appflowy.appflowy"
minSdkVersion 19
targetSdkVersion 31
versionCode flutterVersionCode.toInteger()
@@ -1,5 +1,5 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.app_flowy">
package="io.appflowy.appflowy">
<!-- Flutter needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
@@ -1,7 +1,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.app_flowy">
package="io.appflowy.appflowy">
<application
android:label="app_flowy"
android:label="appflowy_flutter"
android:icon="@mipmap/ic_launcher"
android:name="${applicationName}">
<activity
@@ -1,4 +1,4 @@
package com.example.app_flowy
package io.appflowy.appflowy
import io.flutter.embedding.android.FlutterActivity
Loaded 100 of 2639 files, more files were not shown because too many files have changed in this diff. Show more