Compare commits

..

287 Commits

Author SHA1 Message Date
himself65
32f064c2de v0.7.0-canary.13 2023-06-13 14:13:38 +08:00
himself65
39704bc812 build: fix generate-assets.mjs 2023-06-13 14:12:08 +08:00
Himself65
a421265483 fix: remove unused hooks (#2762) 2023-06-13 12:18:32 +08:00
himself65
e6214cb6ec v0.7.0-canary.12 2023-06-13 11:00:39 +08:00
himself65
ba7d34bce5 docs: update thanks section in README.md 2023-06-13 10:45:52 +08:00
Himself65
ace3c37fcc feat: improve copilot (#2758) 2023-06-13 10:29:04 +08:00
Peng Xiao
5ba2dff008 feat: add helper process (#2753) 2023-06-13 10:01:43 +08:00
Himself65
dff8a0db7d fix: nx build input (#2755) 2023-06-12 13:06:23 +08:00
himself65
ccda45bdd2 build: fix nx.json 2023-06-12 12:05:00 +08:00
Himself65
eeb536d460 feat: use nx to manage monorepo (#2748) 2023-06-10 00:46:24 +08:00
Peng Xiao
1e6e0336c3 fix: electron dev crash (#2746) 2023-06-09 08:47:14 +00:00
Himself65
f2ac2e5b84 feat: isolated plugin system (#2742) 2023-06-09 16:43:46 +08:00
Himself65
af6f431c15 fix: replace noop function (#2744) 2023-06-09 16:00:44 +08:00
Peng Xiao
01ae21e1fa feat: add kalam font (#2743) 2023-06-09 15:48:30 +08:00
LongYinan
34141958eb style: remove some verbose codes (#2741) 2023-06-09 14:55:41 +08:00
JimmFly
c194cff0bd chore: remove en.json code owner (#2740) 2023-06-09 13:24:25 +08:00
Himself65
6b6f2d6910 chore: upgrade yarn (#2739) 2023-06-09 12:33:52 +08:00
LongYinan
2e975e79dd style: add ban-ts-comment rule (#2738) 2023-06-09 11:55:23 +08:00
Himself65
c5a295a87b chore: bump typescript to 5.1.3 (#2735)
Co-authored-by: LongYinan <lynweklm@gmail.com>
2023-06-09 11:42:54 +08:00
himself65
119b4cdf10 v0.7.0-canary.11 2023-06-09 11:30:51 +08:00
Himself65
bf6af934f6 fix: regression on the database and bookmark block (#2737) 2023-06-09 11:29:52 +08:00
Himself65
1971749449 test: add test cases for page setting atom (#2736) 2023-06-09 02:00:09 +08:00
Himself65
b383ce36cd build: enhance tsconfig type check (#2732) 2023-06-09 01:42:58 +08:00
Himself65
fc9a9f479b fix: page meta is undefined (#2734) 2023-06-09 01:19:16 +08:00
himself65
227174db1b build: fix eslint config 2023-06-09 01:11:53 +08:00
Himself65
9f129075dd feat: add page setting atom (#2725) 2023-06-09 00:58:46 +08:00
Peng Xiao
935b4f847c fix: potential flaky issues (#2733) 2023-06-09 00:20:12 +08:00
Whitewater
ec99a0ce05 feat: update desc for empty page (#2710) 2023-06-08 20:28:37 +08:00
Himself65
7ba5f82aef chore: bump blocksuite to 0.0.0-20230607055421-9b20fcaf-nightly (#2731) 2023-06-08 20:27:12 +08:00
Peng Xiao
546d5764e6 fix: a potential crash on fav list (#2716) 2023-06-08 20:06:15 +08:00
himself65
6f411bd459 v0.7.0-canary.10 2023-06-08 18:33:14 +08:00
JimmFly
29d8f61c90 feat: add date picker (#2644)
Co-authored-by: himself65 <himself65@outlook.com>
2023-06-08 17:55:16 +08:00
Peng Xiao
bedf838fe5 feat: add new rule for floating promise (#2726)
Co-authored-by: Himself65 <himself65@outlook.com>
2023-06-08 17:54:25 +08:00
Qi
fda89b05e7 feat: replace electron to puppeteer (#2700)
Co-authored-by: himself65 <himself65@outlook.com>
2023-06-08 17:51:45 +08:00
himself65
de8af5f114 revert: page jump once 2023-06-08 16:54:42 +08:00
himself65
14db45ae95 build: fix the directory path on webstorm 2023-06-08 16:26:09 +08:00
Himself65
27b14af388 test: fix flaky on local-first-workspace-list.spec.ts (#2727) 2023-06-08 16:18:10 +08:00
LongYinan
18dc427bc3 style: enable no-non-null-assertion rule (#2723)
Co-authored-by: Peng Xiao <pengxiao@outlook.com>
2023-06-08 07:23:20 +00:00
Himself65
1ad2e629ac refactor: project tsconfig & abstract infra type (#2721) 2023-06-08 12:41:47 +08:00
Himself65
05288be934 fix: flaky when drag workspace list (#2724) 2023-06-08 11:51:02 +08:00
Himself65
05b73a59be fix: first page default mode (#2719)
Co-authored-by: tzhangchi <c@affine.pro>
2023-06-08 10:17:27 +08:00
Himself65
f3fd5ff76b feat: add infra code (#2718) 2023-06-08 09:41:20 +08:00
Himself65
4958d096b0 fix: move workspace to top level (#2717) 2023-06-07 23:20:35 +08:00
Himself65
7f2006488e fix: type import (#2715) 2023-06-07 22:47:02 +08:00
Peng Xiao
008a05a470 fix(electron): should not continue pull when db closed (#2709) 2023-06-07 18:01:59 +08:00
himself65
3d7721d59d v0.7.0-canary.9 2023-06-07 17:59:55 +08:00
Flrande
35fb10c95b feat: add preloading template (#2655)
Co-authored-by: Himself65 <himself65@outlook.com>
2023-06-07 17:31:54 +08:00
Himself65
c4c4ec6a67 refactor: split storybook (#2706) 2023-06-07 16:55:06 +08:00
Himself65
f4be15baec fix: package affine/env modules (#2707) 2023-06-07 16:31:05 +08:00
himself65
17b40b68df docs: update README.md 2023-06-07 16:29:37 +08:00
Himself65
cd5c4b5cb7 fix: remove dependencies in @affine/debug (#2708) 2023-06-07 15:41:42 +08:00
LongYinan
d28c887237 feat(native): move sqlite operation into Rust (#2497)
Co-authored-by: Peng Xiao <pengxiao@outlook.com>
2023-06-07 14:52:19 +08:00
himself65
541011ba90 build: remove unused reference 2023-06-07 14:21:21 +08:00
wonderl17
fc658f4a95 fix: add bookmark operation flag for ts check (#2699) 2023-06-07 10:18:19 +08:00
Peng Xiao
84f68fc2c0 fix: import workspace may only show default preload page (#2685) 2023-06-06 14:42:50 +08:00
JimmFly
f78760cb83 fix: empty svg color missing (#2692) 2023-06-06 04:45:34 +00:00
Himself65
8f6db00402 feat: init window.affine (#2682) 2023-06-06 11:43:34 +08:00
Peng Xiao
d00d0bd951 fix: the top padding should be draggable (#2688) 2023-06-06 11:12:00 +08:00
Peng Xiao
8f5cd13e78 fix: do not show deleted reference (#2689) 2023-06-06 10:36:58 +08:00
Whitewater
3b4cfc642f fix: overflow in radio button group (#2687) 2023-06-05 10:18:53 +00:00
JimmFly
5807f34935 fix: empty icon color error (#2686) 2023-06-05 10:06:17 +00:00
Whitewater
efae4cccd6 feat: sticky table head in page list (#2668)
Co-authored-by: Himself65 <himself65@outlook.com>
2023-06-05 07:43:24 +00:00
Himself65
b461a684ad chore: bump version (#2681) 2023-06-05 01:00:41 +08:00
3720
b95808a052 test: add some e2e tests for all pages filter (#2674) 2023-06-04 23:34:16 +08:00
Himself65
1716e7a397 fix: use react-resizable-panels (#2679) 2023-06-04 23:33:36 +08:00
Himself65
acda594cba refactor: use esbuild instead of vite (#2672) 2023-06-02 13:22:09 +00:00
Himself65
94d20f1bdc feat: plugin system with isolated bundles (#2660) 2023-06-02 16:28:47 +08:00
Vlad Cuciureanu
f9079bb681 fix: README typo 2023-06-02 15:47:09 +08:00
himself65
0d07ff2390 v0.7.0-canary.8 2023-06-02 13:02:48 +08:00
xiaodong zuo
42bab6990e fix: update version bump-blocksuite (#2658) 2023-06-02 11:16:31 +08:00
fourdim
89a566a645 fix: pdf export in client and hide png export (#2604) 2023-06-01 13:26:57 +00:00
LongYinan
7af5bd3894 v0.7.0-canary.7 2023-06-01 19:11:12 +08:00
Peng Xiao
a57c27679d chore: bump blocksuite (#2652) 2023-06-01 10:55:10 +00:00
JimmFly
68a72b2dfc chore: update whats new link (#2651) 2023-06-01 17:59:30 +08:00
LongYinan
602f795133 build: prevent tsconfig includes sources outside (#2643) 2023-06-01 17:08:14 +08:00
himself65
5df89a925b v0.7.0-canary.6 2023-06-01 15:34:08 +07:00
Whitewater
23126e1ff6 fix: show table head when no item in page list (#2642) 2023-06-01 16:31:51 +08:00
xiaodong zuo
e1f715f837 chore: update blocksuite to 0.0.0-20230601062752-68dbf1a4-nightly (#2641) 2023-06-01 16:25:54 +08:00
himself65
fbcaed40e7 fix: block hub not working in the editor 2023-06-01 14:32:41 +08:00
JimmFly
88757ce488 chore: update all page style (#2638) 2023-06-01 12:38:14 +08:00
Simon He
fc9462eee9 perf: getEnvironment() -> env (#2636) 2023-06-01 03:23:38 +00:00
Qi
e1314730be feat: support get dynamic page meta data (#2632) 2023-06-01 11:03:16 +08:00
Peng Xiao
36978dbed6 fix: plugin bootstrap (#2631)
Co-authored-by: himself65 <himself65@outlook.com>
2023-06-01 01:14:37 +08:00
Whitewater
53d1991211 chore: update page group naming (#2628) 2023-05-31 16:41:25 +00:00
LongYinan
1ea445ab15 build: perform TypeCheck for all packages (#2573)
Co-authored-by: himself65 <himself65@outlook.com>
Co-authored-by: Peng Xiao <pengxiao@outlook.com>
2023-05-31 12:49:56 +00:00
Himself65
78410f531a chore: bump version (#2627) 2023-05-31 18:16:18 +08:00
himself65
96c0321696 v0.7.0-canary.5 2023-05-31 17:34:21 +08:00
himself65
0895f1fb30 ci: enable bookmark block in canary 2023-05-31 17:33:11 +08:00
himself65
b6188f4b11 docs: update logo in README.md 2023-05-31 17:23:01 +08:00
JimmFly
2ed1a7b219 chore: update filter style (#2625) 2023-05-31 17:20:18 +08:00
Himself65
9bee6bd5cc docs: update logo (#2626) 2023-05-31 17:16:50 +08:00
himself65
198f30c86d docs: update README.md 2023-05-31 17:12:27 +08:00
Himself65
454f1887cf feat: add @affine/bookmark-block plugin (#2618) 2023-05-31 17:08:03 +08:00
himself65
4e1e4e9435 v0.7.0-canary.4 2023-05-31 16:47:16 +08:00
3720
f7768563e1 fix: wrong use of dayjs (#2624) 2023-05-31 16:46:36 +08:00
Himself65
6aa0e71b84 chore: bump blocksuite to 0.0.0-20230531080915-ca9c55a2-nightly (#2622) 2023-05-31 16:32:35 +08:00
himself65
f1b3a10969 test: fix mouse click down timeout 2023-05-31 16:22:43 +08:00
Whitewater
90e70ed986 fix: drag delay (#2621) 2023-05-31 16:21:50 +08:00
xiaodong zuo
094a479c2a fix: remove the feature of exporting pdf/png (#2619)
Co-authored-by: himself65 <himself65@outlook.com>
2023-05-31 16:20:42 +08:00
Whitewater
20f1d487c8 feat: add page preview (#2620) 2023-05-31 08:18:48 +00:00
himself65
4c9bda1406 v0.7.0-canary.3 2023-05-31 15:41:52 +08:00
JimmFly
d5debc0bf5 chore: update filter style (#2617)
Co-authored-by: Himself65 <himself65@outlook.com>
2023-05-31 15:41:16 +08:00
Peng Xiao
f5aee7c360 fix: unify sidebar switch (#2616) 2023-05-31 07:06:13 +00:00
Himself65
248cd9a8ab chore: prohibit import package itself (#2612)
Co-authored-by: Whitewater <me@waterwater.moe>
2023-05-31 15:00:50 +08:00
Himself65
06abb702f5 refactor: remove deprecated atoms (#2615) 2023-05-31 14:54:59 +08:00
Himself65
ee289706ec refactor: move affine utils into @affine/workspace (#2611) 2023-05-31 13:13:59 +08:00
Himself65
6cbf310a5a chore: bump blocksuite to 0.0.0-20230531040027-44cd9d8e-nightly (#2610) 2023-05-31 13:10:41 +08:00
Whitewater
855fd8a73a feat: page list supports preview (#2606) 2023-05-31 04:24:55 +00:00
Himself65
8dbd354659 fix: logic after delete all workspaces (#2587)
Co-authored-by: JimmFly <yangjinfei001@gmail.com>
2023-05-31 12:24:14 +08:00
Himself65
1c7ae04f4f feat: update filter button (#2609) 2023-05-31 11:26:20 +08:00
Whitewater
0bb6e362bf feat: add page mode filter (#2601)
Co-authored-by: himself65 <himself65@outlook.com>
2023-05-31 11:15:23 +08:00
Peng Xiao
617350fc7d fix: optimize DB pull (#2589) 2023-05-31 11:09:18 +08:00
Hyden Liu
2713340532 fix(web): header div props error (#2607) 2023-05-31 10:34:42 +08:00
Whitewater
31d552ab7e fix: update breakpoint in all page (#2602) 2023-05-30 18:27:42 +08:00
Himself65
e11326f05f feat: add hook useBlockSuitePagePreview (#2603) 2023-05-30 18:26:13 +08:00
Himself65
6648fe4dcc feat: init @affine/copilot (#2511) 2023-05-30 18:02:49 +08:00
Peng Xiao
f669164674 fix: popover may not be closable (#2598) 2023-05-30 17:29:00 +08:00
JimmFly
c6d8904ca2 fix: quick search result missing title (#2594) 2023-05-30 16:45:00 +08:00
3720
8c5a1e2de3 test: add some tests for page filter (#2593) 2023-05-30 16:39:14 +08:00
himself65
395414c336 v0.7.0-canary.2 2023-05-30 15:17:35 +08:00
xiaodong zuo
96f653ea19 chore: bump blocksuit to 0.0.0-20230530061436-d0702cc0-nightly (#2590) 2023-05-30 15:13:54 +08:00
fourdim
fa089de40d feat: add support for exporting pdf and png (#2588)
This closes #2583.
2023-05-30 14:04:35 +08:00
Doma
4175f5391e feat(web): drag page to trash folder (#2385)
Co-authored-by: Himself65 <himself65@outlook.com>
2023-05-30 13:14:10 +08:00
Himself65
61c417992a feat: init support for multiple tiles (#2585) 2023-05-30 12:27:38 +08:00
Himself65
befae6bc9b feat: page view persistence (#2581) 2023-05-30 00:21:21 +08:00
himself65
e7eb13e966 v0.7.0-canary.1 2023-05-30 00:19:05 +08:00
Whitewater
88eaaf9ce4 feat: add radio group (#2572) 2023-05-29 23:15:22 +08:00
Himself65
20cc082a02 refactor: abstract header adapter (#2580) 2023-05-29 22:52:04 +08:00
Qi
402d12a0e1 fix: bookmark popper menu only display after pasted (#2578) 2023-05-29 14:25:30 +00:00
Himself65
58ba11e13c refactor: ui adapter (#2577) 2023-05-29 21:56:00 +08:00
Horus
cb6ca52b03 fix: replace windows installer loading gif (#2575) 2023-05-29 21:36:08 +08:00
Himself65
cd2ab73e5d chore: bump blocksuite to 0.0.0-20230529102007-5ac37643-nightly (#2569) 2023-05-29 18:51:33 +08:00
JimmFly
b16e725514 chore: adjust switch style (#2570) 2023-05-29 18:40:47 +08:00
JimmFly
004fcc8e80 fix: updater button text overflow (#2571) 2023-05-29 18:39:47 +08:00
Hyden Liu
a01a3ef011 fix: dropdown menu entire right can be pulled down (#2568)
Co-authored-by: Whitewater <me@waterwater.moe>
2023-05-29 07:03:26 +00:00
Peng Xiao
20cf45270d refactor(electron): sqlite db data workflow (remove symlink & fs watcher) (#2491) 2023-05-29 12:53:15 +08:00
3720
f3ac12254c feat: headless filter in all pages tab (#2566)
Co-authored-by: himself65 <himself65@outlook.com>
2023-05-29 04:06:40 +00:00
himself65
e0eb216b9b chore: revert @vanilla-extract/next-plugin to 2.1.2 2023-05-27 21:36:24 +08:00
Himself65
90afed1e74 feat: add build flag enableAllPageFilter (#2562) 2023-05-27 16:35:07 +08:00
Himself65
83d2ed8ace chore: bump version (#2559) 2023-05-27 16:08:07 +08:00
himself65
a0b64ca3e3 docs: update releases.md 2023-05-26 16:12:53 +08:00
himself65
b9fc5ad769 v0.7.0-canary.0 2023-05-26 15:50:00 +08:00
Himself65
ef1a44a413 chore: bump version (#2542) 2023-05-26 15:47:45 +08:00
xiaodong zuo
798dc49da4 feat: the UI of importing Html/Markdown/Notion (#2533)
Co-authored-by: Himself65 <himself65@outlook.com>
2023-05-26 15:30:39 +08:00
himself65
902081d44e ci: remove concurrency in languages-sync.yml 2023-05-26 15:26:12 +08:00
Whitewater
7969b73979 chore: tweak all page styles (#2540) 2023-05-26 15:13:50 +08:00
Himself65
c8734bd6ee chore: bump blocksuite to 0.0.0-20230526024755-74df4d56-nightly (#2541) 2023-05-26 15:13:00 +08:00
Qi
6d3c273ffd feat: support bookmark (#2458)
Co-authored-by: himself65 <himself65@outlook.com>
2023-05-26 06:52:36 +00:00
Himself65
f4b3830a0e feat(component): init notification center (#2426)
Co-authored-by: JimmFly <yangjinfei001@gmail.com>
2023-05-26 14:32:01 +08:00
Whitewater
36534f1915 feat: add storybook i18n decorator (#2538)
Co-authored-by: Himself65 <himself65@outlook.com>
2023-05-26 14:28:11 +08:00
Whitewater
7dcbe64d4e feat: group all page by date (#2532)
Co-authored-by: Himself65 <himself65@outlook.com>
2023-05-26 05:23:51 +00:00
Himself65
60057c666d fix: cannot delete last workspace (#2537) 2023-05-26 13:04:20 +08:00
JimmFly
60a83f4907 chore: update user guide style (#2536) 2023-05-26 12:55:06 +08:00
Horus
b11ce2c8d2 docs: add native build command to readme (#2535) 2023-05-26 10:29:30 +08:00
Whitewater
3b8f2c1ac3 refactor: use date obj in all pages (#2523) 2023-05-25 18:22:57 +08:00
Whitewater
be065e2de3 fix: sort in desc based update date by default (#2510) 2023-05-25 15:33:02 +08:00
Horus
675c737e48 fix: replace new windows install loading gif (#2513) 2023-05-25 14:30:52 +08:00
himself65
1255384cab v0.6.0-canary.8 2023-05-25 14:13:32 +08:00
Himself65
3d423c3299 fix: dispose on editor props.onInit (#2521) 2023-05-25 14:13:06 +08:00
ShortCipher5
ad4737850d chore: update pre-load content (#2518) 2023-05-25 05:41:49 +00:00
Himself65
9dcacd413c chore: bump blocksuite to 0.0.0-20230525011821-20259c76-nightly (#2515) 2023-05-25 13:04:18 +08:00
JimmFly
c1998eddf3 chore: bump electron (#2516) 2023-05-25 03:46:34 +00:00
himself65
db3f63e8f2 v0.6.0-canary.7 2023-05-25 09:17:21 +08:00
JimmFly
e562ca1011 chore: update download tip link (#2509) 2023-05-24 16:43:45 +08:00
fourdim
f6adf93f90 feat: add simple support for pdf (#2503) 2023-05-24 16:40:20 +08:00
Chi Zhang
053eba5d98 docs: update README.md (#2506) 2023-05-24 14:46:26 +08:00
Himself65
49f1ba676f fix: regression on toast component (#2502) 2023-05-24 13:10:25 +08:00
Aditya Sharma
48c109e149 feat(component): keyboard navigation for image-viewer (#2334)
Co-authored-by: Himself65 <himself65@outlook.com>
2023-05-23 09:35:11 +00:00
LongYinan
259d7988d9 chore(native): upgrade notify to v6 (#2489) 2023-05-22 22:45:43 +08:00
fourdim
0a49258ddd docs: update build guideline (#2434)
Co-authored-by: Himself65 <himself65@outlook.com>
2023-05-22 12:18:43 +00:00
himself65
fd35d3427e fix: make editor width to 800px
Fixes: https://github.com/toeverything/AFFiNE/issues/2486
2023-05-22 17:40:51 +08:00
Himself65
ef0a20b358 fix: use data-testid (#2487) 2023-05-22 17:36:52 +08:00
Himself65
f01997f8ee refactor: remove unused code (#2484) 2023-05-22 17:11:18 +08:00
Whitewater
281a068cfb chore(i18n): remove unused dependencies (#2485) 2023-05-22 17:03:55 +08:00
Whitewater
fe5be0cb47 fix: flatten i18n keys (#2483) 2023-05-22 08:08:43 +00:00
himself65
8aab1d6459 docs: add comment on legacy affine adapter 2023-05-22 16:02:05 +08:00
Himself65
2eaaeef4a7 fix: use hook with first render (#2481) 2023-05-22 15:58:13 +08:00
Himself65
5fbfabb3b2 refactor: rename plugins to adapters (#2480) 2023-05-22 15:48:01 +08:00
himself65
ec64260b6a v0.6.0-canary.6 2023-05-22 14:25:20 +08:00
LongYinan
2e23a4830b ci: add circular import detect (#2475)
Co-authored-by: himself65 <himself65@outlook.com>
2023-05-22 04:53:55 +00:00
Himself65
41a3d6f62f fix: wrap all workspaces with Suspense (#2477) 2023-05-22 12:39:07 +08:00
Peng Xiao
752bc9ca0e fix: fav reference style issue (#2476) 2023-05-22 12:01:03 +08:00
Himself65
c08f6fdba4 chore: update blocksuite to 0.0.0-20230519102837-01acd96b-nightly (#2472) 2023-05-22 02:27:03 +00:00
Geoffrey Biggs
b23b7e896b docs: correct spelling (#2469) 2023-05-22 07:26:30 +08:00
Whitewater
d68b421a4b feat: add responvise page view (#2453) 2023-05-22 07:25:25 +08:00
Horus
1f510799e2 fix: add windows install loading gif (#2462) 2023-05-21 16:03:48 +08:00
Peng Xiao
66ea97c7c9 fix: adjust some windows style issues (#2454) 2023-05-19 09:39:51 -07:00
Shishu
ee300e7b60 docs: sign CLA (#2457) 2023-05-19 08:40:59 -07:00
Peng Xiao
ef2d135e9b fix: optimize app updater (#2452) 2023-05-19 00:07:07 -07:00
JimmFly
c82fb89d57 chore: remove unused i18n key (#2451) 2023-05-19 03:38:48 +00:00
himself65
725bf63a32 ci: remove add-to-project.yml 2023-05-18 18:35:19 -07:00
himself65
c1ca578f7d docs: add download count 2023-05-18 13:12:26 -07:00
Whitewater
530dd5ff7f feat: add new page button (#2417) 2023-05-18 13:07:05 -07:00
Himself65
11370bc07e chore: bump version (#2444) 2023-05-18 11:43:45 -07:00
JimmFly
1c53daf1c4 chore: bump icon version (#2441) 2023-05-18 10:37:40 -07:00
Peng Xiao
b2556db33b fix: adjust some styles (#2438) 2023-05-18 09:24:23 +00:00
JimmFly
89310c9b97 chore: adjust delete description style (#2437) 2023-05-18 09:17:38 +00:00
JimmFly
8e09af910f fix: create workspace card responsive (#2435) 2023-05-18 09:11:15 +00:00
himself65
885aea3425 v0.6.0-canary.5 2023-05-18 01:21:25 -07:00
ShortCipher5
a616150f2d chore: update pre-load content (#2432) 2023-05-18 00:08:35 -07:00
Himself65
d80dae8a89 fix: open non-trash page when open (#2431) 2023-05-17 23:22:31 -07:00
Himself65
34ff08b92b chore: bump blocksuite to 0.0.0-20230518051344-45970a96-nightly (#2430) 2023-05-17 22:30:45 -07:00
Peng Xiao
2f7b51d7ff feat: fav page references (#2422)
Co-authored-by: Himself65 <himself65@outlook.com>
2023-05-17 22:18:40 -07:00
ShortCipher5
b7cee3185e chore: update pre-loading page (#2429) 2023-05-17 22:16:19 -07:00
JimmFly
1c5455e6ed chore: adjust copywriting for onboarding (#2428) 2023-05-17 22:15:01 -07:00
himself65
2d303fd5d3 v0.6.0-canary.4 2023-05-17 17:46:39 -07:00
himself65
fbe2543c03 fix: version check 2023-05-17 17:44:58 -07:00
Himself65
d6b640726e refactor: remove unused code (#2425) 2023-05-17 17:15:12 -07:00
Peng Xiao
f875b37641 fix: configurable changelog url (#2418) 2023-05-17 16:16:22 -07:00
Himself65
53c4fc6dfa fix: sidebar fallback ui position (#2424) 2023-05-17 15:49:55 -07:00
Himself65
6c310249d9 chore: bump version (#2423) 2023-05-17 15:02:55 -07:00
Horus
02e1f528bf fix: add workflow to check release version match with package.json (#2420) 2023-05-17 10:37:28 -07:00
Peng Xiao
c870104370 chore: bump blocksuite to 0.0.0-20230517102216-36bda4ab-nightly (#2411) 2023-05-17 10:09:29 -07:00
himself65
627d8ef787 v0.6.0-canary.3 2023-05-17 09:48:51 -07:00
LongYinan
5563823a7a build: missing build native step in nightly build (#2421) 2023-05-17 23:52:32 +08:00
JimmFly
d6804bb0fd chore: update prompt (#2410) 2023-05-17 17:52:57 +08:00
LongYinan
1350633690 build: fix electron release build process (#2408) 2023-05-17 17:22:49 +08:00
JimmFly
50196d8fde chore: update preloading page (#2409) 2023-05-17 09:16:07 +00:00
Peng Xiao
2e0ccb53ec feat: update button enhancements (#2401) 2023-05-17 16:58:14 +08:00
Whitewater
1498ee405b feat: add dropdown button (#2407) 2023-05-17 16:32:37 +08:00
Peng Xiao
cb863c4afa chore: disable image modal by default (#2400) 2023-05-16 23:14:31 -07:00
Himself65
2629d39501 fix: infinite reloading (#2405) 2023-05-17 13:58:34 +08:00
Himself65
38305cd984 fix: hydration error (#2404) 2023-05-17 05:23:55 +00:00
LongYinan
93116c24f2 feat(electron): use affine native (#2329) 2023-05-17 12:36:51 +08:00
Whitewater
017b9c8615 feat: add block card component (#2398) 2023-05-16 18:19:28 +08:00
Whitewater
9ce3a96862 fix: unexpected undefined class in popup (#2394) 2023-05-16 10:01:27 +00:00
Peng Xiao
a0ff520ba4 fix: some style updates (#2396) 2023-05-16 09:46:51 +00:00
Whitewater
a8b8986d89 chore: disable confused storybook backgrounds addon (#2395) 2023-05-16 17:46:35 +08:00
JimmFly
8ffc096fee fix: text overflows in the header option menu (#2393) 2023-05-16 17:35:57 +08:00
JimmFly
7e457f7b4c chore: add responsive styles for workspace card (#2390) 2023-05-16 16:51:46 +08:00
xiaodong zuo
aedf2d339e Update jobs.md
Added a job posting for a full-time or internship engineer.
2023-05-16 15:35:23 +08:00
JimmFly
ffd5ae52b3 feat: add Japanese support and update translation (#2388) 2023-05-16 14:21:51 +08:00
DiamondThree
3093194da8 docs: update jobs.md (#2389) 2023-05-15 22:24:27 -07:00
Horus
68b4f792f0 fix: app updater not working for internal release (#2377) 2023-05-15 20:34:54 -07:00
himself65
e2c6e4f9fc ci: use samver 2023-05-15 09:34:04 -07:00
Whitewater
9ff7dbffb7 feat: supports sort all page (#2356) 2023-05-15 08:50:43 -07:00
JimmFly
0c561da061 chore: remove favorite page (#2372) 2023-05-15 08:41:38 -07:00
JimmFly
06951319a6 chore: remove quick search tips (#2375) 2023-05-15 08:41:10 -07:00
JimmFly
0bfcab4067 chore: add animation for tour modal (#2365) 2023-05-15 16:48:52 +08:00
himself65
2c4db4fa16 v0.6.0-canary.2 2023-05-14 23:14:36 -07:00
Himself65
23b4f9ee12 feat(electron): track router history (#2336)
Co-authored-by: Peng Xiao <pengxiao@outlook.com>
2023-05-14 23:13:30 -07:00
himself65
e5330b1917 build: add app bundle id for internal 2023-05-14 22:35:40 -07:00
Peng Xiao
183611a556 fix: some style updates (#2348) 2023-05-14 21:58:13 -07:00
Himself65
7786456ba4 chore: update blocksuite to 0.0.0-20230514141009-705c0fac-nightly (#2357) 2023-05-14 19:32:27 -07:00
Ikko Eltociear Ashimine
f4bf7e3ddf fix: typo in AFFiNE-Docs.md (#2355) 2023-05-13 22:37:42 -07:00
Doma
05d88215d1 feat(electron): app menu item and hotkey for creating new page (#2267)
Co-authored-by: Peng Xiao <pengxiao@outlook.com>
2023-05-13 15:45:12 +00:00
Himself65
b240a70e51 chore: update blocksuite to 0.0.0-20230512192655-e61e272b-nightly (#2352) 2023-05-12 15:39:05 -05:00
LongYinan
00fd468e9b chore(server): remove bcrypt to avoid node-gyp usage (#2349) 2023-05-12 13:48:38 -05:00
Himself65
b5a7f8b7eb chore: bump version (#2331) 2023-05-12 13:47:14 -05:00
himself65
f03277fd17 v0.6.0-canary.1 2023-05-12 01:30:54 -05:00
himself65
ee93071149 chore: update icons 2023-05-12 01:06:05 -05:00
Himself65
21fdced2bd fix: correct router logic (#2342) 2023-05-12 00:55:45 -05:00
Peng Xiao
10b4558947 feat: new sidebar (app shell) styles (#2303) 2023-05-11 22:13:51 -05:00
Himself65
0fbed5d9d6 ci: collect test coverage on electron (#2335) 2023-05-11 20:51:13 -05:00
Himself65
8d117123d7 fix: remove useEffect on router sync with atoms (#2241) 2023-05-11 16:37:42 -05:00
Himself65
063ffda09d refactor: rename WorkspacePlugin to WorkspaceAdapter (#2330) 2023-05-11 12:43:39 -05:00
Himself65
39c83bd25b fix: delay setAom on rootWorkspacesMetadataAtom (#2271) 2023-05-11 15:03:11 +00:00
Peng Xiao
4444c3d1a6 fix: updater issue 2023-05-11 14:44:54 +08:00
LongYinan
717dd93f37 fix(electron): close db before move db file 2023-05-11 14:41:51 +08:00
LongYinan
c58673c55f chore(native): license 2023-05-11 14:41:51 +08:00
LongYinan
768e55072d ci: rust build config 2023-05-11 14:41:51 +08:00
LongYinan
8c84daec2b feat(native): NotifyEvent types 2023-05-11 14:41:51 +08:00
LongYinan
e54a5b6128 feat(native): provide FSWatcher 2023-05-11 14:41:51 +08:00
LongYinan
ee1e50f391 refactor(native): rename folder name 2023-05-11 14:41:51 +08:00
himself65
268636c440 v0.6.0-canary.0 2023-05-11 01:09:21 -05:00
Peng Xiao
06fa0cdb60 fix: should not show open folder if it is not moved (#2299) 2023-05-11 05:36:22 +00:00
Himself65
73dbb39009 feat(component): improve fallback skeleton (#2323) 2023-05-11 00:35:42 -05:00
JimmFly
47848cb5da fix: delete modal on confirm does not close (#2322) 2023-05-11 05:19:11 +00:00
JimmFly
eff6a03a51 chore: update AFFiNE Cloud prompt (#2321) 2023-05-11 00:18:12 -05:00
himself65
08f6a41ef4 ci: fix set version scripts 2023-05-10 23:00:36 -05:00
himself65
6d1345ffe5 build: replace version 2023-05-10 22:24:34 -05:00
Himself65
689f615b11 chore: bump version (#2310) 2023-05-10 21:43:14 -05:00
Himself65
f82ea5d9c4 build(electron): add internal release channel (#2309) 2023-05-10 21:42:56 -05:00
himself65
dc4979a80c fix(electron): remove unused code 2023-05-10 15:04:13 -05:00
JimmFly
1f48bc4301 refactor: tour modal (#2297) 2023-05-10 08:11:42 +00:00
himself65
beabd1e050 v0.5.4-canary.31 2023-05-10 00:56:04 -05:00
Himself65
19e20a6a20 fix(component): toast too many times when switch page mode (#2296) 2023-05-10 00:50:51 -05:00
Peng Xiao
e4f13ddae4 fix: try to fix updater not working (#2294)
Co-authored-by: Himself65 <himself65@outlook.com>
2023-05-10 00:40:22 -05:00
Himself65
752d0545ca feat: enhance root div styles (#2295) 2023-05-10 00:39:51 -05:00
himself65
08341d3d6c ci: remove master branch build 2023-05-09 23:11:46 -05:00
himself65
ef665df330 ci: add nightly-build.yml 2023-05-09 23:04:24 -05:00
Himself65
b38017cd23 feat(component): add skeleton in page detail (#2292) 2023-05-09 22:38:30 -05:00
Peng Xiao
0c550a2827 fix: theme not being persisted issue (#2283) 2023-05-09 22:04:36 -05:00
Chi Zhang
87ffdad862 docs: update README.md (#2291) 2023-05-09 21:51:44 -05:00
himself65
c6e8024e16 ci: disable fall-test in desktop-test 2023-05-09 21:13:33 -05:00
himself65
4200b3c3e5 ci: build staging and release branches 2023-05-09 20:27:07 -05:00
Himself65
10976a9257 chore: bump version (#2287) 2023-05-09 15:40:36 -05:00
75 changed files with 685 additions and 1955 deletions

View File

@@ -80,19 +80,15 @@ const config = {
'react',
'@typescript-eslint',
'simple-import-sort',
'sonarjs',
'import',
'unused-imports',
'unicorn',
],
rules: {
'array-callback-return': 'error',
'no-undef': 'off',
'no-empty': 'off',
'no-func-assign': 'off',
'no-cond-assign': 'off',
'no-constant-binary-expression': 'error',
'no-constructor-return': 'error',
'react/prop-types': 'off',
'@typescript-eslint/consistent-type-imports': 'error',
'@typescript-eslint/no-non-null-assertion': 'error',
@@ -142,21 +138,6 @@ const config = {
ignore: ['^\\[[a-zA-Z0-9-_]+\\]\\.tsx$'],
},
],
'sonarjs/no-all-duplicated-branches': 'error',
'sonarjs/no-element-overwrite': 'error',
'sonarjs/no-empty-collection': 'error',
'sonarjs/no-extra-arguments': 'error',
'sonarjs/no-identical-conditions': 'error',
'sonarjs/no-identical-expressions': 'error',
'sonarjs/no-ignored-return': 'error',
'sonarjs/no-one-iteration-loop': 'error',
'sonarjs/no-use-of-empty-return-value': 'error',
'sonarjs/non-existent-operator': 'error',
'sonarjs/no-collapsible-if': 'error',
'sonarjs/no-same-line-conditional': 'error',
'sonarjs/no-duplicated-branches': 'error',
'sonarjs/no-collection-size-mischeck': 'error',
'sonarjs/no-useless-catch': 'error',
},
overrides: [
{
@@ -171,27 +152,6 @@ const config = {
'@typescript-eslint/no-var-requires': 0,
},
},
...allPackages.map(pkg => ({
files: [`${pkg}/src/**/*.ts`, `${pkg}/src/**/*.tsx`],
parserOptions: {
project: resolve(__dirname, './tsconfig.eslint.json'),
},
rules: {
'@typescript-eslint/no-restricted-imports': [
'error',
{
patterns: createPattern(pkg),
},
],
'@typescript-eslint/no-floating-promises': [
'error',
{
ignoreVoid: false,
ignoreIIFE: false,
},
],
},
})),
{
files: [
'**/__tests__/**/*',
@@ -213,9 +173,19 @@ const config = {
'ts-check': false,
},
],
'@typescript-eslint/no-floating-promises': 0,
},
},
...allPackages.map(pkg => ({
files: [`${pkg}/src/**/*.ts`, `${pkg}/src/**/*.tsx`],
rules: {
'@typescript-eslint/no-restricted-imports': [
'error',
{
patterns: createPattern(pkg),
},
],
},
})),
],
};

View File

@@ -341,11 +341,6 @@ jobs:
name: affine
fail_ci_if_error: true
- name: Run desktop tests
if: ${{ matrix.spec.test && matrix.spec.os != 'ubuntu-latest' }}
run: yarn test
working-directory: apps/electron
- name: Upload test results
if: ${{ failure() }}
uses: actions/upload-artifact@v3

View File

@@ -56,7 +56,7 @@ jobs:
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
API_SERVER_PROFILE: prod
ENABLE_TEST_PROPERTIES: false
ENABLE_IMAGE_PREVIEW_MODAL: true
ENABLE_IMAGE_PREVIEW_MODAL: false
ENABLE_BOOKMARK_OPERATION: true
RELEASE_VERSION: ${{ needs.set-build-version.outputs.version }}

View File

@@ -56,7 +56,7 @@ jobs:
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
API_SERVER_PROFILE: prod
ENABLE_TEST_PROPERTIES: false
ENABLE_IMAGE_PREVIEW_MODAL: true
ENABLE_IMAGE_PREVIEW_MODAL: false
ENABLE_BOOKMARK_OPERATION: true
RELEASE_VERSION: ${{ github.event.inputs.version }}

View File

@@ -1,5 +1,4 @@
/* eslint-disable @typescript-eslint/no-var-requires */
const { z } = require('zod');
const {
@@ -52,6 +51,8 @@ module.exports = {
teamId: process.env.APPLE_TEAM_ID,
}
: undefined,
// do we need the following line?
extraResource: ['./resources/app-update.yml'],
},
makers: [
{
@@ -103,27 +104,6 @@ module.exports = {
// so stable and canary will not share the same app data
packageJson.productName = productName;
},
prePackage: async () => {
const { rm, cp } = require('node:fs/promises');
const { resolve } = require('node:path');
await rm(
resolve(__dirname, './node_modules/@toeverything/plugin-infra'),
{
recursive: true,
force: true,
}
);
await cp(
resolve(__dirname, '../../packages/plugin-infra'),
resolve(__dirname, './node_modules/@toeverything/plugin-infra'),
{
recursive: true,
force: true,
}
);
},
generateAssets: async (_, platform, arch) => {
if (process.env.SKIP_GENERATE_ASSETS) {
return;

View File

@@ -1,7 +1,7 @@
{
"name": "@affine/electron",
"private": true,
"version": "0.6.1-beta.0",
"version": "0.7.0-canary.13",
"author": "affine",
"repository": {
"url": "https://github.com/toeverything/AFFiNE",
@@ -29,10 +29,6 @@
"devDependencies": {
"@affine-test/kit": "workspace:*",
"@affine/native": "workspace:*",
"@blocksuite/blocks": "0.0.0-20230607055421-9b20fcaf-nightly",
"@blocksuite/editor": "0.0.0-20230607055421-9b20fcaf-nightly",
"@blocksuite/lit": "0.0.0-20230607055421-9b20fcaf-nightly",
"@blocksuite/store": "0.0.0-20230607055421-9b20fcaf-nightly",
"@electron-forge/cli": "^6.1.1",
"@electron-forge/core": "^6.1.1",
"@electron-forge/core-utils": "^6.1.1",
@@ -52,19 +48,17 @@
"electron-window-state": "^5.0.3",
"esbuild": "^0.17.19",
"fs-extra": "^11.1.1",
"jotai": "^2.1.1",
"playwright": "=1.33.0",
"ts-node": "^10.9.1",
"undici": "^5.22.1",
"uuid": "^9.0.0",
"which": "^3.0.1",
"zx": "^7.2.2"
},
"dependencies": {
"@toeverything/plugin-infra": "workspace:*",
"async-call-rpc": "^6.3.1",
"cheerio": "^1.0.0-rc.12",
"electron-updater": "^5.3.0",
"link-preview-js": "^3.0.4",
"lodash-es": "^4.17.21",
"nanoid": "^4.0.2",
"rxjs": "^7.8.1",

View File

@@ -63,7 +63,7 @@ export const config = () => {
bundle: true,
target: `node${NODE_MAJOR_VERSION}`,
platform: 'node',
external: ['@toeverything/plugin-infra', 'async-call-rpc'],
external: ['electron', 'electron-updater', '@toeverything/plugin-infra'],
define: define,
format: 'cjs',
loader: {

View File

@@ -5,7 +5,6 @@ import path, { resolve } from 'node:path';
import electronPath from 'electron';
import * as esbuild from 'esbuild';
import which from 'which';
import { config, electronDir, rootDir } from './common.mjs';
@@ -68,9 +67,9 @@ function spawnOrReloadElectron() {
}
const common = config();
const yarnPath = which.sync('yarn');
async function watchPlugins() {
spawn(yarnPath, ['dev'], {
spawn('yarn', ['dev'], {
stdio: 'inherit',
cwd: resolve(rootDir, './packages/plugin-infra'),
});

View File

@@ -32,6 +32,10 @@ if (releaseVersionEnv && electronPackageJson.version !== releaseVersionEnv) {
}
// copy web dist files to electron dist
// step 1: clean up
await cleanup();
echo('Clean up done');
if (process.platform === 'win32') {
$.shell = 'powershell.exe';
$.prefix = '';
@@ -39,7 +43,7 @@ if (process.platform === 'win32') {
cd(repoRootDir);
// step 1: build web (nextjs) dist
// step 2: build web (nextjs) dist
if (!process.env.SKIP_WEB_BUILD) {
process.env.ENABLE_LEGACY_PROVIDER = 'false';
await $`yarn nx build @affine/web`;
@@ -63,7 +67,7 @@ if (!process.env.SKIP_WEB_BUILD) {
await fs.move(affineWebOutDir, publicAffineOutDir, { overwrite: true });
}
// step 2: update app-updater.yml content with build type in resources folder
// step 3: update app-updater.yml content with build type in resources folder
if (process.env.BUILD_TYPE === 'internal') {
const appUpdaterYml = path.join(publicDistDir, 'app-update.yml');
const appUpdaterYmlContent = await fs.readFile(appUpdaterYml, 'utf-8');
@@ -73,3 +77,14 @@ if (process.env.BUILD_TYPE === 'internal') {
);
await fs.writeFile(appUpdaterYml, newAppUpdaterYmlContent);
}
/// --------
/// --------
/// --------
async function cleanup() {
if (!process.env.SKIP_WEB_BUILD) {
await fs.emptyDir(publicAffineOutDir);
}
await fs.remove(path.join(electronRootDir, 'dist'));
await fs.remove(path.join(electronRootDir, 'out'));
}

View File

@@ -110,9 +110,7 @@ export async function saveDBFileAs(
await fs.copyFile(db.path, filePath);
logger.log('saved', filePath);
mainRPC.showItemInFolder(filePath).catch(err => {
console.error(err);
});
mainRPC.showItemInFolder(filePath);
return { filePath };
} catch (err) {
logger.error('saveDBFileAs', err);

View File

@@ -64,9 +64,7 @@ function setupRendererConnection(rendererPort: Electron.MessagePortMain) {
for (const [key, eventRegister] of Object.entries(namespaceEvents)) {
const subscription = eventRegister((...args: any[]) => {
const chan = `${namespace}:${key}`;
rpc.postEvent(chan, ...args).catch(err => {
console.error(err);
});
rpc.postEvent(chan, ...args);
});
process.on('exit', () => {
subscription();

View File

@@ -60,9 +60,9 @@ app.on('activate', restoreOrCreateWindow);
app
.whenReady()
.then(registerProtocol)
.then(registerPlugin)
.then(registerHandlers)
.then(registerEvents)
.then(registerPlugin)
.then(ensureHelperProcess)
.then(restoreOrCreateWindow)
.then(createApplicationMenu)

View File

@@ -1,7 +1,6 @@
import { join, resolve } from 'node:path';
import { Worker } from 'node:worker_threads';
import { logger } from '@affine/electron/main/logger';
import { AsyncCall } from 'async-call-rpc';
import { ipcMain } from 'electron';
@@ -14,30 +13,23 @@ declare global {
var asyncCall: Record<string, (...args: any) => PromiseLike<any>>;
}
export function registerPlugin() {
export async function registerPlugin() {
const pluginWorkerPath = join(__dirname, './workers/plugin.worker.js');
const asyncCall = AsyncCall<
Record<string, (...args: any) => PromiseLike<any>>
>(
{
log: (...args: any[]) => {
logger.log('Plugin Worker', ...args);
},
},
{},
{
channel: new MessageEventChannel(new Worker(pluginWorkerPath)),
}
);
globalThis.asyncCall = asyncCall;
logger.info('import plugin manager');
import('@toeverything/plugin-infra/manager')
.then(({ rootStore, affinePluginsAtom }) => {
logger.info('import plugin manager');
await import('@toeverything/plugin-infra/manager').then(
({ rootStore, affinePluginsAtom }) => {
const bookmarkPluginPath = join(
process.env.PLUGIN_DIR ?? resolve(__dirname, './plugins'),
'./bookmark-block/index.mjs'
);
logger.info('bookmark plugin path:', bookmarkPluginPath);
import('file://' + bookmarkPluginPath);
let dispose: () => void = () => {
// noop
@@ -46,9 +38,7 @@ export function registerPlugin() {
dispose();
const plugins = rootStore.get(affinePluginsAtom);
Object.values(plugins).forEach(plugin => {
logger.info('register plugin', plugin.definition.id);
plugin.definition.commands.forEach(command => {
logger.info('register plugin command', command);
ipcMain.handle(command, (event, ...args) =>
asyncCall[command](...args)
);
@@ -57,14 +47,11 @@ export function registerPlugin() {
dispose = () => {
Object.values(plugins).forEach(plugin => {
plugin.definition.commands.forEach(command => {
logger.info('unregister plugin command', command);
ipcMain.removeHandler(command);
});
});
};
});
})
.catch(error => {
logger.error('import plugin manager error', error);
});
}
);
}

View File

@@ -11,59 +11,33 @@ if (!parentPort) {
throw new Error('parentPort is undefined');
}
const mainThread = AsyncCall<{
log: (...args: any[]) => Promise<void>;
}>(commandProxy, {
AsyncCall(commandProxy, {
channel: new MessageEventChannel(parentPort),
});
globalThis.console.log = mainThread.log;
globalThis.console.error = mainThread.log;
globalThis.console.info = mainThread.log;
globalThis.console.debug = mainThread.log;
globalThis.console.warn = mainThread.log;
console.log('import plugin infra');
import('@toeverything/plugin-infra/manager')
.then(({ rootStore, affinePluginsAtom }) => {
import('@toeverything/plugin-infra/manager').then(
({ rootStore, affinePluginsAtom }) => {
const bookmarkPluginPath = join(
process.env.PLUGIN_DIR ?? resolve(__dirname, '../plugins'),
'./bookmark-block/index.mjs'
);
console.log('import bookmark plugin', bookmarkPluginPath);
import('file://' + bookmarkPluginPath).catch(console.log);
import('file://' + bookmarkPluginPath);
rootStore.sub(affinePluginsAtom, () => {
const plugins = rootStore.get(affinePluginsAtom);
Object.values(plugins).forEach(plugin => {
console.log('handle plugin', plugin.definition.id);
if (plugin.serverAdapter) {
try {
plugin.serverAdapter({
registerCommand: (command, fn) => {
console.log('register command', command);
commandProxy[command] = fn;
},
unregisterCommand: command => {
console.log('unregister command', command);
delete commandProxy[command];
},
});
} catch (e) {
console.log(
'error when handle plugin',
plugin.definition.id,
`${e}`
);
}
} else {
console.log('no server adapter, skipping.');
plugin.serverAdapter({
registerCommand: (command, fn) => {
console.log('register command', command);
commandProxy[command] = fn;
},
unregisterCommand: command => {
delete commandProxy[command];
},
});
}
});
});
})
.catch(err => {
console.error(err);
});
}
);

View File

@@ -50,6 +50,4 @@ import { contextBridge, ipcRenderer } from 'electron';
} catch (error) {
console.error('Failed to expose affine APIs to window object!', error);
}
})().catch(err => {
console.error('Failed to bootstrap preload script!', err);
});
})();

View File

@@ -1,7 +1,7 @@
{
"name": "@affine/server",
"private": true,
"version": "0.6.1-beta.0",
"version": "0.7.0-canary.13",
"description": "Affine Node.js server",
"type": "module",
"bin": {

View File

@@ -1,7 +1,7 @@
{
"name": "@affine/web",
"private": true,
"version": "0.6.1-beta.0",
"version": "0.7.0-canary.13",
"scripts": {
"dev": "next dev",
"build": "next build",

View File

@@ -75,9 +75,7 @@ export function useHistoryAtom() {
if (forward) {
const target = Math.min(prev.stack.length - 1, prev.current + 1);
const url = prev.stack[target];
router.push(url).catch(err => {
console.error(err);
});
void router.push(url);
return {
...prev,
current: target,
@@ -86,9 +84,7 @@ export function useHistoryAtom() {
} else {
const target = Math.max(0, prev.current - 1);
const url = prev.stack[target];
router.push(url).catch(err => {
console.error(err);
});
void router.push(url);
return {
...prev,
current: target,

View File

@@ -49,24 +49,19 @@ rootWorkspacesMetadataAtom.onMount = setAtom => {
}, 0);
if (environment.isDesktop) {
window.apis?.workspace
.list()
.then(workspaceIDs => {
if (abortController.signal.aborted) return;
const newMetadata = workspaceIDs.map(w => ({
id: w[0],
flavour: WorkspaceFlavour.LOCAL,
}));
setAtom(metadata => {
return [
...metadata,
...newMetadata.filter(m => !metadata.find(m2 => m2.id === m.id)),
];
});
})
.catch(err => {
console.error(err);
window.apis?.workspace.list().then(workspaceIDs => {
if (abortController.signal.aborted) return;
const newMetadata = workspaceIDs.map(w => ({
id: w[0],
flavour: WorkspaceFlavour.LOCAL,
}));
setAtom(metadata => {
return [
...metadata,
...newMetadata.filter(m => !metadata.find(m2 => m2.id === m.id)),
];
});
});
}
return () => {

View File

@@ -116,14 +116,9 @@ const useDefaultDBLocation = () => {
const [defaultDBLocation, setDefaultDBLocation] = useState('');
useEffect(() => {
window.apis?.db
.getDefaultStorageLocation()
.then(dir => {
setDefaultDBLocation(dir);
})
.catch(err => {
console.error(err);
});
window.apis?.db.getDefaultStorageLocation().then(dir => {
setDefaultDBLocation(dir);
});
}, []);
return defaultDBLocation;
@@ -286,9 +281,7 @@ export const CreateWorkspaceModal = ({
}
onClose();
}
})().catch(err => {
console.error(err);
});
})();
} else if (mode === 'new') {
setStep(environment.isDesktop ? 'set-db-location' : 'name-workspace');
} else {

View File

@@ -12,7 +12,7 @@ import { useBlockSuiteWorkspaceAvatarUrl } from '@toeverything/hooks/use-block-s
import { useBlockSuiteWorkspaceName } from '@toeverything/hooks/use-block-suite-workspace-name';
import clsx from 'clsx';
import type React from 'react';
import { useCallback, useEffect, useState } from 'react';
import { useEffect, useState } from 'react';
import { useIsWorkspaceOwner } from '../../../../../hooks/affine/use-is-workspace-owner';
import { Upload } from '../../../../pure/file-upload';
@@ -27,14 +27,9 @@ const useShowOpenDBFile = (workspaceId: string) => {
const [show, setShow] = useState(false);
useEffect(() => {
if (window.apis && window.events && environment.isDesktop) {
window.apis.workspace
.getMeta(workspaceId)
.then(meta => {
setShow(!!meta.secondaryDBPath);
})
.catch(err => {
console.error(err);
});
window.apis.workspace.getMeta(workspaceId).then(meta => {
setShow(!!meta.secondaryDBPath);
});
return window.events.workspace.onMetaChange((newMeta: any) => {
if (newMeta.workspaceId === workspaceId) {
const meta = newMeta.meta;
@@ -59,11 +54,35 @@ export const GeneralPanel: React.FC<PanelProps> = ({
const isOwner = useIsWorkspaceOwner(workspace);
const t = useAFFiNEI18N();
const showOpenFolder = useShowOpenDBFile(workspace.id);
const handleUpdateWorkspaceName = (name: string) => {
setName(name);
toast(t['Update workspace name success']());
};
const [moveToInProgress, setMoveToInProgress] = useState<boolean>(false);
const handleMoveTo = async () => {
if (moveToInProgress) {
return;
}
try {
setMoveToInProgress(true);
const result = await window.apis?.dialog.moveDBFile(workspace.id);
if (!result?.error && !result?.canceled) {
toast(t['Move folder success']());
} else if (result?.error) {
// @ts-expect-error: result.error is dynamic
toast(t[result.error]());
}
} catch (err) {
toast(t['UNKNOWN_ERROR']());
} finally {
setMoveToInProgress(false);
}
};
const [, update] = useBlockSuiteWorkspaceAvatarUrl(
workspace.blockSuiteWorkspace
);
@@ -118,7 +137,9 @@ export const GeneralPanel: React.FC<PanelProps> = ({
placeholder={t['Workspace Name']()}
maxLength={64}
minLength={0}
onChange={setInput}
onChange={newName => {
setInput(newName);
}}
></StyledInput>
</div>
@@ -137,7 +158,63 @@ export const GeneralPanel: React.FC<PanelProps> = ({
</Button>
</div>
</div>
<DesktopClientOnly workspaceId={workspace.id} />
{environment.isDesktop && (
<div className={style.row}>
<div className={style.col}>
<div className={style.settingItemLabel}>
{t['Storage Folder']()}
</div>
<div className={style.settingItemLabelHint}>
{t['Storage Folder Hint']()}
</div>
</div>
<div className={style.col}>
{showOpenFolder && (
<div
className={style.storageTypeWrapper}
onClick={() => {
if (environment.isDesktop) {
window.apis?.dialog.revealDBFile(workspace.id);
}
}}
>
<FolderIcon color="var(--affine-primary-color)" />
<div className={style.storageTypeLabelWrapper}>
<div className={style.storageTypeLabel}>
{t['Open folder']()}
</div>
<div className={style.storageTypeLabelHint}>
{t['Open folder hint']()}
</div>
</div>
<ArrowRightSmallIcon color="var(--affine-primary-color)" />
</div>
)}
<div
data-testid="move-folder"
data-disabled={moveToInProgress}
className={style.storageTypeWrapper}
onClick={handleMoveTo}
>
<MoveToIcon color="var(--affine-primary-color)" />
<div className={style.storageTypeLabelWrapper}>
<div className={style.storageTypeLabel}>
{t['Move folder']()}
</div>
<div className={style.storageTypeLabelHint}>
{t['Move folder hint']()}
</div>
</div>
<ArrowRightSmallIcon color="var(--affine-primary-color)" />
</div>
</div>
<div className={style.col}></div>
</div>
)}
<div className={style.row}>
<div className={style.col}>
<div className={style.settingItemLabel}>
@@ -196,81 +273,3 @@ export const GeneralPanel: React.FC<PanelProps> = ({
</>
);
};
function DesktopClientOnly({ workspaceId }: { workspaceId: string }) {
const t = useAFFiNEI18N();
const showOpenFolder = useShowOpenDBFile(workspaceId);
const onRevealDBFile = useCallback(() => {
if (environment.isDesktop) {
window.apis?.dialog.revealDBFile(workspaceId).catch(err => {
console.error(err);
});
}
}, [workspaceId]);
const [moveToInProgress, setMoveToInProgress] = useState<boolean>(false);
const handleMoveTo = useCallback(() => {
if (moveToInProgress) {
return;
}
setMoveToInProgress(true);
window.apis?.dialog
.moveDBFile(workspaceId)
.then(result => {
if (!result?.error && !result?.canceled) {
toast(t['Move folder success']());
} else if (result?.error) {
// @ts-expect-error: result.error is dynamic
toast(t[result.error]());
}
})
.catch(() => {
toast(t['UNKNOWN_ERROR']());
})
.finally(() => {
setMoveToInProgress(false);
});
}, [moveToInProgress, t, workspaceId]);
const openFolderNode = showOpenFolder ? (
<div className={style.storageTypeWrapper} onClick={onRevealDBFile}>
<FolderIcon color="var(--affine-primary-color)" />
<div className={style.storageTypeLabelWrapper}>
<div className={style.storageTypeLabel}>{t['Open folder']()}</div>
<div className={style.storageTypeLabelHint}>
{t['Open folder hint']()}
</div>
</div>
<ArrowRightSmallIcon color="var(--affine-primary-color)" />
</div>
) : null;
return (
<div className={style.row}>
<div className={style.col}>
<div className={style.settingItemLabel}>{t['Storage Folder']()}</div>
<div className={style.settingItemLabelHint}>
{t['Storage Folder Hint']()}
</div>
</div>
<div className={style.col}>
{openFolderNode}
<div
data-testid="move-folder"
data-disabled={moveToInProgress}
className={style.storageTypeWrapper}
onClick={handleMoveTo}
>
<MoveToIcon color="var(--affine-primary-color)" />
<div className={style.storageTypeLabelWrapper}>
<div className={style.storageTypeLabel}>{t['Move folder']()}</div>
<div className={style.storageTypeLabelHint}>
{t['Move folder hint']()}
</div>
</div>
<ArrowRightSmallIcon color="var(--affine-primary-color)" />
</div>
</div>
<div className={style.col}></div>
</div>
);
}

View File

@@ -9,9 +9,7 @@ const LanguageMenuContent: FC = () => {
const i18n = useI18N();
const changeLanguage = useCallback(
(event: string) => {
i18n.changeLanguage(event).catch(err => {
console.error(err);
});
void i18n.changeLanguage(event);
},
[i18n]
);

View File

@@ -11,14 +11,7 @@ import { affinePluginsAtom } from '@toeverything/plugin-infra/manager';
import type { PluginUIAdapter } from '@toeverything/plugin-infra/type';
import { useAtom, useAtomValue } from 'jotai';
import type { FC, HTMLAttributes, PropsWithChildren, ReactNode } from 'react';
import {
forwardRef,
memo,
useCallback,
useEffect,
useMemo,
useState,
} from 'react';
import { forwardRef, memo, useEffect, useMemo, useState } from 'react';
import { guideDownloadClientTipAtom } from '../../../atoms/guide';
import { contentLayoutAtom } from '../../../atoms/layout';
@@ -106,41 +99,32 @@ const HeaderRightItems: Record<HeaderRightItemName, HeaderItem> = {
},
[HeaderRightItemName.WindowsAppControls]: {
Component: () => {
const handleMinimizeApp = useCallback(() => {
window.apis?.ui.handleMinimizeApp().catch(err => {
console.error(err);
});
}, []);
const handleMaximizeApp = useCallback(() => {
window.apis?.ui.handleMaximizeApp().catch(err => {
console.error(err);
});
}, []);
const handleCloseApp = useCallback(() => {
window.apis?.ui.handleCloseApp().catch(err => {
console.error(err);
});
}, []);
return (
<div className={styles.windowAppControlsWrapper}>
<button
data-type="minimize"
className={styles.windowAppControl}
onClick={handleMinimizeApp}
onClick={() => {
window.apis?.ui.handleMinimizeApp();
}}
>
<MinusIcon />
</button>
<button
data-type="maximize"
className={styles.windowAppControl}
onClick={handleMaximizeApp}
onClick={() => {
window.apis?.ui.handleMaximizeApp();
}}
>
<RoundedRectangleIcon />
</button>
<button
data-type="close"
className={styles.windowAppControl}
onClick={handleCloseApp}
onClick={() => {
window.apis?.ui.handleCloseApp();
}}
>
<CloseIcon />
</button>

View File

@@ -109,7 +109,7 @@ const EditorWrapper = memo(function EditorWrapper({
);
const disposes = uiDecorators.map(ui => ui(editor));
return () => {
disposes.forEach(fn => fn());
disposes.map(fn => fn());
dispose();
};
},

View File

@@ -54,9 +54,7 @@ export const Footer: React.FC<FooterProps> = ({
title: query,
});
onClose();
jumpToPage(blockSuiteWorkspace.id, page.id).catch(err => {
console.error(err);
});
void jumpToPage(blockSuiteWorkspace.id, page.id);
}, [blockSuiteWorkspace, createPage, jumpToPage, onClose, query])}
>
<StyledModalFooterContent>

View File

@@ -107,9 +107,7 @@ export const RootAppSidebar = ({
const [sidebarOpen, setSidebarOpen] = useAtom(appSidebarOpenAtom);
useEffect(() => {
if (environment.isDesktop && typeof sidebarOpen === 'boolean') {
window.apis?.ui.handleSidebarVisibilityChange(sidebarOpen).catch(err => {
console.error(err);
});
window.apis?.ui.handleSidebarVisibilityChange(sidebarOpen);
}
}, [sidebarOpen]);

View File

@@ -80,10 +80,15 @@ export function WorkspaceHeader({
{t['Workspace Settings']()}
</WorkspaceTitle>
);
} else if (
currentEntry.subPath === WorkspaceSubPath.SHARED ||
currentEntry.subPath === WorkspaceSubPath.TRASH
) {
} else if (currentEntry.subPath === WorkspaceSubPath.SHARED) {
return (
<WorkspaceModeFilterTab
workspace={currentWorkspace}
currentPage={null}
isPublic={false}
/>
);
} else if (currentEntry.subPath === WorkspaceSubPath.TRASH) {
return (
<WorkspaceModeFilterTab
workspace={currentWorkspace}

View File

@@ -10,7 +10,7 @@ import {
WorkspaceFallback,
} from '@affine/component/workspace';
import { DebugLogger } from '@affine/debug';
import { config, DEFAULT_HELLO_WORLD_PAGE_ID, env } from '@affine/env';
import { config, DEFAULT_HELLO_WORLD_PAGE_ID } from '@affine/env';
import { initEmptyPage, initPageWithPreloading } from '@affine/env/blocksuite';
import type { BackgroundProvider } from '@affine/env/workspace';
import { WorkspaceFlavour } from '@affine/env/workspace';
@@ -48,7 +48,6 @@ import {
publicWorkspaceAtom,
publicWorkspaceIdAtom,
} from '../atoms/public-workspace';
import type { IslandItemNames } from '../components/pure/help-island';
import { HelpIsland } from '../components/pure/help-island';
import {
DROPPABLE_SIDEBAR_TRASH,
@@ -175,9 +174,7 @@ export const CurrentWorkspaceContext = ({
useEffect(() => {
const id = setTimeout(() => {
if (!exist) {
push('/').catch(err => {
console.error(err);
});
void push('/');
globalThis.HALTING_PROBLEM_TIMEOUT <<= 1;
}
}, globalThis.HALTING_PROBLEM_TIMEOUT);
@@ -322,9 +319,7 @@ export const WorkspaceLayoutInner: FC<PropsWithChildren> = ({ children }) => {
}
if (!router.query.pageId) {
setCurrentPageId(pageId);
jumpToPage(currentWorkspace.id, pageId).catch(err => {
console.error(err);
});
void jumpToPage(currentWorkspace.id, pageId);
}
}
//#endregion
@@ -358,9 +353,7 @@ export const WorkspaceLayoutInner: FC<PropsWithChildren> = ({ children }) => {
}
);
setCurrentPageId(currentPageId);
jumpToPage(currentWorkspace.id, page.id).catch(err => {
console.error(err);
});
void jumpToPage(currentWorkspace.id, page.id);
}
}, [
currentPageId,
@@ -408,10 +401,6 @@ export const WorkspaceLayoutInner: FC<PropsWithChildren> = ({ children }) => {
);
const t = useAFFiNEI18N();
const showList: IslandItemNames[] = env.isDesktop
? ['whatNew', 'contact', 'guide']
: ['whatNew', 'contact'];
const handleDragEnd = useCallback(
(e: DragEndEvent) => {
// Drag page into trash folder
@@ -466,7 +455,9 @@ export const WorkspaceLayoutInner: FC<PropsWithChildren> = ({ children }) => {
</div>
{!isPublicWorkspace && (
<HelpIsland
showList={router.query.pageId ? undefined : showList}
showList={
router.query.pageId ? undefined : ['whatNew', 'contact']
}
/>
)}
</ToolContainer>

View File

@@ -39,31 +39,21 @@ const IndexPageInner = () => {
nonTrashPages.at(0)?.id;
if (pageId) {
logger.debug('Found target workspace. Jump to page', pageId);
jumpToPage(targetWorkspace.id, pageId, RouteLogic.REPLACE).catch(
err => {
console.error(err);
}
);
void jumpToPage(targetWorkspace.id, pageId, RouteLogic.REPLACE);
} else {
const clearId = setTimeout(() => {
dispose.dispose();
logger.debug('Found target workspace. Jump to all pages');
jumpToSubPath(
void jumpToSubPath(
targetWorkspace.id,
WorkspaceSubPath.ALL,
RouteLogic.REPLACE
).catch(err => {
console.error(err);
});
);
}, 1000);
const dispose =
targetWorkspace.blockSuiteWorkspace.slots.pageAdded.once(pageId => {
clearTimeout(clearId);
jumpToPage(targetWorkspace.id, pageId, RouteLogic.REPLACE).catch(
err => {
console.error(err);
}
);
void jumpToPage(targetWorkspace.id, pageId, RouteLogic.REPLACE);
});
return () => {
clearTimeout(clearId);

View File

@@ -11,7 +11,7 @@ import { atomWithStorage } from 'jotai/utils';
import Head from 'next/head';
import type { NextRouter } from 'next/router';
import { useRouter } from 'next/router';
import React, { useCallback } from 'react';
import React, { useCallback, useEffect } from 'react';
import { getUIAdapter } from '../../../adapters/workspace';
import { PageLoading } from '../../../components/pure/loading';
@@ -30,7 +30,7 @@ function useTabRouterSync(
router: NextRouter,
currentTab: SettingPanel,
setCurrentTab: (tab: SettingPanel) => void
): void {
) {
if (!router.isReady) {
return;
}
@@ -39,30 +39,37 @@ function useTabRouterSync(
? router.query.currentTab
: null;
if (
(queryCurrentTab !== null &&
settingPanelValues.indexOf(queryCurrentTab as SettingPanel) === -1) ||
settingPanelValues.indexOf(currentTab as SettingPanel) === -1
queryCurrentTab !== null &&
settingPanelValues.indexOf(queryCurrentTab as SettingPanel) === -1
) {
setCurrentTab(settingPanel.General);
router
.replace({
pathname: router.pathname,
query: {
...router.query,
currentTab: settingPanel.General,
},
})
.catch(console.error);
void router.replace({
pathname: router.pathname,
query: {
...router.query,
currentTab: settingPanel.General,
},
});
return;
} else if (settingPanelValues.indexOf(currentTab as SettingPanel) === -1) {
setCurrentTab(settingPanel.General);
void router.replace({
pathname: router.pathname,
query: {
...router.query,
currentTab: settingPanel.General,
},
});
return;
} else if (queryCurrentTab !== currentTab) {
router
.replace({
pathname: router.pathname,
query: {
...router.query,
currentTab: currentTab,
},
})
.catch(console.error);
void router.replace({
pathname: router.pathname,
query: {
...router.query,
currentTab: currentTab,
},
});
return;
}
}
@@ -71,24 +78,20 @@ const SettingPage: NextPageWithLayout = () => {
const [currentWorkspace] = useCurrentWorkspace();
const t = useAFFiNEI18N();
const [currentTab, setCurrentTab] = useAtom(settingPanelAtom);
useEffect(() => {});
const onChangeTab = useCallback(
(tab: SettingPanel) => {
setCurrentTab(tab as SettingPanel);
router
.push({
pathname: router.pathname,
query: {
...router.query,
currentTab: tab,
},
})
.catch(err => {
console.error(err);
});
void router.push({
pathname: router.pathname,
query: {
...router.query,
currentTab: tab,
},
});
},
[router, setCurrentTab]
);
useTabRouterSync(router, currentTab, setCurrentTab);
const helper = useAppHelper();
@@ -99,11 +102,11 @@ const SettingPage: NextPageWithLayout = () => {
return helper.deleteWorkspace(workspaceId);
}, [currentWorkspace, helper]);
const onTransformWorkspace = useOnTransformWorkspace();
if (
!router.isReady ||
currentWorkspace === null ||
settingPanelValues.indexOf(currentTab as SettingPanel) === -1
) {
if (!router.isReady) {
return <PageLoading />;
} else if (currentWorkspace === null) {
return <PageLoading />;
} else if (settingPanelValues.indexOf(currentTab as SettingPanel) === -1) {
return <PageLoading />;
}
const { SettingsDetail, Header } = getUIAdapter(currentWorkspace.flavour);

View File

@@ -31,7 +31,9 @@ const TrashPage: NextPageWithLayout = () => {
},
[currentWorkspace, jumpToPage]
);
if (!router.isReady || currentWorkspace === null) {
if (!router.isReady) {
return <PageLoading />;
} else if (currentWorkspace === null) {
return <PageLoading />;
}
// todo(himself65): refactor to plugin

16
nx.json
View File

@@ -12,17 +12,13 @@
"affected": {
"defaultBase": "master"
},
"implicitDependencies": {
"package.json": {
"dependencies": "*",
"devDependencies": "*"
},
"tsconfig.json": "*",
"nx.json": "*"
},
"namedInputs": {
"default": ["{projectRoot}/**/*"],
"production": ["!{projectRoot}/**/*.spec.tsx"]
"default": ["{projectRoot}/**/*", "sharedGlobals"],
"sharedGlobals": [
"{workspaceRoot}/tsconfig.json",
"{workspaceRoot}/nx.json"
],
"production": ["default"]
},
"targetDefaults": {
"build": {

View File

@@ -1,6 +1,6 @@
{
"name": "@affine/monorepo",
"version": "0.6.1-beta.0",
"version": "0.7.0-canary.13",
"private": true,
"author": "toeverything",
"license": "MPL-2.0",
@@ -72,7 +72,6 @@
"eslint-plugin-react": "^7.32.2",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-simple-import-sort": "^10.0.0",
"eslint-plugin-sonarjs": "^0.19.0",
"eslint-plugin-unicorn": "^47.0.0",
"eslint-plugin-unused-imports": "^2.0.0",
"fake-indexeddb": "4.0.1",

View File

@@ -15,5 +15,5 @@
"dependencies": {
"dotenv": "^16.1.4"
},
"version": "0.6.1-beta.0"
"version": "0.7.0-canary.13"
}

View File

@@ -66,5 +66,5 @@
"vite": "^4.3.9",
"yjs": "^13.6.1"
},
"version": "0.6.1-beta.0"
"version": "0.7.0-canary.13"
}

View File

@@ -49,9 +49,7 @@ export const updateAvailableAtom = atomWithObservable(() => {
return rpcToObservable(null as any | null, {
event: window.events?.updater.onUpdateAvailable,
onSubscribe: () => {
window.apis?.updater.checkForUpdatesAndNotify().catch(err => {
console.error(err);
});
window.apis?.updater.checkForUpdatesAndNotify();
},
});
});

View File

@@ -65,10 +65,7 @@ export function AppUpdaterButton({ className, style }: AddPageButtonProps) {
}, [currentVersion, setChangelogCheckAtom]);
const onClickUpdate = useCallback(() => {
if (updateReady) {
window.apis?.updater.quitAndInstall().catch(err => {
// TODO: add error toast here
console.error(err);
});
window.apis?.updater.quitAndInstall();
} else if (updateAvailable) {
if (updateAvailable.allowAutoUpdate) {
// wait for download to finish

View File

@@ -1,210 +0,0 @@
import type { MouseEvent as ReactMouseEvent, RefObject } from 'react';
import { useCallback, useEffect, useState } from 'react';
interface UseZoomControlsProps {
zoomRef: RefObject<HTMLDivElement>;
imageRef: RefObject<HTMLImageElement>;
}
export const useZoomControls = ({
zoomRef,
imageRef,
}: UseZoomControlsProps) => {
const [currentScale, setCurrentScale] = useState<number>(1);
const [isZoomedBigger, setIsZoomedBigger] = useState<boolean>(false);
const [isDragging, setIsDragging] = useState<boolean>(false);
const [mouseX, setMouseX] = useState<number>(0);
const [mouseY, setMouseY] = useState<number>(0);
const [dragBeforeX, setDragBeforeX] = useState<number>(0);
const [dragBeforeY, setDragBeforeY] = useState<number>(0);
const [imagePos, setImagePos] = useState<{ x: number; y: number }>({
x: 0,
y: 0,
});
const zoomIn = useCallback(() => {
const image = imageRef.current;
if (image && currentScale < 2) {
const newScale = currentScale + 0.1;
setCurrentScale(newScale);
image.style.width = `${image.naturalWidth * newScale}px`;
image.style.height = `${image.naturalHeight * newScale}px`;
}
}, [imageRef, currentScale]);
const zoomOut = useCallback(() => {
const image = imageRef.current;
if (image && currentScale > 0.2) {
const newScale = currentScale - 0.1;
setCurrentScale(newScale);
image.style.width = `${image.naturalWidth * newScale}px`;
image.style.height = `${image.naturalHeight * newScale}px`;
const zoomedWidth = image.naturalWidth * newScale;
const zoomedHeight = image.naturalHeight * newScale;
const containerWidth = window.innerWidth;
const containerHeight = window.innerHeight;
if (zoomedWidth > containerWidth || zoomedHeight > containerHeight) {
image.style.transform = `translate(0px, 0px)`;
setImagePos({ x: 0, y: 0 });
}
}
}, [imageRef, currentScale]);
const checkZoomSize = useCallback(() => {
const { current: zoomArea } = zoomRef;
if (zoomArea) {
const image = zoomArea.querySelector('img');
if (image) {
const zoomedWidth = image.naturalWidth * currentScale;
const zoomedHeight = image.naturalHeight * currentScale;
const containerWidth = window.innerWidth;
const containerHeight = window.innerHeight;
setIsZoomedBigger(
zoomedWidth > containerWidth || zoomedHeight > containerHeight
);
}
}
}, [currentScale, zoomRef]);
const resetZoom = useCallback(() => {
const image = imageRef.current;
if (image) {
const viewportWidth = window.innerWidth;
const viewportHeight = window.innerHeight;
const margin = 0.2;
const availableWidth = viewportWidth * (1 - margin);
const availableHeight = viewportHeight * (1 - margin);
const widthRatio = availableWidth / image.naturalWidth;
const heightRatio = availableHeight / image.naturalHeight;
const newScale = Math.min(widthRatio, heightRatio);
setCurrentScale(newScale);
image.style.width = `${image.naturalWidth * newScale}px`;
image.style.height = `${image.naturalHeight * newScale}px`;
image.style.transform = 'translate(0px, 0px)';
setImagePos({ x: 0, y: 0 });
checkZoomSize();
}
}, [checkZoomSize, imageRef]);
const handleDragStart = useCallback(
(event: ReactMouseEvent) => {
event?.preventDefault();
setIsDragging(true);
const image = imageRef.current;
if (image && isZoomedBigger) {
image.style.cursor = 'grab';
const rect = image.getBoundingClientRect();
setDragBeforeX(rect.left);
setDragBeforeY(rect.top);
setMouseX(event.clientX);
setMouseY(event.clientY);
}
},
[imageRef, isZoomedBigger]
);
const handleDrag = useCallback(
(event: ReactMouseEvent) => {
event?.preventDefault();
const image = imageRef.current;
if (isDragging && image && isZoomedBigger) {
image.style.cursor = 'grabbing';
const currentX = imagePos.x;
const currentY = imagePos.y;
const newPosX = currentX + event.clientX - mouseX;
const newPosY = currentY + event.clientY - mouseY;
image.style.transform = `translate(${newPosX}px, ${newPosY}px)`;
}
},
[
imagePos.x,
imagePos.y,
imageRef,
isDragging,
isZoomedBigger,
mouseX,
mouseY,
]
);
const dragEndImpl = useCallback(() => {
setIsDragging(false);
const image = imageRef.current;
if (image && isZoomedBigger && isDragging) {
image.style.cursor = 'pointer';
const rect = image.getBoundingClientRect();
const newPos = { x: rect.left, y: rect.top };
const currentX = imagePos.x;
const currentY = imagePos.y;
const newPosX = currentX + newPos.x - dragBeforeX;
const newPosY = currentY + newPos.y - dragBeforeY;
setImagePos({ x: newPosX, y: newPosY });
}
}, [
dragBeforeX,
dragBeforeY,
imagePos.x,
imagePos.y,
imageRef,
isDragging,
isZoomedBigger,
]);
const handleDragEnd = useCallback(
(event: ReactMouseEvent) => {
event.preventDefault();
dragEndImpl();
},
[dragEndImpl]
);
const handleMouseUp = useCallback(() => {
if (isDragging) {
dragEndImpl();
}
}, [isDragging, dragEndImpl]);
useEffect(() => {
const handleScroll = (event: WheelEvent) => {
const { deltaY } = event;
if (deltaY > 0) {
zoomOut();
} else if (deltaY < 0) {
zoomIn();
}
};
const handleResize = () => {
checkZoomSize();
};
checkZoomSize();
window.addEventListener('wheel', handleScroll, { passive: false });
window.addEventListener('resize', handleResize);
window.addEventListener('mouseup', handleMouseUp);
return () => {
window.removeEventListener('wheel', handleScroll);
window.removeEventListener('resize', handleResize);
window.removeEventListener('mouseup', handleMouseUp);
};
}, [zoomIn, zoomOut, checkZoomSize, handleMouseUp]);
return {
zoomIn,
zoomOut,
resetZoom,
isZoomedBigger,
currentScale,
handleDragStart,
handleDrag,
handleDragEnd,
};
};

View File

@@ -11,8 +11,7 @@ export const imagePreviewModalStyle = style({
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
// background: 'var(--affine-background-modal-color)',
background: 'rgba(0,0,0,0.75)',
background: 'var(--affine-background-modal-color)',
});
export const imagePreviewModalCloseButtonStyle = style({
@@ -21,9 +20,11 @@ export const imagePreviewModalCloseButtonStyle = style({
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
height: '36px',
width: '36px',
borderRadius: '10px',
top: '0.5rem',
right: '0.5rem',
background: 'var(--affine-white)',
@@ -32,97 +33,37 @@ export const imagePreviewModalCloseButtonStyle = style({
cursor: 'pointer',
color: 'var(--affine-icon-color)',
transition: 'background 0.2s ease-in-out',
zIndex: 1,
});
export const imagePreviewModalGoStyle = style({
height: '50%',
color: 'var(--affine-white)',
position: 'absolute',
fontSize: '60px',
lineHeight: '60px',
fontWeight: 'bold',
display: 'flex',
alignItems: 'center',
opacity: '0.2',
padding: '0 15px',
cursor: 'pointer',
});
export const imageNavigationControlStyle = style({
display: 'flex',
height: '100%',
zIndex: 2,
justifyContent: 'space-between',
alignItems: 'center',
});
export const imagePreviewModalContainerStyle = style({
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
zIndex: 1,
'@media': {
'screen and (max-width: 768px)': {
alignItems: 'center',
},
},
position: 'absolute',
top: '20%',
});
export const imagePreviewModalCenterStyle = style({
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
});
export const imagePreviewModalCaptionStyle = style({
color: 'var(--affine-white)',
marginTop: '24px',
'@media': {
'screen and (max-width: 768px)': {
textAlign: 'center',
},
},
});
export const imagePreviewActionBarStyle = style({
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
padding: '16px 0',
backgroundColor: 'var(--affine-white)',
borderRadius: '8px',
boxShadow: '2px 2px 4px rgba(0, 0, 0, 0.3)',
maxWidth: 'max-content',
});
export const groupStyle = style({
display: 'inline-flex',
alignItems: 'center',
justifyContent: 'center',
backgroundColor: 'var(--affine-white)',
borderLeft: '1px solid #E3E2E4',
});
export const buttonStyle = style({
paddingLeft: '10px',
paddingRight: '10px',
});
export const scaleIndicatorStyle = style({
margin: '0 8px',
});
export const imageBottomContainerStyle = style({
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
position: 'fixed',
bottom: '28px',
zIndex: baseTheme.zIndexModal + 1,
});
export const captionStyle = style({
export const imagePreviewModalImageStyle = style({
background: 'transparent',
maxWidth: '686px',
color: 'var(--affine-white)',
background: 'rgba(0,0,0,0.75)',
padding: '10px',
marginBottom: '21px',
objectFit: 'contain',
objectPosition: 'center',
borderRadius: '4px',
});
export const imagePreviewModalActionsStyle = style({
position: 'absolute',
bottom: '28px',
background: 'var(--affine-white)',
});

View File

@@ -3,40 +3,19 @@ import '@blocksuite/blocks';
import type { EmbedBlockModel } from '@blocksuite/blocks';
import { assertExists } from '@blocksuite/global/utils';
import {
ArrowLeftSmallIcon,
ArrowRightSmallIcon,
CopyIcon,
DeleteIcon,
DownloadIcon,
MinusIcon,
PlusIcon,
ViewBarIcon,
} from '@blocksuite/icons';
import type { Workspace } from '@blocksuite/store';
import clsx from 'clsx';
import { useAtom } from 'jotai';
import type { ReactElement } from 'react';
import { Suspense, useCallback } from 'react';
import { useEffect, useRef, useState } from 'react';
import useSWR from 'swr';
import Button from '../../ui/button/button';
import { useZoomControls } from './hooks/use-zoom';
import {
buttonStyle,
captionStyle,
groupStyle,
imageBottomContainerStyle,
imageNavigationControlStyle,
imagePreviewActionBarStyle,
imagePreviewModalCaptionStyle,
imagePreviewModalCenterStyle,
imagePreviewModalCloseButtonStyle,
imagePreviewModalContainerStyle,
imagePreviewModalGoStyle,
imagePreviewModalImageStyle,
imagePreviewModalStyle,
scaleIndicatorStyle,
} from './index.css';
import { previewBlockIdAtom } from './index.jotai';
@@ -52,46 +31,38 @@ const ImagePreviewModalImpl = (
}
): ReactElement | null => {
const [blockId, setBlockId] = useAtom(previewBlockIdAtom);
const [bIsActionBarVisible, setBIsActionBarVisible] = useState(false);
const [caption, setCaption] = useState(() => {
const page = props.workspace.getPage(props.pageId);
assertExists(page);
const block = page.getBlockById(props.blockId) as EmbedBlockModel;
const block = page.getBlockById(props.blockId) as EmbedBlockModel | null;
assertExists(block);
return block?.caption;
return block.caption;
});
useEffect(() => {
const page = props.workspace.getPage(props.pageId);
assertExists(page);
const block = page.getBlockById(props.blockId) as EmbedBlockModel;
const block = page.getBlockById(props.blockId) as EmbedBlockModel | null;
assertExists(block);
setCaption(block?.caption);
const disposable = block.propsUpdated.on(() => {
setCaption(block.caption);
});
return () => {
disposable.dispose();
};
}, [props.blockId, props.pageId, props.workspace]);
const { data } = useSWR(['workspace', 'embed', props.pageId, props.blockId], {
fetcher: ([_, __, pageId, blockId]) => {
const page = props.workspace.getPage(pageId);
assertExists(page);
const block = page.getBlockById(blockId) as EmbedBlockModel;
const block = page.getBlockById(blockId) as EmbedBlockModel | null;
assertExists(block);
return props.workspace.blobs.get(block?.sourceId);
return props.workspace.blobs.get(block.sourceId);
},
suspense: true,
});
const zoomRef = useRef<HTMLDivElement | null>(null);
const imageRef = useRef<HTMLImageElement | null>(null);
const {
zoomIn,
zoomOut,
isZoomedBigger,
handleDrag,
handleDragStart,
handleDragEnd,
resetZoom,
currentScale,
} = useZoomControls({ zoomRef, imageRef });
const [prevData, setPrevData] = useState<string | null>(() => data);
const [url, setUrl] = useState<string | null>(null);
const imageRef = useRef<HTMLImageElement>(null);
if (prevData !== data) {
if (url) {
URL.revokeObjectURL(url);
@@ -105,224 +76,8 @@ const ImagePreviewModalImpl = (
if (!url) {
return null;
}
const nextImageHandler = (blockId: string | null) => {
assertExists(blockId);
const workspace = props.workspace;
const page = workspace.getPage(props.pageId);
assertExists(page);
const block = page.getBlockById(blockId);
assertExists(block);
const nextBlock = page
.getNextSiblings(block)
.find(
(block): block is EmbedBlockModel => block.flavour === 'affine:embed'
);
if (nextBlock) {
setBlockId(nextBlock.id);
}
};
const previousImageHandler = (blockId: string | null) => {
assertExists(blockId);
const workspace = props.workspace;
const page = workspace.getPage(props.pageId);
assertExists(page);
const block = page.getBlockById(blockId);
assertExists(block);
const prevBlock = page
.getPreviousSiblings(block)
.findLast(
(block): block is EmbedBlockModel => block.flavour === 'affine:embed'
);
if (prevBlock) {
setBlockId(prevBlock.id);
}
};
const deleteHandler = (blockId: string) => {
const workspace = props.workspace;
const page = workspace.getPage(props.pageId);
assertExists(page);
const block = page.getBlockById(blockId);
assertExists(block);
if (
page
.getPreviousSiblings(block)
.findLast(
(block): block is EmbedBlockModel => block.flavour === 'affine:embed'
)
) {
const prevBlock = page
.getPreviousSiblings(block)
.findLast(
(block): block is EmbedBlockModel => block.flavour === 'affine:embed'
);
if (prevBlock) {
setBlockId(prevBlock.id);
}
} else if (
page
.getNextSiblings(block)
.find(
(block): block is EmbedBlockModel => block.flavour === 'affine:embed'
)
) {
const nextBlock = page
.getNextSiblings(block)
.find(
(block): block is EmbedBlockModel => block.flavour === 'affine:embed'
);
if (nextBlock) {
const image = imageRef.current;
resetZoom();
if (image) {
image.style.width = '100%'; // Reset the width to its original size
image.style.height = 'auto'; // Reset the height to maintain aspect ratio
}
setBlockId(nextBlock.id);
}
} else {
props.onClose();
}
page.deleteBlock(block);
};
let actionbarTimeout: NodeJS.Timeout;
const downloadHandler = async (blockId: string | null) => {
const workspace = props.workspace;
const page = workspace.getPage(props.pageId);
assertExists(page);
if (typeof blockId === 'string') {
const block = page.getBlockById(blockId) as EmbedBlockModel;
assertExists(block);
const store = await block.page.blobs;
const url = store?.get(block.sourceId);
const img = await url;
if (!img) {
return;
}
const arrayBuffer = await img.arrayBuffer();
const buffer = new Uint8Array(arrayBuffer);
let fileType: string;
if (
buffer[0] === 0x47 &&
buffer[1] === 0x49 &&
buffer[2] === 0x46 &&
buffer[3] === 0x38
) {
fileType = 'image/gif';
} else if (
buffer[0] === 0x89 &&
buffer[1] === 0x50 &&
buffer[2] === 0x4e &&
buffer[3] === 0x47
) {
fileType = 'image/png';
} else if (
buffer[0] === 0xff &&
buffer[1] === 0xd8 &&
buffer[2] === 0xff &&
buffer[3] === 0xe0
) {
fileType = 'image/jpeg';
} else {
// unknown, fallback to png
console.error('unknown image type');
fileType = 'image/png';
}
const downloadUrl = URL.createObjectURL(
new Blob([arrayBuffer], { type: fileType })
);
const a = document.createElement('a');
const event = new MouseEvent('click');
a.download = block.id;
a.href = downloadUrl;
a.dispatchEvent(event);
// cleanup
a.remove();
URL.revokeObjectURL(downloadUrl);
}
};
const handleMouseEnter = () => {
clearTimeout(actionbarTimeout);
setBIsActionBarVisible(true);
};
const handleMouseLeave = () => {
actionbarTimeout = setTimeout(() => {
setBIsActionBarVisible(false);
}, 3000);
};
return (
<div
data-testid="image-preview-modal"
className={imagePreviewModalStyle}
onClick={event =>
event.target === event.currentTarget ? props.onClose() : null
}
>
{!isZoomedBigger ? (
<div className={imageNavigationControlStyle}>
<span
className={imagePreviewModalGoStyle}
style={{
left: 0,
}}
onClick={() => {
assertExists(blockId);
previousImageHandler(blockId);
}}
>
</span>
<span
className={imagePreviewModalGoStyle}
style={{
right: 0,
}}
onClick={() => {
assertExists(blockId);
nextImageHandler(blockId);
}}
>
</span>
</div>
) : (
<></>
)}
<div className={imagePreviewModalContainerStyle}>
<div
className={clsx('zoom-area', { 'zoomed-bigger': isZoomedBigger })}
ref={zoomRef}
>
<div className={imagePreviewModalCenterStyle}>
<img
data-blob-id={props.blockId}
src={url}
alt={caption}
ref={imageRef}
draggable={isZoomedBigger}
onMouseDown={handleDragStart}
onMouseMove={handleDrag}
onMouseUp={handleDragEnd}
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
onLoad={resetZoom}
/>
{isZoomedBigger ? null : (
<p className={imagePreviewModalCaptionStyle}>{caption}</p>
)}
</div>
</div>
</div>
<div data-testid="image-preview-modal" className={imagePreviewModalStyle}>
<button
onClick={() => {
props.onClose();
@@ -344,123 +99,67 @@ const ImagePreviewModalImpl = (
/>
</svg>
</button>
{bIsActionBarVisible ? (
<div
className={imageBottomContainerStyle}
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
onClick={event => event.stopPropagation()}
>
{isZoomedBigger && caption !== '' ? (
<p className={captionStyle}>{caption}</p>
) : null}
<div className={imagePreviewActionBarStyle}>
<div>
<Button
icon={<ArrowLeftSmallIcon />}
noBorder={true}
className={buttonStyle}
onClick={() => {
assertExists(blockId);
previousImageHandler(blockId);
}}
/>
<Button
icon={<ArrowRightSmallIcon />}
noBorder={true}
className={buttonStyle}
onClick={() => {
assertExists(blockId);
nextImageHandler(blockId);
}}
/>
</div>
<div className={groupStyle}>
<Button
icon={<ViewBarIcon />}
noBorder={true}
className={buttonStyle}
onClick={() => resetZoom()}
/>
<Button
icon={<MinusIcon />}
noBorder={true}
className={buttonStyle}
onClick={zoomOut}
/>
<span className={scaleIndicatorStyle}>{`${(
currentScale * 100
).toFixed(0)}%`}</span>
<Button
icon={<PlusIcon />}
noBorder={true}
className={buttonStyle}
onClick={() => zoomIn()}
/>
</div>
<div className={groupStyle}>
<Button
icon={<DownloadIcon />}
noBorder={true}
className={buttonStyle}
onClick={() => {
assertExists(blockId);
downloadHandler(blockId).catch(err => {
console.error('Could not download image', err);
});
}}
/>
<Button
icon={<CopyIcon />}
noBorder={true}
className={buttonStyle}
onClick={() => {
if (!imageRef.current) {
return;
}
const canvas = document.createElement('canvas');
canvas.width = imageRef.current.naturalWidth;
canvas.height = imageRef.current.naturalHeight;
const context = canvas.getContext('2d');
if (!context) {
console.warn('Could not get canvas context');
return;
}
context.drawImage(imageRef.current, 0, 0);
canvas.toBlob(blob => {
if (!blob) {
console.warn('Could not get blob');
return;
}
const dataUrl = URL.createObjectURL(blob);
navigator.clipboard
.write([new ClipboardItem({ 'image/png': blob })])
.then(() => {
console.log('Image copied to clipboard');
URL.revokeObjectURL(dataUrl);
})
.catch(error => {
console.error(
'Error copying image to clipboard',
error
);
URL.revokeObjectURL(dataUrl);
});
}, 'image/png');
}}
/>
</div>
<div className={groupStyle}>
<Button
icon={<DeleteIcon />}
noBorder={true}
className={buttonStyle}
onClick={() => blockId && deleteHandler(blockId)}
/>
</div>
</div>
</div>
) : null}
<span
className={imagePreviewModalGoStyle}
style={{
left: 0,
}}
onClick={() => {
assertExists(blockId);
const workspace = props.workspace;
const page = workspace.getPage(props.pageId);
assertExists(page);
const block = page.getBlockById(blockId);
assertExists(block);
const prevBlock = page
.getPreviousSiblings(block)
.findLast(
(block): block is EmbedBlockModel =>
block.flavour === 'affine:embed'
);
if (prevBlock) {
setBlockId(prevBlock.id);
}
}}
>
</span>
<div className={imagePreviewModalContainerStyle}>
<img
data-blob-id={props.blockId}
alt={caption}
className={imagePreviewModalImageStyle}
ref={imageRef}
src={url}
/>
</div>
<span
className={imagePreviewModalGoStyle}
style={{
right: 0,
}}
onClick={() => {
assertExists(blockId);
const workspace = props.workspace;
const page = workspace.getPage(props.pageId);
assertExists(page);
const block = page.getBlockById(blockId);
assertExists(block);
const nextBlock = page
.getNextSiblings(block)
.find(
(block): block is EmbedBlockModel =>
block.flavour === 'affine:embed'
);
if (nextBlock) {
setBlockId(nextBlock.id);
}
}}
>
</span>
</div>
);
};

View File

@@ -9,15 +9,8 @@ export const CopyLink = ({ onItemClick, onSelect }: CommonMenuItemProps) => {
const t = useAFFiNEI18N();
const copyUrl = useCallback(() => {
navigator.clipboard
.writeText(window.location.href)
.then(() => {
toast(t['Copied link to clipboard']());
})
.catch(err => {
// TODO add error toast here
console.error(err);
});
navigator.clipboard.writeText(window.location.href);
toast(t['Copied link to clipboard']());
}, [t]);
return (

View File

@@ -35,13 +35,8 @@ const ExportToPdfMenuItem = ({
if (result !== undefined) {
return;
}
return contentParser.exportPdf();
})
.then(() => {
contentParser.exportPdf();
onSelect?.({ type: 'pdf' });
})
.catch(err => {
console.error(err);
});
}, [currentEditor, onSelect]);
if (currentEditor && currentEditor.mode === 'page') {
@@ -71,9 +66,7 @@ const ExportToHtmlMenuItem = ({
if (!contentParserRef.current) {
contentParserRef.current = new ContentParser(currentEditor.page);
}
contentParserRef.current.exportHtml().catch(err => {
console.error(err);
});
contentParserRef.current.exportHtml();
onSelect?.({ type: 'html' });
}, [onSelect, currentEditor]);
return (
@@ -130,9 +123,7 @@ const ExportToMarkdownMenuItem = ({
if (!contentParserRef.current) {
contentParserRef.current = new ContentParser(currentEditor.page);
}
contentParserRef.current.exportMarkdown().catch(err => {
console.error(err);
});
contentParserRef.current.exportMarkdown();
onSelect?.({ type: 'markdown' });
}, [onSelect, currentEditor]);
return (

View File

@@ -10,11 +10,7 @@ const DesktopThemeSync = memo(function DesktopThemeSync() {
const onceRef = useRef(false);
if (lastThemeRef.current !== theme || !onceRef.current) {
if (environment.isDesktop && theme) {
window.apis?.ui
.handleThemeChange(theme as 'dark' | 'light' | 'system')
.catch(err => {
console.error(err);
});
window.apis?.ui.handleThemeChange(theme as 'dark' | 'light' | 'system');
}
lastThemeRef.current = theme;
onceRef.current = true;

View File

@@ -8,5 +8,5 @@
"devDependencies": {
"@types/debug": "^4.1.8"
},
"version": "0.6.1-beta.0"
"version": "0.7.0-canary.13"
}

View File

@@ -28,5 +28,5 @@
"dependencies": {
"lit": "^2.7.5"
},
"version": "0.6.1-beta.0"
"version": "0.7.0-canary.13"
}

View File

@@ -3,7 +3,7 @@ import type { Page } from '@blocksuite/store';
export async function initPageWithPreloading(page: Page) {
const workspace = page.workspace;
const { data } = await import('@affine/templates/preloading.json');
await workspace.importPageSnapshot(data['space:hello-world'], page.id);
await workspace.importPageSnapshot(data['space:Qmo9-1SGTB'], page.id);
}
export function initEmptyPage(page: Page): void {

View File

@@ -1,6 +1,6 @@
{
"name": "@affine/graphql",
"version": "0.6.1-beta.0",
"version": "0.7.0-canary.13",
"description": "Autogenerated GraphQL client for affine.pro",
"license": "MPL-2.0",
"type": "module",

View File

@@ -8,5 +8,5 @@
"@affine/env": "workspace:*",
"@toeverything/y-indexeddb": "workspace:*"
},
"version": "0.6.1-beta.0"
"version": "0.7.0-canary.13"
}

View File

@@ -36,5 +36,5 @@
"ts-node": "^10.9.1",
"typescript": "^5.1.3"
},
"version": "0.6.1-beta.0"
"version": "0.7.0-canary.13"
}

View File

@@ -4,7 +4,7 @@
"Copied link to clipboard": "Link in die Zwischenablage kopiert",
"Local Workspace Description": "Alle Daten sind auf dem aktuellen Gerät gespeichert. Du kannst AFFiNE Cloud für diesen Workspace aktivieren, um deine Daten mit der Cloud zu synchronisieren.",
"Download all data": "Alle Daten herunterladen",
"It takes up little space on your device": "Es verbraucht nur wenig Speicherplatz auf deinem Gerät.",
"It takes up little space on your device": "Es nimmt nur wenig Platz auf deinem Gerät ein.",
"Help and Feedback": "Hilfe und Feedback",
"Not now": "Vielleicht später",
"Please make sure you are online": "Bitte stelle sicher, dass du online bist",
@@ -189,13 +189,10 @@
"Data sync mode": "Daten-Sync Modus",
"Download core data": "Core Daten herunterladen",
"Check Our Docs": "Sieh dir unsere Dokumentation an",
"Get in touch! Join our communities": "Bleib mit uns in Kontakt und trete unseren Communitys bei!",
"Get in touch! Join our communities": "Nimm teil! Treten Sie unseren Communities bei.",
"Move to Trash": "In Papierkorb verschieben",
"Placeholder of delete workspace": "Bitte zur Bestätigung den Workspace-Namen eingeben",
"Access level": "Zugriffsberechtigung",
"Loading Page": "Lade Seite",
"Loading All Workspaces": "Lade alle Workspaces",
"Discover what's new!": "Erfahre was neu ist!",
"Move to": "Verschieben zu",
"Disable": "Deaktivieren",
"Open Workspace Settings": "Workspace Einstellungen öffnen",
@@ -203,21 +200,18 @@
"Workspace Not Found": "Workspace nicht gefunden",
"Rename": "Umbenennen",
"Page is Loading": "Seite lädt",
"Discover what's new!": "Erfahre was neu ist!",
"Loading All Workspaces": "Lade alle Workspaces",
"Loading Page": "Lade Seite",
"Create Shared Link Description": "Erstelle einen Link, den du leicht mit jedem teilen kannst.",
"Back to Quick Search": "Zurück zur Schnellsuche",
"Disable Public Link": "Öffentlichen Link deaktivieren",
"Disable Public Link ?": "Öffentlichen Link deaktivieren ?",
"Export Shared Pages Description": "Laden eine statische Kopie dieser Seite herunter, um sie mit anderen zu teilen.",
"Favorite pages for easy access": "Favoriten-Seiten für schnellen Zugriff",
"Move page to": "Seite verschieben nach...",
"Navigation Path": "Navigationspfad",
"Pivots": "Pivots",
"RFP": "Seiten können frei zu Pivots hinzugefügt/entfernt werden und bleiben über \"Alle Seiten\" zugänglich.",
"Remove from Pivots": "Von Pivots entfernen",
"Router is Loading": "Router lädt",
"Share Menu Public Workspace Description1": "Laden andere ein, dem Workspace beizutreten oder veröffentliche ihn im Internet.",
"Share Menu Public Workspace Description2": "Der aktuelle Workspace wurde im Internet als öffentlicher Workspace veröffentlicht.",
"View Navigation Path": "Navigationspfad ansehen",
"Add a subpage inside": "Unterseite hinzufügen",
"Disable Public Link Description": "Wenn du diesen öffentlichen Link deaktivierst, können andere Personen mit diesem Link nicht mehr auf diese Seite zugreifen.",
"Disable Public Sharing": "Öffentliche Freigabe deaktivieren",
@@ -227,8 +221,58 @@
"Shared Pages Description": "Die öffentliche Freigabe der Seite erfordert den AFFiNE-Cloud-Dienst.",
"Shared Pages In Public Workspace Description": "Der gesamte Workspace wird im Web veröffentlicht und kann über <1>Workspace Einstellungen</1> bearbeitet werden.",
"emptySharedPages": "Freigegebene Seiten werden hier angezeigt.",
"Recent": "Neueste",
"Synced with AFFiNE Cloud": "Synchronisiert mit AFFiNE Cloud",
"Successfully deleted": "Erfolgreich gelöscht",
"You cannot delete the last workspace": "Du kannst den letzten Workspace nicht löschen"
"You cannot delete the last workspace": "Du kannst den letzten Workspace nicht löschen",
"Move page to": "Seite verschieben nach...",
"Navigation Path": "Navigationspfad",
"Recent": "Neueste",
"Export Shared Pages Description": "Laden eine statische Kopie dieser Seite herunter, um sie mit anderen zu teilen.",
"Share Menu Public Workspace Description1": "Laden andere ein, dem Workspace beizutreten oder veröffentliche ihn im Internet.",
"Share Menu Public Workspace Description2": "Der aktuelle Workspace wurde im Internet als öffentlicher Workspace veröffentlicht.",
"View Navigation Path": "Navigationspfad ansehen",
"Delete Workspace Label Hint": "Wenn dieser Workspace gelöscht wird, wird sein gesamter Inhalt für alle Benutzer dauerhaft gelöscht. Niemand wird in der Lage sein, den Inhalt dieses Workspaces wiederherzustellen.",
"Added Successfully": "Erfolgreich hinzugefügt",
"Continue": "Fortfahren",
"Create your own workspace": "Eigenen Workspace erstellen",
"Created Successfully": "Erfolgreich erstellt",
"Customize": "Anpassen",
"FILE_ALREADY_EXISTS": "Datei existiert bereits",
"Move folder": "Ordner verschieben",
"Move folder hint": "Neuen Speicherort auswählen.",
"Add Workspace Hint": "Auswählen, was du schon hast",
"Change avatar hint": "Avatar von allen Mitgliedern ändern.",
"Change workspace name hint": "Name von allen Mitgliedern ändern.",
"DB_FILE_ALREADY_LOADED": "Datenbankdatei bereits geladen",
"DB_FILE_INVALID": "Ungültige Datenbankdatei",
"DB_FILE_PATH_INVALID": "Pfad der Datenbankdatei ungültig",
"Default Location": "Standard-Speicherort",
"Default db location hint": "Standardmäßig wird unter {{location}} gespeichert.",
"Move folder success": "Ordnerverschiebung erfolgreich",
"Open folder": "Ordner öffnen",
"Save": "Speichern",
"Set database location": "Datenbankstandort festlegen",
"UNKNOWN_ERROR": "Unbekannter Fehler",
"Open folder hint": "Prüfe, wo sich der Speicherordner befindet.",
"Storage Folder": "Speicherordner",
"Storage Folder Hint": "Speicherort überprüfen oder ändern.",
"Sync across devices with AFFiNE Cloud": "Geräteübergreifende Synchronisierung mit AFFiNE Cloud",
"Name Your Workspace": "Workspace benennen",
"Update Available": "Update verfügbar",
"com.affine.edgelessMode": "Edgeless-Modus",
"com.affine.onboarding.title2": "Intuitive und robuste, blockbasierte Bearbeitung",
"com.affine.onboarding.videoDescription1": "Wechsle mühelos zwischen dem Seitenmodus für die strukturierte Dokumentenerstellung und dem Whiteboard-Modus für den Ausdruck kreativer Ideen in freier Form.",
"com.affine.onboarding.videoDescription2": "Verwende eine modulare Schnittstelle, um strukturierte Dokumente zu erstellen, indem du Textblöcke, Bilder und andere Inhalte einfach per Drag-and-drop anordnen kannst.",
"com.affine.onboarding.title1": "Hyperfusion von Whiteboard und Dokumenten",
"com.affine.pageMode": "Seitenmodus",
"Update workspace name success": "Update vom Workspace-Namen erfolgreich",
"Use on current device only": "Nur auf dem aktuellen Gerät verwenden",
"Workspace database storage description": "Wähle den Ort, an dem du deinen Workspace erstellen möchten. Die Daten vom Workspace werden standardmäßig lokal gespeichert.",
"dark": "dunkel",
"system": "system",
"Restart Install Client Update": "Neustart zum Installieren des Updates",
"Add Workspace": "Workspace hinzufügen",
"Export success": "Export erfolgreich",
"light": "hell",
"others": "Andere"
}

View File

@@ -18,7 +18,6 @@
"No item": "No item",
"Import": "Import",
"Trash": "Trash",
"others": "Others",
"New Page": "New Page",
"com.affine.write_with_a_blank_page": "Write with a blank page",
"com.affine.new_edgeless": "New Edgeless",
@@ -266,16 +265,12 @@
"Move folder hint": "Select a new storage location.",
"Storage Folder": "Storage Folder",
"DB_FILE_INVALID": "Invalid Database file",
"FILE_ALREADY_EXISTS": "File already exists",
"Name Your Workspace": "Name Your Workspace",
"Change avatar hint": "New avatar will be shown for everyone.",
"Change workspace name hint": "New name will be shown for everyone.",
"Delete Workspace Label Hint": "After deleting this Workspace, you will permanently delete all of its content for everyone. No one will be able to recover the content of this Workspace.",
"DB_FILE_PATH_INVALID": "Database file path invalid",
"Default db location hint": "By default will be saved to {{location}}",
"light": "light",
"dark": "dark",
"system": "system",
"com.affine.pageMode": "Page Mode",
"com.affine.edgelessMode": "Edgeless Mode",
"com.affine.onboarding.title1": "Hyper merged whiteboard and docs",

View File

@@ -12,13 +12,13 @@
"Retain cached cloud data": "保留缓存的云数据",
"Workspace Owner": "工作区所有者",
"Cloud Workspace": "云端工作区",
"Cloud Workspace Description": "所有数据将被同步并保存在AFFiNE账户(<1>{{email}}</1>)中",
"Copied link to clipboard": "复制链接到剪贴板",
"Available Offline": "可供离线使用",
"Back Home": "返回首页",
"Enabled success": "启用成功",
"Published Description": "当前工作区已被发布到Web所有人都可以通过链接来查看此工作区内容。",
"All data has been stored in the cloud": "所有数据已被保存在云端。",
"Cloud Workspace Description": "所有数据将被同步并保存在 AFFiNE 账户(<1>{{email}}</1>)中",
"Published Description": "当前工作区已被发布到 Web所有人都可以通过链接来查看此工作区内容。",
"Download data": "下载 {{CoreOrAll}} 数据",
"Force Sign Out": "强制登出",
"Joined Workspace": "加入工作区",
@@ -73,18 +73,15 @@
"Access level": "访问权限",
"Added to Favorites": "已收藏",
"Collaboration": "协作",
"Collaboration Description": "与其他成员协作需要AFFiNE云服务支持。",
"Continue with Google": "谷歌登录以继续",
"Delete page?": "确定要删除页面?",
"Delete permanently": "永久删除",
"Delete permanently?": "是否永久删除?",
"Edgeless": "无界",
"Enable AFFiNE Cloud": "启用 AFFiNE 云服务",
"Enable AFFiNE Cloud Description": "如启用此工作区中的数据将通过AFFiNE Cloud进行备份和同步。",
"Favorites": "收藏夹",
"Get in touch!": "保持联络!",
"Got it": "知道了",
"How is AFFiNE Alpha different?": "AFFiNE Alpha有何不同",
"Invite": "邀请",
"Invite Members": "邀请成员",
"Invite placeholder": "搜索邮件仅支持Gmail",
@@ -94,12 +91,16 @@
"Leave Workspace": "退出工作区",
"Leave Workspace Description": "退出后,您将无法再访问此工作区的内容。",
"Link": "超链接(选定文本)",
"Collaboration Description": "与其他成员协作需要 AFFiNE 云服务支持。",
"Moved to Trash": "已移到垃圾箱",
"My Workspaces": "我的工作区",
"Enable AFFiNE Cloud Description": "如启用,此工作区中的数据将通过 AFFiNE Cloud 进行备份和同步。",
"How is AFFiNE Alpha different?": "AFFiNE Alpha 有何不同?",
"Non-Gmail": "不支持非 Gmail 邮箱",
"Publishing": "发布到 web 需要 AFFiNE 云服务。",
"New Page": "新建页面",
"New Workspace": "新建工作区",
"No item": "无项目",
"Non-Gmail": "不支持非Gmail邮箱",
"NotLoggedIn": "当前未登录",
"Official Website": "官网",
"Once deleted, you can't undo this action": "一旦删除,您将无法撤销此操作。",
@@ -115,7 +116,6 @@
"Pending": "待定",
"Permanently deleted": "已永久删除",
"Publish": "发布",
"Publishing": "发布到web需要AFFiNE云服务。",
"Publish to web": "发布到web",
"Quick search": "快速搜索",
"Quick search placeholder": "快速搜索...",

View File

@@ -28,5 +28,5 @@
"vite": "^4.3.9",
"vite-plugin-dts": "^2.3.0"
},
"version": "0.6.1-beta.0"
"version": "0.7.0-canary.13"
}

View File

@@ -21,5 +21,5 @@
"@blocksuite/store": "*",
"lottie-web": "*"
},
"version": "0.6.1-beta.0"
"version": "0.7.0-canary.13"
}

View File

@@ -35,5 +35,5 @@
"test": "cross-env TS_NODE_TRANSPILE_ONLY=1 TS_NODE_PROJECT=./tsconfig.json node --test --loader ts-node/esm --experimental-specifier-resolution=node ./__tests__/**/*.mts",
"version": "napi version"
},
"version": "0.6.1-beta.0"
"version": "0.7.0-canary.13"
}

View File

@@ -22,8 +22,7 @@
"@blocksuite/editor": "0.0.0-20230607055421-9b20fcaf-nightly",
"@blocksuite/global": "0.0.0-20230607055421-9b20fcaf-nightly",
"@blocksuite/lit": "0.0.0-20230607055421-9b20fcaf-nightly",
"@blocksuite/store": "0.0.0-20230607055421-9b20fcaf-nightly",
"jotai": "^2.1.1"
"@blocksuite/store": "0.0.0-20230607055421-9b20fcaf-nightly"
},
"devDependencies": {
"jotai": "^2.1.1",
@@ -40,5 +39,5 @@
"react": "*",
"react-dom": "*"
},
"version": "0.6.1-beta.0"
"version": "0.7.0-canary.13"
}

View File

@@ -32,21 +32,15 @@ export function definePlugin<ID extends string>(
if (isServer) {
if (serverAdapter) {
console.log('register server adapter');
serverAdapter
.load()
.then(({ default: adapter }) => {
rootStore.set(affinePluginsAtom, plugins => ({
...plugins,
[definition.id]: {
...basePlugin,
serverAdapter: adapter,
},
}));
})
.catch(err => {
console.error(err);
});
serverAdapter.load().then(({ default: adapter }) => {
rootStore.set(affinePluginsAtom, plugins => ({
...plugins,
[definition.id]: {
...basePlugin,
serverAdapter: adapter,
},
}));
});
}
} else if (isClient) {
if (blockSuiteAdapter) {

View File

@@ -47,5 +47,5 @@
"@blocksuite/lit": "*",
"@blocksuite/store": "*"
},
"version": "0.6.1-beta.0"
"version": "0.7.0-canary.13"
}

View File

@@ -6,5 +6,5 @@
"./*.md": "./*.md",
"./preloading.json": "./preloading.json"
},
"version": "0.6.1-beta.0"
"version": "0.7.0-canary.13"
}

View File

@@ -3,15 +3,12 @@
"version": 1,
"data": {
"space:meta": {
"name": "Demo Workspace",
"pages": [
{
"id": "hello-world",
"id": "Qmo9-1SGTB",
"title": "AFFiNE - not just a note taking app",
"createDate": 1686627549555,
"subpageIds": [],
"jumpOnce": false,
"updatedDate": 1686627553606
"createDate": 1685676956753,
"subpageIds": []
}
],
"versions": {
@@ -27,15 +24,15 @@
"affine:database": 1
}
},
"space:hello-world": {
"space:Qmo9-1SGTB": {
"_9D75ibqvd": {
"sys:id": "_9D75ibqvd",
"sys:flavour": "affine:page",
"sys:children": [
"4-IQVC-U5A",
"Y4oz3g1LB6",
"VNbg-Wz6Vs",
"V7dUwRJxpY",
"Y4oz3g1LB6",
"1cFTd-rwDr",
"A2hTNhHJSo",
"JSoC9zIZDz",
@@ -60,15 +57,15 @@
],
"prop:background": "--affine-background-secondary-color",
"prop:index": "a2",
"prop:xywh": "[866.5055790704506,86.14140870095756,326.7016703680564,356]"
"prop:xywh": "[866.5055790704506,86.14140870095756,326.7016703680564,500]"
},
"VNbg-Wz6Vs": {
"sys:id": "VNbg-Wz6Vs",
"sys:flavour": "affine:frame",
"sys:children": ["hiVj6pUziI", "6rgGQmAmfb", "KRefAQRNnh"],
"sys:children": ["Prrnq7ruGC", "6rgGQmAmfb", "KRefAQRNnh"],
"prop:index": "a0",
"prop:background": "--affine-tag-green",
"prop:xywh": "[1211.9913594556406,86.0748937043449,552.5830233754074,796]"
"prop:xywh": "[1211.9913594556406,86.0748937043449,552.5830233754074,572]"
},
"V7dUwRJxpY": {
"sys:id": "V7dUwRJxpY",
@@ -5910,16 +5907,16 @@
"Y4oz3g1LB6": {
"sys:id": "Y4oz3g1LB6",
"sys:flavour": "affine:frame",
"sys:children": ["Prrnq7ruGC"],
"prop:xywh": "[855.7586305793726,-38.93174493636967,1488.043436415603,104]",
"sys:children": ["aPk03I3k9L"],
"prop:xywh": "[855.7586305793726,-38.93174493636967,1488.043436415603,112]",
"prop:index": "a0",
"prop:background": "--affine-tag-yellow"
},
"1cFTd-rwDr": {
"sys:id": "1cFTd-rwDr",
"sys:flavour": "affine:frame",
"sys:children": ["aPk03I3k9L", "4_plt-pF5i", "5O-z_KtfdV"],
"prop:xywh": "[1782.1527708473825,83.59728260421294,554.4267667459387,668]",
"sys:children": ["2NKIdhpZZy", "4_plt-pF5i", "5O-z_KtfdV"],
"prop:xywh": "[1782.1527708473825,83.59728260421294,554.4267667459387,573]",
"prop:index": "a0",
"prop:background": "--affine-tag-blue"
},
@@ -5927,7 +5924,7 @@
"sys:id": "A2hTNhHJSo",
"sys:flavour": "affine:frame",
"sys:children": ["1t5gAmmDk1", "Ru5RZxl2cw", "m09CQTVNta"],
"prop:xywh": "[1862.2162713385649,667.8687461185463,471.2475208977704,724]",
"prop:xywh": "[1862.2162713385649,667.8687461185463,471.2475208977704,569]",
"prop:index": "a0",
"prop:background": "--affine-tag-red"
},
@@ -5937,13 +5934,13 @@
"sys:children": ["RYwAAsT0jt", "yui0v4a-DG", "CuW0As_WD5"],
"prop:index": "a0",
"prop:background": "--affine-tag-purple",
"prop:xywh": "[1310.31891616522,676.1486476697154,537.1322406806248,724]"
"prop:xywh": "[1310.31891616522,676.1486476697154,537.1322406806248,561]"
},
"Vq_8QO3ruz": {
"sys:id": "Vq_8QO3ruz",
"sys:flavour": "affine:frame",
"sys:children": ["Z6tZpqYD1i", "cSq4fYa62E", "e-ekSJPKh0"],
"prop:xywh": "[824.3933427871591,677.7709857969486,475.6451530544002,724]",
"prop:xywh": "[824.3933427871591,677.7709857969486,475.6451530544002,542]",
"prop:index": "a0",
"prop:background": "--affine-tag-blue"
},
@@ -5954,16 +5951,17 @@
"YQPpZUitL9",
"jNb1ieggGw",
"yln9MU-iVm",
"z1fWcxw9qe",
"rY1fVETRzE"
],
"prop:index": "a0",
"prop:background": "--affine-tag-green",
"prop:xywh": "[817.0745095091336,1272.4084873924633,586.3018678030073,922]"
"prop:xywh": "[817.0745095091336,1272.4084873924633,586.3018678030073,672]"
},
"3An3wRFKN_": {
"sys:id": "3An3wRFKN_",
"sys:flavour": "affine:frame",
"sys:children": ["KZrhdN52ZD", "3MnKwqEw_Q"],
"sys:children": ["3MnKwqEw_Q"],
"prop:xywh": "[-264.94381566608683,389.00823320424837,494.2811077047478,314]",
"prop:index": "a2",
"prop:background": "--affine-background-secondary-color"
@@ -5972,7 +5970,7 @@
"sys:id": "U2hR9Lu1E7",
"sys:flavour": "affine:frame",
"sys:children": ["LYes52XNDN"],
"prop:xywh": "[2918.2644723261433,881.0630462339941,539.4086027654356,655]",
"prop:xywh": "[2918.2644723261433,881.0630462339941,539.4086027654356,439]",
"prop:index": "a2",
"prop:background": "--affine-background-secondary-color"
},
@@ -5980,7 +5978,7 @@
"sys:id": "nOERveFG0j",
"sys:flavour": "affine:frame",
"sys:children": ["SjyfxmcAjc"],
"prop:xywh": "[2919.8341116576826,1349.0080470072992,535.7138283708327,632]",
"prop:xywh": "[2919.8341116576826,1349.0080470072992,535.7138283708327,451]",
"prop:index": "a2",
"prop:background": "--affine-background-secondary-color"
},
@@ -6060,17 +6058,8 @@
"sys:id": "Prrnq7ruGC",
"sys:flavour": "affine:paragraph",
"sys:children": [],
"prop:type": "h1",
"prop:text": [
{ "insert": "Let's " },
{ "insert": "Write", "attributes": { "bold": true } },
{ "insert": ", " },
{ "insert": "Draw", "attributes": { "bold": true } },
{ "insert": " and " },
{ "insert": "Plan", "attributes": { "bold": true } },
{ "insert": " with " },
{ "insert": "AFFiNE", "attributes": { "bold": true } }
]
"prop:type": "h3",
"prop:text": [{ "insert": "Create Your Workspace" }]
},
"6rgGQmAmfb": {
"sys:id": "6rgGQmAmfb",
@@ -6087,6 +6076,22 @@
"sys:id": "aPk03I3k9L",
"sys:flavour": "affine:paragraph",
"sys:children": [],
"prop:type": "h2",
"prop:text": [
{ "insert": "Let's " },
{ "insert": "Write", "attributes": { "bold": true } },
{ "insert": ", " },
{ "insert": "Draw", "attributes": { "bold": true } },
{ "insert": " and " },
{ "insert": "Plan", "attributes": { "bold": true } },
{ "insert": " with " },
{ "insert": "AFFiNE", "attributes": { "bold": true } }
]
},
"2NKIdhpZZy": {
"sys:id": "2NKIdhpZZy",
"sys:flavour": "affine:paragraph",
"sys:children": [],
"prop:type": "h3",
"prop:text": [{ "insert": "Organise Your Pages" }]
},
@@ -6191,8 +6196,8 @@
}
]
},
"KZrhdN52ZD": {
"sys:id": "KZrhdN52ZD",
"z1fWcxw9qe": {
"sys:id": "z1fWcxw9qe",
"sys:flavour": "affine:divider",
"sys:children": []
},
@@ -6316,8 +6321,8 @@
"prop:width": 0,
"prop:height": 0
},
"5O-z_KtfdV": {
"sys:id": "5O-z_KtfdV",
"rY1fVETRzE": {
"sys:id": "rY1fVETRzE",
"sys:flavour": "affine:embed",
"sys:children": [],
"prop:type": "image",
@@ -6326,8 +6331,8 @@
"prop:width": 0,
"prop:height": 0
},
"m09CQTVNta": {
"sys:id": "m09CQTVNta",
"e-ekSJPKh0": {
"sys:id": "e-ekSJPKh0",
"sys:flavour": "affine:embed",
"sys:children": [],
"prop:type": "image",
@@ -6346,8 +6351,8 @@
"prop:width": 0,
"prop:height": 0
},
"e-ekSJPKh0": {
"sys:id": "e-ekSJPKh0",
"5O-z_KtfdV": {
"sys:id": "5O-z_KtfdV",
"sys:flavour": "affine:embed",
"sys:children": [],
"prop:type": "image",
@@ -6356,8 +6361,8 @@
"prop:width": 0,
"prop:height": 0
},
"rY1fVETRzE": {
"sys:id": "rY1fVETRzE",
"m09CQTVNta": {
"sys:id": "m09CQTVNta",
"sys:flavour": "affine:embed",
"sys:children": [],
"prop:type": "image",
@@ -6366,32 +6371,25 @@
"prop:width": 0,
"prop:height": 0
},
"LYes52XNDN": {
"sys:id": "LYes52XNDN",
"sys:flavour": "affine:embed",
"sys:children": [],
"prop:type": "image",
"prop:sourceId": "https://cdn.affine.pro/047ebf2c9a5c7c9d8521c2ea5e6140ff7732ef9e28a9f944e9bf3ca4.png",
"prop:caption": "",
"prop:width": 0,
"prop:height": 0
},
"SjyfxmcAjc": {
"sys:id": "SjyfxmcAjc",
"sys:flavour": "affine:embed",
"sys:children": [],
"prop:type": "image",
"prop:sourceId": "https://cdn.affine.pro/6aa785ee927547ce9dd9d7b43e01eac948337fe57571443e87bc3a60.png",
"prop:sourceId": "https://cdn.affine.pro/047ebf2c9a5c7c9d8521c2ea5e6140ff7732ef9e28a9f944e9bf3ca4.png",
"prop:caption": "",
"prop:width": 0,
"prop:height": 0
},
"hiVj6pUziI": {
"sys:id": "hiVj6pUziI",
"sys:flavour": "affine:paragraph",
"LYes52XNDN": {
"sys:id": "LYes52XNDN",
"sys:flavour": "affine:embed",
"sys:children": [],
"prop:text": [{ "insert": "Create Your Workspace" }],
"prop:type": "h3"
"prop:type": "image",
"prop:sourceId": "https://cdn.affine.pro/6aa785ee927547ce9dd9d7b43e01eac948337fe57571443e87bc3a60.png",
"prop:caption": "",
"prop:width": 0,
"prop:height": 0
}
}
}

View File

@@ -40,5 +40,5 @@
"next": "=13.4.2",
"ws": "^8.13.0"
},
"version": "0.6.1-beta.0"
"version": "0.7.0-canary.13"
}

View File

@@ -207,12 +207,10 @@ export function createAffineAuth(prefix = '/') {
}),
}).then(r => r.json()) as Promise<LoginResponse>;
} catch (error) {
if (
error instanceof Error &&
'code' in error &&
error.code === 'auth/popup-closed-by-user'
) {
return null;
if (error instanceof Error && 'code' in error) {
if (error.code === 'auth/popup-closed-by-user') {
return null;
}
}
logger.error('Failed to sign in', error);
}

View File

@@ -171,9 +171,7 @@ const createSQLiteProvider = (
if (origin === sqliteOrigin) {
return;
}
apis.db.applyDocUpdate(blockSuiteWorkspace.id, update).catch(err => {
console.error(err);
});
apis.db.applyDocUpdate(blockSuiteWorkspace.id, update);
}
let unsubscribe = () => {};
@@ -249,7 +247,7 @@ const createSQLiteDBDownloadProvider = (
const diff = Y.encodeStateAsUpdate(blockSuiteWorkspace.doc, updates);
// also apply updates to sqlite
await apis.db.applyDocUpdate(blockSuiteWorkspace.id, diff);
apis.db.applyDocUpdate(blockSuiteWorkspace.id, diff);
const bs = blockSuiteWorkspace.blobs;

View File

@@ -1,15 +1,7 @@
{
"name": "@toeverything/y-indexeddb",
"type": "module",
"version": "0.6.1-beta.0",
"description": "IndexedDB database adapter for Yjs",
"repository": "toeverything/AFFiNE",
"author": "toeverything",
"keywords": [
"indexeddb",
"yjs",
"yjs-adapter"
],
"version": "0.7.0-canary.13",
"scripts": {
"build": "vite build"
},
@@ -36,13 +28,14 @@
"idb": "^7.1.1"
},
"devDependencies": {
"@blocksuite/blocks": "0.0.0-20230613142146-d72d4600-nightly",
"@blocksuite/store": "0.0.0-20230613142146-d72d4600-nightly",
"@blocksuite/blocks": "0.0.0-20230607055421-9b20fcaf-nightly",
"@blocksuite/store": "0.0.0-20230607055421-9b20fcaf-nightly",
"vite": "^4.3.9",
"vite-plugin-dts": "^2.3.0",
"y-indexeddb": "^9.0.11"
},
"peerDependencies": {
"yjs": "^13.5.51"
}
},
"stableVersion": "0.5.2"
}

View File

@@ -3,8 +3,8 @@
*/
import 'fake-indexeddb/auto';
import { initEmptyPage } from '@affine/env/blocksuite';
import { __unstableSchemas, AffineSchemas } from '@blocksuite/blocks/models';
import type { Page } from '@blocksuite/store';
import { assertExists, uuidv4, Workspace } from '@blocksuite/store';
import { openDB } from 'idb';
import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest';
@@ -24,21 +24,6 @@ import {
setMergeCount,
} from '../index';
function initEmptyPage(page: Page) {
const pageBlockId = page.addBlock('affine:page', {
title: new page.Text(''),
});
const surfaceBlockId = page.addBlock('affine:surface', {}, pageBlockId);
const frameBLockId = page.addBlock('affine:frame', {}, pageBlockId);
const paragraphBlockId = page.addBlock('affine:paragraph', {}, frameBLockId);
return {
pageBlockId,
surfaceBlockId,
frameBLockId,
paragraphBlockId,
};
}
async function getUpdates(id: string): Promise<Uint8Array[]> {
const db = await openDB(rootDBName, dbVersion);
const store = await db
@@ -88,8 +73,7 @@ describe('indexeddb provider', () => {
},
],
});
const page = workspace.createPage({ id: 'page0' });
await page.waitForLoaded();
const page = workspace.createPage('page0');
const pageBlockId = page.addBlock('affine:page', { title: '' });
const frameId = page.addBlock('affine:frame', {}, pageBlockId);
page.addBlock('affine:paragraph', {}, frameId);
@@ -159,8 +143,7 @@ describe('indexeddb provider', () => {
provider.disconnect();
expect(provider.connected).toBe(false);
{
const page = workspace.createPage({ id: 'page0' });
await page.waitForLoaded();
const page = workspace.createPage('page0');
const pageBlockId = page.addBlock('affine:page', { title: '' });
const frameId = page.addBlock('affine:frame', {}, pageBlockId);
page.addBlock('affine:paragraph', {}, frameId);
@@ -231,11 +214,10 @@ describe('indexeddb provider', () => {
);
provider.connect();
{
const page = workspace.createPage({ id: 'page0' });
await page.waitForLoaded();
const page = workspace.createPage('page0');
const pageBlockId = page.addBlock('affine:page', { title: '' });
const frameId = page.addBlock('affine:frame', {}, pageBlockId);
for (let i = 0; i < 99; i++) {
for (let i = 0; i < 100; i++) {
page.addBlock('affine:paragraph', {}, frameId);
}
}
@@ -390,89 +372,9 @@ describe('milestone', () => {
});
});
describe('subDoc', () => {
test('basic', async () => {
let json1: any, json2: any;
{
const doc = new Doc();
const map = doc.getMap();
const subDoc = new Doc();
subDoc.load();
map.set('1', subDoc);
map.set('2', 'test');
const provider = createIndexedDBProvider('test', doc);
provider.connect();
await provider.whenSynced;
provider.disconnect();
json1 = doc.toJSON();
}
{
const doc = new Doc();
const provider = createIndexedDBProvider('test', doc);
provider.connect();
await provider.whenSynced;
const map = doc.getMap();
const subDoc = map.get('1') as Doc;
subDoc.load();
provider.disconnect();
json2 = doc.toJSON();
}
expect(json1['']['1'].toJSON()).toEqual(json2['']['1'].toJSON());
expect(json1['']['2']).toEqual(json2['']['2']);
});
test('blocksuite', async () => {
const page0 = workspace.createPage({
id: 'page0',
});
await page0.waitForLoaded();
const { paragraphBlockId: paragraphBlockIdPage1 } = initEmptyPage(page0);
const provider = createIndexedDBProvider(
workspace.id,
workspace.doc,
rootDBName
);
provider.connect();
const page1 = workspace.createPage({
id: 'page1',
});
await page1.waitForLoaded();
const { paragraphBlockId: paragraphBlockIdPage2 } = initEmptyPage(page1);
await new Promise(resolve => setTimeout(resolve, 1000));
provider.disconnect();
{
const newWorkspace = new Workspace({
id,
isSSR: true,
});
newWorkspace.register(AffineSchemas).register(__unstableSchemas);
const provider = createIndexedDBProvider(
newWorkspace.id,
newWorkspace.doc,
rootDBName
);
provider.connect();
await provider.whenSynced;
const page0 = newWorkspace.getPage('page0') as Page;
await page0.waitForLoaded();
{
const block = page0.getBlockById(paragraphBlockIdPage1);
assertExists(block);
}
const page1 = newWorkspace.getPage('page1') as Page;
await page1.waitForLoaded();
{
const block = page1.getBlockById(paragraphBlockIdPage2);
assertExists(block);
}
}
});
});
describe('utils', () => {
test('download binary', async () => {
const page = workspace.createPage({ id: 'page0' });
await page.waitForLoaded();
const page = workspace.createPage('page0');
initEmptyPage(page);
const provider = createIndexedDBProvider(
workspace.id,
@@ -495,12 +397,7 @@ describe('utils', () => {
applyUpdate(newWorkspace.doc, update);
await new Promise<void>(resolve =>
setTimeout(() => {
expect(workspace.doc.toJSON()['meta']).toEqual(
newWorkspace.doc.toJSON()['meta']
);
expect(Object.keys(workspace.doc.toJSON()['spaces'])).toEqual(
Object.keys(newWorkspace.doc.toJSON()['spaces'])
);
expect(workspace.doc.toJSON()).toEqual(newWorkspace.doc.toJSON());
resolve();
}, 0)
);

View File

@@ -142,12 +142,6 @@ export const getMilestones = async (
return milestone.milestone;
};
type SubDocsEvent = {
added: Set<Doc>;
removed: Set<Doc>;
loaded: Set<Doc>;
};
export const createIndexedDBProvider = (
id: string,
doc: Doc,
@@ -157,175 +151,62 @@ export const createIndexedDBProvider = (
let reject: (reason?: unknown) => void;
let early = true;
let connected = false;
const dbPromise = openDB<BlockSuiteBinaryDB>(dbName, dbVersion, {
upgrade: upgradeDB,
});
const updateHandlerMap = new WeakMap<
Doc,
(update: Uint8Array, origin: unknown) => void
>();
const destroyHandlerMap = new WeakMap<Doc, () => void>();
const subDocsHandlerMap = new WeakMap<Doc, (event: SubDocsEvent) => void>();
const createOrGetHandleUpdate = (id: string, doc: Doc) => {
if (updateHandlerMap.has(doc)) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
return updateHandlerMap.get(doc)!;
}
const fn = async function handleUpdate(
update: Uint8Array,
origin: unknown
) {
const db = await dbPromise;
if (!connected) {
return;
}
if (origin === indexeddbOrigin) {
return;
}
const store = db
.transaction('workspace', 'readwrite')
.objectStore('workspace');
let data = await store.get(id);
if (!data) {
data = {
id,
updates: [],
};
}
data.updates.push({
timestamp: Date.now(),
update,
});
if (data.updates.length > mergeCount) {
const updates = data.updates.map(({ update }) => update);
const doc = new Doc();
doc.transact(() => {
updates.forEach(update => {
applyUpdate(doc, update, indexeddbOrigin);
});
}, indexeddbOrigin);
const update = encodeStateAsUpdate(doc);
data = {
id,
updates: [
{
timestamp: Date.now(),
update,
},
],
};
await writeOperation(store.put(data));
} else {
await writeOperation(store.put(data));
}
};
updateHandlerMap.set(doc, fn);
return fn;
};
/* deepscan-disable UNUSED_PARAM */
const createOrGetHandleDestroy = (_: string, doc: Doc) => {
if (destroyHandlerMap.has(doc)) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
return destroyHandlerMap.get(doc)!;
}
const fn = async function handleDestroy() {
const db = await dbPromise;
db.close();
};
destroyHandlerMap.set(doc, fn);
return fn;
};
/* deepscan-disable UNUSED_PARAM */
const createOrGetHandleSubDocs = (_: string, doc: Doc) => {
if (subDocsHandlerMap.has(doc)) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
return subDocsHandlerMap.get(doc)!;
}
const fn = async function handleSubDocs(event: SubDocsEvent) {
event.removed.forEach(doc => {
unTrackDoc(doc.guid, doc);
});
event.loaded.forEach(doc => {
trackDoc(doc.guid, doc);
});
};
subDocsHandlerMap.set(doc, fn);
return fn;
};
function trackDoc(id: string, doc: Doc) {
doc.on('update', createOrGetHandleUpdate(id, doc));
doc.on('destroy', createOrGetHandleDestroy(id, doc));
doc.on('subdocs', createOrGetHandleSubDocs(id, doc));
}
function unTrackDoc(id: string, doc: Doc) {
doc.subdocs.forEach(doc => {
unTrackDoc(doc.guid, doc);
});
doc.off('update', createOrGetHandleUpdate(id, doc));
doc.off('destroy', createOrGetHandleDestroy(id, doc));
doc.off('subdocs', createOrGetHandleSubDocs(id, doc));
}
async function saveDocOperation(id: string, doc: Doc) {
async function handleUpdate(update: Uint8Array, origin: unknown) {
const db = await dbPromise;
const store = db
.transaction('workspace', 'readwrite')
.objectStore('workspace');
const data = await store.get(id);
if (!connected) {
return;
}
if (origin === indexeddbOrigin) {
return;
}
const store = db
.transaction('workspace', 'readwrite')
.objectStore('workspace');
let data = await store.get(id);
if (!data) {
await writeOperation(
db.put('workspace', {
id,
updates: [
{
timestamp: Date.now(),
update: encodeStateAsUpdate(doc),
},
],
})
);
} else {
data = {
id,
updates: [],
};
}
data.updates.push({
timestamp: Date.now(),
update,
});
if (data.updates.length > mergeCount) {
const updates = data.updates.map(({ update }) => update);
const fakeDoc = new Doc();
fakeDoc.transact(() => {
updates.forEach(update => {
applyUpdate(fakeDoc, update);
});
}, indexeddbOrigin);
const newUpdate = diffUpdate(
encodeStateAsUpdate(doc),
encodeStateAsUpdate(fakeDoc)
);
await writeOperation(
store.put({
...data,
updates: [
...data.updates,
{
timestamp: Date.now(),
update: newUpdate,
},
],
})
);
const doc = new Doc();
doc.transact(() => {
updates.forEach(update => {
applyUpdate(doc, update);
applyUpdate(doc, update, indexeddbOrigin);
});
}, indexeddbOrigin);
const update = encodeStateAsUpdate(doc);
data = {
id,
updates: [
{
timestamp: Date.now(),
update,
},
],
};
await writeOperation(store.put(data));
} else {
await writeOperation(store.put(data));
}
}
const dbPromise = openDB<BlockSuiteBinaryDB>(dbName, dbVersion, {
upgrade: upgradeDB,
});
const handleDestroy = async () => {
connected = true;
const db = await dbPromise;
db.close();
};
const apis = {
connect: async () => {
if (connected) return;
@@ -336,23 +217,60 @@ export const createIndexedDBProvider = (
reject = _reject;
});
connected = true;
trackDoc(id, doc);
// only the runs `await` below, otherwise the logic is incorrect
doc.on('update', handleUpdate);
doc.on('destroy', handleDestroy);
// only run promise below, otherwise the logic is incorrect
const db = await dbPromise;
await tryMigrate(db, id, dbName);
const store = db
.transaction('workspace', 'readwrite')
.objectStore('workspace');
const data = await store.get(id);
if (!connected) {
return;
}
const docs: [string, Doc][] = [];
docs.push([id, doc]);
while (docs.length > 0) {
const [id, doc] = docs.pop() as [string, Doc];
await saveDocOperation(id, doc);
doc.subdocs.forEach(doc => {
docs.push([doc.guid, doc]);
});
if (!data) {
await writeOperation(
db.put('workspace', {
id,
updates: [
{
timestamp: Date.now(),
update: encodeStateAsUpdate(doc),
},
],
})
);
} else {
const updates = data.updates.map(({ update }) => update);
const fakeDoc = new Doc();
fakeDoc.transact(() => {
updates.forEach(update => {
applyUpdate(fakeDoc, update);
});
}, indexeddbOrigin);
const newUpdate = diffUpdate(
encodeStateAsUpdate(doc),
encodeStateAsUpdate(fakeDoc)
);
await writeOperation(
store.put({
...data,
updates: [
...data.updates,
{
timestamp: Date.now(),
update: newUpdate,
},
],
})
);
doc.transact(() => {
updates.forEach(update => {
applyUpdate(doc, update);
});
}, indexeddbOrigin);
}
early = false;
resolve();
},
@@ -361,7 +279,8 @@ export const createIndexedDBProvider = (
if (early) {
reject(new EarlyDisconnectError());
}
unTrackDoc(id, doc);
doc.off('update', handleUpdate);
doc.off('destroy', handleDestroy);
},
async cleanup() {
if (connected) {

View File

@@ -9,6 +9,9 @@
"references": [
{
"path": "./tsconfig.node.json"
},
{
"path": "../env"
}
]
}

View File

@@ -21,5 +21,5 @@
"react": "*",
"react-dom": "*"
},
"version": "0.6.1-beta.0"
"version": "0.7.0-canary.13"
}

View File

@@ -28,5 +28,5 @@
"react": "*",
"react-dom": "*"
},
"version": "0.6.1-beta.0"
"version": "0.7.0-canary.13"
}

View File

@@ -12,48 +12,47 @@ import { openAIApiKeyAtom, useChatAtoms } from '../core/hooks';
import { detailContentActionsStyle, detailContentStyle } from './index.css';
if (typeof window === 'undefined') {
import('@blocksuite/blocks')
.then(({ FormatQuickBar }) => {
FormatQuickBar.customElements.push((_page, getSelection) => {
const div = document.createElement('div');
const root = createRoot(div);
import('@blocksuite/blocks').then(({ FormatQuickBar }) => {
FormatQuickBar.customElements.push((_page, getSelection) => {
const div = document.createElement('div');
const root = createRoot(div);
const AskAI = (): ReactElement => {
const { conversationAtom } = useChatAtoms();
const call = useSetAtom(conversationAtom);
const onClickAskAI = useCallback(() => {
const selection = getSelection();
if (selection != null) {
const text = selection.models
.map(model => {
return model.text?.toString();
})
.filter((v): v is string => Boolean(v))
.join('\n');
console.log('selected text:', text);
call(
`I selected some text from the document: \n"${text}."`
).catch(err => {
console.error(err);
});
}
}, [call]);
const AskAI = (): ReactElement => {
const { conversationAtom } = useChatAtoms();
const call = useSetAtom(conversationAtom);
return <div onClick={onClickAskAI}>Ask AI</div>;
};
root.render(
<StrictMode>
<Provider store={rootStore}>
<AskAI />
</Provider>
</StrictMode>
return (
<div
onClick={() => {
const selection = getSelection();
if (selection != null) {
const text = selection.models
.map(model => {
return model.text?.toString();
})
.filter((v): v is string => Boolean(v))
.join('\n');
console.log('selected text:', text);
void call(
`I selected some text from the document: \n"${text}."`
);
}
}}
>
Ask AI
</div>
);
return div;
});
})
.catch(error => {
console.error(error);
};
root.render(
<StrictMode>
<Provider store={rootStore}>
<AskAI />
</Provider>
</StrictMode>
);
return div;
});
});
}
const Actions = () => {

View File

@@ -49,14 +49,9 @@ const getConversationAtom = (chat: ConversationChain) => {
throw new Error();
}
const memory = chat.memory as BufferMemory;
memory.chatHistory
.getMessages()
.then(messages => {
setAtom(messages);
})
.catch(err => {
console.error(err);
});
void memory.chatHistory.getMessages().then(messages => {
setAtom(messages);
});
const llmStart = (): void => {
setAtom(conversations => [...conversations, new AIChatMessage('')]);
};
@@ -91,14 +86,9 @@ const getConversationAtom = (chat: ConversationChain) => {
});
// refresh messages
const memory = chat.memory as BufferMemory;
memory.chatHistory
.getMessages()
.then(messages => {
set(conversationBaseAtom, messages);
})
.catch(err => {
console.error(err);
});
void memory.chatHistory.getMessages().then(messages => {
set(conversationBaseAtom, messages);
});
}
);
conversationWeakMap.set(chat, conversationAtom);

View File

@@ -3,5 +3,5 @@
"exports": {
"./*": "./*"
},
"version": "0.6.1-beta.0"
"version": "0.7.0-canary.13"
}

View File

@@ -1,7 +1,7 @@
{
"name": "@affine-test/kit",
"private": true,
"version": "0.6.1-beta.0",
"version": "0.7.0-canary.13",
"exports": {
"./playwright": "./playwright.ts"
},

View File

@@ -1,64 +0,0 @@
import { test } from '@affine-test/kit/playwright';
import type { Page } from '@playwright/test';
import { expect } from '@playwright/test';
import { openHomePage } from '../../libs/load-page';
import { newPage, waitEditorLoad } from '../../libs/page-logic';
const addDatabase = async (page: Page) => {
await page.keyboard.press('/', { delay: 50 });
await page.keyboard.press('d');
await page.keyboard.press('a');
await page.keyboard.press('t');
await page.keyboard.press('a');
await page.keyboard.press('b');
await page.keyboard.press('a', { delay: 50 });
await page.keyboard.press('Enter', { delay: 50 });
};
test('database is useable', async ({ page }) => {
await openHomePage(page);
await waitEditorLoad(page);
await newPage(page);
await page.keyboard.insertText('test title');
await page.keyboard.press('Enter');
const title = page.locator('.affine-default-page-block-title');
expect(await title.innerText()).toBe('test title');
await addDatabase(page);
const database = page.locator('.affine-database-table');
expect(database).toBeVisible();
await page.reload();
await waitEditorLoad(page);
await newPage(page);
await page.keyboard.insertText('test title2');
await page.keyboard.press('Enter');
const title2 = page.locator('.affine-default-page-block-title');
expect(await title2.innerText()).toBe('test title2');
await addDatabase(page);
const database2 = page.locator('.affine-database-table');
expect(database2).toBeVisible();
});
test('link page is useable', async ({ page }) => {
await openHomePage(page);
await waitEditorLoad(page);
await newPage(page);
await page.keyboard.insertText('page1');
await page.keyboard.press('Enter');
const title = page.locator('.affine-default-page-block-title');
expect(await title.innerText()).toBe('page1');
await newPage(page);
await page.keyboard.insertText('page2');
await page.keyboard.press('Enter');
const title2 = page.locator('.affine-default-page-block-title');
expect(await title2.innerText()).toBe('page2');
await page.keyboard.press('@', { delay: 50 });
await page.keyboard.press('p');
await page.keyboard.press('a');
await page.keyboard.press('g');
await page.keyboard.press('e');
await page.keyboard.press('1');
await page.keyboard.press('Enter');
const link = page.locator('.affine-reference');
expect(link).toBeVisible();
await page.click('.affine-reference');
expect(await title.innerText()).toBe('page1');
});

333
yarn.lock
View File

@@ -158,10 +158,6 @@ __metadata:
dependencies:
"@affine-test/kit": "workspace:*"
"@affine/native": "workspace:*"
"@blocksuite/blocks": 0.0.0-20230607055421-9b20fcaf-nightly
"@blocksuite/editor": 0.0.0-20230607055421-9b20fcaf-nightly
"@blocksuite/lit": 0.0.0-20230607055421-9b20fcaf-nightly
"@blocksuite/store": 0.0.0-20230607055421-9b20fcaf-nightly
"@electron-forge/cli": ^6.1.1
"@electron-forge/core": ^6.1.1
"@electron-forge/core-utils": ^6.1.1
@@ -176,6 +172,7 @@ __metadata:
"@types/fs-extra": ^11.0.1
"@types/uuid": ^9.0.1
async-call-rpc: ^6.3.1
cheerio: ^1.0.0-rc.12
cross-env: 7.0.3
electron: =25.0.1
electron-log: ^5.0.0-beta.24
@@ -184,8 +181,6 @@ __metadata:
electron-window-state: ^5.0.3
esbuild: ^0.17.19
fs-extra: ^11.1.1
jotai: ^2.1.1
link-preview-js: ^3.0.4
lodash-es: ^4.17.21
nanoid: ^4.0.2
playwright: =1.33.0
@@ -193,7 +188,6 @@ __metadata:
ts-node: ^10.9.1
undici: ^5.22.1
uuid: ^9.0.0
which: ^3.0.1
yjs: ^13.6.1
zx: ^7.2.2
peerDependencies:
@@ -302,7 +296,6 @@ __metadata:
eslint-plugin-react: ^7.32.2
eslint-plugin-react-hooks: ^4.6.0
eslint-plugin-simple-import-sort: ^10.0.0
eslint-plugin-sonarjs: ^0.19.0
eslint-plugin-unicorn: ^47.0.0
eslint-plugin-unused-imports: ^2.0.0
fake-indexeddb: 4.0.1
@@ -2612,15 +2605,6 @@ __metadata:
languageName: node
linkType: hard
"@babel/runtime@npm:^7.14.0":
version: 7.22.5
resolution: "@babel/runtime@npm:7.22.5"
dependencies:
regenerator-runtime: ^0.13.11
checksum: 12a50b7de2531beef38840d17af50c55a094253697600cee255311222390c68eed704829308d4fd305e1b3dfbce113272e428e9d9d45b1730e0fede997eaceb1
languageName: node
linkType: hard
"@babel/template@npm:^7.18.10, @babel/template@npm:^7.20.7, @babel/template@npm:^7.21.9, @babel/template@npm:^7.3.3":
version: 7.21.9
resolution: "@babel/template@npm:7.21.9"
@@ -2729,32 +2713,6 @@ __metadata:
languageName: node
linkType: hard
"@blocksuite/blocks@npm:0.0.0-20230613142146-d72d4600-nightly":
version: 0.0.0-20230613142146-d72d4600-nightly
resolution: "@blocksuite/blocks@npm:0.0.0-20230613142146-d72d4600-nightly"
dependencies:
"@blocksuite/connector": 0.0.0-20230613142146-d72d4600-nightly
"@blocksuite/global": 0.0.0-20230613142146-d72d4600-nightly
"@blocksuite/phasor": 0.0.0-20230613142146-d72d4600-nightly
"@blocksuite/virgo": 0.0.0-20230613142146-d72d4600-nightly
"@floating-ui/dom": ^1.2.9
hotkeys-js: ^3.10.1
html-to-image: ^1.11.11
jspdf: ^2.5.1
jszip: ^3.10.1
lit: ^2.7.3
marked: ^4.2.12
shiki: ^0.14.1
turndown: ^7.1.1
zod: ^3.21.4
peerDependencies:
"@blocksuite/lit": 0.0.0-20230613142146-d72d4600-nightly
"@blocksuite/store": 0.0.0-20230613142146-d72d4600-nightly
yjs: ^13
checksum: 949d37335c16b6c6fd224a9ce6f0e356d500e139010706351a277f5ec69ebab309016267d8ecbb8d95adcae8d0edad2c99fb763f3caf158cf28d6bb12b8613d3
languageName: node
linkType: hard
"@blocksuite/connector@npm:0.0.0-20230607055421-9b20fcaf-nightly":
version: 0.0.0-20230607055421-9b20fcaf-nightly
resolution: "@blocksuite/connector@npm:0.0.0-20230607055421-9b20fcaf-nightly"
@@ -2762,13 +2720,6 @@ __metadata:
languageName: node
linkType: hard
"@blocksuite/connector@npm:0.0.0-20230613142146-d72d4600-nightly":
version: 0.0.0-20230613142146-d72d4600-nightly
resolution: "@blocksuite/connector@npm:0.0.0-20230613142146-d72d4600-nightly"
checksum: c5fcbae09c72cd61ecf8d4366c720edad7704f7737d0635e420fc0359ab9f4fe5a964581eee8e908ac1cab23abfba8bd770490bf674a594dc53624d6da775d5d
languageName: node
linkType: hard
"@blocksuite/editor@npm:0.0.0-20230607055421-9b20fcaf-nightly":
version: 0.0.0-20230607055421-9b20fcaf-nightly
resolution: "@blocksuite/editor@npm:0.0.0-20230607055421-9b20fcaf-nightly"
@@ -2801,21 +2752,6 @@ __metadata:
languageName: node
linkType: hard
"@blocksuite/global@npm:0.0.0-20230613142146-d72d4600-nightly":
version: 0.0.0-20230613142146-d72d4600-nightly
resolution: "@blocksuite/global@npm:0.0.0-20230613142146-d72d4600-nightly"
dependencies:
ansi-colors: ^4.1.3
zod: ^3.21.4
peerDependencies:
lit: ^2.7
peerDependenciesMeta:
lit:
optional: true
checksum: 45ccaa08c14787da8e3be8cbde9f01a34afea8874da6eaf7900961f953bbc0e7bab13866037d1504a1e983a8cc9e0735f5d9b1e074f6e400b27f7efae00292dd
languageName: node
linkType: hard
"@blocksuite/icons@npm:^2.1.19":
version: 2.1.19
resolution: "@blocksuite/icons@npm:2.1.19"
@@ -2852,20 +2788,6 @@ __metadata:
languageName: node
linkType: hard
"@blocksuite/phasor@npm:0.0.0-20230613142146-d72d4600-nightly":
version: 0.0.0-20230613142146-d72d4600-nightly
resolution: "@blocksuite/phasor@npm:0.0.0-20230613142146-d72d4600-nightly"
dependencies:
"@blocksuite/global": 0.0.0-20230613142146-d72d4600-nightly
fractional-indexing: ^3.2.0
roughjs: ^4.5.2
peerDependencies:
nanoid: ^4
yjs: ^13
checksum: 24dbb806ab928c4b37dcf94ea14fbd1f23dfcf63c42e42b378ca78baa51ec713556fc4a6553c5bf505d59309cd29079ffa8abb575a7c4f04cbef2202714f07c9
languageName: node
linkType: hard
"@blocksuite/store@npm:0.0.0-20230607055421-9b20fcaf-nightly":
version: 0.0.0-20230607055421-9b20fcaf-nightly
resolution: "@blocksuite/store@npm:0.0.0-20230607055421-9b20fcaf-nightly"
@@ -2890,30 +2812,6 @@ __metadata:
languageName: node
linkType: hard
"@blocksuite/store@npm:0.0.0-20230613142146-d72d4600-nightly":
version: 0.0.0-20230613142146-d72d4600-nightly
resolution: "@blocksuite/store@npm:0.0.0-20230613142146-d72d4600-nightly"
dependencies:
"@blocksuite/global": 0.0.0-20230613142146-d72d4600-nightly
"@blocksuite/virgo": 0.0.0-20230613142146-d72d4600-nightly
"@types/flexsearch": ^0.7.3
buffer: ^6.0.3
flexsearch: 0.7.21
idb-keyval: ^6.2.0
ky: ^0.33.3
lib0: ^0.2.74
merge: ^2.1.1
minimatch: ^9.0.0
nanoid: ^4.0.1
y-protocols: ^1.0.5
y-webrtc: ^10.2.5
zod: ^3.21.4
peerDependencies:
yjs: ^13
checksum: 1e6673b4c90ceb73176c552528d174126c036b445cc81c649e4e2fb694b87adbe12dcc3675117a088f5aadbe0410e380601914d05e26334879e12135c0843b17
languageName: node
linkType: hard
"@blocksuite/virgo@npm:0.0.0-20230607055421-9b20fcaf-nightly":
version: 0.0.0-20230607055421-9b20fcaf-nightly
resolution: "@blocksuite/virgo@npm:0.0.0-20230607055421-9b20fcaf-nightly"
@@ -2927,19 +2825,6 @@ __metadata:
languageName: node
linkType: hard
"@blocksuite/virgo@npm:0.0.0-20230613142146-d72d4600-nightly":
version: 0.0.0-20230613142146-d72d4600-nightly
resolution: "@blocksuite/virgo@npm:0.0.0-20230613142146-d72d4600-nightly"
dependencies:
"@blocksuite/global": 0.0.0-20230613142146-d72d4600-nightly
zod: ^3.21.4
peerDependencies:
lit: ^2.7
yjs: ^13
checksum: f3b5ee207b90d7f960eb10c37eb6866f06c0a2ad1e8e8bc46cc131ef2958f70a5b78d3dbafb7b19063b624acb898486a9b1f7fd7f83aa3f6253904b23f3eab47
languageName: node
linkType: hard
"@clack/core@npm:^0.3.2":
version: 0.3.2
resolution: "@clack/core@npm:0.3.2"
@@ -4619,13 +4504,6 @@ __metadata:
languageName: node
linkType: hard
"@floating-ui/core@npm:^1.3.0":
version: 1.3.0
resolution: "@floating-ui/core@npm:1.3.0"
checksum: 51d8acc9fd720cb217cae7074f5f923bf2b6e0bb4f228e03077254d0f6e49f9753b34a14b9abb1f11671c3b61284c487ab27c4ba1843bcd4397e7d72dc7d4a59
languageName: node
linkType: hard
"@floating-ui/dom@npm:^1.2.1":
version: 1.2.9
resolution: "@floating-ui/dom@npm:1.2.9"
@@ -4635,15 +4513,6 @@ __metadata:
languageName: node
linkType: hard
"@floating-ui/dom@npm:^1.2.9":
version: 1.3.0
resolution: "@floating-ui/dom@npm:1.3.0"
dependencies:
"@floating-ui/core": ^1.3.0
checksum: 39f92b3ce6de5d60a1cea951cbee22d0a9670fe4499b0128f0868a697d9288989994394d90cb99c3d1485aa432621e064d6b3c52914042a7d8d3c05897fb185d
languageName: node
linkType: hard
"@floating-ui/react-dom@npm:^1.3.0":
version: 1.3.0
resolution: "@floating-ui/react-dom@npm:1.3.0"
@@ -9408,8 +9277,8 @@ __metadata:
version: 0.0.0-use.local
resolution: "@toeverything/y-indexeddb@workspace:packages/y-indexeddb"
dependencies:
"@blocksuite/blocks": 0.0.0-20230613142146-d72d4600-nightly
"@blocksuite/store": 0.0.0-20230613142146-d72d4600-nightly
"@blocksuite/blocks": 0.0.0-20230607055421-9b20fcaf-nightly
"@blocksuite/store": 0.0.0-20230607055421-9b20fcaf-nightly
idb: ^7.1.1
vite: ^4.3.9
vite-plugin-dts: ^2.3.0
@@ -10032,13 +9901,6 @@ __metadata:
languageName: node
linkType: hard
"@types/raf@npm:^3.4.0":
version: 3.4.0
resolution: "@types/raf@npm:3.4.0"
checksum: d93e9b5244a081c64708b8918ef7e56936d6ef0144925b189e67d34127c0cb3a73fcf6866ab312db156554a66c26609dd056da5f7302f6658c049d6a37ed5f56
languageName: node
linkType: hard
"@types/range-parser@npm:*":
version: 1.2.4
resolution: "@types/range-parser@npm:1.2.4"
@@ -11653,15 +11515,6 @@ __metadata:
languageName: node
linkType: hard
"atob@npm:^2.1.2":
version: 2.1.2
resolution: "atob@npm:2.1.2"
bin:
atob: bin/atob.js
checksum: dfeeeb70090c5ebea7be4b9f787f866686c645d9f39a0d184c817252d0cf08455ed25267d79c03254d3be1f03ac399992a792edcd5ffb9c91e097ab5ef42833a
languageName: node
linkType: hard
"author-regex@npm:^1.0.0":
version: 1.0.0
resolution: "author-regex@npm:1.0.0"
@@ -11987,13 +11840,6 @@ __metadata:
languageName: node
linkType: hard
"base64-arraybuffer@npm:^1.0.2":
version: 1.0.2
resolution: "base64-arraybuffer@npm:1.0.2"
checksum: 15e6400d2d028bf18be4ed97702b11418f8f8779fb8c743251c863b726638d52f69571d4cc1843224da7838abef0949c670bde46936663c45ad078e89fee5c62
languageName: node
linkType: hard
"base64-js@npm:^1.3.1, base64-js@npm:^1.5.1":
version: 1.5.1
resolution: "base64-js@npm:1.5.1"
@@ -12234,15 +12080,6 @@ __metadata:
languageName: node
linkType: hard
"btoa@npm:^1.2.1":
version: 1.2.1
resolution: "btoa@npm:1.2.1"
bin:
btoa: bin/btoa.js
checksum: afbf004fb1b1d530e053ffa66ef5bd3878b101c59d808ac947fcff96810b4452abba2b54be687adadea2ba9efc7af48b04228742789bf824ef93f103767e690c
languageName: node
linkType: hard
"buffer-crc32@npm:~0.2.3":
version: 0.2.13
resolution: "buffer-crc32@npm:0.2.13"
@@ -12511,22 +12348,6 @@ __metadata:
languageName: node
linkType: hard
"canvg@npm:^3.0.6":
version: 3.0.10
resolution: "canvg@npm:3.0.10"
dependencies:
"@babel/runtime": ^7.12.5
"@types/raf": ^3.4.0
core-js: ^3.8.3
raf: ^3.4.1
regenerator-runtime: ^0.13.7
rgbcolor: ^1.0.1
stackblur-canvas: ^2.0.0
svg-pathdata: ^6.0.3
checksum: 2cfd86bcb9b56b43a97745cc672e696169b4c09e8850fb4f27bec5ebf173179d16feb594224d643a32f1ce01e47b55d44e0058419114d48d34f12c2452c65927
languageName: node
linkType: hard
"capital-case@npm:^1.0.4":
version: 1.0.4
resolution: "capital-case@npm:1.0.4"
@@ -12734,6 +12555,21 @@ __metadata:
languageName: node
linkType: hard
"cheerio@npm:^1.0.0-rc.12":
version: 1.0.0-rc.12
resolution: "cheerio@npm:1.0.0-rc.12"
dependencies:
cheerio-select: ^2.1.0
dom-serializer: ^2.0.0
domhandler: ^5.0.3
domutils: ^3.0.1
htmlparser2: ^8.0.1
parse5: ^7.0.0
parse5-htmlparser2-tree-adapter: ^7.0.0
checksum: 5d4c1b7a53cf22d3a2eddc0aff70cf23cbb30d01a4c79013e703a012475c02461aa1fcd99127e8d83a02216386ed6942b2c8103845fd0812300dd199e6e7e054
languageName: node
linkType: hard
"chokidar@npm:3.5.3, chokidar@npm:^3.4.2, chokidar@npm:^3.5.2, chokidar@npm:^3.5.3":
version: 3.5.3
resolution: "chokidar@npm:3.5.3"
@@ -13455,13 +13291,6 @@ __metadata:
languageName: node
linkType: hard
"core-js@npm:^3.6.0, core-js@npm:^3.8.3":
version: 3.31.0
resolution: "core-js@npm:3.31.0"
checksum: f7cf9b3010f7ca99c026d95b61743baca1a85512742ed2b67e8f65a72ac4f4fe0b90b00057783e886bdd39d3a295f42f845d33e7cba3973ed263df978343ab79
languageName: node
linkType: hard
"core-util-is@npm:~1.0.0":
version: 1.0.3
resolution: "core-util-is@npm:1.0.3"
@@ -13602,15 +13431,6 @@ __metadata:
languageName: node
linkType: hard
"css-line-break@npm:^2.1.0":
version: 2.1.0
resolution: "css-line-break@npm:2.1.0"
dependencies:
utrie: ^1.0.2
checksum: 37b1fe632b03be7a287cd394cef8b5285666343443125c510df9cfb6a4734a2c71e154ec8f7bbff72d7c339e1e5872989b1c52d86162aed27d6cc114725bb4d0
languageName: node
linkType: hard
"css-select@npm:^5.1.0":
version: 5.1.0
resolution: "css-select@npm:5.1.0"
@@ -14461,13 +14281,6 @@ __metadata:
languageName: node
linkType: hard
"dompurify@npm:^2.2.0":
version: 2.4.5
resolution: "dompurify@npm:2.4.5"
checksum: d6d3c3b320f15cdb5b26aa1902c3275a3ab2c3705a9df4420bb94691d7c4df67959ec7b91e486c308320791b0ee000456f042734c45d76721e61c2768eac706e
languageName: node
linkType: hard
"domutils@npm:^1.5.1":
version: 1.7.0
resolution: "domutils@npm:1.7.0"
@@ -15462,15 +15275,6 @@ __metadata:
languageName: node
linkType: hard
"eslint-plugin-sonarjs@npm:^0.19.0":
version: 0.19.0
resolution: "eslint-plugin-sonarjs@npm:0.19.0"
peerDependencies:
eslint: ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0
checksum: 893640583f62ce55584c6ddd481aa0fd6fa15fe0fffc32ac92b17f3fadde8eaf32414183bb80b612455212e9bb14400236398af6279ca04e8992f008e011926c
languageName: node
linkType: hard
"eslint-plugin-unicorn@npm:^47.0.0":
version: 47.0.0
resolution: "eslint-plugin-unicorn@npm:47.0.0"
@@ -16127,13 +15931,6 @@ __metadata:
languageName: node
linkType: hard
"fflate@npm:^0.4.8":
version: 0.4.8
resolution: "fflate@npm:0.4.8"
checksum: 29d8cbe44d5e7f53e7f5a160ac7f9cc025480c7b3bfd85c5f898cbe20dfa2dad4732daa534982664bf30b35896a90af44ea33ede5d94c5ffd1b8b0c0a0a56ca2
languageName: node
linkType: hard
"fflate@npm:^0.7.4":
version: 0.7.4
resolution: "fflate@npm:0.7.4"
@@ -17687,16 +17484,6 @@ __metadata:
languageName: node
linkType: hard
"html2canvas@npm:^1.0.0-rc.5":
version: 1.4.1
resolution: "html2canvas@npm:1.4.1"
dependencies:
css-line-break: ^2.1.0
text-segmentation: ^1.0.3
checksum: c134324af57f3262eecf982e436a4843fded3c6cf61954440ffd682527e4dd350e0c2fafd217c0b6f9a455fe345d0c67b4505689796ab160d4ca7c91c3766739
languageName: node
linkType: hard
"htmlparser2@npm:^3.9.2":
version: 3.10.1
resolution: "htmlparser2@npm:3.10.1"
@@ -19924,31 +19711,6 @@ __metadata:
languageName: node
linkType: hard
"jspdf@npm:^2.5.1":
version: 2.5.1
resolution: "jspdf@npm:2.5.1"
dependencies:
"@babel/runtime": ^7.14.0
atob: ^2.1.2
btoa: ^1.2.1
canvg: ^3.0.6
core-js: ^3.6.0
dompurify: ^2.2.0
fflate: ^0.4.8
html2canvas: ^1.0.0-rc.5
dependenciesMeta:
canvg:
optional: true
core-js:
optional: true
dompurify:
optional: true
html2canvas:
optional: true
checksum: 9ecdccc50678cd780f0995157618630ca0da65576835983232d48001aab0b29e51af765e078808526d5e5e2e1ebf3cee460e03eaf590f875d160f2e0cb614a1e
languageName: node
linkType: hard
"jsx-ast-utils@npm:^2.4.1 || ^3.0.0, jsx-ast-utils@npm:^3.3.3":
version: 3.3.3
resolution: "jsx-ast-utils@npm:3.3.3"
@@ -23051,13 +22813,6 @@ __metadata:
languageName: node
linkType: hard
"performance-now@npm:^2.1.0":
version: 2.1.0
resolution: "performance-now@npm:2.1.0"
checksum: 534e641aa8f7cba160f0afec0599b6cecefbb516a2e837b512be0adbe6c1da5550e89c78059c7fabc5c9ffdf6627edabe23eb7c518c4500067a898fa65c2b550
languageName: node
linkType: hard
"picocolors@npm:^1.0.0":
version: 1.0.0
resolution: "picocolors@npm:1.0.0"
@@ -23779,15 +23534,6 @@ __metadata:
languageName: node
linkType: hard
"raf@npm:^3.4.1":
version: 3.4.1
resolution: "raf@npm:3.4.1"
dependencies:
performance-now: ^2.1.0
checksum: 50ba284e481c8185dbcf45fc4618ba3aec580bb50c9121385d5698cb6012fe516d2015b1df6dd407a7b7c58d44be8086108236affbce1861edd6b44637c8cd52
languageName: node
linkType: hard
"ramda@npm:0.29.0":
version: 0.29.0
resolution: "ramda@npm:0.29.0"
@@ -24479,7 +24225,7 @@ __metadata:
languageName: node
linkType: hard
"regenerator-runtime@npm:^0.13.11, regenerator-runtime@npm:^0.13.7, regenerator-runtime@npm:^0.13.9":
"regenerator-runtime@npm:^0.13.11, regenerator-runtime@npm:^0.13.9":
version: 0.13.11
resolution: "regenerator-runtime@npm:0.13.11"
checksum: 27481628d22a1c4e3ff551096a683b424242a216fee44685467307f14d58020af1e19660bf2e26064de946bad7eff28950eae9f8209d55723e2d9351e632bbb4
@@ -24898,13 +24644,6 @@ __metadata:
languageName: node
linkType: hard
"rgbcolor@npm:^1.0.1":
version: 1.0.1
resolution: "rgbcolor@npm:1.0.1"
checksum: bd062ac007a3e979e2f83dc69feb3cc4f9bca7d8631899548394160e30c47e4f7e52b31aa3f66a69061ad56e899e812ec52f5c33686c085d72c9b3d22faed1c8
languageName: node
linkType: hard
"rimraf@npm:^2.6.1":
version: 2.7.1
resolution: "rimraf@npm:2.7.1"
@@ -25810,13 +25549,6 @@ __metadata:
languageName: node
linkType: hard
"stackblur-canvas@npm:^2.0.0":
version: 2.6.0
resolution: "stackblur-canvas@npm:2.6.0"
checksum: 4356b3362773ff9511a8cea715ceda94e45c4e8c34276ddc7e71f2817467b09f66d6bcb299340a661d8ddc053da682aa4d93080ea97492514028762c2ab88e8d
languageName: node
linkType: hard
"stacktrace-parser@npm:^0.1.10":
version: 0.1.10
resolution: "stacktrace-parser@npm:0.1.10"
@@ -26350,13 +26082,6 @@ __metadata:
languageName: node
linkType: hard
"svg-pathdata@npm:^6.0.3":
version: 6.0.3
resolution: "svg-pathdata@npm:6.0.3"
checksum: f0e55be50c654be5d259d70945ed7e5354bf78e51c6039b4045d9f7c49d703a0c33dda36751815aec2824d046c417c35226e7491246ffff3e9164735ea428446
languageName: node
linkType: hard
"swap-case@npm:^2.0.2":
version: 2.0.2
resolution: "swap-case@npm:2.0.2"
@@ -26586,15 +26311,6 @@ __metadata:
languageName: node
linkType: hard
"text-segmentation@npm:^1.0.3":
version: 1.0.3
resolution: "text-segmentation@npm:1.0.3"
dependencies:
utrie: ^1.0.2
checksum: 2e24632d59567c55ab49ac324815e2f7a8043e63e26b109636322ac3e30692cee8679a448fd5d0f0598a345f407afd0e34ba612e22524cf576d382d84058c013
languageName: node
linkType: hard
"text-table@npm:^0.2.0":
version: 0.2.0
resolution: "text-table@npm:0.2.0"
@@ -27648,15 +27364,6 @@ __metadata:
languageName: node
linkType: hard
"utrie@npm:^1.0.2":
version: 1.0.2
resolution: "utrie@npm:1.0.2"
dependencies:
base64-arraybuffer: ^1.0.2
checksum: c96fbb7d4d8855a154327da0b18e39b7511cc70a7e4bcc3658e24f424bb884312d72b5ba777500b8858e34d365dc6b1a921dc5ca2f0d341182519c6b78e280a5
languageName: node
linkType: hard
"uuid@npm:9.0.0, uuid@npm:^9.0.0":
version: 9.0.0
resolution: "uuid@npm:9.0.0"
@@ -28302,7 +28009,7 @@ __metadata:
languageName: node
linkType: hard
"which@npm:^3.0.0, which@npm:^3.0.1":
"which@npm:^3.0.0":
version: 3.0.1
resolution: "which@npm:3.0.1"
dependencies: