Compare commits

...
497 Commits
Author SHA1 Message Date
Nathan.fooo 4850a97315 Merge pull request #541 from AppFlowy-IO/fix/grid_duplicate
fix: duplicate grid
2022-06-06 20:22:09 +08:00
appflowy 8fd9b68d9d fix: duplicate grid 2022-06-06 20:06:08 +08:00
Nathan.fooo 20b4e5da7e Merge pull request #538 from AppFlowy-IO/fix/grid_scroll_bar
chore: fix grid scollbar not visible after screen size changed
2022-06-05 22:43:01 +08:00
appflowy ad5ab10cdd chore: update default scrollbar size 2022-06-05 22:29:09 +08:00
appflowy 6bf1d9c19a chore: fix grid scollbar not visible after screen size changed 2022-06-05 22:28:15 +08:00
Nathan.fooo 9b6451506f Merge pull request #536 from AppFlowy-IO/fix/emoji_close
fix: emoji picker remove without attach overlay
2022-06-05 22:00:16 +08:00
appflowy 39ee73cb64 fix: emoji picker remove without attach overlay 2022-06-05 21:02:51 +08:00
Nathan.fooo 7c03924e9c Merge pull request #535 from AppFlowy-IO/refactor/text_block_event
chore: rename some struct in Rust
2022-06-05 19:32:04 +08:00
appflowy 2dfb7261c7 chore: rename some struct in Rust 2022-06-05 18:56:45 +08:00
Nathan.fooo 59a1b0d869 Merge pull request #534 from AppFlowy-IO/fix/grid_cell_highlight
chore: hide accessory when cell is editing
2022-06-05 18:54:04 +08:00
appflowy f61bebe869 chore: hide accessory when cell is editing 2022-06-05 18:39:37 +08:00
Nathan.fooo fbf7c9c9b8 Merge pull request #532 from AppFlowy-IO/feat/grid_keyboard_shortcut
Feat/grid keyboard shortcut
2022-06-04 15:01:34 +08:00
Nathan.fooo 523caca2ea Merge pull request #531 from moksh-mahajan/CloseEmojiPickerOnPageSwitch
Close emoji picker window on page switch
2022-06-04 14:09:39 +08:00
appflowy a9a75230a2 chore: insert cell content 2022-06-04 14:05:04 +08:00
appflowy bb22ca5d93 chore: copy cell content 2022-06-04 11:44:38 +08:00
appflowy 1a83cb65ed chore: click enter to exist edit state 2022-06-04 11:04:43 +08:00
Moksh Mahajan f4a62209df fix: close emoji picker window on page switch 2022-06-04 02:09:55 +05:30
Nathan.fooo 46f69ee00d Merge pull request #529 from AppFlowy-IO/refactor/grid_cell_focus
refactor: add GridCellState and GridFocusNodeCellState
2022-06-03 12:20:41 +08:00
Nathan.fooo 0f71851433 Merge pull request #524 from moksh-mahajan/RenamingWindowAutoClose
fix: Close renaming window when creating another new option
2022-06-03 12:06:32 +08:00
Nathan.fooo 897035004c Merge pull request #528 from AppFlowy-IO/fix/grid_expand_column
fix: expand the list width after field's width changed
2022-06-03 12:06:23 +08:00
appflowy 4887885aae refactor: add GridCellState and GridFocusNodeCellState 2022-06-03 12:05:47 +08:00
appflowy 2342a9b834 fix: expand the list width after field's width changed 2022-06-03 10:51:24 +08:00
Nathan.fooo e2778aef9c Merge pull request #526 from moksh-mahajan/CreateNewOptionCapsuleClick
Clicking on option capsule will now create and select the new opt value
2022-06-03 10:11:44 +08:00
Moksh Mahajan cf6ad8575f fix: close renaming window when creating another new option 2022-06-02 20:53:46 +05:30
Nathan.fooo 81efee557c Merge pull request #527 from AppFlowy-IO/fix/grid_number_format
fix: disable set decimal scale
2022-06-02 22:13:11 +08:00
appflowy 72e26ab229 fix: disable set decimal scale 2022-06-02 21:57:18 +08:00
Nathan.fooo 8b40244c73 Merge pull request #525 from AppFlowy-IO/fix/grid_date_time
fix: edit date time issue
2022-06-02 21:26:57 +08:00
appflowy 481fd9df51 fix: rust unit test 2022-06-02 20:24:25 +08:00
Moksh Mahajan 4f250a9130 fix: clicking on option capsule will now create and select the new option value 2022-06-02 16:26:54 +05:30
appflowy cad5e5d718 refactor: Date's cell data serde 2022-06-02 18:15:22 +08:00
appflowy 4b88aa8683 fix: edit date time issue 2022-06-02 18:00:55 +08:00
Nathan.fooo a384404814 Merge pull request #521 from AppFlowy-IO/fix/grid_ui_adjust
Fix: grid UI adjust
2022-06-01 16:45:59 +08:00
appflowy b286276108 chore: remove unavailable action of GridSettingAction and RowAction 2022-06-01 16:44:31 +08:00
appflowy 0b83684c66 chore: optimaze tap area of row detail cells 2022-06-01 16:40:24 +08:00
appflowy 5bd0fb9fae chore: config build context of URLCellEditor 2022-06-01 16:24:23 +08:00
appflowy 57e5c36fe8 chore: config toast 2022-06-01 15:28:54 +08:00
appflowy 10365217ca chore: copy property to pasteboard 2022-06-01 15:22:18 +08:00
appflowy 9518e164b5 chore: config cell accessory 2022-06-01 14:40:05 +08:00
appflowy 9c5081bc07 chore: enable the richtext widget as large as parent 2022-05-31 22:07:28 +08:00
appflowy cdfe94cf98 chore: rename some classes 2022-05-31 21:36:04 +08:00
appflowy a568f6323d chore: refactor grid cell expander 2022-05-31 21:06:02 +08:00
Nathan.fooo 7071db65e9 Merge pull request #519 from AppFlowy-IO/feat/grid_column_drag
chore: enable drag to expand field's width
2022-05-31 16:38:54 +08:00
appflowy 3d41cb0cec chore: adjust ui color 2022-05-31 16:22:20 +08:00
appflowy ab896cbc8f chore: enable drag to expand field's width 2022-05-31 16:14:17 +08:00
Nathan.fooo 4e3d2672ec Merge pull request #517 from vincentdchan/feat/native-support-for-m1-mac
feat: native support for m1 mac
2022-05-31 09:33:30 +08:00
Vincent Chan 14b012686b feat: native support for m1 mac 2022-05-30 21:12:44 +08:00
Nathan.fooo e177a1433f Merge pull request #516 from AppFlowy-IO/fix/grid_ui
Fix: Grid UI bugs
2022-05-30 20:43:56 +08:00
appflowy 76da44999c chore: reset content when number is not valid 2022-05-30 20:43:38 +08:00
appflowy 84454469b4 fix: #508 auto format number 2022-05-30 18:40:42 +08:00
appflowy 546b1d22f4 fix: #509 enable select on tag 2022-05-30 10:42:30 +08:00
Nathan.fooo 43ae87c797 Merge pull request #515 from Poly-Pixel/various-fixes
Fix various small issues
2022-05-30 10:40:23 +08:00
appflowy 5da8144456 chore: show url cell editor when tap on edit button 2022-05-30 08:56:08 +08:00
Poly-Pixel bfa3eb9577 fix: Fix various small issues 2022-05-29 15:27:18 -04:00
Nathan.fooo 7ff841c3d8 Merge pull request #512 from AppFlowy-IO/feat_grid_url
feat: add new field type - URL
2022-05-29 22:11:36 +08:00
appflowy 4a9627b31d chore: support open url with https scheme 2022-05-29 21:56:44 +08:00
appflowy ae0f71b5ee chore: return URLCellData & parse url from cell content 2022-05-29 10:56:34 +08:00
Nathan.fooo 7cb9ec3042 Merge pull request #511 from vincentdchan/feature/mac-frameless-window
feat: frameless window for mac
2022-05-28 16:04:13 +08:00
appflowy 9844c02cbc chore: Merge branch 'main' into feat_grid_url
# Conflicts:
#	frontend/rust-lib/flowy-grid/src/event_handler.rs
#	shared-lib/flowy-grid-data-model/src/protobuf/model/grid.rs
2022-05-28 16:01:49 +08:00
Nathan.fooo 81cf96986e Merge pull request #514 from AppFlowy-IO/refactor_cell_data
Refactor cell data
2022-05-28 15:55:59 +08:00
appflowy b8582b9b68 chore: set loaded data in SelectOptionCellEditorBloc 2022-05-28 15:55:43 +08:00
appflowy 62c322ab21 refactor: Date & SingleSelect & Multi-Select type option 2022-05-28 15:30:15 +08:00
appflowy 8d766f3bb4 refactor: cell data loader 2022-05-28 08:35:22 +08:00
appflowy 166438ad73 chore: fix rust unit test 2022-05-27 20:41:27 +08:00
Vincent Chan c4db17f73c feat: frameless window for mac 2022-05-27 20:38:01 +08:00
Nathan.fooo 78e979e438 Merge pull request #513 from AppFlowy-IO/add_test_command
chore: add test comand in cargo make
2022-05-27 20:27:14 +08:00
appflowy 7a7ec10085 chore: add test comand in cargo make 2022-05-27 20:26:33 +08:00
appflowy 40e7b42a63 chore: fix flutter warnings 2022-05-27 19:57:13 +08:00
appflowy 9a93a72c33 feat: add new field type 2022-05-27 19:49:14 +08:00
Nathan.fooo 1170e0324b Merge pull request #510 from AppFlowy-IO/refactor_grid_struct
refactor: rename struct
2022-05-26 22:06:18 +08:00
appflowy 8706b81ac0 refactor: rename struct 2022-05-26 18:01:48 +08:00
Nathan.fooo 60b80005ac Merge pull request #507 from AppFlowy-IO/opti_build_time
chore: udpate launch task
2022-05-26 16:27:11 +08:00
appflowy 89ff8517fa chore: udpate launch task 2022-05-26 16:01:25 +08:00
Nathan.fooo d331a68bd1 Merge pull request #506 from AppFlowy-IO/flutter_3.0
chore: upgrade to flutter 3.0
2022-05-25 17:26:03 +08:00
appflowy aad33f6746 chore: update flutter toolchain version to flutter 3.0 2022-05-25 17:01:34 +08:00
appflowy 896123860d chore: update flutter sdk version 2022-05-25 16:45:13 +08:00
appflowy ef2e9cb57e chore: update flutter version in ci 2022-05-25 16:10:47 +08:00
appflowy 2698fb43ad chore: upgrade to flutter 3.0 2022-05-25 16:05:50 +08:00
Nathan.fooo 1ca602fb72 Merge pull request #505 from AppFlowy-IO/fix_0.0.4_bugs_2
Fix some UI bugs
2022-05-25 06:34:10 +08:00
appflowy 8c7b0bd5a7 fix: unit test 2022-05-24 15:25:39 +08:00
appflowy 5b2b50dc9c refactor: cell data operation 2022-05-24 10:23:46 +08:00
appflowy 1ae0b188b1 refactor: grid unit test 2022-05-22 23:33:08 +08:00
appflowy f521c18512 fix: overflow of SelectOptionTagCell 2022-05-22 13:30:56 +08:00
appflowy 1b5b8f19d7 chore: auto expand row detail page's cell 2022-05-22 13:08:38 +08:00
appflowy 36abd969ac chore: format error message of date cell 2022-05-22 13:08:23 +08:00
appflowy 7950f8170b chore: optimaze error code 2022-05-21 21:58:46 +08:00
Nathan.fooo ef0d59ff30 Merge pull request #500 from AppFlowy-IO/opti_create_option 2022-05-19 12:27:19 +08:00
appflowy e8540b4b78 chore: fix potential issue when call notifier after it was disposed 2022-05-19 10:53:11 +08:00
appflowy 23900b49f5 chore: fix bugs 2022-05-19 10:41:00 +08:00
appflowy f3b87d419f chore: optimaze create option progress 2022-05-18 20:21:01 +08:00
appflowy 1267c7524e refactor: TypeOptionContext 2022-05-18 17:26:50 +08:00
appflowy 5f5177355f chore: update _OptionList cell UI 2022-05-18 16:14:11 +08:00
appflowy 4840d23fff chore: add GridFieldContext 2022-05-18 15:43:10 +08:00
appflowy a59a0af05b refactor: remove FieldTypeOptionContext 2022-05-17 17:22:53 +08:00
Nathan.fooo 7b71fd77ca Merge pull request #498 from AppFlowy-IO/opti_protoc_msg
chore: optimazing install protoc message
2022-05-17 16:36:32 +08:00
appflowy 0d40817cad chore: specify flutter version on CI 2022-05-17 16:07:36 +08:00
appflowy 7e975e8e1d chore: optimaze install protoc message 2022-05-17 16:00:07 +08:00
appflowy 467e0093b2 refactor: rename files 2022-05-15 17:22:56 +08:00
appflowy f8d6aa3c74 Revert "chore: upgrade to flutter 3.0"
This reverts commit 3307e2f8fd.
2022-05-14 18:10:08 +08:00
appflowy 3307e2f8fd chore: upgrade to flutter 3.0 2022-05-14 17:40:34 +08:00
Nathan.fooo 6d392c240a Merge pull request #496 from AppFlowy-IO/feat_time_format 2022-05-14 11:09:06 +08:00
appflowy afc563d781 chore: fix unit test 2022-05-14 10:50:11 +08:00
appflowy c6edd1a6da chore: update data & time format 2022-05-13 22:58:49 +08:00
appflowy efbac6c92d chore: check time format & add time format test 2022-05-13 11:31:56 +08:00
appflowy 76079d8ce0 chore: display time 2022-05-12 23:23:23 +08:00
appflowy 4f9470b076 chore: add date type option test 2022-05-12 18:07:26 +08:00
appflowy a178546acd chore: save date cell data with time 2022-05-11 21:34:58 +08:00
appflowy 6fb163b296 refactor: customize cell data persistence 2022-05-11 21:05:04 +08:00
appflowy 19da42f210 chore: add date cell handler 2022-05-11 11:34:13 +08:00
appflowy a2dfc8bc03 chore: set time 2022-05-10 10:26:40 +08:00
appflowy 81d75147d5 chore: update typeOption data 2022-05-10 09:33:34 +08:00
appflowy d3841154a5 chore: config caladen ui 2022-05-09 21:32:58 +08:00
appflowy f617a04900 refactor: cell with origin data 2022-05-09 16:45:42 +08:00
appflowy f21ca6c52a refactor: CellCalendar with bloc 2022-05-09 14:59:26 +08:00
appflowy 13cb7eeb24 chore: add get type option data handler 2022-05-09 13:23:03 +08:00
Nathan.fooo cb0a86893b Merge pull request #485 from AppFlowy-IO/fix_0.0.4_beta3
Fix 0.0.4 beta3
2022-05-07 17:14:42 +08:00
appflowy 18752e7af8 chore: show create option message on bottom 2022-05-06 21:07:34 +08:00
appflowy 228695d517 chore: add close button on row detail page 2022-05-06 20:21:50 +08:00
appflowy 2f2b69d1a6 fix: view title update issue 2022-05-05 21:15:01 +08:00
appflowy 448c134704 fix: update workspace setting 2022-05-05 10:49:34 +08:00
appflowy 6c2c3b0666 fix: alignment in date cell 2022-05-04 21:13:05 +08:00
appflowy 0b8083cfc6 fix: create option with different color 2022-05-04 20:34:28 +08:00
appflowy bd0907b0a4 fix: support float number 2022-05-03 10:26:42 +08:00
Nathan.fooo a298f7c576 Merge pull request #474 from AppFlowy-IO/feat_number_format
Feature: support more number format
2022-05-02 12:44:02 +08:00
appflowy 1488caa97e chore: filter out number format 2022-05-02 11:07:37 +08:00
appflowy 8d125a07c5 chore: add test 2022-05-02 10:07:13 +08:00
appflowy f3b899d742 chore: update currency 2022-05-02 09:59:19 +08:00
appflowy cf05d7da41 chore: support more number format 2022-05-01 23:11:44 +08:00
Nathan.fooo 5c4a681909 Merge pull request #473 from AppFlowy-IO/feat_search_option
chore: filter for select options
2022-05-01 15:50:58 +08:00
appflowy b66d8fc5aa chore: filter for select options 2022-05-01 15:10:40 +08:00
Nathan.fooo 2848ecb5ba Merge pull request #472 from AppFlowy-IO/feat_row_expand
Feat: auto expand row height
2022-04-30 23:17:08 +08:00
appflowy 3435e427c2 Merge branch 'main' into feat_row_expand 2022-04-30 22:41:11 +08:00
appflowy 518d11162b chore: reload row when fields were changed 2022-04-30 22:02:22 +08:00
appflowy 6b5126b12e refactor: GridCellRequestFocusNotifier only accepts single listener 2022-04-30 09:29:43 +08:00
Nathan.fooo 5e8c8909fb Merge pull request #470 from AppFlowy-IO/fix_shared_lib_unit_test
fix: shared lib unit test
2022-04-30 08:52:09 +08:00
appflowy 371f75343c chore: add min height for row 2022-04-30 08:32:11 +08:00
appflowy 1ad7e0ece2 feat: using wrap to auto expand Multi-select or single select 2022-04-29 22:13:15 +08:00
appflowy 40443ced80 feat: expand row 2022-04-29 10:46:35 +08:00
appflowy f102ca3c85 fix: shared lib unit test 2022-04-29 09:23:36 +08:00
Nathan.fooo fa3a28e850 Merge pull request #469 from AppFlowy-IO/feat_local_folder
chore: show appflowy document path in debug info
2022-04-28 21:53:49 +08:00
appflowy b779097978 fix: rust unit test 2022-04-28 21:53:28 +08:00
appflowy 10d4021d25 fix: dart unit test 2022-04-28 21:18:42 +08:00
appflowy 2d4aafd26f Merge branch 'main' into feat_local_folder 2022-04-28 21:18:09 +08:00
appflowy 233b9366af chore: update crates version 2022-04-28 21:16:28 +08:00
appflowy 6e52b470a7 chore: fix wanrings 2022-04-28 20:59:35 +08:00
appflowy 3d0036a926 chore: show appflowy document path in debug info 2022-04-28 20:54:04 +08:00
Nathan.fooo 0662e376ff Merge pull request #468 from AppFlowy-IO/fix_language_gen
fix: generate en language as default
2022-04-28 20:17:40 +08:00
appflowy 7e7fe41026 fix: generate en language as default 2022-04-28 20:10:12 +08:00
Nathan.fooo f2cd3846f1 Merge pull request #467 from AppFlowy-IO/fix_reorder_animation
Fix: reorder animation
2022-04-28 17:32:33 +08:00
appflowy 66cf0ca544 chore: refactor move field func 2022-04-28 17:06:21 +08:00
appflowy 296013dcbf chore: fix wanrings 2022-04-28 16:45:33 +08:00
appflowy 371c52022b fix: reorder view and field animation 2022-04-28 16:44:35 +08:00
appflowy 0285b286a6 fix: auto expand again after reorder app 2022-04-28 16:30:04 +08:00
appflowy ecd2dc3e72 fix: reorder bugs 2022-04-28 16:10:58 +08:00
appflowy f972cdd3fb chore: optimize cell focus 2022-04-27 18:17:08 +08:00
appflowy d0b4abb0c8 refactor: cell context builder 2022-04-27 13:31:54 +08:00
appflowy 70abe546a1 chore: remove freeze file 2022-04-27 09:12:27 +08:00
Nathan.fooo c3ff984c3f Merge pull request #464 from AppFlowy-IO/feat_view_order
Feature: save view/app order
2022-04-27 08:41:18 +08:00
appflowy b29f53c995 chore: print duplicate event erorr 2022-04-27 07:58:40 +08:00
appflowy e8bb6f0a7f chore: save app order 2022-04-27 07:22:18 +08:00
appflowy 7f7801d04e chore: save view order 2022-04-27 07:21:37 +08:00
appflowy 25548ad9eb chore: add move view event 2022-04-26 21:18:29 +08:00
appflowy 0b1f0ed401 refactor: replace provider with bloc in ViewSection 2022-04-26 16:37:31 +08:00
appflowy c8945133dc fix: open latest view after launch 2022-04-26 14:43:42 +08:00
Nathan.fooo b3764e601f Merge pull request #463 from AppFlowy-IO/fix_0.0.4_bugs
Fix 0.0.4 bugs
2022-04-26 09:21:20 +08:00
Nathan.fooo c7d34465e1 Merge pull request #423 from gaganyadav80/drag_drop_docs
feat: adds drag and drop support to pages and docs
2022-04-26 09:20:14 +08:00
appflowy d390ef9a3a chore: fix warnings 2022-04-25 22:03:10 +08:00
appflowy 8b4c46f75b chore: clone cell context 2022-04-25 21:20:08 +08:00
appflowy 0ac17fa6df chore: replace row when row updated 2022-04-25 10:42:24 +08:00
appflowy cffd8fbec6 fix: setup GridCellContext fieldOnchanged callback 2022-04-24 23:20:28 +08:00
appflowy 6d385877a9 fix: bugs 2022-04-24 17:03:00 +08:00
appflowy af5f42d296 chore: auto reload when field was changed 2022-04-24 07:34:31 +08:00
appflowy be49784f5a chore: refactor cell context 2022-04-23 22:41:47 +08:00
appflowy ec16fbe551 chore: cache cell data 2022-04-23 15:11:05 +08:00
appflowy 5af378c810 chore: remove field listener in cell 2022-04-22 23:36:39 +08:00
appflowy b0f5af679c chore: cache cell data 2022-04-22 22:13:51 +08:00
appflowy fa7097587f chore: reuse widget while inserting row 2022-04-22 20:39:49 +08:00
appflowy bf93376cf3 fix: unselect option 2022-04-22 14:22:47 +08:00
Gagan Yadav 1946959d01 Merge branch 'main' into drag_drop_docs 2022-04-21 22:12:09 +05:30
appflowy b9135d26a9 fix: insert row index 2022-04-21 21:24:28 +08:00
Nathan.fooo 8a7c3a9cfc Merge pull request #460 from AppFlowy-IO/feat_row_detail
Feature: show row detail
2022-04-21 20:47:59 +08:00
appflowy 27c40c7b34 chore: fix warnings 2022-04-21 20:37:05 +08:00
appflowy e1711980c6 chore: edit field 2022-04-21 20:32:48 +08:00
appflowy f66adb53c9 chore: config hover 2022-04-21 15:59:56 +08:00
appflowy eeba6884ce chore: config row detail page 2022-04-20 16:32:23 +08:00
appflowy f40e0c18e6 chore: refactor rowbloc 2022-04-19 21:52:46 +08:00
appflowy b3a99be7f8 chore: refactor row cache 2022-04-19 11:41:37 +08:00
appflowy 5ee4b8a2bc chore: different color when create option for single-select or multi-select 2022-04-18 17:17:42 +08:00
Nathan.fooo 3af558fd94 Merge pull request #457 from AppFlowy-IO/fix_0.0.4_beta_2_bugs
Fix 0.0.4 beta 2 bugs
2022-04-17 21:14:04 +08:00
appflowy 006b3c3811 chore: fix unit test & warnings 2022-04-17 20:50:16 +08:00
appflowy 0acc0b0e81 fix: duplicate field 2022-04-17 15:39:33 +08:00
appflowy 13e8c62988 fix: grid property list bugs 2022-04-17 15:15:34 +08:00
appflowy 917e15a1b7 chore: remove listener 2022-04-17 14:50:29 +08:00
appflowy 0a19364ea7 chore: remove row listener from rowbloc 2022-04-17 10:14:17 +08:00
appflowy e647fd0a57 chore: add cell cache 2022-04-17 08:17:50 +08:00
appflowy c82754f284 chore: refactor row cache with row listener 2022-04-16 22:26:34 +08:00
appflowy 3cc7c8e6de chore: cache row data 2022-04-16 21:05:41 +08:00
appflowy 792f8b95aa fix: triger rowbloc event after it was closed 2022-04-16 17:06:08 +08:00
appflowy d4de5767a6 chore: auto resize row height 2022-04-16 10:03:47 +08:00
appflowy f3c82f5c30 chore: insert without remove field on FieldCache 2022-04-16 10:03:47 +08:00
appflowy ea654b602c fix: listen on listState if changed 2022-04-15 22:10:38 +08:00
appflowy 0c8850503f chore: reorder field 2022-04-15 19:56:44 +08:00
appflowy 6dbb708991 chore: repalce sliver header with single scroll view 2022-04-15 15:55:46 +08:00
appflowy d71e0de8c3 chore: set notifier to null after dispose 2022-04-15 14:21:32 +08:00
appflowy 676dffbf21 chore: reorder fields 2022-04-15 10:24:59 +08:00
appflowy a81db92ee1 chore: fix warnings 2022-04-14 21:57:51 +08:00
appflowy b282a14b58 chore: add sync feature 2022-04-14 21:57:00 +08:00
appflowy ac766c0359 chore: fix row rebuild refresh issue 2022-04-14 21:16:29 +08:00
appflowy b606c5ba7b chore: fix some bugs 2022-04-14 18:11:28 +08:00
appflowy fd9e13bf4b chore: refactor grid field listener 2022-04-14 13:59:42 +08:00
appflowy 06af45a8ed chore: udpate field notification 2022-04-13 21:26:27 +08:00
appflowy 2fa6adeee6 chore: move field 2022-04-13 14:24:54 +08:00
appflowy b0e07c952e chore: fixed grid toolbar 2022-04-13 11:06:24 +08:00
appflowy a707410548 chore: format number cell 2022-04-12 21:31:38 +08:00
Nathan.fooo 3089180630 Merge pull request #449 from hewyy/fix_page_delete_143
fixes #143: consecutive deletes to a doc
2022-04-12 16:16:05 +08:00
appflowy 943b4507ac chore: config field separate line 2022-04-12 15:53:11 +08:00
Nathan.fooo ee0939ab86 Merge pull request #450 from AppFlowy-IO/fix_rust_unit_test
Fix rust unit test
2022-04-12 11:58:49 +08:00
appflowy a0553b1255 chore: fix warnings 2022-04-12 11:52:14 +08:00
appflowy f4b206d196 chore: config test log 2022-04-12 11:13:35 +08:00
appflowy a049034110 chore: support including time on date type 2022-04-12 10:06:47 +08:00
appflowy cd14598199 chore: update archive package path 2022-04-12 08:03:39 +08:00
appflowy ce21c3207c chore: build flowy_sdk as static lib in macOS 2022-04-12 07:51:53 +08:00
Nathan.fooo 2495675fd7 Merge pull request #428 from MrTanoshii/main
Make the 2nd `'` in the `Getting started\Read me` regular text
2022-04-12 07:50:18 +08:00
hewyyy 722bacd118 fix: update view after delete to fix consecutive delete bug 2022-04-11 18:12:39 -04:00
appflowy a19536d525 chore: disable time format temporarily 2022-04-11 21:34:14 +08:00
appflowy 16a167c19c chore: update default grid 2022-04-11 21:14:45 +08:00
Nathan.fooo d0d8295e15 Merge pull request #447 from AppFlowy-IO/feat_grid_row_animation
Feat grid row animation
2022-04-11 21:07:15 +08:00
appflowy ac584fb7ef chore: fix warnings 2022-04-11 20:58:56 +08:00
appflowy f5b140a4d9 chore: disable some test 2022-04-11 20:54:43 +08:00
appflowy 31b2ace48f chore: replace SliverList with SliverAnimatedList 2022-04-11 20:52:15 +08:00
Nathan.fooo 6af78641d2 Merge pull request #446 from AppFlowy-IO/fix_data_error
Fix: grid data parser error
2022-04-11 15:37:27 +08:00
appflowy 82840e1201 chore: replace uuid with nanoid 2022-04-11 15:27:03 +08:00
appflowy f438898831 fix: grid header refresh issue 2022-04-11 14:17:56 +08:00
appflowy 2dd5930560 fix: deserial cells data from delta error 2022-04-11 14:09:50 +08:00
appflowy 9d629412c8 chore: fix transform field type error 2022-04-10 20:27:07 +08:00
appflowy 43095cb0dd chore: close grid handler 2022-04-10 16:29:45 +08:00
appflowy 5db5fd118e chore: highlight cell when edit 2022-04-10 15:07:06 +08:00
Nathan.fooo 5d9763ff7f Merge pull request #442 from AppFlowy-IO/feat_row_delete
Feature: support row delete
2022-04-10 14:57:45 +08:00
appflowy df6871e777 chore: fix wanrings 2022-04-10 14:41:42 +08:00
appflowy fbb2f49b6f chore: enable rust lint and test by remove path 2022-04-10 14:33:34 +08:00
appflowy f01d3250ae chore: reload after delete or insert row 2022-04-10 14:25:25 +08:00
appflowy 420b8ca05d chore: fix deserialize GridBlockMetaPad error 2022-04-10 10:31:55 +08:00
appflowy a755d52371 chore: using cow for row ids stuff 2022-04-10 09:14:42 +08:00
appflowy b92660058c chore: remove grid block from dart side 2022-04-10 07:10:15 +08:00
appflowy d08f298fb6 chore: rename structs 2022-04-09 22:42:42 +08:00
appflowy b93feb49c3 chore: config row action sheet 2022-04-09 22:07:48 +08:00
appflowy ed10ebac7a fix: add new select option tag from textfield 2022-04-09 20:50:03 +08:00
Nathan.fooo ce85050114 Merge pull request #441 from AppFlowy-IO/feat_date_cell
Feautre: support date column
2022-04-09 16:28:18 +08:00
appflowy a53ffdfade chore: update cell when field changed 2022-04-09 16:15:26 +08:00
appflowy 8a94644add chore: config date cell ui 2022-04-09 15:57:12 +08:00
appflowy 0ba0bb62ce chore: config flowy-sync crate log level 2022-04-09 11:55:00 +08:00
appflowy 953af35029 chore: rename struct property 2022-04-09 07:35:35 +08:00
Nathan.fooo 1e997ccaad Merge pull request #440 from AppFlowy-IO/fix_grid_ui_bugs
Fix grid UI bugs
2022-04-08 23:00:28 +08:00
appflowy fc4ed6c057 fix: grid header cell refresh after field was changed 2022-04-08 22:38:38 +08:00
appflowy fc77e0857a fix: select option cell pannel refresh 2022-04-08 21:57:24 +08:00
appflowy 59fbe02ded chore: rename class 2022-04-08 21:21:42 +08:00
appflowy 4f2c733746 chore: Merge branch 'release/0.0.4' 2022-04-08 20:22:40 +08:00
appflowy a035228798 chore: release beta package 2022-04-08 20:16:38 +08:00
appflowy 6de7933a2f fix: the updated option will added to selected option list 2022-04-08 17:44:06 +08:00
Annie 5e686906ec Update CHANGELOG.md 2022-04-08 15:17:54 +08:00
appflowy 1f657f3bf8 fix: blockService exception 2022-04-08 15:13:53 +08:00
Nathan.fooo 7b98e8dbca Update CHANGELOG.md 2022-04-08 14:46:20 +08:00
Nathan.fooo 814fdfe8e9 Merge pull request #438 from AppFlowy-IO/grid_bug_fix
chore: fix some ui bugs
2022-04-08 14:33:26 +08:00
appflowy ef008a7b0b chore: fix some ui bugs 2022-04-08 14:31:33 +08:00
appflowy 9073351cbb chore: disable create grid temporarily 2022-04-07 21:31:38 +08:00
Nathan.fooo 65993b7205 Merge pull request #435 from AppFlowy-IO/grid_field_operation
Grid field operation
2022-04-07 21:26:20 +08:00
appflowy 11627269be chore: config number ui 2022-04-07 20:54:22 +08:00
appflowy e15d335fed chore: config checkbox ui 2022-04-07 20:15:00 +08:00
appflowy c82c6d9c6e fix: deserialize multiple select cell data issues 2022-04-07 17:07:46 +08:00
appflowy bf8a752b4d fix: update row after field was changed 2022-04-07 16:37:12 +08:00
appflowy a3770a699c fix: unit test errors 2022-04-07 15:34:00 +08:00
appflowy d09a5bf42b chore: update and delete select option 2022-04-07 10:57:40 +08:00
appflowy 6a36e2bcfd chore: listen on cell update 2022-04-06 10:32:12 +08:00
appflowy c7a3bb73b9 chore: listen on row update 2022-04-05 22:46:23 +08:00
appflowy 2607822412 chore: show selection 2022-04-05 21:25:59 +08:00
appflowy 99d827f07d chore: update cell data 2022-04-05 14:25:07 +08:00
appflowy 5358203a46 chore: config option editor ui 2022-04-04 20:47:04 +08:00
appflowy 271a8485b6 chore: selection text field 2022-04-04 14:37:08 +08:00
appflowy 1abf0b565f chore: cell highlight 2022-04-04 11:10:41 +08:00
appflowy 5c3500e24c chore: cell select option editor 2022-04-03 22:22:54 +08:00
appflowy aa9e3d065b chore: show and hide property 2022-04-03 20:29:06 +08:00
appflowy 6a94594a35 chore: grid property list 2022-04-03 17:05:28 +08:00
appflowy 5d007c5359 chore: grid setting list 2022-04-03 10:53:31 +08:00
MrTanoshii 79c178a6e1 docs: make ' regular text 2022-04-02 21:18:18 +04:00
appflowy 147e948b35 chore: add grid setting 2022-04-02 23:54:48 +08:00
appflowy 6ac2617113 chore: update row state using provider 2022-04-02 23:48:56 +08:00
appflowy ca45673a9e chore: transform cell data 2022-04-02 21:30:25 +08:00
appflowy 2262dd0d7b chore: get cell metas 2022-04-02 10:54:01 +08:00
appflowy 82eed0506b chore: fix warnings 2022-04-02 08:54:32 +08:00
appflowy 915d71991a chore: save multi type option data 2022-04-01 22:46:01 +08:00
appflowy e0b969595c chore: save type option data as map 2022-04-01 17:17:31 +08:00
appflowy 80f82fa5b1 chore: update field type option data using deserializer 2022-04-01 09:31:10 +08:00
appflowy 3749168861 fix: fix some bugs 2022-03-31 22:51:46 +08:00
appflowy c3c75dde9f chore: show edit field 2022-03-31 19:45:54 +08:00
appflowy 7c6a857a69 chore: multi select 2022-03-31 14:59:57 +08:00
appflowy 4b27fef76e chore: select option color 2022-03-31 14:43:31 +08:00
appflowy 547b8ec29c fix: fix bugs 2022-03-30 22:51:52 +08:00
appflowy 065a72a8da chore: add option & color selection 2022-03-29 22:58:38 +08:00
appflowy 55b888e364 chore: single selection field 2022-03-29 11:29:21 +08:00
Mike Wallace 0c1670cdab Merge pull request #397 from hasanbeder/main
Add Turkish translation
2022-03-28 21:12:49 -04:00
hasanbeder 32aa19dc39 feat: Add Turkish translation.
Added support for the Turkish language.
2022-03-28 12:29:01 -04:00
hasanbeder dd589e0768 feat: Delete tr-TR.json 2022-03-28 12:28:50 -04:00
hasanbeder 47e2571f38 feat: Update language.dart
Turkish language line is added.
2022-03-28 12:28:35 -04:00
hasanbeder 4a797fcf96 feat: Update app_widget.dart
Turkish language line added.
2022-03-28 12:28:23 -04:00
hasanbeder f829c63bd2 feat: Turkish Language Added 2022-03-28 12:28:05 -04:00
appflowy d2080a6c03 chore: date field 2022-03-28 22:47:30 +08:00
appflowy 35e27b579f chore: number field 2022-03-27 22:38:50 +08:00
appflowy 8b7eee46bb chore: duplicate and hide field 2022-03-27 11:14:21 +08:00
appflowy c7bba01fe5 chore: delete field 2022-03-27 09:35:10 +08:00
appflowy b65b4796d2 fix: add event after bloc close 2022-03-26 22:05:26 +08:00
appflowy 16598650ff chore: lazy load cell 2022-03-26 20:27:32 +08:00
appflowy 28948e567c fix: serde type option data 2022-03-25 20:55:56 +08:00
appflowy 90e7873135 chore: create field 2022-03-25 15:02:43 +08:00
appflowy 2eccd0452b chore: close bloc when overlay dismiss 2022-03-24 23:52:06 +08:00
gaganyadav80 933689269b refactor: remove unused code 2022-03-24 15:49:53 +05:30
gaganyadav80 8ab2fe3e30 feat: adds drag-drop to docs section 2022-03-24 15:36:57 +05:30
appflowy 3fdf922f81 chore: config create field pannel 2022-03-24 17:09:05 +08:00
appflowy 694963a47d chore: add update field and create field handler 2022-03-23 22:10:31 +08:00
appflowy 188302d4ba chore: config field editor 2022-03-22 20:51:15 +08:00
appflowy 2bbcfaf3ce chore: config edit pannel 2022-03-21 23:13:19 +08:00
appflowy 475d511829 fix: can't find overlay exists above editabletext 2022-03-20 22:38:57 +08:00
appflowy 1f30a77f1d feat: save text cell data 2022-03-20 17:17:06 +08:00
Nathan.fooo c77a31806d Merge pull request #420 from AppFlowy-IO/opti_compilation
Opti compilation
2022-03-19 18:35:36 +08:00
appflowy 6a3820253f chore: rename crates 2022-03-19 16:55:29 +08:00
appflowy b1d87d95cf chore: remove unuse crates 2022-03-19 16:23:34 +08:00
appflowy 27628cc78e chore: fix rust unit test 2022-03-18 22:13:12 +08:00
Nathan.fooo d6a1afe326 Merge pull request #419 from AppFlowy-IO/feat_grid_ui
Config grid ui
2022-03-18 21:41:52 +08:00
appflowy f181ce106d chore: Merge branch 'main' into feat_grid_ui 2022-03-18 21:09:06 +08:00
appflowy 318d7e6456 chore: fix warnings 2022-03-18 21:07:31 +08:00
appflowy 05bcd38534 chore: render rows 2022-03-18 17:14:46 +08:00
appflowy 9a40fc9974 chore: lazy load row data 2022-03-17 20:59:21 +08:00
appflowy 4730ca9302 chore: refactor grid block 2022-03-17 17:25:43 +08:00
appflowy 1237962ab2 chore: config notification of grid 2022-03-16 21:19:51 +08:00
Nathan.fooo 34530a58ec Merge pull request #415 from AppFlowy-IO/fix_git_protocol_issue
fix: git protocol security issue
2022-03-16 17:56:55 +08:00
appflowy 7fd06361b3 fix: git protocol security issue 2022-03-16 17:39:36 +08:00
appflowy 694c612c67 fix: event handler not found for ApplyDocDelta 2022-03-16 16:34:38 +08:00
appflowy 8c148e3b67 chore: save text cell data & insert row 2022-03-16 16:10:35 +08:00
appflowy b3ed254caf chore: add more test and fix warnings 2022-03-16 10:02:37 +08:00
appflowy 47081f3095 chore: update grid test 2022-03-15 19:00:28 +08:00
appflowy 50f32521c5 chore: rename trait 2022-03-15 11:07:18 +08:00
appflowy 46be04f94e chore: config update cell 2022-03-14 23:16:25 +08:00
appflowy 196d254278 chore: add row test 2022-03-14 17:24:25 +08:00
appflowy d101509b32 chore: add row test 2022-03-13 23:19:43 +08:00
appflowy 572e38ec1c chore: config grid row changeset 2022-03-13 11:07:29 +08:00
appflowy baa70f2ee6 chore: add grid unit test 2022-03-12 22:52:24 +08:00
appflowy 1e6d82c0ec chore: add field builder 2022-03-12 21:53:49 +08:00
appflowy 6579940dc8 chore: create default grid 2022-03-12 10:47:34 +08:00
appflowy df399d3f35 feat: support option enum in pb 2022-03-11 22:07:01 +08:00
appflowy e11176436d chore: grid block meta editor 2022-03-11 21:36:00 +08:00
appflowy 9a791974b4 chore: config grid rev persistence 2022-03-10 22:27:19 +08:00
appflowy cea7d30a53 chore: config BlockMetaPad 2022-03-10 21:43:23 +08:00
appflowy 7ac6a1dc89 chore: rename struct 2022-03-10 17:14:10 +08:00
appflowy e45be3b81e chore: add grid meta 2022-03-10 12:01:31 +08:00
appflowy fe8811392b feat: config cells 2022-03-09 19:37:33 +08:00
appflowy 321682717c chore: opti row rebuild 2022-03-09 12:11:27 +08:00
appflowy 00db755c29 feat: add cloumn bloc 2022-03-09 09:31:06 +08:00
appflowy 808d848f62 feat: cell border 2022-03-08 22:58:43 +08:00
appflowy 54cf451826 feat: config textfield cell 2022-03-08 15:25:56 +08:00
appflowy 0502eec717 chore: config plugin display 2022-03-07 20:51:13 +08:00
appflowy 1c1e955151 chore: set error_task script 2022-03-07 08:30:59 +08:00
appflowy 733b6f7176 feat: disable grid 2022-03-06 22:02:09 +08:00
Nathan.fooo a323073244 Merge pull request #412 from AppFlowy-IO/feat_grid
Create grid/table
2022-03-06 21:55:02 +08:00
appflowy 05441f865e feat: show grid 2022-03-06 21:31:18 +08:00
appflowy 9bb516786e fix: make grid with view_id 2022-03-06 11:28:24 +08:00
appflowy 264166fa29 chore: impl view data processor 2022-03-06 09:25:34 +08:00
gaganyadav80 628e53adc1 feat: adds drag-drop support to sidebar pages
1. On mobile it uses ReorderableDelayedDragStartListener (like long press)
2. On desktop it uses ReorderableDragStartListener (instantly)
2022-03-06 01:53:15 +05:30
appflowy 1b80934899 chore: impl view data processor 2022-03-05 22:30:42 +08:00
appflowy 5c155a07bf feat: move handles to flowy-block crate 2022-03-05 21:15:10 +08:00
appflowy 11ceb96f65 feat: return rows and fields 2022-03-05 17:52:25 +08:00
appflowy 8029f1035d chore: impl handler logic 2022-03-05 10:59:44 +08:00
appflowy d0b457c007 feat: integrate grid into flowy-sdk 2022-03-04 22:09:16 +08:00
appflowy 9125db7ef0 feat: config grid editor 2022-03-04 21:26:32 +08:00
appflowy 49807a0b57 feat: config grid db 2022-03-04 18:13:17 +08:00
appflowy 67e6b091a5 feat: config grid plugin 2022-03-04 18:13:17 +08:00
appflowy 477fa5f4f6 feat: config grid bloc 2022-03-04 18:13:17 +08:00
appflowy 0bbf17f776 feat: add grid widget 2022-03-04 18:13:16 +08:00
appflowy 03f34b143d feat: add grid event 2022-03-04 18:13:16 +08:00
appflowy 4187e99433 feat: add grid struct 2022-03-04 18:13:13 +08:00
appflowy 5549cff177 chore: add flowy-grid crate 2022-03-04 18:12:46 +08:00
appflowy 84afc50cd3 chore: rename classes 2022-03-04 18:12:46 +08:00
Nathan.fooo 383925ba55 Merge pull request #407 from AppFlowy-IO/refactor_flowy_document
Rename flowy-document to flowy-block
2022-03-02 15:46:49 +08:00
appflowy 2e6dd39780 refactor: rename flowy-document to flowy-block 2022-03-02 15:22:18 +08:00
Nathan.fooo 0e8ac4828b Merge pull request #405 from MikeWallaceDev/put_business_logic_in_services2
Put business logic in services2
2022-03-02 10:20:02 +08:00
MikeWallaceDev be14a6b0ad refactor: renamed helper.dart to notification_helper.dart 2022-03-01 11:31:20 -05:00
MikeWallaceDev 31467d3e98 refactor: move resolvers to /startup 2022-03-01 11:31:20 -05:00
MikeWallaceDev c2f2ad24db refactor: Empty out infrastructure folder
move router.dart to user/presentation
move network_monitor.dart to core
move deps_resolver.dart to user/presentation
2022-03-01 11:31:20 -05:00
MikeWallaceDev 853d9e8968 refactor: put UserSettings business logic in a service 2022-03-01 11:31:20 -05:00
MikeWallaceDev 33c758e711 refactor: put Auth business logic in a service 2022-03-01 11:31:20 -05:00
Nathan.fooo e7033aa6e8 Merge pull request #403 from AppFlowy-IO/refactor_document_data_layer
Refactor document data layer
2022-03-01 23:56:05 +08:00
appflowy 8a0308703e fix: compose folder error 2022-03-01 23:38:26 +08:00
appflowy b16b61f46c chore: merge main 2022-03-01 21:09:52 +08:00
appflowy 6eddb7c8c5 chore: serde ViewDataType as u8 2022-03-01 20:51:49 +08:00
Nathan.fooo cace6248e0 Merge pull request #401 from MikeWallaceDev/put_business_logic_in_services
Put business logic in services
2022-03-01 20:29:23 +08:00
Nathan.fooo dd61dd4d2f Merge pull request #402 from tsuiyuenhong/main 2022-03-01 18:58:19 +08:00
appflowy d1ce1686a4 chore: merge main 2022-03-01 16:26:09 +08:00
appflowy 7a36fed778 refactor: remove domain folder 2022-03-01 16:17:09 +08:00
tsuiyuenhong 65917da468 chore: use actions-cache to speed up dart & rust test. 2022-03-01 15:43:42 +08:00
MikeWallaceDev 64d651ab13 refactor: move markdown to application
created a core folder
2022-02-28 23:56:41 -05:00
MikeWallaceDev 4180765dc6 refactor: Put DocShare business logic in a service 2022-02-28 23:45:17 -05:00
MikeWallaceDev afab7f23c4 refactor: Put User business logic in a service 2022-02-28 23:37:41 -05:00
MikeWallaceDev 289b3e31e7 refactor: Put View business logic in a service 2022-02-28 23:06:36 -05:00
MikeWallaceDev 871d0bb7be refactor: put Workspace business logic in a service 2022-02-28 22:38:11 -05:00
appflowy 156d38179a fix: add default value of serde 2022-03-01 11:22:39 +08:00
MikeWallaceDev a979037644 refactor: put App business logic in a service. 2022-02-28 21:42:46 -05:00
appflowy b6de0caad6 refactor: show plugin 2022-03-01 10:25:21 +08:00
MikeWallaceDev 95d33c75a5 refactor: Put Trash business logic in service 2022-02-28 21:17:08 -05:00
MikeWallaceDev 6509247fbd refactor: put document business logic into service 2022-02-28 21:02:46 -05:00
Mike Wallace 8128283ad4 Merge pull request #396 from peter-gy/main
Add Hungarian translation
2022-02-28 20:09:13 -05:00
Mike Wallace 9112bbbcd3 Merge pull request #393 from ikipm/main
Add catalan translation
2022-02-28 19:59:45 -05:00
Mike Wallace d1e1813002 Merge pull request #387 from luzpaz/typos
Fix various typos
2022-02-28 19:59:16 -05:00
appflowy 8747457836 refactor: add plugins 2022-03-01 00:23:04 +08:00
Péter Ferenc Gyarmati d9f7b1047d feature: add Hungarian translation 2022-02-28 11:46:01 +01:00
appflowy 74831964a6 feat: update view properties 2022-02-28 16:00:43 +08:00
ikipm d00425d50b feature: Added catalan translation 2022-02-27 13:41:26 -05:00
luz paz 5d09e1509d fix: various typos
Found via `codespell -q 3 -S *.svg,./frontend/app_flowy/assets/translations -L bloc,crate,homestate,nd,ot,ser`
2022-02-27 13:14:14 -05:00
Mike Wallace 11fee0a815 Update README.md 2022-02-27 13:06:15 -05:00
Mike Wallace 4cf509d695 Merge pull request #302 from lays147/main
Add portuguese translation
2022-02-27 11:21:39 -05:00
Lays Rodrigues 8f50d0c6dc feat: add portuguese translation
Signed-off-by: Lays Rodrigues <laysrodriguessilva@gmail.com>
2022-02-27 10:28:58 -05:00
Nathan.fooo 912fb0b9da Merge pull request #391 from tsuiyuenhong/main
chore: use actions-cache to speed up CI.
2022-02-27 10:44:08 +08:00
tsuiyuenhong 3021bdc1af chore: use actions-cache to speed up CI. 2022-02-26 22:56:48 +08:00
appflowy 23ccfa54b5 feat: config new ViewType 2022-02-26 18:35:42 +08:00
appflowy d18e06a9ef feat: migrate ViewType::Doc to ViewType::QuillDocument 2022-02-26 18:28:09 +08:00
appflowy c843571e3d feat: add new view_type, kanban 2022-02-26 17:28:23 +08:00
Nathan.fooo e282a7672f Merge pull request #388 from AppFlowy-IO/remove_freezed_files
chore: delete remaining freeze files
2022-02-26 17:16:05 +08:00
appflowy d6770c6690 chore: delete freeze files 2022-02-26 16:49:55 +08:00
appflowy 01985848f9 refactor: rename structs 2022-02-26 11:03:42 +08:00
Mike Wallace 0a9fb53ef8 Merge pull request #289 from Aquitano/main
Added german translations
2022-02-25 13:49:31 -05:00
Aquitano / Thomas Breindl e9226243df Merge branch 'main' of https://github.com/Aquitano/appflowy 2022-02-25 11:51:11 -05:00
Aquitano / Thomas Breindl 2d7d61bdaa Renamed de_DE.json to de-DE.json 2022-02-25 11:51:11 -05:00
Aquitano 3eacf70edd Updated german translation
changes were suggested by lguenth
2022-02-25 11:51:11 -05:00
Aquitano / Thomas Breindl cebf097fb2 Added german translations
+ added de_DE.json
+ registered german locale
2022-02-25 11:51:11 -05:00
appflowy 6078e46d3d refactor: rename structs 2022-02-25 23:30:02 +08:00
Nathan.fooo 349a8350c3 Merge pull request #381 from MikeWallaceDev/adjust_commitlint_config
Adjust commitlint config
2022-02-25 13:15:51 +08:00
Nathan.fooo d13a6b9649 Merge pull request #382 from MikeWallaceDev/improve_french_translation
fix: improve French Canadian translation
2022-02-25 13:14:09 +08:00
Nathan.fooo d5cc168d75 Merge pull request #383 from AppFlowy-IO/fix_dart_test
ci: try to fix dart test
2022-02-25 13:13:52 +08:00
appflowy 926b1666dd ci: try to fix dart test 2022-02-25 11:37:14 +08:00
MikeWallaceDev 8bdcb43332 fix: improve French Canadian translation 2022-02-24 21:22:27 -05:00
Mehdi BertulandMikeWallaceDev f8f77db79b Fix the translation to fr-FR (Closes #369) (#371)
* fix: rename fr.json to fr-FR.json
* fix: the translation mistakes in fr-FR.json
* fix: added french language to system

Co-authored-by: MikeWallaceDev <mike@wallacehub.com>
2022-02-24 20:48:47 -05:00
MikeWallaceDev be3141b08e ci: improve commitlint configuration
Added types: build, feature
no longer checks subject's case
now forces a leading blank before body (This is required by Github)
Increased body length to 200
2022-02-24 20:36:18 -05:00
MikeWallaceDev 87cc542275 refactor: change order of rules
rules are now in order of a commit message and separated into sections.
2022-02-24 20:22:02 -05:00
Nathan.fooo 441627783b Merge pull request #379 from AppFlowy-IO/refactor_document
Refactor folder crate structs
2022-02-24 23:52:58 +08:00
Nathan.fooo 03192f8d7e Merge pull request #373 from PabloCastellano/more-docker
Multiple improvements in docker image
2022-02-24 23:25:42 +08:00
appflowy ed9a48fc1c chore: rename struct property 2022-02-24 23:19:41 +08:00
appflowy 93695dc4be chore: rename structs 2022-02-24 20:36:24 +08:00
appflowy 62c104179a chore: ignore ds_store files 2022-02-24 20:35:22 +08:00
appflowy b855a1199d Merge branch 'main' into refactor_document 2022-02-24 17:29:29 +08:00
Nathan.fooo 5fdeff83dd Merge pull request #377 from AppFlowy-IO/fix_dart_test
ci: fix dart test
2022-02-24 17:28:58 +08:00
Nathan.fooo 959b2db9a3 Merge pull request #376 from gaganyadav80/emoji_picker
feat: add emoji picker
2022-02-24 17:18:17 +08:00
appflowy d30ac55b0f ci: fix dart test 2022-02-24 17:08:31 +08:00
appflowy 67a3ba6b34 chore: merge main 2022-02-24 16:49:14 +08:00
Nathan 74ca10cf28 Merge branch 'main' of github.com:AppFlowy-IO/appflowy 2022-02-24 16:17:45 +08:00
nathan 4bcc05fc8a chore: add code gen introductions 2022-02-24 16:17:02 +08:00
Nathan.fooo c5759baea4 Merge pull request #374 from hieugao/refactor/remove-freezed-files
Remove `freezed` files
2022-02-24 16:15:43 +08:00
Hieu 0c9fc35cb3 ci: refactor code generation 2022-02-24 14:40:48 +07:00
Hieu d05e4bbc82 chore: ignore freezed files 2022-02-24 12:56:54 +07:00
Nathan.fooo aa77d52b58 Merge pull request #375 from Pualoo/fix_docbanner
fix: DocBanner overflow issue: #354
2022-02-24 11:58:33 +08:00
gaganyadav80 6ffa1ad191 feat: add emoji picker
1. files are under lib/workspace/presentation/widgets/emoji_picker/
2. add icon for emoji picker button on toolbar.
3. handles case when no emoji is found for the given query.
2022-02-24 02:09:51 +05:30
Pualoo 3a2424cda3 fix: DocBanner overflow issue#354 2022-02-23 14:33:08 -03:00
Hieu 288afbe68b ci: no more sed
Fix "Bad state: Unable to generate package graph"
2022-02-23 22:02:46 +07:00
appflowy c1237452ab refactor: rename some class names 2022-02-23 22:32:27 +08:00
Hieu 6e1c6d7a47 fix: cargo-make platforms, mac not macos 2022-02-23 21:18:20 +07:00
Hieu 6ae8efbdfe ci: generate freezed files 2022-02-23 20:40:22 +07:00
Hieu a0654d8a41 chore: disable invalid_annotation_target warning 2022-02-23 20:39:29 +07:00
Hieu a829d2ac61 refactor: remove freezed files 2022-02-23 20:33:17 +07:00
Pablo Castellano 3bfda80911 docs: add docker command to readme 2022-02-23 13:14:08 +01:00
Pablo Castellano 0b2bb33b73 fix: multiple improvements in docker image
* Reduce image size again, to 894MB
* Adjust permissions and remove need to run xhost
* Run appflowy as unprivileged user
* Add README file for more information
2022-02-23 12:28:28 +01:00
Nathan.fooo b8a4897056 Update CHANGELOG.md
add 0.0.3 version change log
2022-02-23 10:04:14 +08:00
appflowy 3028195e5e chore: rename docker image 2022-02-22 19:32:09 +08:00
Nathan.fooo fe3533cb2c Merge pull request #367 from AppFlowy-IO/docker_setting
Docker setting
2022-02-22 15:49:20 +08:00
appflowy 06d3aace92 ci: update build cache name 2022-02-22 15:48:51 +08:00
Nathan.fooo 3f90170c71 Merge pull request #348 from PabloCastellano/github-docker-push
Push docker image to Docker Hub
2022-02-22 09:18:10 +08:00
Nathan.fooo ef770980f5 Merge pull request #345 from PabloCastellano/docker 2022-02-21 22:47:30 +08:00
Nathan.fooo b5d463578a Merge pull request #364 from tsuiyuenhong/main 2022-02-21 22:46:02 +08:00
Pablo Castellano ca0851418e chore: use docker multi-stage builds
Previous image was 7.69GB which is somewhat heavy.
Now the resulting image is 1.20GB thanks to multi-stage builds.
2022-02-21 10:06:41 +01:00
xurunkang a6221d34cb chore: move CHANGELOG.md to the root dir 2022-02-21 15:59:04 +08:00
Nathan.fooo 7eada39a8b Merge pull request #346 from PabloCastellano/docker-fix
Fix docker build
2022-02-21 10:22:11 +08:00
Pablo Castellano 23795e1b67 feat: add docker-compose data persistance 2022-02-20 11:00:01 +01:00
Nathan.fooo 7314f02282 Merge pull request #352 from AppFlowy-IO/bloc_test
Bloc test
2022-02-20 16:37:40 +08:00
appflowy e3d9d4c42a chore: rename some enum 2022-02-20 16:34:15 +08:00
appflowy 22742c904b chore: rename some classes 2022-02-20 16:12:43 +08:00
appflowy 9012494e1f chore: update launch option 2022-02-20 09:59:52 +08:00
appflowy c9424c5d55 Merge branch 'main' into bloc_test 2022-02-20 08:49:53 +08:00
appflowy cdec567cbb feat: separate develop, release, test working directory 2022-02-20 08:35:52 +08:00
Annie 33358c2a04 Merge pull request #353 from jay-tau/patch-1
Add French Translations
2022-02-20 08:31:45 +08:00
appflowy e9ba9ad149 ci: add .appflowy_dev 2022-02-20 08:06:53 +08:00
appflowy 7d93ed8e81 ci: run actions when specified files changed. 2022-02-20 07:22:39 +08:00
appflowy 860ebc567b ci: update dart_tests 2022-02-20 07:08:42 +08:00
appflowy bf7e1b9829 ci: add build flowy_sdk deps 2022-02-19 23:26:38 +08:00
appflowy 0b0cbe192b ci: run flutter test on ci 2022-02-19 23:19:33 +08:00
Joel Tony 0acb7063ed Add 'fr' 2022-02-19 17:45:34 +05:30
Joel Tony cf1ecaf89b Create fr.json 2022-02-19 15:48:59 +05:30
appflowy 2781809f87 chore: await Sytem launch 2022-02-19 17:12:44 +08:00
appflowy 6fc8197468 feat: build flowy_sdk as dylib on macOS 2022-02-19 16:59:36 +08:00
appflowy c559c5cc6b feat: config bloc test 2022-02-19 16:48:57 +08:00
appflowy 2c3aade0f9 refactor: remove unuse code 2022-02-19 13:52:52 +08:00
Pablo Castellano cea62a5c8e ci: push docker image to Docker Hub 2022-02-17 22:48:34 +01:00
Pablo Castellano 7820c8e70d fix: also mount other required volumes in docker-compose 2022-02-17 21:43:02 +01:00
Pablo Castellano bde597a10b fix: docker build
❌ The protoc-gen-dart was not installed correctly.
✅ You can fix that by adding "dart pub global activate protoc_plugin" to your shell's
config file.(.bashrc, .bash, etc.)
2022-02-17 21:43:02 +01:00
799 changed files with 55899 additions and 21296 deletions

No files matched your search

+70 -64
View File
@@ -1,79 +1,85 @@
name: CI
on:
push:
branches: [main]
branches:
- 'main'
pull_request:
branches: [main]
branches:
- 'main'
jobs:
build-macos:
runs-on: macOS-latest
build:
strategy:
matrix:
os: [ubuntu-latest, macos-latest]
include:
- os: ubuntu-latest
flutter_profile: development-linux-x86
- os: macos-latest
flutter_profile: development-mac-x86_64
runs-on: ${{ matrix.os }}
steps:
- name: Checkout
uses: actions/checkout@v2
- uses: actions-rs/toolchain@v1
- uses: actions/checkout@v2
- id: rust_toolchain
uses: actions-rs/toolchain@v1
with:
toolchain: stable
- name: Checkout Flutter
uses: actions/checkout@v2
toolchain: 'stable-2022-01-20'
- id: flutter
uses: subosito/flutter-action@v2
with:
repository: flutter/flutter
path: flutter
- name: Flutter
working-directory: flutter
run: |
echo "$(pwd)/bin" >> $GITHUB_PATH
export PATH="$PATH:$(pwd)/bin"
flutter channel stable
flutter config --enable-macos-desktop
flutter doctor
channel: 'stable'
cache: true
flutter-version: '3.0.0'
- name: Cache Cargo
uses: actions/cache@v2
with:
path: |
~/.cargo
key: ${{ runner.os }}-cargo-${{ steps.rust_toolchain.outputs.rustc_hash }}-${{ hashFiles('./frontend/rust-lib/Cargo.toml') }}
- name: Cache Rust
uses: actions/cache@v2
with:
path: |
frontend/rust-lib/target
shared-lib/target
key: ${{ runner.os }}-rust-rust-lib-share-lib-${{ steps.rust_toolchain.outputs.rustc_hash }}-${{ hashFiles('./frontend/rust-lib/Cargo.toml') }}
- name: Setup Environment
run: |
if [ "$RUNNER_OS" == "Linux" ]; then
sudo wget -qO /etc/apt/trusted.gpg.d/dart_linux_signing_key.asc https://dl-ssl.google.com/linux/linux_signing_key.pub
sudo wget -qO /etc/apt/sources.list.d/dart_stable.list https://storage.googleapis.com/download.dartlang.org/linux/debian/dart_stable.list
sudo apt-get update
sudo apt-get install -y dart curl build-essential libsqlite3-dev libssl-dev clang cmake ninja-build pkg-config libgtk-3-dev
elif [ "$RUNNER_OS" == "macOS" ]; then
echo 'do nothing'
fi
shell: bash
- name: Deps
working-directory: frontend
run: |
cargo install --force cargo-make
cargo install --force duckscript_cli
cargo install cargo-make
cargo install duckscript_cli
cargo make flowy_dev
echo PATH="$PATH":"$HOME/.pub-cache/bin" >> $GITHUB_PATH
- name: Config Flutter
run: |
if [ "$RUNNER_OS" == "Linux" ]; then
flutter config --enable-linux-desktop
elif [ "$RUNNER_OS" == "macOS" ]; then
flutter config --enable-macos-desktop
fi
shell: bash
- name: Build
working-directory: frontend
run: cargo make --profile production-mac-x86 appflowy
build-ubuntu:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Packages
run: |
sudo wget -qO /etc/apt/trusted.gpg.d/dart_linux_signing_key.asc https://dl-ssl.google.com/linux/linux_signing_key.pub
sudo wget -qO /etc/apt/sources.list.d/dart_stable.list https://storage.googleapis.com/download.dartlang.org/linux/debian/dart_stable.list
sudo apt-get update
sudo apt-get install -y dart curl build-essential libsqlite3-dev libssl-dev clang cmake ninja-build pkg-config libgtk-3-dev
- name: Rust
run: |
curl \
--proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
source $HOME/.cargo/env
rustup toolchain install stable
rustup default stable
- name: Checkout Flutter
uses: actions/checkout@v2
with:
repository: flutter/flutter
path: flutter
- name: Flutter
working-directory: flutter
run: |
echo "$(pwd)/bin" >> $GITHUB_PATH
export PATH="$PATH:$(pwd)/bin"
flutter channel stable
flutter config --enable-linux-desktop
flutter doctor
- name: Deps
working-directory: frontend
run: |
cargo install --force cargo-make
cargo install --force duckscript_cli
cargo make flowy_dev
echo PATH="$PATH":"$HOME/.pub-cache/bin" >> $GITHUB_PATH
- name: Build
working-directory: frontend
run: cargo make --profile production-linux-x86 appflowy
cargo make --profile ${{ matrix.flutter_profile }} appflowy-dev
+8 -7
View File
@@ -11,7 +11,6 @@ on:
pull_request:
branches: [ main ]
env:
CARGO_TERM_COLOR: always
@@ -24,15 +23,17 @@ jobs:
uses: actions/checkout@v2
- uses: subosito/flutter-action@v1
with:
flutter-version: '3.0.0'
channel: "stable"
- name: Flutter pub get
run: flutter pub get
- name: Deps Flutter
run: flutter packages pub get
working-directory: frontend/app_flowy
- name: Generate language files
- name: Code Generation
working-directory: frontend/app_flowy
run:
flutter pub run easy_localization:generate --source-dir ./assets/translations -f keys -O lib/generated -o locale_keys.g.dart
- name: flutter analyze
run: |
flutter packages pub run easy_localization:generate -f keys -o locale_keys.g.dart -S assets/translations -s en.json
flutter packages pub run build_runner build --delete-conflicting-outputs
- name: Run Flutter Analyzer
working-directory: frontend/app_flowy
run: flutter analyze
+75
View File
@@ -0,0 +1,75 @@
name: Unit test(Flutter)
on:
push:
branches:
- 'main'
pull_request:
branches:
- 'main'
env:
CARGO_TERM_COLOR: always
jobs:
tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions-rs/toolchain@v1
with:
toolchain: 'stable-2022-01-20'
- uses: subosito/flutter-action@v2
with:
channel: 'stable'
flutter-version: '3.0.0'
cache: true
- name: Cache Cargo
uses: actions/cache@v2
with:
path: |
~/.cargo
key: ${{ runner.os }}-cargo-${{ steps.rust_toolchain.outputs.rustc_hash }}-${{ hashFiles('./frontend/rust-lib/Cargo.toml') }}
- name: Cache Rust
uses: actions/cache@v2
with:
path: |
frontend/rust-lib/target
shared-lib/target
key: ${{ runner.os }}-rust-rust-lib-share-lib-${{ steps.rust_toolchain.outputs.rustc_hash }}-${{ hashFiles('./frontend/rust-lib/Cargo.toml') }}
- name: Deps Flutter
working-directory: frontend/app_flowy
run: |
flutter config --enable-linux-desktop
- name: Deps Rust
working-directory: frontend
run: |
cargo install cargo-make
cargo install duckscript_cli
cargo make flowy_dev
- name: Code Generation
working-directory: frontend/app_flowy
run: |
flutter packages pub get
flutter packages pub run easy_localization:generate -f keys -o locale_keys.g.dart -S assets/translations -s en.json
flutter packages pub run build_runner build --delete-conflicting-outputs
- name: Build FlowySDK
working-directory: frontend
run: |
cargo make --profile development-linux-x86 flowy-sdk-dev
- name: Run bloc tests
working-directory: frontend/app_flowy
run: |
flutter pub get
flutter test
+16 -15
View File
@@ -17,7 +17,6 @@ jobs:
uses: actions/checkout@v2
- name: Build release notes
working-directory: frontend/app_flowy
run: |
touch ${{ env.RELEASE_NOTES_PATH }}
cat CHANGELOG.md | sed -e '/./{H;$!d;}' -e "x;/##\ Version\ ${{ github.ref_name }}/"'!d;' >> ${{ env.RELEASE_NOTES_PATH }}
@@ -35,22 +34,23 @@ jobs:
build-linux-x86:
runs-on: ubuntu-latest
needs: create-release
env:
env:
LINUX_APP_RELEASE_PATH: frontend/app_flowy/product/${{ github.ref_name }}/linux/Release
LINUX_ZIP_NAME: AppFlowy-linux-x86.tar.gz
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Setup environment - Rust and Cargo
uses: actions-rs/toolchain@v1
with:
toolchain: stable
toolchain: 'stable-2022-01-20'
- name: Setup environment - Flutter
uses: subosito/flutter-action@v2
with:
channel: 'stable'
flutter-version: '3.0.0'
- name: Pre build
working-directory: frontend
@@ -62,13 +62,13 @@ jobs:
cargo install --force cargo-make
cargo install --force duckscript_cli
cargo make flowy_dev
- name: Build Linux app
working-directory: frontend
run: |
flutter config --enable-linux-desktop
cargo make --profile production-linux-x86 appflowy
cargo make --env APP_VERSION=${{ github.ref_name }} --profile production-linux-x86 appflowy
- name: Upload Release Asset
id: upload-release-asset
uses: actions/upload-release-asset@v1
@@ -83,7 +83,7 @@ jobs:
build-macos-x86_64:
runs-on: macos-latest
needs: create-release
env:
env:
MACOS_APP_RELEASE_PATH: frontend/app_flowy/product/${{ github.ref_name }}/macos/Release
MACOS_X86_ZIP_NAME: Appflowy-macos-x86_64.zip
steps:
@@ -93,12 +93,13 @@ jobs:
- name: Setup environment - Rust and Cargo
uses: actions-rs/toolchain@v1
with:
toolchain: stable
toolchain: 'stable-2022-01-20'
- name: Setup environment - Flutter
uses: subosito/flutter-action@v2
with:
channel: 'stable'
flutter-version: '3.0.0'
- name: Pre build
working-directory: frontend
@@ -107,17 +108,17 @@ jobs:
cargo install --force cargo-make
cargo install --force duckscript_cli
cargo make flowy_dev
- name: Build macOS app for x86_64
working-directory: frontend
run: |
flutter config --enable-macos-desktop
cargo make --profile production-mac-x86 appflowy
cargo make --env APP_VERSION=${{ github.ref_name }} --profile production-mac-x86_64 appflowy
- name: Archive macOS app
working-directory: ${{ env.MACOS_APP_RELEASE_PATH }}
run: zip -qr ${{ env.MACOS_X86_ZIP_NAME }} AppFlowy.app
- name: Upload Release Asset
uses: actions/upload-release-asset@v1
env:
@@ -126,4 +127,4 @@ jobs:
upload_url: ${{ needs.create-release.outputs.upload_url }}
asset_path: ${{ env.MACOS_APP_RELEASE_PATH }}/${{ env.MACOS_X86_ZIP_NAME }}
asset_name: ${{ env.MACOS_X86_ZIP_NAME }}
asset_content_type: application/octet-stream
asset_content_type: application/octet-stream
+35
View File
@@ -0,0 +1,35 @@
name: release_docker
on:
push:
branches:
- 'main'
tags:
- '*'
jobs:
build-docker-image:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Login to Docker Hub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKER_HUB_USERNAME }}
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: Build and push
uses: docker/build-push-action@v2
with:
context: .
file: ./frontend/scripts/docker-buildfiles/Dockerfile
builder: ${{ steps.buildx.outputs.name }}
push: true
tags: ${{ secrets.DOCKER_HUB_USERNAME }}/appflowy_client:${{ github.ref_name }}
cache-from: type=registry,ref=${{ secrets.DOCKER_HUB_USERNAME }}/af_build_cache:buildcache
cache-to: type=registry,ref=${{ secrets.DOCKER_HUB_USERNAME }}/af_build_cache:buildcache,mode=max
+2 -8
View File
@@ -3,14 +3,8 @@ name: Rust lint
on:
push:
branches: [ main ]
paths:
- 'frontend/rust-lib'
- 'shared-lib'
pull_request:
branches: [ main ]
paths:
- 'frontend/rust-lib'
- 'shared-lib'
env:
@@ -24,7 +18,7 @@ jobs:
- uses: actions/checkout@v2
- uses: actions-rs/toolchain@v1
with:
toolchain: stable
toolchain: 'stable-2022-01-20'
override: true
- run: rustup component add rustfmt
working-directory: frontend/rust-lib
@@ -39,7 +33,7 @@ jobs:
- uses: actions/checkout@v2
- uses: actions-rs/toolchain@v1
with:
toolchain: stable
toolchain: 'stable-2022-01-20'
override: true
- run: rustup component add clippy
working-directory: frontend/rust-lib
+32 -20
View File
@@ -2,15 +2,11 @@ name: Unit test(Rust)
on:
push:
branches: [ main ]
# paths:
# - 'frontend/rust-lib'
# - 'shared-lib'
branches:
- 'main'
pull_request:
branches: [ main ]
# paths:
# - 'frontend/rust-lib'
# - 'shared-lib'
branches:
- 'main'
env:
CARGO_TERM_COLOR: always
@@ -21,19 +17,35 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Install Rust
run: |
curl \
--proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
source $HOME/.cargo/env
rustup toolchain install stable
rustup default stable
- id: rust_toolchain
uses: actions-rs/toolchain@v1
with:
toolchain: 'stable-2022-01-20'
- name: Cache Cargo
uses: actions/cache@v2
with:
path: |
~/.cargo
key: ${{ runner.os }}-cargo-${{ steps.rust_toolchain.outputs.rustc_hash }}-${{ hashFiles('./frontend/rust-lib/Cargo.toml') }}
- name: Cache Rust
uses: actions/cache@v2
with:
path: |
frontend/rust-lib/target
shared-lib/target
key: ${{ runner.os }}-rust-rust-lib-share-lib-${{ steps.rust_toolchain.outputs.rustc_hash }}-${{ hashFiles('./frontend/rust-lib/Cargo.toml') }}
- name: Install cargo-make
run: cargo install --force cargo-make
working-directory: frontend
- name: RustLib tests
run: cargo test --no-default-features
run: cargo install cargo-make
- name: Run rust-lib tests
working-directory: frontend/rust-lib
- name: Sharedlib tests
run: cargo test --no-default-features
run: RUST_LOG=info cargo test --no-default-features --features="sync"
- name: Run shared-lib tests
working-directory: shared-lib
run: RUST_LOG=info cargo test --no-default-features
+2 -1
View File
@@ -16,4 +16,5 @@ package-lock.json
yarn.lock
node_modules
**/.proto_cache
**/.cache
**/.cache
**/.DS_Store
+27
View File
@@ -0,0 +1,27 @@
# Release Notes
## Version 0.0.4 - beta.1 - 2022-04-08
v0.0.4 - beta.1 is pre-release
New features
- Table-view database
- supported column types: Text, Checbox, Single-select, Multi-select, Numbers
- hide / delete columns
- insert rows
## Version 0.0.3 - 2022-02-23
v0.0.3 is production ready, available on Linux, macOS, and Windows
New features
- Dark Mode
- Support new languages: French, Italian, Russian, Simplified Chinese, Spanish
- Add Settings: Toggle on Dark Mode; Select a language
- Show device info
- Add tooltip on toolbar icons
Bug fixes and improvements
- Increased height of action
- CPU performance issue
- Fix potential data parser error
- More foundation work for online collaboration
+4 -3
View File
@@ -20,12 +20,13 @@ You are in charge of your data and customizations.
<p align="center">
<a href="http://www.appflowy.io"><b>Website</b></a> •
<a href="https://discord.gg/9Q2xaN37tV"><b>Discord</b></a> •
<a href="https://twitter.com/appflowy"><b>Twitter</b></a>
</p>
<a href="https://twitter.com/appflowy"><b>Twitter</b></a>
</p>
<p align="center"><img src="https://github.com/AppFlowy-IO/appflowy/blob/main/doc/imgs/welcome.png" alt="The Open Source Alternative To Notion." width="1000px" /></p>
## User Installation
Please view the [documentation](https://appflowy.gitbook.io/docs/essential-documentation/install-appflowy/installation-methods) for OS specific installation instructions.
## Built With
@@ -85,4 +86,4 @@ Distributed under the AGPLv3 License. See `LICENSE.md` for more information.
Special thanks to these amazing projects which help power AppFlowy.IO:
- [flutter-quill](https://github.com/singerdmx/flutter-quill)
- [cargo-make](https://github.com/sagiegurari/cargo-make)
- [cargo-make](https://github.com/sagiegurari/cargo-make)
+14 -10
View File
@@ -1,20 +1,24 @@
// module.exports = {extends: ['@commitlint/config-conventional']}
module.exports = {
rules: {
'type-enum': [2, 'always', ['chore', 'ci', 'docs', 'feat', 'fix', 'refactor', 'style', 'test']],
'body-leading-blank': [1, 'always'],
'body-max-line-length': [2, 'always', 100],
'footer-leading-blank': [1, 'always'],
'footer-max-line-length': [2, 'always', 100],
'header-max-length': [2, 'always', 100],
'type-enum': [2, 'always', ['build', 'chore', 'ci', 'docs', 'feat', 'feature', 'fix', 'refactor', 'style', 'test']],
'type-empty': [2, 'never'],
'type-case': [2, 'always', 'lower-case'],
'subject-empty': [2, 'never'],
'subject-case': [
2,
0,
'never',
['sentence-case', 'start-case', 'pascal-case', 'upper-case'],
],
'subject-empty': [2, 'never'],
'type-empty': [2, 'never'],
'type-case': [2, 'always', 'lower-case'],
'body-case': [2, 'never', []]
'body-leading-blank': [2, 'always'],
'body-max-line-length': [2, 'always', 200],
'body-case': [0, 'never', []],
'footer-leading-blank': [1, 'always'],
'footer-max-line-length': [2, 'always', 100]
},
};
+2 -2
View File
@@ -11,7 +11,7 @@
"type": "dart",
"preLaunchTask": "build_flowy_sdk",
"env":{
"RUST_LOG":"info",
"RUST_LOG":"info"
},
"cwd": "${workspaceRoot}/app_flowy"
},
@@ -22,7 +22,7 @@
"type": "dart",
"preLaunchTask": "build_flowy_sdk",
"env":{
"RUST_LOG":"trace",
"RUST_LOG":"trace"
},
"cwd": "${workspaceRoot}/app_flowy"
},
+35 -8
View File
@@ -7,32 +7,61 @@ extend = [
{ path = "scripts/makefile/docker.toml" },
{ path = "scripts/makefile/env.toml" },
{ path = "scripts/makefile/flutter.toml" },
{ path = "scripts/makefile/tool.toml" },
]
[config]
on_error_task = "catch"
[tasks.catch]
run_task = {name = ["restore-crate-type"]}
[env]
RUST_LOG = "info"
CARGO_MAKE_EXTEND_WORKSPACE_MAKEFILE = true
CARGO_MAKE_CRATE_FS_NAME = "dart_ffi"
CARGO_MAKE_CRATE_NAME = "dart-ffi"
VERSION = "0.0.3"
LIB_NAME = "dart_ffi"
CURRENT_APP_VERSION = "0.0.4"
FEATURES = "flutter"
PRODUCT_NAME = "AppFlowy"
#CRATE_TYPE: https://doc.rust-lang.org/reference/linkage.html
# CRATE_TYPE: https://doc.rust-lang.org/reference/linkage.html
# If you update the macOS's CRATE_TYPE, don't forget to update the
# flowy_sdk.podspec
# for staticlib:
# s.static_framework = true
# s.vendored_libraries = "libdart_ffi.a"
# for cdylib:
# s.vendored_libraries = "libdart_ffi.dylib"
#
# Remember to update the ffi.dart:
# for staticlib:
# if (Platform.isMacOS) return DynamicLibrary.open('${prefix}/libdart_ffi.a');
# for cdylib:
# if (Platform.isMacOS) return DynamicLibrary.open('${prefix}/libdart_ffi.dylib');
CRATE_TYPE = "staticlib"
SDK_EXT = "a"
APP_ENVIRONMENT = "local"
FLUTTER_FLOWY_SDK_PATH="app_flowy/packages/flowy_sdk"
PROTOBUF_DERIVE_CACHE="../shared-lib/flowy-derive/src/derive_cache/derive_cache.rs"
[env.development-mac]
RUST_LOG = "trace"
[env.development-mac-arm64]
RUST_LOG = "info"
TARGET_OS = "macos"
RUST_COMPILE_TARGET = "aarch64-apple-darwin"
BUILD_FLAG = "debug"
FLUTTER_OUTPUT_DIR = "Debug"
PRODUCT_EXT = "app"
[env.development-mac-x86_64]
RUST_LOG = "info"
TARGET_OS = "macos"
RUST_COMPILE_TARGET = "x86_64-apple-darwin"
BUILD_FLAG = "debug"
FLUTTER_OUTPUT_DIR = "Debug"
PRODUCT_EXT = "app"
[env.production-mac-aarch64]
[env.production-mac-arm64]
BUILD_FLAG = "release"
TARGET_OS = "macos"
RUST_COMPILE_TARGET = "aarch64-apple-darwin"
@@ -40,7 +69,7 @@ FLUTTER_OUTPUT_DIR = "Release"
PRODUCT_EXT = "app"
APP_ENVIRONMENT = "production"
[env.production-mac-x86]
[env.production-mac-x86_64]
BUILD_FLAG = "release"
TARGET_OS = "macos"
RUST_COMPILE_TARGET = "x86_64-apple-darwin"
@@ -124,7 +153,6 @@ script_runner = "@shell"
[env.production-ios]
BUILD_FLAG = "release"
TARGET_OS = "ios"
CRATE_TYPE = "staticlib"
FLUTTER_OUTPUT_DIR = "Release"
PRODUCT_EXT = "ipa"
@@ -153,7 +181,6 @@ script = [
]
script_runner = "@duckscript"
[tasks.test-build]
condition = { env_set = [ "FLUTTER_FLOWY_SDK_PATH"] }
script = [
+6 -1
View File
@@ -37,6 +37,10 @@ lib/generated_plugin_registrant.dart
# Language related generated files
lib/generated/
# Freezed generated files
*.g.dart
*.freezed.dart
# Symbolication related
app.*.symbols
@@ -59,4 +63,5 @@ windows/flutter/dart_ffi/
**/**/*.lib
**/**/*.dll
**/**/*.so
**/**/Brewfile.lock.json
**/**/Brewfile.lock.json
**/.sandbox
+21 -17
View File
@@ -5,40 +5,44 @@
"version": "0.2.0",
"configurations": [
{
"name": "app_flowy",
// This task builds the Rust and Dart code of AppFlowy.
"name": "Build",
"request": "launch",
"program": "${workspaceRoot}/lib/main.dart",
"type": "dart",
"preLaunchTask": "build_flowy_sdk",
"env":{
"RUST_LOG":"info",
"type": "dart",
"env": {
"RUST_LOG": "debug"
},
"cwd": "${workspaceRoot}"
},
{
"name": "app_flowy(trace)",
// This task only build the Dart code of AppFlowy.
"name": "Build (Dart)",
"request": "launch",
"program": "${workspaceRoot}/lib/main.dart",
"type": "dart",
"preLaunchTask": "build_flowy_sdk",
"env":{
"RUST_LOG":"trace",
"env": {
"RUST_LOG": "debug"
},
"cwd": "${workspaceRoot}"
},
{
"name": "app_flowy (profile mode)",
"name": "Build (trace log)",
"request": "launch",
"program": "${workspaceRoot}/lib/main.dart",
"type": "dart",
"preLaunchTask": "build_flowy_sdk",
"env": {
"RUST_LOG": "trace"
},
"cwd": "${workspaceRoot}"
},
{
"name": "Build (profile mode)",
"request": "launch",
"type": "dart",
"flutterMode": "profile"
},
{
"name": "Generate Language Files",
"request": "launch",
"program": "${workspaceRoot}/lib/main.dart",
"type": "dart",
"preLaunchTask": "Generate Language Files",
"cwd": "${workspaceRoot}"
},
]
}
+34 -4
View File
@@ -50,6 +50,40 @@
// "$rustc"
// ],
},
{
"label": "Code Gen",
"type": "shell",
"dependsOn": [
"Flutter Pub",
"Flutter Package Get",
"Generate Language Files",
"Generate Freezed Files"
],
"group": {
"kind": "build",
"isDefault": true,
},
"dependsOrder": "sequence",
"presentation": {
"reveal": "always",
"panel": "new"
},
},
{
"label": "Flutter Pub",
"type": "shell",
"command": "flutter pub get",
},
{
"label": "Flutter Package Get",
"type": "shell",
"command": "flutter packages pub get",
},
{
"label": "Generate Freezed Files",
"type": "shell",
"command": "flutter pub run build_runner build --delete-conflicting-outputs",
},
{
"label": "Generate Language Files",
"type": "shell",
@@ -87,10 +121,6 @@
}
}
},
"group": {
"kind": "build",
"isDefault": true,
},
"options": {
"cwd": "${workspaceFolder}/../"
},
-4
View File
@@ -1,4 +0,0 @@
# Release Notes
## Version 0.0.0 - 2022-22-14
* 😁 Replace Me.
+3
View File
@@ -36,3 +36,6 @@ linter:
# Additional information about this file can be found at
# https://dart.dev/guides/language/analysis-options
errors:
invalid_annotation_target: ignore
@@ -1,3 +0,0 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11.2304 4.2561H10.0184L8.02638 7.9401H8.00238L5.99838 4.2561H4.78638L7.06638 8.2401H5.43438V8.9601H7.47438L7.48638 8.9841V9.8241H5.43438V10.5321H7.48638V12.5001H8.53038V10.5321H10.4984V9.8241H8.53038V8.9841L8.54238 8.9601H10.4984V8.2401H8.95038L11.2304 4.2561Z" fill="#333333"/>
</svg>

Before

Width:  |  Height:  |  Size: 392 B

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="16px" height="16px" viewBox="0 0 16 16" version="1.1">
<g id="surface1">
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(12.941176%,12.941176%,12.941176%);fill-opacity:1;" d="M 8 1.332031 C 11.683594 1.332031 14.667969 4.316406 14.667969 8 C 14.667969 11.683594 11.683594 14.667969 8 14.667969 C 4.316406 14.667969 1.332031 11.683594 1.332031 8 C 1.332031 4.316406 4.316406 1.332031 8 1.332031 Z M 8 2.332031 C 4.871094 2.332031 2.332031 4.871094 2.332031 8 C 2.332031 11.128906 4.871094 13.667969 8 13.667969 C 11.128906 13.667969 13.667969 11.128906 13.667969 8 C 13.667969 4.871094 11.128906 2.332031 8 2.332031 Z M 5.640625 9.855469 C 6.207031 10.574219 7.066406 11 8 11 C 8.929688 11 9.789062 10.574219 10.355469 9.859375 C 10.527344 9.640625 10.84375 9.605469 11.058594 9.777344 C 11.277344 9.949219 11.3125 10.261719 11.140625 10.476562 C 10.386719 11.433594 9.238281 12 8 12 C 6.757812 12 5.609375 11.429688 4.855469 10.476562 C 4.683594 10.257812 4.722656 9.945312 4.9375 9.773438 C 5.15625 9.601562 5.46875 9.640625 5.640625 9.855469 Z M 6 5.835938 C 6.460938 5.835938 6.832031 6.207031 6.832031 6.667969 C 6.832031 7.125 6.460938 7.5 6 7.5 C 5.539062 7.5 5.167969 7.125 5.167969 6.667969 C 5.167969 6.207031 5.539062 5.835938 6 5.835938 Z M 10 5.835938 C 10.460938 5.835938 10.832031 6.207031 10.832031 6.667969 C 10.832031 7.125 10.460938 7.5 10 7.5 C 9.539062 7.5 9.167969 7.125 9.167969 6.667969 C 9.167969 6.207031 9.539062 5.835938 10 5.835938 Z M 10 5.835938 "/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="16px" height="16px" viewBox="0 0 16 16" version="1.1">
<g id="surface1">
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(12.941176%,12.941176%,12.941176%);fill-opacity:1;" d="M 11.667969 8 C 13.691406 8 15.332031 9.640625 15.332031 11.667969 C 15.332031 13.691406 13.691406 15.332031 11.667969 15.332031 C 9.640625 15.332031 8 13.691406 8 11.667969 C 8 9.640625 9.640625 8 11.667969 8 Z M 8 1.332031 C 11.683594 1.332031 14.667969 4.316406 14.667969 8 C 14.667969 8.175781 14.660156 8.351562 14.648438 8.523438 C 14.355469 8.246094 14.023438 8.007812 13.664062 7.820312 C 13.570312 4.773438 11.070312 2.332031 8 2.332031 C 4.871094 2.332031 2.332031 4.871094 2.332031 8 C 2.332031 11.070312 4.773438 13.570312 7.820312 13.664062 C 8.007812 14.027344 8.246094 14.355469 8.523438 14.648438 C 8.351562 14.660156 8.175781 14.667969 8 14.667969 C 4.316406 14.667969 1.332031 11.683594 1.332031 8 C 1.332031 4.316406 4.316406 1.332031 8 1.332031 Z M 11.667969 9.332031 L 11.605469 9.339844 C 11.46875 9.363281 11.363281 9.46875 11.339844 9.605469 L 11.332031 9.667969 L 11.332031 11.332031 L 9.664062 11.332031 L 9.605469 11.339844 C 9.46875 11.363281 9.363281 11.46875 9.335938 11.605469 L 9.332031 11.667969 L 9.335938 11.726562 C 9.363281 11.863281 9.46875 11.96875 9.605469 11.996094 L 9.664062 12 L 11.332031 12 L 11.335938 13.667969 L 11.339844 13.730469 C 11.363281 13.863281 11.472656 13.972656 11.609375 13.996094 L 11.667969 14.003906 L 11.726562 13.996094 C 11.863281 13.972656 11.96875 13.863281 11.996094 13.730469 L 12 13.667969 L 12 12 L 13.667969 12 L 13.730469 11.996094 C 13.867188 11.96875 13.972656 11.863281 13.996094 11.726562 L 14.003906 11.667969 L 13.996094 11.605469 C 13.972656 11.46875 13.867188 11.363281 13.730469 11.339844 L 13.667969 11.332031 L 12 11.332031 L 12 9.667969 L 11.996094 9.605469 C 11.96875 9.46875 11.863281 9.363281 11.726562 9.339844 Z M 5.640625 9.855469 C 6.082031 10.414062 6.703125 10.796875 7.394531 10.941406 C 7.355469 11.175781 7.332031 11.417969 7.332031 11.667969 C 7.332031 11.761719 7.335938 11.855469 7.34375 11.945312 C 6.359375 11.785156 5.472656 11.261719 4.855469 10.476562 C 4.683594 10.257812 4.722656 9.945312 4.9375 9.773438 C 5.15625 9.601562 5.46875 9.640625 5.640625 9.855469 Z M 6 5.835938 C 6.460938 5.835938 6.832031 6.207031 6.832031 6.667969 C 6.832031 7.125 6.460938 7.5 6 7.5 C 5.539062 7.5 5.167969 7.125 5.167969 6.667969 C 5.167969 6.207031 5.539062 5.835938 6 5.835938 Z M 10 5.835938 C 10.460938 5.835938 10.832031 6.207031 10.832031 6.667969 C 10.832031 7.125 10.460938 7.5 10 7.5 C 9.539062 7.5 9.167969 7.125 9.167969 6.667969 C 9.167969 6.207031 9.539062 5.835938 10 5.835938 Z M 10 5.835938 "/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.8 KiB

@@ -0,0 +1,3 @@
<svg width="10" height="8" viewBox="0 0 10 8" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M1 5.2L2.84615 7L9 1" stroke="#00BCF0" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 198 B

@@ -0,0 +1,6 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M3 4.3999H4.11111H13" stroke="#333333" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M5.77775 4.4V3.2C5.77775 2.88174 5.89481 2.57652 6.10319 2.35147C6.31156 2.12643 6.59418 2 6.88886 2H9.11108C9.40577 2 9.68838 2.12643 9.89676 2.35147C10.1051 2.57652 10.2222 2.88174 10.2222 3.2V4.4M11.8889 4.4V12.8C11.8889 13.1183 11.7718 13.4235 11.5634 13.6485C11.3551 13.8736 11.0724 14 10.7778 14H5.2222C4.92751 14 4.64489 13.8736 4.43652 13.6485C4.22815 13.4235 4.11108 13.1183 4.11108 12.8V4.4H11.8889Z" stroke="#333333" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M6.88892 7.3999V10.9999" stroke="#333333" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M9.11108 7.3999V10.9999" stroke="#333333" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 886 B

@@ -0,0 +1,4 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="8" cy="6" r="1" fill="#333333"/>
<circle cx="8" cy="10" r="1" fill="#333333"/>
</svg>

After

Width:  |  Height:  |  Size: 194 B

@@ -0,0 +1,4 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11.9743 6.33301H7.35889C6.79245 6.33301 6.33325 6.7922 6.33325 7.35865V11.974C6.33325 12.5405 6.79245 12.9997 7.35889 12.9997H11.9743C12.5407 12.9997 12.9999 12.5405 12.9999 11.974V7.35865C12.9999 6.7922 12.5407 6.33301 11.9743 6.33301Z" stroke="#333333" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M4.53846 9.66667H4.02564C3.75362 9.66667 3.49275 9.55861 3.3004 9.36626C3.10806 9.17392 3 8.91304 3 8.64103V4.02564C3 3.75362 3.10806 3.49275 3.3004 3.3004C3.49275 3.10806 3.75362 3 4.02564 3H8.64103C8.91304 3 9.17392 3.10806 9.36626 3.3004C9.55861 3.49275 9.66667 3.75362 9.66667 4.02564V4.53846" stroke="#333333" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 790 B

@@ -0,0 +1,6 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M6 13H3V10" stroke="#00BCF0" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M10 3H13V6" stroke="#00BCF0" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M3 13L7 9" stroke="#00BCF0" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M13 3L9 7" stroke="#00BCF0" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 449 B

@@ -0,0 +1,4 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M6.5 8L8.11538 9.5L13.5 4.5" stroke="#333333" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M13 8.5V11.8889C13 12.1836 12.8829 12.4662 12.6746 12.6746C12.4662 12.8829 12.1836 13 11.8889 13H4.11111C3.81643 13 3.53381 12.8829 3.32544 12.6746C3.11706 12.4662 3 12.1836 3 11.8889V4.11111C3 3.81643 3.11706 3.53381 3.32544 3.32544C3.53381 3.11706 3.81643 3 4.11111 3H10.2222" stroke="#333333" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 561 B

@@ -0,0 +1,4 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M6.5 8L8.11538 9.5L13.5 4.5" stroke="#333333" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M13.5 8C13.5 11.0376 11.0376 13.5 8 13.5C4.96243 13.5 2.5 11.0376 2.5 8C2.5 4.96243 4.96243 2.5 8 2.5C8.81896 2.5 9.59612 2.679 10.2945 3" stroke="#333333" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 421 B

@@ -0,0 +1,6 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11.8889 3.5H4.11111C3.49746 3.5 3 3.94772 3 4.5V11.5C3 12.0523 3.49746 12.5 4.11111 12.5H11.8889C12.5025 12.5 13 12.0523 13 11.5V4.5C13 3.94772 12.5025 3.5 11.8889 3.5Z" stroke="#333333" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M10 2.5V4.58181" stroke="#333333" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M6 2.5V4.58181" stroke="#333333" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M3 6.5H13" stroke="#333333" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 618 B

@@ -0,0 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M10.9083 10.9011C10.4173 11.2751 9.83813 11.4814 9.09532 11.4814C7.93705 11.4814 6.82914 10.8367 6.45144 9.2765H10.027V8.50287H6.32554C6.31295 8.34814 6.31295 8.19341 6.31295 8.02579C6.31295 7.84527 6.32554 7.67765 6.33813 7.51003H10.027V6.73639H6.45144C6.81655 5.25358 7.82374 4.50573 9.09532 4.50573C9.72482 4.50573 10.304 4.69914 10.8201 5.06017L11.4371 4.24785C10.7194 3.73209 9.91367 3.5 9.09532 3.5C7.10612 3.5 5.72122 4.69914 5.31835 6.73639H4.5V7.51003H5.21763C5.20504 7.67765 5.20504 7.84527 5.20504 8.02579C5.20504 8.19341 5.20504 8.34814 5.21763 8.50287H4.5V9.2765H5.31835C5.7464 11.5716 7.40827 12.5 9.09532 12.5C10.0773 12.5 10.8705 12.1777 11.5 11.7264L10.9083 10.9011Z" fill="#333333"/>
</svg>

After

Width:  |  Height:  |  Size: 814 B

@@ -0,0 +1,8 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M6.5 4L12.5 4" stroke="#333333" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M6.5 8H12.5" stroke="#333333" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M6.5 12H12.5" stroke="#333333" stroke-linecap="round" stroke-linejoin="round"/>
<circle cx="4" cy="4" r="0.5" fill="#333333"/>
<circle cx="4" cy="8" r="0.5" fill="#333333"/>
<circle cx="4" cy="12" r="0.5" fill="#333333"/>
</svg>

After

Width:  |  Height:  |  Size: 512 B

@@ -0,0 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M2.201 6.4H3.001V12H2.081V7.384L0.953 7.704L0.729 6.92L2.201 6.4ZM3.91156 12V11.1L6.35156 8.61C6.9449 8.01667 7.24156 7.50333 7.24156 7.07C7.24156 6.73 7.13823 6.46667 6.93156 6.28C6.73156 6.08667 6.4749 5.99 6.16156 5.99C5.5749 5.99 5.14156 6.28 4.86156 6.86L3.89156 6.29C4.11156 5.82333 4.42156 5.47 4.82156 5.23C5.22156 4.99 5.6649 4.87 6.15156 4.87C6.7649 4.87 7.29156 5.06333 7.73156 5.45C8.17156 5.83667 8.39156 6.36333 8.39156 7.03C8.39156 7.74333 7.9949 8.50333 7.20156 9.31L5.62156 10.89H8.52156V12H3.91156ZM12.9025 7.032C13.5105 7.176 14.0025 7.46 14.3785 7.884C14.7625 8.3 14.9545 8.824 14.9545 9.456C14.9545 10.296 14.6705 10.956 14.1025 11.436C13.5345 11.916 12.8385 12.156 12.0145 12.156C11.3745 12.156 10.7985 12.008 10.2865 11.712C9.78253 11.416 9.41853 10.984 9.19453 10.416L10.3705 9.732C10.6185 10.452 11.1665 10.812 12.0145 10.812C12.4945 10.812 12.8745 10.692 13.1545 10.452C13.4345 10.204 13.5745 9.872 13.5745 9.456C13.5745 9.04 13.4345 8.712 13.1545 8.472C12.8745 8.232 12.4945 8.112 12.0145 8.112H11.7025L11.1505 7.284L12.9625 4.896H9.44653V3.6H14.6065V4.776L12.9025 7.032Z" fill="#333333"/>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

@@ -0,0 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M2.201 6.4H3.001V12H2.081V7.384L0.953 7.704L0.729 6.92L2.201 6.4ZM3.91156 12V11.1L6.35156 8.61C6.9449 8.01667 7.24156 7.50333 7.24156 7.07C7.24156 6.73 7.13823 6.46667 6.93156 6.28C6.73156 6.08667 6.4749 5.99 6.16156 5.99C5.5749 5.99 5.14156 6.28 4.86156 6.86L3.89156 6.29C4.11156 5.82333 4.42156 5.47 4.82156 5.23C5.22156 4.99 5.6649 4.87 6.15156 4.87C6.7649 4.87 7.29156 5.06333 7.73156 5.45C8.17156 5.83667 8.39156 6.36333 8.39156 7.03C8.39156 7.74333 7.9949 8.50333 7.20156 9.31L5.62156 10.89H8.52156V12H3.91156ZM12.9025 7.032C13.5105 7.176 14.0025 7.46 14.3785 7.884C14.7625 8.3 14.9545 8.824 14.9545 9.456C14.9545 10.296 14.6705 10.956 14.1025 11.436C13.5345 11.916 12.8385 12.156 12.0145 12.156C11.3745 12.156 10.7985 12.008 10.2865 11.712C9.78253 11.416 9.41853 10.984 9.19453 10.416L10.3705 9.732C10.6185 10.452 11.1665 10.812 12.0145 10.812C12.4945 10.812 12.8745 10.692 13.1545 10.452C13.4345 10.204 13.5745 9.872 13.5745 9.456C13.5745 9.04 13.4345 8.712 13.1545 8.472C12.8745 8.232 12.4945 8.112 12.0145 8.112H11.7025L11.1505 7.284L12.9625 4.896H9.44653V3.6H14.6065V4.776L12.9025 7.032Z" fill="#333333"/>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

@@ -0,0 +1,4 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M7.78787 8.78787L6.51213 7.51213C6.32314 7.32314 6.45699 7 6.72426 7H9.27574C9.54301 7 9.67686 7.32314 9.48787 7.51213L8.21213 8.78787C8.09497 8.90503 7.90503 8.90503 7.78787 8.78787Z" fill="#333333"/>
<path d="M8 13C10.7614 13 13 10.7614 13 8C13 5.23858 10.7614 3 8 3C5.23858 3 3 5.23858 3 8C3 10.7614 5.23858 13 8 13Z" stroke="#333333" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 499 B

@@ -0,0 +1,4 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M7.15625 11.8359L6.43768 9.85414H2.46662L1.74805 11.8359H0.5L3.7903 3H5.11399L8.4043 11.8359H7.15625ZM2.87003 8.75596H6.03427L4.44584 4.40112L2.87003 8.75596Z" fill="#333333"/>
<path d="M14.4032 5.52454H15.5V11.8359H14.4032V10.7504C13.8569 11.5835 13.0627 12 12.0206 12C11.1381 12 10.386 11.6802 9.76403 11.0407C9.14211 10.3927 8.83114 9.60589 8.83114 8.68022C8.83114 7.75456 9.14211 6.97195 9.76403 6.3324C10.386 5.68443 11.1381 5.36045 12.0206 5.36045C13.0627 5.36045 13.8569 5.777 14.4032 6.6101V5.52454ZM12.1593 10.9397C12.798 10.9397 13.3317 10.7251 13.7603 10.2959C14.1889 9.85835 14.4032 9.31978 14.4032 8.68022C14.4032 8.04067 14.1889 7.50631 13.7603 7.07714C13.3317 6.63955 12.798 6.42076 12.1593 6.42076C11.5289 6.42076 10.9995 6.63955 10.5708 7.07714C10.1422 7.50631 9.92791 8.04067 9.92791 8.68022C9.92791 9.31978 10.1422 9.85835 10.5708 10.2959C10.9995 10.7251 11.5289 10.9397 12.1593 10.9397Z" fill="#333333"/>
</svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

@@ -0,0 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M13 7.688L8.27223 12.1469C7.69304 12.6931 6.90749 13 6.0884 13C5.26931 13 4.48376 12.6931 3.90457 12.1469C3.32538 11.6006 3 10.8598 3 10.0873C3 9.31474 3.32538 8.57387 3.90457 8.02763L8.63234 3.56875C9.01847 3.20459 9.54216 3 10.0882 3C10.6343 3 11.158 3.20459 11.5441 3.56875C11.9302 3.93291 12.1472 4.42683 12.1472 4.94183C12.1472 5.45684 11.9302 5.95075 11.5441 6.31491L6.8112 10.7738C6.61814 10.9559 6.35629 11.0582 6.08326 11.0582C5.81022 11.0582 5.54838 10.9559 5.35531 10.7738C5.16225 10.5917 5.05379 10.3448 5.05379 10.0873C5.05379 9.82975 5.16225 9.58279 5.35531 9.40071L9.72297 5.28632" stroke="#333333" stroke-width="0.9989" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 797 B

@@ -0,0 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M10.716 9.828C10.716 8.292 9.6 7.896 8.124 7.416C7.128 7.092 6.396 6.828 6.396 6.072C6.396 5.376 6.984 4.968 7.824 4.968C8.412 4.968 9.216 5.22 9.84 5.676L10.44 4.944C9.9 4.512 9.096 4.176 8.352 4.056V2.508H7.572V4.008C6.12 4.092 5.304 4.98 5.304 6.132C5.304 7.56 6.516 7.98 7.824 8.388C8.928 8.748 9.612 9.036 9.612 9.9C9.612 10.644 8.964 11.088 8.076 11.088C7.308 11.088 6.444 10.752 5.772 10.092L5.136 10.836C5.844 11.532 6.684 11.904 7.572 12.012V13.476H8.352V12.024C9.84 11.928 10.716 11.052 10.716 9.828Z" fill="#333333"/>
</svg>

After

Width:  |  Height:  |  Size: 641 B

@@ -0,0 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11.2301 4.25586H10.0181L8.02613 7.93986H8.00213L5.99813 4.25586H4.78613L7.06613 8.23986H5.43413V8.95986H7.47413L7.48613 8.98386V9.82386H5.43413V10.5319H7.48613V12.4999H8.53013V10.5319H10.4981V9.82386H8.53013V8.98386L8.54213 8.95986H10.4981V8.23986H8.95013L11.2301 4.25586Z" fill="#333333"/>
</svg>

After

Width:  |  Height:  |  Size: 404 B

@@ -0,0 +1,4 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M5.12265 11.5847C5.92255 12.1165 6.88538 12.5 8.00024 12.5C10.4842 12.5 12.2135 10.596 13.0675 9.39083C13.6624 8.55146 13.6624 7.44854 13.0675 6.60917C12.7341 6.13867 12.2673 5.56168 11.6743 5.03305L10.9661 5.74127C11.4908 6.20089 11.9225 6.72296 12.2516 7.18736C12.601 7.68035 12.601 8.31965 12.2516 8.81264C11.4276 9.97552 9.9599 11.5 8.00024 11.5C7.19618 11.5 6.47495 11.2434 5.84702 10.8603L5.12265 11.5847ZM5.03441 10.2587L4.32618 10.967C3.73316 10.4383 3.26636 9.86133 2.93294 9.39083C2.33811 8.55146 2.33811 7.44854 2.93294 6.60917C3.78701 5.40397 5.51627 3.5 8.00024 3.5C9.1151 3.5 10.0779 3.88354 10.8778 4.4153L10.1535 5.13966C9.52554 4.75665 8.80431 4.5 8.00024 4.5C6.04059 4.5 4.57293 6.02448 3.74884 7.18736C3.39948 7.68035 3.39948 8.31965 3.74884 8.81264C4.07794 9.27704 4.50968 9.79911 5.03441 10.2587ZM6.99269 9.71466C7.28548 9.8954 7.62952 10 8.00036 10C9.09422 10 9.95491 9.08996 9.95491 8C9.95491 7.64165 9.86187 7.30275 9.69811 7.00924L8.93118 7.77618C8.94668 7.84779 8.95491 7.92265 8.95491 8C8.95491 8.5669 8.51315 9 8.00036 9C7.91225 9 7.82623 8.98721 7.7442 8.96316L6.99269 9.71466ZM7.06951 8.22363L6.30253 8.99061C6.13882 8.69713 6.04582 8.35829 6.04582 8C6.04582 6.91005 6.9065 6 8.00036 6C8.37114 6 8.71513 6.10456 9.00789 6.28525L8.25635 7.03679C8.17436 7.01277 8.08841 7 8.00036 7C7.48757 7 7.04582 7.4331 7.04582 8C7.04582 8.07728 7.05403 8.15208 7.06951 8.22363Z" fill="#333333"/>
<path d="M11.667 3.33398L3.33366 11.6673" stroke="#333333" stroke-linecap="round"/>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

@@ -0,0 +1,5 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M3 11.7778L3 4" stroke="#333333" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M9.5 4.5L6 8L9.5 11.5" stroke="#333333" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M6 8L13 8" stroke="#333333" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 378 B

@@ -0,0 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M9.39568 7.6963L6.91032 5.56599C6.65085 5.34358 6.25 5.52795 6.25 5.86969L6.25 10.1303C6.25 10.4721 6.65085 10.6564 6.91032 10.434L9.39568 8.3037C9.58192 8.14406 9.58192 7.85594 9.39568 7.6963Z" fill="#333333"/>
</svg>

After

Width:  |  Height:  |  Size: 324 B

@@ -0,0 +1,5 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M13 11.7778L13 4" stroke="#333333" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M6.5 4.5L10 8L6.5 11.5" stroke="#333333" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M10 8L3 8" stroke="#333333" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 381 B

@@ -0,0 +1,4 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M10.5221 3.21932C11.4366 2.6913 12.5634 2.6913 13.4779 3.21932L18.8653 6.32972C19.7799 6.85774 20.3433 7.83356 20.3433 8.88959V15.1104C20.3433 16.1664 19.7799 17.1423 18.8653 17.6703L13.4779 20.7807C12.5634 21.3087 11.4366 21.3087 10.5221 20.7807L5.13468 17.6703C4.22012 17.1423 3.65673 16.1664 3.65673 15.1104V8.88959C3.65673 7.83356 4.22012 6.85774 5.13467 6.32972L10.5221 3.21932Z" stroke="#333333" stroke-width="1.5"/>
<circle cx="12" cy="12" r="3.75" stroke="#333333" stroke-width="1.5"/>
</svg>

After

Width:  |  Height:  |  Size: 606 B

@@ -0,0 +1,4 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="2.5" y="3" width="4" height="10" rx="1" stroke="#333333"/>
<rect x="9.5" y="7" width="4" height="6" rx="1" stroke="#333333"/>
</svg>

After

Width:  |  Height:  |  Size: 238 B

@@ -0,0 +1,145 @@
{
"appName": "AppFlowy",
"defaultUsername": "Jo",
"welcomeText": "Benvingut a @:appName",
"githubStarText": "Preferit a Github",
"subscribeNewsletterText": "Subscriu-me al butlletí",
"letsGoButtonText": "Endavant",
"title": "Títol",
"signUp": {
"buttonText": "Registra't",
"title": "Registra't a @:appName",
"getStartedText": "Comencem",
"emptyPasswordError": "La contrasenya no pot ser buida",
"repeatPasswordEmptyError": "La contrasenya repetida no pot ser buida",
"unmatchedPasswordError": "Les contrasenyes no concorden",
"alreadyHaveAnAccount": "Ja tens un compte?",
"emailHint": "Correu electrònic",
"passwordHint": "Contrasenya",
"repeatPasswordHint": "Repeteix la contrasenya"
},
"signIn": {
"loginTitle": "Inicia sessió a @:appName",
"loginButtonText": "Inicia sessió",
"buttonText": "Inicia sessió",
"forgotPassword": "Has oblidat la contrasenya?",
"emailHint": "Correu electrònic",
"passwordHint": "Contrasenya",
"dontHaveAnAccount": "No tens un compte?",
"repeatPasswordEmptyError": "La contrasenya repetida no pot ser buida",
"unmatchedPasswordError": "Les contrasenyes no concorden"
},
"workspace": {
"create": "Crear un espai de treball",
"hint": "espai de treball",
"notFoundError": "No s'ha trobat l'espai de treball"
},
"shareAction": {
"buttonText": "Compartir",
"workInProgress": "Pròximament",
"markdown": "Markdown",
"copyLink": "Copiar l'enllaç"
},
"disclosureAction": {
"rename": "Canviar el nom",
"delete": "Eliminar",
"duplicate": "Duplicar"
},
"blankPageTitle": "Pàgina en blanc",
"newPageText": "Nova pàgina",
"trash": {
"text": "Paperera",
"restoreAll": "Recuperar-ho tot",
"deleteAll": "Eliminar-ho tot",
"pageHeader": {
"fileName": "Nom del fitxer",
"lastModified": "Última modificació",
"created": "Creat"
}
},
"deletePagePrompt": {
"text": "Aquest pàgina es troba a la paperera",
"restore": "Recuperar-la",
"deletePermanent": "Elimina-la"
},
"dialogCreatePageNameHint": "Nom de la pàgina",
"questionBubble": {
"whatsNew": "Què hi ha de nou?",
"help": "Ajuda i Suport",
"debug": {
"name": "Informació de depuració",
"success": "S'ha copiat la informació de depuració!",
"fail": "No es pot copiar la informació de depuració"
}
},
"menuAppHeader": {
"addPageTooltip": "Afegeix ràpidament una pàgina dins",
"defaultNewPageName": "Sense títol",
"renameDialog": "Canviar el nom"
},
"toolbar": {
"undo": "Desfer",
"redo": "Refer",
"bold": "Negreta",
"italic": "Cursiva",
"underline": "Text subratllar",
"strike": "Ratllat",
"numList": "Llista numerada",
"bulletList": "Llista de punts",
"checkList": "Llista de comprovació",
"inlineCode": "Inserir codi",
"quote": "Bloc citat",
"header": "Capçalera",
"highlight": "Subratllar"
},
"tooltip": {
"lightMode": "Canviar a mode clar",
"darkMode": "Canviar a mode fosc"
},
"contactsPage": {
"title": "Contactes",
"whatsHappening": "Que passa aquesta setmana?",
"addContact": "Afegir un contacte",
"editContact": "Editar un contacte"
},
"button": {
"OK": "OK",
"Cancel": "Cancel·lar",
"signIn": "Iniciar sessió",
"signOut": "Tancar sessió",
"complete": "Completar",
"save": "Guardar"
},
"label": {
"welcome": "Benvingut!",
"firstName": "Nom",
"middleName": "Segon Nom",
"lastName": "Cognom",
"stepX": "Pas {X}"
},
"oAuth": {
"err": {
"failedTitle": "No s'ha pogut connectar al teu compte.",
"failedMsg": "Assegureu-vos que heu completat el procés d'inici de sessió al vostre navegador."
},
"google": {
"title": "Iniciar sessió amb Google",
"instruction1": "Per importar els vostres contactes de Google, haureu d'autoritzar aquesta aplicació mitjançant el vostre navegador web.",
"instruction2": "Copia aquest codi clicant la icona o seleccionant el text:",
"instruction3": "Navega al següent enllaç amb el teu navegador i insereix el codi anterior:",
"instruction4": "Pressiona el botó d'avall una vegada hagis completat el registre:"
}
},
"settings": {
"title": "Configuració",
"menu": {
"appearance": "Aparença",
"language": "Idioma",
"open": "Obrir la configuració"
},
"appearance": {
"lightLabel": "Mode Clar",
"darkLabel": "Mode Fosc"
}
}
}
@@ -0,0 +1,146 @@
{
"appName": "AppFlowy",
"defaultUsername": "Ich",
"welcomeText": "Willkommen bei @:appName",
"githubStarText": "GitHub Star vergeben",
"subscribeNewsletterText": "Abonniere den Newsletter",
"letsGoButtonText": "Los geht's",
"title": "Titel",
"signUp": {
"buttonText": "Registrieren",
"title": "Registriere dich bei @:appName",
"getStartedText": "Erste Schritte",
"emptyPasswordError": "Passwort darf nicht leer sein",
"repeatPasswordEmptyError": "Passwortwiederholung darf nicht leer sein",
"unmatchedPasswordError": "Passwörter stimmen nicht überein",
"alreadyHaveAnAccount": "Bereits registriert?",
"emailHint": "E-Mail",
"passwordHint": "Passwort",
"repeatPasswordHint": "Wiederhole Passwort"
},
"signIn": {
"loginTitle": "Bei @:appName einloggen",
"loginButtonText": "Anmelden",
"buttonText": "Anmelden",
"forgotPassword": "Passwort vergessen?",
"emailHint": "E-Mail",
"passwordHint": "Passwort",
"dontHaveAnAccount": "Du besitzt noch kein Konto?",
"repeatPasswordEmptyError": "Passwortwiederholung darf nicht leer sein",
"unmatchedPasswordError": "Passwörter stimmen nicht überein"
},
"workspace": {
"create": "Arbeitsbereich erstellen",
"hint": "Arbeitsbereich",
"notFoundError": "Arbeitsbereich nicht gefunden"
},
"shareAction": {
"buttonText": "Teilen",
"workInProgress": "Demnächst verfügbar",
"markdown": "Markdown",
"copyLink": "Link kopieren"
},
"disclosureAction": {
"rename": "Umbenennen",
"delete": "Löschen",
"duplicate": "Duplizieren"
},
"blankPageTitle": "Leere Seite",
"newPageText": "Neue Seite",
"trash": {
"text": "Papierkorb",
"restoreAll": "Alles wiederherstellen",
"deleteAll": "Alles löschen",
"pageHeader": {
"fileName": "Dateiname",
"lastModified": "Letzte Änderung",
"created": "Erstellt"
}
},
"deletePagePrompt": {
"text": "Diese Seite ist im Papierkorb",
"restore": "Seite wiederherstellen",
"deletePermanent": "Dauerhaft löschen"
},
"dialogCreatePageNameHint": "Seitenname",
"questionBubble": {
"whatsNew": "Was gibt es Neues?",
"help": "Hilfe & Support",
"debug": {
"name": "Debug-Informationen",
"success": "Debug-Informationen in die Zwischenablage kopiert!",
"fail": "Debug-Informationen können nicht in die Zwischenablage kopiert werden"
}
},
"menuAppHeader": {
"addPageTooltip": "Schnell eine Seite innerhalb hinzufügen",
"defaultNewPageName": "Unbenannt",
"renameDialog": "Umbenennen"
},
"toolbar": {
"undo": "Rückgängig",
"redo": "Wiederherstellen",
"bold": "Fett",
"italic": "Kursiv",
"underline": "Unterstreichen",
"strike": "Durchstreichen",
"numList": "Nummerierte Liste",
"bulletList": "Aufzählung",
"checkList": "Checkliste",
"inlineCode": "Inline-Code",
"quote": "Zitat",
"header": "Überschrift",
"highlight": "Hervorhebung"
},
"tooltip": {
"lightMode": "In den hellen Modus wechseln",
"darkMode": "In den dunklen Modus wechseln"
},
"contactsPage": {
"title": "Kontakte",
"whatsHappening": "Was geschieht diese Woche?",
"addContact": "Kontakt hinzufügen",
"editContact": "Kontakt bearbeiten"
},
"button": {
"OK": "OK",
"Cancel": "Abbrechen",
"signIn": "Anmelden",
"signOut": "Abmelden",
"complete": "Fertig",
"save": "Speichern"
},
"label": {
"welcome": "Willkommen!",
"firstName": "Vorname",
"middleName": "Zweiter Vorname",
"lastName": "Nachname",
"stepX": "Schritt {X}"
},
"oAuth": {
"err": {
"failedTitle": "Keine Verbindung zu Ihrem Konto möglich.",
"failedMsg": "Bitte vergewissern Sie sich, dass Sie den Anmeldevorgang in Ihrem Browser abgeschlossen haben."
},
"google": {
"title": "GOOGLE ANMELDUNG",
"instruction1": "Um Ihre Google-Kontakte zu importieren, müssen Sie diese Anwendung über Ihren Webbrowser autorisieren.",
"instruction2": "Kopieren Sie diesen Code in Ihre Zwischenablage, indem Sie auf das Symbol klicken oder den Text auswählen:",
"instruction3": "Rufen Sie den folgenden Link in Ihrem Webbrowser auf, und geben Sie den obigen Code ein:",
"instruction4": "Klicken Sie unten auf die Schaltfläche, wenn Sie die Anmeldung abgeschlossen haben:"
}
},
"settings": {
"title": "Einstellungen",
"menu": {
"appearance": "Aussehen",
"language": "Sprache",
"open": "Einstellungen öffnen"
},
"appearance": {
"lightLabel": "Heller Modus",
"darkLabel": "Dunkler Modus"
}
}
}
@@ -141,5 +141,67 @@
"lightLabel": "Light Mode",
"darkLabel": "Dark Mode"
}
},
"grid": {
"settings": {
"filter": "Filter",
"sortBy": "Sort by",
"Properties": "Properties"
},
"field": {
"hide": "Hide",
"insertLeft": "Insert Left",
"insertRight": "Insert Right",
"duplicate": "Duplicate",
"delete": "Delete",
"textFieldName": "Text",
"checkboxFieldName": "Checkbox",
"dateFieldName": "Date",
"numberFieldName": "Numbers",
"singleSelectFieldName": "Select",
"multiSelectFieldName": "Multiselect",
"urlFieldName": "URL",
"numberFormat": " Number format",
"dateFormat": " Date format",
"includeTime": " Include time",
"dateFormatFriendly": "Month Day,Year",
"dateFormatISO": "Year-Month-Day",
"dateFormatLocal": "Month/Month/Day",
"dateFormatUS": "Month/Month/Day",
"timeFormat": " Time format",
"invalidTimeFormat": "Invalid format",
"timeFormatTwelveHour": "12 hour",
"timeFormatTwentyFourHour": "24 hour",
"addSelectOption": "Add an option",
"optionTitle": "Options",
"addOption": "Add option",
"editProperty": "Edit property"
},
"row": {
"duplicate": "Duplicate",
"delete": "Delete",
"textPlaceholder": "Empty",
"copyProperty": "Copied property to clipboard"
},
"selectOption": {
"create": "Create",
"purpleColor": "Purple",
"pinkColor": "Pink",
"lightPinkColor": "Light Pink",
"orangeColor": "Orange",
"yellowColor": "Yellow",
"limeColor": "Lime",
"greenColor": "Green",
"aquaColor": "Aqua",
"blueColor": "Blue",
"deleteTag": "Delete tag",
"colorPannelTitle": "Colors",
"pannelTitle": "Select an option or create one",
"searchOption": "Search for an option"
},
"date": {
"timeHintTextInTwelveHour": "12:00 AM",
"timeHintTextInTwentyFourHour": "12:00"
}
}
}
@@ -1,75 +1,75 @@
{
"appName": "AppFlowy",
"defaultUsername": "Moi",
"welcomeText": "Bienvenu à @:appName",
"githubStarText": "Favorier sur GitHub",
"welcomeText": "Bienvenue sur @:appName",
"githubStarText": "Favoriser sur GitHub",
"subscribeNewsletterText": "Abonnez-vous à notre courriel",
"letsGoButtonText": "Allons-y",
"title": "Titre",
"signUp": {
"buttonText": "S'abonner",
"title": "S'abonner à @:appName",
"buttonText": "S'inscrire",
"title": "S'inscrire à @:appName",
"getStartedText": "Commencer",
"emptyPasswordError": "Mot de passe ne doit pas être vide",
"emptyPasswordError": "Vous n'avez pas saisi votre mot de passe",
"repeatPasswordEmptyError": "Mot de passe ne doit pas être vide",
"unmatchedPasswordError": "Les mots de pass ne concordent pas",
"unmatchedPasswordError": "Les deux mots de passe ne sont pas identiques",
"alreadyHaveAnAccount": "Avez-vous déjà un compte?",
"emailHint": "courriel",
"passwordHint": "Mot de passe",
"repeatPasswordHint": "Resaisir le mot de passe"
"repeatPasswordHint": "Ressaisir votre mot de passe"
},
"signIn": {
"loginTitle": "Se connecter à @:appName",
"loginTitle": "Connexion à @:appName",
"loginButtonText": "Connexion",
"buttonText": "Connexion",
"buttonText": "Se connecter",
"forgotPassword": "Mot de passe oublié?",
"emailHint": "courriel",
"passwordHint": "Mot de passe",
"dontHaveAnAccount": "Vous n'avez pas de compte?",
"repeatPasswordEmptyError": "Mot de passe ne doit pas être vide",
"unmatchedPasswordError": "Les mots de passe ne concordent pas"
"unmatchedPasswordError": "Les deux mots de passe ne sont pas identiques"
},
"workspace": {
"create": "Créer une espace de travail",
"hint": "espace de travail",
"notFoundError": "Espace de travail non trouvé"
"create": "Créer un espace de travail",
"hint": "Espace de travail",
"notFoundError": "Espace de travail introuvable"
},
"shareAction": {
"buttonText": "Partager",
"workInProgress": "Bientôt disponible",
"markdown": "Markdown",
"copyLink": "Copier le liens"
"copyLink": "Copier le lien"
},
"disclosureAction": {
"rename": "Renommer",
"delete": "Supprimer",
"duplicate": "Dupliquer"
},
"blankPageTitle": "Page vide",
"blankPageTitle": "Page vierge",
"newPageText": "Nouvelle page",
"trash": {
"text": "Poubelle",
"text": "Corbeille",
"restoreAll": "Tout récupérer",
"deleteAll": "Tout supprimer",
"pageHeader": {
"fileName": "Nom de fichier",
"lastModified": "Dernière modification",
"created": "Crée"
"created": "Créé"
}
},
"deletePagePrompt": {
"text": "Cette page est dans la poubelle",
"text": "Cette page est dans la corbeille",
"restore": "Récupérer la page",
"deletePermanent": "Supprimer en permanence"
"deletePermanent": "Supprimer définitivement"
},
"dialogCreatePageNameHint": "Nom de la page",
"questionBubble": {
"whatsNew": "Quoi de neuf?",
"help": "Aide & Support Technique",
"whatsNew": "Nouveautés",
"help": "Aide et Support Technique",
"debug": {
"name": "Info du système",
"name": "Infos du système",
"success": "Info copié!",
"fail": "Incapable de copié l'info"
"fail": "Impossible de copier l'info"
}
},
"menuAppHeader": {
@@ -79,67 +79,67 @@
},
"toolbar": {
"undo": "Annuler",
"redo": "Refaire",
"redo": "Rétablir",
"bold": "Gras",
"italic": "Italique",
"underline": "Souligné",
"underline": "Souligner",
"strike": "Barré",
"numList": "Liste numérotée",
"bulletList": "Liste à puces",
"checkList": "Liste de contrôle",
"inlineCode": "Code en ligne",
"quote": "Citation",
"header": "en-tête",
"header": "En-tête",
"highlight": "Surligner"
},
"tooltip": {
"lightMode": "Aller en mode claire",
"darkMode": "Aller en mode foncé"
"lightMode": "Passer en mode clair",
"darkMode": "Passer en mode sombre"
},
"contactsPage": {
"title": "Contacts",
"whatsHappening": "Quoi de neuf?",
"addContact": "Ajouter Contact",
"editContact": "Éditer Contact"
"addContact": "Ajouter un contact",
"editContact": "Modifier le contact"
},
"button": {
"OK": "OK",
"Cancel": "Annuler",
"signIn": "Connecter",
"signOut": "Déconnecter",
"complete": "Complêt",
"signIn": "Se connecter",
"signOut": "Se déconnecter",
"complete": "Achevé",
"save": "Sauvegarder"
},
"label": {
"welcome": "Bienvenu!",
"welcome": "Bienvenue!",
"firstName": "Prénom",
"middleName": "Nom",
"middleName": "Deuxième nom",
"lastName": "Nom de famille",
"stepX": "Étape {X}"
},
"oAuth": {
"err": {
"failedTitle": "Incapable de connecter à votre compte.",
"failedTitle": "Incapable de se connecter à votre compte.",
"failedMsg": "SVP vous assurrez d'avoir complèté le processus d'enregistrement dans votre fureteur."
},
"google": {
"title": "S'identifier avec Google",
"instruction1": "Pour importer vos contacts Google, vous devez autoriser cette application à l'aide de votre navigateur Web.",
"instruction2": "Copiez ce code dans votre presse-papiers en cliquant sur l'icône ou en sélectionnant le texte :",
"instruction3": "Accédez au lien suivant dans votre navigateur Web et saisissez le code ci-dessus :",
"instruction4": "Appuyez sur le bouton ci-dessous lorsque vous avez terminé votre inscription :"
"instruction2": "Copiez ce code dans votre presse-papiers en cliquant sur l'icône ou en sélectionnant le texte:",
"instruction3": "Accédez au lien suivant dans votre navigateur Web et saisissez le code ci-dessus:",
"instruction4": "Appuyez sur le bouton ci-dessous lorsque vous avez terminé votre inscription:"
}
},
"settings": {
"title": "Réglages",
"title": "Paramètres",
"menu": {
"appearance": "Apparence",
"language": "Langue",
"open": "ouvrir les paramètres"
"open": "Ouvrir les paramètres"
},
"appearance": {
"lightLabel": "Mode claire",
"darkLabel": "Mode foncé"
"lightLabel": "Mode clair",
"darkLabel": "Mode sombre"
}
}
}
@@ -0,0 +1,145 @@
{
"appName": "AppFlowy",
"defaultUsername": "Moi",
"welcomeText": "Bienvenue sur @:appName",
"githubStarText": "Favoriser sur GitHub",
"subscribeNewsletterText": "S'inscrire à la Newsletter",
"letsGoButtonText": "Allons-y",
"title": "Titre",
"signUp": {
"buttonText": "S'inscrire",
"title": "Inscrivez-vous sur @:appName",
"getStartedText": "Commencer",
"emptyPasswordError": "Vous n'avez pas saisi votre mot de passe",
"repeatPasswordEmptyError": "Vous n'avez pas ressaisi votre mot de passe",
"unmatchedPasswordError": "Les deux mots de passe ne sont pas identiques",
"alreadyHaveAnAccount": "Avez-vous déjà un compte ?",
"emailHint": "Email",
"passwordHint": "Mot de passe",
"repeatPasswordHint": "Ressaisir votre mot de passe"
},
"signIn": {
"loginTitle": "Connexion à @:appName",
"loginButtonText": "Connexion",
"buttonText": "Se connecter",
"forgotPassword": "Mot de passe oublié ?",
"emailHint": "Email",
"passwordHint": "Mot de passe",
"dontHaveAnAccount": "Vous n'avez pas encore créé votre compte ?",
"repeatPasswordEmptyError": "Vous n'avez pas ressaisi votre mot de passe",
"unmatchedPasswordError": "Les deux mots de passe ne sont pas identiques"
},
"workspace": {
"create": "Créer un espace de travail",
"hint": "Espace de travail",
"notFoundError": "Espace de travail introuvable"
},
"shareAction": {
"buttonText": "Partager",
"workInProgress": "Bientôt disponible",
"markdown": "Markdown",
"copyLink": "Copier le lien"
},
"disclosureAction": {
"rename": "Renommer",
"delete": "Supprimer",
"duplicate": "Dupliquer"
},
"blankPageTitle": "Page vierge",
"newPageText": "Nouvelle page",
"trash": {
"text": "Corbeille",
"restoreAll": "Restaurer tout",
"deleteAll": "Supprimer tout",
"pageHeader": {
"fileName": "Nom de fichier",
"lastModified": "Dernière modification",
"created": "Créé"
}
},
"deletePagePrompt": {
"text": "Cette page a été supprimée, vous pouvez la retrouver dans la corbeille",
"restore": "Restaurer la page",
"deletePermanent": "Supprimer définitivement"
},
"dialogCreatePageNameHint": "Nom de la page",
"questionBubble": {
"whatsNew": "Nouveautés",
"help": "Aide et Support",
"debug": {
"name": "Informations de Débogage",
"success": "Informations de Débogage copiées dans le presse-papiers!",
"fail": "Impossible de copier les informations de Débogage dans le presse-papiers"
}
},
"menuAppHeader": {
"addPageTooltip": "Ajoutez rapidement une page à l'intérieur",
"defaultNewPageName": "Sans-titre",
"renameDialog": "Renommer"
},
"toolbar": {
"undo": "Annuler",
"redo": "Rétablir",
"bold": "Gras",
"italic": "Italique",
"underline": "Souligner",
"strike": "Barré",
"numList": "Liste numérotée",
"bulletList": "Liste à puces",
"checkList": "To-Do List",
"inlineCode": "Code",
"quote": "Bloc de citation",
"header": "En-tête",
"highlight": "Surligner"
},
"tooltip": {
"lightMode": "Passer en mode clair",
"darkMode": "Passer en mode sombre"
},
"contactsPage": {
"title": "Contacts",
"whatsHappening": "Que se passe-t-il cette semaine ?",
"addContact": "Ajouter un contact",
"editContact": "Modifier le contact"
},
"button": {
"OK": "OK",
"Cancel": "Annuler",
"signIn": "Se connecter",
"signOut": "Se déconnecter",
"complete": "Achevé",
"save": "Enregistrer"
},
"label": {
"welcome": "Bienvenue !",
"firstName": "Prénom",
"middleName": "Deuxième prénom",
"lastName": "Nom",
"stepX": "Étape {X}"
},
"oAuth": {
"err": {
"failedTitle": "Impossible de se connecter à votre compte.",
"failedMsg": "Assurez-vous d'avoir terminé le processus de connexion dans votre navigateur."
},
"google": {
"title": "CONNEXION GOOGLE",
"instruction1": "Pour importer vos contacts Google, vous devez autoriser cette application à l'aide de votre navigateur web.",
"instruction2": "Copiez ce code dans votre presse-papiers en cliquant sur l'icône ou en sélectionnant le texte:",
"instruction3": "Accédez au lien suivant dans votre navigateur web et saisissez le code ci-dessus:",
"instruction4": "Appuyez sur le bouton ci-dessous lorsque vous avez terminé votre inscription:"
}
},
"settings": {
"title": "Paramètres",
"menu": {
"appearance": "Apparence",
"language": "Langue",
"open": "Ouvrir les paramètres"
},
"appearance": {
"lightLabel": "Mode clair",
"darkLabel": "Mode sombre"
}
}
}
@@ -0,0 +1,145 @@
{
"appName": "AppFlowy",
"defaultUsername": "Én",
"welcomeText": "Üdvözöl az @:appName",
"githubStarText": "GitHub csillagozás",
"subscribeNewsletterText": "Iratkozz fel a hírlevelünkre",
"letsGoButtonText": "Vágjunk bele",
"title": "Cím",
"signUp": {
"buttonText": "Regisztráció",
"title": "Regisztrálj az @:appName -ra",
"getStartedText": "Kezdés",
"emptyPasswordError": "A jelszó nem lehet üres",
"repeatPasswordEmptyError": "A jelszó megerősítése nem lehet üres",
"unmatchedPasswordError": "A jelszavak nem egyeznek",
"alreadyHaveAnAccount": "Rendelkezel már fiókkal?",
"emailHint": "Email",
"passwordHint": "Jelszó",
"repeatPasswordHint": "Jelszó megerősítése"
},
"signIn": {
"loginTitle": "Bejelentkezés az @:appName -ba",
"loginButtonText": "Belépés",
"buttonText": "Bejelentkezés",
"forgotPassword": "Elfelejtett jelszó?",
"emailHint": "Email",
"passwordHint": "Jelszó",
"dontHaveAnAccount": "Még nincs fiókod?",
"repeatPasswordEmptyError": "A jelszó megerősítése nem lehet üres",
"unmatchedPasswordError": "A jelszavak nem egyeznek"
},
"workspace": {
"create": "Új munkaterület létrehozása",
"hint": "munkaterület",
"notFoundError": "munkaterület nem található"
},
"shareAction": {
"buttonText": "Megosztás",
"workInProgress": "Hamarosan érkezik...",
"markdown": "Markdown",
"copyLink": "Link másolása"
},
"disclosureAction": {
"rename": "Átnevezés",
"delete": "Törlés",
"duplicate": "Duplikálás"
},
"blankPageTitle": "Üres oldal",
"newPageText": "Új oldal",
"trash": {
"text": "Kuka",
"restoreAll": "Összes visszaállítása",
"deleteAll": "Összes törlése",
"pageHeader": {
"fileName": "Fájlnév",
"lastModified": "Utoljára módosítva",
"created": "Létrehozva"
}
},
"deletePagePrompt": {
"text": "Ez az oldal a kukában van",
"restore": "Oldal visszaállítása",
"deletePermanent": "Végleges törlés"
},
"dialogCreatePageNameHint": "Oldalnév",
"questionBubble": {
"whatsNew": "Újdonságok",
"help": "Segítség & Támogatás",
"debug": {
"name": "Debug Információ",
"success": "Debug információ a vágólapra másolva",
"fail": "A Debug információ nem másolható a vágólapra"
}
},
"menuAppHeader": {
"addPageTooltip": "Belső oldal hozzáadása",
"defaultNewPageName": "Névtelen",
"renameDialog": "Átnevezés"
},
"toolbar": {
"undo": "Vissza",
"redo": "Előre",
"bold": "Félkövér",
"italic": "Dőlt",
"underline": "Aláhúzott",
"strike": "Áthúzott",
"numList": "Számozott lista",
"bulletList": "Felsorolás",
"checkList": "Ellenőrző lista",
"inlineCode": "Inline kód",
"quote": "Idézet",
"header": "Címsor",
"highlight": "Kiemelés"
},
"tooltip": {
"lightMode": "Világos mód",
"darkMode": "Éjjeli mód"
},
"contactsPage": {
"title": "Kontaktok",
"whatsHappening": "Heti újdonságok",
"addContact": "Új Kontakt",
"editContact": "Kontakt Szerkesztése"
},
"button": {
"OK": "OK",
"Cancel": "Mégse",
"signIn": "Bejelentkezés",
"signOut": "Kijelentkezés",
"complete": "Kész",
"save": "Mentés"
},
"label": {
"welcome": "Üdvözlünk!",
"firstName": "Keresztnév",
"middleName": "Középső név",
"lastName": "Vezetéknév",
"stepX": "{X}. lépés"
},
"oAuth": {
"err": {
"failedTitle": "Sikertelen bejelentkezés.",
"failedMsg": "Kérjük győződj meg róla, hogy elvégezted a bejelentkezési folyamatot a böngésződben"
},
"google": {
"title": "Bejelentkezés Google-al",
"instruction1": "Ahhoz, hogy hozzáférj a Google Kontaktjaidhoz, kérjük hatalmazd fel ezt az alkalmazást a böngésződben.",
"instruction2": "Másold ezt a kódot a vágólapra az ikonra kattintással vagy a szöveg kijelölésével:",
"instruction3": "Nyisd meg ezt a linket a böngésződben, és írjd be a fenti kódot:",
"instruction4": "Nyomd meg az alábbi gombot, ha elvégezted a registrációt:"
}
},
"settings": {
"title": "Beállítások",
"menu": {
"appearance": "Megjelenés",
"language": "Nyelv",
"open": "Beállítások megnyitása"
},
"appearance": {
"lightLabel": "Világos mód",
"darkLabel": "Éjjeli mód"
}
}
}
@@ -0,0 +1,146 @@
{
"appName": "AppFlowy",
"defaultUsername": "Me",
"welcomeText": "Bem vindo @:appName",
"githubStarText": "Star on GitHub",
"subscribeNewsletterText": "Se inscreva na Newsletter",
"letsGoButtonText": "Vamos lá",
"title": "Título",
"signUp": {
"buttonText": "Inscreve-se",
"title": "Inscrever-se @:appName",
"getStartedText": "Começar",
"emptyPasswordError": "Senha não pode ser em branco.",
"repeatPasswordEmptyError": "Confirmar a senha não pode ser em branco.",
"unmatchedPasswordError": "As senhas não conferem.",
"alreadyHaveAnAccount": "Já possui uma conta?",
"emailHint": "Email",
"passwordHint": "Senha",
"repeatPasswordHint": "Confirme a senha"
},
"signIn": {
"loginTitle": "Login to @:appName",
"loginButtonText": "Login",
"buttonText": "Entre",
"forgotPassword": "Esqueceu a senha?",
"emailHint": "Email",
"passwordHint": "Senha",
"dontHaveAnAccount": "Não possui uma conta?",
"repeatPasswordEmptyError": "Confirmar a senha não pode ser em branco.",
"unmatchedPasswordError": "As senhas não conferem."
},
"workspace": {
"create": "Crie uma área de trabalho",
"hint": "área de trabalho",
"notFoundError": "Área de trabalho não encontrada"
},
"shareAction": {
"buttonText": "Compartilhar",
"workInProgress": "Em breve",
"markdown": "Markdown",
"copyLink": "Copiar o link"
},
"disclosureAction": {
"rename": "Renomear",
"delete": "Deletar",
"duplicate": "Duplicar"
},
"blankPageTitle": "Página em branco",
"newPageText": "Nova página",
"trash": {
"text": "Lixeira",
"restoreAll": "Restaurar todos",
"deleteAll": "Deletar todos",
"pageHeader": {
"fileName": "Nome do arquivo",
"lastModified": "Última modificação",
"created": "Criado"
}
},
"deletePagePrompt": {
"text": "Está página está na lixeira",
"restore": "Restaurar a oágina",
"deletePermanent": "Deletar permanentemente"
},
"dialogCreatePageNameHint": "Nome da página",
"questionBubble": {
"whatsNew": "O que há de novo?",
"help": "Ajuda & Suporte",
"debug": {
"name": "Informação de debug",
"success": "Copiar informação de debug para o clipboard!",
"fail": "Falha em copiar a informação de debug para o clipboard"
}
},
"menuAppHeader": {
"addPageTooltip": "Adicione uma nova página.",
"defaultNewPageName": "Sem título",
"renameDialog": "Renomear"
},
"toolbar": {
"undo": "Desfazer",
"redo": "Refazer",
"bold": "Negrito",
"italic": "Itálico",
"underline": "Sublinhado",
"strike": "Tachado",
"numList": "Lista numerada",
"bulletList": "Lista com marcadores",
"checkList": "Check List",
"inlineCode": "Embutir código",
"quote": "Citação em bloco",
"header": "Cabeçalho",
"highlight": "Realçar"
},
"tooltip": {
"lightMode": "Mudar para o modo Claro.",
"darkMode": "Mudar para o modo Escuro."
},
"contactsPage": {
"title": "Contatos",
"whatsHappening": "O que está acontecendo essa semana?",
"addContact": "Adicionar um contato",
"editContact": "Editar um contato"
},
"button": {
"OK": "OK",
"Cancel": "Canelar",
"signIn": "Entrar",
"signOut": "Sair",
"complete": "Completar",
"save": "Salvar"
},
"label": {
"welcome": "Bem vindo!",
"firstName": "Primeiro Nome",
"middleName": "Nome do Meio",
"lastName": "Último Nome",
"stepX": "Passo {X}"
},
"oAuth": {
"err": {
"failedTitle": "Erro ao conectar a sua conta.",
"failedMsg": "Verifique se você concluiu o processo de login em seu navegador."
},
"google": {
"title": "GOOGLE SIGN-IN",
"instruction1": "Para importar seus Contatos do Google, você precisará autorizar este aplicativo usando seu navegador web.",
"instruction2": "Copie este código para sua área de transferência clicando no ícone ou selecionando o texto:",
"instruction3": "Navegue até o link a seguir em seu navegador e digite o código acima:",
"instruction4": "Pressione o botão abaixo ao concluir a inscrição:"
}
},
"settings": {
"title": "Configurações",
"menu": {
"appearance": "Aparência",
"language": "Idioma",
"open": "Abrir as Configurações"
},
"appearance": {
"lightLabel": "Modo Claro",
"darkLabel": "Modo Escuro"
}
}
}
@@ -0,0 +1,145 @@
{
"appName": "AppFlowy",
"defaultUsername": "Ben",
"welcomeText": "@:appName'e Hoş Geldiniz!",
"githubStarText": "GitHub Yıldızı!",
"subscribeNewsletterText": "Bültene Abone Ol",
"letsGoButtonText": "Hadi başlayalım.",
"title": "Başlık",
"signUp": {
"buttonText": "Kayıt Ol",
"title": "@:appName'e kaydolun.",
"getStartedText": "başlayalım",
"emptyPasswordError": "Parola boş olamaz",
"repeatPasswordEmptyError": "Parola (tekrar) boş olamaz",
"unmatchedPasswordError": "Parolalar eşleşmiyor",
"alreadyHaveAnAccount": "Zaten hesabınız var mı?",
"emailHint": "E-Posta",
"passwordHint": "Parola",
"repeatPasswordHint": "Tekrar parola"
},
"signIn": {
"loginTitle": "@:appName oturum aç",
"loginButtonText": "Giriş",
"buttonText": "Oturum Aç",
"forgotPassword": "Parolanızı mı Unuttunuz?",
"emailHint": "E-Posta",
"passwordHint": "Parola",
"dontHaveAnAccount": "Hesabınız yok mu?",
"repeatPasswordEmptyError": "Parola (tekrar) boş olamaz",
"unmatchedPasswordError": "Parolalar eşleşmiyor"
},
"workspace": {
"create": "Çalışma alanı oluştur",
"hint": "Çalışma alanı",
"notFoundError": "Çalışma alanı bulunamadı"
},
"shareAction": {
"buttonText": "Paylaş",
"workInProgress": "Yakında",
"markdown": "Markdown",
"copyLink": "Link'i Kopyala"
},
"disclosureAction": {
"rename": "Yeniden adlandır",
"delete": "Sil",
"duplicate": "Çoğalt"
},
"blankPageTitle": "Boş sayfa",
"newPageText": "Yeni sayfa",
"trash": {
"text": "Çöp",
"restoreAll": "Geri Yükle",
"deleteAll": "Sil",
"pageHeader": {
"fileName": "Dosya adı",
"lastModified": "Son Değiştirme",
"created": "Oluşturuldu"
}
},
"deletePagePrompt": {
"text": "Bu sayfa Çöp Kutusu'nda",
"restore": "Sayfayı geri yükle",
"deletePermanent": "Kalıcı olarak sil"
},
"dialogCreatePageNameHint": "Sayfa adı",
"questionBubble": {
"whatsNew": "Yeni ne var?",
"help": "Yardım & Destek",
"debug": {
"name": "Hata Ayıklama",
"success": "Hata ayıklama bilgileri panoya kopyalandı!",
"fail": "Hata ayıklama bilgileri panoya kopyalanamıyor"
}
},
"menuAppHeader": {
"addPageTooltip": "Yeni bir sayfa ekleyin",
"defaultNewPageName": "Başlıksız",
"renameDialog": "Yeniden adlandır"
},
"toolbar": {
"undo": "Geri",
"redo": "İleri",
"bold": "Kalın",
"italic": "İtalik",
"underline": "Altı Çizili",
"strike": "Üstü Çizili",
"numList": "Numaralı Liste",
"bulletList": "Madde İşaretli Liste",
"checkList": "Yapılacaklar Listesi",
"inlineCode": "Kod",
"quote": "Alıntı",
"header": "Başlık",
"highlight": "Vurgu"
},
"tooltip": {
"lightMode": "Aydınlık Mod'a Geç",
"darkMode": "Karanlık Mod'a Geç"
},
"contactsPage": {
"title": "İletişim",
"whatsHappening": "Bu hafta neler var?",
"addContact": "Kişi Ekle",
"editContact": "Kişiyi Düzenle"
},
"button": {
"OK": "TAMAM",
"Cancel": "İptal",
"signIn": "Oturum Aç",
"signOut": "Oturum Kapat",
"complete": "Tamamlandı",
"save": "Kaydet"
},
"label": {
"welcome": "Merhaba!",
"firstName": "Ad",
"middleName": "İkinci Ad",
"lastName": "Soyad",
"stepX": "Aşama {X}"
},
"oAuth": {
"err": {
"failedTitle": "Hesabınıza bağlanılamıyor.",
"failedMsg": "Lütfen, tarayıcınızda oturum açma işlemini tamamladığınızdan emin olun."
},
"google": {
"title": "GOOGLE OTURUM AÇMA",
"instruction1": "Google Kişilerinizi içe aktarmak için web tarayıcınızı kullanarak bu uygulamaya izin vermeniz gerekir.",
"instruction2": "Simgeyi tıklayarak veya metni seçerek bu kodu panonuza kopyalayın:",
"instruction3": "Web tarayıcınızda aşağıdaki bağlantıyı açın ve yukarıdaki kodu girin:",
"instruction4": "Kayıt işlemini tamamladığınızda aşağıdaki düğmeye basın:"
}
},
"settings": {
"title": "Ayarlar",
"menu": {
"appearance": "Görünüm",
"language": "Dil",
"open": "Ayarları Aç"
},
"appearance": {
"lightLabel": "Aydınlık Mod",
"darkLabel": "Karanlık Mod"
}
}
}
@@ -0,0 +1,67 @@
import 'package:flutter/services.dart';
import 'package:flutter/material.dart';
import 'dart:io' show Platform;
class CocoaWindowChannel {
CocoaWindowChannel._();
final MethodChannel _channel = const MethodChannel("flutter/cocoaWindow");
static final CocoaWindowChannel instance = CocoaWindowChannel._();
Future<void> setWindowPosition(Offset offset) async {
await _channel.invokeMethod("setWindowPosition", [offset.dx, offset.dy]);
}
Future<List<double>> getWindowPosition() async {
final raw = await _channel.invokeMethod("getWindowPosition");
final arr = raw as List<dynamic>;
final List<double> result = arr.map((s) => s as double).toList();
return result;
}
Future<void> zoom() async {
await _channel.invokeMethod("zoom");
}
}
class MoveWindowDetector extends StatefulWidget {
const MoveWindowDetector({Key? key, this.child}) : super(key: key);
final Widget? child;
@override
_MoveWindowDetectorState createState() => _MoveWindowDetectorState();
}
class _MoveWindowDetectorState extends State<MoveWindowDetector> {
double winX = 0;
double winY = 0;
@override
Widget build(BuildContext context) {
if (!Platform.isMacOS) {
return widget.child ?? Container();
}
return GestureDetector(
// https://stackoverflow.com/questions/52965799/flutter-gesturedetector-not-working-with-containers-in-stack
behavior: HitTestBehavior.translucent,
onDoubleTap: () async {
await CocoaWindowChannel.instance.zoom();
},
onPanStart: (DragStartDetails details) {
winX = details.globalPosition.dx;
winY = details.globalPosition.dy;
},
onPanUpdate: (DragUpdateDetails details) async {
final windowPos = await CocoaWindowChannel.instance.getWindowPosition();
final double dx = windowPos[0];
final double dy = windowPos[1];
final deltaX = details.globalPosition.dx - winX;
final deltaY = details.globalPosition.dy - winY;
await CocoaWindowChannel.instance.setWindowPosition(Offset(dx + deltaX, dy - deltaY));
},
child: widget.child,
);
}
}
@@ -1,16 +1,16 @@
import 'dart:async';
import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:flowy_log/flowy_log.dart';
import 'package:flowy_sdk/log.dart';
import 'package:flowy_sdk/dispatch/dispatch.dart';
import 'package:flowy_sdk/protobuf/flowy-net/network_state.pb.dart';
import 'package:flutter/services.dart';
class NetworkMonitor {
class NetworkListener {
final Connectivity _connectivity = Connectivity();
late StreamSubscription<ConnectivityResult> _connectivitySubscription;
NetworkMonitor() {
NetworkListener() {
_connectivitySubscription = _connectivity.onConnectivityChanged.listen(_updateConnectionStatus);
}
@@ -1,10 +1,14 @@
import 'dart:async';
import 'dart:typed_data';
import 'package:flowy_sdk/protobuf/dart-notify/protobuf.dart';
import 'package:flowy_sdk/protobuf/flowy-user/protobuf.dart';
import 'package:dartz/dartz.dart';
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-folder/dart_notification.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/dart_notification.pb.dart';
import 'package:flowy_sdk/rust_stream.dart';
// User
typedef UserNotificationCallback = void Function(UserNotification, Either<Uint8List, FlowyError>);
class UserNotificationParser extends NotificationParser<UserNotification, FlowyError> {
@@ -17,10 +21,11 @@ class UserNotificationParser extends NotificationParser<UserNotification, FlowyE
);
}
typedef NotificationCallback = void Function(FolderNotification, Either<Uint8List, FlowyError>);
// Folder
typedef FolderNotificationCallback = void Function(FolderNotification, Either<Uint8List, FlowyError>);
class FolderNotificationParser extends NotificationParser<FolderNotification, FlowyError> {
FolderNotificationParser({String? id, required NotificationCallback callback})
FolderNotificationParser({String? id, required FolderNotificationCallback callback})
: super(
id: id,
callback: callback,
@@ -29,6 +34,36 @@ class FolderNotificationParser extends NotificationParser<FolderNotification, Fl
);
}
// Grid
typedef GridNotificationCallback = void Function(GridNotification, Either<Uint8List, FlowyError>);
class GridNotificationParser extends NotificationParser<GridNotification, FlowyError> {
GridNotificationParser({String? id, required GridNotificationCallback callback})
: super(
id: id,
callback: callback,
tyParser: (ty) => GridNotification.valueOf(ty),
errorParser: (bytes) => FlowyError.fromBuffer(bytes),
);
}
typedef GridNotificationHandler = Function(GridNotification ty, Either<Uint8List, FlowyError> result);
class GridNotificationListener {
StreamSubscription<SubscribeObject>? _subscription;
GridNotificationParser? _parser;
GridNotificationListener({required String objectId, required GridNotificationHandler handler})
: _parser = GridNotificationParser(id: objectId, callback: handler) {
_subscription = RustStreamReceiver.listen((observable) => _parser?.parse(observable));
}
Future<void> stop() async {
_parser = null;
await _subscription?.cancel();
}
}
class NotificationParser<T, E> {
String? id;
void Function(T, Either<Uint8List, E>) callback;
+1 -1
View File
@@ -14,5 +14,5 @@ void main() async {
WidgetsFlutterBinding.ensureInitialized();
await EasyLocalization.ensureInitialized();
System.run(FlowyApp());
await FlowyRunner.run(FlowyApp());
}
+93
View File
@@ -0,0 +1,93 @@
library flowy_plugin;
import 'package:app_flowy/plugin/plugin.dart';
import 'package:app_flowy/startup/startup.dart';
import 'package:app_flowy/workspace/presentation/home/home_stack.dart';
import 'package:flowy_infra/notifier.dart';
import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart';
import 'package:flutter/widgets.dart';
export "./src/sandbox.dart";
enum DefaultPlugin {
quill,
blank,
trash,
grid,
}
extension FlowyDefaultPluginExt on DefaultPlugin {
int type() {
switch (this) {
case DefaultPlugin.quill:
return 0;
case DefaultPlugin.blank:
return 1;
case DefaultPlugin.trash:
return 2;
case DefaultPlugin.grid:
return 3;
}
}
}
typedef PluginType = int;
typedef PluginDataType = ViewDataType;
typedef PluginId = String;
abstract class Plugin {
PluginId get id;
PluginDisplay get display;
PluginType get ty;
void dispose() {}
}
abstract class PluginBuilder {
Plugin build(dynamic data);
String get menuName;
PluginType get pluginType;
ViewDataType get dataType => ViewDataType.TextBlock;
}
abstract class PluginConfig {
// Return false will disable the user to create it. For example, a trash plugin shouldn't be created by the user,
bool get creatable => true;
}
abstract class PluginDisplay<T> with NavigationItem {
List<NavigationItem> get navigationItems;
PublishNotifier<T>? get notifier => null;
Widget buildWidget();
}
void registerPlugin({required PluginBuilder builder, PluginConfig? config}) {
getIt<PluginSandbox>().registerPlugin(builder.pluginType, builder, config: config);
}
Plugin makePlugin({required PluginType pluginType, dynamic data}) {
final plugin = getIt<PluginSandbox>().buildPlugin(pluginType, data);
return plugin;
}
List<PluginBuilder> pluginBuilders() {
final pluginBuilders = getIt<PluginSandbox>().builders;
final pluginConfigs = getIt<PluginSandbox>().pluginConfigs;
return pluginBuilders.where(
(builder) {
final config = pluginConfigs[builder.pluginType]?.creatable;
return config ?? true;
},
).toList();
}
enum FlowyPluginException {
invalidData,
}
@@ -0,0 +1 @@
class PluginRunner {}
@@ -0,0 +1,46 @@
import 'dart:collection';
import 'package:flutter/services.dart';
import '../plugin.dart';
import 'runner.dart';
class PluginSandbox {
final LinkedHashMap<PluginType, PluginBuilder> _pluginBuilders = LinkedHashMap();
final Map<PluginType, PluginConfig> _pluginConfigs = <PluginType, PluginConfig>{};
late PluginRunner pluginRunner;
PluginSandbox() {
pluginRunner = PluginRunner();
}
int indexOf(PluginType pluginType) {
final index = _pluginBuilders.keys.toList().indexWhere((ty) => ty == pluginType);
if (index == -1) {
throw PlatformException(code: '-1', message: "Can't find the flowy plugin type: $pluginType");
}
return index;
}
Plugin buildPlugin(PluginType pluginType, dynamic data) {
final plugin = _pluginBuilders[pluginType]!.build(data);
return plugin;
}
void registerPlugin(PluginType pluginType, PluginBuilder builder, {PluginConfig? config}) {
if (_pluginBuilders.containsKey(pluginType)) {
throw PlatformException(code: '-1', message: "$pluginType was registered before");
}
_pluginBuilders[pluginType] = builder;
if (config != null) {
_pluginConfigs[pluginType] = config;
}
}
List<int> get supportPluginTypes => _pluginBuilders.keys.toList();
List<PluginBuilder> get builders => _pluginBuilders.values.toList();
Map<PluginType, PluginConfig> get pluginConfigs => _pluginConfigs;
}
@@ -0,0 +1,194 @@
import 'package:app_flowy/core/network_monitor.dart';
import 'package:app_flowy/user/application/user_listener.dart';
import 'package:app_flowy/user/application/user_service.dart';
import 'package:app_flowy/workspace/application/app/prelude.dart';
import 'package:app_flowy/workspace/application/doc/prelude.dart';
import 'package:app_flowy/workspace/application/grid/prelude.dart';
import 'package:app_flowy/workspace/application/trash/prelude.dart';
import 'package:app_flowy/workspace/application/workspace/prelude.dart';
import 'package:app_flowy/workspace/application/edit_pannel/edit_pannel_bloc.dart';
import 'package:app_flowy/workspace/application/view/prelude.dart';
import 'package:app_flowy/workspace/application/menu/prelude.dart';
import 'package:app_flowy/user/application/prelude.dart';
import 'package:app_flowy/user/presentation/router.dart';
import 'package:app_flowy/workspace/presentation/home/home_stack.dart';
import 'package:app_flowy/workspace/presentation/home/menu/menu.dart';
import 'package:flowy_sdk/protobuf/flowy-folder-data-model/app.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-user-data-model/user_profile.pb.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:get_it/get_it.dart';
class DependencyResolver {
static Future<void> resolve(GetIt getIt) async {
_resolveUserDeps(getIt);
_resolveHomeDeps(getIt);
_resolveFolderDeps(getIt);
_resolveDocDeps(getIt);
_resolveGridDeps(getIt);
}
}
void _resolveUserDeps(GetIt getIt) {
getIt.registerFactory<AuthService>(() => AuthService());
getIt.registerFactory<AuthRouter>(() => AuthRouter());
getIt.registerFactory<SignInBloc>(() => SignInBloc(getIt<AuthService>()));
getIt.registerFactory<SignUpBloc>(() => SignUpBloc(getIt<AuthService>()));
getIt.registerFactory<SplashRoute>(() => SplashRoute());
getIt.registerFactory<EditPannelBloc>(() => EditPannelBloc());
getIt.registerFactory<SplashBloc>(() => SplashBloc());
getIt.registerLazySingleton<NetworkListener>(() => NetworkListener());
}
void _resolveHomeDeps(GetIt getIt) {
getIt.registerSingleton(FToast());
getIt.registerSingleton(MenuSharedState());
getIt.registerFactoryParam<UserListener, UserProfile, void>(
(user, _) => UserListener(user: user),
);
//
getIt.registerLazySingleton<HomeStackManager>(() => HomeStackManager());
getIt.registerFactoryParam<WelcomeBloc, UserProfile, void>(
(user, _) => WelcomeBloc(
userService: UserService(),
userListener: getIt<UserListener>(param1: user),
),
);
// share
getIt.registerLazySingleton<ShareService>(() => ShareService());
getIt.registerFactoryParam<DocShareBloc, View, void>(
(view, _) => DocShareBloc(view: view, service: getIt<ShareService>()));
}
void _resolveFolderDeps(GetIt getIt) {
//workspace
getIt.registerFactoryParam<WorkspaceListener, UserProfile, String>((user, workspaceId) =>
WorkspaceListener(service: WorkspaceListenerService(user: user, workspaceId: workspaceId)));
// View
getIt.registerFactoryParam<ViewListener, View, void>(
(view, _) => ViewListener(view: view),
);
getIt.registerFactoryParam<ViewBloc, View, void>(
(view, _) => ViewBloc(
view: view,
service: ViewService(),
listener: getIt<ViewListener>(param1: view),
),
);
//Menu
getIt.registerFactoryParam<MenuBloc, UserProfile, String>(
(user, workspaceId) => MenuBloc(
workspaceId: workspaceId,
listener: getIt<WorkspaceListener>(param1: user, param2: workspaceId),
),
);
getIt.registerFactoryParam<MenuUserBloc, UserProfile, void>(
(user, _) => MenuUserBloc(
user,
UserService(),
getIt<UserListener>(param1: user),
),
);
// App
getIt.registerFactoryParam<AppBloc, App, void>(
(app, _) => AppBloc(
app: app,
appService: AppService(appId: app.id),
appListener: AppListener(appId: app.id),
),
);
// trash
getIt.registerLazySingleton<TrashService>(() => TrashService());
getIt.registerLazySingleton<TrashListener>(() => TrashListener());
getIt.registerFactory<TrashBloc>(
() => TrashBloc(
service: getIt<TrashService>(),
listener: getIt<TrashListener>(),
),
);
}
void _resolveDocDeps(GetIt getIt) {
// Doc
getIt.registerFactoryParam<DocumentBloc, View, void>(
(view, _) => DocumentBloc(
view: view,
service: DocumentService(),
listener: getIt<ViewListener>(param1: view),
trashService: getIt<TrashService>(),
),
);
}
void _resolveGridDeps(GetIt getIt) {
// Grid
getIt.registerFactoryParam<GridBloc, View, void>(
(view, _) => GridBloc(view: view),
);
getIt.registerFactoryParam<GridHeaderBloc, String, GridFieldCache>(
(gridId, fieldCache) => GridHeaderBloc(
gridId: gridId,
fieldCache: fieldCache,
),
);
getIt.registerFactoryParam<FieldActionSheetBloc, GridFieldCellContext, void>(
(data, _) => FieldActionSheetBloc(
field: data.field,
fieldService: FieldService(gridId: data.gridId, fieldId: data.field.id),
),
);
getIt.registerFactoryParam<TextCellBloc, GridCellContext, void>(
(context, _) => TextCellBloc(
cellContext: context,
),
);
getIt.registerFactoryParam<SelectOptionCellBloc, GridSelectOptionCellContext, void>(
(context, _) => SelectOptionCellBloc(
cellContext: context,
),
);
getIt.registerFactoryParam<NumberCellBloc, GridCellContext, void>(
(context, _) => NumberCellBloc(
cellContext: context,
),
);
getIt.registerFactoryParam<DateCellBloc, GridDateCellContext, void>(
(context, _) => DateCellBloc(
cellContext: context,
),
);
getIt.registerFactoryParam<CheckboxCellBloc, GridCellContext, void>(
(cellData, _) => CheckboxCellBloc(
service: CellService(),
cellContext: cellData,
),
);
getIt.registerFactoryParam<GridPropertyBloc, String, GridFieldCache>(
(gridId, cache) => GridPropertyBloc(gridId: gridId, fieldCache: cache),
);
}
@@ -1,40 +0,0 @@
import 'package:app_flowy/startup/startup.dart';
import 'package:get_it/get_it.dart';
class LaunchContext {
GetIt getIt;
IntegrationEnv env;
LaunchContext(this.getIt, this.env);
}
enum LaunchTaskType {
dataProcessing,
appLauncher,
}
/// The interface of an app launch task, which will trigger
/// some nonresident indispensable task in app launching task.
abstract class LaunchTask {
LaunchTaskType get type => LaunchTaskType.dataProcessing;
Future<void> initialize(LaunchContext context);
}
class AppLauncher {
List<LaunchTask> tasks;
IntegrationEnv env;
GetIt getIt;
AppLauncher(this.env, this.getIt) : tasks = List.from([]);
void addTask(LaunchTask task) {
tasks.add(task);
}
void launch() async {
final context = LaunchContext(getIt, env);
for (var task in tasks) {
await task.initialize(context);
}
}
}
//test git hooks
+81 -24
View File
@@ -1,13 +1,13 @@
import 'package:app_flowy/startup/launcher.dart';
import 'dart:io';
import 'package:app_flowy/plugin/plugin.dart';
import 'package:app_flowy/startup/tasks/prelude.dart';
import 'package:app_flowy/startup/deps_resolver.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:get_it/get_it.dart';
import 'package:app_flowy/workspace/infrastructure/deps_resolver.dart';
import 'package:app_flowy/user/infrastructure/deps_resolver.dart';
import 'package:flowy_sdk/flowy_sdk.dart';
import 'tasks/init_platform_service.dart';
// [[diagram: flowy startup flow]]
// ┌──────────┐
// │ FlowyApp │
@@ -26,44 +26,101 @@ import 'tasks/init_platform_service.dart';
//
// 3.build MeterialApp
final getIt = GetIt.instance;
enum IntegrationEnv {
dev,
pro,
}
abstract class EntryPoint {
Widget create();
}
class System {
static void run(EntryPoint f) {
class FlowyRunner {
static Future<void> run(EntryPoint f) async {
// Specify the env
const env = IntegrationEnv.dev;
// Config the deps graph
getIt.registerFactory<EntryPoint>(() => f);
resolveDependencies(env);
final env = integrationEnv();
initGetIt(getIt, env, f);
// add task
getIt<AppLauncher>().addTask(InitRustSDKTask());
getIt<AppLauncher>().addTask(AppWidgetTask());
getIt<AppLauncher>().addTask(InitPlatformService());
if (!env.isTest()) {
getIt<AppLauncher>().addTask(PluginLoadTask());
getIt<AppLauncher>().addTask(InitAppWidgetTask());
getIt<AppLauncher>().addTask(InitPlatformServiceTask());
}
// execute the tasks
getIt<AppLauncher>().launch();
}
}
void resolveDependencies(IntegrationEnv env) => initGetIt(getIt, env);
Future<void> initGetIt(
GetIt getIt,
IntegrationEnv env,
IntegrationMode env,
EntryPoint f,
) async {
getIt.registerFactory<EntryPoint>(() => f);
getIt.registerLazySingleton<FlowySDK>(() => const FlowySDK());
getIt.registerLazySingleton<AppLauncher>(() => AppLauncher(env, getIt));
getIt.registerSingleton<PluginSandbox>(PluginSandbox());
await UserDepsResolver.resolve(getIt);
await HomeDepsResolver.resolve(getIt);
await DependencyResolver.resolve(getIt);
}
class LaunchContext {
GetIt getIt;
IntegrationMode env;
LaunchContext(this.getIt, this.env);
}
enum LaunchTaskType {
dataProcessing,
appLauncher,
}
/// The interface of an app launch task, which will trigger
/// some nonresident indispensable task in app launching task.
abstract class LaunchTask {
LaunchTaskType get type => LaunchTaskType.dataProcessing;
Future<void> initialize(LaunchContext context);
}
class AppLauncher {
List<LaunchTask> tasks;
IntegrationMode env;
GetIt getIt;
AppLauncher(this.env, this.getIt) : tasks = List.from([]);
void addTask(LaunchTask task) {
tasks.add(task);
}
Future<void> launch() async {
final context = LaunchContext(getIt, env);
for (var task in tasks) {
await task.initialize(context);
}
}
}
enum IntegrationMode {
develop,
release,
test,
}
extension IntegrationEnvExt on IntegrationMode {
bool isTest() {
return this == IntegrationMode.test;
}
}
IntegrationMode integrationEnv() {
if (Platform.environment.containsKey('FLUTTER_TEST')) {
return IntegrationMode.test;
}
if (kReleaseMode) {
return IntegrationMode.release;
}
return IntegrationMode.develop;
}
@@ -1,5 +1,5 @@
import 'package:app_flowy/startup/startup.dart';
import 'package:app_flowy/user/infrastructure/repos/user_setting_repo.dart';
import 'package:app_flowy/user/application/user_settings_service.dart';
import 'package:app_flowy/workspace/application/appearance.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flowy_infra/theme.dart';
@@ -7,18 +7,17 @@ import 'package:flowy_infra_ui/flowy_infra_ui.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:window_size/window_size.dart';
import 'package:app_flowy/startup/launcher.dart';
import 'package:bloc/bloc.dart';
import 'package:flowy_log/flowy_log.dart';
import 'package:flowy_sdk/log.dart';
class AppWidgetTask extends LaunchTask {
class InitAppWidgetTask extends LaunchTask {
@override
LaunchTaskType get type => LaunchTaskType.appLauncher;
@override
Future<void> initialize(LaunchContext context) async {
final widget = context.getIt<EntryPoint>().create();
final setting = await UserSettingReppsitory().getAppearanceSettings();
final setting = await UserSettingsService().getAppearanceSettings();
final settingModel = AppearanceSettingModel(setting);
final app = ApplicationWidget(
child: widget,
@@ -30,11 +29,17 @@ class AppWidgetTask extends LaunchTask {
EasyLocalization(
supportedLocales: const [
// In alphabetical order
Locale('ca', 'ES'),
Locale('de', 'DE'),
Locale('en'),
Locale('es', 'VE'),
Locale('fr', 'FR'),
Locale('fr', 'CA'),
Locale('hu', 'HU'),
Locale('it', 'IT'),
Locale('pt', 'BR'),
Locale('ru', 'RU'),
Locale('tr', 'TR'),
Locale('zh', 'CN'),
],
path: 'assets/translations',
@@ -62,40 +67,42 @@ class ApplicationWidget extends StatelessWidget {
}) : super(key: key);
@override
Widget build(BuildContext context) => ChangeNotifierProvider.value(
value: settingModel,
builder: (context, _) {
const ratio = 1.73;
const minWidth = 600.0;
setWindowMinSize(const Size(minWidth, minWidth / ratio));
settingModel.readLocaleWhenAppLaunch(context);
AppTheme theme = context.select<AppearanceSettingModel, AppTheme>(
(value) => value.theme,
);
Locale locale = context.select<AppearanceSettingModel, Locale>(
(value) => value.locale,
);
Widget build(BuildContext context) {
return ChangeNotifierProvider.value(
value: settingModel,
builder: (context, _) {
const ratio = 1.73;
const minWidth = 600.0;
setWindowMinSize(const Size(minWidth, minWidth / ratio));
settingModel.readLocaleWhenAppLaunch(context);
AppTheme theme = context.select<AppearanceSettingModel, AppTheme>(
(value) => value.theme,
);
Locale locale = context.select<AppearanceSettingModel, Locale>(
(value) => value.locale,
);
return MultiProvider(
providers: [
Provider.value(value: theme),
Provider.value(value: locale),
],
builder: (context, _) {
return MaterialApp(
builder: overlayManagerBuilder(),
debugShowCheckedModeBanner: false,
theme: theme.themeData,
localizationsDelegates: context.localizationDelegates,
supportedLocales: context.supportedLocales,
locale: locale,
navigatorKey: AppGlobals.rootNavKey,
home: child,
);
},
);
},
);
return MultiProvider(
providers: [
Provider.value(value: theme),
Provider.value(value: locale),
],
builder: (context, _) {
return MaterialApp(
builder: overlayManagerBuilder(),
debugShowCheckedModeBanner: false,
theme: theme.themeData,
localizationsDelegates: context.localizationDelegates,
supportedLocales: context.supportedLocales,
locale: locale,
navigatorKey: AppGlobals.rootNavKey,
home: child,
);
},
);
},
);
}
}
class AppGlobals {
@@ -108,7 +115,7 @@ class ApplicationBlocObserver extends BlocObserver {
// ignore: unnecessary_overrides
void onTransition(Bloc bloc, Transition transition) {
// Log.debug("[current]: ${transition.currentState} \n\n[next]: ${transition.nextState}");
//Log.debug("${transition.nextState}");
// Log.debug("${transition.nextState}");
super.onTransition(bloc, transition);
}
@@ -118,9 +125,9 @@ class ApplicationBlocObserver extends BlocObserver {
super.onError(bloc, error, stackTrace);
}
@override
void onEvent(Bloc bloc, Object? event) {
Log.debug("$event");
super.onEvent(bloc, event);
}
// @override
// void onEvent(Bloc bloc, Object? event) {
// Log.debug("$event");
// super.onEvent(bloc, event);
// }
}
@@ -1,14 +0,0 @@
import 'package:app_flowy/startup/launcher.dart';
import 'package:app_flowy/user/infrastructure/network_monitor.dart';
import '../startup.dart';
class InitPlatformService extends LaunchTask {
@override
LaunchTaskType get type => LaunchTaskType.dataProcessing;
@override
Future<void> initialize(LaunchContext context) async {
getIt<NetworkMonitor>().start();
}
}
@@ -1,33 +0,0 @@
import 'dart:io';
import 'package:app_flowy/startup/launcher.dart';
import 'package:app_flowy/startup/startup.dart';
import 'package:path_provider/path_provider.dart';
import 'package:flowy_sdk/flowy_sdk.dart';
import 'package:flutter/material.dart';
class InitRustSDKTask extends LaunchTask {
@override
LaunchTaskType get type => LaunchTaskType.dataProcessing;
@override
Future<void> initialize(LaunchContext context) async {
WidgetsFlutterBinding.ensureInitialized();
Directory directory = await getApplicationDocumentsDirectory();
final documentPath = directory.path;
return Directory('$documentPath/flowy').create().then((Directory directory) async {
switch (context.env) {
case IntegrationEnv.dev:
// await context.getIt<FlowySDK>().init(Directory('./temp/flowy_dev'));
await context.getIt<FlowySDK>().init(directory);
break;
case IntegrationEnv.pro:
await context.getIt<FlowySDK>().init(directory);
break;
default:
assert(false, 'Unsupported env');
}
});
}
}
@@ -0,0 +1,19 @@
import 'package:app_flowy/plugin/plugin.dart';
import 'package:app_flowy/startup/startup.dart';
import 'package:app_flowy/workspace/presentation/plugins/blank/blank.dart';
import 'package:app_flowy/workspace/presentation/plugins/doc/document.dart';
import 'package:app_flowy/workspace/presentation/plugins/grid/grid.dart';
import 'package:app_flowy/workspace/presentation/plugins/trash/trash.dart';
class PluginLoadTask extends LaunchTask {
@override
LaunchTaskType get type => LaunchTaskType.dataProcessing;
@override
Future<void> initialize(LaunchContext context) async {
registerPlugin(builder: BlankPluginBuilder(), config: BlankPluginConfig());
registerPlugin(builder: TrashPluginBuilder(), config: TrashPluginConfig());
registerPlugin(builder: DocumentPluginBuilder());
registerPlugin(builder: GridPluginBuilder(), config: GridPluginConfig());
}
}
@@ -0,0 +1,12 @@
import 'package:app_flowy/core/network_monitor.dart';
import '../startup.dart';
class InitPlatformServiceTask extends LaunchTask {
@override
LaunchTaskType get type => LaunchTaskType.dataProcessing;
@override
Future<void> initialize(LaunchContext context) async {
getIt<NetworkListener>().start();
}
}
@@ -1,2 +1,4 @@
export 'application_widget.dart';
export 'init_sdk.dart';
export 'app_widget.dart';
export 'rust_sdk.dart';
export 'platform_service.dart';
export 'load_plugin.dart';
@@ -0,0 +1,29 @@
import 'dart:io';
import 'package:app_flowy/startup/startup.dart';
import 'package:path_provider/path_provider.dart';
import 'package:flowy_sdk/flowy_sdk.dart';
class InitRustSDKTask extends LaunchTask {
@override
LaunchTaskType get type => LaunchTaskType.dataProcessing;
@override
Future<void> initialize(LaunchContext context) async {
await appFlowyDocumentDirectory().then((directory) async {
await context.getIt<FlowySDK>().init(directory);
});
}
}
Future<Directory> appFlowyDocumentDirectory() async {
Directory documentsDir = await getApplicationDocumentsDirectory();
switch (integrationEnv()) {
case IntegrationMode.develop:
return Directory('${documentsDir.path}/flowy_dev').create();
case IntegrationMode.release:
return Directory('${documentsDir.path}/flowy').create();
case IntegrationMode.test:
return Directory("${Directory.current.path}/.sandbox");
}
}
@@ -1,12 +1,12 @@
import 'package:dartz/dartz.dart';
import 'package:flowy_sdk/dispatch/dispatch.dart';
import 'package:flowy_sdk/protobuf/flowy-user-data-model/protobuf.dart' show SignInRequest, SignUpRequest, UserProfile;
import 'package:flowy_sdk/protobuf/flowy-user-data-model/protobuf.dart' show SignInPayload, SignUpPayload, UserProfile;
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
class AuthRepository {
class AuthService {
Future<Either<UserProfile, FlowyError>> signIn({required String? email, required String? password}) {
//
final request = SignInRequest.create()
final request = SignInPayload.create()
..email = email ?? ''
..password = password ?? '';
@@ -15,7 +15,7 @@ class AuthRepository {
Future<Either<UserProfile, FlowyError>> signUp(
{required String? name, required String? password, required String? email}) {
final request = SignUpRequest.create()
final request = SignUpPayload.create()
..email = email ?? ''
..name = name ?? ''
..password = password ?? '';
@@ -0,0 +1,4 @@
export './auth_service.dart';
export './sign_in_bloc.dart';
export './sign_up_bloc.dart';
export './splash_bloc.dart';
@@ -1,4 +1,4 @@
import 'package:app_flowy/user/infrastructure/repos/auth_repo.dart';
import 'package:app_flowy/user/application/auth_service.dart';
import 'package:dartz/dartz.dart';
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-user-data-model/protobuf.dart' show UserProfile, ErrorCode;
@@ -8,8 +8,8 @@ import 'package:flutter_bloc/flutter_bloc.dart';
part 'sign_in_bloc.freezed.dart';
class SignInBloc extends Bloc<SignInEvent, SignInState> {
final AuthRepository authRepo;
SignInBloc(this.authRepo) : super(SignInState.initial()) {
final AuthService authService;
SignInBloc(this.authService) : super(SignInState.initial()) {
on<SignInEvent>((event, emit) async {
await event.map(
signedInWithUserEmailAndPassword: (e) async {
@@ -31,7 +31,7 @@ class SignInBloc extends Bloc<SignInEvent, SignInState> {
Future<void> _performActionOnSignIn(SignInState state, Emitter<SignInState> emit) async {
emit(state.copyWith(isSubmitting: true, emailError: none(), passwordError: none(), successOrFail: none()));
final result = await authRepo.signIn(
final result = await authService.signIn(
email: state.email,
password: state.password,
);
@@ -54,14 +54,14 @@ class SignInBloc extends Bloc<SignInEvent, SignInState> {
}
@freezed
abstract class SignInEvent with _$SignInEvent {
class SignInEvent with _$SignInEvent {
const factory SignInEvent.signedInWithUserEmailAndPassword() = SignedInWithUserEmailAndPassword;
const factory SignInEvent.emailChanged(String email) = EmailChanged;
const factory SignInEvent.passwordChanged(String password) = PasswordChanged;
}
@freezed
abstract class SignInState with _$SignInState {
class SignInState with _$SignInState {
const factory SignInState({
String? email,
String? password,
@@ -1,771 +0,0 @@
// coverage:ignore-file
// GENERATED CODE - DO NOT MODIFY BY HAND
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target
part of 'sign_in_bloc.dart';
// **************************************************************************
// FreezedGenerator
// **************************************************************************
T _$identity<T>(T value) => value;
final _privateConstructorUsedError = UnsupportedError(
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more informations: https://github.com/rrousselGit/freezed#custom-getters-and-methods');
/// @nodoc
class _$SignInEventTearOff {
const _$SignInEventTearOff();
SignedInWithUserEmailAndPassword signedInWithUserEmailAndPassword() {
return const SignedInWithUserEmailAndPassword();
}
EmailChanged emailChanged(String email) {
return EmailChanged(
email,
);
}
PasswordChanged passwordChanged(String password) {
return PasswordChanged(
password,
);
}
}
/// @nodoc
const $SignInEvent = _$SignInEventTearOff();
/// @nodoc
mixin _$SignInEvent {
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function() signedInWithUserEmailAndPassword,
required TResult Function(String email) emailChanged,
required TResult Function(String password) passwordChanged,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({
TResult Function()? signedInWithUserEmailAndPassword,
TResult Function(String email)? emailChanged,
TResult Function(String password)? passwordChanged,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function()? signedInWithUserEmailAndPassword,
TResult Function(String email)? emailChanged,
TResult Function(String password)? passwordChanged,
required TResult orElse(),
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(SignedInWithUserEmailAndPassword value)
signedInWithUserEmailAndPassword,
required TResult Function(EmailChanged value) emailChanged,
required TResult Function(PasswordChanged value) passwordChanged,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>({
TResult Function(SignedInWithUserEmailAndPassword value)?
signedInWithUserEmailAndPassword,
TResult Function(EmailChanged value)? emailChanged,
TResult Function(PasswordChanged value)? passwordChanged,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(SignedInWithUserEmailAndPassword value)?
signedInWithUserEmailAndPassword,
TResult Function(EmailChanged value)? emailChanged,
TResult Function(PasswordChanged value)? passwordChanged,
required TResult orElse(),
}) =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $SignInEventCopyWith<$Res> {
factory $SignInEventCopyWith(
SignInEvent value, $Res Function(SignInEvent) then) =
_$SignInEventCopyWithImpl<$Res>;
}
/// @nodoc
class _$SignInEventCopyWithImpl<$Res> implements $SignInEventCopyWith<$Res> {
_$SignInEventCopyWithImpl(this._value, this._then);
final SignInEvent _value;
// ignore: unused_field
final $Res Function(SignInEvent) _then;
}
/// @nodoc
abstract class $SignedInWithUserEmailAndPasswordCopyWith<$Res> {
factory $SignedInWithUserEmailAndPasswordCopyWith(
SignedInWithUserEmailAndPassword value,
$Res Function(SignedInWithUserEmailAndPassword) then) =
_$SignedInWithUserEmailAndPasswordCopyWithImpl<$Res>;
}
/// @nodoc
class _$SignedInWithUserEmailAndPasswordCopyWithImpl<$Res>
extends _$SignInEventCopyWithImpl<$Res>
implements $SignedInWithUserEmailAndPasswordCopyWith<$Res> {
_$SignedInWithUserEmailAndPasswordCopyWithImpl(
SignedInWithUserEmailAndPassword _value,
$Res Function(SignedInWithUserEmailAndPassword) _then)
: super(_value, (v) => _then(v as SignedInWithUserEmailAndPassword));
@override
SignedInWithUserEmailAndPassword get _value =>
super._value as SignedInWithUserEmailAndPassword;
}
/// @nodoc
class _$SignedInWithUserEmailAndPassword
implements SignedInWithUserEmailAndPassword {
const _$SignedInWithUserEmailAndPassword();
@override
String toString() {
return 'SignInEvent.signedInWithUserEmailAndPassword()';
}
@override
bool operator ==(dynamic other) {
return identical(this, other) ||
(other is SignedInWithUserEmailAndPassword);
}
@override
int get hashCode => runtimeType.hashCode;
@override
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function() signedInWithUserEmailAndPassword,
required TResult Function(String email) emailChanged,
required TResult Function(String password) passwordChanged,
}) {
return signedInWithUserEmailAndPassword();
}
@override
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({
TResult Function()? signedInWithUserEmailAndPassword,
TResult Function(String email)? emailChanged,
TResult Function(String password)? passwordChanged,
}) {
return signedInWithUserEmailAndPassword?.call();
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function()? signedInWithUserEmailAndPassword,
TResult Function(String email)? emailChanged,
TResult Function(String password)? passwordChanged,
required TResult orElse(),
}) {
if (signedInWithUserEmailAndPassword != null) {
return signedInWithUserEmailAndPassword();
}
return orElse();
}
@override
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(SignedInWithUserEmailAndPassword value)
signedInWithUserEmailAndPassword,
required TResult Function(EmailChanged value) emailChanged,
required TResult Function(PasswordChanged value) passwordChanged,
}) {
return signedInWithUserEmailAndPassword(this);
}
@override
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>({
TResult Function(SignedInWithUserEmailAndPassword value)?
signedInWithUserEmailAndPassword,
TResult Function(EmailChanged value)? emailChanged,
TResult Function(PasswordChanged value)? passwordChanged,
}) {
return signedInWithUserEmailAndPassword?.call(this);
}
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(SignedInWithUserEmailAndPassword value)?
signedInWithUserEmailAndPassword,
TResult Function(EmailChanged value)? emailChanged,
TResult Function(PasswordChanged value)? passwordChanged,
required TResult orElse(),
}) {
if (signedInWithUserEmailAndPassword != null) {
return signedInWithUserEmailAndPassword(this);
}
return orElse();
}
}
abstract class SignedInWithUserEmailAndPassword implements SignInEvent {
const factory SignedInWithUserEmailAndPassword() =
_$SignedInWithUserEmailAndPassword;
}
/// @nodoc
abstract class $EmailChangedCopyWith<$Res> {
factory $EmailChangedCopyWith(
EmailChanged value, $Res Function(EmailChanged) then) =
_$EmailChangedCopyWithImpl<$Res>;
$Res call({String email});
}
/// @nodoc
class _$EmailChangedCopyWithImpl<$Res> extends _$SignInEventCopyWithImpl<$Res>
implements $EmailChangedCopyWith<$Res> {
_$EmailChangedCopyWithImpl(
EmailChanged _value, $Res Function(EmailChanged) _then)
: super(_value, (v) => _then(v as EmailChanged));
@override
EmailChanged get _value => super._value as EmailChanged;
@override
$Res call({
Object? email = freezed,
}) {
return _then(EmailChanged(
email == freezed
? _value.email
: email // ignore: cast_nullable_to_non_nullable
as String,
));
}
}
/// @nodoc
class _$EmailChanged implements EmailChanged {
const _$EmailChanged(this.email);
@override
final String email;
@override
String toString() {
return 'SignInEvent.emailChanged(email: $email)';
}
@override
bool operator ==(dynamic other) {
return identical(this, other) ||
(other is EmailChanged &&
(identical(other.email, email) ||
const DeepCollectionEquality().equals(other.email, email)));
}
@override
int get hashCode =>
runtimeType.hashCode ^ const DeepCollectionEquality().hash(email);
@JsonKey(ignore: true)
@override
$EmailChangedCopyWith<EmailChanged> get copyWith =>
_$EmailChangedCopyWithImpl<EmailChanged>(this, _$identity);
@override
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function() signedInWithUserEmailAndPassword,
required TResult Function(String email) emailChanged,
required TResult Function(String password) passwordChanged,
}) {
return emailChanged(email);
}
@override
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({
TResult Function()? signedInWithUserEmailAndPassword,
TResult Function(String email)? emailChanged,
TResult Function(String password)? passwordChanged,
}) {
return emailChanged?.call(email);
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function()? signedInWithUserEmailAndPassword,
TResult Function(String email)? emailChanged,
TResult Function(String password)? passwordChanged,
required TResult orElse(),
}) {
if (emailChanged != null) {
return emailChanged(email);
}
return orElse();
}
@override
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(SignedInWithUserEmailAndPassword value)
signedInWithUserEmailAndPassword,
required TResult Function(EmailChanged value) emailChanged,
required TResult Function(PasswordChanged value) passwordChanged,
}) {
return emailChanged(this);
}
@override
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>({
TResult Function(SignedInWithUserEmailAndPassword value)?
signedInWithUserEmailAndPassword,
TResult Function(EmailChanged value)? emailChanged,
TResult Function(PasswordChanged value)? passwordChanged,
}) {
return emailChanged?.call(this);
}
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(SignedInWithUserEmailAndPassword value)?
signedInWithUserEmailAndPassword,
TResult Function(EmailChanged value)? emailChanged,
TResult Function(PasswordChanged value)? passwordChanged,
required TResult orElse(),
}) {
if (emailChanged != null) {
return emailChanged(this);
}
return orElse();
}
}
abstract class EmailChanged implements SignInEvent {
const factory EmailChanged(String email) = _$EmailChanged;
String get email => throw _privateConstructorUsedError;
@JsonKey(ignore: true)
$EmailChangedCopyWith<EmailChanged> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $PasswordChangedCopyWith<$Res> {
factory $PasswordChangedCopyWith(
PasswordChanged value, $Res Function(PasswordChanged) then) =
_$PasswordChangedCopyWithImpl<$Res>;
$Res call({String password});
}
/// @nodoc
class _$PasswordChangedCopyWithImpl<$Res>
extends _$SignInEventCopyWithImpl<$Res>
implements $PasswordChangedCopyWith<$Res> {
_$PasswordChangedCopyWithImpl(
PasswordChanged _value, $Res Function(PasswordChanged) _then)
: super(_value, (v) => _then(v as PasswordChanged));
@override
PasswordChanged get _value => super._value as PasswordChanged;
@override
$Res call({
Object? password = freezed,
}) {
return _then(PasswordChanged(
password == freezed
? _value.password
: password // ignore: cast_nullable_to_non_nullable
as String,
));
}
}
/// @nodoc
class _$PasswordChanged implements PasswordChanged {
const _$PasswordChanged(this.password);
@override
final String password;
@override
String toString() {
return 'SignInEvent.passwordChanged(password: $password)';
}
@override
bool operator ==(dynamic other) {
return identical(this, other) ||
(other is PasswordChanged &&
(identical(other.password, password) ||
const DeepCollectionEquality()
.equals(other.password, password)));
}
@override
int get hashCode =>
runtimeType.hashCode ^ const DeepCollectionEquality().hash(password);
@JsonKey(ignore: true)
@override
$PasswordChangedCopyWith<PasswordChanged> get copyWith =>
_$PasswordChangedCopyWithImpl<PasswordChanged>(this, _$identity);
@override
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function() signedInWithUserEmailAndPassword,
required TResult Function(String email) emailChanged,
required TResult Function(String password) passwordChanged,
}) {
return passwordChanged(password);
}
@override
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({
TResult Function()? signedInWithUserEmailAndPassword,
TResult Function(String email)? emailChanged,
TResult Function(String password)? passwordChanged,
}) {
return passwordChanged?.call(password);
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function()? signedInWithUserEmailAndPassword,
TResult Function(String email)? emailChanged,
TResult Function(String password)? passwordChanged,
required TResult orElse(),
}) {
if (passwordChanged != null) {
return passwordChanged(password);
}
return orElse();
}
@override
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(SignedInWithUserEmailAndPassword value)
signedInWithUserEmailAndPassword,
required TResult Function(EmailChanged value) emailChanged,
required TResult Function(PasswordChanged value) passwordChanged,
}) {
return passwordChanged(this);
}
@override
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>({
TResult Function(SignedInWithUserEmailAndPassword value)?
signedInWithUserEmailAndPassword,
TResult Function(EmailChanged value)? emailChanged,
TResult Function(PasswordChanged value)? passwordChanged,
}) {
return passwordChanged?.call(this);
}
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(SignedInWithUserEmailAndPassword value)?
signedInWithUserEmailAndPassword,
TResult Function(EmailChanged value)? emailChanged,
TResult Function(PasswordChanged value)? passwordChanged,
required TResult orElse(),
}) {
if (passwordChanged != null) {
return passwordChanged(this);
}
return orElse();
}
}
abstract class PasswordChanged implements SignInEvent {
const factory PasswordChanged(String password) = _$PasswordChanged;
String get password => throw _privateConstructorUsedError;
@JsonKey(ignore: true)
$PasswordChangedCopyWith<PasswordChanged> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
class _$SignInStateTearOff {
const _$SignInStateTearOff();
_SignInState call(
{String? email,
String? password,
required bool isSubmitting,
required Option<String> passwordError,
required Option<String> emailError,
required Option<Either<UserProfile, FlowyError>> successOrFail}) {
return _SignInState(
email: email,
password: password,
isSubmitting: isSubmitting,
passwordError: passwordError,
emailError: emailError,
successOrFail: successOrFail,
);
}
}
/// @nodoc
const $SignInState = _$SignInStateTearOff();
/// @nodoc
mixin _$SignInState {
String? get email => throw _privateConstructorUsedError;
String? get password => throw _privateConstructorUsedError;
bool get isSubmitting => throw _privateConstructorUsedError;
Option<String> get passwordError => throw _privateConstructorUsedError;
Option<String> get emailError => throw _privateConstructorUsedError;
Option<Either<UserProfile, FlowyError>> get successOrFail =>
throw _privateConstructorUsedError;
@JsonKey(ignore: true)
$SignInStateCopyWith<SignInState> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $SignInStateCopyWith<$Res> {
factory $SignInStateCopyWith(
SignInState value, $Res Function(SignInState) then) =
_$SignInStateCopyWithImpl<$Res>;
$Res call(
{String? email,
String? password,
bool isSubmitting,
Option<String> passwordError,
Option<String> emailError,
Option<Either<UserProfile, FlowyError>> successOrFail});
}
/// @nodoc
class _$SignInStateCopyWithImpl<$Res> implements $SignInStateCopyWith<$Res> {
_$SignInStateCopyWithImpl(this._value, this._then);
final SignInState _value;
// ignore: unused_field
final $Res Function(SignInState) _then;
@override
$Res call({
Object? email = freezed,
Object? password = freezed,
Object? isSubmitting = freezed,
Object? passwordError = freezed,
Object? emailError = freezed,
Object? successOrFail = freezed,
}) {
return _then(_value.copyWith(
email: email == freezed
? _value.email
: email // ignore: cast_nullable_to_non_nullable
as String?,
password: password == freezed
? _value.password
: password // ignore: cast_nullable_to_non_nullable
as String?,
isSubmitting: isSubmitting == freezed
? _value.isSubmitting
: isSubmitting // ignore: cast_nullable_to_non_nullable
as bool,
passwordError: passwordError == freezed
? _value.passwordError
: passwordError // ignore: cast_nullable_to_non_nullable
as Option<String>,
emailError: emailError == freezed
? _value.emailError
: emailError // ignore: cast_nullable_to_non_nullable
as Option<String>,
successOrFail: successOrFail == freezed
? _value.successOrFail
: successOrFail // ignore: cast_nullable_to_non_nullable
as Option<Either<UserProfile, FlowyError>>,
));
}
}
/// @nodoc
abstract class _$SignInStateCopyWith<$Res>
implements $SignInStateCopyWith<$Res> {
factory _$SignInStateCopyWith(
_SignInState value, $Res Function(_SignInState) then) =
__$SignInStateCopyWithImpl<$Res>;
@override
$Res call(
{String? email,
String? password,
bool isSubmitting,
Option<String> passwordError,
Option<String> emailError,
Option<Either<UserProfile, FlowyError>> successOrFail});
}
/// @nodoc
class __$SignInStateCopyWithImpl<$Res> extends _$SignInStateCopyWithImpl<$Res>
implements _$SignInStateCopyWith<$Res> {
__$SignInStateCopyWithImpl(
_SignInState _value, $Res Function(_SignInState) _then)
: super(_value, (v) => _then(v as _SignInState));
@override
_SignInState get _value => super._value as _SignInState;
@override
$Res call({
Object? email = freezed,
Object? password = freezed,
Object? isSubmitting = freezed,
Object? passwordError = freezed,
Object? emailError = freezed,
Object? successOrFail = freezed,
}) {
return _then(_SignInState(
email: email == freezed
? _value.email
: email // ignore: cast_nullable_to_non_nullable
as String?,
password: password == freezed
? _value.password
: password // ignore: cast_nullable_to_non_nullable
as String?,
isSubmitting: isSubmitting == freezed
? _value.isSubmitting
: isSubmitting // ignore: cast_nullable_to_non_nullable
as bool,
passwordError: passwordError == freezed
? _value.passwordError
: passwordError // ignore: cast_nullable_to_non_nullable
as Option<String>,
emailError: emailError == freezed
? _value.emailError
: emailError // ignore: cast_nullable_to_non_nullable
as Option<String>,
successOrFail: successOrFail == freezed
? _value.successOrFail
: successOrFail // ignore: cast_nullable_to_non_nullable
as Option<Either<UserProfile, FlowyError>>,
));
}
}
/// @nodoc
class _$_SignInState implements _SignInState {
const _$_SignInState(
{this.email,
this.password,
required this.isSubmitting,
required this.passwordError,
required this.emailError,
required this.successOrFail});
@override
final String? email;
@override
final String? password;
@override
final bool isSubmitting;
@override
final Option<String> passwordError;
@override
final Option<String> emailError;
@override
final Option<Either<UserProfile, FlowyError>> successOrFail;
@override
String toString() {
return 'SignInState(email: $email, password: $password, isSubmitting: $isSubmitting, passwordError: $passwordError, emailError: $emailError, successOrFail: $successOrFail)';
}
@override
bool operator ==(dynamic other) {
return identical(this, other) ||
(other is _SignInState &&
(identical(other.email, email) ||
const DeepCollectionEquality().equals(other.email, email)) &&
(identical(other.password, password) ||
const DeepCollectionEquality()
.equals(other.password, password)) &&
(identical(other.isSubmitting, isSubmitting) ||
const DeepCollectionEquality()
.equals(other.isSubmitting, isSubmitting)) &&
(identical(other.passwordError, passwordError) ||
const DeepCollectionEquality()
.equals(other.passwordError, passwordError)) &&
(identical(other.emailError, emailError) ||
const DeepCollectionEquality()
.equals(other.emailError, emailError)) &&
(identical(other.successOrFail, successOrFail) ||
const DeepCollectionEquality()
.equals(other.successOrFail, successOrFail)));
}
@override
int get hashCode =>
runtimeType.hashCode ^
const DeepCollectionEquality().hash(email) ^
const DeepCollectionEquality().hash(password) ^
const DeepCollectionEquality().hash(isSubmitting) ^
const DeepCollectionEquality().hash(passwordError) ^
const DeepCollectionEquality().hash(emailError) ^
const DeepCollectionEquality().hash(successOrFail);
@JsonKey(ignore: true)
@override
_$SignInStateCopyWith<_SignInState> get copyWith =>
__$SignInStateCopyWithImpl<_SignInState>(this, _$identity);
}
abstract class _SignInState implements SignInState {
const factory _SignInState(
{String? email,
String? password,
required bool isSubmitting,
required Option<String> passwordError,
required Option<String> emailError,
required Option<Either<UserProfile, FlowyError>> successOrFail}) =
_$_SignInState;
@override
String? get email => throw _privateConstructorUsedError;
@override
String? get password => throw _privateConstructorUsedError;
@override
bool get isSubmitting => throw _privateConstructorUsedError;
@override
Option<String> get passwordError => throw _privateConstructorUsedError;
@override
Option<String> get emailError => throw _privateConstructorUsedError;
@override
Option<Either<UserProfile, FlowyError>> get successOrFail =>
throw _privateConstructorUsedError;
@override
@JsonKey(ignore: true)
_$SignInStateCopyWith<_SignInState> get copyWith =>
throw _privateConstructorUsedError;
}
@@ -1,4 +1,4 @@
import 'package:app_flowy/user/infrastructure/repos/auth_repo.dart';
import 'package:app_flowy/user/application/auth_service.dart';
import 'package:dartz/dartz.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flowy_sdk/protobuf/flowy-user-data-model/protobuf.dart' show UserProfile, ErrorCode;
@@ -10,16 +10,16 @@ import 'package:app_flowy/generated/locale_keys.g.dart';
part 'sign_up_bloc.freezed.dart';
class SignUpBloc extends Bloc<SignUpEvent, SignUpState> {
final AuthRepository autoRepo;
SignUpBloc(this.autoRepo) : super(SignUpState.initial()) {
final AuthService authService;
SignUpBloc(this.authService) : super(SignUpState.initial()) {
on<SignUpEvent>((event, emit) async {
await event.map(signUpWithUserEmailAndPassword: (e) async {
await _performActionOnSignUp(emit);
}, emailChanged: (EmailChanged value) async {
}, emailChanged: (_EmailChanged value) async {
emit(state.copyWith(email: value.email, emailError: none(), successOrFail: none()));
}, passwordChanged: (PasswordChanged value) async {
}, passwordChanged: (_PasswordChanged value) async {
emit(state.copyWith(password: value.password, passwordError: none(), successOrFail: none()));
}, repeatPasswordChanged: (RepeatPasswordChanged value) async {
}, repeatPasswordChanged: (_RepeatPasswordChanged value) async {
emit(state.copyWith(repeatedPassword: value.password, repeatPasswordError: none(), successOrFail: none()));
});
});
@@ -62,7 +62,7 @@ class SignUpBloc extends Bloc<SignUpEvent, SignUpState> {
repeatPasswordError: none(),
));
final result = await autoRepo.signUp(
final result = await authService.signUp(
name: state.email,
password: state.password,
email: state.email,
@@ -104,9 +104,9 @@ class SignUpBloc extends Bloc<SignUpEvent, SignUpState> {
@freezed
class SignUpEvent with _$SignUpEvent {
const factory SignUpEvent.signUpWithUserEmailAndPassword() = SignUpWithUserEmailAndPassword;
const factory SignUpEvent.emailChanged(String email) = EmailChanged;
const factory SignUpEvent.passwordChanged(String password) = PasswordChanged;
const factory SignUpEvent.repeatPasswordChanged(String password) = RepeatPasswordChanged;
const factory SignUpEvent.emailChanged(String email) = _EmailChanged;
const factory SignUpEvent.passwordChanged(String password) = _PasswordChanged;
const factory SignUpEvent.repeatPasswordChanged(String password) = _RepeatPasswordChanged;
}
@freezed
File diff suppressed because it is too large. Load diff
@@ -1,312 +0,0 @@
// coverage:ignore-file
// GENERATED CODE - DO NOT MODIFY BY HAND
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target
part of 'splash_bloc.dart';
// **************************************************************************
// FreezedGenerator
// **************************************************************************
T _$identity<T>(T value) => value;
final _privateConstructorUsedError = UnsupportedError(
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more informations: https://github.com/rrousselGit/freezed#custom-getters-and-methods');
/// @nodoc
class _$SplashEventTearOff {
const _$SplashEventTearOff();
_GetUser getUser() {
return const _GetUser();
}
}
/// @nodoc
const $SplashEvent = _$SplashEventTearOff();
/// @nodoc
mixin _$SplashEvent {
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function() getUser,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({
TResult Function()? getUser,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function()? getUser,
required TResult orElse(),
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(_GetUser value) getUser,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>({
TResult Function(_GetUser value)? getUser,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(_GetUser value)? getUser,
required TResult orElse(),
}) =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $SplashEventCopyWith<$Res> {
factory $SplashEventCopyWith(
SplashEvent value, $Res Function(SplashEvent) then) =
_$SplashEventCopyWithImpl<$Res>;
}
/// @nodoc
class _$SplashEventCopyWithImpl<$Res> implements $SplashEventCopyWith<$Res> {
_$SplashEventCopyWithImpl(this._value, this._then);
final SplashEvent _value;
// ignore: unused_field
final $Res Function(SplashEvent) _then;
}
/// @nodoc
abstract class _$GetUserCopyWith<$Res> {
factory _$GetUserCopyWith(_GetUser value, $Res Function(_GetUser) then) =
__$GetUserCopyWithImpl<$Res>;
}
/// @nodoc
class __$GetUserCopyWithImpl<$Res> extends _$SplashEventCopyWithImpl<$Res>
implements _$GetUserCopyWith<$Res> {
__$GetUserCopyWithImpl(_GetUser _value, $Res Function(_GetUser) _then)
: super(_value, (v) => _then(v as _GetUser));
@override
_GetUser get _value => super._value as _GetUser;
}
/// @nodoc
class _$_GetUser implements _GetUser {
const _$_GetUser();
@override
String toString() {
return 'SplashEvent.getUser()';
}
@override
bool operator ==(dynamic other) {
return identical(this, other) || (other is _GetUser);
}
@override
int get hashCode => runtimeType.hashCode;
@override
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function() getUser,
}) {
return getUser();
}
@override
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({
TResult Function()? getUser,
}) {
return getUser?.call();
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function()? getUser,
required TResult orElse(),
}) {
if (getUser != null) {
return getUser();
}
return orElse();
}
@override
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(_GetUser value) getUser,
}) {
return getUser(this);
}
@override
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>({
TResult Function(_GetUser value)? getUser,
}) {
return getUser?.call(this);
}
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(_GetUser value)? getUser,
required TResult orElse(),
}) {
if (getUser != null) {
return getUser(this);
}
return orElse();
}
}
abstract class _GetUser implements SplashEvent {
const factory _GetUser() = _$_GetUser;
}
/// @nodoc
class _$SplashStateTearOff {
const _$SplashStateTearOff();
_SplashState call({required AuthState auth}) {
return _SplashState(
auth: auth,
);
}
}
/// @nodoc
const $SplashState = _$SplashStateTearOff();
/// @nodoc
mixin _$SplashState {
AuthState get auth => throw _privateConstructorUsedError;
@JsonKey(ignore: true)
$SplashStateCopyWith<SplashState> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $SplashStateCopyWith<$Res> {
factory $SplashStateCopyWith(
SplashState value, $Res Function(SplashState) then) =
_$SplashStateCopyWithImpl<$Res>;
$Res call({AuthState auth});
$AuthStateCopyWith<$Res> get auth;
}
/// @nodoc
class _$SplashStateCopyWithImpl<$Res> implements $SplashStateCopyWith<$Res> {
_$SplashStateCopyWithImpl(this._value, this._then);
final SplashState _value;
// ignore: unused_field
final $Res Function(SplashState) _then;
@override
$Res call({
Object? auth = freezed,
}) {
return _then(_value.copyWith(
auth: auth == freezed
? _value.auth
: auth // ignore: cast_nullable_to_non_nullable
as AuthState,
));
}
@override
$AuthStateCopyWith<$Res> get auth {
return $AuthStateCopyWith<$Res>(_value.auth, (value) {
return _then(_value.copyWith(auth: value));
});
}
}
/// @nodoc
abstract class _$SplashStateCopyWith<$Res>
implements $SplashStateCopyWith<$Res> {
factory _$SplashStateCopyWith(
_SplashState value, $Res Function(_SplashState) then) =
__$SplashStateCopyWithImpl<$Res>;
@override
$Res call({AuthState auth});
@override
$AuthStateCopyWith<$Res> get auth;
}
/// @nodoc
class __$SplashStateCopyWithImpl<$Res> extends _$SplashStateCopyWithImpl<$Res>
implements _$SplashStateCopyWith<$Res> {
__$SplashStateCopyWithImpl(
_SplashState _value, $Res Function(_SplashState) _then)
: super(_value, (v) => _then(v as _SplashState));
@override
_SplashState get _value => super._value as _SplashState;
@override
$Res call({
Object? auth = freezed,
}) {
return _then(_SplashState(
auth: auth == freezed
? _value.auth
: auth // ignore: cast_nullable_to_non_nullable
as AuthState,
));
}
}
/// @nodoc
class _$_SplashState implements _SplashState {
const _$_SplashState({required this.auth});
@override
final AuthState auth;
@override
String toString() {
return 'SplashState(auth: $auth)';
}
@override
bool operator ==(dynamic other) {
return identical(this, other) ||
(other is _SplashState &&
(identical(other.auth, auth) ||
const DeepCollectionEquality().equals(other.auth, auth)));
}
@override
int get hashCode =>
runtimeType.hashCode ^ const DeepCollectionEquality().hash(auth);
@JsonKey(ignore: true)
@override
_$SplashStateCopyWith<_SplashState> get copyWith =>
__$SplashStateCopyWithImpl<_SplashState>(this, _$identity);
}
abstract class _SplashState implements SplashState {
const factory _SplashState({required AuthState auth}) = _$_SplashState;
@override
AuthState get auth => throw _privateConstructorUsedError;
@override
@JsonKey(ignore: true)
_$SplashStateCopyWith<_SplashState> get copyWith =>
throw _privateConstructorUsedError;
}
@@ -0,0 +1,121 @@
import 'dart:async';
import 'package:dartz/dartz.dart';
import 'package:flowy_sdk/protobuf/flowy-folder-data-model/workspace.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
import 'dart:typed_data';
import 'package:app_flowy/core/notification_helper.dart';
import 'package:flowy_infra/notifier.dart';
import 'package:flowy_sdk/protobuf/dart-notify/protobuf.dart';
import 'package:flowy_sdk/protobuf/flowy-folder/dart_notification.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-user-data-model/errors.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-user-data-model/user_profile.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-user/dart_notification.pb.dart' as user;
import 'package:flowy_sdk/rust_stream.dart';
typedef UserProfileNotifyValue = Either<UserProfile, FlowyError>;
typedef AuthNotifyValue = Either<Unit, FlowyError>;
typedef WorkspaceListNotifyValue = Either<List<Workspace>, FlowyError>;
typedef WorkspaceSettingNotifyValue = Either<CurrentWorkspaceSetting, FlowyError>;
class UserListener {
StreamSubscription<SubscribeObject>? _subscription;
final _profileNotifier = PublishNotifier<UserProfileNotifyValue>();
final _authNotifier = PublishNotifier<AuthNotifyValue>();
final _workspaceListNotifier = PublishNotifier<WorkspaceListNotifyValue>();
final _workSettingNotifier = PublishNotifier<WorkspaceSettingNotifyValue>();
FolderNotificationParser? _workspaceParser;
UserNotificationParser? _userParser;
final UserProfile _user;
UserListener({
required UserProfile user,
}) : _user = user;
void start({
void Function(AuthNotifyValue)? onAuthChanged,
void Function(UserProfileNotifyValue)? onProfileUpdated,
void Function(WorkspaceListNotifyValue)? onWorkspaceListUpdated,
void Function(WorkspaceSettingNotifyValue)? onWorkspaceSettingUpdated,
}) {
if (onAuthChanged != null) {
_authNotifier.addListener(() {
onAuthChanged(_authNotifier.currentValue!);
});
}
if (onProfileUpdated != null) {
_profileNotifier.addListener(() {
onProfileUpdated(_profileNotifier.currentValue!);
});
}
if (onWorkspaceListUpdated != null) {
_workspaceListNotifier.addListener(() {
onWorkspaceListUpdated(_workspaceListNotifier.currentValue!);
});
}
if (onWorkspaceSettingUpdated != null) {
_workSettingNotifier.addListener(() {
onWorkspaceSettingUpdated(_workSettingNotifier.currentValue!);
});
}
_workspaceParser = FolderNotificationParser(id: _user.token, callback: _notificationCallback);
_userParser = UserNotificationParser(id: _user.token, callback: _userNotificationCallback);
_subscription = RustStreamReceiver.listen((observable) {
_workspaceParser?.parse(observable);
_userParser?.parse(observable);
});
}
Future<void> stop() async {
_workspaceParser = null;
_userParser = null;
await _subscription?.cancel();
_profileNotifier.dispose();
_authNotifier.dispose();
_workspaceListNotifier.dispose();
}
void _notificationCallback(FolderNotification ty, Either<Uint8List, FlowyError> result) {
switch (ty) {
case FolderNotification.UserCreateWorkspace:
case FolderNotification.UserDeleteWorkspace:
case FolderNotification.WorkspaceListUpdated:
result.fold(
(payload) => _workspaceListNotifier.value = left(RepeatedWorkspace.fromBuffer(payload).items),
(error) => _workspaceListNotifier.value = right(error),
);
break;
case FolderNotification.WorkspaceSetting:
result.fold(
(payload) => _workSettingNotifier.value = left(CurrentWorkspaceSetting.fromBuffer(payload)),
(error) => _workSettingNotifier.value = right(error),
);
break;
case FolderNotification.UserUnauthorized:
result.fold(
(_) {},
(error) => _authNotifier.value = right(FlowyError.create()..code = ErrorCode.UserUnauthorized.value),
);
break;
default:
break;
}
}
void _userNotificationCallback(user.UserNotification ty, Either<Uint8List, FlowyError> result) {
switch (ty) {
case user.UserNotification.UserUnauthorized:
result.fold(
(payload) => _profileNotifier.value = left(UserProfile.fromBuffer(payload)),
(error) => _profileNotifier.value = right(error),
);
break;
default:
break;
}
}
}
@@ -0,0 +1,57 @@
import 'dart:async';
import 'package:dartz/dartz.dart';
import 'package:flowy_sdk/dispatch/dispatch.dart';
import 'package:flowy_sdk/protobuf/flowy-folder-data-model/workspace.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-user-data-model/user_profile.pb.dart';
class UserService {
Future<Either<UserProfile, FlowyError>> fetchUserProfile({required String userId}) {
return UserEventGetUserProfile().send();
}
Future<Either<Unit, FlowyError>> deleteWorkspace({required String workspaceId}) {
throw UnimplementedError();
}
Future<Either<Unit, FlowyError>> signOut() {
return UserEventSignOut().send();
}
Future<Either<Unit, FlowyError>> initUser() async {
return UserEventInitUser().send();
}
Future<Either<List<Workspace>, FlowyError>> getWorkspaces() {
final request = WorkspaceId.create();
return FolderEventReadWorkspaces(request).send().then((result) {
return result.fold(
(workspaces) => left(workspaces.items),
(error) => right(error),
);
});
}
Future<Either<Workspace, FlowyError>> openWorkspace(String workspaceId) {
final request = WorkspaceId.create()..value = workspaceId;
return FolderEventOpenWorkspace(request).send().then((result) {
return result.fold(
(workspace) => left(workspace),
(error) => right(error),
);
});
}
Future<Either<Workspace, FlowyError>> createWorkspace(String name, String desc) {
final request = CreateWorkspacePayload.create()
..name = name
..desc = desc;
return FolderEventCreateWorkspace(request).send().then((result) {
return result.fold(
(workspace) => left(workspace),
(error) => right(error),
);
});
}
}
@@ -4,7 +4,7 @@ import 'package:flowy_sdk/flowy_sdk.dart';
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-user-data-model/user_setting.pb.dart';
class UserSettingReppsitory {
class UserSettingsService {
Future<AppearanceSettings> getAppearanceSettings() async {
final result = await UserEventGetAppearanceSetting().send();
@@ -4,7 +4,7 @@ import 'package:freezed_annotation/freezed_annotation.dart';
part 'auth_state.freezed.dart';
@freezed
abstract class AuthState with _$AuthState {
class AuthState with _$AuthState {
const factory AuthState.authenticated(UserProfile userProfile) = Authenticated;
const factory AuthState.unauthenticated(FlowyError error) = Unauthenticated;
const factory AuthState.initial() = _Initial;
@@ -1,487 +0,0 @@
// coverage:ignore-file
// GENERATED CODE - DO NOT MODIFY BY HAND
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target
part of 'auth_state.dart';
// **************************************************************************
// FreezedGenerator
// **************************************************************************
T _$identity<T>(T value) => value;
final _privateConstructorUsedError = UnsupportedError(
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more informations: https://github.com/rrousselGit/freezed#custom-getters-and-methods');
/// @nodoc
class _$AuthStateTearOff {
const _$AuthStateTearOff();
Authenticated authenticated(UserProfile userProfile) {
return Authenticated(
userProfile,
);
}
Unauthenticated unauthenticated(FlowyError error) {
return Unauthenticated(
error,
);
}
_Initial initial() {
return const _Initial();
}
}
/// @nodoc
const $AuthState = _$AuthStateTearOff();
/// @nodoc
mixin _$AuthState {
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function(UserProfile userProfile) authenticated,
required TResult Function(FlowyError error) unauthenticated,
required TResult Function() initial,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({
TResult Function(UserProfile userProfile)? authenticated,
TResult Function(FlowyError error)? unauthenticated,
TResult Function()? initial,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function(UserProfile userProfile)? authenticated,
TResult Function(FlowyError error)? unauthenticated,
TResult Function()? initial,
required TResult orElse(),
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(Authenticated value) authenticated,
required TResult Function(Unauthenticated value) unauthenticated,
required TResult Function(_Initial value) initial,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>({
TResult Function(Authenticated value)? authenticated,
TResult Function(Unauthenticated value)? unauthenticated,
TResult Function(_Initial value)? initial,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(Authenticated value)? authenticated,
TResult Function(Unauthenticated value)? unauthenticated,
TResult Function(_Initial value)? initial,
required TResult orElse(),
}) =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $AuthStateCopyWith<$Res> {
factory $AuthStateCopyWith(AuthState value, $Res Function(AuthState) then) =
_$AuthStateCopyWithImpl<$Res>;
}
/// @nodoc
class _$AuthStateCopyWithImpl<$Res> implements $AuthStateCopyWith<$Res> {
_$AuthStateCopyWithImpl(this._value, this._then);
final AuthState _value;
// ignore: unused_field
final $Res Function(AuthState) _then;
}
/// @nodoc
abstract class $AuthenticatedCopyWith<$Res> {
factory $AuthenticatedCopyWith(
Authenticated value, $Res Function(Authenticated) then) =
_$AuthenticatedCopyWithImpl<$Res>;
$Res call({UserProfile userProfile});
}
/// @nodoc
class _$AuthenticatedCopyWithImpl<$Res> extends _$AuthStateCopyWithImpl<$Res>
implements $AuthenticatedCopyWith<$Res> {
_$AuthenticatedCopyWithImpl(
Authenticated _value, $Res Function(Authenticated) _then)
: super(_value, (v) => _then(v as Authenticated));
@override
Authenticated get _value => super._value as Authenticated;
@override
$Res call({
Object? userProfile = freezed,
}) {
return _then(Authenticated(
userProfile == freezed
? _value.userProfile
: userProfile // ignore: cast_nullable_to_non_nullable
as UserProfile,
));
}
}
/// @nodoc
class _$Authenticated implements Authenticated {
const _$Authenticated(this.userProfile);
@override
final UserProfile userProfile;
@override
String toString() {
return 'AuthState.authenticated(userProfile: $userProfile)';
}
@override
bool operator ==(dynamic other) {
return identical(this, other) ||
(other is Authenticated &&
(identical(other.userProfile, userProfile) ||
const DeepCollectionEquality()
.equals(other.userProfile, userProfile)));
}
@override
int get hashCode =>
runtimeType.hashCode ^ const DeepCollectionEquality().hash(userProfile);
@JsonKey(ignore: true)
@override
$AuthenticatedCopyWith<Authenticated> get copyWith =>
_$AuthenticatedCopyWithImpl<Authenticated>(this, _$identity);
@override
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function(UserProfile userProfile) authenticated,
required TResult Function(FlowyError error) unauthenticated,
required TResult Function() initial,
}) {
return authenticated(userProfile);
}
@override
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({
TResult Function(UserProfile userProfile)? authenticated,
TResult Function(FlowyError error)? unauthenticated,
TResult Function()? initial,
}) {
return authenticated?.call(userProfile);
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function(UserProfile userProfile)? authenticated,
TResult Function(FlowyError error)? unauthenticated,
TResult Function()? initial,
required TResult orElse(),
}) {
if (authenticated != null) {
return authenticated(userProfile);
}
return orElse();
}
@override
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(Authenticated value) authenticated,
required TResult Function(Unauthenticated value) unauthenticated,
required TResult Function(_Initial value) initial,
}) {
return authenticated(this);
}
@override
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>({
TResult Function(Authenticated value)? authenticated,
TResult Function(Unauthenticated value)? unauthenticated,
TResult Function(_Initial value)? initial,
}) {
return authenticated?.call(this);
}
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(Authenticated value)? authenticated,
TResult Function(Unauthenticated value)? unauthenticated,
TResult Function(_Initial value)? initial,
required TResult orElse(),
}) {
if (authenticated != null) {
return authenticated(this);
}
return orElse();
}
}
abstract class Authenticated implements AuthState {
const factory Authenticated(UserProfile userProfile) = _$Authenticated;
UserProfile get userProfile => throw _privateConstructorUsedError;
@JsonKey(ignore: true)
$AuthenticatedCopyWith<Authenticated> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $UnauthenticatedCopyWith<$Res> {
factory $UnauthenticatedCopyWith(
Unauthenticated value, $Res Function(Unauthenticated) then) =
_$UnauthenticatedCopyWithImpl<$Res>;
$Res call({FlowyError error});
}
/// @nodoc
class _$UnauthenticatedCopyWithImpl<$Res> extends _$AuthStateCopyWithImpl<$Res>
implements $UnauthenticatedCopyWith<$Res> {
_$UnauthenticatedCopyWithImpl(
Unauthenticated _value, $Res Function(Unauthenticated) _then)
: super(_value, (v) => _then(v as Unauthenticated));
@override
Unauthenticated get _value => super._value as Unauthenticated;
@override
$Res call({
Object? error = freezed,
}) {
return _then(Unauthenticated(
error == freezed
? _value.error
: error // ignore: cast_nullable_to_non_nullable
as FlowyError,
));
}
}
/// @nodoc
class _$Unauthenticated implements Unauthenticated {
const _$Unauthenticated(this.error);
@override
final FlowyError error;
@override
String toString() {
return 'AuthState.unauthenticated(error: $error)';
}
@override
bool operator ==(dynamic other) {
return identical(this, other) ||
(other is Unauthenticated &&
(identical(other.error, error) ||
const DeepCollectionEquality().equals(other.error, error)));
}
@override
int get hashCode =>
runtimeType.hashCode ^ const DeepCollectionEquality().hash(error);
@JsonKey(ignore: true)
@override
$UnauthenticatedCopyWith<Unauthenticated> get copyWith =>
_$UnauthenticatedCopyWithImpl<Unauthenticated>(this, _$identity);
@override
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function(UserProfile userProfile) authenticated,
required TResult Function(FlowyError error) unauthenticated,
required TResult Function() initial,
}) {
return unauthenticated(error);
}
@override
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({
TResult Function(UserProfile userProfile)? authenticated,
TResult Function(FlowyError error)? unauthenticated,
TResult Function()? initial,
}) {
return unauthenticated?.call(error);
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function(UserProfile userProfile)? authenticated,
TResult Function(FlowyError error)? unauthenticated,
TResult Function()? initial,
required TResult orElse(),
}) {
if (unauthenticated != null) {
return unauthenticated(error);
}
return orElse();
}
@override
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(Authenticated value) authenticated,
required TResult Function(Unauthenticated value) unauthenticated,
required TResult Function(_Initial value) initial,
}) {
return unauthenticated(this);
}
@override
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>({
TResult Function(Authenticated value)? authenticated,
TResult Function(Unauthenticated value)? unauthenticated,
TResult Function(_Initial value)? initial,
}) {
return unauthenticated?.call(this);
}
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(Authenticated value)? authenticated,
TResult Function(Unauthenticated value)? unauthenticated,
TResult Function(_Initial value)? initial,
required TResult orElse(),
}) {
if (unauthenticated != null) {
return unauthenticated(this);
}
return orElse();
}
}
abstract class Unauthenticated implements AuthState {
const factory Unauthenticated(FlowyError error) = _$Unauthenticated;
FlowyError get error => throw _privateConstructorUsedError;
@JsonKey(ignore: true)
$UnauthenticatedCopyWith<Unauthenticated> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class _$InitialCopyWith<$Res> {
factory _$InitialCopyWith(_Initial value, $Res Function(_Initial) then) =
__$InitialCopyWithImpl<$Res>;
}
/// @nodoc
class __$InitialCopyWithImpl<$Res> extends _$AuthStateCopyWithImpl<$Res>
implements _$InitialCopyWith<$Res> {
__$InitialCopyWithImpl(_Initial _value, $Res Function(_Initial) _then)
: super(_value, (v) => _then(v as _Initial));
@override
_Initial get _value => super._value as _Initial;
}
/// @nodoc
class _$_Initial implements _Initial {
const _$_Initial();
@override
String toString() {
return 'AuthState.initial()';
}
@override
bool operator ==(dynamic other) {
return identical(this, other) || (other is _Initial);
}
@override
int get hashCode => runtimeType.hashCode;
@override
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function(UserProfile userProfile) authenticated,
required TResult Function(FlowyError error) unauthenticated,
required TResult Function() initial,
}) {
return initial();
}
@override
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({
TResult Function(UserProfile userProfile)? authenticated,
TResult Function(FlowyError error)? unauthenticated,
TResult Function()? initial,
}) {
return initial?.call();
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function(UserProfile userProfile)? authenticated,
TResult Function(FlowyError error)? unauthenticated,
TResult Function()? initial,
required TResult orElse(),
}) {
if (initial != null) {
return initial();
}
return orElse();
}
@override
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(Authenticated value) authenticated,
required TResult Function(Unauthenticated value) unauthenticated,
required TResult Function(_Initial value) initial,
}) {
return initial(this);
}
@override
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>({
TResult Function(Authenticated value)? authenticated,
TResult Function(Unauthenticated value)? unauthenticated,
TResult Function(_Initial value)? initial,
}) {
return initial?.call(this);
}
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(Authenticated value)? authenticated,
TResult Function(Unauthenticated value)? unauthenticated,
TResult Function(_Initial value)? initial,
required TResult orElse(),
}) {
if (initial != null) {
return initial(this);
}
return orElse();
}
}
abstract class _Initial implements AuthState {
const factory _Initial() = _$_Initial;
}
@@ -1,29 +0,0 @@
import 'package:app_flowy/user/application/sign_in_bloc.dart';
import 'package:app_flowy/user/application/sign_up_bloc.dart';
import 'package:app_flowy/user/application/splash_bloc.dart';
import 'package:app_flowy/user/infrastructure/repos/auth_repo.dart';
import 'package:app_flowy/user/infrastructure/router.dart';
import 'package:app_flowy/workspace/application/edit_pannel/edit_pannel_bloc.dart';
import 'package:app_flowy/workspace/application/home/home_bloc.dart';
import 'package:get_it/get_it.dart';
import 'network_monitor.dart';
class UserDepsResolver {
static Future<void> resolve(GetIt getIt) async {
getIt.registerFactory<AuthRepository>(() => AuthRepository());
//Interface implementation
getIt.registerFactory<AuthRouter>(() => AuthRouter());
//Bloc
getIt.registerFactory<SignInBloc>(() => SignInBloc(getIt<AuthRepository>()));
getIt.registerFactory<SignUpBloc>(() => SignUpBloc(getIt<AuthRepository>()));
getIt.registerFactory<SplashRoute>(() => SplashRoute());
getIt.registerFactory<HomeBloc>(() => HomeBloc());
getIt.registerFactory<EditPannelBloc>(() => EditPannelBloc());
getIt.registerFactory<SplashBloc>(() => SplashBloc());
getIt.registerLazySingleton<NetworkMonitor>(() => NetworkMonitor());
}
}
@@ -1,10 +1,9 @@
import 'package:app_flowy/startup/startup.dart';
import 'package:app_flowy/user/infrastructure/repos/auth_repo.dart';
import 'package:app_flowy/user/application/auth_service.dart';
import 'package:app_flowy/user/presentation/sign_in_screen.dart';
import 'package:app_flowy/user/presentation/sign_up_screen.dart';
import 'package:app_flowy/user/presentation/skip_log_in_screen.dart';
import 'package:app_flowy/user/presentation/welcome_screen.dart';
import 'package:app_flowy/workspace/infrastructure/repos/user_repo.dart';
import 'package:app_flowy/workspace/presentation/home/home_screen.dart';
import 'package:flowy_infra/time/duration.dart';
import 'package:flowy_infra_ui/widget/route/animation.dart';
@@ -38,9 +37,8 @@ class AuthRouter {
}
class SplashRoute {
Future<void> pushWelcomeScreen(BuildContext context, UserProfile user) async {
final repo = UserRepo(user: user);
final screen = WelcomeScreen(repo: repo);
Future<void> pushWelcomeScreen(BuildContext context, UserProfile userProfile) async {
final screen = WelcomeScreen(userProfile: userProfile);
final workspaceId = await Navigator.of(context).push(
PageRoutes.fade(
() => screen,
@@ -48,7 +46,7 @@ class SplashRoute {
),
);
pushHomeScreen(context, repo.user, workspaceId);
pushHomeScreen(context, userProfile, workspaceId);
}
void pushHomeScreen(BuildContext context, UserProfile userProfile, CurrentWorkspaceSetting workspaceSetting) {
@@ -71,7 +69,7 @@ class SplashRoute {
PageRoutes.fade(
() => SkipLogInScreen(
router: getIt<AuthRouter>(),
authRepo: getIt<AuthRepository>(),
authService: getIt<AuthService>(),
),
RouteDurations.slow.inMilliseconds * .001),
);
@@ -1,6 +1,6 @@
import 'package:app_flowy/startup/startup.dart';
import 'package:app_flowy/user/application/sign_in_bloc.dart';
import 'package:app_flowy/user/infrastructure/router.dart';
import 'package:app_flowy/user/presentation/router.dart';
import 'package:app_flowy/user/presentation/widgets/background.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flowy_infra/size.dart';
@@ -170,11 +170,11 @@ class PasswordTextField extends StatelessWidget {
return RoundedInputField(
obscureText: true,
style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w500),
obscureIcon: svg("home/hide"),
obscureHideIcon: svg("home/show"),
obscureIcon: svgWidget("home/hide"),
obscureHideIcon: svgWidget("home/show"),
hintText: LocaleKeys.signIn_passwordHint.tr(),
normalBorderColor: theme.shader4,
highlightBorderColor: theme.red,
errorBorderColor: theme.red,
cursorColor: theme.main1,
errorText: context.read<SignInBloc>().state.passwordError.fold(() => "", (error) => error),
onChanged: (value) => context.read<SignInBloc>().add(SignInEvent.passwordChanged(value)),
@@ -199,7 +199,7 @@ class EmailTextField extends StatelessWidget {
hintText: LocaleKeys.signIn_emailHint.tr(),
style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w500),
normalBorderColor: theme.shader4,
highlightBorderColor: theme.red,
errorBorderColor: theme.red,
cursorColor: theme.main1,
errorText: context.read<SignInBloc>().state.emailError.fold(() => "", (error) => error),
onChanged: (value) => context.read<SignInBloc>().add(SignInEvent.emailChanged(value)),
@@ -1,6 +1,6 @@
import 'package:app_flowy/startup/startup.dart';
import 'package:app_flowy/user/application/sign_up_bloc.dart';
import 'package:app_flowy/user/infrastructure/router.dart';
import 'package:app_flowy/user/presentation/router.dart';
import 'package:app_flowy/user/presentation/widgets/background.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flowy_infra/theme.dart';
@@ -134,12 +134,12 @@ class PasswordTextField extends StatelessWidget {
builder: (context, state) {
return RoundedInputField(
obscureText: true,
obscureIcon: svg("home/hide"),
obscureHideIcon: svg("home/show"),
obscureIcon: svgWidget("home/hide"),
obscureHideIcon: svgWidget("home/show"),
style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w500),
hintText: LocaleKeys.signUp_passwordHint.tr(),
normalBorderColor: theme.shader4,
highlightBorderColor: theme.red,
errorBorderColor: theme.red,
cursorColor: theme.main1,
errorText: context.read<SignUpBloc>().state.passwordError.fold(() => "", (error) => error),
onChanged: (value) => context.read<SignUpBloc>().add(SignUpEvent.passwordChanged(value)),
@@ -162,12 +162,12 @@ class RepeatPasswordTextField extends StatelessWidget {
builder: (context, state) {
return RoundedInputField(
obscureText: true,
obscureIcon: svg("home/hide"),
obscureHideIcon: svg("home/show"),
obscureIcon: svgWidget("home/hide"),
obscureHideIcon: svgWidget("home/show"),
style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w500),
hintText: LocaleKeys.signUp_repeatPasswordHint.tr(),
normalBorderColor: theme.shader4,
highlightBorderColor: theme.red,
errorBorderColor: theme.red,
cursorColor: theme.main1,
errorText: context.read<SignUpBloc>().state.repeatPasswordError.fold(() => "", (error) => error),
onChanged: (value) => context.read<SignUpBloc>().add(SignUpEvent.repeatPasswordChanged(value)),
@@ -192,7 +192,7 @@ class EmailTextField extends StatelessWidget {
hintText: LocaleKeys.signUp_emailHint.tr(),
style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w500),
normalBorderColor: theme.shader4,
highlightBorderColor: theme.red,
errorBorderColor: theme.red,
cursorColor: theme.main1,
errorText: context.read<SignUpBloc>().state.emailError.fold(() => "", (error) => error),
onChanged: (value) => context.read<SignUpBloc>().add(SignUpEvent.emailChanged(value)),
@@ -1,14 +1,14 @@
import 'package:app_flowy/user/infrastructure/router.dart';
import 'package:app_flowy/user/infrastructure/repos/auth_repo.dart';
import 'package:app_flowy/user/application/auth_service.dart';
import 'package:app_flowy/user/application/user_listener.dart';
import 'package:app_flowy/user/presentation/router.dart';
import 'package:app_flowy/user/presentation/widgets/background.dart';
import 'package:app_flowy/workspace/infrastructure/repos/user_repo.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flowy_infra/size.dart';
import 'package:flowy_infra/theme.dart';
import 'package:flowy_infra/uuid.dart';
import 'package:flowy_infra_ui/widget/rounded_button.dart';
import 'package:flowy_infra_ui/widget/spacing.dart';
import 'package:flowy_log/flowy_log.dart';
import 'package:flowy_sdk/log.dart';
import 'package:flowy_sdk/dispatch/dispatch.dart';
import 'package:flowy_sdk/protobuf/flowy-folder-data-model/protobuf.dart';
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
@@ -21,12 +21,12 @@ import 'package:app_flowy/generated/locale_keys.g.dart';
class SkipLogInScreen extends StatefulWidget {
final AuthRouter router;
final AuthRepository authRepo;
final AuthService authService;
const SkipLogInScreen({
Key? key,
required this.router,
required this.authRepo,
required this.authService,
}) : super(key: key);
@override
@@ -88,8 +88,9 @@ class _SkipLogInScreenState extends State<SkipLogInScreen> {
}
_launchURL(String url) async {
if (await canLaunch(url)) {
await launch(url);
final uri = Uri.parse(url);
if (await canLaunchUrl(uri)) {
await launchUrl(uri);
} else {
throw 'Could not launch $url';
}
@@ -99,7 +100,7 @@ class _SkipLogInScreenState extends State<SkipLogInScreen> {
const password = "AppFlowy123@";
final uid = uuid();
final userEmail = "$uid@appflowy.io";
final result = await widget.authRepo.signUp(
final result = await widget.authService.signUp(
name: LocaleKeys.defaultUsername.tr(),
password: password,
email: userEmail,
@@ -1,10 +1,10 @@
import 'package:app_flowy/startup/startup.dart';
import 'package:app_flowy/user/application/splash_bloc.dart';
import 'package:app_flowy/user/domain/auth_state.dart';
import 'package:app_flowy/user/infrastructure/router.dart';
import 'package:flowy_log/flowy_log.dart';
import 'package:app_flowy/user/presentation/router.dart';
import 'package:flowy_sdk/log.dart';
import 'package:flowy_sdk/dispatch/dispatch.dart';
import 'package:flowy_sdk/protobuf/flowy-folder-data-model/errors.pb.dart';
import 'package:flowy_sdk/protobuf/error-code/error_code.pbenum.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
@@ -6,22 +6,22 @@ import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart';
import 'package:flowy_infra_ui/style_widget/button.dart';
import 'package:flowy_infra_ui/widget/error_page.dart';
import 'package:flowy_sdk/protobuf/flowy-folder-data-model/workspace.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-user-data-model/user_profile.pb.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:app_flowy/workspace/infrastructure/repos/user_repo.dart';
import 'package:app_flowy/generated/locale_keys.g.dart';
class WelcomeScreen extends StatelessWidget {
final UserRepo repo;
final UserProfile userProfile;
const WelcomeScreen({
Key? key,
required this.repo,
required this.userProfile,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (_) => getIt<WelcomeBloc>(param1: repo.user)..add(const WelcomeEvent.initial()),
create: (_) => getIt<WelcomeBloc>(param1: userProfile)..add(const WelcomeEvent.initial()),
child: BlocBuilder<WelcomeBloc, WelcomeState>(
builder: (context, state) {
return Scaffold(
@@ -44,7 +44,7 @@ class FlowyLogoTitle extends StatelessWidget {
children: [
SizedBox.fromSize(
size: logoSize,
child: svg("flowy_logo"),
child: svgWidget("flowy_logo"),
),
const VSpace(30),
Text(
@@ -1,8 +1,16 @@
import 'package:app_flowy/workspace/infrastructure/repos/app_repo.dart';
import 'package:flowy_log/flowy_log.dart';
import 'dart:collection';
import 'package:app_flowy/plugin/plugin.dart';
import 'package:app_flowy/startup/startup.dart';
import 'package:app_flowy/workspace/application/app/app_listener.dart';
import 'package:app_flowy/workspace/application/app/app_service.dart';
import 'package:app_flowy/workspace/presentation/home/menu/menu.dart';
import 'package:expandable/expandable.dart';
import 'package:flowy_sdk/log.dart';
import 'package:flowy_sdk/protobuf/flowy-folder-data-model/app.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
import 'package:flutter/foundation.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:dartz/dartz.dart';
@@ -10,64 +18,92 @@ import 'package:dartz/dartz.dart';
part 'app_bloc.freezed.dart';
class AppBloc extends Bloc<AppEvent, AppState> {
final AppRepository repo;
final AppListener listener;
AppBloc({required App app, required this.repo, required this.listener}) : super(AppState.initial(app)) {
final App app;
final AppService appService;
final AppListener appListener;
AppBloc({required this.app, required this.appService, required this.appListener}) : super(AppState.initial(app)) {
on<AppEvent>((event, emit) async {
await event.map(initial: (e) async {
listener.startListening(
viewsChanged: _handleViewsChanged,
appUpdated: (app) => add(AppEvent.appDidUpdate(app)),
);
await _fetchViews(emit);
_startListening();
await _loadViews(emit);
}, createView: (CreateView value) async {
final viewOrFailed = await repo.createView(name: value.name, desc: value.desc, viewType: value.viewType);
viewOrFailed.fold(
(view) => emit(state.copyWith(
latestCreatedView: view,
successOrFailure: left(unit),
)),
(error) {
Log.error(error);
emit(state.copyWith(successOrFailure: right(error)));
},
);
}, didReceiveViews: (e) async {
await handleDidReceiveViews(e.views, emit);
await _createView(value, emit);
}, didReceiveViewUpdated: (e) async {
await _didReceiveViewUpdated(e.views, emit);
}, delete: (e) async {
final result = await repo.delete();
result.fold(
(unit) => emit(state.copyWith(successOrFailure: left(unit))),
(error) => emit(state.copyWith(successOrFailure: right(error))),
);
await _deleteView(emit);
}, rename: (e) async {
final result = await repo.updateApp(name: e.newName);
result.fold(
(l) => emit(state.copyWith(successOrFailure: left(unit))),
(error) => emit(state.copyWith(successOrFailure: right(error))),
);
await _renameView(e, emit);
}, appDidUpdate: (e) async {
emit(state.copyWith(app: e.app));
});
});
}
@override
Future<void> close() async {
await listener.close();
return super.close();
}
void _handleViewsChanged(Either<List<View>, FlowyError> result) {
result.fold(
(views) => add(AppEvent.didReceiveViews(views)),
(error) {
Log.error(error);
void _startListening() {
appListener.start(
onViewsChanged: (result) {
result.fold(
(views) {
if (!isClosed) {
add(AppEvent.didReceiveViewUpdated(views));
}
},
(error) => Log.error(error),
);
},
onAppUpdated: (app) {
if (!isClosed) {
add(AppEvent.appDidUpdate(app));
}
},
);
}
Future<void> handleDidReceiveViews(List<View> views, Emitter<AppState> emit) async {
Future<void> _renameView(Rename e, Emitter<AppState> emit) async {
final result = await appService.updateApp(appId: app.id, name: e.newName);
result.fold(
(l) => emit(state.copyWith(successOrFailure: left(unit))),
(error) => emit(state.copyWith(successOrFailure: right(error))),
);
}
Future<void> _deleteView(Emitter<AppState> emit) async {
final result = await appService.delete(appId: app.id);
result.fold(
(unit) => emit(state.copyWith(successOrFailure: left(unit))),
(error) => emit(state.copyWith(successOrFailure: right(error))),
);
}
Future<void> _createView(CreateView value, Emitter<AppState> emit) async {
final viewOrFailed = await appService.createView(
appId: app.id,
name: value.name,
desc: value.desc,
dataType: value.dataType,
pluginType: value.pluginType,
);
viewOrFailed.fold(
(view) => emit(state.copyWith(
latestCreatedView: view,
successOrFailure: left(unit),
)),
(error) {
Log.error(error);
emit(state.copyWith(successOrFailure: right(error)));
},
);
}
@override
Future<void> close() async {
await appListener.stop();
return super.close();
}
Future<void> _didReceiveViewUpdated(List<View> views, Emitter<AppState> emit) async {
final latestCreatedView = state.latestCreatedView;
AppState newState = state.copyWith(views: views);
if (latestCreatedView != null) {
@@ -80,10 +116,10 @@ class AppBloc extends Bloc<AppEvent, AppState> {
emit(newState);
}
Future<void> _fetchViews(Emitter<AppState> emit) async {
final viewsOrFailed = await repo.getViews();
Future<void> _loadViews(Emitter<AppState> emit) async {
final viewsOrFailed = await appService.getViews(appId: app.id);
viewsOrFailed.fold(
(apps) => emit(state.copyWith(views: apps)),
(views) => emit(state.copyWith(views: views)),
(error) {
Log.error(error);
emit(state.copyWith(successOrFailure: right(error)));
@@ -95,10 +131,15 @@ class AppBloc extends Bloc<AppEvent, AppState> {
@freezed
class AppEvent with _$AppEvent {
const factory AppEvent.initial() = Initial;
const factory AppEvent.createView(String name, String desc, ViewType viewType) = CreateView;
const factory AppEvent.createView(
String name,
String desc,
PluginDataType dataType,
PluginType pluginType,
) = CreateView;
const factory AppEvent.delete() = Delete;
const factory AppEvent.rename(String newName) = Rename;
const factory AppEvent.didReceiveViews(List<View> views) = ReceiveViews;
const factory AppEvent.didReceiveViewUpdated(List<View> views) = ReceiveViews;
const factory AppEvent.appDidUpdate(App app) = AppDidUpdate;
}
@@ -106,17 +147,102 @@ class AppEvent with _$AppEvent {
class AppState with _$AppState {
const factory AppState({
required App app,
required bool isLoading,
required List<View>? views,
required List<View> views,
View? latestCreatedView,
required Either<Unit, FlowyError> successOrFailure,
}) = _AppState;
factory AppState.initial(App app) => AppState(
app: app,
isLoading: false,
views: null,
latestCreatedView: null,
views: [],
successOrFailure: left(unit),
);
}
class AppViewDataContext extends ChangeNotifier {
final String appId;
final ValueNotifier<List<View>> _viewsNotifier = ValueNotifier([]);
final ValueNotifier<View?> _selectedViewNotifier = ValueNotifier(null);
VoidCallback? _menuSharedStateListener;
ExpandableController expandController = ExpandableController(initialExpanded: false);
AppViewDataContext({required this.appId}) {
_setLatestView(getIt<MenuSharedState>().latestOpenView);
_menuSharedStateListener = getIt<MenuSharedState>().addLatestViewListener((view) {
_setLatestView(view);
});
}
VoidCallback addSelectedViewChangeListener(void Function(View?) callback) {
listener() {
callback(_selectedViewNotifier.value);
}
_selectedViewNotifier.addListener(listener);
return listener;
}
void removeSelectedViewListener(VoidCallback listener) {
_selectedViewNotifier.removeListener(listener);
}
void _setLatestView(View? view) {
view?.freeze();
if (_selectedViewNotifier.value != view) {
_selectedViewNotifier.value = view;
_expandIfNeed();
notifyListeners();
}
}
View? get selectedView => _selectedViewNotifier.value;
set views(List<View> views) {
if (_viewsNotifier.value != views) {
_viewsNotifier.value = views;
_expandIfNeed();
notifyListeners();
}
}
UnmodifiableListView<View> get views => UnmodifiableListView(_viewsNotifier.value);
VoidCallback addViewsChangeListener(void Function(UnmodifiableListView<View>) callback) {
listener() {
callback(views);
}
_viewsNotifier.addListener(listener);
return listener;
}
void removeViewsListener(VoidCallback listener) {
_viewsNotifier.removeListener(listener);
}
void _expandIfNeed() {
if (_selectedViewNotifier.value == null) {
return;
}
if (!_viewsNotifier.value.contains(_selectedViewNotifier.value)) {
return;
}
if (expandController.expanded == false) {
// Workaround: Delay 150 milliseconds to make the smooth animation while expanding
Future.delayed(const Duration(milliseconds: 150), () {
expandController.expanded = true;
});
}
}
@override
void dispose() {
if (_menuSharedStateListener != null) {
getIt<MenuSharedState>().removeLatestViewListener(_menuSharedStateListener!);
}
super.dispose();
}
}
File diff suppressed because it is too large. Load diff
@@ -1,67 +1,14 @@
import 'dart:async';
import 'dart:typed_data';
import 'package:dartz/dartz.dart';
import 'package:flowy_log/flowy_log.dart';
import 'package:flowy_sdk/dispatch/dispatch.dart';
import 'package:app_flowy/core/notification_helper.dart';
import 'package:flowy_sdk/log.dart';
import 'package:flowy_sdk/protobuf/dart-notify/subject.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-folder-data-model/app.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-folder/dart_notification.pb.dart';
import 'package:flowy_sdk/rust_stream.dart';
import 'helper.dart';
class AppRepository {
String appId;
AppRepository({
required this.appId,
});
Future<Either<App, FlowyError>> getAppDesc() {
final request = QueryAppRequest.create()..appIds.add(appId);
return FolderEventReadApp(request).send();
}
Future<Either<View, FlowyError>> createView({
required String name,
required String desc,
required ViewType viewType,
}) {
final request = CreateViewRequest.create()
..belongToId = appId
..name = name
..desc = desc
..viewType = viewType;
return FolderEventCreateView(request).send();
}
Future<Either<List<View>, FlowyError>> getViews() {
final request = QueryAppRequest.create()..appIds.add(appId);
return FolderEventReadApp(request).send().then((result) {
return result.fold(
(app) => left(app.belongings.items),
(error) => right(error),
);
});
}
Future<Either<Unit, FlowyError>> delete() {
final request = QueryAppRequest.create()..appIds.add(appId);
return FolderEventDeleteApp(request).send();
}
Future<Either<Unit, FlowyError>> updateApp({String? name}) {
UpdateAppRequest request = UpdateAppRequest.create()..appId = appId;
if (name != null) {
request.name = name;
}
return FolderEventUpdateApp(request).send();
}
}
typedef AppDidUpdateCallback = void Function(App app);
typedef ViewsDidChangeCallback = void Function(Either<List<View>, FlowyError> viewsOrFailed);
@@ -70,18 +17,18 @@ class AppListener {
StreamSubscription<SubscribeObject>? _subscription;
ViewsDidChangeCallback? _viewsChanged;
AppDidUpdateCallback? _updated;
late FolderNotificationParser _parser;
FolderNotificationParser? _parser;
String appId;
AppListener({
required this.appId,
});
void startListening({ViewsDidChangeCallback? viewsChanged, AppDidUpdateCallback? appUpdated}) {
_viewsChanged = viewsChanged;
_updated = appUpdated;
void start({ViewsDidChangeCallback? onViewsChanged, AppDidUpdateCallback? onAppUpdated}) {
_viewsChanged = onViewsChanged;
_updated = onAppUpdated;
_parser = FolderNotificationParser(id: appId, callback: _bservableCallback);
_subscription = RustStreamReceiver.listen((observable) => _parser.parse(observable));
_subscription = RustStreamReceiver.listen((observable) => _parser?.parse(observable));
}
void _bservableCallback(FolderNotification ty, Either<Uint8List, FlowyError> result) {
@@ -113,7 +60,8 @@ class AppListener {
}
}
Future<void> close() async {
Future<void> stop() async {
_parser = null;
await _subscription?.cancel();
_viewsChanged = null;
_updated = null;
@@ -0,0 +1,78 @@
import 'dart:async';
import 'package:dartz/dartz.dart';
import 'package:flowy_sdk/dispatch/dispatch.dart';
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-folder-data-model/app.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart';
import 'package:app_flowy/plugin/plugin.dart';
class AppService {
final String appId;
AppService({
required this.appId,
});
Future<Either<App, FlowyError>> getAppDesc({required String appId}) {
final payload = AppId.create()..value = appId;
return FolderEventReadApp(payload).send();
}
Future<Either<View, FlowyError>> createView({
required String appId,
required String name,
required String desc,
required PluginDataType dataType,
required PluginType pluginType,
}) {
final payload = CreateViewPayload.create()
..belongToId = appId
..name = name
..desc = desc
..dataType = dataType
..pluginType = pluginType;
return FolderEventCreateView(payload).send();
}
Future<Either<List<View>, FlowyError>> getViews({required String appId}) {
final payload = AppId.create()..value = appId;
return FolderEventReadApp(payload).send().then((result) {
return result.fold(
(app) => left(app.belongings.items),
(error) => right(error),
);
});
}
Future<Either<Unit, FlowyError>> delete({required String appId}) {
final request = AppId.create()..value = appId;
return FolderEventDeleteApp(request).send();
}
Future<Either<Unit, FlowyError>> updateApp({required String appId, String? name}) {
UpdateAppPayload payload = UpdateAppPayload.create()..appId = appId;
if (name != null) {
payload.name = name;
}
return FolderEventUpdateApp(payload).send();
}
Future<Either<Unit, FlowyError>> moveView({
required String viewId,
required int fromIndex,
required int toIndex,
}) {
final payload = MoveFolderItemPayload.create()
..itemId = viewId
..from = fromIndex
..to = toIndex
..ty = MoveFolderItemType.MoveView;
return FolderEventMoveFolderItem(payload).send();
}
}
@@ -0,0 +1,3 @@
export 'app_bloc.dart';
export 'app_listener.dart';
export 'app_service.dart';
Loaded 100 of 799 files, more files were not shown because too many files have changed in this diff. Show more