Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dd8c26df02 | ||
|
|
dd832b7482 | ||
|
|
6593855f8f | ||
|
|
dab835ad86 | ||
|
|
06967d8057 | ||
|
|
ceaf1ccc21 | ||
|
|
33ff6b2f23 | ||
|
|
eda5d9f4f9 | ||
|
|
5c74e1d667 | ||
|
|
e1f9260982 | ||
|
|
a7819c6456 | ||
|
|
373407fd57 | ||
|
|
47d17e6bb2 | ||
|
|
91b1430e7b | ||
|
|
7335119933 | ||
|
|
6061dc1989 | ||
|
|
c760ca6788 | ||
|
|
5a0f87fe02 | ||
|
|
2a6ce12a55 | ||
|
|
0aed86737f | ||
|
|
afd8335e95 | ||
|
|
cd013529d4 | ||
|
|
bf3a0b6e5b | ||
|
|
0933935071 | ||
|
|
427d2c2e25 | ||
|
|
aecf29ddca | ||
|
|
f65ee293ae | ||
|
|
e9712540a1 | ||
|
|
bcf9e83fd7 | ||
|
|
fa33f0c21b | ||
|
|
257ea11ce6 | ||
|
|
ddcbd25fae | ||
|
|
9b8c110a66 | ||
|
|
320aea039a | ||
|
|
9434bff9c9 | ||
|
|
ff203a91eb | ||
|
|
afa629a2b4 | ||
|
|
f192406afd | ||
|
|
4e2bd6ba74 | ||
|
|
53e2fbad3d | ||
|
|
4ba1ba00a5 | ||
|
|
5ceaee415c | ||
|
|
bf36cbccbb | ||
|
|
6d4335ae04 | ||
|
|
bbbf3006c9 | ||
|
|
fa57de5419 | ||
|
|
04f61cdf5e | ||
|
|
983fed16dc | ||
|
|
e0495b65ab | ||
|
|
45826b5571 | ||
|
|
8df2dccfce | ||
|
|
686507cd67 | ||
|
|
487e5035bb | ||
|
|
f872c6c1f8 | ||
|
|
08433defd8 | ||
|
|
68dfde4cf8 | ||
|
|
d6409e5889 | ||
|
|
ebfddc744b | ||
|
|
c407c38dc3 | ||
|
|
ddc2926c9b | ||
|
|
17c8f9fdde | ||
|
|
82ac2a5d79 | ||
|
|
5809758539 | ||
|
|
93863462a2 | ||
|
|
7cceafa432 | ||
|
|
4b63170e56 | ||
|
|
1c3c519b14 | ||
|
|
7646f984e0 | ||
|
|
32e0b5e96d | ||
|
|
30bedb337f | ||
|
|
832db73410 | ||
|
|
837666d36d | ||
|
|
10187ce049 | ||
|
|
68b0730dda | ||
|
|
1ab3f42477 | ||
|
|
15d91d3cbe | ||
|
|
f55de1fd17 | ||
|
|
014ff27881 | ||
|
|
dd3f1d0b24 | ||
|
|
561aa348e9 | ||
|
|
79d30eb84d | ||
|
|
d0b02cb4fd | ||
|
|
9135b92a39 | ||
|
|
ecf2598be7 | ||
|
|
59aed762e7 | ||
|
|
337161c3d7 | ||
|
|
9f8e3b09c3 | ||
|
|
0c6903f793 | ||
|
|
084e9c5f6f | ||
|
|
680d130986 | ||
|
|
248473dddf | ||
|
|
67dff1720b | ||
|
|
cac0dcaf7f | ||
|
|
c5aefeb45e | ||
|
|
e1f6e483e7 | ||
|
|
1796d0a448 | ||
|
|
f1a8919772 | ||
|
|
28e3cb35b8 | ||
|
|
62bafce0b2 | ||
|
|
e9ba1e1886 | ||
|
|
0d47397851 | ||
|
|
592e91bed4 | ||
|
|
0758db971b | ||
|
|
662220ab8a | ||
|
|
18407a0e47 | ||
|
|
cb57d20bfb | ||
|
|
a6f675c1d9 | ||
|
|
ec4d69e5b8 | ||
|
|
e65a320c00 | ||
|
|
5519dcd525 | ||
|
|
92b3f3e769 | ||
|
|
ef1d10b377 | ||
|
|
ea0179536d | ||
|
|
b21498dc9b | ||
|
|
062873a1fe | ||
|
|
177ed8d51a | ||
|
|
728d60239a | ||
|
|
df5e178c6c | ||
|
|
be806e301c | ||
|
|
8127e47cea | ||
|
|
99cadf98d2 | ||
|
|
aaca3ba90d | ||
|
|
6e8c3c821a | ||
|
|
f709bb6a6d | ||
|
|
4aa51a933d | ||
|
|
df642b54f6 | ||
|
|
204c0a90f2 | ||
|
|
2090c36f71 | ||
|
|
fcc6f51b3b | ||
|
|
a48031df7c | ||
|
|
442bf57e44 | ||
|
|
195bb9edcb | ||
|
|
fccd8ad4b9 | ||
|
|
0159414cac | ||
|
|
3a1136a8fb | ||
|
|
513423a9be | ||
|
|
3e3ac9503c | ||
|
|
5a3099e323 | ||
|
|
68d4c6dbdb | ||
|
|
595cfed892 | ||
|
|
d7b936a017 | ||
|
|
835a64ca75 | ||
|
|
214946cbbc | ||
|
|
8e14f8b9f1 | ||
|
|
95247bc5fb | ||
|
|
578bf963f7 | ||
|
|
6ea43cd5e5 | ||
|
|
1c6b78e7d4 | ||
|
|
beb844da17 | ||
|
|
ef8624e87c | ||
|
|
564af73076 | ||
|
|
814f9f4c19 | ||
|
|
1c2c1e6250 | ||
|
|
8449f736e7 | ||
|
|
80242afb93 | ||
|
|
17e82f98d5 | ||
|
|
774d9ddcf6 | ||
|
|
df0e128810 | ||
|
|
e98972cebc | ||
|
|
c9c2ea74ad | ||
|
|
e77e6d275f | ||
|
|
2fa99a563c | ||
|
|
17955bcf43 | ||
|
|
eff62b24fb | ||
|
|
6b314ea283 | ||
|
|
75bc7495bd | ||
|
|
c95fdc4782 | ||
|
|
9f54be3fcc | ||
|
|
8eaec5e58c | ||
|
|
cc86089715 | ||
|
|
f0f4bc0b30 | ||
|
|
1cd1d49c07 | ||
|
|
4cdf3e3e3e | ||
|
|
61dd68199e | ||
|
|
49f1a96cda | ||
|
|
d333f754c2 | ||
|
|
44af890f05 | ||
|
|
353bdc592b | ||
|
|
22c8850cea | ||
|
|
d97abcc99f | ||
|
|
f90e3b63cd | ||
|
|
48e9e75cc7 | ||
|
|
7f8c0ed53f | ||
|
|
bba8f8ae01 | ||
|
|
a9eec5baed | ||
|
|
24c1817c8d | ||
|
|
d5ffeb3c8a | ||
|
|
10d99bdd8b | ||
|
|
8fa3590661 | ||
|
|
cfb589dda1 | ||
|
|
dccbd45a00 | ||
|
|
fa91654f68 | ||
|
|
2031368ac3 | ||
|
|
23c4924532 | ||
|
|
ccb7d0181f | ||
|
|
1313178924 | ||
|
|
222067ec5a | ||
|
|
1e66aae051 | ||
|
|
9d8db6e746 | ||
|
|
1c8d5a782b | ||
|
|
cae691df9a | ||
|
|
27f900753e | ||
|
|
dc05a4cc65 | ||
|
|
4da2dadf69 | ||
|
|
33212df63a | ||
|
|
d1c5df4b88 | ||
|
|
130923af55 | ||
|
|
fa006e0b99 | ||
|
|
584af6aa71 | ||
|
|
2317f1682c | ||
|
|
8c17e96c51 | ||
|
|
ffa9d7bbf4 | ||
|
|
c1ccad104b | ||
|
|
907b10b783 | ||
|
|
fd98b192af | ||
|
|
324dc53e5f | ||
|
|
0ed1847672 | ||
|
|
03e58a90d2 | ||
|
|
01d2860948 | ||
|
|
b2eb964045 | ||
|
|
afeda52419 | ||
|
|
44ff74a37c | ||
|
|
cfeb408bab | ||
|
|
7f1a0adf13 | ||
|
|
3eff006d6d | ||
|
|
6bca483c28 | ||
|
|
02201c238c | ||
|
|
13aba928c3 | ||
|
|
3964508cd8 | ||
|
|
f9b552395b | ||
|
|
dac86ef857 | ||
|
|
718613de42 | ||
|
|
554cfb53e5 | ||
|
|
0fba8d9195 | ||
|
|
3c819ead49 | ||
|
|
60e9071685 | ||
|
|
4bdd9df54c | ||
|
|
e7aad4045b | ||
|
|
855d396122 | ||
|
|
2ae4762de8 | ||
|
|
95378dd73a | ||
|
|
46a3eb57fa | ||
|
|
5e56f5e0ec | ||
|
|
08a43c03d4 | ||
|
|
7e7254b306 | ||
|
|
c456687a18 | ||
|
|
1e0cef41a9 | ||
|
|
287698be9e | ||
|
|
f66ea6d224 | ||
|
|
28d8a3a269 | ||
|
|
2a134bcb40 | ||
|
|
956ad1b590 | ||
|
|
1cfcbbc35b | ||
|
|
9ca2d60f3f | ||
|
|
b239f28d10 | ||
|
|
4fd9388b79 | ||
|
|
a488944d2c | ||
|
|
53126c47d1 | ||
|
|
85ad90fc51 | ||
|
|
ddd0dec5c3 | ||
|
|
33d82a5104 | ||
|
|
2e047de2a2 | ||
|
|
1846f86dd7 | ||
|
|
b354fb79c8 | ||
|
|
96f6a1d37c | ||
|
|
3fd3389f62 | ||
|
|
7b772a8a6e | ||
|
|
89bff10c84 | ||
|
|
af08c55ebf | ||
|
|
661940f728 | ||
|
|
951584c2ab | ||
|
|
1a869c0003 | ||
|
|
12e8424e8a | ||
|
|
df5266d7c9 | ||
|
|
a654623c12 | ||
|
|
09ef0927f7 | ||
|
|
45821f00a2 | ||
|
|
282ed9067a | ||
|
|
f17f0dd6cf | ||
|
|
152cb17701 | ||
|
|
e4e40ebe20 | ||
|
|
049b8828fe | ||
|
|
a0e6c61f50 | ||
|
|
bbc9190bc0 | ||
|
|
0c7c3621d7 | ||
|
|
2b9ce79ed4 | ||
|
|
95e0418d97 | ||
|
|
e069bfb057 | ||
|
|
463cab6eee | ||
|
|
64ea2d4f31 | ||
|
|
777082c879 | ||
|
|
cb4398eab0 | ||
|
|
eb601932ea | ||
|
|
da4f7f40e7 | ||
|
|
da1ed0c320 | ||
|
|
dd5d745c31 | ||
|
|
cd85f3f464 | ||
|
|
bda6840523 | ||
|
|
bc645af3e2 | ||
|
|
c2196c7dba | ||
|
|
6325bd300b | ||
|
|
547be89b72 | ||
|
|
e0e48f1e99 | ||
|
|
3d67c0698a | ||
|
|
9fc13c7d62 | ||
|
|
7270c578e9 | ||
|
|
b25db57fca | ||
|
|
adce96f15b | ||
|
|
d9421f70a0 | ||
|
|
b04111e5a3 | ||
|
|
b22b8ab3a0 | ||
|
|
b66f46108d | ||
|
|
e55b79d3e6 | ||
|
|
d3a00b14b0 | ||
|
|
ef491f4276 | ||
|
|
f0b61546fe | ||
|
|
16c702b1e1 | ||
|
|
936e133624 | ||
|
|
77be3e9c71 | ||
|
|
79aa20d662 | ||
|
|
987a246c80 | ||
|
|
baade1f5d4 | ||
|
|
7a264dba6a | ||
|
|
fc74b2b962 | ||
|
|
d445aeb304 | ||
|
|
cdb36f9526 | ||
|
|
327fa0c811 | ||
|
|
1744938a51 | ||
|
|
913da7ce5b | ||
|
|
a93d7e1987 | ||
|
|
405c618d27 | ||
|
|
6f5e19d053 | ||
|
|
4a46bf3fa3 | ||
|
|
9b85349650 | ||
|
|
b413fade91 | ||
|
|
72a851bd7e | ||
|
|
4a49669cc5 | ||
|
|
869399eb16 | ||
|
|
511b6658a4 | ||
|
|
ef6e777ec0 | ||
|
|
446da06212 | ||
|
|
a8b42cbc95 | ||
|
|
84d5d2c2f1 | ||
|
|
c93e73d3d1 | ||
|
|
1b1ab4ad26 | ||
|
|
013d8f753a | ||
|
|
2e24ae65fd | ||
|
|
72a8f7a9e3 | ||
|
|
75f021744b | ||
|
|
6f05d317e9 | ||
|
|
a5facab7e3 | ||
|
|
72fef86e28 | ||
|
|
5946dd0b7b | ||
|
|
8adc4501ef | ||
|
|
5b7e6690f8 | ||
|
|
bf344685e6 | ||
|
|
31086ad4df | ||
|
|
ab214d4a74 | ||
|
|
df432d11c3 | ||
|
|
dfa9c04f5a | ||
|
|
54cd9eca8c | ||
|
|
0231ad3adf | ||
|
|
90e3ba14f1 | ||
|
|
94dc76d1a9 | ||
|
|
66defa85f6 | ||
|
|
c2f4ee4cac | ||
|
|
31ced8bde7 | ||
|
|
d3bfca10e9 | ||
|
|
d80061461b | ||
|
|
85cc9b60d9 | ||
|
|
c8f6f4861b | ||
|
|
b73f35b18c | ||
|
|
69ee8aff55 | ||
|
|
aeb448c4de | ||
|
|
34441ee076 | ||
|
|
d283d29202 | ||
|
|
45d9a0918f | ||
|
|
3fa0f97e74 | ||
|
|
909406bf08 | ||
|
|
0172fc71db | ||
|
|
6b338d4cc5 | ||
|
|
7ac55f29db | ||
|
|
4450d4410b | ||
|
|
23f4684d3f | ||
|
|
8a9a23ddbe | ||
|
|
2f413a8e67 | ||
|
|
8457682092 | ||
|
|
6298a0d96d | ||
|
|
29c14949cb | ||
|
|
cea83238eb | ||
|
|
e28b1ab8b3 | ||
|
|
2aaa076592 | ||
|
|
b8ce9b9afb | ||
|
|
90cac1819a | ||
|
|
a519e96b17 | ||
|
|
a935f25344 | ||
|
|
5a89655982 | ||
|
|
52d510691f | ||
|
|
ee9884ba34 | ||
|
|
90b5eca5d9 | ||
|
|
bb07eeb2e2 | ||
|
|
b701abed12 | ||
|
|
2e7ab3000f | ||
|
|
ce8805aff8 | ||
|
|
31efacb274 | ||
|
|
63082418be | ||
|
|
c649673b2b | ||
|
|
76691e3e8c | ||
|
|
e7cc11cc44 | ||
|
|
6fa7b0632a | ||
|
|
2514a65617 | ||
|
|
643bb25e2b | ||
|
|
67ef72ee41 | ||
|
|
719c2d10c7 | ||
|
|
0999263902 | ||
|
|
83b30a2185 | ||
|
|
31d3ffb664 | ||
|
|
739333c29c | ||
|
|
24ea68c605 | ||
|
|
06a91b02fb | ||
|
|
6653385a85 | ||
|
|
6e51173335 | ||
|
|
b17a3f50db | ||
|
|
cb802c3162 | ||
|
|
76c1cd70a5 | ||
|
|
8f582faffe | ||
|
|
5f064b8118 | ||
|
|
e46326f775 | ||
|
|
cdc6da835e | ||
|
|
10febe2497 | ||
|
|
d1364354ff | ||
|
|
488ba00456 | ||
|
|
e1ed027b9c | ||
|
|
6504863586 | ||
|
|
d33f646790 | ||
|
|
d6b5e4c404 | ||
|
|
6b7a46e781 | ||
|
|
aa86a44af8 | ||
|
|
8259752958 | ||
|
|
826be05494 | ||
|
|
2d058ea100 | ||
|
|
d8171238f2 | ||
|
|
28f0288526 | ||
|
|
d822f036e0 | ||
|
|
e763525c58 | ||
|
|
f22cf6349b | ||
|
|
079f18d727 | ||
|
|
321de104fe | ||
|
|
841d5e6fd0 | ||
|
|
57f8226b38 | ||
|
|
3363952a23 | ||
|
|
0c1263cb78 | ||
|
|
c4088622f8 | ||
|
|
8c54949271 | ||
|
|
1239c9026e | ||
|
|
964aec8066 | ||
|
|
8940f87935 | ||
|
|
fc82b2b7e1 | ||
|
|
c8a7fb2e2b | ||
|
|
ed117c4d31 | ||
|
|
f9bfe94a6b | ||
|
|
180b0cd568 | ||
|
|
172e1ab1de | ||
|
|
271cd0dd61 | ||
|
|
3abd5b953e | ||
|
|
8d9cde17a9 | ||
|
|
f8f5b7c233 | ||
|
|
b83ff2c3c5 | ||
|
|
3d93308293 | ||
|
|
d010211028 | ||
|
|
f59cf4eb71 | ||
|
|
784d518632 | ||
|
|
3648a42054 | ||
|
|
b37e636da3 | ||
|
|
0f48d5da53 | ||
|
|
35d3224d08 | ||
|
|
e2c2a6602a | ||
|
|
08de5da716 | ||
|
|
ac32760bfc | ||
|
|
688ca90ec8 | ||
|
|
038bf41077 | ||
|
|
4a72b7a87c | ||
|
|
ba5d66cea0 | ||
|
|
2c8cce99e8 | ||
|
|
a0c59fd61d | ||
|
|
542622c512 | ||
|
|
513df69042 | ||
|
|
5c5f0f6a1e | ||
|
|
627aac9a15 | ||
|
|
870aa61080 | ||
|
|
f45608163c | ||
|
|
fd07d64a7b | ||
|
|
93b7cf481b | ||
|
|
ce077c059e | ||
|
|
054fa4c952 | ||
|
|
ce126fe08d | ||
|
|
7b47fb5c7f | ||
|
|
0d28267386 | ||
|
|
76c8aa82ad | ||
|
|
8acdb82612 | ||
|
|
6c9fa781cf | ||
|
|
7288224c3e | ||
|
|
9790251aa2 | ||
|
|
1ee5a9402b | ||
|
|
b2f3570bbf | ||
|
|
fe88e100e2 | ||
|
|
0f0dd5755d | ||
|
|
5703d7ea9f | ||
|
|
08635f1984 | ||
|
|
dd92d0faf4 | ||
|
|
91d9516dc7 | ||
|
|
db5d9aa891 | ||
|
|
b8eedf70c3 | ||
|
|
838c85c5f2 | ||
|
|
9fc5d628b0 | ||
|
|
a216c52416 | ||
|
|
538d8916c7 | ||
|
|
9d5eafc97b | ||
|
|
24ca6259da | ||
|
|
7bf0d8e230 | ||
|
|
0548546881 | ||
|
|
0bbf9c3ef1 | ||
|
|
9453f8a4b7 | ||
|
|
19521bf695 | ||
|
|
4e9472c3e8 | ||
|
|
32949d0395 | ||
|
|
f21cd52f26 | ||
|
|
e66c8ac78e | ||
|
|
6c958cf43d | ||
|
|
09358570b3 | ||
|
|
1517202889 | ||
|
|
a535b8585f | ||
|
|
4324897054 | ||
|
|
169f1e2c44 | ||
|
|
e713a6dfc6 | ||
|
|
ccf7ff8888 | ||
|
|
ac9a89fdca | ||
|
|
d4432eabb9 | ||
|
|
b0ab6bdd4b | ||
|
|
a008cb6bd5 | ||
|
|
c6524b273f | ||
|
|
35f4aa64c4 | ||
|
|
673afa1fcb | ||
|
|
702a04ab24 | ||
|
|
4beeffbc37 | ||
|
|
d4fc1b9126 | ||
|
|
502229adb8 | ||
|
|
e5d8581091 | ||
|
|
4b1010fb13 | ||
|
|
910a70fb41 | ||
|
|
01cc16d50f | ||
|
|
0dcaa6be2f | ||
|
|
d3dd3e229d | ||
|
|
7f70036951 | ||
|
|
81511764c4 | ||
|
|
704035e070 | ||
|
|
3038dc3c93 | ||
|
|
2a1c5a3420 | ||
|
|
0888e7afbd | ||
|
|
7d5c002952 | ||
|
|
461a4ddb3f | ||
|
|
89bbd5b893 | ||
|
|
8e994a954e | ||
|
|
be23b4cc5a | ||
|
|
8fc2089d51 | ||
|
|
55c05364dd | ||
|
|
8f1d62f115 | ||
|
|
f93f012bc8 | ||
|
|
0fc09dcb53 | ||
|
|
447766f9cb | ||
|
|
c25153e666 | ||
|
|
8660ade554 | ||
|
|
f474476e24 | ||
|
|
a06a2b9e5b | ||
|
|
ba67652e29 | ||
|
|
2449e9352c | ||
|
|
80d1b3072d | ||
|
|
7bd2773cf2 | ||
|
|
c64ef55d60 | ||
|
|
91c9f2c62f | ||
|
|
7c60626049 | ||
|
|
49cbc6c1b3 | ||
|
|
9474f1f722 | ||
|
|
5076a6cb38 | ||
|
|
d965d26e60 | ||
|
|
2b9367aa40 | ||
|
|
0b6d52cb46 | ||
|
|
b7a40a7cda | ||
|
|
58078c26db | ||
|
|
5a1e059a78 | ||
|
|
fc5e82d169 | ||
|
|
93ce7d3b7d | ||
|
|
6536098b38 | ||
|
|
5ee37972ef | ||
|
|
59922b95a9 | ||
|
|
89ba4195e5 | ||
|
|
f94f3f2d6a | ||
|
|
74239d65cb | ||
|
|
19968010af | ||
|
|
796a0a9f41 | ||
|
|
3cfa7d0c68 | ||
|
|
e334cde639 | ||
|
|
1cdf5aea53 | ||
|
|
ce8979afe8 | ||
|
|
df053fbc48 | ||
|
|
fcb8d49cf9 | ||
|
|
a72dc5d2ec | ||
|
|
418812d61d | ||
|
|
a2854297b3 | ||
|
|
92ab7eac17 | ||
|
|
96560d2b3e |
No files matched your search
+4
-7
@@ -1,7 +1,4 @@
|
||||
.env
|
||||
.dockerignore
|
||||
doc/
|
||||
scripts/
|
||||
rust-lib/target/
|
||||
backend/target/
|
||||
app_flowy/
|
||||
frontend/app_flowy/
|
||||
frontend/scripts/
|
||||
frontend/rust-lib/target
|
||||
shared-lib/target/
|
||||
Executable → Regular
+1
-1
@@ -11,7 +11,7 @@ function file_too_large(){
|
||||
cat <<HEREDOC
|
||||
|
||||
File $filename is $filesize MB, which is larger than github's maximum
|
||||
file size (1 MB). We will not be able to push this file to Github.
|
||||
file size (1 MB). We will not be able to push this file to GitHub.
|
||||
Commit aborted
|
||||
HEREDOC
|
||||
|
||||
|
||||
Executable → Regular
File mode changed.
@@ -0,0 +1,79 @@
|
||||
name: CI
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
pull_request:
|
||||
branches: [main]
|
||||
jobs:
|
||||
build-macos:
|
||||
runs-on: macOS-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
- name: Checkout Flutter
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
repository: flutter/flutter
|
||||
path: flutter
|
||||
- name: Flutter
|
||||
working-directory: flutter
|
||||
run: |
|
||||
echo "$(pwd)/bin" >> $GITHUB_PATH
|
||||
export PATH="$PATH:$(pwd)/bin"
|
||||
flutter channel stable
|
||||
flutter config --enable-macos-desktop
|
||||
flutter doctor
|
||||
- name: Deps
|
||||
working-directory: frontend
|
||||
run: |
|
||||
cargo install --force cargo-make
|
||||
cargo install --force duckscript_cli
|
||||
cargo make flowy_dev
|
||||
echo PATH="$PATH":"$HOME/.pub-cache/bin" >> $GITHUB_PATH
|
||||
- name: Build
|
||||
working-directory: frontend
|
||||
run: cargo make --profile production-mac-x86 appflowy
|
||||
build-ubuntu:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
- name: Packages
|
||||
run: |
|
||||
sudo wget -qO /etc/apt/trusted.gpg.d/dart_linux_signing_key.asc https://dl-ssl.google.com/linux/linux_signing_key.pub
|
||||
sudo wget -qO /etc/apt/sources.list.d/dart_stable.list https://storage.googleapis.com/download.dartlang.org/linux/debian/dart_stable.list
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y dart curl build-essential libsqlite3-dev libssl-dev clang cmake ninja-build pkg-config libgtk-3-dev
|
||||
- name: Rust
|
||||
run: |
|
||||
curl \
|
||||
--proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
|
||||
source $HOME/.cargo/env
|
||||
rustup toolchain install stable
|
||||
rustup default stable
|
||||
- name: Checkout Flutter
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
repository: flutter/flutter
|
||||
path: flutter
|
||||
- name: Flutter
|
||||
working-directory: flutter
|
||||
run: |
|
||||
echo "$(pwd)/bin" >> $GITHUB_PATH
|
||||
export PATH="$PATH:$(pwd)/bin"
|
||||
flutter channel stable
|
||||
flutter config --enable-linux-desktop
|
||||
flutter doctor
|
||||
- name: Deps
|
||||
working-directory: frontend
|
||||
run: |
|
||||
cargo install --force cargo-make
|
||||
cargo install --force duckscript_cli
|
||||
cargo make flowy_dev
|
||||
echo PATH="$PATH":"$HOME/.pub-cache/bin" >> $GITHUB_PATH
|
||||
- name: Build
|
||||
working-directory: frontend
|
||||
run: cargo make --profile production-linux-x86 appflowy
|
||||
@@ -0,0 +1,12 @@
|
||||
name: Commit messages lint
|
||||
on: [pull_request, push]
|
||||
|
||||
jobs:
|
||||
commitlint:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: wagoid/commitlint-github-action@v4
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
# This workflow uses actions that are not certified by GitHub.
|
||||
# They are provided by a third-party and are governed by
|
||||
# separate terms of service, privacy policy, and support
|
||||
# documentation.
|
||||
|
||||
name: Flutter lint
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
pull_request:
|
||||
branches: [ main ]
|
||||
|
||||
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
|
||||
jobs:
|
||||
flutter-analyze:
|
||||
name: flutter analyze
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
- uses: subosito/flutter-action@v1
|
||||
with:
|
||||
channel: "stable"
|
||||
- name: Flutter pub get
|
||||
run: flutter pub get
|
||||
working-directory: frontend/app_flowy
|
||||
- name: Generate language files
|
||||
working-directory: frontend/app_flowy
|
||||
run:
|
||||
flutter pub run easy_localization:generate --source-dir ./assets/translations -f keys -O lib/generated -o locale_keys.g.dart
|
||||
- name: flutter analyze
|
||||
working-directory: frontend/app_flowy
|
||||
run: flutter analyze
|
||||
|
||||
@@ -0,0 +1,129 @@
|
||||
name: release
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- '*'
|
||||
|
||||
jobs:
|
||||
create-release:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
RELEASE_NOTES_PATH: /tmp/release_notes
|
||||
outputs:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Build release notes
|
||||
working-directory: frontend/app_flowy
|
||||
run: |
|
||||
touch ${{ env.RELEASE_NOTES_PATH }}
|
||||
cat CHANGELOG.md | sed -e '/./{H;$!d;}' -e "x;/##\ Version\ ${{ github.ref_name }}/"'!d;' >> ${{ env.RELEASE_NOTES_PATH }}
|
||||
|
||||
- name: Create release
|
||||
id: create_release
|
||||
uses: actions/create-release@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
tag_name: ${{ github.ref }}
|
||||
release_name: Release ${{ github.ref }}
|
||||
body_path: ${{ env.RELEASE_NOTES_PATH }}
|
||||
|
||||
build-linux-x86:
|
||||
runs-on: ubuntu-latest
|
||||
needs: create-release
|
||||
env:
|
||||
LINUX_APP_RELEASE_PATH: frontend/app_flowy/product/${{ github.ref_name }}/linux/Release
|
||||
LINUX_ZIP_NAME: AppFlowy-linux-x86.tar.gz
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Setup environment - Rust and Cargo
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
|
||||
- name: Setup environment - Flutter
|
||||
uses: subosito/flutter-action@v2
|
||||
with:
|
||||
channel: 'stable'
|
||||
|
||||
- name: Pre build
|
||||
working-directory: frontend
|
||||
run: |
|
||||
sudo wget -qO /etc/apt/trusted.gpg.d/dart_linux_signing_key.asc https://dl-ssl.google.com/linux/linux_signing_key.pub
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y build-essential libsqlite3-dev libssl-dev clang cmake ninja-build pkg-config libgtk-3-dev
|
||||
source $HOME/.cargo/env
|
||||
cargo install --force cargo-make
|
||||
cargo install --force duckscript_cli
|
||||
cargo make flowy_dev
|
||||
|
||||
- name: Build Linux app
|
||||
working-directory: frontend
|
||||
run: |
|
||||
flutter config --enable-linux-desktop
|
||||
cargo make --profile production-linux-x86 appflowy
|
||||
|
||||
- name: Upload Release Asset
|
||||
id: upload-release-asset
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ needs.create-release.outputs.upload_url }}
|
||||
asset_path: ${{ env.LINUX_APP_RELEASE_PATH }}/${{ env.LINUX_ZIP_NAME }}
|
||||
asset_name: ${{ env.LINUX_ZIP_NAME }}
|
||||
asset_content_type: application/octet-stream
|
||||
|
||||
build-macos-x86_64:
|
||||
runs-on: macos-latest
|
||||
needs: create-release
|
||||
env:
|
||||
MACOS_APP_RELEASE_PATH: frontend/app_flowy/product/${{ github.ref_name }}/macos/Release
|
||||
MACOS_X86_ZIP_NAME: Appflowy-macos-x86_64.zip
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Setup environment - Rust and Cargo
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
|
||||
- name: Setup environment - Flutter
|
||||
uses: subosito/flutter-action@v2
|
||||
with:
|
||||
channel: 'stable'
|
||||
|
||||
- name: Pre build
|
||||
working-directory: frontend
|
||||
run: |
|
||||
source $HOME/.cargo/env
|
||||
cargo install --force cargo-make
|
||||
cargo install --force duckscript_cli
|
||||
cargo make flowy_dev
|
||||
|
||||
- name: Build macOS app for x86_64
|
||||
working-directory: frontend
|
||||
run: |
|
||||
flutter config --enable-macos-desktop
|
||||
cargo make --profile production-mac-x86 appflowy
|
||||
|
||||
- name: Archive macOS app
|
||||
working-directory: ${{ env.MACOS_APP_RELEASE_PATH }}
|
||||
run: zip -qr ${{ env.MACOS_X86_ZIP_NAME }} AppFlowy.app
|
||||
|
||||
- name: Upload Release Asset
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ needs.create-release.outputs.upload_url }}
|
||||
asset_path: ${{ env.MACOS_APP_RELEASE_PATH }}/${{ env.MACOS_X86_ZIP_NAME }}
|
||||
asset_name: ${{ env.MACOS_X86_ZIP_NAME }}
|
||||
asset_content_type: application/octet-stream
|
||||
@@ -0,0 +1,47 @@
|
||||
name: Rust lint
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
paths:
|
||||
- 'frontend/rust-lib'
|
||||
- 'shared-lib'
|
||||
pull_request:
|
||||
branches: [ main ]
|
||||
paths:
|
||||
- 'frontend/rust-lib'
|
||||
- 'shared-lib'
|
||||
|
||||
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
|
||||
jobs:
|
||||
rust-fmt:
|
||||
name: Rustfmt
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
override: true
|
||||
- run: rustup component add rustfmt
|
||||
working-directory: frontend/rust-lib
|
||||
- run: cargo fmt --all -- --check
|
||||
working-directory: frontend/rust-lib/
|
||||
|
||||
|
||||
rust-clippy:
|
||||
runs-on: ubuntu-latest
|
||||
name: Clippy
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
override: true
|
||||
- run: rustup component add clippy
|
||||
working-directory: frontend/rust-lib
|
||||
- run: cargo clippy --no-default-features
|
||||
working-directory: frontend/rust-lib
|
||||
@@ -0,0 +1,39 @@
|
||||
name: Unit test(Rust)
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
# paths:
|
||||
# - 'frontend/rust-lib'
|
||||
# - 'shared-lib'
|
||||
pull_request:
|
||||
branches: [ main ]
|
||||
# paths:
|
||||
# - 'frontend/rust-lib'
|
||||
# - 'shared-lib'
|
||||
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
|
||||
jobs:
|
||||
tests:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
- name: Install Rust
|
||||
run: |
|
||||
curl \
|
||||
--proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
|
||||
source $HOME/.cargo/env
|
||||
rustup toolchain install stable
|
||||
rustup default stable
|
||||
- name: Install cargo-make
|
||||
run: cargo install --force cargo-make
|
||||
working-directory: frontend
|
||||
- name: RustLib tests
|
||||
run: cargo test --no-default-features
|
||||
working-directory: frontend/rust-lib
|
||||
- name: Sharedlib tests
|
||||
run: cargo test --no-default-features
|
||||
working-directory: shared-lib
|
||||
@@ -0,0 +1,19 @@
|
||||
name: Translation Notify
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
paths:
|
||||
- "frontend/app_flowy/assets/translations/en.json"
|
||||
pull_request:
|
||||
branches: [ main ]
|
||||
paths:
|
||||
- "frontend/app_flowy/assets/translations/en.json"
|
||||
jobs:
|
||||
Discord-Notify:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: Ilshidur/action-discord@0.3.2
|
||||
env:
|
||||
DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }}
|
||||
with:
|
||||
args: '@appflowytranslators English UI strings has been updated.'
|
||||
+9
-5
@@ -1,15 +1,19 @@
|
||||
# Generated by Cargo
|
||||
# will have compiled files and executables
|
||||
/target/
|
||||
|
||||
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
|
||||
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
|
||||
Cargo.lock
|
||||
# backend
|
||||
/target/
|
||||
|
||||
# These are backup files generated by rustfmt
|
||||
**/*.rs.bk
|
||||
**/target/
|
||||
**/*.db
|
||||
.idea/
|
||||
/flowy-test/
|
||||
.ruby-version
|
||||
**/temp/**
|
||||
.ruby-version
|
||||
package-lock.json
|
||||
yarn.lock
|
||||
node_modules
|
||||
**/.proto_cache
|
||||
**/.cache
|
||||
Executable
+4
@@ -0,0 +1,4 @@
|
||||
#!/bin/sh
|
||||
. "$(dirname "$0")/_/husky.sh"
|
||||
|
||||
npx --no -- commitlint --edit
|
||||
@@ -1,17 +1,18 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="ProtoBuf_Gen" type="CargoCommandRunConfiguration" factoryName="Cargo Command">
|
||||
<option name="command" value="run --manifest-path $PROJECT_DIR$/scripts/flowy-tool/Cargo.toml -- pb-gen --rust_source=$PROJECT_DIR$/rust-lib/ --derive_meta=$PROJECT_DIR$/rust-lib/flowy-derive/src/derive_cache/derive_cache.rs --flutter_package_lib=$PROJECT_DIR$/app_flowy/packages/flowy_sdk/lib" />
|
||||
<option name="workingDirectory" value="file://$PROJECT_DIR$" />
|
||||
<option name="command" value="run --manifest-path ${flowy_tool} -- pb-gen --rust_sources=${rust_lib},${shared_lib} --derive_meta=${derive_meta} --flutter_package_lib=${flutter_package_lib}" />
|
||||
<option name="workingDirectory" value="file://$PROJECT_DIR$/frontend" />
|
||||
<option name="channel" value="DEFAULT" />
|
||||
<option name="allFeatures" value="false" />
|
||||
<option name="emulateTerminal" value="false" />
|
||||
<option name="backtrace" value="SHORT" />
|
||||
<envs>
|
||||
<env name="rust_source" value="${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/rust-lib/" />
|
||||
<env name="build_cache" value="${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/rust-lib/flowy-derive/src/auto_gen_file/category_from_str.rs" />
|
||||
<env name="proto_file_output" value="${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/rust-lib/flowy-protobuf/define" />
|
||||
<env name="rust_mod_dir" value="${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/rust-lib/flowy-protobuf/src/" />
|
||||
<env name="flutter_mod_dir" value="${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/flutter-lib/packages/flowy_protobuf/lib/" />
|
||||
<env name="flowy_tool" value="${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/scripts/flowy-tool/Cargo.toml" />
|
||||
<env name="rust_lib" value="${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/rust-lib/" />
|
||||
<env name="shared_lib" value="${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/../shared_lib" />
|
||||
<env name="flutter_lib" value="${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/app_flowy/packages" />
|
||||
<env name="derive_meta" value="${shared_lib}/flowy-derive/src/derive_cache/derive_cache.rs" />
|
||||
<env name="flutter_package_lib" value="${flutter_lib}/flowy_sdk/lib" />
|
||||
</envs>
|
||||
<option name="isRedirectInput" value="false" />
|
||||
<option name="redirectInputPath" value="" />
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="dart-event" type="CargoCommandRunConfiguration" factoryName="Cargo Command">
|
||||
<option name="command" value="run --manifest-path $PROJECT_DIR$/scripts/flowy-tool/Cargo.toml -- dart-event --rust_source=$PROJECT_DIR$/rust-lib/ --output=$PROJECT_DIR$/app_flowy/packages/flowy_sdk/lib/dispatch/code_gen.dart" />
|
||||
<option name="command" value="run --manifest-path $PROJECT_DIR$/scripts/flowy-tool/Cargo.toml -- dart-event --rust_source=$PROJECT_DIR$/rust-lib/ --output=$PROJECT_DIR$/app_flowy/packages/flowy_sdk/lib/dispatch/dart_event.dart" />
|
||||
<option name="workingDirectory" value="file://$PROJECT_DIR$" />
|
||||
<option name="channel" value="DEFAULT" />
|
||||
<option name="allFeatures" value="false" />
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
.PHONY: flowy_dev install_cargo_make
|
||||
|
||||
flowy_dev: install_cargo_make
|
||||
cargo make flowy_dev
|
||||
|
||||
install_cargo_make:
|
||||
cargo install --force cargo-make
|
||||
|
||||
install_rust:
|
||||
sudo xcode-select -s /Applications/Xcode.app/Contents/Developer
|
||||
curl https://sh.rustup.rs -sSf | sh -s -- --default-toolchain nightly -y
|
||||
echo 'export PATH="$$HOME/.cargo/bin:$$PATH"' >> ~/.bash_profile
|
||||
source ~/.bash_profile
|
||||
+27
-88
@@ -1,96 +1,35 @@
|
||||
#https://github.com/sagiegurari/cargo-make
|
||||
|
||||
extend = [
|
||||
{ path = "scripts/makefile/desktop.toml" },
|
||||
{ path = "scripts/makefile/protobuf.toml" },
|
||||
{ path = "scripts/makefile/tests.toml" },
|
||||
{ path = "scripts/makefile/docker.toml" },
|
||||
{ path = "scripts/makefile/env.toml" },
|
||||
{ path = "scripts/makefile/flutter.toml" },
|
||||
]
|
||||
|
||||
[env]
|
||||
CARGO_MAKE_EXTEND_WORKSPACE_MAKEFILE = true
|
||||
CARGO_MAKE_CRATE_FS_NAME = "dart_ffi"
|
||||
CARGO_MAKE_CRATE_NAME = "dart-ffi"
|
||||
VERSION = "0.0.2"
|
||||
FEATURES = "flutter"
|
||||
PRODUCT_NAME = "AppFlowy"
|
||||
#CRATE_TYPE: https://doc.rust-lang.org/reference/linkage.html
|
||||
CRATE_TYPE = "cdylib"
|
||||
|
||||
|
||||
[env.development-mac]
|
||||
TARGET_OS = "macos"
|
||||
RUST_COMPILE_TARGET = "x86_64-apple-darwin"
|
||||
BUILD_FLAG = "debug"
|
||||
FLUTTER_OUTPUT_DIR = "Debug"
|
||||
PRODUCT_EXT = "app"
|
||||
|
||||
[env.production-desktop-mac-aarch64]
|
||||
BUILD_FLAG = "release"
|
||||
TARGET_OS = "macos"
|
||||
RUST_COMPILE_TARGET = "aarch64-apple-darwin"
|
||||
FLUTTER_OUTPUT_DIR = "Release"
|
||||
PRODUCT_EXT = "app"
|
||||
|
||||
[env.production-desktop-mac-x86]
|
||||
BUILD_FLAG = "release"
|
||||
TARGET_OS = "macos"
|
||||
RUST_COMPILE_TARGET = "x86_64-apple-darwin"
|
||||
FLUTTER_OUTPUT_DIR = "Release"
|
||||
PRODUCT_EXT = "app"
|
||||
CRATE_TYPE = "staticlib"
|
||||
|
||||
[env.production-desktop-windows-x86]
|
||||
BUILD_FLAG = "release"
|
||||
TARGET_OS = "windows"
|
||||
RUST_COMPILE_TARGET = "x86_64-pc-windows-gnu"
|
||||
FLUTTER_OUTPUT_DIR = "Release"
|
||||
PRODUCT_EXT = "exe"
|
||||
|
||||
[tasks.echo_env]
|
||||
script = [
|
||||
'''
|
||||
echo CRATE_TYPE: ${CRATE_TYPE}
|
||||
echo BUILD_FLAG: ${BUILD_FLAG}
|
||||
echo TARGET_OS: ${TARGET_OS}
|
||||
echo RUST_COMPILE_TARGET: ${RUST_COMPILE_TARGET}
|
||||
echo FEATURES: ${FEATURES}
|
||||
echo PRODUCT_EXT: ${PRODUCT_EXT}
|
||||
echo ${platforms}
|
||||
'''
|
||||
]
|
||||
|
||||
[env.production-ios]
|
||||
BUILD_FLAG = "release"
|
||||
TARGET_OS = "ios"
|
||||
CRATE_TYPE = "staticlib"
|
||||
BUILD_FLAG = "release"
|
||||
FLUTTER_OUTPUT_DIR = "Release"
|
||||
PRODUCT_EXT = "ipa"
|
||||
|
||||
|
||||
[tasks.setup-crate-type]
|
||||
private = true
|
||||
[tasks.install-commitlint.mac]
|
||||
script = [
|
||||
"""
|
||||
toml = readfile ${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/rust-lib/${CARGO_MAKE_CRATE_NAME}/Cargo.toml
|
||||
val = replace ${toml} "dylib" ${CRATE_TYPE}
|
||||
result = writefile ${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/rust-lib/${CARGO_MAKE_CRATE_NAME}/Cargo.toml ${val}
|
||||
assert ${result}
|
||||
""",
|
||||
brew install npm
|
||||
yarn install
|
||||
yarn husky install
|
||||
""",
|
||||
]
|
||||
script_runner = "@shell"
|
||||
|
||||
[tasks.install-commitlint.windows]
|
||||
script = [
|
||||
"""
|
||||
echo "WIP"
|
||||
""",
|
||||
]
|
||||
script_runner = "@duckscript"
|
||||
|
||||
[tasks.restore-crate-type]
|
||||
private = true
|
||||
[tasks.install-commitlint.linux]
|
||||
script = [
|
||||
"""
|
||||
toml = readfile ${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/rust-lib/${CARGO_MAKE_CRATE_NAME}/Cargo.toml
|
||||
val = replace ${toml} ${CRATE_TYPE} "dylib"
|
||||
result = writefile ${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/rust-lib/${CARGO_MAKE_CRATE_NAME}/Cargo.toml ${val}
|
||||
assert ${result}
|
||||
""",
|
||||
if command -v apt &> /dev/null
|
||||
then
|
||||
echo "Installing node.js and yarn (sudo apt install nodejs yarn)"
|
||||
sudo apt install nodejs yarn
|
||||
else
|
||||
echo "Installing node.js and yarn (sudo pacman -S nodejs yarn)"
|
||||
sudo pacman -S nodejs yarn
|
||||
fi
|
||||
|
||||
yarn install
|
||||
yarn husky install
|
||||
""",
|
||||
]
|
||||
script_runner = "@duckscript"
|
||||
script_runner = "@shell"
|
||||
@@ -2,38 +2,31 @@
|
||||
<b>
|
||||
<a href="https://www.appflowy.io">AppFlowy.IO</a><br>
|
||||
</b>
|
||||
⭐️ The Open Source Notion Alternative ⭐️ <br>
|
||||
⭐️ The Open Source Alternative To Notion ⭐️ <br>
|
||||
</h1>
|
||||
|
||||
|
||||
<p align="center">
|
||||
<a href="https://discord.gg/9Q2xaN37tV"><img src="https://img.shields.io/badge/AppFlowy.IO-discord-orange"></a>
|
||||
<a href="https://github.com/AppFlowy-IO/appflowy"><img src="https://img.shields.io/github/stars/AppFlowy-IO/appflowy.svg?style=flat&logo=github&colorB=deeppink&label=stars"></a>
|
||||
<a href="https://github.com/AppFlowy-IO/appflowy"><img src="https://img.shields.io/github/forks/AppFlowy-IO/appflowy.svg"></a>
|
||||
<a href="https://opensource.org/licenses/AGPL-3.0"><img src="https://img.shields.io/badge/license-APGL-purple.svg" alt="License: AGPL"></a>
|
||||
|
||||
</p>
|
||||
|
||||
|
||||
|
||||
<p align="center">
|
||||
You are in charge of your data and customizations.
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://discord.gg/9Q2xaN37tV"><img src="https://img.shields.io/badge/AppFlowy.IO-discord-orange"></a>
|
||||
<a href="https://github.com/AppFlowy-IO/appflowy"><img src="https://img.shields.io/github/stars/AppFlowy-IO/appflowy.svg?style=flat&logo=github&colorB=deeppink&label=stars"></a>
|
||||
<a href="https://github.com/AppFlowy-IO/appflowy"><img src="https://img.shields.io/github/forks/AppFlowy-IO/appflowy.svg"></a>
|
||||
<a href="https://opensource.org/licenses/AGPL-3.0"><img src="https://img.shields.io/badge/license-AGPL-purple.svg" alt="License: AGPL"></a>
|
||||
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="http://www.appflowy.io"><b>Website</b></a> •
|
||||
<a href="https://discord.gg/9Q2xaN37tV"><b>Discord</b></a> •
|
||||
<a href="https://twitter.com/appflowy"><b>Twitter</b></a> •
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="https://twitter.com/appflowy"><b>Twitter</b></a>
|
||||
</p>
|
||||
|
||||
<p align="center"><img src="https://github.com/AppFlowy-IO/appflowy/blob/main/doc/imgs/welcome.png" alt="The Open Source Notion Alternative." width="1000px" /></p>
|
||||
|
||||
<p align="center"><img src="https://github.com/AppFlowy-IO/appflowy/blob/main/doc/imgs/welcome.png" alt="The Open Source Alternative To Notion." width="1000px" /></p>
|
||||
|
||||
## User Installation
|
||||
Please view the [documentation](https://appflowy.gitbook.io/docs/essential-documentation/install-appflowy/installation-methods) for OS specific installation instructions.
|
||||
|
||||
## Built With
|
||||
|
||||
@@ -45,49 +38,8 @@ You are in charge of your data and customizations.
|
||||
|
||||
<p align="center"><img src="https://github.com/AppFlowy-IO/appflowy/blob/main/doc/imgs/howtostar.gif" alt="AppFlowy Github" width="1000px" /></p>
|
||||
|
||||
## Getting Started
|
||||
|
||||
How to build on MacOS, please follow these simple steps.
|
||||
|
||||
**Step 1:**
|
||||
|
||||
```shell
|
||||
git clone https://github.com/AppFlowy-IO/appflowy.git
|
||||
```
|
||||
|
||||
**Step 2:**
|
||||
|
||||
```shell
|
||||
cd appflowy
|
||||
```
|
||||
```shell
|
||||
make install_rust
|
||||
```
|
||||
```shell
|
||||
make install_cargo_make
|
||||
```
|
||||
```shell
|
||||
cargo make install_targets
|
||||
```
|
||||
|
||||
>
|
||||
>
|
||||
> 🚀 Skip install_rust or install_cargo_make if you already installed it.
|
||||
> FYI, AppFlowy uses [https://github.com/sagiegurari/cargo-make](https://github.com/sagiegurari/cargo-make) to construct the build scripts
|
||||
|
||||
**Step 3:**
|
||||
|
||||
Follow the instructions [here](https://flutter.dev/docs/get-started/install) to install Flutter. As AppFlowy uses the `dev` channel, you need to switch the channel. Just type:
|
||||
|
||||
```shell
|
||||
flutter channel dev
|
||||
```
|
||||
|
||||
**Step 4:**
|
||||
|
||||
* Open the `app_flowy` folder located at xx/appflowy/app_flowy with Visual Studio or other IDEs at your disposal.
|
||||
* Go to the Run and Debug tab and then click the run button.
|
||||

|
||||
## Getting Started with development
|
||||
Please view the [documentation](https://appflowy.gitbook.io/docs/essential-documentation/contribute-to-appflowy) for OS specific development instructions
|
||||
|
||||
## Roadmap
|
||||
|
||||
@@ -97,11 +49,11 @@ If you'd like to propose a feature, submit an issue [here](https://github.com/Ap
|
||||
|
||||
## **Releases**
|
||||
|
||||
Please see the [changelog](https://www.appflowy.io/whatsnew) for more details about a given release.
|
||||
Please see the [changelog](https://www.appflowy.io/whatsnew) for more details about a given release.
|
||||
|
||||
## Contributing
|
||||
|
||||
Contributions are what make the open source community such an amazing place to be learn, inspire, and create. Any contributions you make are **greatly appreciated**. Please look at [CONTRIBUTING.md](https://github.com/AppFlowy-IO/appflowy/blob/main/doc/CONTRIBUTING.md) for details.
|
||||
Contributions are what make the open source community such an amazing place to be learn, inspire, and create. Any contributions you make are **greatly appreciated**. Please look at [CONTRIBUTING.md](https://github.com/AppFlowy-IO/appflowy/blob/main/doc/CONTRIBUTING.md) for details.
|
||||
|
||||
## Why Are We Building This?
|
||||
|
||||
@@ -126,10 +78,11 @@ To be honest, we do not claim to outperform Notion in terms of functionality and
|
||||
|
||||
## License
|
||||
|
||||
Distributed under the AGPLv3 License. See `LICENSE.md` for more information.
|
||||
Distributed under the AGPLv3 License. See `LICENSE.md` for more information.
|
||||
|
||||
## Acknowledgements
|
||||
|
||||
Special thanks to these amazing projects which help power AppFlowy.IO:
|
||||
|
||||
- [flutter-quill](https://github.com/singerdmx/flutter-quill)
|
||||
- [cargo-make](https://github.com/sagiegurari/cargo-make)
|
||||
Vendored
-23
@@ -1,23 +0,0 @@
|
||||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
|
||||
{
|
||||
"name": "app_flowy",
|
||||
"request": "launch",
|
||||
"program": "${workspaceRoot}/lib/main.dart",
|
||||
"type": "dart",
|
||||
"preLaunchTask": "build_flowy_sdk",
|
||||
"cwd": "${workspaceRoot}"
|
||||
},
|
||||
{
|
||||
"name": "app_flowy (profile mode)",
|
||||
"request": "launch",
|
||||
"type": "dart",
|
||||
"flutterMode": "profile"
|
||||
},
|
||||
]
|
||||
}
|
||||
Vendored
-26
@@ -1,26 +0,0 @@
|
||||
{
|
||||
"version": "2.0.0",
|
||||
// https://code.visualstudio.com/docs/editor/tasks
|
||||
//https://gist.github.com/deadalusai/9e13e36d61ec7fb72148
|
||||
|
||||
// ${workspaceRoot}: the root folder of the team
|
||||
// ${file}: the current opened file
|
||||
// ${fileBasename}: the current opened file's basename
|
||||
// ${fileDirname}: the current opened file's dirname
|
||||
// ${fileExtname}: the current opened file's extension
|
||||
// ${cwd}: the current working directory of the spawned process
|
||||
"tasks": [
|
||||
{
|
||||
"type": "shell",
|
||||
"command": "sh ./scripts/build_sdk.sh",
|
||||
"group": "build",
|
||||
"options": {
|
||||
"cwd": "${workspaceFolder}/../"
|
||||
},
|
||||
// "problemMatcher": [
|
||||
// "$rustc"
|
||||
// ],
|
||||
"label": "build_flowy_sdk"
|
||||
},
|
||||
]
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
import 'package:app_flowy/startup/startup.dart';
|
||||
import 'package:flowy_infra/theme.dart';
|
||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:window_size/window_size.dart';
|
||||
import 'package:app_flowy/startup/launcher.dart';
|
||||
import 'package:bloc/bloc.dart';
|
||||
import 'package:flowy_log/flowy_log.dart';
|
||||
|
||||
class AppWidgetTask extends LaunchTask {
|
||||
@override
|
||||
LaunchTaskType get type => LaunchTaskType.appLauncher;
|
||||
|
||||
@override
|
||||
Future<void> initialize(LaunchContext context) {
|
||||
final widget = context.getIt<EntryPoint>().create();
|
||||
final app = ApplicationWidget(child: widget);
|
||||
Bloc.observer = ApplicationBlocObserver();
|
||||
runApp(app);
|
||||
|
||||
return Future(() => {});
|
||||
}
|
||||
}
|
||||
|
||||
class ApplicationWidget extends StatelessWidget {
|
||||
final Widget child;
|
||||
const ApplicationWidget({
|
||||
Key? key,
|
||||
required this.child,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
const ratio = 1.73;
|
||||
const minWidth = 800.0;
|
||||
setWindowMinSize(const Size(minWidth, minWidth / ratio));
|
||||
// const launchWidth = 1310.0;
|
||||
// setWindowFrame(const Rect.fromLTWH(0, 0, launchWidth, launchWidth / ratio));
|
||||
|
||||
final theme = AppTheme.fromType(ThemeType.light);
|
||||
return Provider.value(
|
||||
value: theme,
|
||||
child: MaterialApp(
|
||||
builder: overlayManagerBuilder(),
|
||||
debugShowCheckedModeBanner: false,
|
||||
theme: theme.themeData,
|
||||
navigatorKey: AppGlobals.rootNavKey,
|
||||
home: child,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class AppGlobals {
|
||||
static GlobalKey<NavigatorState> rootNavKey = GlobalKey();
|
||||
static NavigatorState get nav => rootNavKey.currentState!;
|
||||
}
|
||||
|
||||
class ApplicationBlocObserver extends BlocObserver {
|
||||
@override
|
||||
// ignore: unnecessary_overrides
|
||||
void onTransition(Bloc bloc, Transition transition) {
|
||||
// Log.debug("[current]: ${transition.currentState} \n\n[next]: ${transition.nextState}");
|
||||
//Log.debug("${transition.nextState}");
|
||||
super.onTransition(bloc, transition);
|
||||
}
|
||||
|
||||
@override
|
||||
void onError(BlocBase bloc, Object error, StackTrace stackTrace) {
|
||||
Log.debug(error);
|
||||
super.onError(bloc, error, stackTrace);
|
||||
}
|
||||
|
||||
@override
|
||||
void onEvent(Bloc bloc, Object? event) {
|
||||
Log.debug("$event");
|
||||
super.onEvent(bloc, event);
|
||||
}
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
export 'application_task.dart';
|
||||
export 'sdk_task.dart';
|
||||
@@ -1,26 +0,0 @@
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-user/protobuf.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace-infra/protobuf.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class NewUser {
|
||||
UserProfile profile;
|
||||
String workspaceId;
|
||||
NewUser({
|
||||
required this.profile,
|
||||
required this.workspaceId,
|
||||
});
|
||||
}
|
||||
|
||||
abstract class IAuth {
|
||||
Future<Either<UserProfile, UserError>> signIn(String? email, String? password);
|
||||
Future<Either<UserProfile, UserError>> signUp(String? name, String? password, String? email);
|
||||
Future<Either<Unit, UserError>> signOut();
|
||||
}
|
||||
|
||||
abstract class IAuthRouter {
|
||||
void pushWelcomeScreen(BuildContext context, UserProfile userProfile);
|
||||
void pushSignUpScreen(BuildContext context);
|
||||
void pushForgetPasswordScreen(BuildContext context);
|
||||
void pushHomeScreen(BuildContext context, UserProfile profile, CurrentWorkspaceSetting workspaceSetting);
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
import 'package:flowy_sdk/protobuf/flowy-user/protobuf.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace-infra/protobuf.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
import 'auth_state.dart';
|
||||
|
||||
abstract class ISplashUser {
|
||||
Future<AuthState> currentUserProfile();
|
||||
}
|
||||
|
||||
abstract class ISplashUserWatch {
|
||||
void startWatching({
|
||||
void Function(AuthState)? authStateCallback,
|
||||
});
|
||||
|
||||
Future<void> stopWatching();
|
||||
}
|
||||
|
||||
abstract class ISplashRoute {
|
||||
void pushSignInScreen(BuildContext context);
|
||||
void pushSkipLoginScreen(BuildContext context);
|
||||
|
||||
Future<void> pushWelcomeScreen(BuildContext context, UserProfile profile);
|
||||
void pushHomeScreen(BuildContext context, UserProfile profile, CurrentWorkspaceSetting workspaceSetting);
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
import 'package:app_flowy/user/application/sign_in_bloc.dart';
|
||||
import 'package:app_flowy/user/application/sign_up_bloc.dart';
|
||||
import 'package:app_flowy/user/application/splash_bloc.dart';
|
||||
import 'package:app_flowy/user/domain/i_auth.dart';
|
||||
import 'package:app_flowy/user/domain/i_splash.dart';
|
||||
import 'package:app_flowy/user/infrastructure/repos/auth_repo.dart';
|
||||
import 'package:app_flowy/user/infrastructure/i_auth_impl.dart';
|
||||
import 'package:app_flowy/user/infrastructure/i_splash_impl.dart';
|
||||
import 'package:app_flowy/workspace/application/edit_pannel/edit_pannel_bloc.dart';
|
||||
import 'package:app_flowy/workspace/application/home/home_bloc.dart';
|
||||
import 'package:app_flowy/workspace/application/home/home_listen_bloc.dart';
|
||||
import 'package:app_flowy/workspace/domain/i_user.dart';
|
||||
import 'package:app_flowy/workspace/infrastructure/i_user_impl.dart';
|
||||
import 'package:get_it/get_it.dart';
|
||||
|
||||
class UserDepsResolver {
|
||||
static Future<void> resolve(GetIt getIt) async {
|
||||
getIt.registerFactory<AuthRepository>(() => AuthRepository());
|
||||
|
||||
//Interface implementation
|
||||
getIt.registerFactory<IAuth>(() => AuthImpl(repo: getIt<AuthRepository>()));
|
||||
getIt.registerFactory<IAuthRouter>(() => AuthRouterImpl());
|
||||
|
||||
//Bloc
|
||||
getIt.registerFactory<SignInBloc>(() => SignInBloc(getIt<IAuth>()));
|
||||
getIt.registerFactory<SignUpBloc>(() => SignUpBloc(getIt<IAuth>()));
|
||||
|
||||
getIt.registerFactory<ISplashUser>(() => SplashUserImpl());
|
||||
getIt.registerFactory<ISplashRoute>(() => SplashRoute());
|
||||
getIt.registerFactory<HomeBloc>(() => HomeBloc());
|
||||
getIt.registerFactory<EditPannelBloc>(() => EditPannelBloc());
|
||||
getIt.registerFactory<SplashBloc>(() => SplashBloc(getIt<ISplashUser>()));
|
||||
|
||||
getIt.registerFactoryParam<HomeListenBloc, UserProfile, void>(
|
||||
(user, _) => HomeListenBloc(
|
||||
getIt<IUserListener>(param1: user),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
import 'package:app_flowy/startup/startup.dart';
|
||||
import 'package:app_flowy/user/domain/i_splash.dart';
|
||||
import 'package:app_flowy/user/presentation/sign_up_screen.dart';
|
||||
import 'package:app_flowy/workspace/presentation/home/home_screen.dart';
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:flowy_infra/time/duration.dart';
|
||||
import 'package:flowy_infra_ui/widget/route/animation.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-user/protobuf.dart';
|
||||
import 'package:app_flowy/user/domain/i_auth.dart';
|
||||
import 'package:app_flowy/user/infrastructure/repos/auth_repo.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace-infra/protobuf.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class AuthImpl extends IAuth {
|
||||
AuthRepository repo;
|
||||
AuthImpl({
|
||||
required this.repo,
|
||||
});
|
||||
|
||||
@override
|
||||
Future<Either<UserProfile, UserError>> signIn(String? email, String? password) {
|
||||
return repo.signIn(email: email, password: password);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Either<UserProfile, UserError>> signUp(String? name, String? password, String? email) {
|
||||
return repo.signUp(name: name, password: password, email: email);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Either<Unit, UserError>> signOut() {
|
||||
return repo.signOut();
|
||||
}
|
||||
}
|
||||
|
||||
class AuthRouterImpl extends IAuthRouter {
|
||||
@override
|
||||
void pushForgetPasswordScreen(BuildContext context) {
|
||||
// TODO: implement showForgetPasswordScreen
|
||||
}
|
||||
|
||||
@override
|
||||
void pushWelcomeScreen(BuildContext context, UserProfile userProfile) {
|
||||
getIt<ISplashRoute>().pushWelcomeScreen(context, userProfile);
|
||||
}
|
||||
|
||||
@override
|
||||
void pushSignUpScreen(BuildContext context) {
|
||||
Navigator.of(context).push(
|
||||
PageRoutes.fade(
|
||||
() => SignUpScreen(router: getIt<IAuthRouter>()),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void pushHomeScreen(BuildContext context, UserProfile profile, CurrentWorkspaceSetting workspaceSetting) {
|
||||
Navigator.push(
|
||||
context,
|
||||
PageRoutes.fade(() => HomeScreen(profile, workspaceSetting), RouteDurations.slow.inMilliseconds * .001),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,125 +0,0 @@
|
||||
import 'package:app_flowy/workspace/domain/i_app.dart';
|
||||
import 'package:flowy_log/flowy_log.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace-infra/app_create.pb.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace-infra/view_create.pb.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:dartz/dartz.dart';
|
||||
|
||||
part 'app_bloc.freezed.dart';
|
||||
|
||||
class AppBloc extends Bloc<AppEvent, AppState> {
|
||||
final IApp appManager;
|
||||
final IAppListenr listener;
|
||||
AppBloc({required App app, required this.appManager, required this.listener}) : super(AppState.initial(app));
|
||||
|
||||
@override
|
||||
Stream<AppState> mapEventToState(
|
||||
AppEvent event,
|
||||
) async* {
|
||||
yield* event.map(initial: (e) async* {
|
||||
listener.start(
|
||||
viewsChangeCallback: _handleViewsChanged,
|
||||
updatedCallback: (app) => add(AppEvent.appDidUpdate(app)),
|
||||
);
|
||||
yield* _fetchViews();
|
||||
}, createView: (CreateView value) async* {
|
||||
final viewOrFailed = await appManager.createView(name: value.name, desc: value.desc, viewType: value.viewType);
|
||||
yield viewOrFailed.fold(
|
||||
(view) => state.copyWith(
|
||||
latestCreatedView: view,
|
||||
successOrFailure: left(unit),
|
||||
),
|
||||
(error) {
|
||||
Log.error(error);
|
||||
return state.copyWith(successOrFailure: right(error));
|
||||
},
|
||||
);
|
||||
}, didReceiveViews: (e) async* {
|
||||
yield* handleDidReceiveViews(e.views);
|
||||
}, delete: (e) async* {
|
||||
final result = await appManager.delete();
|
||||
yield result.fold(
|
||||
(unit) => state.copyWith(successOrFailure: left(unit)),
|
||||
(error) => state.copyWith(successOrFailure: right(error)),
|
||||
);
|
||||
}, rename: (e) async* {
|
||||
final result = await appManager.rename(e.newName);
|
||||
yield result.fold(
|
||||
(l) => state.copyWith(successOrFailure: left(unit)),
|
||||
(error) => state.copyWith(successOrFailure: right(error)),
|
||||
);
|
||||
}, appDidUpdate: (e) async* {
|
||||
yield state.copyWith(app: e.app);
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> close() async {
|
||||
await listener.stop();
|
||||
return super.close();
|
||||
}
|
||||
|
||||
void _handleViewsChanged(Either<List<View>, WorkspaceError> result) {
|
||||
result.fold(
|
||||
(views) => add(AppEvent.didReceiveViews(views)),
|
||||
(error) {
|
||||
Log.error(error);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Stream<AppState> handleDidReceiveViews(List<View> views) async* {
|
||||
final latestCreatedView = state.latestCreatedView;
|
||||
AppState newState = state.copyWith(views: views);
|
||||
if (latestCreatedView != null) {
|
||||
final index = views.indexWhere((element) => element.id == latestCreatedView.id);
|
||||
if (index == -1) {
|
||||
newState = newState.copyWith(latestCreatedView: null);
|
||||
}
|
||||
}
|
||||
|
||||
yield newState;
|
||||
}
|
||||
|
||||
Stream<AppState> _fetchViews() async* {
|
||||
final viewsOrFailed = await appManager.getViews();
|
||||
yield viewsOrFailed.fold(
|
||||
(apps) => state.copyWith(views: apps),
|
||||
(error) {
|
||||
Log.error(error);
|
||||
return state.copyWith(successOrFailure: right(error));
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@freezed
|
||||
class AppEvent with _$AppEvent {
|
||||
const factory AppEvent.initial() = Initial;
|
||||
const factory AppEvent.createView(String name, String desc, ViewType viewType) = CreateView;
|
||||
const factory AppEvent.delete() = Delete;
|
||||
const factory AppEvent.rename(String newName) = Rename;
|
||||
const factory AppEvent.didReceiveViews(List<View> views) = ReceiveViews;
|
||||
const factory AppEvent.appDidUpdate(App app) = AppDidUpdate;
|
||||
}
|
||||
|
||||
@freezed
|
||||
class AppState with _$AppState {
|
||||
const factory AppState({
|
||||
required App app,
|
||||
required bool isLoading,
|
||||
required List<View>? views,
|
||||
View? latestCreatedView,
|
||||
required Either<Unit, WorkspaceError> successOrFailure,
|
||||
}) = _AppState;
|
||||
|
||||
factory AppState.initial(App app) => AppState(
|
||||
app: app,
|
||||
isLoading: false,
|
||||
views: null,
|
||||
latestCreatedView: null,
|
||||
successOrFailure: left(unit),
|
||||
);
|
||||
}
|
||||
@@ -1,113 +0,0 @@
|
||||
import 'dart:async';
|
||||
import 'package:app_flowy/workspace/domain/i_workspace.dart';
|
||||
import 'package:app_flowy/workspace/domain/page_stack/page_stack.dart';
|
||||
import 'package:app_flowy/workspace/presentation/stack_page/blank/blank_page.dart';
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:flowy_log/flowy_log.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace-infra/app_create.pb.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
part 'menu_bloc.freezed.dart';
|
||||
|
||||
class MenuBloc extends Bloc<MenuEvent, MenuState> {
|
||||
final IWorkspace workspaceManager;
|
||||
final IWorkspaceListener listener;
|
||||
MenuBloc({required this.workspaceManager, required this.listener}) : super(MenuState.initial());
|
||||
|
||||
@override
|
||||
Stream<MenuState> mapEventToState(
|
||||
MenuEvent event,
|
||||
) async* {
|
||||
yield* event.map(
|
||||
initial: (e) async* {
|
||||
listener.start(addAppCallback: _handleAppsOrFail);
|
||||
yield* _fetchApps();
|
||||
},
|
||||
collapse: (e) async* {
|
||||
final isCollapse = state.isCollapse;
|
||||
yield state.copyWith(isCollapse: !isCollapse);
|
||||
},
|
||||
openPage: (e) async* {
|
||||
yield* _performActionOnOpenPage(e);
|
||||
},
|
||||
createApp: (CreateApp event) async* {
|
||||
yield* _performActionOnCreateApp(event);
|
||||
},
|
||||
didReceiveApps: (e) async* {
|
||||
yield e.appsOrFail.fold(
|
||||
(apps) => state.copyWith(apps: some(apps), successOrFailure: left(unit)),
|
||||
(err) => state.copyWith(successOrFailure: right(err)),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> close() async {
|
||||
await listener.stop();
|
||||
return super.close();
|
||||
}
|
||||
|
||||
Stream<MenuState> _performActionOnOpenPage(OpenPage e) async* {
|
||||
yield state.copyWith(stackContext: e.context);
|
||||
}
|
||||
|
||||
Stream<MenuState> _performActionOnCreateApp(CreateApp event) async* {
|
||||
final result = await workspaceManager.createApp(name: event.name, desc: event.desc);
|
||||
yield result.fold(
|
||||
(app) => state.copyWith(apps: some([app])),
|
||||
(error) {
|
||||
Log.error(error);
|
||||
return state.copyWith(successOrFailure: right(error));
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
// ignore: unused_element
|
||||
Stream<MenuState> _fetchApps() async* {
|
||||
final appsOrFail = await workspaceManager.getApps();
|
||||
yield appsOrFail.fold(
|
||||
(apps) => state.copyWith(apps: some(apps)),
|
||||
(error) {
|
||||
Log.error(error);
|
||||
return state.copyWith(successOrFailure: right(error));
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void _handleAppsOrFail(Either<List<App>, WorkspaceError> appsOrFail) {
|
||||
appsOrFail.fold(
|
||||
(apps) => add(MenuEvent.didReceiveApps(left(apps))),
|
||||
(error) => add(MenuEvent.didReceiveApps(right(error))),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@freezed
|
||||
class MenuEvent with _$MenuEvent {
|
||||
const factory MenuEvent.initial() = _Initial;
|
||||
const factory MenuEvent.collapse() = Collapse;
|
||||
const factory MenuEvent.openPage(HomeStackContext context) = OpenPage;
|
||||
const factory MenuEvent.createApp(String name, {String? desc}) = CreateApp;
|
||||
const factory MenuEvent.didReceiveApps(Either<List<App>, WorkspaceError> appsOrFail) = ReceiveApps;
|
||||
}
|
||||
|
||||
@freezed
|
||||
class MenuState with _$MenuState {
|
||||
const factory MenuState({
|
||||
required bool isCollapse,
|
||||
required Option<List<App>> apps,
|
||||
required Either<Unit, WorkspaceError> successOrFailure,
|
||||
required HomeStackContext stackContext,
|
||||
}) = _MenuState;
|
||||
|
||||
factory MenuState.initial() => MenuState(
|
||||
isCollapse: false,
|
||||
apps: none(),
|
||||
successOrFailure: left(unit),
|
||||
stackContext: BlankStackContext(),
|
||||
);
|
||||
}
|
||||
@@ -1,94 +0,0 @@
|
||||
import 'package:app_flowy/workspace/domain/i_trash.dart';
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:flowy_log/flowy_log.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace-infra/trash_create.pb.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
part 'trash_bloc.freezed.dart';
|
||||
|
||||
class TrashBloc extends Bloc<TrashEvent, TrashState> {
|
||||
final ITrash trasnManager;
|
||||
final ITrashListener listener;
|
||||
TrashBloc({required this.trasnManager, required this.listener}) : super(TrashState.init());
|
||||
|
||||
@override
|
||||
Stream<TrashState> mapEventToState(TrashEvent event) async* {
|
||||
yield* event.map(
|
||||
initial: (e) async* {
|
||||
listener.start(_listenTrashUpdated);
|
||||
final result = await trasnManager.readTrash();
|
||||
yield result.fold(
|
||||
(objects) => state.copyWith(objects: objects, successOrFailure: left(unit)),
|
||||
(error) => state.copyWith(successOrFailure: right(error)),
|
||||
);
|
||||
},
|
||||
didReceiveTrash: (e) async* {
|
||||
yield state.copyWith(objects: e.trash);
|
||||
},
|
||||
putback: (e) async* {
|
||||
final result = await trasnManager.putback(e.trashId);
|
||||
yield* _handleResult(result);
|
||||
},
|
||||
delete: (e) async* {
|
||||
final result = await trasnManager.deleteViews([Tuple2(e.trash.id, e.trash.ty)]);
|
||||
yield* _handleResult(result);
|
||||
},
|
||||
deleteAll: (e) async* {
|
||||
final result = await trasnManager.deleteAll();
|
||||
yield* _handleResult(result);
|
||||
},
|
||||
restoreAll: (e) async* {
|
||||
final result = await trasnManager.restoreAll();
|
||||
yield* _handleResult(result);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Stream<TrashState> _handleResult(Either<dynamic, WorkspaceError> result) async* {
|
||||
yield result.fold(
|
||||
(l) => state.copyWith(successOrFailure: left(unit)),
|
||||
(error) => state.copyWith(successOrFailure: right(error)),
|
||||
);
|
||||
}
|
||||
|
||||
void _listenTrashUpdated(Either<List<Trash>, WorkspaceError> trashOrFailed) {
|
||||
trashOrFailed.fold(
|
||||
(trash) {
|
||||
add(TrashEvent.didReceiveTrash(trash));
|
||||
},
|
||||
(error) {
|
||||
Log.error(error);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> close() async {
|
||||
await listener.stop();
|
||||
return super.close();
|
||||
}
|
||||
}
|
||||
|
||||
@freezed
|
||||
class TrashEvent with _$TrashEvent {
|
||||
const factory TrashEvent.initial() = Initial;
|
||||
const factory TrashEvent.didReceiveTrash(List<Trash> trash) = ReceiveTrash;
|
||||
const factory TrashEvent.putback(String trashId) = Putback;
|
||||
const factory TrashEvent.delete(Trash trash) = Delete;
|
||||
const factory TrashEvent.restoreAll() = RestoreAll;
|
||||
const factory TrashEvent.deleteAll() = DeleteAll;
|
||||
}
|
||||
|
||||
@freezed
|
||||
class TrashState with _$TrashState {
|
||||
const factory TrashState({
|
||||
required List<Trash> objects,
|
||||
required Either<Unit, WorkspaceError> successOrFailure,
|
||||
}) = _TrashState;
|
||||
|
||||
factory TrashState.init() => TrashState(
|
||||
objects: [],
|
||||
successOrFailure: left(unit),
|
||||
);
|
||||
}
|
||||
@@ -1,96 +0,0 @@
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace-infra/view_create.pb.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
import 'package:app_flowy/workspace/domain/i_view.dart';
|
||||
|
||||
part 'view_bloc.freezed.dart';
|
||||
|
||||
class ViewBloc extends Bloc<ViewEvent, ViewState> {
|
||||
final IView viewManager;
|
||||
final IViewListener listener;
|
||||
|
||||
ViewBloc({
|
||||
required this.viewManager,
|
||||
required this.listener,
|
||||
}) : super(ViewState.init(viewManager.view));
|
||||
|
||||
@override
|
||||
Stream<ViewState> mapEventToState(ViewEvent event) async* {
|
||||
yield* event.map(
|
||||
initial: (e) async* {
|
||||
listener.updatedNotifier.addPublishListener((result) {
|
||||
add(ViewEvent.viewDidUpdate(result));
|
||||
});
|
||||
listener.start();
|
||||
yield state;
|
||||
},
|
||||
setIsEditing: (e) async* {
|
||||
yield state.copyWith(isEditing: e.isEditing);
|
||||
},
|
||||
viewDidUpdate: (e) async* {
|
||||
yield* _handleViewDidUpdate(e.result);
|
||||
},
|
||||
rename: (e) async* {
|
||||
final result = await viewManager.rename(e.newName);
|
||||
yield result.fold(
|
||||
(l) => state.copyWith(successOrFailure: left(unit)),
|
||||
(error) => state.copyWith(successOrFailure: right(error)),
|
||||
);
|
||||
},
|
||||
delete: (e) async* {
|
||||
final result = await viewManager.delete();
|
||||
yield result.fold(
|
||||
(l) => state.copyWith(successOrFailure: left(unit)),
|
||||
(error) => state.copyWith(successOrFailure: right(error)),
|
||||
);
|
||||
},
|
||||
duplicate: (e) async* {
|
||||
final result = await viewManager.duplicate();
|
||||
yield result.fold(
|
||||
(l) => state.copyWith(successOrFailure: left(unit)),
|
||||
(error) => state.copyWith(successOrFailure: right(error)),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Stream<ViewState> _handleViewDidUpdate(Either<View, WorkspaceError> result) async* {
|
||||
yield result.fold(
|
||||
(view) => state.copyWith(view: view, successOrFailure: left(unit)),
|
||||
(error) => state.copyWith(successOrFailure: right(error)),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> close() async {
|
||||
await listener.stop();
|
||||
return super.close();
|
||||
}
|
||||
}
|
||||
|
||||
@freezed
|
||||
class ViewEvent with _$ViewEvent {
|
||||
const factory ViewEvent.initial() = Initial;
|
||||
const factory ViewEvent.setIsEditing(bool isEditing) = SetEditing;
|
||||
const factory ViewEvent.rename(String newName) = Rename;
|
||||
const factory ViewEvent.delete() = Delete;
|
||||
const factory ViewEvent.duplicate() = Duplicate;
|
||||
const factory ViewEvent.viewDidUpdate(Either<View, WorkspaceError> result) = ViewDidUpdate;
|
||||
}
|
||||
|
||||
@freezed
|
||||
class ViewState with _$ViewState {
|
||||
const factory ViewState({
|
||||
required View view,
|
||||
required bool isEditing,
|
||||
required Either<Unit, WorkspaceError> successOrFailure,
|
||||
}) = _ViewState;
|
||||
|
||||
factory ViewState.init(View view) => ViewState(
|
||||
view: view,
|
||||
isEditing: false,
|
||||
successOrFailure: left(unit),
|
||||
);
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace-infra/app_create.pb.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace-infra/view_create.pb.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace-infra/protobuf.dart';
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart';
|
||||
|
||||
typedef AppUpdatedCallback = void Function(App app);
|
||||
typedef AppViewsChangeCallback = void Function(Either<List<View>, WorkspaceError> viewsOrFailed);
|
||||
|
||||
abstract class IApp {
|
||||
Future<Either<List<View>, WorkspaceError>> getViews();
|
||||
|
||||
Future<Either<View, WorkspaceError>> createView({required String name, String? desc, required ViewType viewType});
|
||||
|
||||
Future<Either<Unit, WorkspaceError>> delete();
|
||||
|
||||
Future<Either<Unit, WorkspaceError>> rename(String newName);
|
||||
}
|
||||
|
||||
abstract class IAppListenr {
|
||||
void start({AppViewsChangeCallback? viewsChangeCallback, AppUpdatedCallback? updatedCallback});
|
||||
|
||||
Future<void> stop();
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
import 'dart:async';
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-document-infra/doc.pb.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart';
|
||||
|
||||
abstract class IDoc {
|
||||
Future<Either<DocDelta, WorkspaceError>> readDoc();
|
||||
Future<Either<DocDelta, WorkspaceError>> composeDelta({required String json});
|
||||
Future<Either<Unit, WorkspaceError>> closeDoc();
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
import 'dart:async';
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace-infra/protobuf.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart';
|
||||
|
||||
abstract class IShare {
|
||||
Future<Either<ExportData, WorkspaceError>> exportText(String docId);
|
||||
|
||||
Future<Either<ExportData, WorkspaceError>> exportMarkdown(String docId);
|
||||
|
||||
Future<Either<ExportData, WorkspaceError>> exportURL(String docId);
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
import 'dart:async';
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace-infra/trash_create.pb.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart';
|
||||
|
||||
abstract class ITrash {
|
||||
Future<Either<List<Trash>, WorkspaceError>> readTrash();
|
||||
|
||||
Future<Either<Unit, WorkspaceError>> putback(String trashId);
|
||||
|
||||
Future<Either<Unit, WorkspaceError>> deleteViews(List<Tuple2<String, TrashType>> trashList);
|
||||
|
||||
Future<Either<Unit, WorkspaceError>> restoreAll();
|
||||
|
||||
Future<Either<Unit, WorkspaceError>> deleteAll();
|
||||
}
|
||||
|
||||
typedef TrashUpdatedCallback = void Function(Either<List<Trash>, WorkspaceError> trashOrFailed);
|
||||
|
||||
abstract class ITrashListener {
|
||||
void start(TrashUpdatedCallback updateCallback);
|
||||
Future<void> stop();
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:flowy_infra/notifier.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-user/errors.pb.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-user/user_profile.pb.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace-infra/workspace_create.pb.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart';
|
||||
export 'package:flowy_sdk/protobuf/flowy-user/errors.pb.dart';
|
||||
export 'package:flowy_sdk/protobuf/flowy-user/user_profile.pb.dart';
|
||||
|
||||
abstract class IUser {
|
||||
UserProfile get user;
|
||||
Future<Either<UserProfile, UserError>> fetchUserProfile(String userId);
|
||||
Future<Either<List<Workspace>, WorkspaceError>> fetchWorkspaces();
|
||||
Future<Either<Unit, WorkspaceError>> deleteWorkspace(String workspaceId);
|
||||
Future<Either<Unit, UserError>> signOut();
|
||||
Future<Either<Unit, UserError>> initUser();
|
||||
}
|
||||
|
||||
typedef UserProfileUpdatedNotifierValue = Either<UserProfile, UserError>;
|
||||
typedef AuthNotifierValue = Either<Unit, UserError>;
|
||||
typedef WorkspaceUpdatedNotifierValue = Either<List<Workspace>, WorkspaceError>;
|
||||
|
||||
abstract class IUserListener {
|
||||
void start();
|
||||
|
||||
PublishNotifier<UserProfileUpdatedNotifierValue> get profileUpdatedNotifier;
|
||||
PublishNotifier<AuthNotifierValue> get authDidChangedNotifier;
|
||||
PublishNotifier<WorkspaceUpdatedNotifierValue> get workspaceUpdatedNotifier;
|
||||
|
||||
Future<void> stop();
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace-infra/view_create.pb.dart';
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:flowy_infra/notifier.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart';
|
||||
|
||||
typedef ViewUpdatedCallback = void Function(Either<View, WorkspaceError>);
|
||||
|
||||
typedef DeleteNotifierValue = Either<View, WorkspaceError>;
|
||||
typedef UpdateNotifierValue = Either<View, WorkspaceError>;
|
||||
typedef RestoreNotifierValue = Either<View, WorkspaceError>;
|
||||
|
||||
abstract class IView {
|
||||
View get view;
|
||||
|
||||
Future<Either<Unit, WorkspaceError>> delete();
|
||||
|
||||
Future<Either<View, WorkspaceError>> rename(String newName);
|
||||
|
||||
Future<Either<Unit, WorkspaceError>> duplicate();
|
||||
}
|
||||
|
||||
abstract class IViewListener {
|
||||
void start();
|
||||
|
||||
PublishNotifier<UpdateNotifierValue> get updatedNotifier;
|
||||
|
||||
PublishNotifier<DeleteNotifierValue> get deletedNotifier;
|
||||
|
||||
PublishNotifier<RestoreNotifierValue> get restoredNotifier;
|
||||
|
||||
Future<void> stop();
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace-infra/protobuf.dart';
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart';
|
||||
|
||||
typedef WorkspaceAppsChangedCallback = void Function(Either<List<App>, WorkspaceError> appsOrFail);
|
||||
|
||||
typedef WorkspaceUpdatedCallback = void Function(String name, String desc);
|
||||
|
||||
abstract class IWorkspace {
|
||||
Future<Either<App, WorkspaceError>> createApp({required String name, String? desc});
|
||||
|
||||
Future<Either<List<App>, WorkspaceError>> getApps();
|
||||
}
|
||||
|
||||
abstract class IWorkspaceListener {
|
||||
void start({WorkspaceAppsChangedCallback? addAppCallback, WorkspaceUpdatedCallback? updatedCallback});
|
||||
|
||||
Future<void> stop();
|
||||
}
|
||||
@@ -1,116 +0,0 @@
|
||||
import 'package:app_flowy/workspace/application/app/app_bloc.dart';
|
||||
import 'package:app_flowy/workspace/application/doc/doc_bloc.dart';
|
||||
import 'package:app_flowy/workspace/application/doc/share_bloc.dart';
|
||||
import 'package:app_flowy/workspace/application/menu/menu_bloc.dart';
|
||||
import 'package:app_flowy/workspace/application/menu/menu_user_bloc.dart';
|
||||
import 'package:app_flowy/workspace/application/trash/trash_bloc.dart';
|
||||
import 'package:app_flowy/workspace/application/view/view_bloc.dart';
|
||||
import 'package:app_flowy/workspace/application/workspace/welcome_bloc.dart';
|
||||
import 'package:app_flowy/workspace/domain/i_doc.dart';
|
||||
import 'package:app_flowy/workspace/domain/i_share.dart';
|
||||
import 'package:app_flowy/workspace/domain/i_trash.dart';
|
||||
import 'package:app_flowy/workspace/domain/i_view.dart';
|
||||
import 'package:app_flowy/workspace/domain/page_stack/page_stack.dart';
|
||||
import 'package:app_flowy/workspace/infrastructure/i_app_impl.dart';
|
||||
import 'package:app_flowy/workspace/infrastructure/i_doc_impl.dart';
|
||||
import 'package:app_flowy/workspace/infrastructure/i_trash_impl.dart';
|
||||
import 'package:app_flowy/workspace/infrastructure/i_workspace_impl.dart';
|
||||
import 'package:app_flowy/workspace/infrastructure/repos/app_repo.dart';
|
||||
import 'package:app_flowy/workspace/infrastructure/repos/doc_repo.dart';
|
||||
import 'package:app_flowy/workspace/infrastructure/repos/trash_repo.dart';
|
||||
import 'package:app_flowy/workspace/infrastructure/repos/view_repo.dart';
|
||||
import 'package:app_flowy/workspace/infrastructure/repos/workspace_repo.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-user/user_profile.pb.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace-infra/app_create.pb.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace-infra/view_create.pb.dart';
|
||||
import 'package:get_it/get_it.dart';
|
||||
|
||||
import 'i_share_impl.dart';
|
||||
import 'i_user_impl.dart';
|
||||
import 'i_view_impl.dart';
|
||||
import 'repos/share_repo.dart';
|
||||
|
||||
class HomeDepsResolver {
|
||||
static Future<void> resolve(GetIt getIt) async {
|
||||
//
|
||||
getIt.registerLazySingleton<HomeStackManager>(() => HomeStackManager());
|
||||
getIt.registerFactoryParam<WelcomeBloc, UserProfile, void>(
|
||||
(user, _) => WelcomeBloc(
|
||||
repo: UserRepo(user: user),
|
||||
listener: getIt<IUserListener>(param1: user),
|
||||
),
|
||||
);
|
||||
|
||||
//App
|
||||
getIt.registerFactoryParam<IApp, String, void>((appId, _) => IAppImpl(repo: AppRepository(appId: appId)));
|
||||
getIt.registerFactoryParam<IAppListenr, String, void>(
|
||||
(appId, _) => IAppListenerhImpl(repo: AppListenerRepository(appId: appId)));
|
||||
|
||||
//workspace
|
||||
getIt.registerFactoryParam<IWorkspace, UserProfile, String>(
|
||||
(user, workspaceId) => IWorkspaceImpl(repo: WorkspaceRepo(user: user, workspaceId: workspaceId)));
|
||||
getIt.registerFactoryParam<IWorkspaceListener, UserProfile, String>((user, workspaceId) =>
|
||||
IWorkspaceListenerImpl(repo: WorkspaceListenerRepo(user: user, workspaceId: workspaceId)));
|
||||
|
||||
// View
|
||||
getIt.registerFactoryParam<IView, View, void>((view, _) => IViewImpl(repo: ViewRepository(view: view)));
|
||||
getIt.registerFactoryParam<IViewListener, View, void>(
|
||||
(view, _) => IViewListenerImpl(repo: ViewListenerRepository(view: view)));
|
||||
getIt.registerFactoryParam<ViewBloc, View, void>(
|
||||
(view, _) => ViewBloc(
|
||||
viewManager: getIt<IView>(param1: view),
|
||||
listener: getIt<IViewListener>(param1: view),
|
||||
),
|
||||
);
|
||||
|
||||
// Doc
|
||||
getIt.registerFactoryParam<IDoc, String, void>((docId, _) => IDocImpl(repo: DocRepository(docId: docId)));
|
||||
|
||||
// User
|
||||
getIt.registerFactoryParam<IUser, UserProfile, void>((user, _) => IUserImpl(repo: UserRepo(user: user)));
|
||||
getIt.registerFactoryParam<IUserListener, UserProfile, void>((user, _) => IUserListenerImpl(user: user));
|
||||
|
||||
//Menu Bloc
|
||||
getIt.registerFactoryParam<MenuBloc, UserProfile, String>(
|
||||
(user, workspaceId) => MenuBloc(
|
||||
workspaceManager: getIt<IWorkspace>(param1: user, param2: workspaceId),
|
||||
listener: getIt<IWorkspaceListener>(param1: user, param2: workspaceId),
|
||||
),
|
||||
);
|
||||
|
||||
getIt.registerFactoryParam<MenuUserBloc, UserProfile, void>(
|
||||
(user, _) => MenuUserBloc(getIt<IUser>(param1: user), getIt<IUserListener>(param1: user)));
|
||||
|
||||
// App
|
||||
getIt.registerFactoryParam<AppBloc, App, void>(
|
||||
(app, _) => AppBloc(
|
||||
app: app,
|
||||
appManager: getIt<IApp>(param1: app.id),
|
||||
listener: getIt<IAppListenr>(param1: app.id),
|
||||
),
|
||||
);
|
||||
|
||||
// Doc
|
||||
getIt.registerFactoryParam<DocBloc, View, void>(
|
||||
(view, _) => DocBloc(
|
||||
view: view,
|
||||
docManager: getIt<IDoc>(param1: view.id),
|
||||
listener: getIt<IViewListener>(param1: view),
|
||||
trasnManager: getIt<ITrash>(),
|
||||
),
|
||||
);
|
||||
|
||||
// trash
|
||||
getIt.registerLazySingleton<TrashRepo>(() => TrashRepo());
|
||||
getIt.registerLazySingleton<TrashListenerRepo>(() => TrashListenerRepo());
|
||||
getIt.registerFactory<ITrash>(() => ITrashImpl(repo: getIt<TrashRepo>()));
|
||||
getIt.registerFactory<ITrashListener>(() => ITrashListenerImpl(repo: getIt<TrashListenerRepo>()));
|
||||
getIt.registerFactory<TrashBloc>(() => TrashBloc(trasnManager: getIt<ITrash>(), listener: getIt<ITrashListener>()));
|
||||
|
||||
// share
|
||||
getIt.registerLazySingleton<ShareRepo>(() => ShareRepo());
|
||||
getIt.registerFactory<IShare>(() => IShareImpl(repo: getIt<ShareRepo>()));
|
||||
getIt.registerFactoryParam<DocShareBloc, View, void>(
|
||||
(view, _) => DocShareBloc(view: view, shareManager: getIt<IShare>()));
|
||||
}
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
import 'package:app_flowy/workspace/infrastructure/repos/app_repo.dart';
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:app_flowy/workspace/domain/i_app.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace-infra/view_create.pb.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart';
|
||||
export 'package:app_flowy/workspace/domain/i_app.dart';
|
||||
|
||||
class IAppImpl extends IApp {
|
||||
AppRepository repo;
|
||||
IAppImpl({
|
||||
required this.repo,
|
||||
});
|
||||
|
||||
@override
|
||||
Future<Either<List<View>, WorkspaceError>> getViews() {
|
||||
return repo.getViews();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Either<View, WorkspaceError>> createView({required String name, String? desc, required ViewType viewType}) {
|
||||
return repo.createView(name, desc ?? "", viewType).then((result) {
|
||||
return result.fold(
|
||||
(view) => left(view),
|
||||
(r) => right(r),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Either<Unit, WorkspaceError>> delete() {
|
||||
return repo.delete();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Either<Unit, WorkspaceError>> rename(String newName) {
|
||||
return repo.updateApp(name: newName);
|
||||
}
|
||||
}
|
||||
|
||||
class IAppListenerhImpl extends IAppListenr {
|
||||
AppListenerRepository repo;
|
||||
IAppListenerhImpl({
|
||||
required this.repo,
|
||||
});
|
||||
|
||||
@override
|
||||
Future<void> stop() async {
|
||||
await repo.close();
|
||||
}
|
||||
|
||||
@override
|
||||
void start({AppViewsChangeCallback? viewsChangeCallback, AppUpdatedCallback? updatedCallback}) {
|
||||
repo.startListening(viewsChanged: viewsChangeCallback, update: updatedCallback);
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:app_flowy/workspace/domain/i_doc.dart';
|
||||
import 'package:app_flowy/workspace/infrastructure/repos/doc_repo.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-document-infra/doc.pb.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart';
|
||||
|
||||
class IDocImpl extends IDoc {
|
||||
DocRepository repo;
|
||||
|
||||
IDocImpl({required this.repo});
|
||||
|
||||
@override
|
||||
Future<Either<Unit, WorkspaceError>> closeDoc() {
|
||||
return repo.closeDoc();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Either<DocDelta, WorkspaceError>> readDoc() async {
|
||||
final docOrFail = await repo.readDoc();
|
||||
return docOrFail;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Either<DocDelta, WorkspaceError>> composeDelta({required String json}) {
|
||||
return repo.composeDelta(data: json);
|
||||
}
|
||||
}
|
||||
|
||||
// ignore: unused_element
|
||||
Uint8List _encodeJsonText(String? json) {
|
||||
final data = utf8.encode(json ?? "");
|
||||
return Uint8List.fromList(data);
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
import 'package:app_flowy/workspace/domain/i_share.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace-infra/protobuf.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart';
|
||||
import 'package:dartz/dartz.dart';
|
||||
|
||||
import 'repos/share_repo.dart';
|
||||
|
||||
class IShareImpl extends IShare {
|
||||
ShareRepo repo;
|
||||
|
||||
IShareImpl({required this.repo});
|
||||
|
||||
@override
|
||||
Future<Either<ExportData, WorkspaceError>> exportText(String docId) {
|
||||
return repo.export(docId, ExportType.Text);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Either<ExportData, WorkspaceError>> exportMarkdown(String docId) {
|
||||
return repo.export(docId, ExportType.Markdown);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Either<ExportData, WorkspaceError>> exportURL(String docId) {
|
||||
return repo.export(docId, ExportType.Link);
|
||||
}
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
import 'package:app_flowy/workspace/domain/i_trash.dart';
|
||||
import 'package:app_flowy/workspace/infrastructure/repos/trash_repo.dart';
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace-infra/trash_create.pb.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart';
|
||||
|
||||
class ITrashImpl implements ITrash {
|
||||
TrashRepo repo;
|
||||
|
||||
ITrashImpl({required this.repo});
|
||||
|
||||
@override
|
||||
Future<Either<List<Trash>, WorkspaceError>> readTrash() {
|
||||
return repo.readTrash().then((result) {
|
||||
return result.fold(
|
||||
(repeatedTrash) => left(repeatedTrash.items),
|
||||
(err) => right(err),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Either<Unit, WorkspaceError>> putback(String trashId) {
|
||||
return repo.putback(trashId);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Either<Unit, WorkspaceError>> deleteAll() {
|
||||
return repo.deleteAll();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Either<Unit, WorkspaceError>> restoreAll() {
|
||||
return repo.restoreAll();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Either<Unit, WorkspaceError>> deleteViews(List<Tuple2<String, TrashType>> trashList) {
|
||||
return repo.deleteViews(trashList);
|
||||
}
|
||||
}
|
||||
|
||||
class ITrashListenerImpl extends ITrashListener {
|
||||
TrashListenerRepo repo;
|
||||
ITrashListenerImpl({
|
||||
required this.repo,
|
||||
});
|
||||
|
||||
@override
|
||||
Future<void> stop() async {
|
||||
await repo.close();
|
||||
}
|
||||
|
||||
@override
|
||||
void start(TrashUpdatedCallback updateCallback) {
|
||||
repo.startListening(trashUpdated: updateCallback);
|
||||
}
|
||||
}
|
||||
@@ -1,124 +0,0 @@
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:app_flowy/workspace/infrastructure/repos/helper.dart';
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:app_flowy/workspace/domain/i_user.dart';
|
||||
import 'package:app_flowy/workspace/infrastructure/repos/user_repo.dart';
|
||||
import 'package:flowy_infra/notifier.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-dart-notify/protobuf.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-user-infra/errors.pb.dart';
|
||||
// import 'package:flowy_sdk/protobuf/flowy-user/errors.pb.dart' as user_error;
|
||||
import 'package:flowy_sdk/protobuf/flowy-user/observable.pb.dart' as user;
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace-infra/workspace_create.pb.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace/observable.pb.dart';
|
||||
export 'package:app_flowy/workspace/domain/i_user.dart';
|
||||
export 'package:app_flowy/workspace/infrastructure/repos/user_repo.dart';
|
||||
import 'package:flowy_sdk/rust_stream.dart';
|
||||
import 'dart:async';
|
||||
|
||||
class IUserImpl extends IUser {
|
||||
UserRepo repo;
|
||||
IUserImpl({
|
||||
required this.repo,
|
||||
});
|
||||
|
||||
@override
|
||||
Future<Either<Unit, WorkspaceError>> deleteWorkspace(String workspaceId) {
|
||||
return repo.deleteWorkspace(workspaceId: workspaceId);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Either<UserProfile, UserError>> fetchUserProfile(String userId) {
|
||||
return repo.fetchUserProfile(userId: userId);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Either<Unit, UserError>> signOut() {
|
||||
return repo.signOut();
|
||||
}
|
||||
|
||||
@override
|
||||
UserProfile get user => repo.user;
|
||||
|
||||
@override
|
||||
Future<Either<List<Workspace>, WorkspaceError>> fetchWorkspaces() {
|
||||
return repo.getWorkspaces();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Either<Unit, UserError>> initUser() {
|
||||
return repo.initUser();
|
||||
}
|
||||
}
|
||||
|
||||
class IUserListenerImpl extends IUserListener {
|
||||
StreamSubscription<SubscribeObject>? _subscription;
|
||||
|
||||
@override
|
||||
final profileUpdatedNotifier = PublishNotifier<UserProfileUpdatedNotifierValue>();
|
||||
|
||||
@override
|
||||
final authDidChangedNotifier = PublishNotifier<AuthNotifierValue>();
|
||||
|
||||
@override
|
||||
final workspaceUpdatedNotifier = PublishNotifier<WorkspaceUpdatedNotifierValue>();
|
||||
|
||||
late WorkspaceNotificationParser _workspaceParser;
|
||||
late UserNotificationParser _userParser;
|
||||
late UserProfile _user;
|
||||
IUserListenerImpl({
|
||||
required UserProfile user,
|
||||
}) {
|
||||
_user = user;
|
||||
}
|
||||
|
||||
@override
|
||||
void start() {
|
||||
_workspaceParser = WorkspaceNotificationParser(id: _user.token, callback: _notificationCallback);
|
||||
_userParser = UserNotificationParser(id: _user.token, callback: _userNotificationCallback);
|
||||
_subscription = RustStreamReceiver.listen((observable) {
|
||||
_workspaceParser.parse(observable);
|
||||
_userParser.parse(observable);
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> stop() async {
|
||||
await _subscription?.cancel();
|
||||
}
|
||||
|
||||
void _notificationCallback(WorkspaceNotification ty, Either<Uint8List, WorkspaceError> result) {
|
||||
switch (ty) {
|
||||
case WorkspaceNotification.UserCreateWorkspace:
|
||||
case WorkspaceNotification.UserDeleteWorkspace:
|
||||
case WorkspaceNotification.WorkspaceListUpdated:
|
||||
result.fold(
|
||||
(payload) => workspaceUpdatedNotifier.value = left(RepeatedWorkspace.fromBuffer(payload).items),
|
||||
(error) => workspaceUpdatedNotifier.value = right(error),
|
||||
);
|
||||
break;
|
||||
case WorkspaceNotification.UserUnauthorized:
|
||||
result.fold(
|
||||
(_) {},
|
||||
(error) => authDidChangedNotifier.value = right(UserError.create()..code = ErrorCode.UserUnauthorized.value),
|
||||
);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void _userNotificationCallback(user.UserNotification ty, Either<Uint8List, UserError> result) {
|
||||
switch (ty) {
|
||||
case user.UserNotification.UserUnauthorized:
|
||||
result.fold(
|
||||
(payload) => profileUpdatedNotifier.value = left(UserProfile.fromBuffer(payload)),
|
||||
(error) => profileUpdatedNotifier.value = right(error),
|
||||
);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
import 'package:app_flowy/workspace/domain/i_view.dart';
|
||||
import 'package:app_flowy/workspace/infrastructure/repos/view_repo.dart';
|
||||
import 'package:flowy_infra/notifier.dart';
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace-infra/view_create.pb.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart';
|
||||
|
||||
class IViewImpl extends IView {
|
||||
ViewRepository repo;
|
||||
|
||||
IViewImpl({required this.repo});
|
||||
|
||||
@override
|
||||
View get view => repo.view;
|
||||
|
||||
@override
|
||||
Future<Either<Unit, WorkspaceError>> delete() {
|
||||
return repo.delete().then((result) {
|
||||
return result.fold(
|
||||
(_) => left(unit),
|
||||
(error) => right(error),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Either<View, WorkspaceError>> rename(String newName) {
|
||||
return repo.updateView(name: newName);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Either<Unit, WorkspaceError>> duplicate() {
|
||||
return repo.duplicate();
|
||||
}
|
||||
}
|
||||
|
||||
class IViewListenerImpl extends IViewListener {
|
||||
final ViewListenerRepository repo;
|
||||
IViewListenerImpl({
|
||||
required this.repo,
|
||||
});
|
||||
|
||||
@override
|
||||
void start() {
|
||||
repo.start();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> stop() async {
|
||||
await repo.close();
|
||||
}
|
||||
|
||||
@override
|
||||
PublishNotifier<DeleteNotifierValue> get deletedNotifier => repo.deletedNotifier;
|
||||
|
||||
@override
|
||||
PublishNotifier<UpdateNotifierValue> get updatedNotifier => repo.updatedNotifier;
|
||||
|
||||
@override
|
||||
PublishNotifier<RestoreNotifierValue> get restoredNotifier => repo.restoredNotifier;
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
import 'package:app_flowy/workspace/domain/i_workspace.dart';
|
||||
import 'package:app_flowy/workspace/infrastructure/repos/workspace_repo.dart';
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace-infra/app_create.pb.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart';
|
||||
|
||||
export 'package:app_flowy/workspace/domain/i_workspace.dart';
|
||||
|
||||
class IWorkspaceImpl extends IWorkspace {
|
||||
WorkspaceRepo repo;
|
||||
IWorkspaceImpl({
|
||||
required this.repo,
|
||||
});
|
||||
|
||||
@override
|
||||
Future<Either<App, WorkspaceError>> createApp({required String name, String? desc}) {
|
||||
return repo.createApp(name, desc ?? "");
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Either<List<App>, WorkspaceError>> getApps() {
|
||||
return repo.getApps().then((result) {
|
||||
return result.fold(
|
||||
(apps) => left(apps),
|
||||
(error) => right(error),
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
class IWorkspaceListenerImpl extends IWorkspaceListener {
|
||||
WorkspaceListenerRepo repo;
|
||||
IWorkspaceListenerImpl({
|
||||
required this.repo,
|
||||
});
|
||||
|
||||
@override
|
||||
void start({WorkspaceAppsChangedCallback? addAppCallback, WorkspaceUpdatedCallback? updatedCallback}) {
|
||||
repo.startListening(appsChanged: addAppCallback, update: updatedCallback);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> stop() async {
|
||||
await repo.close();
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,116 +0,0 @@
|
||||
import 'dart:async';
|
||||
import 'dart:typed_data';
|
||||
import 'package:app_flowy/workspace/domain/i_app.dart';
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:flowy_log/flowy_log.dart';
|
||||
import 'package:flowy_sdk/dispatch/dispatch.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-dart-notify/subject.pb.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace-infra/app_create.pb.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace-infra/app_query.pb.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace-infra/app_update.pb.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace-infra/view_create.pb.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace-infra/view_create.pbenum.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace/observable.pb.dart';
|
||||
import 'package:flowy_sdk/rust_stream.dart';
|
||||
import 'helper.dart';
|
||||
|
||||
class AppRepository {
|
||||
String appId;
|
||||
AppRepository({
|
||||
required this.appId,
|
||||
});
|
||||
|
||||
Future<Either<App, WorkspaceError>> getAppDesc() {
|
||||
final request = QueryAppRequest.create()..appIds.add(appId);
|
||||
|
||||
return WorkspaceEventReadApp(request).send();
|
||||
}
|
||||
|
||||
Future<Either<View, WorkspaceError>> createView(String name, String desc, ViewType viewType) {
|
||||
final request = CreateViewRequest.create()
|
||||
..belongToId = appId
|
||||
..name = name
|
||||
..desc = desc
|
||||
..viewType = viewType;
|
||||
|
||||
return WorkspaceEventCreateView(request).send();
|
||||
}
|
||||
|
||||
Future<Either<List<View>, WorkspaceError>> getViews() {
|
||||
final request = QueryAppRequest.create()..appIds.add(appId);
|
||||
|
||||
return WorkspaceEventReadApp(request).send().then((result) {
|
||||
return result.fold(
|
||||
(app) => left(app.belongings.items),
|
||||
(error) => right(error),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
Future<Either<Unit, WorkspaceError>> delete() {
|
||||
final request = QueryAppRequest.create()..appIds.add(appId);
|
||||
return WorkspaceEventDeleteApp(request).send();
|
||||
}
|
||||
|
||||
Future<Either<Unit, WorkspaceError>> updateApp({String? name}) {
|
||||
UpdateAppRequest request = UpdateAppRequest.create()..appId = appId;
|
||||
|
||||
if (name != null) {
|
||||
request.name = name;
|
||||
}
|
||||
return WorkspaceEventUpdateApp(request).send();
|
||||
}
|
||||
}
|
||||
|
||||
class AppListenerRepository {
|
||||
StreamSubscription<SubscribeObject>? _subscription;
|
||||
AppViewsChangeCallback? _viewsChanged;
|
||||
AppUpdatedCallback? _update;
|
||||
late WorkspaceNotificationParser _parser;
|
||||
String appId;
|
||||
|
||||
AppListenerRepository({
|
||||
required this.appId,
|
||||
});
|
||||
|
||||
void startListening({AppViewsChangeCallback? viewsChanged, AppUpdatedCallback? update}) {
|
||||
_viewsChanged = viewsChanged;
|
||||
_update = update;
|
||||
_parser = WorkspaceNotificationParser(id: appId, callback: _bservableCallback);
|
||||
_subscription = RustStreamReceiver.listen((observable) => _parser.parse(observable));
|
||||
}
|
||||
|
||||
void _bservableCallback(WorkspaceNotification ty, Either<Uint8List, WorkspaceError> result) {
|
||||
switch (ty) {
|
||||
case WorkspaceNotification.AppViewsChanged:
|
||||
if (_viewsChanged != null) {
|
||||
result.fold(
|
||||
(payload) {
|
||||
final repeatedView = RepeatedView.fromBuffer(payload);
|
||||
_viewsChanged!(left(repeatedView.items));
|
||||
},
|
||||
(error) => _viewsChanged!(right(error)),
|
||||
);
|
||||
}
|
||||
break;
|
||||
case WorkspaceNotification.AppUpdated:
|
||||
if (_update != null) {
|
||||
result.fold(
|
||||
(payload) {
|
||||
final app = App.fromBuffer(payload);
|
||||
_update!(app);
|
||||
},
|
||||
(error) => Log.error(error),
|
||||
);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> close() async {
|
||||
await _subscription?.cancel();
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:flowy_sdk/dispatch/dispatch.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-document-infra/doc.pb.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace-infra/view_query.pb.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart';
|
||||
|
||||
class DocRepository {
|
||||
final String docId;
|
||||
DocRepository({
|
||||
required this.docId,
|
||||
});
|
||||
|
||||
Future<Either<DocDelta, WorkspaceError>> readDoc() {
|
||||
final request = QueryViewRequest(viewIds: [docId]);
|
||||
return WorkspaceEventOpenView(request).send();
|
||||
}
|
||||
|
||||
Future<Either<DocDelta, WorkspaceError>> composeDelta({required String data}) {
|
||||
final request = DocDelta.create()
|
||||
..docId = docId
|
||||
..data = data;
|
||||
return WorkspaceEventApplyDocDelta(request).send();
|
||||
}
|
||||
|
||||
Future<Either<Unit, WorkspaceError>> closeDoc() {
|
||||
final request = QueryViewRequest(viewIds: [docId]);
|
||||
return WorkspaceEventCloseView(request).send();
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
import 'dart:async';
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:flowy_sdk/dispatch/dispatch.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace-infra/protobuf.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart';
|
||||
|
||||
class ShareRepo {
|
||||
Future<Either<ExportData, WorkspaceError>> export(String docId, ExportType type) {
|
||||
final request = ExportRequest.create()
|
||||
..docId = docId
|
||||
..exportType = type;
|
||||
|
||||
return WorkspaceEventExportDocument(request).send();
|
||||
}
|
||||
}
|
||||
@@ -1,76 +0,0 @@
|
||||
import 'dart:async';
|
||||
import 'dart:typed_data';
|
||||
import 'package:app_flowy/workspace/domain/i_trash.dart';
|
||||
import 'package:app_flowy/workspace/infrastructure/repos/helper.dart';
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:flowy_sdk/dispatch/dispatch.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-dart-notify/subject.pb.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace-infra/trash_create.pb.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace/observable.pb.dart';
|
||||
import 'package:flowy_sdk/rust_stream.dart';
|
||||
|
||||
class TrashRepo {
|
||||
Future<Either<RepeatedTrash, WorkspaceError>> readTrash() {
|
||||
return WorkspaceEventReadTrash().send();
|
||||
}
|
||||
|
||||
Future<Either<Unit, WorkspaceError>> putback(String trashId) {
|
||||
final id = TrashIdentifier.create()..id = trashId;
|
||||
|
||||
return WorkspaceEventPutbackTrash(id).send();
|
||||
}
|
||||
|
||||
Future<Either<Unit, WorkspaceError>> deleteViews(List<Tuple2<String, TrashType>> trashList) {
|
||||
final items = trashList.map((trash) {
|
||||
return TrashIdentifier.create()
|
||||
..id = trash.value1
|
||||
..ty = trash.value2;
|
||||
});
|
||||
|
||||
final trashIdentifiers = TrashIdentifiers(items: items);
|
||||
return WorkspaceEventDeleteTrash(trashIdentifiers).send();
|
||||
}
|
||||
|
||||
Future<Either<Unit, WorkspaceError>> restoreAll() {
|
||||
return WorkspaceEventRestoreAll().send();
|
||||
}
|
||||
|
||||
Future<Either<Unit, WorkspaceError>> deleteAll() {
|
||||
return WorkspaceEventDeleteAll().send();
|
||||
}
|
||||
}
|
||||
|
||||
class TrashListenerRepo {
|
||||
StreamSubscription<SubscribeObject>? _subscription;
|
||||
TrashUpdatedCallback? _trashUpdated;
|
||||
late WorkspaceNotificationParser _parser;
|
||||
|
||||
void startListening({TrashUpdatedCallback? trashUpdated}) {
|
||||
_trashUpdated = trashUpdated;
|
||||
_parser = WorkspaceNotificationParser(callback: _bservableCallback);
|
||||
_subscription = RustStreamReceiver.listen((observable) => _parser.parse(observable));
|
||||
}
|
||||
|
||||
void _bservableCallback(WorkspaceNotification ty, Either<Uint8List, WorkspaceError> result) {
|
||||
switch (ty) {
|
||||
case WorkspaceNotification.TrashUpdated:
|
||||
if (_trashUpdated != null) {
|
||||
result.fold(
|
||||
(payload) {
|
||||
final repeatedTrash = RepeatedTrash.fromBuffer(payload);
|
||||
_trashUpdated!(left(repeatedTrash.items));
|
||||
},
|
||||
(error) => _trashUpdated!(right(error)),
|
||||
);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> close() async {
|
||||
await _subscription?.cancel();
|
||||
}
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
import 'dart:async';
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:flowy_sdk/dispatch/dispatch.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-user/errors.pb.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-user/user_profile.pb.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace-infra/workspace_create.pb.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace-infra/workspace_query.pb.dart';
|
||||
import 'package:app_flowy/workspace/domain/i_user.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart';
|
||||
|
||||
class UserRepo {
|
||||
final UserProfile user;
|
||||
UserRepo({
|
||||
required this.user,
|
||||
});
|
||||
|
||||
Future<Either<UserProfile, UserError>> fetchUserProfile({required String userId}) {
|
||||
return UserEventGetUserProfile().send();
|
||||
}
|
||||
|
||||
Future<Either<Unit, WorkspaceError>> deleteWorkspace({required String workspaceId}) {
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
Future<Either<Unit, UserError>> signOut() {
|
||||
return UserEventSignOut().send();
|
||||
}
|
||||
|
||||
Future<Either<Unit, UserError>> initUser() async {
|
||||
return UserEventInitUser().send();
|
||||
}
|
||||
|
||||
Future<Either<List<Workspace>, WorkspaceError>> getWorkspaces() {
|
||||
final request = QueryWorkspaceRequest.create();
|
||||
|
||||
return WorkspaceEventReadWorkspaces(request).send().then((result) {
|
||||
return result.fold(
|
||||
(workspaces) => left(workspaces.items),
|
||||
(error) => right(error),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
Future<Either<Workspace, WorkspaceError>> openWorkspace(String workspaceId) {
|
||||
final request = QueryWorkspaceRequest.create()..workspaceId = workspaceId;
|
||||
return WorkspaceEventOpenWorkspace(request).send().then((result) {
|
||||
return result.fold(
|
||||
(workspace) => left(workspace),
|
||||
(error) => right(error),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
Future<Either<Workspace, WorkspaceError>> createWorkspace(String name, String desc) {
|
||||
final request = CreateWorkspaceRequest.create()
|
||||
..name = name
|
||||
..desc = desc;
|
||||
return WorkspaceEventCreateWorkspace(request).send().then((result) {
|
||||
return result.fold(
|
||||
(workspace) => left(workspace),
|
||||
(error) => right(error),
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
PODS:
|
||||
- flowy_editor (0.0.1):
|
||||
- FlutterMacOS
|
||||
- flowy_infra_ui (0.0.1):
|
||||
- FlutterMacOS
|
||||
- flowy_sdk (0.0.1):
|
||||
- FlutterMacOS
|
||||
- FlutterMacOS (1.0.0)
|
||||
- package_info_plus_macos (0.0.1):
|
||||
- FlutterMacOS
|
||||
- path_provider_macos (0.0.1):
|
||||
- FlutterMacOS
|
||||
- url_launcher_macos (0.0.1):
|
||||
- FlutterMacOS
|
||||
- window_size (0.0.2):
|
||||
- FlutterMacOS
|
||||
|
||||
DEPENDENCIES:
|
||||
- flowy_editor (from `Flutter/ephemeral/.symlinks/plugins/flowy_editor/macos`)
|
||||
- flowy_infra_ui (from `Flutter/ephemeral/.symlinks/plugins/flowy_infra_ui/macos`)
|
||||
- flowy_sdk (from `Flutter/ephemeral/.symlinks/plugins/flowy_sdk/macos`)
|
||||
- FlutterMacOS (from `Flutter/ephemeral`)
|
||||
- package_info_plus_macos (from `Flutter/ephemeral/.symlinks/plugins/package_info_plus_macos/macos`)
|
||||
- path_provider_macos (from `Flutter/ephemeral/.symlinks/plugins/path_provider_macos/macos`)
|
||||
- url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`)
|
||||
- window_size (from `Flutter/ephemeral/.symlinks/plugins/window_size/macos`)
|
||||
|
||||
EXTERNAL SOURCES:
|
||||
flowy_editor:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/flowy_editor/macos
|
||||
flowy_infra_ui:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/flowy_infra_ui/macos
|
||||
flowy_sdk:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/flowy_sdk/macos
|
||||
FlutterMacOS:
|
||||
:path: Flutter/ephemeral
|
||||
package_info_plus_macos:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/package_info_plus_macos/macos
|
||||
path_provider_macos:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/path_provider_macos/macos
|
||||
url_launcher_macos:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos
|
||||
window_size:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/window_size/macos
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
flowy_editor: 26060a984848e6afac1f6a4455511f4114119d8d
|
||||
flowy_infra_ui: 9d5021b1610fe0476eb1191bf7cd41c4a4138d8f
|
||||
flowy_sdk: b7efddcc3af4ea87dc2f842c22dc37283bb9e169
|
||||
FlutterMacOS: 57701585bf7de1b3fc2bb61f6378d73bbdea8424
|
||||
package_info_plus_macos: f010621b07802a241d96d01876d6705f15e77c1c
|
||||
path_provider_macos: 160cab0d5461f0c0e02995469a98f24bdb9a3f1f
|
||||
url_launcher_macos: 45af3d61de06997666568a7149c1be98b41c95d4
|
||||
window_size: 339dafa0b27a95a62a843042038fa6c3c48de195
|
||||
|
||||
PODFILE CHECKSUM: 6eac6b3292e5142cfc23bdeb71848a40ec51c14c
|
||||
|
||||
COCOAPODS: 1.10.1
|
||||
@@ -1,10 +0,0 @@
|
||||
# This file tracks properties of this Flutter project.
|
||||
# Used by Flutter tool to assess capabilities and perform upgrades etc.
|
||||
#
|
||||
# This file should be version controlled and should not be manually edited.
|
||||
|
||||
version:
|
||||
revision: b7d4806243a4e906bf061f79a0e314ba28111aa6
|
||||
channel: dev
|
||||
|
||||
project_type: plugin
|
||||
@@ -1,19 +0,0 @@
|
||||
{
|
||||
// 使用 IntelliSense 了解相关属性。
|
||||
// 悬停以查看现有属性的描述。
|
||||
// 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "flowy_editor",
|
||||
"request": "launch",
|
||||
"type": "dart"
|
||||
},
|
||||
{
|
||||
"name": "flowy_editor example",
|
||||
"cwd": "example",
|
||||
"request": "launch",
|
||||
"type": "dart"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
include: package:pedantic/analysis_options.yaml
|
||||
analyzer:
|
||||
exclude:
|
||||
- "**/*.g.dart"
|
||||
- "**/*.freezed.dart"
|
||||
|
||||
|
||||
# https://dart.dev/guides/language/analysis-options
|
||||
@@ -1,40 +0,0 @@
|
||||
group 'com.plugin.flowy_editor'
|
||||
version '1.0-SNAPSHOT'
|
||||
|
||||
buildscript {
|
||||
ext.kotlin_version = '1.3.50'
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:4.1.0'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
}
|
||||
}
|
||||
|
||||
rootProject.allprojects {
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'com.android.library'
|
||||
apply plugin: 'kotlin-android'
|
||||
|
||||
android {
|
||||
compileSdkVersion 30
|
||||
|
||||
sourceSets {
|
||||
main.java.srcDirs += 'src/main/kotlin'
|
||||
}
|
||||
defaultConfig {
|
||||
minSdkVersion 16
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
rootProject.name = 'flowy_editor'
|
||||
@@ -1,3 +0,0 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.plugin.flowy_editor">
|
||||
</manifest>
|
||||
-36
@@ -1,36 +0,0 @@
|
||||
package com.plugin.flowy_editor
|
||||
|
||||
import androidx.annotation.NonNull
|
||||
|
||||
import io.flutter.embedding.engine.plugins.FlutterPlugin
|
||||
import io.flutter.plugin.common.MethodCall
|
||||
import io.flutter.plugin.common.MethodChannel
|
||||
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
|
||||
import io.flutter.plugin.common.MethodChannel.Result
|
||||
import io.flutter.plugin.common.PluginRegistry.Registrar
|
||||
|
||||
/** FlowyEditorPlugin */
|
||||
class FlowyEditorPlugin: FlutterPlugin, MethodCallHandler {
|
||||
/// The MethodChannel that will the communication between Flutter and native Android
|
||||
///
|
||||
/// This local reference serves to register the plugin with the Flutter Engine and unregister it
|
||||
/// when the Flutter Engine is detached from the Activity
|
||||
private lateinit var channel : MethodChannel
|
||||
|
||||
override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
|
||||
channel = MethodChannel(flutterPluginBinding.binaryMessenger, "flowy_editor")
|
||||
channel.setMethodCallHandler(this)
|
||||
}
|
||||
|
||||
override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) {
|
||||
if (call.method == "getPlatformVersion") {
|
||||
result.success("Android ${android.os.Build.VERSION.RELEASE}")
|
||||
} else {
|
||||
result.notImplemented()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) {
|
||||
channel.setMethodCallHandler(null)
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
# This file tracks properties of this Flutter project.
|
||||
# Used by Flutter tool to assess capabilities and perform upgrades etc.
|
||||
#
|
||||
# This file should be version controlled and should not be manually edited.
|
||||
|
||||
version:
|
||||
revision: b7d4806243a4e906bf061f79a0e314ba28111aa6
|
||||
channel: dev
|
||||
|
||||
project_type: app
|
||||
@@ -1,16 +0,0 @@
|
||||
# flowy_editor_example
|
||||
|
||||
Demonstrates how to use the flowy_editor plugin.
|
||||
|
||||
## Getting Started
|
||||
|
||||
This project is a starting point for a Flutter application.
|
||||
|
||||
A few resources to get you started if this is your first Flutter project:
|
||||
|
||||
- [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab)
|
||||
- [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook)
|
||||
|
||||
For help getting started with Flutter, view our
|
||||
[online documentation](https://flutter.dev/docs), which offers tutorials,
|
||||
samples, guidance on mobile development, and a full API reference.
|
||||
@@ -1,59 +0,0 @@
|
||||
def localProperties = new Properties()
|
||||
def localPropertiesFile = rootProject.file('local.properties')
|
||||
if (localPropertiesFile.exists()) {
|
||||
localPropertiesFile.withReader('UTF-8') { reader ->
|
||||
localProperties.load(reader)
|
||||
}
|
||||
}
|
||||
|
||||
def flutterRoot = localProperties.getProperty('flutter.sdk')
|
||||
if (flutterRoot == null) {
|
||||
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
|
||||
}
|
||||
|
||||
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
|
||||
if (flutterVersionCode == null) {
|
||||
flutterVersionCode = '1'
|
||||
}
|
||||
|
||||
def flutterVersionName = localProperties.getProperty('flutter.versionName')
|
||||
if (flutterVersionName == null) {
|
||||
flutterVersionName = '1.0'
|
||||
}
|
||||
|
||||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
|
||||
|
||||
android {
|
||||
compileSdkVersion 30
|
||||
|
||||
sourceSets {
|
||||
main.java.srcDirs += 'src/main/kotlin'
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
|
||||
applicationId "com.plugin.flowy_editor_example"
|
||||
minSdkVersion 16
|
||||
targetSdkVersion 30
|
||||
versionCode flutterVersionCode.toInteger()
|
||||
versionName flutterVersionName
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
// TODO: Add your own signing config for the release build.
|
||||
// Signing with the debug keys for now, so `flutter run --release` works.
|
||||
signingConfig signingConfigs.debug
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
flutter {
|
||||
source '../..'
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.plugin.flowy_editor_example">
|
||||
<!-- Flutter needs it to communicate with the running application
|
||||
to allow setting breakpoints, to provide hot reload, etc.
|
||||
-->
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
</manifest>
|
||||
@@ -1,41 +0,0 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.plugin.flowy_editor_example">
|
||||
<application
|
||||
android:label="flowy_editor_example"
|
||||
android:icon="@mipmap/ic_launcher">
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:launchMode="singleTop"
|
||||
android:theme="@style/LaunchTheme"
|
||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
|
||||
android:hardwareAccelerated="true"
|
||||
android:windowSoftInputMode="adjustResize">
|
||||
<!-- Specifies an Android theme to apply to this Activity as soon as
|
||||
the Android process has started. This theme is visible to the user
|
||||
while the Flutter UI initializes. After that, this theme continues
|
||||
to determine the Window background behind the Flutter UI. -->
|
||||
<meta-data
|
||||
android:name="io.flutter.embedding.android.NormalTheme"
|
||||
android:resource="@style/NormalTheme"
|
||||
/>
|
||||
<!-- Displays an Android View that continues showing the launch screen
|
||||
Drawable until Flutter paints its first frame, then this splash
|
||||
screen fades out. A splash screen is useful to avoid any visual
|
||||
gap between the end of Android's launch screen and the painting of
|
||||
Flutter's first frame. -->
|
||||
<meta-data
|
||||
android:name="io.flutter.embedding.android.SplashScreenDrawable"
|
||||
android:resource="@drawable/launch_background"
|
||||
/>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<!-- Don't delete the meta-data below.
|
||||
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
|
||||
<meta-data
|
||||
android:name="flutterEmbedding"
|
||||
android:value="2" />
|
||||
</application>
|
||||
</manifest>
|
||||
-6
@@ -1,6 +0,0 @@
|
||||
package com.plugin.flowy_editor_example
|
||||
|
||||
import io.flutter.embedding.android.FlutterActivity
|
||||
|
||||
class MainActivity: FlutterActivity() {
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.plugin.flowy_editor_example">
|
||||
<!-- Flutter needs it to communicate with the running application
|
||||
to allow setting breakpoints, to provide hot reload, etc.
|
||||
-->
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
</manifest>
|
||||
@@ -1,33 +0,0 @@
|
||||
[
|
||||
{
|
||||
"insert":"This is a checkbox"
|
||||
},
|
||||
{
|
||||
"attributes":{
|
||||
"list":"checked"
|
||||
},
|
||||
"insert":"\n"
|
||||
},
|
||||
{
|
||||
"insert": {
|
||||
"flutter_logo": ""
|
||||
},
|
||||
"attributes":{
|
||||
"size": 200.0
|
||||
}
|
||||
},
|
||||
{
|
||||
"insert":"\n"
|
||||
},
|
||||
{
|
||||
"insert": {
|
||||
"test_block_type": "test_data"
|
||||
},
|
||||
"attributes":{
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
"insert":"\n"
|
||||
}
|
||||
]
|
||||
@@ -1,95 +0,0 @@
|
||||
[
|
||||
{
|
||||
"insert":"Flowy Editor"
|
||||
},
|
||||
{
|
||||
"attributes":{
|
||||
"heading":1
|
||||
},
|
||||
"insert":"\n"
|
||||
},
|
||||
{
|
||||
"insert":"Flowy Editor"
|
||||
},
|
||||
{
|
||||
"attributes":{
|
||||
"heading":2
|
||||
},
|
||||
"insert":"\n"
|
||||
},
|
||||
{
|
||||
"insert":"Flowy Editor"
|
||||
},
|
||||
{
|
||||
"attributes":{
|
||||
"heading":3
|
||||
},
|
||||
"insert":"\n"
|
||||
},
|
||||
{
|
||||
"insert":"Flowy Editor\n"
|
||||
},
|
||||
{
|
||||
"insert":"Flowy Editor"
|
||||
},
|
||||
{
|
||||
"attributes":{
|
||||
"heading":1
|
||||
},
|
||||
"insert":"\n"
|
||||
},
|
||||
{
|
||||
"insert":"Flowy Editor"
|
||||
},
|
||||
{
|
||||
"attributes":{
|
||||
"heading":2
|
||||
},
|
||||
"insert":"\n"
|
||||
},
|
||||
{
|
||||
"insert":"Flowy Editor"
|
||||
},
|
||||
{
|
||||
"attributes":{
|
||||
"heading":3
|
||||
},
|
||||
"insert":"\n"
|
||||
},
|
||||
{
|
||||
"insert":"Flowy Editor\n"
|
||||
},
|
||||
{
|
||||
"insert":"Flowy Editor"
|
||||
},
|
||||
{
|
||||
"attributes":{
|
||||
"heading":1
|
||||
},
|
||||
"insert":"\n"
|
||||
},
|
||||
{
|
||||
"insert":"Flowy Editor"
|
||||
},
|
||||
{
|
||||
"attributes":{
|
||||
"heading":2
|
||||
},
|
||||
"insert":"\n"
|
||||
},
|
||||
{
|
||||
"insert":"Flowy Editor"
|
||||
},
|
||||
{
|
||||
"attributes":{
|
||||
"heading":3
|
||||
},
|
||||
"insert":"\n"
|
||||
},
|
||||
{
|
||||
"insert":"Flowy Editor\n"
|
||||
},
|
||||
{
|
||||
"insert":"\n"
|
||||
}
|
||||
]
|
||||
@@ -1,125 +0,0 @@
|
||||
[
|
||||
{
|
||||
"insert":"Flowy Editor"
|
||||
},
|
||||
{
|
||||
"attributes":{
|
||||
"header":1
|
||||
},
|
||||
"insert":"\n"
|
||||
},
|
||||
{
|
||||
"insert":"This is the test document for flowy editor.\nTest the decoding Delta and renderiing attributed text.\nTest Content"
|
||||
},
|
||||
{
|
||||
"attributes":{
|
||||
"header":2
|
||||
},
|
||||
"insert":"\n"
|
||||
},
|
||||
{
|
||||
"insert":"This is a plain text.\nThis is a quote text."
|
||||
},
|
||||
{
|
||||
"attributes":{
|
||||
"quote_block":true
|
||||
},
|
||||
"insert":"\n"
|
||||
},
|
||||
{
|
||||
"insert":"This line contains a "
|
||||
},
|
||||
{
|
||||
"attributes":{
|
||||
"bold":true
|
||||
},
|
||||
"insert":"bold"
|
||||
},
|
||||
{
|
||||
"insert":" word, also, "
|
||||
},
|
||||
{
|
||||
"attributes":{
|
||||
"italic":true
|
||||
},
|
||||
"insert":"italic"
|
||||
},
|
||||
{
|
||||
"insert":" word here, and "
|
||||
},
|
||||
{
|
||||
"attributes":{
|
||||
"strikethrough":true
|
||||
},
|
||||
"insert":"strikethrough"
|
||||
},
|
||||
{
|
||||
"insert": " and "
|
||||
},
|
||||
{
|
||||
"attributes":{
|
||||
"underline":true
|
||||
},
|
||||
"insert":"underline"
|
||||
},
|
||||
{
|
||||
"insert":" etc...\n"
|
||||
},
|
||||
{
|
||||
"attributes":{
|
||||
"link":"appflowy.com"
|
||||
},
|
||||
"insert":"AppFlowy.com"
|
||||
},
|
||||
{
|
||||
"insert":"\nEl"
|
||||
},
|
||||
{
|
||||
"attributes":{
|
||||
"bold":true
|
||||
},
|
||||
"insert": "eme"
|
||||
},
|
||||
{
|
||||
"insert": "nt 1"
|
||||
},
|
||||
{
|
||||
"attributes":{
|
||||
"list":"bullet"
|
||||
},
|
||||
"insert":"\n"
|
||||
},
|
||||
{
|
||||
"insert":"Element 2"
|
||||
},
|
||||
{
|
||||
"attributes":{
|
||||
"list":"bullet"
|
||||
},
|
||||
"insert":"\n"
|
||||
},
|
||||
{
|
||||
"insert":"Choice 1"
|
||||
},
|
||||
{
|
||||
"attributes":{
|
||||
"list":"ordered"
|
||||
},
|
||||
"insert":"\n"
|
||||
},
|
||||
{
|
||||
"insert":"Choice 2"
|
||||
},
|
||||
{
|
||||
"attributes":{
|
||||
"list":"ordered"
|
||||
},
|
||||
"insert":"\n"
|
||||
},
|
||||
{
|
||||
"insert":"\nThis is the content of a checkbox"
|
||||
},
|
||||
{
|
||||
"insert":"\n"
|
||||
}
|
||||
]
|
||||
@@ -1,40 +0,0 @@
|
||||
PODS:
|
||||
- flowy_editor (0.0.1):
|
||||
- Flutter
|
||||
- Flutter (1.0.0)
|
||||
- flutter_keyboard_visibility (0.0.1):
|
||||
- Flutter
|
||||
- path_provider (0.0.1):
|
||||
- Flutter
|
||||
- url_launcher (0.0.1):
|
||||
- Flutter
|
||||
|
||||
DEPENDENCIES:
|
||||
- flowy_editor (from `.symlinks/plugins/flowy_editor/ios`)
|
||||
- Flutter (from `Flutter`)
|
||||
- flutter_keyboard_visibility (from `.symlinks/plugins/flutter_keyboard_visibility/ios`)
|
||||
- path_provider (from `.symlinks/plugins/path_provider/ios`)
|
||||
- url_launcher (from `.symlinks/plugins/url_launcher/ios`)
|
||||
|
||||
EXTERNAL SOURCES:
|
||||
flowy_editor:
|
||||
:path: ".symlinks/plugins/flowy_editor/ios"
|
||||
Flutter:
|
||||
:path: Flutter
|
||||
flutter_keyboard_visibility:
|
||||
:path: ".symlinks/plugins/flutter_keyboard_visibility/ios"
|
||||
path_provider:
|
||||
:path: ".symlinks/plugins/path_provider/ios"
|
||||
url_launcher:
|
||||
:path: ".symlinks/plugins/url_launcher/ios"
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
flowy_editor: bf8d58894ddb03453bd4d8521c57267ad638b837
|
||||
Flutter: 434fef37c0980e73bb6479ef766c45957d4b510c
|
||||
flutter_keyboard_visibility: 0339d06371254c3eb25eeb90ba8d17dca8f9c069
|
||||
path_provider: abfe2b5c733d04e238b0d8691db0cfd63a27a93c
|
||||
url_launcher: 6fef411d543ceb26efce54b05a0a40bfd74cbbef
|
||||
|
||||
PODFILE CHECKSUM: aafe91acc616949ddb318b77800a7f51bffa2a4c
|
||||
|
||||
COCOAPODS: 1.9.3
|
||||
@@ -1,546 +0,0 @@
|
||||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 46;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
|
||||
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
|
||||
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
|
||||
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
|
||||
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
|
||||
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
|
||||
E3DDC456A090874E3DDA4243 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9AC220F65A26B2252F1DA215 /* Pods_Runner.framework */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
9705A1C41CF9048500538489 /* Embed Frameworks */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = "";
|
||||
dstSubfolderSpec = 10;
|
||||
files = (
|
||||
);
|
||||
name = "Embed Frameworks";
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
0ADA789FA5EE9F1E98B5777F /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
|
||||
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
|
||||
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
|
||||
207AE31B53F0717E0281FD87 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
|
||||
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
|
||||
3BAB9388A73799EC42C6C044 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
|
||||
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
|
||||
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
|
||||
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
|
||||
97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
|
||||
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
9AC220F65A26B2252F1DA215 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
97C146EB1CF9000F007C117D /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
E3DDC456A090874E3DDA4243 /* Pods_Runner.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
597674AF1FE94F975393FEB7 /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
9AC220F65A26B2252F1DA215 /* Pods_Runner.framework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
9740EEB11CF90186004384FC /* Flutter */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
|
||||
9740EEB21CF90195004384FC /* Debug.xcconfig */,
|
||||
7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
|
||||
9740EEB31CF90195004384FC /* Generated.xcconfig */,
|
||||
);
|
||||
name = Flutter;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
97C146E51CF9000F007C117D = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
9740EEB11CF90186004384FC /* Flutter */,
|
||||
97C146F01CF9000F007C117D /* Runner */,
|
||||
97C146EF1CF9000F007C117D /* Products */,
|
||||
F25CAD61A400EA4A979759D7 /* Pods */,
|
||||
597674AF1FE94F975393FEB7 /* Frameworks */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
97C146EF1CF9000F007C117D /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
97C146EE1CF9000F007C117D /* Runner.app */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
97C146F01CF9000F007C117D /* Runner */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
97C146FA1CF9000F007C117D /* Main.storyboard */,
|
||||
97C146FD1CF9000F007C117D /* Assets.xcassets */,
|
||||
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
|
||||
97C147021CF9000F007C117D /* Info.plist */,
|
||||
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
|
||||
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
|
||||
74858FAE1ED2DC5600515810 /* AppDelegate.swift */,
|
||||
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */,
|
||||
);
|
||||
path = Runner;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F25CAD61A400EA4A979759D7 /* Pods */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
3BAB9388A73799EC42C6C044 /* Pods-Runner.debug.xcconfig */,
|
||||
0ADA789FA5EE9F1E98B5777F /* Pods-Runner.release.xcconfig */,
|
||||
207AE31B53F0717E0281FD87 /* Pods-Runner.profile.xcconfig */,
|
||||
);
|
||||
name = Pods;
|
||||
path = Pods;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
97C146ED1CF9000F007C117D /* Runner */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
|
||||
buildPhases = (
|
||||
5B014E49941065F7FD60552C /* [CP] Check Pods Manifest.lock */,
|
||||
9740EEB61CF901F6004384FC /* Run Script */,
|
||||
97C146EA1CF9000F007C117D /* Sources */,
|
||||
97C146EB1CF9000F007C117D /* Frameworks */,
|
||||
97C146EC1CF9000F007C117D /* Resources */,
|
||||
9705A1C41CF9048500538489 /* Embed Frameworks */,
|
||||
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
|
||||
3083A35B476F73AE59140313 /* [CP] Embed Pods Frameworks */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = Runner;
|
||||
productName = Runner;
|
||||
productReference = 97C146EE1CF9000F007C117D /* Runner.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
97C146E61CF9000F007C117D /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 1020;
|
||||
ORGANIZATIONNAME = "";
|
||||
TargetAttributes = {
|
||||
97C146ED1CF9000F007C117D = {
|
||||
CreatedOnToolsVersion = 7.3.1;
|
||||
LastSwiftMigration = 1100;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
|
||||
compatibilityVersion = "Xcode 9.3";
|
||||
developmentRegion = en;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
Base,
|
||||
);
|
||||
mainGroup = 97C146E51CF9000F007C117D;
|
||||
productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
97C146ED1CF9000F007C117D /* Runner */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
97C146EC1CF9000F007C117D /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
|
||||
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
|
||||
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
|
||||
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
3083A35B476F73AE59140313 /* [CP] Embed Pods Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh",
|
||||
"${BUILT_PRODUCTS_DIR}/flowy_editor/flowy_editor.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/flutter_keyboard_visibility/flutter_keyboard_visibility.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/path_provider/path_provider.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/url_launcher/url_launcher.framework",
|
||||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
outputPaths = (
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flowy_editor.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_keyboard_visibility.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/path_provider.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/url_launcher.framework",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "Thin Binary";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
|
||||
};
|
||||
5B014E49941065F7FD60552C /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
||||
"${PODS_ROOT}/Manifest.lock",
|
||||
);
|
||||
name = "[CP] Check Pods Manifest.lock";
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
"$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
9740EEB61CF901F6004384FC /* Run Script */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "Run Script";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
97C146EA1CF9000F007C117D /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */,
|
||||
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXVariantGroup section */
|
||||
97C146FA1CF9000F007C117D /* Main.storyboard */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
97C146FB1CF9000F007C117D /* Base */,
|
||||
);
|
||||
name = Main.storyboard;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
97C147001CF9000F007C117D /* Base */,
|
||||
);
|
||||
name = LaunchScreen.storyboard;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXVariantGroup section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
249021D3217E4FDB00AE95B9 /* Profile */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
SUPPORTED_PLATFORMS = iphoneos;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
name = Profile;
|
||||
};
|
||||
249021D4217E4FDB00AE95B9 /* Profile */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.plugin.flowyEditorExample;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||
SWIFT_VERSION = 5.0;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
};
|
||||
name = Profile;
|
||||
};
|
||||
97C147031CF9000F007C117D /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
97C147041CF9000F007C117D /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
SUPPORTED_PLATFORMS = iphoneos;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
97C147061CF9000F007C117D /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.plugin.flowyEditorExample;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 5.0;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
97C147071CF9000F007C117D /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.plugin.flowyEditorExample;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||
SWIFT_VERSION = 5.0;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
97C147031CF9000F007C117D /* Debug */,
|
||||
97C147041CF9000F007C117D /* Release */,
|
||||
249021D3217E4FDB00AE95B9 /* Profile */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
97C147061CF9000F007C117D /* Debug */,
|
||||
97C147071CF9000F007C117D /* Release */,
|
||||
249021D4217E4FDB00AE95B9 /* Profile */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 97C146E61CF9000F007C117D /* Project object */;
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>flowy_editor_example</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>$(FLUTTER_BUILD_NAME)</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>$(FLUTTER_BUILD_NUMBER)</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>LaunchScreen</string>
|
||||
<key>UIMainStoryboardFile</key>
|
||||
<string>Main</string>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>UIViewControllerBasedStatusBarAppearance</key>
|
||||
<false/>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -1,67 +0,0 @@
|
||||
import 'widgets/home_drawer.dart';
|
||||
import 'widgets/editor_scaffold.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
final flowyDocs = [
|
||||
'plain_text_document.fdoc',
|
||||
'block_document.fdoc',
|
||||
'long_document.fdoc',
|
||||
];
|
||||
|
||||
class HomeScreen extends StatefulWidget {
|
||||
@override
|
||||
_HomeScreenState createState() => _HomeScreenState();
|
||||
}
|
||||
|
||||
class _HomeScreenState extends State<HomeScreen> {
|
||||
String filename;
|
||||
Widget _editor;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
filename = flowyDocs[1];
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return HomeDrawer(
|
||||
drawer: Container(
|
||||
constraints: BoxConstraints(minWidth: 250, maxWidth: 250),
|
||||
color: Colors.white,
|
||||
child: ListView.separated(
|
||||
itemBuilder: (context, index) {
|
||||
return GestureDetector(
|
||||
onTap: () => _selectDoc(index),
|
||||
child: Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 8.0, vertical: 16.0),
|
||||
child: Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Text(
|
||||
flowyDocs[index],
|
||||
style: TextStyle(fontSize: 16.0, color: Colors.black54),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
itemCount: flowyDocs.length,
|
||||
separatorBuilder: (context, index) => Divider(),
|
||||
),
|
||||
),
|
||||
body: _editor ?? _homepageEditor(),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _homepageEditor() {
|
||||
return EditorScaffold(filename: filename);
|
||||
}
|
||||
|
||||
void _selectDoc(int index) {
|
||||
final filename = flowyDocs[index];
|
||||
setState(() {
|
||||
_editor = null;
|
||||
this.filename = filename;
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
import 'home_screen.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
void main() {
|
||||
runApp(MyApp());
|
||||
}
|
||||
|
||||
class MyApp extends StatefulWidget {
|
||||
@override
|
||||
_MyAppState createState() => _MyAppState();
|
||||
}
|
||||
|
||||
class _MyAppState extends State<MyApp> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MaterialApp(
|
||||
debugShowCheckedModeBanner: false,
|
||||
home: HomeScreen(),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,130 +0,0 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flowy_editor/flowy_editor.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
class EditorScaffold extends StatefulWidget {
|
||||
final String filename;
|
||||
|
||||
const EditorScaffold({
|
||||
Key key,
|
||||
@required this.filename,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
_EditorScaffoldState createState() => _EditorScaffoldState();
|
||||
}
|
||||
|
||||
class _EditorScaffoldState extends State<EditorScaffold> {
|
||||
EditorController _controller;
|
||||
String _filename;
|
||||
final FocusNode _focusNode = FocusNode();
|
||||
|
||||
bool _loading = false;
|
||||
String errorMsg;
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_controller.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
super.didChangeDependencies();
|
||||
if (_controller == null && !_loading) {
|
||||
_load();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Widget body;
|
||||
if (_loading) {
|
||||
body = Center(child: Text('Loading...'));
|
||||
} else if (_filename != widget.filename) {
|
||||
_load();
|
||||
} else if (_controller == null) {
|
||||
body = _zeroStateView();
|
||||
} else {
|
||||
final editor = FlowyEditor(
|
||||
controller: _controller,
|
||||
focusNode: _focusNode,
|
||||
scrollable: true,
|
||||
autoFocus: false,
|
||||
expands: false,
|
||||
padding: EdgeInsets.symmetric(horizontal: 8.0),
|
||||
readOnly: false,
|
||||
scrollBottomInset: 0,
|
||||
scrollController: ScrollController(),
|
||||
);
|
||||
body = SafeArea(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Container(
|
||||
child: editor,
|
||||
)),
|
||||
Container(
|
||||
child: FlowyToolbar.basic(
|
||||
controller: _controller,
|
||||
onImageSelectCallback: _onImageSelection,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
elevation: 0,
|
||||
title: Text(widget.filename),
|
||||
),
|
||||
body: body,
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _load() async {
|
||||
_filename = widget.filename;
|
||||
try {
|
||||
final docJson = await rootBundle.loadString('assets/${widget.filename}');
|
||||
final doc = Document.fromJson(jsonDecode(docJson));
|
||||
setState(() {
|
||||
_controller = EditorController(
|
||||
document: doc,
|
||||
selection: const TextSelection.collapsed(offset: 0),
|
||||
);
|
||||
_loading = false;
|
||||
});
|
||||
} catch (error) {
|
||||
setState(() {
|
||||
_loading = false;
|
||||
errorMsg = error.toString();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Widget _zeroStateView() {
|
||||
return Container(
|
||||
child: Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Icon(Icons.error, color: Colors.red),
|
||||
Text('Error: ${errorMsg ?? "unknow"}'),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<String> _onImageSelection(File file) {
|
||||
// TODO: Impl this
|
||||
return Future.value('');
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class HomeDrawer extends StatelessWidget {
|
||||
final Widget drawer;
|
||||
final Widget body;
|
||||
|
||||
const HomeDrawer({
|
||||
Key key,
|
||||
this.drawer,
|
||||
this.body,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return LayoutBuilder(
|
||||
builder: (context, constraints) {
|
||||
final appBar = AppBar(
|
||||
title: Text('Flowy Editor Example'),
|
||||
);
|
||||
if (constraints.maxWidth < 800) {
|
||||
return Scaffold(
|
||||
appBar: appBar,
|
||||
drawer: drawer,
|
||||
body: body,
|
||||
);
|
||||
}
|
||||
return Scaffold(
|
||||
body: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
Container(
|
||||
constraints: BoxConstraints(minWidth: 250, maxWidth: 250),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
appBar,
|
||||
Expanded(child: drawer),
|
||||
],
|
||||
),
|
||||
),
|
||||
VerticalDivider(width: 1.0),
|
||||
Expanded(child: body),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
//
|
||||
// Generated file. Do not edit.
|
||||
//
|
||||
|
||||
import FlutterMacOS
|
||||
import Foundation
|
||||
|
||||
import flowy_editor
|
||||
import path_provider_macos
|
||||
import url_launcher_macos
|
||||
|
||||
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||
FlowyEditorPlugin.register(with: registry.registrar(forPlugin: "FlowyEditorPlugin"))
|
||||
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
|
||||
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
PODS:
|
||||
- flowy_editor (0.0.1):
|
||||
- FlutterMacOS
|
||||
- FlutterMacOS (1.0.0)
|
||||
- path_provider_macos (0.0.1):
|
||||
- FlutterMacOS
|
||||
- url_launcher_macos (0.0.1):
|
||||
- FlutterMacOS
|
||||
|
||||
DEPENDENCIES:
|
||||
- flowy_editor (from `Flutter/ephemeral/.symlinks/plugins/flowy_editor/macos`)
|
||||
- FlutterMacOS (from `Flutter/ephemeral`)
|
||||
- path_provider_macos (from `Flutter/ephemeral/.symlinks/plugins/path_provider_macos/macos`)
|
||||
- url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`)
|
||||
|
||||
EXTERNAL SOURCES:
|
||||
flowy_editor:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/flowy_editor/macos
|
||||
FlutterMacOS:
|
||||
:path: Flutter/ephemeral
|
||||
path_provider_macos:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/path_provider_macos/macos
|
||||
url_launcher_macos:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
flowy_editor: 26060a984848e6afac1f6a4455511f4114119d8d
|
||||
FlutterMacOS: 57701585bf7de1b3fc2bb61f6378d73bbdea8424
|
||||
path_provider_macos: a0a3fd666cb7cd0448e936fb4abad4052961002b
|
||||
url_launcher_macos: 45af3d61de06997666568a7149c1be98b41c95d4
|
||||
|
||||
PODFILE CHECKSUM: 6eac6b3292e5142cfc23bdeb71848a40ec51c14c
|
||||
|
||||
COCOAPODS: 1.9.3
|
||||
@@ -1,632 +0,0 @@
|
||||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 51;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXAggregateTarget section */
|
||||
33CC111A2044C6BA0003C045 /* Flutter Assemble */ = {
|
||||
isa = PBXAggregateTarget;
|
||||
buildConfigurationList = 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */;
|
||||
buildPhases = (
|
||||
33CC111E2044C6BF0003C045 /* ShellScript */,
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = "Flutter Assemble";
|
||||
productName = FLX;
|
||||
};
|
||||
/* End PBXAggregateTarget section */
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
0C27A898F19849756B2961F2 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C702E5916917E3066B271F03 /* Pods_Runner.framework */; };
|
||||
335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; };
|
||||
33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; };
|
||||
33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; };
|
||||
33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; };
|
||||
33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
33CC111F2044C79F0003C045 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 33CC10E52044A3C60003C045 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = 33CC111A2044C6BA0003C045;
|
||||
remoteInfo = FLX;
|
||||
};
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
33CC110E2044A8840003C045 /* Bundle Framework */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = "";
|
||||
dstSubfolderSpec = 10;
|
||||
files = (
|
||||
);
|
||||
name = "Bundle Framework";
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = "<group>"; };
|
||||
335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = "<group>"; };
|
||||
33CC10ED2044A3C60003C045 /* flowy_editor_example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = flowy_editor_example.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||
33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = "<group>"; };
|
||||
33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = "<group>"; };
|
||||
33CC10F72044A3C60003C045 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = Runner/Info.plist; sourceTree = "<group>"; };
|
||||
33CC11122044BFA00003C045 /* MainFlutterWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainFlutterWindow.swift; sourceTree = "<group>"; };
|
||||
33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Debug.xcconfig"; sourceTree = "<group>"; };
|
||||
33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Release.xcconfig"; sourceTree = "<group>"; };
|
||||
33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = "Flutter-Generated.xcconfig"; path = "ephemeral/Flutter-Generated.xcconfig"; sourceTree = "<group>"; };
|
||||
33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = "<group>"; };
|
||||
33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = "<group>"; };
|
||||
33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = "<group>"; };
|
||||
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = "<group>"; };
|
||||
7C0A6189862111BCAA63B271 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
|
||||
8F992DDDDDA933A327DC365B /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
|
||||
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = "<group>"; };
|
||||
C702E5916917E3066B271F03 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
E8F099538E88718D3391B642 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
33CC10EA2044A3C60003C045 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
0C27A898F19849756B2961F2 /* Pods_Runner.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
33BA886A226E78AF003329D5 /* Configs */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
33E5194F232828860026EE4D /* AppInfo.xcconfig */,
|
||||
9740EEB21CF90195004384FC /* Debug.xcconfig */,
|
||||
7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
|
||||
333000ED22D3DE5D00554162 /* Warnings.xcconfig */,
|
||||
);
|
||||
path = Configs;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
33CC10E42044A3C60003C045 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
33FAB671232836740065AC1E /* Runner */,
|
||||
33CEB47122A05771004F2AC0 /* Flutter */,
|
||||
33CC10EE2044A3C60003C045 /* Products */,
|
||||
D73912EC22F37F3D000D13A0 /* Frameworks */,
|
||||
E817C7529977AC9EA3A99B00 /* Pods */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
33CC10EE2044A3C60003C045 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
33CC10ED2044A3C60003C045 /* flowy_editor_example.app */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
33CC11242044D66E0003C045 /* Resources */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
33CC10F22044A3C60003C045 /* Assets.xcassets */,
|
||||
33CC10F42044A3C60003C045 /* MainMenu.xib */,
|
||||
33CC10F72044A3C60003C045 /* Info.plist */,
|
||||
);
|
||||
name = Resources;
|
||||
path = ..;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
33CEB47122A05771004F2AC0 /* Flutter */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */,
|
||||
33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */,
|
||||
33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */,
|
||||
33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */,
|
||||
);
|
||||
path = Flutter;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
33FAB671232836740065AC1E /* Runner */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
33CC10F02044A3C60003C045 /* AppDelegate.swift */,
|
||||
33CC11122044BFA00003C045 /* MainFlutterWindow.swift */,
|
||||
33E51913231747F40026EE4D /* DebugProfile.entitlements */,
|
||||
33E51914231749380026EE4D /* Release.entitlements */,
|
||||
33CC11242044D66E0003C045 /* Resources */,
|
||||
33BA886A226E78AF003329D5 /* Configs */,
|
||||
);
|
||||
path = Runner;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D73912EC22F37F3D000D13A0 /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C702E5916917E3066B271F03 /* Pods_Runner.framework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
E817C7529977AC9EA3A99B00 /* Pods */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
E8F099538E88718D3391B642 /* Pods-Runner.debug.xcconfig */,
|
||||
8F992DDDDDA933A327DC365B /* Pods-Runner.release.xcconfig */,
|
||||
7C0A6189862111BCAA63B271 /* Pods-Runner.profile.xcconfig */,
|
||||
);
|
||||
name = Pods;
|
||||
path = Pods;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
33CC10EC2044A3C60003C045 /* Runner */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */;
|
||||
buildPhases = (
|
||||
0504CFEF98C55A917E5E1B29 /* [CP] Check Pods Manifest.lock */,
|
||||
33CC10E92044A3C60003C045 /* Sources */,
|
||||
33CC10EA2044A3C60003C045 /* Frameworks */,
|
||||
33CC10EB2044A3C60003C045 /* Resources */,
|
||||
33CC110E2044A8840003C045 /* Bundle Framework */,
|
||||
3399D490228B24CF009A79C7 /* ShellScript */,
|
||||
AD8696D5D39F3E86C935FCC3 /* [CP] Embed Pods Frameworks */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
33CC11202044C79F0003C045 /* PBXTargetDependency */,
|
||||
);
|
||||
name = Runner;
|
||||
productName = Runner;
|
||||
productReference = 33CC10ED2044A3C60003C045 /* flowy_editor_example.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
33CC10E52044A3C60003C045 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastSwiftUpdateCheck = 0920;
|
||||
LastUpgradeCheck = 0930;
|
||||
ORGANIZATIONNAME = "";
|
||||
TargetAttributes = {
|
||||
33CC10EC2044A3C60003C045 = {
|
||||
CreatedOnToolsVersion = 9.2;
|
||||
LastSwiftMigration = 1100;
|
||||
ProvisioningStyle = Automatic;
|
||||
SystemCapabilities = {
|
||||
com.apple.Sandbox = {
|
||||
enabled = 1;
|
||||
};
|
||||
};
|
||||
};
|
||||
33CC111A2044C6BA0003C045 = {
|
||||
CreatedOnToolsVersion = 9.2;
|
||||
ProvisioningStyle = Manual;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */;
|
||||
compatibilityVersion = "Xcode 9.3";
|
||||
developmentRegion = en;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
Base,
|
||||
);
|
||||
mainGroup = 33CC10E42044A3C60003C045;
|
||||
productRefGroup = 33CC10EE2044A3C60003C045 /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
33CC10EC2044A3C60003C045 /* Runner */,
|
||||
33CC111A2044C6BA0003C045 /* Flutter Assemble */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
33CC10EB2044A3C60003C045 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */,
|
||||
33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
0504CFEF98C55A917E5E1B29 /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
||||
"${PODS_ROOT}/Manifest.lock",
|
||||
);
|
||||
name = "[CP] Check Pods Manifest.lock";
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
"$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
3399D490228B24CF009A79C7 /* ShellScript */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "echo \"$PRODUCT_NAME.app\" > \"$PROJECT_DIR\"/Flutter/ephemeral/.app_filename && \"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh embed\n";
|
||||
};
|
||||
33CC111E2044C6BF0003C045 /* ShellScript */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
Flutter/ephemeral/FlutterInputs.xcfilelist,
|
||||
);
|
||||
inputPaths = (
|
||||
Flutter/ephemeral/tripwire,
|
||||
);
|
||||
outputFileListPaths = (
|
||||
Flutter/ephemeral/FlutterOutputs.xcfilelist,
|
||||
);
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire";
|
||||
};
|
||||
AD8696D5D39F3E86C935FCC3 /* [CP] Embed Pods Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
||||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
outputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
33CC10E92044A3C60003C045 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */,
|
||||
33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */,
|
||||
335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXTargetDependency section */
|
||||
33CC11202044C79F0003C045 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = 33CC111A2044C6BA0003C045 /* Flutter Assemble */;
|
||||
targetProxy = 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */;
|
||||
};
|
||||
/* End PBXTargetDependency section */
|
||||
|
||||
/* Begin PBXVariantGroup section */
|
||||
33CC10F42044A3C60003C045 /* MainMenu.xib */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
33CC10F52044A3C60003C045 /* Base */,
|
||||
);
|
||||
name = MainMenu.xib;
|
||||
path = Runner;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXVariantGroup section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
338D0CE9231458BD00FA5F75 /* Profile */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CODE_SIGN_IDENTITY = "-";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.11;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = macosx;
|
||||
SWIFT_COMPILATION_MODE = wholemodule;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-O";
|
||||
};
|
||||
name = Profile;
|
||||
};
|
||||
338D0CEA231458BD00FA5F75 /* Profile */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
);
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SWIFT_VERSION = 5.0;
|
||||
};
|
||||
name = Profile;
|
||||
};
|
||||
338D0CEB231458BD00FA5F75 /* Profile */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Profile;
|
||||
};
|
||||
33CC10F92044A3C60003C045 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CODE_SIGN_IDENTITY = "-";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.11;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = macosx;
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
33CC10FA2044A3C60003C045 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CODE_SIGN_IDENTITY = "-";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.11;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = macosx;
|
||||
SWIFT_COMPILATION_MODE = wholemodule;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-O";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
33CC10FC2044A3C60003C045 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
);
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 5.0;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
33CC10FD2044A3C60003C045 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
);
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SWIFT_VERSION = 5.0;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
33CC111C2044C6BA0003C045 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
33CC111D2044C6BA0003C045 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
33CC10F92044A3C60003C045 /* Debug */,
|
||||
33CC10FA2044A3C60003C045 /* Release */,
|
||||
338D0CE9231458BD00FA5F75 /* Profile */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
33CC10FC2044A3C60003C045 /* Debug */,
|
||||
33CC10FD2044A3C60003C045 /* Release */,
|
||||
338D0CEA231458BD00FA5F75 /* Profile */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
33CC111C2044C6BA0003C045 /* Debug */,
|
||||
33CC111D2044C6BA0003C045 /* Release */,
|
||||
338D0CEB231458BD00FA5F75 /* Profile */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 33CC10E52044A3C60003C045 /* Project object */;
|
||||
}
|
||||
-89
@@ -1,89 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1000"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "33CC10EC2044A3C60003C045"
|
||||
BuildableName = "flowy_editor_example.app"
|
||||
BlueprintName = "Runner"
|
||||
ReferencedContainer = "container:Runner.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "33CC10EC2044A3C60003C045"
|
||||
BuildableName = "flowy_editor_example.app"
|
||||
BlueprintName = "Runner"
|
||||
ReferencedContainer = "container:Runner.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "33CC10EC2044A3C60003C045"
|
||||
BuildableName = "flowy_editor_example.app"
|
||||
BlueprintName = "Runner"
|
||||
ReferencedContainer = "container:Runner.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Profile"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "33CC10EC2044A3C60003C045"
|
||||
BuildableName = "flowy_editor_example.app"
|
||||
BlueprintName = "Runner"
|
||||
ReferencedContainer = "container:Runner.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
||||
@@ -1,14 +0,0 @@
|
||||
// Application-level settings for the Runner target.
|
||||
//
|
||||
// This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the
|
||||
// future. If not, the values below would default to using the project name when this becomes a
|
||||
// 'flutter create' template.
|
||||
|
||||
// The application's name. By default this is also the title of the Flutter window.
|
||||
PRODUCT_NAME = flowy_editor_example
|
||||
|
||||
// The application's bundle identifier
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.plugin.flowyEditorExample
|
||||
|
||||
// The copyright displayed in application information
|
||||
PRODUCT_COPYRIGHT = Copyright © 2021 com.plugin. All rights reserved.
|
||||
@@ -1,397 +0,0 @@
|
||||
# Generated by pub
|
||||
# See https://dart.dev/tools/pub/glossary#lockfile
|
||||
packages:
|
||||
async:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: async
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.8.2"
|
||||
boolean_selector:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: boolean_selector
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.0"
|
||||
characters:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: characters
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
charcode:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: charcode
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.3.1"
|
||||
clock:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: clock
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
collection:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: collection
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.15.0"
|
||||
cupertino_icons:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: cupertino_icons
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.2"
|
||||
fake_async:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: fake_async
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
ffi:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: ffi
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.0"
|
||||
file:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: file
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "6.1.0"
|
||||
flowy_editor:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
path: ".."
|
||||
relative: true
|
||||
source: path
|
||||
version: "0.0.1"
|
||||
flowy_log:
|
||||
dependency: transitive
|
||||
description:
|
||||
path: "../../flowy_log"
|
||||
relative: true
|
||||
source: path
|
||||
version: "0.0.1"
|
||||
flutter:
|
||||
dependency: "direct main"
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
flutter_colorpicker:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_colorpicker
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.6.0"
|
||||
flutter_keyboard_visibility:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_keyboard_visibility
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "5.0.1"
|
||||
flutter_keyboard_visibility_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_keyboard_visibility_platform_interface
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.0"
|
||||
flutter_keyboard_visibility_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_keyboard_visibility_web
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.0"
|
||||
flutter_test:
|
||||
dependency: "direct dev"
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
flutter_web_plugins:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
js:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: js
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.6.3"
|
||||
logger:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: logger
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
matcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: matcher
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.12.11"
|
||||
meta:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: meta
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.7.0"
|
||||
nested:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: nested
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.0"
|
||||
path:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.8.0"
|
||||
path_provider:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: path_provider
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.1"
|
||||
path_provider_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_linux
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.0"
|
||||
path_provider_macos:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_macos
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.0"
|
||||
path_provider_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_platform_interface
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.1"
|
||||
path_provider_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_windows
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.1"
|
||||
pedantic:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: pedantic
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.11.1"
|
||||
photo_view:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: photo_view
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.13.0"
|
||||
platform:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: platform
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.0.0"
|
||||
plugin_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: plugin_platform_interface
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.0"
|
||||
process:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: process
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "4.2.1"
|
||||
provider:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: provider
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "5.0.0"
|
||||
quiver:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: quiver
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.0.1"
|
||||
quiver_hashcode:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: quiver_hashcode
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.0"
|
||||
sky_engine:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.99"
|
||||
source_span:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: source_span
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.8.1"
|
||||
stack_trace:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stack_trace
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.10.0"
|
||||
stream_channel:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stream_channel
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.0"
|
||||
string_scanner:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: string_scanner
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
string_validator:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: string_validator
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.3.0"
|
||||
term_glyph:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: term_glyph
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
test_api:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: test_api
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.4.3"
|
||||
tuple:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: tuple
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.0"
|
||||
typed_data:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: typed_data
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.3.0"
|
||||
url_launcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "6.0.3"
|
||||
url_launcher_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_linux
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.0"
|
||||
url_launcher_macos:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_macos
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.0"
|
||||
url_launcher_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_platform_interface
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.2"
|
||||
url_launcher_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_web
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.0"
|
||||
url_launcher_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_windows
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.0"
|
||||
vector_math:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vector_math
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.0"
|
||||
win32:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: win32
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.5"
|
||||
xdg_directories:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: xdg_directories
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.2.0"
|
||||
sdks:
|
||||
dart: ">=2.12.0 <3.0.0"
|
||||
flutter: ">=1.22.0"
|
||||
@@ -1,74 +0,0 @@
|
||||
name: flowy_editor_example
|
||||
description: Demonstrates how to use the flowy_editor plugin.
|
||||
|
||||
# The following line prevents the package from being accidentally published to
|
||||
# pub.dev using `pub publish`. This is preferred for private packages.
|
||||
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
||||
|
||||
environment:
|
||||
sdk: ">=2.7.0 <3.0.0"
|
||||
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
|
||||
file: ^6.1.0
|
||||
path_provider: ^2.0.1
|
||||
provider: ^5.0.0
|
||||
flowy_editor:
|
||||
# When depending on this package from a real application you should use:
|
||||
# flowy_editor: ^x.y.z
|
||||
# See https://dart.dev/tools/pub/dependencies#version-constraints
|
||||
# The example app is bundled with the plugin so we use a path dependency on
|
||||
# the parent directory to use the current plugin's version.
|
||||
path: ../
|
||||
|
||||
# The following adds the Cupertino Icons font to your application.
|
||||
# Use with the CupertinoIcons class for iOS style icons.
|
||||
cupertino_icons: ^1.0.2
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
|
||||
# For information on the generic Dart part of this file, see the
|
||||
# following page: https://dart.dev/tools/pub/pubspec
|
||||
|
||||
# The following section is specific to Flutter.
|
||||
flutter:
|
||||
|
||||
# The following line ensures that the Material Icons font is
|
||||
# included with your application, so that you can use the icons in
|
||||
# the material Icons class.
|
||||
uses-material-design: true
|
||||
|
||||
# To add assets to your application, add an assets section, like this:
|
||||
assets:
|
||||
- assets/
|
||||
# - images/a_dot_ham.jpeg
|
||||
|
||||
# An image asset can refer to one or more resolution-specific "variants", see
|
||||
# https://flutter.dev/assets-and-images/#resolution-aware.
|
||||
|
||||
# For details regarding adding assets from package dependencies, see
|
||||
# https://flutter.dev/assets-and-images/#from-packages
|
||||
|
||||
# To add custom fonts to your application, add a fonts section here,
|
||||
# in this "flutter" section. Each entry in this list should have a
|
||||
# "family" key with the font family name, and a "fonts" key with a
|
||||
# list giving the asset and other descriptors for the font. For
|
||||
# example:
|
||||
# fonts:
|
||||
# - family: Schyler
|
||||
# fonts:
|
||||
# - asset: fonts/Schyler-Regular.ttf
|
||||
# - asset: fonts/Schyler-Italic.ttf
|
||||
# style: italic
|
||||
# - family: Trajan Pro
|
||||
# fonts:
|
||||
# - asset: fonts/TrajanPro.ttf
|
||||
# - asset: fonts/TrajanPro_Bold.ttf
|
||||
# weight: 700
|
||||
#
|
||||
# For details regarding fonts from package dependencies,
|
||||
# see https://flutter.dev/custom-fonts/#from-packages
|
||||
@@ -1,98 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<!--
|
||||
If you are serving your web app in a path other than the root, change the
|
||||
href value below to reflect the base path you are serving from.
|
||||
|
||||
The path provided below has to start and end with a slash "/" in order for
|
||||
it to work correctly.
|
||||
|
||||
Fore more details:
|
||||
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base
|
||||
-->
|
||||
<base href="/">
|
||||
|
||||
<meta charset="UTF-8">
|
||||
<meta content="IE=Edge" http-equiv="X-UA-Compatible">
|
||||
<meta name="description" content="Demonstrates how to use the flowy_editor plugin.">
|
||||
|
||||
<!-- iOS meta tags & icons -->
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black">
|
||||
<meta name="apple-mobile-web-app-title" content="flowy_editor_example">
|
||||
<link rel="apple-touch-icon" href="icons/Icon-192.png">
|
||||
|
||||
<title>flowy_editor_example</title>
|
||||
<link rel="manifest" href="manifest.json">
|
||||
</head>
|
||||
<body>
|
||||
<!-- This script installs service_worker.js to provide PWA functionality to
|
||||
application. For more information, see:
|
||||
https://developers.google.com/web/fundamentals/primers/service-workers -->
|
||||
<script>
|
||||
var serviceWorkerVersion = null;
|
||||
var scriptLoaded = false;
|
||||
function loadMainDartJs() {
|
||||
if (scriptLoaded) {
|
||||
return;
|
||||
}
|
||||
scriptLoaded = true;
|
||||
var scriptTag = document.createElement('script');
|
||||
scriptTag.src = 'main.dart.js';
|
||||
scriptTag.type = 'application/javascript';
|
||||
document.body.append(scriptTag);
|
||||
}
|
||||
|
||||
if ('serviceWorker' in navigator) {
|
||||
// Service workers are supported. Use them.
|
||||
window.addEventListener('load', function () {
|
||||
// Wait for registration to finish before dropping the <script> tag.
|
||||
// Otherwise, the browser will load the script multiple times,
|
||||
// potentially different versions.
|
||||
var serviceWorkerUrl = 'flutter_service_worker.js?v=' + serviceWorkerVersion;
|
||||
navigator.serviceWorker.register(serviceWorkerUrl)
|
||||
.then((reg) => {
|
||||
function waitForActivation(serviceWorker) {
|
||||
serviceWorker.addEventListener('statechange', () => {
|
||||
if (serviceWorker.state == 'activated') {
|
||||
console.log('Installed new service worker.');
|
||||
loadMainDartJs();
|
||||
}
|
||||
});
|
||||
}
|
||||
if (!reg.active && (reg.installing || reg.waiting)) {
|
||||
// No active web worker and we have installed or are installing
|
||||
// one for the first time. Simply wait for it to activate.
|
||||
waitForActivation(reg.installing ?? reg.waiting);
|
||||
} else if (!reg.active.scriptURL.endsWith(serviceWorkerVersion)) {
|
||||
// When the app updates the serviceWorkerVersion changes, so we
|
||||
// need to ask the service worker to update.
|
||||
console.log('New service worker available.');
|
||||
reg.update();
|
||||
waitForActivation(reg.installing);
|
||||
} else {
|
||||
// Existing service worker is still good.
|
||||
console.log('Loading app from service worker.');
|
||||
loadMainDartJs();
|
||||
}
|
||||
});
|
||||
|
||||
// If service worker doesn't succeed in a reasonable amount of time,
|
||||
// fallback to plaint <script> tag.
|
||||
setTimeout(() => {
|
||||
if (!scriptLoaded) {
|
||||
console.warn(
|
||||
'Failed to load app from service worker. Falling back to plain <script> tag.',
|
||||
);
|
||||
loadMainDartJs();
|
||||
}
|
||||
}, 4000);
|
||||
});
|
||||
} else {
|
||||
// Service workers not supported. Just drop the <script> tag.
|
||||
loadMainDartJs();
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,23 +0,0 @@
|
||||
{
|
||||
"name": "flowy_editor_example",
|
||||
"short_name": "flowy_editor_example",
|
||||
"start_url": ".",
|
||||
"display": "standalone",
|
||||
"background_color": "#0175C2",
|
||||
"theme_color": "#0175C2",
|
||||
"description": "Demonstrates how to use the flowy_editor plugin.",
|
||||
"orientation": "portrait-primary",
|
||||
"prefer_related_applications": false,
|
||||
"icons": [
|
||||
{
|
||||
"src": "icons/Icon-192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "icons/Icon-512.png",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png"
|
||||
}
|
||||
]
|
||||
}
|
||||
-15
@@ -1,15 +0,0 @@
|
||||
//
|
||||
// Generated file. Do not edit.
|
||||
//
|
||||
|
||||
#include "generated_plugin_registrant.h"
|
||||
|
||||
#include <flowy_editor/flowy_editor_plugin.h>
|
||||
#include <url_launcher_windows/url_launcher_plugin.h>
|
||||
|
||||
void RegisterPlugins(flutter::PluginRegistry* registry) {
|
||||
FlowyEditorPluginRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("FlowyEditorPlugin"));
|
||||
UrlLauncherPluginRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("UrlLauncherPlugin"));
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
#include "run_loop.h"
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
RunLoop::RunLoop() {}
|
||||
|
||||
RunLoop::~RunLoop() {}
|
||||
|
||||
void RunLoop::Run() {
|
||||
bool keep_running = true;
|
||||
TimePoint next_flutter_event_time = TimePoint::clock::now();
|
||||
while (keep_running) {
|
||||
std::chrono::nanoseconds wait_duration =
|
||||
std::max(std::chrono::nanoseconds(0),
|
||||
next_flutter_event_time - TimePoint::clock::now());
|
||||
::MsgWaitForMultipleObjects(
|
||||
0, nullptr, FALSE, static_cast<DWORD>(wait_duration.count() / 1000),
|
||||
QS_ALLINPUT);
|
||||
bool processed_events = false;
|
||||
MSG message;
|
||||
// All pending Windows messages must be processed; MsgWaitForMultipleObjects
|
||||
// won't return again for items left in the queue after PeekMessage.
|
||||
while (::PeekMessage(&message, nullptr, 0, 0, PM_REMOVE)) {
|
||||
processed_events = true;
|
||||
if (message.message == WM_QUIT) {
|
||||
keep_running = false;
|
||||
break;
|
||||
}
|
||||
::TranslateMessage(&message);
|
||||
::DispatchMessage(&message);
|
||||
// Allow Flutter to process messages each time a Windows message is
|
||||
// processed, to prevent starvation.
|
||||
next_flutter_event_time =
|
||||
std::min(next_flutter_event_time, ProcessFlutterMessages());
|
||||
}
|
||||
// If the PeekMessage loop didn't run, process Flutter messages.
|
||||
if (!processed_events) {
|
||||
next_flutter_event_time =
|
||||
std::min(next_flutter_event_time, ProcessFlutterMessages());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RunLoop::RegisterFlutterInstance(
|
||||
flutter::FlutterEngine* flutter_instance) {
|
||||
flutter_instances_.insert(flutter_instance);
|
||||
}
|
||||
|
||||
void RunLoop::UnregisterFlutterInstance(
|
||||
flutter::FlutterEngine* flutter_instance) {
|
||||
flutter_instances_.erase(flutter_instance);
|
||||
}
|
||||
|
||||
RunLoop::TimePoint RunLoop::ProcessFlutterMessages() {
|
||||
TimePoint next_event_time = TimePoint::max();
|
||||
for (auto instance : flutter_instances_) {
|
||||
std::chrono::nanoseconds wait_duration = instance->ProcessMessages();
|
||||
if (wait_duration != std::chrono::nanoseconds::max()) {
|
||||
next_event_time =
|
||||
std::min(next_event_time, TimePoint::clock::now() + wait_duration);
|
||||
}
|
||||
}
|
||||
return next_event_time;
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
#ifndef RUNNER_RUN_LOOP_H_
|
||||
#define RUNNER_RUN_LOOP_H_
|
||||
|
||||
#include <flutter/flutter_engine.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <set>
|
||||
|
||||
// A runloop that will service events for Flutter instances as well
|
||||
// as native messages.
|
||||
class RunLoop {
|
||||
public:
|
||||
RunLoop();
|
||||
~RunLoop();
|
||||
|
||||
// Prevent copying
|
||||
RunLoop(RunLoop const&) = delete;
|
||||
RunLoop& operator=(RunLoop const&) = delete;
|
||||
|
||||
// Runs the run loop until the application quits.
|
||||
void Run();
|
||||
|
||||
// Registers the given Flutter instance for event servicing.
|
||||
void RegisterFlutterInstance(
|
||||
flutter::FlutterEngine* flutter_instance);
|
||||
|
||||
// Unregisters the given Flutter instance from event servicing.
|
||||
void UnregisterFlutterInstance(
|
||||
flutter::FlutterEngine* flutter_instance);
|
||||
|
||||
private:
|
||||
using TimePoint = std::chrono::steady_clock::time_point;
|
||||
|
||||
// Processes all currently pending messages for registered Flutter instances.
|
||||
TimePoint ProcessFlutterMessages();
|
||||
|
||||
std::set<flutter::FlutterEngine*> flutter_instances_;
|
||||
};
|
||||
|
||||
#endif // RUNNER_RUN_LOOP_H_
|
||||
@@ -1,4 +0,0 @@
|
||||
#import <Flutter/Flutter.h>
|
||||
|
||||
@interface FlowyEditorPlugin : NSObject<FlutterPlugin>
|
||||
@end
|
||||
@@ -1,15 +0,0 @@
|
||||
#import "FlowyEditorPlugin.h"
|
||||
#if __has_include(<flowy_editor/flowy_editor-Swift.h>)
|
||||
#import <flowy_editor/flowy_editor-Swift.h>
|
||||
#else
|
||||
// Support project import fallback if the generated compatibility header
|
||||
// is not copied when this plugin is created as a library.
|
||||
// https://forums.swift.org/t/swift-static-libraries-dont-copy-generated-objective-c-header/19816
|
||||
#import "flowy_editor-Swift.h"
|
||||
#endif
|
||||
|
||||
@implementation FlowyEditorPlugin
|
||||
+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar {
|
||||
[SwiftFlowyEditorPlugin registerWithRegistrar:registrar];
|
||||
}
|
||||
@end
|
||||
@@ -1,23 +0,0 @@
|
||||
#
|
||||
# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html.
|
||||
# Run `pod lib lint flowy_editor.podspec` to validate before publishing.
|
||||
#
|
||||
Pod::Spec.new do |s|
|
||||
s.name = 'flowy_editor'
|
||||
s.version = '0.0.1'
|
||||
s.summary = 'A new flutter plugin project.'
|
||||
s.description = <<-DESC
|
||||
A new flutter plugin project.
|
||||
DESC
|
||||
s.homepage = 'http://example.com'
|
||||
s.license = { :file => '../LICENSE' }
|
||||
s.author = { 'Your Company' => 'email@example.com' }
|
||||
s.source = { :path => '.' }
|
||||
s.source_files = 'Classes/**/*'
|
||||
s.dependency 'Flutter'
|
||||
s.platform = :ios, '8.0'
|
||||
|
||||
# Flutter.framework does not contain a i386 slice.
|
||||
s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386' }
|
||||
s.swift_version = '5.0'
|
||||
end
|
||||
@@ -1,9 +0,0 @@
|
||||
library flowy_editor;
|
||||
|
||||
export 'src/widget/editor.dart';
|
||||
export 'src/widget/builder.dart';
|
||||
export 'src/widget/toolbar.dart';
|
||||
export 'src/widget/flowy_toolbar.dart';
|
||||
export 'src/service/style.dart';
|
||||
export 'src/service/controller.dart';
|
||||
export 'src/model/document/document.dart';
|
||||
@@ -1,44 +0,0 @@
|
||||
import 'dart:async';
|
||||
// In order to *not* need this ignore, consider extracting the "web" version
|
||||
// of your plugin as a separate package, instead of inlining it in the same
|
||||
// package as the core of your plugin.
|
||||
// ignore: avoid_web_libraries_in_flutter
|
||||
import 'dart:html' as html show window;
|
||||
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_web_plugins/flutter_web_plugins.dart';
|
||||
|
||||
/// A web implementation of the FlowyEditor plugin.
|
||||
class FlowyEditorWeb {
|
||||
static void registerWith(Registrar registrar) {
|
||||
final channel = MethodChannel(
|
||||
'flowy_editor',
|
||||
const StandardMethodCodec(),
|
||||
registrar,
|
||||
);
|
||||
|
||||
final pluginInstance = FlowyEditorWeb();
|
||||
channel.setMethodCallHandler(pluginInstance.handleMethodCall);
|
||||
}
|
||||
|
||||
/// Handles method calls over the MethodChannel of this plugin.
|
||||
/// Note: Check the "federated" architecture for a new way of doing this:
|
||||
/// https://flutter.dev/go/federated-plugins
|
||||
Future<dynamic> handleMethodCall(MethodCall call) async {
|
||||
switch (call.method) {
|
||||
case 'getPlatformVersion':
|
||||
return getPlatformVersion();
|
||||
default:
|
||||
throw PlatformException(
|
||||
code: 'Unimplemented',
|
||||
details: 'flowy_editor for web doesn\'t implement \'${call.method}\'',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a [String] containing the version of the platform.
|
||||
Future<String> getPlatformVersion() {
|
||||
final version = html.window.navigator.userAgent;
|
||||
return Future.value(version);
|
||||
}
|
||||
}
|
||||
@@ -1,307 +0,0 @@
|
||||
import 'dart:collection';
|
||||
|
||||
import 'package:quiver/core.dart';
|
||||
|
||||
enum AttributeScope {
|
||||
INLINE, // refer to https://quilljs.com/docs/formats/#inline
|
||||
BLOCK, // refer to https://quilljs.com/docs/formats/#block
|
||||
EMBEDS, // refer to https://quilljs.com/docs/formats/#embeds
|
||||
IGNORE, // attributes that can be ignored
|
||||
}
|
||||
|
||||
class Attribute<T> {
|
||||
Attribute(this.key, this.scope, this.value);
|
||||
|
||||
final String key;
|
||||
final AttributeScope scope;
|
||||
final T value;
|
||||
|
||||
static final Map<String, Attribute> _registry = LinkedHashMap.of({
|
||||
Attribute.bold.key: Attribute.bold,
|
||||
Attribute.italic.key: Attribute.italic,
|
||||
Attribute.small.key: Attribute.small,
|
||||
Attribute.underline.key: Attribute.underline,
|
||||
Attribute.strikeThrough.key: Attribute.strikeThrough,
|
||||
Attribute.font.key: Attribute.font,
|
||||
Attribute.size.key: Attribute.size,
|
||||
Attribute.link.key: Attribute.link,
|
||||
Attribute.color.key: Attribute.color,
|
||||
Attribute.background.key: Attribute.background,
|
||||
Attribute.placeholder.key: Attribute.placeholder,
|
||||
Attribute.header.key: Attribute.header,
|
||||
Attribute.align.key: Attribute.align,
|
||||
Attribute.list.key: Attribute.list,
|
||||
Attribute.codeBlock.key: Attribute.codeBlock,
|
||||
Attribute.quoteBlock.key: Attribute.quoteBlock,
|
||||
Attribute.indent.key: Attribute.indent,
|
||||
Attribute.width.key: Attribute.width,
|
||||
Attribute.height.key: Attribute.height,
|
||||
Attribute.style.key: Attribute.style,
|
||||
Attribute.token.key: Attribute.token,
|
||||
});
|
||||
|
||||
static final BoldAttribute bold = BoldAttribute();
|
||||
|
||||
static final ItalicAttribute italic = ItalicAttribute();
|
||||
|
||||
static final SmallAttribute small = SmallAttribute();
|
||||
|
||||
static final UnderlineAttribute underline = UnderlineAttribute();
|
||||
|
||||
static final StrikeThroughAttribute strikeThrough = StrikeThroughAttribute();
|
||||
|
||||
static final FontAttribute font = FontAttribute(null);
|
||||
|
||||
static final SizeAttribute size = SizeAttribute(null);
|
||||
|
||||
static final LinkAttribute link = LinkAttribute(null);
|
||||
|
||||
static final ColorAttribute color = ColorAttribute(null);
|
||||
|
||||
static final BackgroundAttribute background = BackgroundAttribute(null);
|
||||
|
||||
static final PlaceholderAttribute placeholder = PlaceholderAttribute();
|
||||
|
||||
static final HeaderAttribute header = HeaderAttribute();
|
||||
|
||||
static final IndentAttribute indent = IndentAttribute();
|
||||
|
||||
static final AlignAttribute align = AlignAttribute(null);
|
||||
|
||||
static final ListAttribute list = ListAttribute(null);
|
||||
|
||||
static final CodeBlockAttribute codeBlock = CodeBlockAttribute();
|
||||
|
||||
static final QuoteBlockAttribute quoteBlock = QuoteBlockAttribute();
|
||||
|
||||
static final WidthAttribute width = WidthAttribute(null);
|
||||
|
||||
static final HeightAttribute height = HeightAttribute(null);
|
||||
|
||||
static final StyleAttribute style = StyleAttribute(null);
|
||||
|
||||
static final TokenAttribute token = TokenAttribute('');
|
||||
|
||||
static final Set<String> inlineKeys = {
|
||||
Attribute.bold.key,
|
||||
Attribute.italic.key,
|
||||
Attribute.small.key,
|
||||
Attribute.underline.key,
|
||||
Attribute.strikeThrough.key,
|
||||
Attribute.link.key,
|
||||
Attribute.color.key,
|
||||
Attribute.background.key,
|
||||
Attribute.placeholder.key,
|
||||
};
|
||||
|
||||
static final Set<String> blockKeys = LinkedHashSet.of({
|
||||
Attribute.header.key,
|
||||
Attribute.align.key,
|
||||
Attribute.list.key,
|
||||
Attribute.codeBlock.key,
|
||||
Attribute.quoteBlock.key,
|
||||
Attribute.indent.key,
|
||||
});
|
||||
|
||||
static final Set<String> blockKeysExceptHeader = LinkedHashSet.of({
|
||||
Attribute.list.key,
|
||||
Attribute.align.key,
|
||||
Attribute.codeBlock.key,
|
||||
Attribute.quoteBlock.key,
|
||||
Attribute.indent.key,
|
||||
});
|
||||
|
||||
static final Set<String> exclusiveBlockKeys = LinkedHashSet.of({
|
||||
Attribute.header.key,
|
||||
Attribute.list.key,
|
||||
Attribute.codeBlock.key,
|
||||
Attribute.quoteBlock.key,
|
||||
});
|
||||
|
||||
static Attribute<int?> get h1 => HeaderAttribute(level: 1);
|
||||
|
||||
static Attribute<int?> get h2 => HeaderAttribute(level: 2);
|
||||
|
||||
static Attribute<int?> get h3 => HeaderAttribute(level: 3);
|
||||
|
||||
// "attributes":{"align":"left"}
|
||||
static Attribute<String?> get leftAlignment => AlignAttribute('left');
|
||||
|
||||
// "attributes":{"align":"center"}
|
||||
static Attribute<String?> get centerAlignment => AlignAttribute('center');
|
||||
|
||||
// "attributes":{"align":"right"}
|
||||
static Attribute<String?> get rightAlignment => AlignAttribute('right');
|
||||
|
||||
// "attributes":{"align":"justify"}
|
||||
static Attribute<String?> get justifyAlignment => AlignAttribute('justify');
|
||||
|
||||
// "attributes":{"list":"bullet"}
|
||||
static Attribute<String?> get bullet => ListAttribute('bullet');
|
||||
|
||||
// "attributes":{"list":"ordered"}
|
||||
static Attribute<String?> get ordered => ListAttribute('ordered');
|
||||
|
||||
// "attributes":{"list":"checked"}
|
||||
static Attribute<String?> get checked => ListAttribute('checked');
|
||||
|
||||
// "attributes":{"list":"unchecked"}
|
||||
static Attribute<String?> get unchecked => ListAttribute('unchecked');
|
||||
|
||||
// "attributes":{"indent":1"}
|
||||
static Attribute<int?> get indentL1 => IndentAttribute(level: 1);
|
||||
|
||||
// "attributes":{"indent":2"}
|
||||
static Attribute<int?> get indentL2 => IndentAttribute(level: 2);
|
||||
|
||||
// "attributes":{"indent":3"}
|
||||
static Attribute<int?> get indentL3 => IndentAttribute(level: 3);
|
||||
|
||||
static Attribute<int?> getIndentLevel(int? level) {
|
||||
if (level == 1) {
|
||||
return indentL1;
|
||||
}
|
||||
if (level == 2) {
|
||||
return indentL2;
|
||||
}
|
||||
if (level == 3) {
|
||||
return indentL3;
|
||||
}
|
||||
return IndentAttribute(level: level);
|
||||
}
|
||||
|
||||
bool get isInline => scope == AttributeScope.INLINE;
|
||||
|
||||
bool get isBlockExceptHeader => blockKeysExceptHeader.contains(key);
|
||||
|
||||
Map<String, dynamic> toJson() => <String, dynamic>{key: value};
|
||||
|
||||
static Attribute? fromKeyValue(String key, dynamic value) {
|
||||
final origin = _registry[key];
|
||||
if (origin == null) {
|
||||
return null;
|
||||
}
|
||||
final attribute = clone(origin, value);
|
||||
return attribute;
|
||||
}
|
||||
|
||||
static int getRegistryOrder(Attribute attribute) {
|
||||
var order = 0;
|
||||
for (final attr in _registry.values) {
|
||||
if (attr.key == attribute.key) {
|
||||
break;
|
||||
}
|
||||
order++;
|
||||
}
|
||||
|
||||
return order;
|
||||
}
|
||||
|
||||
static Attribute clone(Attribute origin, dynamic value) {
|
||||
return Attribute(origin.key, origin.scope, value);
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (identical(this, other)) return true;
|
||||
if (other is! Attribute) return false;
|
||||
final typedOther = other;
|
||||
return key == typedOther.key &&
|
||||
scope == typedOther.scope &&
|
||||
value == typedOther.value;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => hash3(key, scope, value);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'Attribute{key: $key, scope: $scope, value: $value}';
|
||||
}
|
||||
}
|
||||
|
||||
class BoldAttribute extends Attribute<bool> {
|
||||
BoldAttribute() : super('bold', AttributeScope.INLINE, true);
|
||||
}
|
||||
|
||||
class ItalicAttribute extends Attribute<bool> {
|
||||
ItalicAttribute() : super('italic', AttributeScope.INLINE, true);
|
||||
}
|
||||
|
||||
class SmallAttribute extends Attribute<bool> {
|
||||
SmallAttribute() : super('small', AttributeScope.INLINE, true);
|
||||
}
|
||||
|
||||
class UnderlineAttribute extends Attribute<bool> {
|
||||
UnderlineAttribute() : super('underline', AttributeScope.INLINE, true);
|
||||
}
|
||||
|
||||
class StrikeThroughAttribute extends Attribute<bool> {
|
||||
StrikeThroughAttribute() : super('strike', AttributeScope.INLINE, true);
|
||||
}
|
||||
|
||||
class FontAttribute extends Attribute<String?> {
|
||||
FontAttribute(String? val) : super('font', AttributeScope.INLINE, val);
|
||||
}
|
||||
|
||||
class SizeAttribute extends Attribute<String?> {
|
||||
SizeAttribute(String? val) : super('size', AttributeScope.INLINE, val);
|
||||
}
|
||||
|
||||
class LinkAttribute extends Attribute<String?> {
|
||||
LinkAttribute(String? val) : super('link', AttributeScope.INLINE, val);
|
||||
}
|
||||
|
||||
class ColorAttribute extends Attribute<String?> {
|
||||
ColorAttribute(String? val) : super('color', AttributeScope.INLINE, val);
|
||||
}
|
||||
|
||||
class BackgroundAttribute extends Attribute<String?> {
|
||||
BackgroundAttribute(String? val)
|
||||
: super('background', AttributeScope.INLINE, val);
|
||||
}
|
||||
|
||||
/// This is custom attribute for hint
|
||||
class PlaceholderAttribute extends Attribute<bool> {
|
||||
PlaceholderAttribute() : super('placeholder', AttributeScope.INLINE, true);
|
||||
}
|
||||
|
||||
class HeaderAttribute extends Attribute<int?> {
|
||||
HeaderAttribute({int? level}) : super('header', AttributeScope.BLOCK, level);
|
||||
}
|
||||
|
||||
class IndentAttribute extends Attribute<int?> {
|
||||
IndentAttribute({int? level}) : super('indent', AttributeScope.BLOCK, level);
|
||||
}
|
||||
|
||||
class AlignAttribute extends Attribute<String?> {
|
||||
AlignAttribute(String? val) : super('align', AttributeScope.BLOCK, val);
|
||||
}
|
||||
|
||||
class ListAttribute extends Attribute<String?> {
|
||||
ListAttribute(String? val) : super('list', AttributeScope.BLOCK, val);
|
||||
}
|
||||
|
||||
class CodeBlockAttribute extends Attribute<bool> {
|
||||
CodeBlockAttribute() : super('code-block', AttributeScope.BLOCK, true);
|
||||
}
|
||||
|
||||
class QuoteBlockAttribute extends Attribute<bool?> {
|
||||
QuoteBlockAttribute() : super('quote_block', AttributeScope.BLOCK, true);
|
||||
}
|
||||
|
||||
class WidthAttribute extends Attribute<String?> {
|
||||
WidthAttribute(String? val) : super('width', AttributeScope.IGNORE, val);
|
||||
}
|
||||
|
||||
class HeightAttribute extends Attribute<String?> {
|
||||
HeightAttribute(String? val) : super('height', AttributeScope.IGNORE, val);
|
||||
}
|
||||
|
||||
class StyleAttribute extends Attribute<String?> {
|
||||
StyleAttribute(String? val) : super('style', AttributeScope.IGNORE, val);
|
||||
}
|
||||
|
||||
class TokenAttribute extends Attribute<String> {
|
||||
TokenAttribute(String val) : super('token', AttributeScope.IGNORE, val);
|
||||
}
|
||||
@@ -1,294 +0,0 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:tuple/tuple.dart';
|
||||
|
||||
import '../quill_delta.dart';
|
||||
import '../heuristic/rule.dart';
|
||||
import '../document/style.dart';
|
||||
import 'history.dart';
|
||||
import 'attribute.dart';
|
||||
import 'node/block.dart';
|
||||
import 'node/container.dart';
|
||||
import 'node/embed.dart';
|
||||
import 'node/line.dart';
|
||||
import 'node/node.dart';
|
||||
import 'package:flowy_log/flowy_log.dart';
|
||||
|
||||
/// The rich text document
|
||||
class Document {
|
||||
Document() : _delta = Delta()..insert('\n') {
|
||||
_loadDocument(_delta);
|
||||
}
|
||||
|
||||
Document.fromJson(List data) : _delta = _transform(Delta.fromJson(data)) {
|
||||
_loadDocument(_delta);
|
||||
}
|
||||
|
||||
Document.fromDelta(Delta delta) : _delta = delta {
|
||||
_loadDocument(delta);
|
||||
}
|
||||
|
||||
/// The root node of the document tree
|
||||
final Root _root = Root();
|
||||
|
||||
Root get root => _root;
|
||||
|
||||
int get length => _root.length;
|
||||
|
||||
Delta _delta;
|
||||
|
||||
Delta toDelta() => Delta.from(_delta);
|
||||
|
||||
final Rules _rules = Rules.getInstance();
|
||||
|
||||
void setCustomRules(List<Rule> customRules) {
|
||||
_rules.setCustomRules(customRules);
|
||||
}
|
||||
|
||||
final StreamController<Tuple3<Delta, Delta, ChangeSource>> _observer =
|
||||
StreamController.broadcast();
|
||||
|
||||
final History _history = History();
|
||||
|
||||
Stream<Tuple3<Delta, Delta, ChangeSource>> get changes => _observer.stream;
|
||||
|
||||
Delta insert(int index, Object? data, {int replaceLength = 0}) {
|
||||
assert(index >= 0);
|
||||
assert(data is String || data is Embeddable);
|
||||
if (data is Embeddable) {
|
||||
data = data.toJson();
|
||||
} else if ((data as String).isEmpty) {
|
||||
return Delta();
|
||||
}
|
||||
|
||||
final delta = _rules.apply(RuleType.INSERT, this, index,
|
||||
data: data, len: replaceLength);
|
||||
compose(delta, ChangeSource.LOCAL);
|
||||
return delta;
|
||||
}
|
||||
|
||||
Delta delete(int index, int len) {
|
||||
assert(index >= 0 && len > 0);
|
||||
final delta = _rules.apply(RuleType.DELETE, this, index, len: len);
|
||||
if (delta.isNotEmpty) {
|
||||
compose(delta, ChangeSource.LOCAL);
|
||||
}
|
||||
return delta;
|
||||
}
|
||||
|
||||
Delta replace(int index, int len, Object? data) {
|
||||
assert(index >= 0);
|
||||
assert(data is String || data is Embeddable);
|
||||
|
||||
final dataIsNotEmpty = (data is String) ? data.isNotEmpty : true;
|
||||
|
||||
assert(dataIsNotEmpty || len > 0);
|
||||
|
||||
var delta = Delta();
|
||||
|
||||
// We have to insert before applying delete rules
|
||||
// Otherwise delete would be operating on stale document snapshot.
|
||||
if (dataIsNotEmpty) {
|
||||
delta = insert(index, data, replaceLength: len);
|
||||
}
|
||||
|
||||
if (len > 0) {
|
||||
final deleteDelta = delete(index, len);
|
||||
delta = delta.compose(deleteDelta);
|
||||
}
|
||||
|
||||
return delta;
|
||||
}
|
||||
|
||||
Delta format(int index, int len, Attribute? attribute) {
|
||||
assert(index >= 0 && len >= 0 && attribute != null);
|
||||
|
||||
var delta = Delta();
|
||||
|
||||
final formatDelta = _rules.apply(RuleType.FORMAT, this, index,
|
||||
len: len, attribute: attribute);
|
||||
if (formatDelta.isNotEmpty) {
|
||||
compose(formatDelta, ChangeSource.LOCAL);
|
||||
delta = delta.compose(formatDelta);
|
||||
}
|
||||
|
||||
return delta;
|
||||
}
|
||||
|
||||
/// Only attributes applied to all characters within this range are
|
||||
/// included in the result.
|
||||
Style collectStyle(int index, int len) {
|
||||
final res = queryChild(index);
|
||||
return (res.node as Line).collectStyle(res.offset, len);
|
||||
}
|
||||
|
||||
/// Returns all styles for any character within the specified text range.
|
||||
List<Style> collectAllStyles(int index, int len) {
|
||||
final res = queryChild(index);
|
||||
return (res.node as Line).collectAllStyles(res.offset, len);
|
||||
}
|
||||
|
||||
ChildQuery queryChild(int offset) {
|
||||
final res = _root.queryChild(offset, true);
|
||||
if (res.node is Line) {
|
||||
return res;
|
||||
}
|
||||
final block = res.node as Block;
|
||||
return block.queryChild(res.offset, true);
|
||||
}
|
||||
|
||||
void compose(Delta delta, ChangeSource changeSource) {
|
||||
assert(!_observer.isClosed);
|
||||
delta.trim();
|
||||
assert(delta.isNotEmpty);
|
||||
|
||||
var offset = 0;
|
||||
delta = _transform(delta);
|
||||
final originalDelta = toDelta();
|
||||
for (final op in delta.toList()) {
|
||||
final style =
|
||||
op.attributes != null ? Style.fromJson(op.attributes) : null;
|
||||
|
||||
if (op.isInsert) {
|
||||
_root.insert(offset, _normalize(op.data), style);
|
||||
} else if (op.isDelete) {
|
||||
_root.delete(offset, op.length);
|
||||
} else if (op.attributes != null) {
|
||||
_root.retain(offset, op.length, style);
|
||||
}
|
||||
|
||||
if (!op.isDelete) {
|
||||
offset += op.length!;
|
||||
}
|
||||
}
|
||||
try {
|
||||
final changeset = delta;
|
||||
|
||||
_delta = _delta.compose(delta);
|
||||
} catch (e) {
|
||||
throw '_delta compose failed';
|
||||
}
|
||||
|
||||
if (_delta != _root.toDelta()) {
|
||||
throw 'Compose failed';
|
||||
}
|
||||
final change = Tuple3(originalDelta, delta, changeSource);
|
||||
_observer.add(change);
|
||||
_history.handleDocChange(change);
|
||||
}
|
||||
|
||||
Tuple2 undo() {
|
||||
return _history.undo(this);
|
||||
}
|
||||
|
||||
Tuple2 redo() {
|
||||
return _history.redo(this);
|
||||
}
|
||||
|
||||
bool get hasUndo => _history.hasUndo;
|
||||
|
||||
bool get hasRedo => _history.hasRedo;
|
||||
|
||||
static Delta _transform(Delta delta) {
|
||||
final res = Delta();
|
||||
final ops = delta.toList();
|
||||
for (var i = 0; i < ops.length; i++) {
|
||||
final op = ops[i];
|
||||
res.push(op);
|
||||
_autoAppendNewlineAfterEmbeddable(i, ops, op, res, 'video');
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static void _autoAppendNewlineAfterEmbeddable(
|
||||
int i, List<Operation> ops, Operation op, Delta res, String type) {
|
||||
final nextOpIsEmbed = i + 1 < ops.length &&
|
||||
ops[i + 1].isInsert &&
|
||||
ops[i + 1].data is Map &&
|
||||
(ops[i + 1].data as Map).containsKey(type);
|
||||
if (nextOpIsEmbed &&
|
||||
op.data is String &&
|
||||
(op.data as String).isNotEmpty &&
|
||||
!(op.data as String).endsWith('\n')) {
|
||||
res.push(Operation.insert('\n'));
|
||||
}
|
||||
// embed could be image or video
|
||||
final opInsertEmbed =
|
||||
op.isInsert && op.data is Map && (op.data as Map).containsKey(type);
|
||||
final nextOpIsLineBreak = i + 1 < ops.length &&
|
||||
ops[i + 1].isInsert &&
|
||||
ops[i + 1].data is String &&
|
||||
(ops[i + 1].data as String).startsWith('\n');
|
||||
if (opInsertEmbed && (i + 1 == ops.length - 1 || !nextOpIsLineBreak)) {
|
||||
// automatically append '\n' for embeddable
|
||||
res.push(Operation.insert('\n'));
|
||||
}
|
||||
}
|
||||
|
||||
Object _normalize(Object? data) {
|
||||
if (data is String) {
|
||||
return data;
|
||||
}
|
||||
|
||||
if (data is Embeddable) {
|
||||
return data;
|
||||
}
|
||||
return Embeddable.fromJson(data as Map<String, dynamic>);
|
||||
}
|
||||
|
||||
void close() {
|
||||
_observer.close();
|
||||
_history.clear();
|
||||
}
|
||||
|
||||
String toPlainText() => _root.children.map((e) => e.toPlainText()).join();
|
||||
|
||||
void _loadDocument(Delta doc) {
|
||||
if (doc.isEmpty) {
|
||||
throw ArgumentError.value(doc, 'Document Delta cannot be empty.');
|
||||
}
|
||||
|
||||
assert((doc.last.data as String).endsWith('\n'));
|
||||
|
||||
var offset = 0;
|
||||
for (final op in doc.toList()) {
|
||||
if (!op.isInsert) {
|
||||
throw ArgumentError.value(doc,
|
||||
'Document can only contain insert operations but ${op.key} found.');
|
||||
}
|
||||
final style =
|
||||
op.attributes != null ? Style.fromJson(op.attributes) : null;
|
||||
final data = _normalize(op.data);
|
||||
_root.insert(offset, data, style);
|
||||
offset += op.length!;
|
||||
}
|
||||
final node = _root.last;
|
||||
if (node is Line &&
|
||||
node.parent is! Block &&
|
||||
node.style.isEmpty &&
|
||||
_root.childCount > 1) {
|
||||
_root.remove(node);
|
||||
}
|
||||
}
|
||||
|
||||
bool isEmpty() {
|
||||
if (root.children.length != 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final node = root.children.first;
|
||||
if (!node.isLast) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final delta = node.toDelta();
|
||||
return delta.length == 1 &&
|
||||
delta.first.data == '\n' &&
|
||||
delta.first.key == 'insert';
|
||||
}
|
||||
}
|
||||
|
||||
enum ChangeSource {
|
||||
LOCAL,
|
||||
REMOTE,
|
||||
}
|
||||
@@ -1,133 +0,0 @@
|
||||
import 'package:tuple/tuple.dart';
|
||||
|
||||
import '../quill_delta.dart';
|
||||
import 'document.dart';
|
||||
|
||||
class History {
|
||||
History({
|
||||
this.ignoreChange = false,
|
||||
this.minRecordThreshold = 400,
|
||||
this.capacity = 100,
|
||||
this.userOnly = false,
|
||||
this.lastRecorded = 0,
|
||||
});
|
||||
|
||||
final HistoryStack stack = HistoryStack.empty();
|
||||
|
||||
bool get hasUndo => stack.undo.isNotEmpty;
|
||||
|
||||
bool get hasRedo => stack.redo.isNotEmpty;
|
||||
|
||||
/// used for disable redo or undo function
|
||||
bool ignoreChange;
|
||||
|
||||
int lastRecorded;
|
||||
|
||||
/// Collaborative editing's conditions should be true
|
||||
final bool userOnly;
|
||||
|
||||
/// max operation count for undo
|
||||
final int capacity;
|
||||
|
||||
/// record delay
|
||||
final int minRecordThreshold;
|
||||
|
||||
void handleDocChange(Tuple3<Delta, Delta, ChangeSource> change) {
|
||||
if (ignoreChange) return;
|
||||
if (!userOnly || change.item3 == ChangeSource.LOCAL) {
|
||||
record(change.item2, change.item1);
|
||||
} else {
|
||||
transform(change.item2);
|
||||
}
|
||||
}
|
||||
|
||||
void clear() {
|
||||
stack.clear();
|
||||
}
|
||||
|
||||
void record(Delta change, Delta before) {
|
||||
if (change.isEmpty) return;
|
||||
stack.redo.clear();
|
||||
var undoDelta = change.invert(before);
|
||||
final timestamp = DateTime.now().millisecondsSinceEpoch;
|
||||
|
||||
if (stack.undo.isNotEmpty) {
|
||||
final lastDelta = stack.undo.removeLast();
|
||||
undoDelta = undoDelta.compose(lastDelta);
|
||||
} else {
|
||||
lastRecorded = timestamp;
|
||||
}
|
||||
|
||||
if (undoDelta.isEmpty) return;
|
||||
stack.undo.add(undoDelta);
|
||||
|
||||
if (stack.undo.length > capacity) {
|
||||
stack.undo.removeAt(0);
|
||||
}
|
||||
}
|
||||
|
||||
void transform(Delta delta) {
|
||||
transformStack(stack.undo, delta);
|
||||
transformStack(stack.redo, delta);
|
||||
}
|
||||
|
||||
void transformStack(List<Delta> stack, Delta delta) {
|
||||
for (var i = stack.length - 1; i >= 0; i -= 1) {
|
||||
final oldDelta = stack[i];
|
||||
stack[i] = delta.transform(oldDelta, true);
|
||||
delta = oldDelta.transform(delta, false);
|
||||
if (stack[i].length == 0) {
|
||||
stack.removeAt(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Tuple2 undo(Document doc) {
|
||||
return _change(doc, stack.undo, stack.redo);
|
||||
}
|
||||
|
||||
Tuple2 redo(Document doc) {
|
||||
return _change(doc, stack.redo, stack.undo);
|
||||
}
|
||||
|
||||
Tuple2 _change(Document doc, List<Delta> source, List<Delta> target) {
|
||||
if (source.isEmpty) {
|
||||
return const Tuple2(false, 0);
|
||||
}
|
||||
|
||||
final delta = source.removeLast();
|
||||
// look for insert or delete
|
||||
int? len = 0;
|
||||
final ops = delta.toList();
|
||||
for (var i = 0; i < ops.length; i++) {
|
||||
if (ops[i].key == Operation.insertKey) {
|
||||
len = ops[i].length;
|
||||
} else if (ops[i].key == Operation.deleteKey) {
|
||||
len = ops[i].length! * -1;
|
||||
}
|
||||
}
|
||||
final base = Delta.from(doc.toDelta());
|
||||
final inverseDelta = delta.invert(base);
|
||||
target.add(inverseDelta);
|
||||
lastRecorded = 0;
|
||||
ignoreChange = true;
|
||||
doc.compose(delta, ChangeSource.LOCAL);
|
||||
ignoreChange = false;
|
||||
return Tuple2(true, len);
|
||||
}
|
||||
}
|
||||
|
||||
class HistoryStack {
|
||||
HistoryStack.empty()
|
||||
: undo = [],
|
||||
redo = [];
|
||||
|
||||
final List<Delta> undo;
|
||||
|
||||
final List<Delta> redo;
|
||||
|
||||
void clear() {
|
||||
undo.clear();
|
||||
redo.clear();
|
||||
}
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
import '../../quill_delta.dart';
|
||||
import 'container.dart';
|
||||
import 'line.dart';
|
||||
import 'node.dart';
|
||||
|
||||
/// Represents a group of adjacent [Line]s with the same block style.
|
||||
///
|
||||
/// Block elements are:
|
||||
/// - Blockquote
|
||||
/// - Header
|
||||
/// - Indent
|
||||
/// - List
|
||||
/// - Text Alignment
|
||||
/// - Text Direction
|
||||
/// - Code Block
|
||||
class Block extends Container<Line?> {
|
||||
/// Creates new unmounted [Block].
|
||||
@override
|
||||
Node newInstance() => Block();
|
||||
|
||||
@override
|
||||
Line get defaultChild => Line();
|
||||
|
||||
@override
|
||||
Delta toDelta() {
|
||||
return children
|
||||
.map((child) => child.toDelta())
|
||||
.fold(Delta(), (a, b) => a.concat(b));
|
||||
}
|
||||
|
||||
@override
|
||||
void adjust() {
|
||||
if (isEmpty) {
|
||||
final sibling = previous;
|
||||
unlink();
|
||||
if (sibling != null) {
|
||||
sibling.adjust();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
var block = this;
|
||||
final prev = block.previous;
|
||||
// merging it with previous block if style is the same
|
||||
if (!block.isFirst &&
|
||||
block.previous is Block &&
|
||||
prev!.style == block.style) {
|
||||
block
|
||||
..moveChildToNewParent(prev as Container<Node?>?)
|
||||
..unlink();
|
||||
block = prev as Block;
|
||||
}
|
||||
final next = block.next;
|
||||
// merging it with next block if style is the same
|
||||
if (!block.isLast && block.next is Block && next!.style == block.style) {
|
||||
(next as Block).moveChildToNewParent(block);
|
||||
next.unlink();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
final block = style.attributes.toString();
|
||||
final buffer = StringBuffer('§ {$block}\n');
|
||||
for (final child in children) {
|
||||
final tree = child.isLast ? '└' : '├';
|
||||
buffer.write(' $tree $child');
|
||||
if (!child.isLast) buffer.writeln();
|
||||
}
|
||||
return buffer.toString();
|
||||
}
|
||||
}
|
||||
@@ -1,160 +0,0 @@
|
||||
import 'dart:collection';
|
||||
|
||||
import '../style.dart';
|
||||
import 'line.dart';
|
||||
import 'node.dart';
|
||||
import 'leaf.dart';
|
||||
|
||||
/// Container can accommodate other nodes.
|
||||
///
|
||||
/// Delegates insert, retain and delete operations to children nodes. For each
|
||||
/// operation container looks for a child at specified index position and
|
||||
/// forwards operation to that child.
|
||||
///
|
||||
/// Most of the operation handling logic is implemented by [Line] and [Text].
|
||||
abstract class Container<T extends Node?> extends Node {
|
||||
final LinkedList<Node> _children = LinkedList<Node>();
|
||||
|
||||
/// List of children.
|
||||
LinkedList<Node> get children => _children;
|
||||
|
||||
/// Returns total number of child nodes in this container.
|
||||
///
|
||||
/// To get text length of this container see [length].
|
||||
int get childCount => _children.length;
|
||||
|
||||
/// Returns the first child [Node].
|
||||
Node get first => _children.first;
|
||||
|
||||
/// Returns the last child [Node].
|
||||
Node get last => _children.last;
|
||||
|
||||
/// Returns `true` if this container has no child nodes.
|
||||
bool get isEmpty => _children.isEmpty;
|
||||
|
||||
/// Returns `true` if this container has at least 1 child.
|
||||
bool get isNotEmpty => _children.isNotEmpty;
|
||||
|
||||
/// Returns an instance of default child for this container node.
|
||||
///
|
||||
/// Always returns fresh instance.
|
||||
T get defaultChild;
|
||||
|
||||
/// Adds [node] to the end of this container children list.
|
||||
void add(T node) {
|
||||
assert(node?.parent == null);
|
||||
node?.parent = this;
|
||||
_children.add(node as Node);
|
||||
}
|
||||
|
||||
/// Adds [node] to the beginning of this container children list.
|
||||
void addFirst(T node) {
|
||||
assert(node?.parent == null);
|
||||
node?.parent = this;
|
||||
_children.addFirst(node as Node);
|
||||
}
|
||||
|
||||
/// Removes [node] from this container.
|
||||
void remove(T node) {
|
||||
assert(node?.parent == this);
|
||||
node?.parent = null;
|
||||
_children.remove(node as Node);
|
||||
}
|
||||
|
||||
/// Moves children of this node to [newParent].
|
||||
void moveChildToNewParent(Container? newParent) {
|
||||
if (isEmpty) {
|
||||
return;
|
||||
}
|
||||
|
||||
final last = newParent!.isEmpty ? null : newParent.last as T?;
|
||||
while (isNotEmpty) {
|
||||
final child = first as T;
|
||||
child?.unlink();
|
||||
newParent.add(child);
|
||||
}
|
||||
|
||||
/// In case [newParent] already had children we need to make sure
|
||||
/// combined list is optimized.
|
||||
if (last != null) last.adjust();
|
||||
}
|
||||
|
||||
/// Queries the child [Node] at [offset] in this container.
|
||||
///
|
||||
/// The result may contain the found node or `null` if no node is found
|
||||
/// at specified offset.
|
||||
///
|
||||
/// [ChildQuery.offset] is set to relative offset within returned child node
|
||||
/// which points at the same character position in the document as the
|
||||
/// original [offset].
|
||||
ChildQuery queryChild(int offset, bool inclusive) {
|
||||
if (offset < 0 || offset > length) {
|
||||
return ChildQuery(null, 0);
|
||||
}
|
||||
|
||||
for (final node in children) {
|
||||
final len = node.length;
|
||||
if (offset < len || (inclusive && offset == len && node.isLast)) {
|
||||
return ChildQuery(node, offset);
|
||||
}
|
||||
offset -= len;
|
||||
}
|
||||
return ChildQuery(null, 0);
|
||||
}
|
||||
|
||||
@override
|
||||
String toPlainText() => children.map((child) => child.toPlainText()).join();
|
||||
|
||||
/// Content length of this node's children.
|
||||
///
|
||||
/// To get number of children in this node use [childCount].
|
||||
@override
|
||||
int get length => _children.fold(0, (cur, node) => cur + node.length);
|
||||
|
||||
@override
|
||||
void insert(int index, Object data, Style? style) {
|
||||
assert(index == 0 || (index > 0 && index < length));
|
||||
|
||||
if (isNotEmpty) {
|
||||
final child = queryChild(index, false);
|
||||
child.node!.insert(child.offset, data, style);
|
||||
return;
|
||||
}
|
||||
|
||||
// empty
|
||||
assert(index == 0);
|
||||
final node = defaultChild;
|
||||
add(node);
|
||||
node?.insert(index, data, style);
|
||||
}
|
||||
|
||||
@override
|
||||
void retain(int index, int? length, Style? attributes) {
|
||||
assert(isNotEmpty);
|
||||
final child = queryChild(index, false);
|
||||
child.node!.retain(child.offset, length, attributes);
|
||||
}
|
||||
|
||||
@override
|
||||
void delete(int index, int? length) {
|
||||
assert(isNotEmpty);
|
||||
final child = queryChild(index, false);
|
||||
child.node!.delete(child.offset, length);
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() => _children.join('\n');
|
||||
}
|
||||
|
||||
/// Result of a child query in a [Container].
|
||||
class ChildQuery {
|
||||
ChildQuery(this.node, this.offset);
|
||||
|
||||
/// The child node if found, otherwise `null`.
|
||||
final Node? node;
|
||||
|
||||
/// Starting offset within the child [node] which points at the same
|
||||
/// character in the document as the original offset passed to
|
||||
/// [Container.queryChild] method.
|
||||
final int offset;
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
/// An object which can be embedded into a Quill document.
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [BlockEmbed] which represents a block embed.
|
||||
class Embeddable {
|
||||
const Embeddable(this.type, this.data);
|
||||
|
||||
/// The type of this object.
|
||||
final String type;
|
||||
|
||||
/// The data payload of this object.
|
||||
final dynamic data;
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final m = <String, String>{type: data};
|
||||
return m;
|
||||
}
|
||||
|
||||
static Embeddable fromJson(Map<String, dynamic> json) {
|
||||
final m = Map<String, dynamic>.from(json);
|
||||
assert(m.length == 1, 'Embeddable map has one key');
|
||||
|
||||
return BlockEmbed(m.keys.first, m.values.first);
|
||||
}
|
||||
}
|
||||
|
||||
/// An object which occupies an entire line in a document and cannot co-exist
|
||||
/// inline with regular text.
|
||||
///
|
||||
/// There are two built-in embed types supported by Quill documents, however
|
||||
/// the document model itself does not make any assumptions about the types
|
||||
/// of embedded objects and allows users to define their own types.
|
||||
class BlockEmbed extends Embeddable {
|
||||
const BlockEmbed(String type, String data) : super(type, data);
|
||||
|
||||
static const String horizontalRuleType = 'divider';
|
||||
static BlockEmbed horizontalRule = const BlockEmbed(horizontalRuleType, 'hr');
|
||||
|
||||
static const String imageType = 'image';
|
||||
static BlockEmbed image(String imageUrl) => BlockEmbed(imageType, imageUrl);
|
||||
|
||||
static const String videoType = 'video';
|
||||
static BlockEmbed video(String videoUrl) => BlockEmbed(videoType, videoUrl);
|
||||
}
|
||||
@@ -1,251 +0,0 @@
|
||||
import 'dart:math' as math;
|
||||
|
||||
import '../../quill_delta.dart';
|
||||
import '../style.dart';
|
||||
import 'embed.dart';
|
||||
import 'line.dart';
|
||||
import 'node.dart';
|
||||
|
||||
abstract class Leaf extends Node {
|
||||
/// Creates a new [Leaf] with specified [data].
|
||||
factory Leaf(Object data) {
|
||||
if (data is Embeddable) {
|
||||
return Embed(data);
|
||||
}
|
||||
final text = data as String;
|
||||
assert(text.isNotEmpty);
|
||||
return Text(text);
|
||||
}
|
||||
|
||||
Leaf.val(Object val) : _value = val;
|
||||
|
||||
/// Contents of this node, either a String if this is a [Text] or an
|
||||
/// [Embed] if this is an [BlockEmbed].
|
||||
Object get value => _value;
|
||||
Object _value;
|
||||
|
||||
@override
|
||||
void applyStyle(Style value) {
|
||||
assert(value.isInline || value.isIgnored || value.isEmpty,
|
||||
'Unable to apply Style to leaf: $value');
|
||||
super.applyStyle(value);
|
||||
}
|
||||
|
||||
@override
|
||||
Line? get parent => super.parent as Line?;
|
||||
|
||||
@override
|
||||
int get length {
|
||||
if (_value is String) {
|
||||
return (_value as String).length;
|
||||
}
|
||||
// return 1 for embedded object
|
||||
return 1;
|
||||
}
|
||||
|
||||
@override
|
||||
Delta toDelta() {
|
||||
final data =
|
||||
_value is Embeddable ? (_value as Embeddable).toJson() : _value;
|
||||
return Delta()..insert(data, style.toJson());
|
||||
}
|
||||
|
||||
@override
|
||||
void insert(int index, Object data, Style? style) {
|
||||
assert(index >= 0 && index <= length);
|
||||
final node = Leaf(data);
|
||||
if (index < length) {
|
||||
splitAt(index)!.insertBefore(node);
|
||||
} else {
|
||||
insertAfter(node);
|
||||
}
|
||||
node.format(style);
|
||||
}
|
||||
|
||||
@override
|
||||
void retain(int index, int? len, Style? style) {
|
||||
if (style == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final local = math.min(length - index, len!);
|
||||
final remain = len - local;
|
||||
final node = _isolate(index, local);
|
||||
|
||||
if (remain > 0) {
|
||||
assert(node.next != null);
|
||||
node.next!.retain(0, remain, style);
|
||||
}
|
||||
node.format(style);
|
||||
}
|
||||
|
||||
@override
|
||||
void delete(int index, int? len) {
|
||||
assert(index < length);
|
||||
|
||||
final local = math.min(length - index, len!);
|
||||
final target = _isolate(index, local);
|
||||
final prev = target.previous as Leaf?;
|
||||
final next = target.next as Leaf?;
|
||||
target.unlink();
|
||||
|
||||
final remain = len - local;
|
||||
if (remain > 0) {
|
||||
assert(next != null);
|
||||
next!.delete(0, remain);
|
||||
}
|
||||
|
||||
if (prev != null) {
|
||||
prev.adjust();
|
||||
}
|
||||
}
|
||||
|
||||
/// Adjust this text node by merging it with adjacent nodes if they share
|
||||
/// the same style.
|
||||
@override
|
||||
void adjust() {
|
||||
if (this is Embed) {
|
||||
// Embed nodes cannot be merged with text nor other embeds (in fact,
|
||||
// there could be no two adjacent embeds on the same line since an
|
||||
// embed occupies an entire line).
|
||||
return;
|
||||
}
|
||||
|
||||
// This is a text node and it can only be merged with other text nodes.
|
||||
var node = this as Text;
|
||||
|
||||
// Merging it with previous node if style is the same.
|
||||
final prev = node.previous;
|
||||
if (!node.isFirst && prev is Text && prev.style == node.style) {
|
||||
prev._value = prev.value + node.value;
|
||||
node.unlink();
|
||||
node = prev;
|
||||
}
|
||||
|
||||
// Merging it with next node if style is the same.
|
||||
final next = node.next;
|
||||
if (!node.isLast && next is Text && next.style == node.style) {
|
||||
node._value = node.value + next.value;
|
||||
next.unlink();
|
||||
}
|
||||
}
|
||||
|
||||
/// Splits this leaf node at [index] and returns new node.
|
||||
///
|
||||
/// If this is the last node in its list and [index] equals this node's
|
||||
/// length then this method returns `null` as there is nothing left to split.
|
||||
/// If there is another leaf node after this one and [index] equals this
|
||||
/// node's length then the next leaf node is returned.
|
||||
///
|
||||
/// If [index] equals to `0` then this node itself is returned unchanged.
|
||||
///
|
||||
/// In case a new node is actually split from this one, it inherits this
|
||||
/// node's style.
|
||||
Leaf? splitAt(int index) {
|
||||
assert(index >= 0 && index <= length);
|
||||
if (index == 0) {
|
||||
return this;
|
||||
}
|
||||
if (index == length) {
|
||||
return isLast ? null : next as Leaf?;
|
||||
}
|
||||
|
||||
assert(this is Text);
|
||||
final text = _value as String;
|
||||
_value = text.substring(0, index);
|
||||
final split = Leaf(text.substring(index))..applyStyle(style);
|
||||
insertAfter(split);
|
||||
return split;
|
||||
}
|
||||
|
||||
/// Cuts a leaf from [index] to the end of this node and returns new node
|
||||
/// in detached state (e.g. [mounted] returns `false`).
|
||||
///
|
||||
/// Splitting logic is identical to one described in [splitAt], meaning this
|
||||
/// method may return `null`.
|
||||
Leaf? cutAt(int index) {
|
||||
assert(index >= 0 && index <= length);
|
||||
final cut = splitAt(index);
|
||||
cut?.unlink();
|
||||
return cut;
|
||||
}
|
||||
|
||||
/// Formats this node and optimizes it with adjacent leaf nodes if needed.
|
||||
void format(Style? style) {
|
||||
if (style != null && style.isNotEmpty) {
|
||||
applyStyle(style);
|
||||
}
|
||||
adjust();
|
||||
}
|
||||
|
||||
/// Isolates a new leaf starting at [index] with specified [length].
|
||||
///
|
||||
/// Splitting logic is identical to one described in [splitAt], with one
|
||||
/// exception that it is required for [index] to always be less than this
|
||||
/// node's length. As a result this method always returns a [LeafNode]
|
||||
/// instance. Returned node may still be the same as this node
|
||||
/// if provided [index] is `0`.
|
||||
Leaf _isolate(int index, int length) {
|
||||
assert(
|
||||
index >= 0 && index < this.length && (index + length <= this.length));
|
||||
final target = splitAt(index)!..splitAt(length);
|
||||
return target;
|
||||
}
|
||||
}
|
||||
|
||||
/// A span of formatted text within a line in a Quill document.
|
||||
///
|
||||
/// Text is a leaf node of a document tree.
|
||||
///
|
||||
/// Parent of a text node is always a [Line], and as a consequence text
|
||||
/// node's [value] cannot contain any line-break characters.
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [Embed], a leaf node representing an embeddable object.
|
||||
/// * [Line], a node representing a line of text.
|
||||
class Text extends Leaf {
|
||||
Text([String text = ''])
|
||||
: assert(!text.contains('\n')),
|
||||
super.val(text);
|
||||
|
||||
@override
|
||||
Node newInstance() => Text(value);
|
||||
|
||||
@override
|
||||
String get value => _value as String;
|
||||
|
||||
@override
|
||||
String toPlainText() => value;
|
||||
}
|
||||
|
||||
/// An embed node inside of a line in a Quill document.
|
||||
///
|
||||
/// Embed node is a leaf node similar to [Text]. It represents an arbitrary
|
||||
/// piece of non-textual content embedded into a document, such as, image,
|
||||
/// horizontal rule, video, or any other object with defined structure,
|
||||
/// like a tweet, for instance.
|
||||
///
|
||||
/// Embed node's length is always `1` character and it is represented with
|
||||
/// unicode object replacement character in the document text.
|
||||
///
|
||||
/// Any inline style can be applied to an embed, however this does not
|
||||
/// necessarily mean the embed will look according to that style. For instance,
|
||||
/// applying "bold" style to an image gives no effect, while adding a "link" to
|
||||
/// an image actually makes the image react to user's action.
|
||||
class Embed extends Leaf {
|
||||
Embed(Embeddable data) : super.val(data);
|
||||
|
||||
static const kObjectReplacementCharacter = '\uFFFC';
|
||||
|
||||
@override
|
||||
Node newInstance() => throw UnimplementedError();
|
||||
|
||||
@override
|
||||
Embeddable get value => super.value as Embeddable;
|
||||
|
||||
/// // Embed nodes are represented as unicode object replacement character in
|
||||
// plain text.
|
||||
@override
|
||||
String toPlainText() => kObjectReplacementCharacter;
|
||||
}
|
||||
@@ -1,412 +0,0 @@
|
||||
import 'dart:math' as math;
|
||||
import 'package:collection/collection.dart';
|
||||
import '../../quill_delta.dart';
|
||||
import '../attribute.dart';
|
||||
import '../style.dart';
|
||||
import 'block.dart';
|
||||
import 'container.dart';
|
||||
import 'embed.dart';
|
||||
import 'leaf.dart';
|
||||
import 'node.dart';
|
||||
|
||||
/// A line of rich text in a Quill document.
|
||||
///
|
||||
/// Line serves as a container for [Leaf]s, like [Text] and [Embed].
|
||||
///
|
||||
/// When a line contains an embed, it fully occupies the line, no other embeds
|
||||
/// or text nodes are allowed.
|
||||
class Line extends Container<Leaf?> {
|
||||
@override
|
||||
Leaf get defaultChild => Text();
|
||||
|
||||
@override
|
||||
int get length => super.length + 1;
|
||||
|
||||
/// Returns `true` if this line contains an embedded object.
|
||||
bool get hasEmbed {
|
||||
return children.any((child) => child is Embed);
|
||||
}
|
||||
|
||||
/// Returns next [Line] or `null` if this is the last line in the document.
|
||||
Line? get nextLine {
|
||||
if (!isLast) {
|
||||
return next is Block ? (next as Block).first as Line? : next as Line?;
|
||||
}
|
||||
if (parent is! Block) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (parent!.isLast) {
|
||||
return null;
|
||||
}
|
||||
return parent!.next is Block
|
||||
? (parent!.next as Block).first as Line?
|
||||
: parent!.next as Line?;
|
||||
}
|
||||
|
||||
@override
|
||||
Node newInstance() => Line();
|
||||
|
||||
@override
|
||||
Delta toDelta() {
|
||||
final delta = children
|
||||
.map((child) => child.toDelta())
|
||||
.fold(Delta(), (dynamic a, b) => a.concat(b));
|
||||
var attributes = style;
|
||||
if (parent is Block) {
|
||||
final block = parent as Block;
|
||||
attributes = attributes.mergeAll(block.style);
|
||||
}
|
||||
delta.insert('\n', attributes.toJson());
|
||||
return delta;
|
||||
}
|
||||
|
||||
@override
|
||||
String toPlainText() => '${super.toPlainText()}\n';
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
final body = children.join(' → ');
|
||||
final styleString = style.isNotEmpty ? ' $style' : '';
|
||||
return '¶ $body ⏎$styleString';
|
||||
}
|
||||
|
||||
@override
|
||||
void insert(int index, Object data, Style? style) {
|
||||
if (data is Embeddable) {
|
||||
// We do not check whether this line already has any children here as
|
||||
// inserting an embed into a line with other text is acceptable from the
|
||||
// Delta format perspective.
|
||||
// We rely on heuristic rules to ensure that embeds occupy an entire line.
|
||||
_insertSafe(index, data, style);
|
||||
return;
|
||||
}
|
||||
|
||||
final text = data as String;
|
||||
final lineBreak = text.indexOf('\n');
|
||||
if (lineBreak < 0) {
|
||||
_insertSafe(index, text, style);
|
||||
// No need to update line or block format since those attributes can only
|
||||
// be attached to `\n` character and we already know it's not present.
|
||||
return;
|
||||
}
|
||||
|
||||
final prefix = text.substring(0, lineBreak);
|
||||
_insertSafe(index, prefix, style);
|
||||
if (prefix.isNotEmpty) {
|
||||
index += prefix.length;
|
||||
}
|
||||
|
||||
// Next line inherits our format.
|
||||
final nextLine = _getNextLine(index);
|
||||
|
||||
// Reset our format and unwrap from a block if needed.
|
||||
clearStyle();
|
||||
if (parent is Block) {
|
||||
_unwrap();
|
||||
}
|
||||
|
||||
// Now we can apply new format and re-layout.
|
||||
_format(style);
|
||||
|
||||
// Continue with remaining part.
|
||||
final remain = text.substring(lineBreak + 1);
|
||||
nextLine.insert(0, remain, style);
|
||||
}
|
||||
|
||||
@override
|
||||
void retain(int index, int? len, Style? style) {
|
||||
if (style == null) {
|
||||
return;
|
||||
}
|
||||
final thisLength = length;
|
||||
|
||||
final local = math.min(thisLength - index, len!);
|
||||
// If index is at newline character then this is a line/block style update.
|
||||
final isLineFormat = (index + local == thisLength) && local == 1;
|
||||
|
||||
if (isLineFormat) {
|
||||
assert(style.values.every((attr) => attr.scope == AttributeScope.BLOCK),
|
||||
'It is not allowed to apply inline attributes to line itself.');
|
||||
_format(style);
|
||||
} else {
|
||||
// Otherwise forward to children as it's an inline format update.
|
||||
assert(style.values.every((attr) => attr.scope == AttributeScope.INLINE));
|
||||
assert(index + local != thisLength);
|
||||
super.retain(index, local, style);
|
||||
}
|
||||
|
||||
final remain = len - local;
|
||||
if (remain > 0) {
|
||||
assert(nextLine != null);
|
||||
nextLine!.retain(0, remain, style);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void delete(int index, int? len) {
|
||||
final local = math.min(length - index, len!);
|
||||
final isLFDeleted = index + local == length; // Line feed
|
||||
if (isLFDeleted) {
|
||||
// Our newline character deleted with all style information.
|
||||
clearStyle();
|
||||
if (local > 1) {
|
||||
// Exclude newline character from delete range for children.
|
||||
super.delete(index, local - 1);
|
||||
}
|
||||
} else {
|
||||
super.delete(index, local);
|
||||
}
|
||||
|
||||
final remaining = len - local;
|
||||
if (remaining > 0) {
|
||||
assert(nextLine != null);
|
||||
nextLine!.delete(0, remaining);
|
||||
}
|
||||
|
||||
if (isLFDeleted && isNotEmpty) {
|
||||
// Since we lost our line-break and still have child text nodes those must
|
||||
// migrate to the next line.
|
||||
|
||||
// nextLine might have been unmounted since last assert so we need to
|
||||
// check again we still have a line after us.
|
||||
assert(nextLine != null);
|
||||
|
||||
// Move remaining children in this line to the next line so that all
|
||||
// attributes of nextLine are preserved.
|
||||
nextLine!.moveChildToNewParent(this);
|
||||
moveChildToNewParent(nextLine);
|
||||
}
|
||||
|
||||
if (isLFDeleted) {
|
||||
// Now we can remove this line.
|
||||
final block = parent!; // remember reference before un-linking.
|
||||
unlink();
|
||||
block.adjust();
|
||||
}
|
||||
}
|
||||
|
||||
/// Formats this line.
|
||||
void _format(Style? newStyle) {
|
||||
if (newStyle == null || newStyle.isEmpty) {
|
||||
return;
|
||||
}
|
||||
|
||||
applyStyle(newStyle);
|
||||
final blockStyle = newStyle.getBlockExceptHeader();
|
||||
if (blockStyle == null) {
|
||||
return;
|
||||
} // No block-level changes
|
||||
|
||||
if (parent is Block) {
|
||||
final parentStyle = (parent as Block).style.getBlocksExceptHeader();
|
||||
// Ensure that we're only unwrapping the block only if we unset a single
|
||||
// block format in the `parentStyle` and there are no more block formats
|
||||
// left to unset.
|
||||
if (blockStyle.value == null &&
|
||||
parentStyle.containsKey(blockStyle.key) &&
|
||||
parentStyle.length == 1) {
|
||||
_unwrap();
|
||||
} else if (!const MapEquality()
|
||||
.equals(newStyle.getBlocksExceptHeader(), parentStyle)) {
|
||||
_unwrap();
|
||||
// Block style now can contain multiple attributes
|
||||
if (newStyle.attributes.keys
|
||||
.any(Attribute.exclusiveBlockKeys.contains)) {
|
||||
parentStyle.removeWhere(
|
||||
(key, attr) => Attribute.exclusiveBlockKeys.contains(key));
|
||||
}
|
||||
parentStyle.removeWhere(
|
||||
(key, attr) => newStyle?.attributes.keys.contains(key) ?? false);
|
||||
final parentStyleToMerge = Style.attr(parentStyle);
|
||||
newStyle = newStyle.mergeAll(parentStyleToMerge);
|
||||
_applyBlockStyles(newStyle);
|
||||
} // else the same style, no-op.
|
||||
} else if (blockStyle.value != null) {
|
||||
// Only wrap with a new block if this is not an unset
|
||||
_applyBlockStyles(newStyle);
|
||||
}
|
||||
}
|
||||
|
||||
void _applyBlockStyles(Style newStyle) {
|
||||
var block = Block();
|
||||
for (final style in newStyle.getBlocksExceptHeader().values) {
|
||||
block = block..applyAttribute(style);
|
||||
}
|
||||
_wrap(block);
|
||||
block.adjust();
|
||||
}
|
||||
|
||||
/// Wraps this line with new parent [block].
|
||||
///
|
||||
/// This line can not be in a [Block] when this method is called.
|
||||
void _wrap(Block block) {
|
||||
assert(parent != null && parent is! Block);
|
||||
insertAfter(block);
|
||||
unlink();
|
||||
block.add(this);
|
||||
}
|
||||
|
||||
/// Unwraps this line from it's parent [Block].
|
||||
///
|
||||
/// This method asserts if current [parent] of this line is not a [Block].
|
||||
void _unwrap() {
|
||||
if (parent is! Block) {
|
||||
throw ArgumentError('Invalid parent');
|
||||
}
|
||||
final block = parent as Block;
|
||||
|
||||
assert(block.children.contains(this));
|
||||
|
||||
if (isFirst) {
|
||||
unlink();
|
||||
block.insertBefore(this);
|
||||
} else if (isLast) {
|
||||
unlink();
|
||||
block.insertAfter(this);
|
||||
} else {
|
||||
final before = block.clone() as Block;
|
||||
block.insertBefore(before);
|
||||
|
||||
var child = block.first as Line;
|
||||
while (child != this) {
|
||||
child.unlink();
|
||||
before.add(child);
|
||||
child = block.first as Line;
|
||||
}
|
||||
unlink();
|
||||
block.insertBefore(this);
|
||||
}
|
||||
block.adjust();
|
||||
}
|
||||
|
||||
Line _getNextLine(int index) {
|
||||
assert(index == 0 || (index > 0 && index < length));
|
||||
|
||||
final line = clone() as Line;
|
||||
insertAfter(line);
|
||||
if (index == length - 1) {
|
||||
return line;
|
||||
}
|
||||
|
||||
final query = queryChild(index, false);
|
||||
while (!query.node!.isLast) {
|
||||
final next = (last as Leaf)..unlink();
|
||||
line.addFirst(next);
|
||||
}
|
||||
final child = query.node as Leaf;
|
||||
final cut = child.splitAt(query.offset);
|
||||
cut?.unlink();
|
||||
line.addFirst(cut);
|
||||
return line;
|
||||
}
|
||||
|
||||
void _insertSafe(int index, Object data, Style? style) {
|
||||
assert(index == 0 || (index > 0 && index < length));
|
||||
|
||||
if (data is String) {
|
||||
assert(!data.contains('\n'));
|
||||
if (data.isEmpty) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (isEmpty) {
|
||||
final child = Leaf(data);
|
||||
add(child);
|
||||
child.format(style);
|
||||
} else {
|
||||
final result = queryChild(index, true);
|
||||
result.node!.insert(result.offset, data, style);
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns style for specified text range.
|
||||
///
|
||||
/// Only attributes applied to all characters within this range are
|
||||
/// included in the result. Inline and line level attributes are
|
||||
/// handled separately, e.g.:
|
||||
///
|
||||
/// - line attribute X is included in the result only if it exists for
|
||||
/// every line within this range (partially included lines are counted).
|
||||
/// - inline attribute X is included in the result only if it exists
|
||||
/// for every character within this range (line-break characters excluded).
|
||||
Style collectStyle(int offset, int len) {
|
||||
final local = math.min(length - offset, len);
|
||||
var result = Style();
|
||||
final excluded = <Attribute>{};
|
||||
|
||||
void _handle(Style style) {
|
||||
if (result.isEmpty) {
|
||||
excluded.addAll(style.values);
|
||||
} else {
|
||||
for (final attr in result.values) {
|
||||
if (!style.containsKey(attr.key)) {
|
||||
excluded.add(attr);
|
||||
}
|
||||
}
|
||||
}
|
||||
final remaining = style.removeAll(excluded);
|
||||
result = result.removeAll(excluded);
|
||||
result = result.mergeAll(remaining);
|
||||
}
|
||||
|
||||
final data = queryChild(offset, true);
|
||||
var node = data.node as Leaf?;
|
||||
if (node != null) {
|
||||
result = result.mergeAll(node.style);
|
||||
var pos = node.length - data.offset;
|
||||
while (!node!.isLast && pos < local) {
|
||||
node = node.next as Leaf?;
|
||||
_handle(node!.style);
|
||||
pos += node.length;
|
||||
}
|
||||
}
|
||||
|
||||
result = result.mergeAll(style);
|
||||
if (parent is Block) {
|
||||
final block = parent as Block;
|
||||
result = result.mergeAll(block.style);
|
||||
}
|
||||
|
||||
final remaining = len - local;
|
||||
if (remaining > 0) {
|
||||
final rest = nextLine!.collectStyle(0, remaining);
|
||||
_handle(rest);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// Returns all styles for any character within the specified text range.
|
||||
List<Style> collectAllStyles(int offset, int len) {
|
||||
final local = math.min(length - offset, len);
|
||||
final result = <Style>[];
|
||||
|
||||
final data = queryChild(offset, true);
|
||||
var node = data.node as Leaf?;
|
||||
if (node != null) {
|
||||
result.add(node.style);
|
||||
var pos = node.length - data.offset;
|
||||
while (!node!.isLast && pos < local) {
|
||||
node = node.next as Leaf?;
|
||||
result.add(node!.style);
|
||||
pos += node.length;
|
||||
}
|
||||
}
|
||||
|
||||
result.add(style);
|
||||
if (parent is Block) {
|
||||
final block = parent as Block;
|
||||
result.add(block.style);
|
||||
}
|
||||
|
||||
final remaining = len - local;
|
||||
if (remaining > 0) {
|
||||
final rest = nextLine!.collectAllStyles(0, remaining);
|
||||
result.addAll(rest);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
Loaded 100 of 2121 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user