Compare commits
1031 Commits
jazz-brows
...
jazz-tools
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8fb1748433 | ||
|
|
c8644bf678 | ||
|
|
269ee94338 | ||
|
|
dae80eeba8 | ||
|
|
ce54667b4d | ||
|
|
5963658e28 | ||
|
|
71c1411bbd | ||
|
|
71b221dc79 | ||
|
|
2d11d448dc | ||
|
|
2d42fc9b34 | ||
|
|
c9bda7e1e3 | ||
|
|
476f2d7eee | ||
|
|
1ba3a2ca34 | ||
|
|
7dd3d005a3 | ||
|
|
2c2dfb52d4 | ||
|
|
d33917fbaa | ||
|
|
f0c73d9cc6 | ||
|
|
d9324a9809 | ||
|
|
f7b5454cc6 | ||
|
|
5de338bdaf | ||
|
|
e67d44d47a | ||
|
|
a310293346 | ||
|
|
716d770258 | ||
|
|
4e85b50e1b | ||
|
|
643297b42e | ||
|
|
261efd99be | ||
|
|
f75f4f9b2d | ||
|
|
a0021f060c | ||
|
|
86bd87e6d0 | ||
|
|
ae55e80801 | ||
|
|
e830caf966 | ||
|
|
2f7240121d | ||
|
|
97699a6d5b | ||
|
|
5f8a2ba8df | ||
|
|
fe06e12b85 | ||
|
|
5b2b16a5c6 | ||
|
|
a966912c8a | ||
|
|
b63b70fb80 | ||
|
|
6b3e02920a | ||
|
|
f566961390 | ||
|
|
265b265365 | ||
|
|
83fc22f39a | ||
|
|
794681a8bb | ||
|
|
899bb0d2a1 | ||
|
|
33cfc4cc25 | ||
|
|
42c60c99fe | ||
|
|
e42518ed29 | ||
|
|
5b7ef3cd89 | ||
|
|
fc02fc0608 | ||
|
|
ceaa555e83 | ||
|
|
03229b2ea9 | ||
|
|
e2737d44b6 | ||
|
|
4b73834883 | ||
|
|
1b3d43d5f4 | ||
|
|
9c9a689879 | ||
|
|
60b5288042 | ||
|
|
2fd88b938c | ||
|
|
d1f955006f | ||
|
|
bb3d5f1f87 | ||
|
|
26ce61ab78 | ||
|
|
1f300114d5 | ||
|
|
da69f812f8 | ||
|
|
0bcbf551ca | ||
|
|
6b3d5b5560 | ||
|
|
d1bdbf5d49 | ||
|
|
621e809fad | ||
|
|
d6600d9322 | ||
|
|
2b08bd77c1 | ||
|
|
c1c6e31711 | ||
|
|
0b16085f3c | ||
|
|
e53db2e96a | ||
|
|
384f0e23c0 | ||
|
|
daaf1789d9 | ||
|
|
1f9e20e753 | ||
|
|
ce9ca54f5c | ||
|
|
67e0968809 | ||
|
|
96a922cceb | ||
|
|
9b22fc74cd | ||
|
|
1bebe3c6c8 | ||
|
|
0a98b826f1 | ||
|
|
e1bd16d08b | ||
|
|
0967c2ee5a | ||
|
|
62a3854c41 | ||
|
|
f22ef4e646 | ||
|
|
6c35d0031d | ||
|
|
7bdb6f4279 | ||
|
|
93f3fb231b | ||
|
|
01d13d5df2 | ||
|
|
944e725b95 | ||
|
|
16024fec8e | ||
|
|
f90414ab95 | ||
|
|
492eecb46a | ||
|
|
51144ec832 | ||
|
|
fcaf4b9c30 | ||
|
|
afae2649f5 | ||
|
|
b5b0284c61 | ||
|
|
bf1475a143 | ||
|
|
e82cb80ca4 | ||
|
|
32c2a617d6 | ||
|
|
d3c2a41c81 | ||
|
|
4b99ff1fe3 | ||
|
|
3ebf8258a0 | ||
|
|
4809d14f6d | ||
|
|
5ae1f33127 | ||
|
|
ca5d84f6a9 | ||
|
|
6e6acc3404 | ||
|
|
b17b7b6481 | ||
|
|
5341646301 | ||
|
|
5416165d28 | ||
|
|
b5a9f681c5 | ||
|
|
7dffc006eb | ||
|
|
cd3cc5b0ab | ||
|
|
ceab75eb4d | ||
|
|
103d1b41f7 | ||
|
|
b87cc6973e | ||
|
|
3d541ca241 | ||
|
|
e72bfec884 | ||
|
|
19c7ad27d9 | ||
|
|
0bc7bfc5cc | ||
|
|
2c8120d46f | ||
|
|
c936c8c611 | ||
|
|
58c6013770 | ||
|
|
3eb3291a97 | ||
|
|
6b659f2df3 | ||
|
|
dcc9c9a5ec | ||
|
|
fe9a244363 | ||
|
|
9440bbc058 | ||
|
|
1c92cc2997 | ||
|
|
33ebbf0bdd | ||
|
|
d630b5bde5 | ||
|
|
8c56445882 | ||
|
|
1c6ae12cd9 | ||
|
|
ac5d20d159 | ||
|
|
21bcaabd5a | ||
|
|
17b4d5b668 | ||
|
|
3cd15862d5 | ||
|
|
b3d1ad7201 | ||
|
|
d87df11795 | ||
|
|
82c2a62b2a | ||
|
|
0a9112506e | ||
|
|
d9c9b5f099 | ||
|
|
fbc29f2f17 | ||
|
|
3915bbbf3c | ||
|
|
0b471c4e89 | ||
|
|
09077d37ef | ||
|
|
afe06b4fa6 | ||
|
|
d89b6e488a | ||
|
|
f6361ee43b | ||
|
|
726dbfb6df | ||
|
|
267f689f10 | ||
|
|
893ad3ae23 | ||
|
|
f5590b1be8 | ||
|
|
17a01f57e8 | ||
|
|
7318d86f52 | ||
|
|
1c8403e87a | ||
|
|
dd747c068a | ||
|
|
1f0f230fe2 | ||
|
|
da655cbff5 | ||
|
|
02f6c6220e | ||
|
|
0755cd198e | ||
|
|
c4a8227b66 | ||
|
|
86f0302233 | ||
|
|
72b5542130 | ||
|
|
5fd9225a54 | ||
|
|
9138d30208 | ||
|
|
a5ece15797 | ||
|
|
9f8877202e | ||
|
|
d190097ed9 | ||
|
|
9841617c66 | ||
|
|
165a6170cd | ||
|
|
5148419df9 | ||
|
|
fc0ecb0968 | ||
|
|
802b5a3060 | ||
|
|
e47af262b3 | ||
|
|
688a4850a4 | ||
|
|
e87fef751e | ||
|
|
8f714440f8 | ||
|
|
70cd09170e | ||
|
|
e98b610fd0 | ||
|
|
b554983558 | ||
|
|
4c63334299 | ||
|
|
4aef7cdac5 | ||
|
|
76adeb0d53 | ||
|
|
d95dcbe7db | ||
|
|
f9d538f049 | ||
|
|
40c7336c09 | ||
|
|
e0d2723615 | ||
|
|
93e68c62f5 | ||
|
|
dadee9dcc5 | ||
|
|
6724c4bd83 | ||
|
|
1942bd5de4 | ||
|
|
16764f6365 | ||
|
|
b56cfc2e1f | ||
|
|
7091bcf9c0 | ||
|
|
436cbfa095 | ||
|
|
c19a25f928 | ||
|
|
104e664bbb | ||
|
|
f199b451eb | ||
|
|
70bc48458e | ||
|
|
f28b2a6135 | ||
|
|
55b770b7c9 | ||
|
|
e6838dfb98 | ||
|
|
5e34061fdc | ||
|
|
6d9b77195a | ||
|
|
9bf7946ee6 | ||
|
|
acecffaeb2 | ||
|
|
0a98d6aaf2 | ||
|
|
4ea1a63a0a | ||
|
|
41a4c3bc95 | ||
|
|
60d0027f9d | ||
|
|
748c2ff751 | ||
|
|
cc291b590a | ||
|
|
1f144e89bf | ||
|
|
70938b0ab3 | ||
|
|
f2f5b55dbf | ||
|
|
3c3acae803 | ||
|
|
896ee3460f | ||
|
|
9b9bf44e2b | ||
|
|
8e9acb37f8 | ||
|
|
392aa88d95 | ||
|
|
7ce82cd934 | ||
|
|
0c8158b91c | ||
|
|
5a48c9c44c | ||
|
|
25c56146f5 | ||
|
|
8115e194d3 | ||
|
|
c564fbb02e | ||
|
|
12481e14c2 | ||
|
|
fd2d247ff5 | ||
|
|
9e9ea029b2 | ||
|
|
a0da272dcd | ||
|
|
72fbcc3262 | ||
|
|
f4c8cc858b | ||
|
|
0ab4d7a20d | ||
|
|
5c98ff4e4f | ||
|
|
4cbda689c4 | ||
|
|
771b0ed914 | ||
|
|
79913c3136 | ||
|
|
43d3511d15 | ||
|
|
928ef14086 | ||
|
|
048dd7def0 | ||
|
|
51fcb8a44b | ||
|
|
c5888c39f5 | ||
|
|
2defcfae67 | ||
|
|
873b146d15 | ||
|
|
213de11c3b | ||
|
|
2f24d35471 | ||
|
|
42667c81bb | ||
|
|
1b881cc89f | ||
|
|
af295d816a | ||
|
|
fe8d3497c0 | ||
|
|
c2899e94ca | ||
|
|
f4be67e9b6 | ||
|
|
ba9ad295b6 | ||
|
|
9ed5a96ef8 | ||
|
|
4272ea9019 | ||
|
|
9509307ed1 | ||
|
|
be08921bc5 | ||
|
|
77e3c21cbd | ||
|
|
ab1798c7bd | ||
|
|
26ae69a242 | ||
|
|
25be055a51 | ||
|
|
21ad3767b9 | ||
|
|
a9383516c1 | ||
|
|
bffc516c68 | ||
|
|
9e7c0d9887 | ||
|
|
99b44d5780 | ||
|
|
02db5f3b1d | ||
|
|
1949a5fcd9 | ||
|
|
dcd3b022cc | ||
|
|
a7b837c7e1 | ||
|
|
88ebcf58ab | ||
|
|
b173e0884a | ||
|
|
f379a168be | ||
|
|
bde6ac7d45 | ||
|
|
231947c97a | ||
|
|
d1609cdd55 | ||
|
|
d5b57ad1fc | ||
|
|
b71ab3168a | ||
|
|
0c8f6e5039 | ||
|
|
0bf5c53bec | ||
|
|
e7b1550003 | ||
|
|
6a93a1b8a3 | ||
|
|
9f654a2603 | ||
|
|
dbf735d9e1 | ||
|
|
c62abefb66 | ||
|
|
1453869a46 | ||
|
|
f5039cefc1 | ||
|
|
239da90c9f | ||
|
|
972791e7a8 | ||
|
|
6540893caf | ||
|
|
bfc85c4573 | ||
|
|
e9076313ab | ||
|
|
c6afd8ae36 | ||
|
|
370f20d13d | ||
|
|
0c0178764e | ||
|
|
928350b821 | ||
|
|
be3fd9c696 | ||
|
|
269c028df0 | ||
|
|
e4df837138 | ||
|
|
54fe6d93ba | ||
|
|
979689c6d8 | ||
|
|
859a37868f | ||
|
|
57bd32d77e | ||
|
|
f9b3116deb | ||
|
|
352d34979f | ||
|
|
7ff736ace4 | ||
|
|
5bab466fd0 | ||
|
|
329b8c3d6a | ||
|
|
e21cbccd4b | ||
|
|
a66ab7d174 | ||
|
|
78e91f4030 | ||
|
|
7a915c198e | ||
|
|
c9b0420746 | ||
|
|
2303f3e70a | ||
|
|
a7bc9569a3 | ||
|
|
f351ba0fcd | ||
|
|
d3e554f491 | ||
|
|
b5e31456ad | ||
|
|
c0aeb7baf9 | ||
|
|
8a14de10d7 | ||
|
|
b585b39a86 | ||
|
|
42d07ba7b4 | ||
|
|
b81b6ba69b | ||
|
|
1bc1759bb4 | ||
|
|
225bc1f63f | ||
|
|
5d94564f99 | ||
|
|
9633d0187f | ||
|
|
b82ecaa3ca | ||
|
|
111ec8d351 | ||
|
|
512aacdbc2 | ||
|
|
7ad843aa3e | ||
|
|
071128339b | ||
|
|
688ced499d | ||
|
|
ac91c8e7c2 | ||
|
|
c3b303c310 | ||
|
|
fc027a56db | ||
|
|
959a7a3927 | ||
|
|
2548085b59 | ||
|
|
b27bb3e65b | ||
|
|
937284f7e9 | ||
|
|
e999727c70 | ||
|
|
2197766624 | ||
|
|
d1efde468f | ||
|
|
4d4fd0beaa | ||
|
|
2b61e853a7 | ||
|
|
6f79b45544 | ||
|
|
2e1ff99579 | ||
|
|
7361854ee4 | ||
|
|
4a775fada3 | ||
|
|
3fe53a3a4a | ||
|
|
fe37516786 | ||
|
|
4beafb7cf3 | ||
|
|
82a592e08a | ||
|
|
4c6926153a | ||
|
|
c51b088243 | ||
|
|
867cb6b7a5 | ||
|
|
3a1fdd7600 | ||
|
|
3fdbb43b54 | ||
|
|
02969ee89b | ||
|
|
e9b2860e74 | ||
|
|
9b4988a514 | ||
|
|
6327d74f68 | ||
|
|
8aa4b59d49 | ||
|
|
ac782674de | ||
|
|
bedbabdcb4 | ||
|
|
5eb406d54d | ||
|
|
a3be832414 | ||
|
|
7ca8dd960e | ||
|
|
62c8aff73f | ||
|
|
7731109a28 | ||
|
|
0401fcf2a8 | ||
|
|
139a649279 | ||
|
|
9acccb5df2 | ||
|
|
fd90cdb49a | ||
|
|
4a29999c6a | ||
|
|
df487d5335 | ||
|
|
1efe84c691 | ||
|
|
73b99c6c1a | ||
|
|
039b92c839 | ||
|
|
618af5f1e3 | ||
|
|
dfc4286694 | ||
|
|
970ff0d813 | ||
|
|
65eee0ef01 | ||
|
|
eee221f563 | ||
|
|
063553090e | ||
|
|
97f6bcedbd | ||
|
|
7c63e6bb0f | ||
|
|
08aedcf517 | ||
|
|
3e12ee127f | ||
|
|
2283d375ef | ||
|
|
202e763380 | ||
|
|
52bbdb37a9 | ||
|
|
c2c223f22a | ||
|
|
96f743b2f4 | ||
|
|
f5c47feeb6 | ||
|
|
6dffe73bd2 | ||
|
|
6f9ee31179 | ||
|
|
52f324ffc4 | ||
|
|
2d86f53575 | ||
|
|
68cb357a94 | ||
|
|
56ccf9ab9d | ||
|
|
b8b0851433 | ||
|
|
2bbb07b0bf | ||
|
|
4f7bc91502 | ||
|
|
d3053955d8 | ||
|
|
f61a120560 | ||
|
|
2f1307a0ba | ||
|
|
fa15ea56d1 | ||
|
|
1e58ecb3ac | ||
|
|
ceeabfaf89 | ||
|
|
70ce7c5736 | ||
|
|
f40484eca9 | ||
|
|
d581a59aa1 | ||
|
|
0ca09f75c1 | ||
|
|
e8fcd101f2 | ||
|
|
cf43fa7529 | ||
|
|
df1cdda4e8 | ||
|
|
be46042cdc | ||
|
|
6afdb16739 | ||
|
|
7a60d7bb76 | ||
|
|
f8263a8358 | ||
|
|
f6da966922 | ||
|
|
b0b2b85a6f | ||
|
|
8a2ab51543 | ||
|
|
28c19c134f | ||
|
|
0924c9baaa | ||
|
|
8bfaa0a18b | ||
|
|
b2712e18a2 | ||
|
|
66894b63d7 | ||
|
|
147be76399 | ||
|
|
36770bed52 | ||
|
|
466e6c44ee | ||
|
|
5bd8277161 | ||
|
|
b1a05143e3 | ||
|
|
fb761ce66d | ||
|
|
07a6c340dc | ||
|
|
8b4261f7d8 | ||
|
|
0ec917e453 | ||
|
|
6326d0fc45 | ||
|
|
d746b1279a | ||
|
|
0fea904dd0 | ||
|
|
373aef313f | ||
|
|
c09dcdfc76 | ||
|
|
a584590ed8 | ||
|
|
0a830e29a9 | ||
|
|
4402c553b6 | ||
|
|
e76fe343da | ||
|
|
dc183a19b2 | ||
|
|
fef55a4cd6 | ||
|
|
ddef54048f | ||
|
|
a2626a0f38 | ||
|
|
ec579bcaf7 | ||
|
|
8aa2d2a789 | ||
|
|
a39d009b87 | ||
|
|
6b662b0efe | ||
|
|
efff4d0f4f | ||
|
|
ea2b01d8a2 | ||
|
|
e9af90c841 | ||
|
|
2b7c6f5aa7 | ||
|
|
d73a3d9d46 | ||
|
|
8af39077a3 | ||
|
|
54bd487818 | ||
|
|
f01dab5c8f | ||
|
|
a8b3ec7bb0 | ||
|
|
a7f6870048 | ||
|
|
3b294f6994 | ||
|
|
a420b43029 | ||
|
|
a57268de32 | ||
|
|
6b2c4ed280 | ||
|
|
8d4e0027be | ||
|
|
a4141da1b7 | ||
|
|
c9ca5202f9 | ||
|
|
7b50a2e06d | ||
|
|
43dabccb57 | ||
|
|
b6d04f56ef | ||
|
|
628195b678 | ||
|
|
9a5d769717 | ||
|
|
e30a3f66bf | ||
|
|
6327fce933 | ||
|
|
a650da4184 | ||
|
|
6e4a94f6ce | ||
|
|
b73bec64bc | ||
|
|
50ae2f47c2 | ||
|
|
724d8e7f30 | ||
|
|
7b285ab110 | ||
|
|
01ac9b8c4c | ||
|
|
4e2e1ac73e | ||
|
|
94960c1f65 | ||
|
|
b5af58347b | ||
|
|
46a84558c5 | ||
|
|
f93566c045 | ||
|
|
d97ed603a3 | ||
|
|
8d33103182 | ||
|
|
aaa1ff978b | ||
|
|
82655ea7a7 | ||
|
|
8afe3a2e02 | ||
|
|
ae2adcbd15 | ||
|
|
eb0460d330 | ||
|
|
55cb83e6e0 | ||
|
|
6290088fec | ||
|
|
b9c17b37db | ||
|
|
6c76ff8fbf | ||
|
|
3c6a2a6092 | ||
|
|
e8a950e61a | ||
|
|
e2cbf035de | ||
|
|
47599b6307 | ||
|
|
901d0762ee | ||
|
|
d1c1b0c5cc | ||
|
|
cf4ad7285d | ||
|
|
255a947ea6 | ||
|
|
530a263d35 | ||
|
|
2983c7bd58 | ||
|
|
d60e345b4d | ||
|
|
745020b7a8 | ||
|
|
be47d866bc | ||
|
|
ab6328f767 | ||
|
|
e0555debde | ||
|
|
247f4556e7 | ||
|
|
7903c737f4 | ||
|
|
6145da5525 | ||
|
|
fc0a2e77a3 | ||
|
|
334fbbbb7f | ||
|
|
eaac1e6580 | ||
|
|
114898d8a9 | ||
|
|
991aebf7a7 | ||
|
|
cbc3f0cc65 | ||
|
|
29c487e288 | ||
|
|
0b0590a364 | ||
|
|
1eb01997d8 | ||
|
|
0dc8d511a1 | ||
|
|
9b75880b10 | ||
|
|
962213c712 | ||
|
|
427df8fcbb | ||
|
|
98fe72ed42 | ||
|
|
1f5c81c2ea | ||
|
|
c40aad55dc | ||
|
|
fc41aa165b | ||
|
|
dfca5926de | ||
|
|
9815ec61f0 | ||
|
|
fca60d213e | ||
|
|
b4fdab475b | ||
|
|
2b043abffa | ||
|
|
958c122c36 | ||
|
|
5842838371 | ||
|
|
e136e1b696 | ||
|
|
2475a46578 | ||
|
|
41466ea399 | ||
|
|
44f653a64b | ||
|
|
f8437042a6 | ||
|
|
3b91594d10 | ||
|
|
ac88bdcb98 | ||
|
|
30704bcaf7 | ||
|
|
acd908fbc2 | ||
|
|
4e61d1d191 | ||
|
|
db23582b4c | ||
|
|
4b0b6d8a69 | ||
|
|
d450b394fa | ||
|
|
0abc96e400 | ||
|
|
7562354b29 | ||
|
|
6c085a3919 | ||
|
|
6afff848bc | ||
|
|
47059845cc | ||
|
|
a1735a8232 | ||
|
|
1f5750d8c4 | ||
|
|
f756ce26b5 | ||
|
|
84f5bdda74 | ||
|
|
ee7aefa97c | ||
|
|
b0895981ba | ||
|
|
94f636b2ee | ||
|
|
331ab070f6 | ||
|
|
13e73adfb9 | ||
|
|
265a6405af | ||
|
|
9f6079b6c6 | ||
|
|
4033d78fa6 | ||
|
|
83af94c850 | ||
|
|
70fe856713 | ||
|
|
42e4afc42b | ||
|
|
0e6797b222 | ||
|
|
3634eaf8e9 | ||
|
|
58dfda3d0f | ||
|
|
d304b0bcb5 | ||
|
|
44f5a3f5a2 | ||
|
|
ebb3ce1c25 | ||
|
|
a67bba0dcf | ||
|
|
4a72c26e42 | ||
|
|
084cb5936d | ||
|
|
f1552b8262 | ||
|
|
6826ad8e45 | ||
|
|
7c1b757b62 | ||
|
|
326e1734a4 | ||
|
|
0cf027c91b | ||
|
|
e358881b76 | ||
|
|
cee8010918 | ||
|
|
cc877139ef | ||
|
|
56a9b89538 | ||
|
|
199c463e28 | ||
|
|
50e523d19c | ||
|
|
796ea24288 | ||
|
|
c8be86e823 | ||
|
|
41b7054aab | ||
|
|
101adcd024 | ||
|
|
a2854aeec9 | ||
|
|
bdc9aee689 | ||
|
|
2f53ae0ab8 | ||
|
|
f76c05448c | ||
|
|
585e7e8177 | ||
|
|
82d8d1d873 | ||
|
|
2c523c86ff | ||
|
|
6616668d4a | ||
|
|
a4d23d527b | ||
|
|
8a3be85e97 | ||
|
|
1a7f2b7379 | ||
|
|
caac82dffd | ||
|
|
27b48378e5 | ||
|
|
cfd3c3ca5c | ||
|
|
41f26b7a4f | ||
|
|
c57ebb1cea | ||
|
|
259aded5cc | ||
|
|
1f5e091dd7 | ||
|
|
bbb1c44977 | ||
|
|
4327ecbfdf | ||
|
|
114c10bc77 | ||
|
|
cecdf29721 | ||
|
|
bd717fc0d7 | ||
|
|
739fff68b3 | ||
|
|
d49cab0afa | ||
|
|
ffebb4fdaf | ||
|
|
32565f0e53 | ||
|
|
61a5889bea | ||
|
|
82bd3e1ea6 | ||
|
|
b800a6fba2 | ||
|
|
1b6dbfdfff | ||
|
|
061a70f1b3 | ||
|
|
f1c1e0dafd | ||
|
|
c3912fdb37 | ||
|
|
356bfa4860 | ||
|
|
38446668c4 | ||
|
|
e2bb3b8015 | ||
|
|
11dcfd703d | ||
|
|
0b09d23bd1 | ||
|
|
879b726537 | ||
|
|
66bbd03262 | ||
|
|
c09b63698f | ||
|
|
bed7db0a33 | ||
|
|
8ff3e234c1 | ||
|
|
296da5a5c4 | ||
|
|
700a4f1ba1 | ||
|
|
6f6663d825 | ||
|
|
844cdc907f | ||
|
|
9e32d4cb92 | ||
|
|
85dc6ba148 | ||
|
|
16c4d27e00 | ||
|
|
69170fe0e0 | ||
|
|
a646ba54b3 | ||
|
|
45d60fc3c8 | ||
|
|
6f0c399ccd | ||
|
|
40e1ca7cb1 | ||
|
|
80cf21e453 | ||
|
|
48c8a3d219 | ||
|
|
31bb1201fc | ||
|
|
08d1b05607 | ||
|
|
d64a14210d | ||
|
|
7e53d33e9b | ||
|
|
ea2b39cc30 | ||
|
|
6b835f95cf | ||
|
|
a229ae5f70 | ||
|
|
84fdc1d8fd | ||
|
|
9b1d52d183 | ||
|
|
14a8b32522 | ||
|
|
ddc09a0d6b | ||
|
|
3b45a3f2fd | ||
|
|
9034a45da0 | ||
|
|
6247fac6c5 | ||
|
|
a5ceaffb0c | ||
|
|
dcee2f9b4e | ||
|
|
f27a2c541e | ||
|
|
83fdc504ff | ||
|
|
2317a23fd4 | ||
|
|
a34c0675cd | ||
|
|
5a8a62b4a3 | ||
|
|
325a554bd1 | ||
|
|
7422943e83 | ||
|
|
23bfea5861 | ||
|
|
605a54eb11 | ||
|
|
a7aaee51e6 | ||
|
|
4b8983858a | ||
|
|
8a8c4d11e1 | ||
|
|
26994684d7 | ||
|
|
14a5e036a4 | ||
|
|
5b1c1ca522 | ||
|
|
a9c8458c51 | ||
|
|
5f31d6cbe1 | ||
|
|
b774bb345d | ||
|
|
7fd891d7b9 | ||
|
|
27cac4a6d7 | ||
|
|
2b71ef1181 | ||
|
|
ae169c7b3a | ||
|
|
d888c99d9a | ||
|
|
0b54917f19 | ||
|
|
c87b215b75 | ||
|
|
e4ba23cbef | ||
|
|
98c005a6e0 | ||
|
|
477fd8a62d | ||
|
|
90999ee709 | ||
|
|
38065f0cdf | ||
|
|
c77d16cdb3 | ||
|
|
9410084e6a | ||
|
|
8528db4de4 | ||
|
|
e0fe5a20b7 | ||
|
|
e16e4d53d1 | ||
|
|
d904fae506 | ||
|
|
f67c0b3db3 | ||
|
|
283d7c6bf0 | ||
|
|
e67c5838a9 | ||
|
|
0e7a7dbbc0 | ||
|
|
63c69b6b95 | ||
|
|
a141cbc7f7 | ||
|
|
6a5352cf3a | ||
|
|
27762637ee | ||
|
|
03108871e9 | ||
|
|
dcebe34891 | ||
|
|
99d510815f | ||
|
|
928962c08b | ||
|
|
cdadd6db1d | ||
|
|
d45b8ae70b | ||
|
|
445a58c864 | ||
|
|
1895b474ea | ||
|
|
fd02627069 | ||
|
|
827adc991d | ||
|
|
651b69e5af | ||
|
|
277e4d49e8 | ||
|
|
8990ff39a5 | ||
|
|
71e4c97255 | ||
|
|
577e960e28 | ||
|
|
f232f75d40 | ||
|
|
cfa44f32eb | ||
|
|
ef920435e9 | ||
|
|
87d05404dd | ||
|
|
535c460f5a | ||
|
|
e1a7f829b4 | ||
|
|
fa1b302474 | ||
|
|
45f73a774c | ||
|
|
2a9e271dc3 | ||
|
|
3d96d9c829 | ||
|
|
844051405d | ||
|
|
625eff2333 | ||
|
|
59e2871065 | ||
|
|
acdc88fb91 | ||
|
|
05eab4e2a9 | ||
|
|
efcd65ae38 | ||
|
|
f82177b9da | ||
|
|
ad60fa942a | ||
|
|
c1c553bad0 | ||
|
|
5272d3cd2a | ||
|
|
588ea02f63 | ||
|
|
d837811813 | ||
|
|
2b4aba2d1b | ||
|
|
50b4da18d9 | ||
|
|
d18d09e002 | ||
|
|
d983f27bbe | ||
|
|
fcf83b0da4 | ||
|
|
9231e2c22f | ||
|
|
33157ee0ad | ||
|
|
4b964edcaf | ||
|
|
df22f2617e | ||
|
|
ddc69f2268 | ||
|
|
7c62689319 | ||
|
|
280495c533 | ||
|
|
d5c6fbdc3c | ||
|
|
57776a1400 | ||
|
|
156c45aa0e | ||
|
|
2d0dba6bbc | ||
|
|
7241d2ad95 | ||
|
|
4a9eeace00 | ||
|
|
4f9c91f6ff | ||
|
|
a8e1726797 | ||
|
|
a6eeada331 | ||
|
|
3b38a8241c | ||
|
|
c49330c308 | ||
|
|
0c4e27c18d | ||
|
|
d8d273821e | ||
|
|
def0ca81b4 | ||
|
|
7ff13a8f55 | ||
|
|
53fff71f25 | ||
|
|
0e7e53238b | ||
|
|
fcc18e5212 | ||
|
|
5741d7f09c | ||
|
|
766d2c8846 | ||
|
|
70a43d0c39 | ||
|
|
c28a04d09e | ||
|
|
56fe0aa614 | ||
|
|
745e3132ca | ||
|
|
ace1c796b5 | ||
|
|
1556e41895 | ||
|
|
2badb7e706 | ||
|
|
6f5731b86e | ||
|
|
b9214a8ef4 | ||
|
|
c65940fa94 | ||
|
|
74e3c0864a | ||
|
|
1d3a0e8d6c | ||
|
|
e1f2c1936a | ||
|
|
10c139ae97 | ||
|
|
e0cd3a5637 | ||
|
|
cf44258848 | ||
|
|
4db5ec2dd8 | ||
|
|
c3610d3b98 | ||
|
|
4983e57e62 | ||
|
|
5b2fc70ca1 | ||
|
|
0e3a4d2c46 | ||
|
|
53af54570c | ||
|
|
c1be360e3b | ||
|
|
3b4c83088e | ||
|
|
25fd7f39ae | ||
|
|
591d6f1ed8 | ||
|
|
e0b4626c22 | ||
|
|
fbf9dd29db | ||
|
|
ae09b47c33 | ||
|
|
a273a0db58 | ||
|
|
277104ebba | ||
|
|
7eac549606 | ||
|
|
042d03f002 | ||
|
|
434e59d5c4 | ||
|
|
bb20907774 | ||
|
|
282425575f | ||
|
|
8e4cfd08b2 | ||
|
|
66b5f8d4c8 | ||
|
|
9c6ca9e864 | ||
|
|
858386b5b1 | ||
|
|
238e9ab7a0 | ||
|
|
f45af0a5cf | ||
|
|
22af329930 | ||
|
|
c27ac18135 | ||
|
|
8f86d44174 | ||
|
|
4d7555a4ee | ||
|
|
75501a9051 | ||
|
|
fc342306e2 | ||
|
|
8e4a9c7211 | ||
|
|
362284f6b7 | ||
|
|
975c7bc785 | ||
|
|
9a1295d4f6 | ||
|
|
256fdfd0db | ||
|
|
4cf2bf5fef | ||
|
|
cae74bd051 | ||
|
|
05a3786e23 | ||
|
|
0fa051a59d | ||
|
|
1378a1ff68 | ||
|
|
5ad093cb6a | ||
|
|
c114cf4029 | ||
|
|
98407c2314 | ||
|
|
03da7dc994 | ||
|
|
65e14c6176 | ||
|
|
9fa79b3a5f | ||
|
|
c90222d32e | ||
|
|
d084b41929 | ||
|
|
65e78014fa | ||
|
|
d693800eb3 | ||
|
|
12d5c68f98 | ||
|
|
4ab0b1f4b2 | ||
|
|
ec1e359621 | ||
|
|
44fb13ddd7 | ||
|
|
4fd4c5bbed | ||
|
|
9157effdb3 | ||
|
|
a1d31566ed | ||
|
|
dcde3aa811 | ||
|
|
30b2820a8c | ||
|
|
bb561e2650 | ||
|
|
7cdf397a01 | ||
|
|
44116b805b | ||
|
|
e93c27910d | ||
|
|
16428cace4 | ||
|
|
f48dabaa1a | ||
|
|
7ff90cb81e | ||
|
|
3a53cc4c00 | ||
|
|
ea6c50b2b8 | ||
|
|
6d93f7b388 | ||
|
|
ebc0139559 | ||
|
|
01c07e34e4 | ||
|
|
c89b94aa3b | ||
|
|
01e2977a13 | ||
|
|
41354cb2c1 | ||
|
|
530f9d3e11 | ||
|
|
c965c904bc | ||
|
|
a621141d76 | ||
|
|
0e1fbd7dfc | ||
|
|
d527ae2db0 | ||
|
|
b9261aa4c1 | ||
|
|
41dd1fa80b | ||
|
|
27efdf9b8e | ||
|
|
83068b33e9 | ||
|
|
769d9b0517 | ||
|
|
b0ffe5ed7e | ||
|
|
53dabbd955 | ||
|
|
a036a1c58c | ||
|
|
f4f47258eb | ||
|
|
7e605bb1f3 | ||
|
|
c67a0cd3ce | ||
|
|
48e11a243f | ||
|
|
de904698d8 | ||
|
|
7c8180dcb4 | ||
|
|
da3e101c50 | ||
|
|
7605d228f2 | ||
|
|
3063d74ab9 | ||
|
|
2a4e3fc0cd | ||
|
|
7cc6d63d40 | ||
|
|
d574bbc521 | ||
|
|
6388a7272b | ||
|
|
cd358888d8 | ||
|
|
f427f2324b | ||
|
|
d62285ba22 | ||
|
|
04575ff237 | ||
|
|
34a5e17cab | ||
|
|
759a800874 | ||
|
|
c5ca74e2a9 | ||
|
|
0e4a523757 | ||
|
|
733b48ab2d | ||
|
|
4bf6ecce9d | ||
|
|
f7742a0ba1 | ||
|
|
b897e950bb | ||
|
|
69c92ab908 | ||
|
|
10e1612fd4 | ||
|
|
282a2798c7 | ||
|
|
31b89adb03 | ||
|
|
793787bc66 | ||
|
|
17710122af | ||
|
|
1173884769 | ||
|
|
1c40b3fd6d | ||
|
|
2506ac799b | ||
|
|
905ba921b1 | ||
|
|
336b51eac7 | ||
|
|
b71a8dec3d | ||
|
|
1058156953 | ||
|
|
edbc10c892 | ||
|
|
4470d52326 | ||
|
|
b110f00561 | ||
|
|
f3f8baebba | ||
|
|
d330e0e7e6 | ||
|
|
5cf888930f | ||
|
|
9d75d38bbd | ||
|
|
8a45dae3f7 | ||
|
|
6110c82106 | ||
|
|
d0e2041b10 | ||
|
|
edce59d238 | ||
|
|
7f75d852c1 | ||
|
|
2683af7d28 | ||
|
|
4223720010 | ||
|
|
1b4508fea7 | ||
|
|
776fa09279 | ||
|
|
5c200aa60d | ||
|
|
9fc6c5f6c8 | ||
|
|
7e06cd4a77 | ||
|
|
c43191d97b | ||
|
|
5706b5eb81 | ||
|
|
5eed930997 | ||
|
|
35e5e50508 | ||
|
|
e88a3d0712 | ||
|
|
13b64af5b2 | ||
|
|
9804c6a729 | ||
|
|
ea3a69cf53 | ||
|
|
24987fa9ec | ||
|
|
937d415cc2 | ||
|
|
9196154207 | ||
|
|
c907b2aac2 | ||
|
|
b5a9dfa7ec | ||
|
|
113c77b416 | ||
|
|
cad5444400 | ||
|
|
b2b350e4d0 | ||
|
|
80d5d62852 | ||
|
|
527082b108 | ||
|
|
75f8833c1a | ||
|
|
99d1f3f28b | ||
|
|
4066cfe011 | ||
|
|
e5f8b06af1 | ||
|
|
485b5a238d | ||
|
|
c42ee6d6e2 | ||
|
|
1fb2fd0f50 | ||
|
|
0fce4adfc5 | ||
|
|
b59086c808 | ||
|
|
fe91463652 | ||
|
|
b9065db109 | ||
|
|
d13da295ed | ||
|
|
0291389c3b | ||
|
|
f417f518cb | ||
|
|
f69f99a209 | ||
|
|
31c4fd7c07 | ||
|
|
613aadd775 | ||
|
|
0f969b4be4 | ||
|
|
f7ac1015b2 | ||
|
|
63500e17f2 | ||
|
|
d7c5d4a03d | ||
|
|
8384c55cce | ||
|
|
be947d1086 | ||
|
|
3924bb2ede | ||
|
|
2e3003c2fc | ||
|
|
5ec15ba0a2 | ||
|
|
c7ccf5c5d7 | ||
|
|
9e8c81a1a6 | ||
|
|
c563e2547f | ||
|
|
00cb697bc7 | ||
|
|
a6a0560059 | ||
|
|
55fa5977c2 | ||
|
|
8b4bc1bc97 | ||
|
|
df403ccbc6 | ||
|
|
1f490d2aae | ||
|
|
1b766b6369 | ||
|
|
3f54da98f8 | ||
|
|
05b98c0f8b | ||
|
|
928e63620b | ||
|
|
ea9b1eb88e | ||
|
|
83a88252e2 | ||
|
|
7a61c19135 | ||
|
|
a2f87f304c | ||
|
|
f9f24d2ad2 | ||
|
|
ed3197a7fd | ||
|
|
772a88e98f | ||
|
|
e22a7f46ad | ||
|
|
f890f2f460 | ||
|
|
e9c17e12dc | ||
|
|
4b908e3024 | ||
|
|
90fd2b5da0 | ||
|
|
d7b4360f11 | ||
|
|
df7011167c | ||
|
|
28a785acb0 | ||
|
|
3ee557bfbe | ||
|
|
af94255166 | ||
|
|
4a0dea3f75 | ||
|
|
6a42bc9655 | ||
|
|
c6c8a7f6b7 | ||
|
|
133dd0e26d | ||
|
|
815339272f | ||
|
|
9c1f340029 | ||
|
|
b72ea9608d |
@@ -6,40 +6,19 @@
|
|||||||
"fixed": [
|
"fixed": [
|
||||||
[
|
[
|
||||||
"cojson",
|
"cojson",
|
||||||
"cojson-storage",
|
|
||||||
"cojson-storage-indexeddb",
|
"cojson-storage-indexeddb",
|
||||||
"cojson-storage-sqlite",
|
"cojson-storage-sqlite",
|
||||||
"cojson-transport-ws",
|
"cojson-transport-ws",
|
||||||
"jazz-browser",
|
|
||||||
"jazz-auth-clerk",
|
|
||||||
"jazz-auth-betterauth",
|
"jazz-auth-betterauth",
|
||||||
"jazz-betterauth-client-plugin",
|
"jazz-betterauth-client-plugin",
|
||||||
"jazz-betterauth-server-plugin",
|
"jazz-betterauth-server-plugin",
|
||||||
"jazz-react-auth-betterauth",
|
"jazz-react-auth-betterauth",
|
||||||
"jazz-browser-media-images",
|
|
||||||
"jazz-expo",
|
|
||||||
"jazz-inspector",
|
|
||||||
"jazz-inspector-element",
|
|
||||||
"jazz-nodejs",
|
|
||||||
"jazz-react",
|
|
||||||
"jazz-react-core",
|
|
||||||
"jazz-react-auth-clerk",
|
|
||||||
"jazz-react-native-core",
|
|
||||||
"jazz-react-native",
|
|
||||||
"jazz-react-native-media-images",
|
|
||||||
"jazz-richtext-prosemirror",
|
|
||||||
"jazz-richtext-tiptap",
|
|
||||||
"jazz-run",
|
"jazz-run",
|
||||||
"jazz-svelte",
|
|
||||||
"jazz-tools",
|
"jazz-tools",
|
||||||
"jazz-vue"
|
"community-jazz-vue"
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
"access": "public",
|
"access": "public",
|
||||||
"baseBranch": "main",
|
"baseBranch": "main",
|
||||||
"updateInternalDependencies": "patch",
|
"updateInternalDependencies": "minor"
|
||||||
"ignore": [],
|
|
||||||
"___experimentalUnsafeOptions_WILL_CHANGE_IN_PATCH": {
|
|
||||||
"onlyUpdatePeerDependentsWhenOutOfRange": true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
23
.github/pull_request_template.md
vendored
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
# Description
|
||||||
|
<!-- Please include a summary of the change and which issue is fixed -->
|
||||||
|
<!-- Please also include relevant motivation and context -->
|
||||||
|
<!-- Include any links to documentation like RFC’s if necessary -->
|
||||||
|
<!-- Add a link to to relevant preview environments or anything that would simplify visual review process -->
|
||||||
|
<!-- Supplemental screenshots and video are encouraged, but the primary description should be in text -->
|
||||||
|
|
||||||
|
## Manual testing instructions
|
||||||
|
|
||||||
|
<!-- Add any actions required to manually test the changes -->
|
||||||
|
|
||||||
|
## Tests
|
||||||
|
|
||||||
|
- [ ] Tests have been added and/or updated
|
||||||
|
- [ ] Tests have not been updated, because: <!-- Insert reason for not updating tests here -->
|
||||||
|
- [ ] I need help with writing tests
|
||||||
|
|
||||||
|
|
||||||
|
## Checklist
|
||||||
|
|
||||||
|
- [ ] I've updated the part of the docs that are affected the PR changes
|
||||||
|
- [ ] I've generated a changeset, if a version bump is required
|
||||||
|
- [ ] I've updated the jsDoc comments to the public APIs I've modified, or added them when missing
|
||||||
31
.github/workflows/build-examples.yaml
vendored
@@ -1,31 +0,0 @@
|
|||||||
name: Build Examples
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [ "main" ]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build-examples:
|
|
||||||
runs-on: blacksmith-4vcpu-ubuntu-2204
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
example: [
|
|
||||||
"passkey-svelte",
|
|
||||||
"chat-svelte",
|
|
||||||
"file-share-svelte",
|
|
||||||
]
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
submodules: true
|
|
||||||
|
|
||||||
- name: Setup Source Code
|
|
||||||
uses: ./.github/actions/source-code/
|
|
||||||
|
|
||||||
- name: Pnpm Build
|
|
||||||
run: |
|
|
||||||
pnpm install
|
|
||||||
pnpm turbo build;
|
|
||||||
working-directory: ./examples/${{ matrix.example }}
|
|
||||||
16
.github/workflows/code-quality.yml
vendored
@@ -1,21 +1,27 @@
|
|||||||
name: Code quality
|
name: Code quality
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
# For pushes, this lets concurrent runs happen, so each push gets a result.
|
||||||
|
# But for other events (e.g. PRs), we can cancel the previous runs.
|
||||||
|
group: ${{ github.workflow }}-${{ github.event_name == 'push' && github.sha || github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
|
branches:
|
||||||
|
- "main"
|
||||||
pull_request:
|
pull_request:
|
||||||
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
quality:
|
quality:
|
||||||
runs-on: blacksmith-4vcpu-ubuntu-2204
|
runs-on: blacksmith-2vcpu-ubuntu-2404-arm
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
- name: Setup Biome
|
- name: Setup Biome
|
||||||
uses: biomejs/setup-biome@v2
|
uses: biomejs/setup-biome@v2
|
||||||
with:
|
with:
|
||||||
version: 1.9.4
|
version: 2.1.3
|
||||||
- name: Run Biome
|
- name: Run Biome
|
||||||
run: biome ci .
|
run: biome ci .
|
||||||
|
|
||||||
- name: Check Catalog Dependencies
|
|
||||||
run: node scripts/check-catalog-deps.js
|
|
||||||
|
|||||||
9
.github/workflows/e2e-rn-test.yml
vendored
@@ -1,5 +1,11 @@
|
|||||||
name: End-to-End Tests for React Native
|
name: End-to-End Tests for React Native
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
# For pushes, this lets concurrent runs happen, so each push gets a result.
|
||||||
|
# But for other events (e.g. PRs), we can cancel the previous runs.
|
||||||
|
group: ${{ github.workflow }}-${{ github.event_name == 'push' && github.sha || github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
on:
|
on:
|
||||||
pull_request:
|
pull_request:
|
||||||
types: [opened, synchronize, reopened]
|
types: [opened, synchronize, reopened]
|
||||||
@@ -60,7 +66,8 @@ jobs:
|
|||||||
emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none -no-metrics
|
emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none -no-metrics
|
||||||
disable-animations: true
|
disable-animations: true
|
||||||
working-directory: ./examples/chat-rn-expo/
|
working-directory: ./examples/chat-rn-expo/
|
||||||
script: ./test/e2e/run.sh
|
# killall due to this issue: https://github.com/ReactiveCircus/android-emulator-runner/issues/385
|
||||||
|
script: ./test/e2e/run.sh && ( killall -INT crashpad_handler || true )
|
||||||
|
|
||||||
- name: Copy Maestro Output
|
- name: Copy Maestro Output
|
||||||
if: steps.e2e_test.outcome != 'success'
|
if: steps.e2e_test.outcome != 'success'
|
||||||
|
|||||||
8
.github/workflows/jazz-run.yml
vendored
@@ -1,5 +1,11 @@
|
|||||||
name: Jazz Run Tests
|
name: Jazz Run Tests
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
# For pushes, this lets concurrent runs happen, so each push gets a result.
|
||||||
|
# But for other events (e.g. PRs), we can cancel the previous runs.
|
||||||
|
group: ${{ github.workflow }}-${{ github.event_name == 'push' && github.sha || github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: ["main"]
|
branches: ["main"]
|
||||||
@@ -8,7 +14,7 @@ on:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
test:
|
test:
|
||||||
runs-on: blacksmith-4vcpu-ubuntu-2204
|
runs-on: blacksmith-4vcpu-ubuntu-2404
|
||||||
timeout-minutes: 5
|
timeout-minutes: 5
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
|
|||||||
49
.github/workflows/playwright-homepage.yml
vendored
@@ -1,49 +0,0 @@
|
|||||||
name: Playwright Tests
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: ["main"]
|
|
||||||
pull_request:
|
|
||||||
types: [opened, synchronize, reopened]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
test:
|
|
||||||
timeout-minutes: 60
|
|
||||||
runs-on: blacksmith-4vcpu-ubuntu-2204
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
project: ["homepage/homepage"]
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
submodules: true
|
|
||||||
|
|
||||||
- name: Setup Source Code
|
|
||||||
uses: ./.github/actions/source-code/
|
|
||||||
|
|
||||||
- name: Install root dependencies
|
|
||||||
run: pnpm install && pnpm turbo build
|
|
||||||
|
|
||||||
- name: Install project dependencies
|
|
||||||
run: pnpm install
|
|
||||||
working-directory: ./${{ matrix.project }}
|
|
||||||
|
|
||||||
- name: Pnpm Build
|
|
||||||
run: pnpm turbo build
|
|
||||||
working-directory: ./${{ matrix.project }}
|
|
||||||
|
|
||||||
- name: Install Playwright Browsers
|
|
||||||
run: pnpm exec playwright install
|
|
||||||
working-directory: ./${{ matrix.project }}
|
|
||||||
|
|
||||||
- name: Run Playwright tests
|
|
||||||
run: pnpm exec playwright test
|
|
||||||
working-directory: ./${{ matrix.project }}
|
|
||||||
|
|
||||||
- uses: actions/upload-artifact@v4
|
|
||||||
if: failure()
|
|
||||||
with:
|
|
||||||
name: ${{ hashFiles(format('{0}/package.json', matrix.project)) }}-playwright-report
|
|
||||||
path: ./${{ matrix.project }}/playwright-report/
|
|
||||||
retention-days: 30
|
|
||||||
168
.github/workflows/playwright.yml
vendored
@@ -1,5 +1,11 @@
|
|||||||
name: Playwright Tests
|
name: Playwright Tests
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
# For pushes, this lets concurrent runs happen, so each push gets a result.
|
||||||
|
# But for other events (e.g. PRs), we can cancel the previous runs.
|
||||||
|
group: ${{ github.workflow }}-${{ github.event_name == 'push' && github.sha || github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: ["main"]
|
branches: ["main"]
|
||||||
@@ -9,25 +15,11 @@ on:
|
|||||||
jobs:
|
jobs:
|
||||||
test:
|
test:
|
||||||
timeout-minutes: 60
|
timeout-minutes: 60
|
||||||
runs-on: blacksmith-4vcpu-ubuntu-2204
|
runs-on: blacksmith-4vcpu-ubuntu-2404
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
project: [
|
shard: ["1/2", "2/2"]
|
||||||
"tests/e2e",
|
|
||||||
"examples/chat",
|
|
||||||
"examples/clerk",
|
|
||||||
"examples/betterauth",
|
|
||||||
"examples/file-share-svelte",
|
|
||||||
"examples/form",
|
|
||||||
"examples/inspector",
|
|
||||||
"examples/music-player",
|
|
||||||
"examples/organization",
|
|
||||||
"examples/pets",
|
|
||||||
"starters/react-passkey-auth",
|
|
||||||
"starters/svelte-passkey-auth",
|
|
||||||
"packages/jazz-svelte"
|
|
||||||
]
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
@@ -37,25 +29,131 @@ jobs:
|
|||||||
- name: Setup Source Code
|
- name: Setup Source Code
|
||||||
uses: ./.github/actions/source-code/
|
uses: ./.github/actions/source-code/
|
||||||
|
|
||||||
- name: Pnpm Build
|
|
||||||
run: |
|
|
||||||
if [ -f .env.test ]; then
|
|
||||||
cp .env.test .env
|
|
||||||
fi
|
|
||||||
pnpm turbo build
|
|
||||||
working-directory: ./${{ matrix.project }}
|
|
||||||
|
|
||||||
- name: Install Playwright Browsers
|
- name: Install Playwright Browsers
|
||||||
run: pnpm exec playwright install
|
run: pnpm exec playwright install
|
||||||
working-directory: ./${{ matrix.project }}
|
|
||||||
|
|
||||||
- name: Run Playwright tests
|
- name: Run Playwright tests for shard ${{ matrix.shard }}
|
||||||
run: pnpm exec playwright test
|
run: |
|
||||||
working-directory: ./${{ matrix.project }}
|
# Parse shard information (e.g., "1/2" -> shard_num=1, total_shards=2)
|
||||||
|
IFS='/' read -r shard_num total_shards <<< "${{ matrix.shard }}"
|
||||||
- uses: actions/upload-artifact@v4
|
shard_index=$((shard_num - 1)) # Convert to 0-based index
|
||||||
if: failure()
|
|
||||||
with:
|
# Debug: Print parsed values
|
||||||
name: ${{ hashFiles(format('{0}/package.json', matrix.project)) }}-playwright-report
|
echo "Parsed shard_num: $shard_num"
|
||||||
path: ./${{ matrix.project }}/playwright-report/
|
echo "Parsed total_shards: $total_shards"
|
||||||
retention-days: 30
|
echo "Calculated shard_index: $shard_index"
|
||||||
|
|
||||||
|
# Define all projects to test
|
||||||
|
all_projects=(
|
||||||
|
"tests/e2e"
|
||||||
|
"examples/chat"
|
||||||
|
"examples/chat-svelte"
|
||||||
|
"examples/community-clerk-vue"
|
||||||
|
"examples/clerk"
|
||||||
|
"examples/betterauth"
|
||||||
|
"examples/file-share-svelte"
|
||||||
|
"examples/form"
|
||||||
|
"examples/inspector"
|
||||||
|
"examples/music-player"
|
||||||
|
"examples/organization"
|
||||||
|
"examples/server-worker-http"
|
||||||
|
"starters/react-passkey-auth"
|
||||||
|
"starters/svelte-passkey-auth"
|
||||||
|
"tests/jazz-svelte"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Calculate which projects this shard should run
|
||||||
|
shard_projects=()
|
||||||
|
for i in "${!all_projects[@]}"; do
|
||||||
|
if [ $((i % total_shards)) -eq $shard_index ]; then
|
||||||
|
shard_projects+=("${all_projects[i]}")
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Track project results
|
||||||
|
overall_exit_code=0
|
||||||
|
failed_projects=()
|
||||||
|
passed_projects=()
|
||||||
|
|
||||||
|
echo "=== Running tests for shard ${{ matrix.shard }} ==="
|
||||||
|
echo "Projects in this shard:"
|
||||||
|
printf '%s\n' "${shard_projects[@]}"
|
||||||
|
echo
|
||||||
|
|
||||||
|
# Run tests for each project
|
||||||
|
for project in "${shard_projects[@]}"; do
|
||||||
|
echo "=== Testing project: $project ==="
|
||||||
|
|
||||||
|
# Check if project directory exists
|
||||||
|
if [ ! -d "$project" ]; then
|
||||||
|
echo "❌ FAILED: Project directory $project does not exist"
|
||||||
|
failed_projects+=("$project (directory not found)")
|
||||||
|
overall_exit_code=1
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if project has package.json
|
||||||
|
if [ ! -f "$project/package.json" ]; then
|
||||||
|
echo "❌ FAILED: No package.json found in $project"
|
||||||
|
failed_projects+=("$project (no package.json)")
|
||||||
|
overall_exit_code=1
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Build the project
|
||||||
|
echo "🔨 Building $project..."
|
||||||
|
cd "$project"
|
||||||
|
|
||||||
|
if [ -f .env.test ]; then
|
||||||
|
cp .env.test .env
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! pnpm turbo build; then
|
||||||
|
echo "❌ BUILD FAILED: $project"
|
||||||
|
failed_projects+=("$project (build failed)")
|
||||||
|
overall_exit_code=1
|
||||||
|
cd - > /dev/null
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Run Playwright tests
|
||||||
|
echo "🧪 Running Playwright tests for $project..."
|
||||||
|
if ! pnpm exec playwright test; then
|
||||||
|
echo "❌ TESTS FAILED: $project"
|
||||||
|
failed_projects+=("$project (tests failed)")
|
||||||
|
overall_exit_code=1
|
||||||
|
else
|
||||||
|
echo "✅ TESTS PASSED: $project"
|
||||||
|
passed_projects+=("$project")
|
||||||
|
fi
|
||||||
|
|
||||||
|
cd - > /dev/null
|
||||||
|
echo "=== Finished testing $project ==="
|
||||||
|
echo
|
||||||
|
done
|
||||||
|
|
||||||
|
# Print summary report
|
||||||
|
echo "=========================================="
|
||||||
|
echo "📊 TEST SUMMARY FOR SHARD ${{ matrix.shard }}"
|
||||||
|
echo "=========================================="
|
||||||
|
|
||||||
|
if [ ${#passed_projects[@]} -gt 0 ]; then
|
||||||
|
echo "✅ PASSED (${#passed_projects[@]}):"
|
||||||
|
printf ' - %s\n' "${passed_projects[@]}"
|
||||||
|
echo
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ${#failed_projects[@]} -gt 0 ]; then
|
||||||
|
echo "❌ FAILED (${#failed_projects[@]}):"
|
||||||
|
printf ' - %s\n' "${failed_projects[@]}"
|
||||||
|
echo
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
echo "Total projects in shard: ${#shard_projects[@]}"
|
||||||
|
echo "Passed: ${#passed_projects[@]}"
|
||||||
|
echo "Failed: ${#failed_projects[@]}"
|
||||||
|
echo "=========================================="
|
||||||
|
|
||||||
|
# Exit with overall status
|
||||||
|
exit $overall_exit_code
|
||||||
|
|||||||
7
.github/workflows/pre-release.yml
vendored
@@ -1,4 +1,11 @@
|
|||||||
name: Pre-Publish tagged Pull Requests
|
name: Pre-Publish tagged Pull Requests
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
# For pushes, this lets concurrent runs happen, so each push gets a result.
|
||||||
|
# But for other events (e.g. PRs), we can cancel the previous runs.
|
||||||
|
group: ${{ github.workflow }}-${{ github.event_name == 'push' && github.sha || github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
on:
|
on:
|
||||||
pull_request:
|
pull_request:
|
||||||
types: [opened, synchronize, reopened, labeled]
|
types: [opened, synchronize, reopened, labeled]
|
||||||
|
|||||||
2
.github/workflows/release.yml
vendored
@@ -17,7 +17,7 @@ concurrency: ${{ github.workflow }}-${{ github.ref }}
|
|||||||
jobs:
|
jobs:
|
||||||
release:
|
release:
|
||||||
name: Release
|
name: Release
|
||||||
runs-on: blacksmith-4vcpu-ubuntu-2204
|
runs-on: blacksmith-4vcpu-ubuntu-2404
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout Repo
|
- name: Checkout Repo
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|||||||
8
.github/workflows/unit-test.yml
vendored
@@ -1,5 +1,11 @@
|
|||||||
name: Unit Tests
|
name: Unit Tests
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
# For pushes, this lets concurrent runs happen, so each push gets a result.
|
||||||
|
# But for other events (e.g. PRs), we can cancel the previous runs.
|
||||||
|
group: ${{ github.workflow }}-${{ github.event_name == 'push' && github.sha || github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
on:
|
on:
|
||||||
pull_request:
|
pull_request:
|
||||||
types: [opened, synchronize, reopened]
|
types: [opened, synchronize, reopened]
|
||||||
@@ -9,7 +15,7 @@ on:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
unit-tests:
|
unit-tests:
|
||||||
runs-on: blacksmith-4vcpu-ubuntu-2204
|
runs-on: blacksmith-4vcpu-ubuntu-2404
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ You'll need Node.js 22.x installed (we're working on support for 23.x), and pnpm
|
|||||||
4. **Build the packages**:
|
4. **Build the packages**:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
pnpm build
|
pnpm build:packages
|
||||||
```
|
```
|
||||||
|
|
||||||
5. **Run tests** to verify everything is working:
|
5. **Run tests** to verify everything is working:
|
||||||
|
|||||||
72
biome.json
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",
|
"$schema": "https://biomejs.dev/schemas/2.1.3/schema.json",
|
||||||
"vcs": {
|
"vcs": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"clientKind": "git",
|
"clientKind": "git",
|
||||||
@@ -7,39 +7,35 @@
|
|||||||
},
|
},
|
||||||
"files": {
|
"files": {
|
||||||
"ignoreUnknown": false,
|
"ignoreUnknown": false,
|
||||||
"ignore": [
|
"includes": [
|
||||||
"jazz-tools.json",
|
"**",
|
||||||
"**/ios/**",
|
"!**/jazz-tools.json",
|
||||||
"**/android/**",
|
"!**/ios/**",
|
||||||
"packages/jazz-svelte/**",
|
"!**/android/**",
|
||||||
"examples/*svelte*/**",
|
"!**/tests/jazz-svelte/src/**",
|
||||||
"starters/*svelte*/**",
|
"!**/examples/**/*svelte*/**",
|
||||||
"examples/jazz-paper-scissors/src/routeTree.gen.ts",
|
"!**/starters/**/*svelte*/**",
|
||||||
"homepage/homepage/**",
|
"!**/examples/server-worker-inbox/src/routeTree.gen.ts",
|
||||||
"**/package.json"
|
"!**/homepage/homepage/**",
|
||||||
|
"!**/package.json",
|
||||||
|
"!**/*svelte*/**"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"formatter": {
|
"formatter": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"indentStyle": "space"
|
"indentStyle": "space"
|
||||||
},
|
},
|
||||||
"organizeImports": {
|
"assist": { "actions": { "source": { "organizeImports": "off" } } },
|
||||||
"enabled": true
|
|
||||||
},
|
|
||||||
"linter": {
|
"linter": {
|
||||||
"enabled": false,
|
"enabled": false,
|
||||||
"rules": {
|
"rules": {
|
||||||
"recommended": true,
|
"recommended": true,
|
||||||
"correctness": {
|
"correctness": {
|
||||||
|
"useExhaustiveDependencies": "off",
|
||||||
"useImportExtensions": {
|
"useImportExtensions": {
|
||||||
"level": "error",
|
"level": "error",
|
||||||
"options": {
|
"options": {
|
||||||
"suggestedExtensions": {
|
"forceJsExtensions": true
|
||||||
"ts": {
|
|
||||||
"module": "js",
|
|
||||||
"component": "jsx"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -47,16 +43,7 @@
|
|||||||
},
|
},
|
||||||
"overrides": [
|
"overrides": [
|
||||||
{
|
{
|
||||||
"include": ["packages/**/src/**"],
|
"includes": ["packages/community-jazz-vue/src/**"],
|
||||||
"linter": {
|
|
||||||
"enabled": true,
|
|
||||||
"rules": {
|
|
||||||
"recommended": false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"include": ["packages/cojson-storage*/**", "cojson-transport-ws/**"],
|
|
||||||
"linter": {
|
"linter": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"rules": {
|
"rules": {
|
||||||
@@ -65,7 +52,28 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"include": ["**/tests/**"],
|
"includes": ["**/packages/**/src/**"],
|
||||||
|
"linter": {
|
||||||
|
"enabled": true,
|
||||||
|
"rules": {
|
||||||
|
"recommended": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"includes": [
|
||||||
|
"**/packages/cojson/src/storage/**/*/**",
|
||||||
|
"**/cojson-transport-ws/**"
|
||||||
|
],
|
||||||
|
"linter": {
|
||||||
|
"enabled": true,
|
||||||
|
"rules": {
|
||||||
|
"recommended": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"includes": ["**/tests/**"],
|
||||||
"linter": {
|
"linter": {
|
||||||
"rules": {
|
"rules": {
|
||||||
"correctness": {
|
"correctness": {
|
||||||
@@ -75,7 +83,7 @@
|
|||||||
"noNonNullAssertion": "off"
|
"noNonNullAssertion": "off"
|
||||||
},
|
},
|
||||||
"suspicious": {
|
"suspicious": {
|
||||||
"noExplicitAny": "info"
|
"noExplicitAny": "off"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,30 +21,28 @@
|
|||||||
"better-sqlite3": "^11.9.1",
|
"better-sqlite3": "^11.9.1",
|
||||||
"class-variance-authority": "^0.7.1",
|
"class-variance-authority": "^0.7.1",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
|
"jazz-react-auth-betterauth": "workspace:*",
|
||||||
"jazz-betterauth-client-plugin": "workspace:*",
|
"jazz-betterauth-client-plugin": "workspace:*",
|
||||||
"jazz-betterauth-server-plugin": "workspace:*",
|
"jazz-betterauth-server-plugin": "workspace:*",
|
||||||
"jazz-inspector": "workspace:*",
|
|
||||||
"jazz-react": "workspace:*",
|
|
||||||
"jazz-react-auth-betterauth": "workspace:*",
|
|
||||||
"jazz-tools": "workspace:*",
|
"jazz-tools": "workspace:*",
|
||||||
"lucide-react": "^0.510.0",
|
"lucide-react": "^0.510.0",
|
||||||
"next": "15.3.2",
|
"next": "15.3.2",
|
||||||
"react": "^18.0.0",
|
"react": "catalog:react",
|
||||||
"react-dom": "^18.0.0",
|
"react-dom": "catalog:react",
|
||||||
"sonner": "^2.0.3",
|
"sonner": "^2.0.3",
|
||||||
"tailwind-merge": "^3.3.0",
|
"tailwind-merge": "^3.3.0",
|
||||||
"tw-animate-css": "^1.2.5"
|
"tw-animate-css": "^1.2.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@biomejs/biome": "1.9.4",
|
"@biomejs/biome": "catalog:default",
|
||||||
"@playwright/test": "^1.50.1",
|
"@playwright/test": "^1.50.1",
|
||||||
"@tailwindcss/postcss": "^4",
|
"@tailwindcss/postcss": "^4",
|
||||||
"@types/better-sqlite3": "^7.6.12",
|
"@types/better-sqlite3": "^7.6.12",
|
||||||
"@types/node": "^20",
|
"@types/node": "^20",
|
||||||
"@types/react": "^18",
|
"@types/react": "catalog:react",
|
||||||
"@types/react-dom": "^18",
|
"@types/react-dom": "catalog:react",
|
||||||
"react-email": "^4.0.11",
|
"react-email": "^4.0.11",
|
||||||
"tailwindcss": "^4",
|
"tailwindcss": "^4",
|
||||||
"typescript": "^5"
|
"typescript": "catalog:default"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { useAccount } from "jazz-react";
|
|
||||||
import { Account } from "jazz-tools";
|
import { Account } from "jazz-tools";
|
||||||
|
import { useAccount } from "jazz-tools/react";
|
||||||
import {
|
import {
|
||||||
AppWindowMacIcon,
|
AppWindowMacIcon,
|
||||||
FileTextIcon,
|
FileTextIcon,
|
||||||
|
|||||||
@@ -1,21 +1,21 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { JazzProvider } from "jazz-react";
|
|
||||||
import { AuthProvider } from "jazz-react-auth-betterauth";
|
import { AuthProvider } from "jazz-react-auth-betterauth";
|
||||||
|
import { JazzReactProvider } from "jazz-tools/react";
|
||||||
import { type ReactNode, lazy } from "react";
|
import { type ReactNode, lazy } from "react";
|
||||||
|
|
||||||
const JazzDevTools =
|
const JazzDevTools =
|
||||||
process.env.NODE_ENV === "production"
|
process.env.NODE_ENV === "production"
|
||||||
? () => null
|
? () => null
|
||||||
: lazy(() =>
|
: lazy(() =>
|
||||||
import("jazz-inspector").then((res) => ({
|
import("jazz-tools/inspector").then((res) => ({
|
||||||
default: res.JazzInspector,
|
default: res.JazzInspector,
|
||||||
})),
|
})),
|
||||||
);
|
);
|
||||||
|
|
||||||
export function JazzAndAuth({ children }: { children: ReactNode }) {
|
export function JazzAndAuth({ children }: { children: ReactNode }) {
|
||||||
return (
|
return (
|
||||||
<JazzProvider
|
<JazzReactProvider
|
||||||
sync={{
|
sync={{
|
||||||
peer: "wss://cloud.jazz.tools/?key=betterauth-example@garden.co",
|
peer: "wss://cloud.jazz.tools/?key=betterauth-example@garden.co",
|
||||||
}}
|
}}
|
||||||
@@ -28,6 +28,6 @@ export function JazzAndAuth({ children }: { children: ReactNode }) {
|
|||||||
{children}
|
{children}
|
||||||
</AuthProvider>
|
</AuthProvider>
|
||||||
<JazzDevTools />
|
<JazzDevTools />
|
||||||
</JazzProvider>
|
</JazzReactProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { useAccount, useIsAuthenticated } from "jazz-react";
|
|
||||||
import { useAuth } from "jazz-react-auth-betterauth";
|
import { useAuth } from "jazz-react-auth-betterauth";
|
||||||
import { Account } from "jazz-tools";
|
import { Account } from "jazz-tools";
|
||||||
|
import { useAccount, useIsAuthenticated } from "jazz-tools/react";
|
||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { useCallback } from "react";
|
import { useCallback } from "react";
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { useAccount, useIsAuthenticated } from "jazz-react";
|
|
||||||
import { useAuth } from "jazz-react-auth-betterauth";
|
import { useAuth } from "jazz-react-auth-betterauth";
|
||||||
|
import { useAccount, useIsAuthenticated } from "jazz-tools/react";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
|
|||||||
23
examples/chat-rn-expo-clerk/.gitignore
vendored
@@ -1,23 +0,0 @@
|
|||||||
node_modules/
|
|
||||||
.expo/
|
|
||||||
dist/
|
|
||||||
npm-debug.*
|
|
||||||
*.jks
|
|
||||||
*.p8
|
|
||||||
*.p12
|
|
||||||
*.key
|
|
||||||
*.mobileprovision
|
|
||||||
*.orig.*
|
|
||||||
web-build/
|
|
||||||
|
|
||||||
# macOS
|
|
||||||
.DS_Store
|
|
||||||
|
|
||||||
ios
|
|
||||||
android
|
|
||||||
|
|
||||||
# Env
|
|
||||||
.env
|
|
||||||
.env.*
|
|
||||||
!.env.example
|
|
||||||
!.env.test
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
# 🎷 Jazz + Expo + `expo-router` + Clerk Auth
|
|
||||||
|
|
||||||
## 🚀 How to Run
|
|
||||||
|
|
||||||
### 1. Inside the Workspace Root
|
|
||||||
|
|
||||||
First, install dependencies and build the project:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
pnpm i
|
|
||||||
mv .env.example .env
|
|
||||||
pnpm run build
|
|
||||||
```
|
|
||||||
|
|
||||||
Don't forget to update `VITE_CLERK_PUBLISHABLE_KEY` in `.env` with your [Publishable Key](https://clerk.com/docs/deployments/clerk-environment-variables#clerk-publishable-and-secret-keys) from Clerk.
|
|
||||||
|
|
||||||
### 2. Inside the `examples/chat-rn-expo-clerk` Directory
|
|
||||||
|
|
||||||
Next, navigate to the specific example project and run the following commands:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
pnpm expo prebuild
|
|
||||||
pnpx pod-install
|
|
||||||
pnpm expo run:ios
|
|
||||||
```
|
|
||||||
|
|
||||||
This will set up and launch the app on iOS. For Android, you can replace the last command with `pnpm expo run:android`.
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
{
|
|
||||||
"expo": {
|
|
||||||
"name": "jazz-chat-rn-expo-clerk",
|
|
||||||
"scheme": "jazz-chat-rn-expo-clerk",
|
|
||||||
"slug": "jazz-chat-rn-expo-clerk",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"orientation": "portrait",
|
|
||||||
"icon": "./assets/images/icon.png",
|
|
||||||
"userInterfaceStyle": "light",
|
|
||||||
"splash": {
|
|
||||||
"image": "./assets/images/splash.png",
|
|
||||||
"resizeMode": "contain",
|
|
||||||
"backgroundColor": "#ffffff"
|
|
||||||
},
|
|
||||||
"ios": {
|
|
||||||
"supportsTablet": true,
|
|
||||||
"bundleIdentifier": "com.jazz.chatrnclerk"
|
|
||||||
},
|
|
||||||
"android": {
|
|
||||||
"adaptiveIcon": {
|
|
||||||
"foregroundImage": "./assets/images/adaptive-icon.png",
|
|
||||||
"backgroundColor": "#ffffff"
|
|
||||||
},
|
|
||||||
"package": "com.jazz.chatrnclerk"
|
|
||||||
},
|
|
||||||
"newArchEnabled": true,
|
|
||||||
"plugins": [
|
|
||||||
"expo-secure-store",
|
|
||||||
"expo-font",
|
|
||||||
"expo-router",
|
|
||||||
"expo-sqlite",
|
|
||||||
[
|
|
||||||
"expo-image-picker",
|
|
||||||
{
|
|
||||||
"photosPermission": "The app accesses your photos to let you share them with your friends."
|
|
||||||
}
|
|
||||||
]
|
|
||||||
],
|
|
||||||
"extra": {
|
|
||||||
"eas": {
|
|
||||||
"projectId": "ca3d46e5-a10a-47ec-9d77-3b841e1c62d4"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
import { Redirect, Stack } from "expo-router";
|
|
||||||
import { useIsAuthenticated } from "jazz-expo";
|
|
||||||
import React from "react";
|
|
||||||
|
|
||||||
export default function HomeLayout() {
|
|
||||||
const isAuthenticated = useIsAuthenticated();
|
|
||||||
|
|
||||||
if (isAuthenticated) {
|
|
||||||
return <Redirect href={"/chat"} />;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Stack screenOptions={{ headerShown: false, headerBackVisible: true }} />
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
import { SignedOut } from "@clerk/clerk-expo";
|
|
||||||
import { Link } from "expo-router";
|
|
||||||
import React from "react";
|
|
||||||
import { Text, View } from "react-native";
|
|
||||||
|
|
||||||
export default function HomePage() {
|
|
||||||
return (
|
|
||||||
<View className="flex-1 justify-center items-center bg-gray-100 p-6">
|
|
||||||
<SignedOut>
|
|
||||||
<View className="bg-white p-6 rounded-lg shadow-lg w-11/12 max-w-md">
|
|
||||||
<Text className="text-2xl font-bold text-center text-gray-900 mb-4">
|
|
||||||
Jazz 🤝 Clerk 🤝 Expo
|
|
||||||
</Text>
|
|
||||||
<Link href="/sign-in" className="mb-4">
|
|
||||||
<Text className="text-center text-blue-600 underline text-lg">
|
|
||||||
Sign In
|
|
||||||
</Text>
|
|
||||||
</Link>
|
|
||||||
<Link href="/sign-in-oauth" className="mb-4">
|
|
||||||
<Text className="text-center text-blue-600 underline text-lg">
|
|
||||||
Sign In OAuth
|
|
||||||
</Text>
|
|
||||||
</Link>
|
|
||||||
<Link href="/sign-up">
|
|
||||||
<Text className="text-center text-blue-600 underline text-lg">
|
|
||||||
Sign Up
|
|
||||||
</Text>
|
|
||||||
</Link>
|
|
||||||
</View>
|
|
||||||
</SignedOut>
|
|
||||||
</View>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
import { Redirect, Stack } from "expo-router";
|
|
||||||
import { useIsAuthenticated } from "jazz-expo";
|
|
||||||
|
|
||||||
export default function UnAuthenticatedLayout() {
|
|
||||||
const isAuthenticated = useIsAuthenticated();
|
|
||||||
|
|
||||||
if (isAuthenticated) {
|
|
||||||
return <Redirect href={"/chat"} />;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Stack
|
|
||||||
screenOptions={{
|
|
||||||
headerShown: true,
|
|
||||||
headerBackVisible: true,
|
|
||||||
headerTitle: "",
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,65 +0,0 @@
|
|||||||
import { useOAuth } from "@clerk/clerk-expo";
|
|
||||||
import * as Linking from "expo-linking";
|
|
||||||
import { Link } from "expo-router";
|
|
||||||
import * as WebBrowser from "expo-web-browser";
|
|
||||||
import React from "react";
|
|
||||||
import { Text, TouchableOpacity, View } from "react-native";
|
|
||||||
|
|
||||||
export const useWarmUpBrowser = () => {
|
|
||||||
React.useEffect(() => {
|
|
||||||
// Warm up the android browser to improve UX
|
|
||||||
// https://docs.expo.dev/guides/authentication/#improving-user-experience
|
|
||||||
void WebBrowser.warmUpAsync();
|
|
||||||
return () => {
|
|
||||||
void WebBrowser.coolDownAsync();
|
|
||||||
};
|
|
||||||
}, []);
|
|
||||||
};
|
|
||||||
|
|
||||||
WebBrowser.maybeCompleteAuthSession();
|
|
||||||
|
|
||||||
const SignInWithOAuth = () => {
|
|
||||||
useWarmUpBrowser();
|
|
||||||
|
|
||||||
const { startOAuthFlow } = useOAuth({ strategy: "oauth_google" });
|
|
||||||
|
|
||||||
const onPress = React.useCallback(async () => {
|
|
||||||
try {
|
|
||||||
const { createdSessionId, signIn, signUp, setActive } =
|
|
||||||
await startOAuthFlow({
|
|
||||||
redirectUrl: Linking.createURL("/", {
|
|
||||||
scheme: "jazz-chat-rn-expo-clerk",
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
|
|
||||||
if (createdSessionId) {
|
|
||||||
setActive!({ session: createdSessionId });
|
|
||||||
} else {
|
|
||||||
// Use signIn or signUp for next steps such as MFA
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
console.error("OAuth error", err);
|
|
||||||
}
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<View className="flex-1 justify-center items-center bg-gray-50 p-6">
|
|
||||||
<View className="bg-white w-11/12 max-w-md p-8 rounded-lg shadow-lg items-center">
|
|
||||||
<TouchableOpacity
|
|
||||||
onPress={onPress}
|
|
||||||
className="w-full bg-red-500 py-3 rounded-lg flex items-center justify-center"
|
|
||||||
>
|
|
||||||
<Text className="text-white text-lg font-semibold">
|
|
||||||
Sign in with Google
|
|
||||||
</Text>
|
|
||||||
</TouchableOpacity>
|
|
||||||
<Link href="/" className="mt-4">
|
|
||||||
<Text className="text-blue-600 text-lg font-semibold underline mb-6">
|
|
||||||
Back to Home
|
|
||||||
</Text>
|
|
||||||
</Link>
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
export default SignInWithOAuth;
|
|
||||||
@@ -1,79 +0,0 @@
|
|||||||
import { useSignIn } from "@clerk/clerk-expo";
|
|
||||||
import { Link } from "expo-router";
|
|
||||||
import React from "react";
|
|
||||||
import { Text, TextInput, TouchableOpacity, View } from "react-native";
|
|
||||||
|
|
||||||
export default function SignInPage() {
|
|
||||||
const { signIn, setActive, isLoaded } = useSignIn();
|
|
||||||
const [emailAddress, setEmailAddress] = React.useState("");
|
|
||||||
const [password, setPassword] = React.useState("");
|
|
||||||
const [errorMessage, setErrorMessage] = React.useState("");
|
|
||||||
|
|
||||||
const onSignInPress = React.useCallback(async () => {
|
|
||||||
if (!isLoaded) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
setErrorMessage("");
|
|
||||||
|
|
||||||
try {
|
|
||||||
const signInAttempt = await signIn.create({
|
|
||||||
identifier: emailAddress,
|
|
||||||
password,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (signInAttempt.status === "complete") {
|
|
||||||
await setActive({ session: signInAttempt.createdSessionId });
|
|
||||||
} else {
|
|
||||||
console.error(JSON.stringify(signInAttempt, null, 2));
|
|
||||||
setErrorMessage("Invalid credentials. Please try again.");
|
|
||||||
}
|
|
||||||
} catch (err: any) {
|
|
||||||
console.error(JSON.stringify(err, null, 2));
|
|
||||||
if (err.errors && err.errors[0]?.message) {
|
|
||||||
setErrorMessage(err.errors[0].message);
|
|
||||||
} else {
|
|
||||||
setErrorMessage("An unexpected error occurred. Please try again.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, [isLoaded, emailAddress, password]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<View className="flex-1 justify-center items-center bg-gray-50 p-6">
|
|
||||||
<View className="bg-white w-11/12 max-w-md p-8 rounded-lg shadow-md">
|
|
||||||
<Text className="text-3xl font-bold text-center text-gray-800 mb-6">
|
|
||||||
Sign In
|
|
||||||
</Text>
|
|
||||||
{errorMessage ? (
|
|
||||||
<Text className="text-red-500 text-center mb-4">{errorMessage}</Text>
|
|
||||||
) : null}
|
|
||||||
<TextInput
|
|
||||||
autoCapitalize="none"
|
|
||||||
value={emailAddress}
|
|
||||||
placeholder="Email..."
|
|
||||||
onChangeText={(emailAddress) => setEmailAddress(emailAddress)}
|
|
||||||
className="w-full h-12 mb-4 px-4 bg-gray-100 border border-gray-300 rounded-lg focus:border-blue-500 focus:outline-none"
|
|
||||||
/>
|
|
||||||
<TextInput
|
|
||||||
value={password}
|
|
||||||
placeholder="Password..."
|
|
||||||
secureTextEntry={true}
|
|
||||||
onChangeText={(password) => setPassword(password)}
|
|
||||||
className="w-full h-12 mb-6 px-4 bg-gray-100 border border-gray-300 rounded-lg focus:border-blue-500 focus:outline-none"
|
|
||||||
/>
|
|
||||||
<TouchableOpacity
|
|
||||||
onPress={onSignInPress}
|
|
||||||
className="w-full h-12 bg-blue-600 rounded-lg flex items-center justify-center"
|
|
||||||
>
|
|
||||||
<Text className="text-white text-lg font-semibold">Sign In</Text>
|
|
||||||
</TouchableOpacity>
|
|
||||||
<View className="flex-row items-center justify-center mt-4">
|
|
||||||
<Text className="text-gray-600">Don't have an account?</Text>
|
|
||||||
<Link href="/sign-up">
|
|
||||||
<Text className="text-blue-500 ml-2 font-semibold">Sign up</Text>
|
|
||||||
</Link>
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,120 +0,0 @@
|
|||||||
import { useSignUp } from "@clerk/clerk-expo";
|
|
||||||
import { useNavigation } from "@react-navigation/native";
|
|
||||||
import * as React from "react";
|
|
||||||
import { Text, TextInput, TouchableOpacity, View } from "react-native";
|
|
||||||
|
|
||||||
export default function SignUpPage() {
|
|
||||||
const { isLoaded, signUp, setActive } = useSignUp();
|
|
||||||
|
|
||||||
const [emailAddress, setEmailAddress] = React.useState("");
|
|
||||||
const [password, setPassword] = React.useState("");
|
|
||||||
const [pendingVerification, setPendingVerification] = React.useState(false);
|
|
||||||
const [code, setCode] = React.useState("");
|
|
||||||
const [errorMessage, setErrorMessage] = React.useState("");
|
|
||||||
const navigation = useNavigation();
|
|
||||||
|
|
||||||
const onSignUpPress = async () => {
|
|
||||||
if (!isLoaded) return;
|
|
||||||
|
|
||||||
setErrorMessage("");
|
|
||||||
|
|
||||||
try {
|
|
||||||
await signUp.create({
|
|
||||||
emailAddress,
|
|
||||||
password,
|
|
||||||
});
|
|
||||||
|
|
||||||
await signUp.prepareEmailAddressVerification({
|
|
||||||
strategy: "email_code",
|
|
||||||
});
|
|
||||||
|
|
||||||
setPendingVerification(true);
|
|
||||||
} catch (err: any) {
|
|
||||||
console.error(JSON.stringify(err, null, 2));
|
|
||||||
if (err.errors && err.errors[0]?.message) {
|
|
||||||
setErrorMessage(err.errors[0].message);
|
|
||||||
} else {
|
|
||||||
setErrorMessage("An unexpected error occurred. Please try again.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const onPressVerify = async () => {
|
|
||||||
if (!isLoaded) return;
|
|
||||||
|
|
||||||
setErrorMessage("");
|
|
||||||
|
|
||||||
try {
|
|
||||||
const completeSignUp = await signUp.attemptEmailAddressVerification({
|
|
||||||
code,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (completeSignUp.status === "complete") {
|
|
||||||
await setActive({ session: completeSignUp.createdSessionId });
|
|
||||||
} else {
|
|
||||||
console.error(JSON.stringify(completeSignUp, null, 2));
|
|
||||||
setErrorMessage("Failed to verify. Please check your code.");
|
|
||||||
}
|
|
||||||
} catch (err: any) {
|
|
||||||
console.error(JSON.stringify(err, null, 2));
|
|
||||||
setErrorMessage("Invalid verification code. Please try again.");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<View className="flex-1 justify-center items-center bg-gray-50 p-6">
|
|
||||||
<View className="bg-white w-11/12 max-w-md p-8 rounded-lg shadow-lg">
|
|
||||||
<Text className="text-3xl font-bold text-center text-gray-800 mb-6">
|
|
||||||
{pendingVerification ? "Verify Email" : "Sign Up"}
|
|
||||||
</Text>
|
|
||||||
{errorMessage ? (
|
|
||||||
<Text className="text-red-500 text-center mb-4">{errorMessage}</Text>
|
|
||||||
) : null}
|
|
||||||
|
|
||||||
{!pendingVerification && (
|
|
||||||
<>
|
|
||||||
<TextInput
|
|
||||||
autoCapitalize="none"
|
|
||||||
value={emailAddress}
|
|
||||||
placeholder="Email..."
|
|
||||||
onChangeText={(email) => setEmailAddress(email)}
|
|
||||||
className="w-full h-12 mb-4 px-4 bg-gray-100 border border-gray-300 rounded-lg focus:border-blue-500 focus:outline-none"
|
|
||||||
/>
|
|
||||||
<TextInput
|
|
||||||
value={password}
|
|
||||||
placeholder="Password..."
|
|
||||||
secureTextEntry={true}
|
|
||||||
onChangeText={(password) => setPassword(password)}
|
|
||||||
className="w-full h-12 mb-6 px-4 bg-gray-100 border border-gray-300 rounded-lg focus:border-blue-500 focus:outline-none"
|
|
||||||
/>
|
|
||||||
<TouchableOpacity
|
|
||||||
onPress={onSignUpPress}
|
|
||||||
className="w-full h-12 bg-blue-600 rounded-lg flex justify-center items-center mb-4"
|
|
||||||
>
|
|
||||||
<Text className="text-white text-lg font-semibold">Sign Up</Text>
|
|
||||||
</TouchableOpacity>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{pendingVerification && (
|
|
||||||
<>
|
|
||||||
<TextInput
|
|
||||||
value={code}
|
|
||||||
placeholder="Verification Code..."
|
|
||||||
onChangeText={(code) => setCode(code)}
|
|
||||||
className="w-full h-12 mb-4 px-4 bg-gray-100 border border-gray-300 rounded-lg focus:border-blue-500 focus:outline-none"
|
|
||||||
/>
|
|
||||||
<TouchableOpacity
|
|
||||||
onPress={onPressVerify}
|
|
||||||
className="w-full h-12 bg-green-600 rounded-lg flex justify-center items-center mb-4"
|
|
||||||
>
|
|
||||||
<Text className="text-white text-lg font-semibold">
|
|
||||||
Verify Email
|
|
||||||
</Text>
|
|
||||||
</TouchableOpacity>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
import { ScrollViewStyleReset } from "expo-router/html";
|
|
||||||
import { type PropsWithChildren } from "react";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This file is web-only and used to configure the root HTML for every web page during static rendering.
|
|
||||||
* The contents of this function only run in Node.js environments and do not have access to the DOM or browser APIs.
|
|
||||||
*/
|
|
||||||
export default function Root({ children }: PropsWithChildren) {
|
|
||||||
return (
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charSet="utf-8" />
|
|
||||||
<meta httpEquiv="X-UA-Compatible" content="IE=edge" />
|
|
||||||
<meta
|
|
||||||
name="viewport"
|
|
||||||
content="width=device-width, initial-scale=1, shrink-to-fit=no"
|
|
||||||
/>
|
|
||||||
|
|
||||||
{/*
|
|
||||||
Disable body scrolling on web. This makes ScrollView components work closer to how they do on native.
|
|
||||||
However, body scrolling is often nice to have for mobile web. If you want to enable it, remove this line.
|
|
||||||
*/}
|
|
||||||
<ScrollViewStyleReset />
|
|
||||||
|
|
||||||
{/* Using raw CSS styles as an escape-hatch to ensure the background color never flickers in dark-mode. */}
|
|
||||||
<style dangerouslySetInnerHTML={{ __html: responsiveBackground }} />
|
|
||||||
{/* Add any additional <head> elements that you want globally available on web... */}
|
|
||||||
</head>
|
|
||||||
<body>{children}</body>
|
|
||||||
</html>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const responsiveBackground = `
|
|
||||||
body {
|
|
||||||
background-color: #fff;
|
|
||||||
}
|
|
||||||
@media (prefers-color-scheme: dark) {
|
|
||||||
body {
|
|
||||||
background-color: #000;
|
|
||||||
}
|
|
||||||
}`;
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
import { Link, Stack } from "expo-router";
|
|
||||||
import { StyleSheet, Text, View } from "react-native";
|
|
||||||
|
|
||||||
export default function NotFoundScreen() {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Stack.Screen options={{ title: "Oops!" }} />
|
|
||||||
<View style={styles.container}>
|
|
||||||
<Text>This screen doesn't exist.</Text>
|
|
||||||
<Link href="/" style={styles.link}>
|
|
||||||
<Text>Go to home screen!</Text>
|
|
||||||
</Link>
|
|
||||||
</View>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
|
||||||
container: {
|
|
||||||
flex: 1,
|
|
||||||
alignItems: "center",
|
|
||||||
justifyContent: "center",
|
|
||||||
padding: 20,
|
|
||||||
},
|
|
||||||
link: {
|
|
||||||
marginTop: 15,
|
|
||||||
paddingVertical: 15,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
import "../global.css";
|
|
||||||
import { ClerkLoaded, ClerkProvider } from "@clerk/clerk-expo";
|
|
||||||
import { secureStore } from "@clerk/clerk-expo/secure-store";
|
|
||||||
import { useFonts } from "expo-font";
|
|
||||||
import { Slot, useRouter, useSegments } from "expo-router";
|
|
||||||
import * as SplashScreen from "expo-splash-screen";
|
|
||||||
import { useIsAuthenticated, useJazzContext } from "jazz-expo";
|
|
||||||
import React, { useEffect } from "react";
|
|
||||||
import { tokenCache } from "../cache";
|
|
||||||
import { JazzAndAuth } from "../src/auth-context";
|
|
||||||
|
|
||||||
SplashScreen.preventAutoHideAsync();
|
|
||||||
|
|
||||||
function InitialLayout() {
|
|
||||||
const isAuthenticated = useIsAuthenticated();
|
|
||||||
const segments = useSegments();
|
|
||||||
const router = useRouter();
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const inAuthGroup = segments[0] === "(auth)";
|
|
||||||
|
|
||||||
if (isAuthenticated && inAuthGroup) {
|
|
||||||
router.replace("/chat");
|
|
||||||
} else if (!isAuthenticated && !inAuthGroup) {
|
|
||||||
router.replace("/");
|
|
||||||
}
|
|
||||||
|
|
||||||
SplashScreen.hideAsync();
|
|
||||||
}, [isAuthenticated, segments, router]);
|
|
||||||
|
|
||||||
return <Slot />;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function RootLayout() {
|
|
||||||
const [fontsLoaded] = useFonts({
|
|
||||||
SpaceMono: require("../assets/fonts/SpaceMono-Regular.ttf"),
|
|
||||||
});
|
|
||||||
|
|
||||||
const publishableKey = process.env.EXPO_PUBLIC_CLERK_PUBLISHABLE_KEY;
|
|
||||||
|
|
||||||
if (!publishableKey) {
|
|
||||||
throw new Error(
|
|
||||||
"Missing Publishable Key. Please set EXPO_PUBLIC_CLERK_PUBLISHABLE_KEY in your .env",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (fontsLoaded) {
|
|
||||||
} else {
|
|
||||||
SplashScreen.preventAutoHideAsync();
|
|
||||||
}
|
|
||||||
}, [fontsLoaded]);
|
|
||||||
|
|
||||||
if (!fontsLoaded) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<ClerkProvider
|
|
||||||
tokenCache={tokenCache}
|
|
||||||
publishableKey={publishableKey}
|
|
||||||
__experimental_resourceCache={secureStore}
|
|
||||||
>
|
|
||||||
<ClerkLoaded>
|
|
||||||
<JazzAndAuth>
|
|
||||||
<InitialLayout />
|
|
||||||
</JazzAndAuth>
|
|
||||||
</ClerkLoaded>
|
|
||||||
</ClerkProvider>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,234 +0,0 @@
|
|||||||
import { Chat, Message } from "@/src/schema";
|
|
||||||
import { useNavigation } from "@react-navigation/native";
|
|
||||||
import clsx from "clsx";
|
|
||||||
import * as Clipboard from "expo-clipboard";
|
|
||||||
import * as ImagePicker from "expo-image-picker";
|
|
||||||
import { useLocalSearchParams } from "expo-router";
|
|
||||||
import { useAccount, useCoState } from "jazz-expo";
|
|
||||||
import { ProgressiveImg } from "jazz-expo";
|
|
||||||
import { createImage } from "jazz-react-native-media-images";
|
|
||||||
import { CoPlainText, Group, Loaded } from "jazz-tools";
|
|
||||||
import { useEffect, useLayoutEffect, useState } from "react";
|
|
||||||
import React, {
|
|
||||||
SafeAreaView,
|
|
||||||
View,
|
|
||||||
Text,
|
|
||||||
Alert,
|
|
||||||
TouchableOpacity,
|
|
||||||
FlatList,
|
|
||||||
KeyboardAvoidingView,
|
|
||||||
TextInput,
|
|
||||||
Button,
|
|
||||||
Image,
|
|
||||||
ActivityIndicator,
|
|
||||||
} from "react-native";
|
|
||||||
|
|
||||||
export default function Conversation() {
|
|
||||||
const { chatId } = useLocalSearchParams();
|
|
||||||
const { me } = useAccount();
|
|
||||||
const [chat, setChat] = useState<Loaded<typeof Chat>>();
|
|
||||||
const [message, setMessage] = useState("");
|
|
||||||
const loadedChat = useCoState(Chat, chat?.id, { resolve: { $each: true } });
|
|
||||||
const navigation = useNavigation();
|
|
||||||
const [isUploading, setIsUploading] = useState(false);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (chat) return;
|
|
||||||
if (chatId === "new") {
|
|
||||||
createChat();
|
|
||||||
} else {
|
|
||||||
loadChat(chatId as string);
|
|
||||||
}
|
|
||||||
}, [chat]);
|
|
||||||
|
|
||||||
// Effect to dynamically set header options
|
|
||||||
useLayoutEffect(() => {
|
|
||||||
navigation.setOptions({
|
|
||||||
headerTitle: "Chat",
|
|
||||||
headerRight: () =>
|
|
||||||
chat ? (
|
|
||||||
<Button
|
|
||||||
onPress={() => {
|
|
||||||
if (chat?.id) {
|
|
||||||
Clipboard.setStringAsync(
|
|
||||||
`https://chat.jazz.tools/#/chat/${chat.id}`,
|
|
||||||
);
|
|
||||||
Alert.alert("Copied to clipboard", `Chat ID: ${chat.id}`);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
title="Share"
|
|
||||||
/>
|
|
||||||
) : null,
|
|
||||||
});
|
|
||||||
}, [navigation, chat]);
|
|
||||||
|
|
||||||
const createChat = () => {
|
|
||||||
const group = Group.create({ owner: me });
|
|
||||||
group.addMember("everyone", "writer");
|
|
||||||
const chat = Chat.create([], { owner: group });
|
|
||||||
setChat(chat);
|
|
||||||
};
|
|
||||||
|
|
||||||
const loadChat = async (chatId: string) => {
|
|
||||||
try {
|
|
||||||
const chat = await Chat.load(chatId);
|
|
||||||
if (chat) setChat(chat);
|
|
||||||
} catch (error) {
|
|
||||||
console.log("Error loading chat", error);
|
|
||||||
Alert.alert("Error", `Error loading chat: ${error}`);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const sendMessage = () => {
|
|
||||||
if (!chat) return;
|
|
||||||
if (message.trim()) {
|
|
||||||
chat.push(
|
|
||||||
Message.create(
|
|
||||||
{ text: CoPlainText.create(message, chat._owner) },
|
|
||||||
chat._owner,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
setMessage("");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleImageUpload = async () => {
|
|
||||||
try {
|
|
||||||
const result = await ImagePicker.launchImageLibraryAsync({
|
|
||||||
mediaTypes: ImagePicker.MediaTypeOptions.Images,
|
|
||||||
base64: true,
|
|
||||||
quality: 0.7,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!result.canceled && result.assets[0].base64 && chat) {
|
|
||||||
setIsUploading(true);
|
|
||||||
const base64Uri = `data:image/jpeg;base64,${result.assets[0].base64}`;
|
|
||||||
|
|
||||||
const image = await createImage(base64Uri, {
|
|
||||||
owner: chat._owner,
|
|
||||||
maxSize: 2048,
|
|
||||||
});
|
|
||||||
|
|
||||||
chat.push(
|
|
||||||
Message.create(
|
|
||||||
{ text: CoPlainText.create("", chat._owner), image },
|
|
||||||
chat._owner,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
Alert.alert("Error", "Failed to upload image");
|
|
||||||
} finally {
|
|
||||||
setIsUploading(false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const renderMessageItem = ({ item }: { item: Loaded<typeof Message> }) => {
|
|
||||||
const isMe = item._edits.text?.by?.isMe;
|
|
||||||
return (
|
|
||||||
<View
|
|
||||||
className={clsx(
|
|
||||||
`rounded-xl px-3 py-2 max-w-[75%] my-1`,
|
|
||||||
isMe ? `bg-blue-500 self-end` : `bg-gray-200 self-start`,
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
{!isMe ? (
|
|
||||||
<Text
|
|
||||||
className={clsx(
|
|
||||||
`text-xs text-gray-500 mb-1`,
|
|
||||||
isMe ? "text-right" : "text-left",
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
{item._edits.text?.by?.profile?.name}
|
|
||||||
</Text>
|
|
||||||
) : null}
|
|
||||||
<View
|
|
||||||
className={clsx(
|
|
||||||
"flex relative items-end justify-between",
|
|
||||||
isMe ? "flex-row" : "flex-row",
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
{item.image && (
|
|
||||||
<ProgressiveImg image={item.image} maxWidth={1024}>
|
|
||||||
{({ src, res, originalSize }) => (
|
|
||||||
<Image
|
|
||||||
source={{ uri: src }}
|
|
||||||
className="w-48 h-48 rounded-lg mb-2"
|
|
||||||
resizeMode="cover"
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</ProgressiveImg>
|
|
||||||
)}
|
|
||||||
{item.text && (
|
|
||||||
<Text
|
|
||||||
className={clsx(
|
|
||||||
!isMe ? "text-black" : "text-gray-200",
|
|
||||||
`text-md max-w-[85%]`,
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
{item.text}
|
|
||||||
</Text>
|
|
||||||
)}
|
|
||||||
<Text
|
|
||||||
className={clsx(
|
|
||||||
"text-[10px] text-right ml-2",
|
|
||||||
!isMe ? "mt-2 text-gray-500" : "mt-1 text-gray-200",
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
{item._edits.text?.madeAt?.getHours().toString().padStart(2, "0")}:
|
|
||||||
{item._edits.text?.madeAt?.getMinutes().toString().padStart(2, "0")}
|
|
||||||
</Text>
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<View className="flex-1 bg-gray-50">
|
|
||||||
<FlatList
|
|
||||||
contentContainerStyle={{
|
|
||||||
flexGrow: 1,
|
|
||||||
paddingVertical: 10,
|
|
||||||
paddingHorizontal: 8,
|
|
||||||
}}
|
|
||||||
className="flex"
|
|
||||||
data={loadedChat}
|
|
||||||
keyExtractor={(item) => item.id}
|
|
||||||
renderItem={renderMessageItem}
|
|
||||||
/>
|
|
||||||
<KeyboardAvoidingView
|
|
||||||
keyboardVerticalOffset={110}
|
|
||||||
behavior="padding"
|
|
||||||
className="p-3 bg-white border-t border-gray-300"
|
|
||||||
>
|
|
||||||
<SafeAreaView className="flex-row items-center gap-2">
|
|
||||||
<TouchableOpacity
|
|
||||||
onPress={handleImageUpload}
|
|
||||||
disabled={isUploading}
|
|
||||||
className="h-10 w-10 items-center justify-center"
|
|
||||||
>
|
|
||||||
{isUploading ? (
|
|
||||||
<ActivityIndicator size="small" color="#0000ff" />
|
|
||||||
) : (
|
|
||||||
<Text className="text-2xl">🖼️</Text>
|
|
||||||
)}
|
|
||||||
</TouchableOpacity>
|
|
||||||
<TextInput
|
|
||||||
className="flex-1 rounded-full h-10 px-4 bg-gray-100 border border-gray-300 focus:border-blue-500 focus:bg-white"
|
|
||||||
value={message}
|
|
||||||
onChangeText={setMessage}
|
|
||||||
placeholder="Type a message..."
|
|
||||||
textAlignVertical="center"
|
|
||||||
onSubmitEditing={sendMessage}
|
|
||||||
/>
|
|
||||||
<TouchableOpacity
|
|
||||||
onPress={sendMessage}
|
|
||||||
className="bg-blue-500 rounded-full h-10 w-10 items-center justify-center"
|
|
||||||
>
|
|
||||||
<Text className="text-white text-xl">↑</Text>
|
|
||||||
</TouchableOpacity>
|
|
||||||
</SafeAreaView>
|
|
||||||
</KeyboardAvoidingView>
|
|
||||||
</View>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
import { Stack } from "expo-router";
|
|
||||||
import React from "react";
|
|
||||||
|
|
||||||
export default function ChatLayout() {
|
|
||||||
return (
|
|
||||||
<Stack
|
|
||||||
screenOptions={{
|
|
||||||
headerShown: true,
|
|
||||||
headerBackVisible: true,
|
|
||||||
headerTitle: "",
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,90 +0,0 @@
|
|||||||
import { useNavigation } from "@react-navigation/native";
|
|
||||||
import { useRouter } from "expo-router";
|
|
||||||
import { ID } from "jazz-tools";
|
|
||||||
import { useLayoutEffect } from "react";
|
|
||||||
import React, {
|
|
||||||
Button,
|
|
||||||
Text,
|
|
||||||
TouchableOpacity,
|
|
||||||
View,
|
|
||||||
Alert,
|
|
||||||
} from "react-native";
|
|
||||||
|
|
||||||
import { useUser } from "@clerk/clerk-expo";
|
|
||||||
import { useAccount } from "jazz-expo";
|
|
||||||
import { Chat } from "../../src/schema";
|
|
||||||
|
|
||||||
export default function ChatScreen() {
|
|
||||||
const { logOut } = useAccount();
|
|
||||||
const router = useRouter();
|
|
||||||
const navigation = useNavigation();
|
|
||||||
const { user } = useUser();
|
|
||||||
|
|
||||||
function handleLogOut() {
|
|
||||||
logOut();
|
|
||||||
router.navigate("/");
|
|
||||||
}
|
|
||||||
|
|
||||||
useLayoutEffect(() => {
|
|
||||||
navigation.setOptions({
|
|
||||||
headerTitle: "Chat",
|
|
||||||
headerRight: () => <Button onPress={handleLogOut} title="Logout" />,
|
|
||||||
});
|
|
||||||
}, [navigation]);
|
|
||||||
|
|
||||||
const loadChat = async (chatId: string | "new") => {
|
|
||||||
router.navigate(`/chat/${chatId}`);
|
|
||||||
};
|
|
||||||
|
|
||||||
const joinChat = () => {
|
|
||||||
Alert.prompt(
|
|
||||||
"Join Chat",
|
|
||||||
"Enter the Chat ID (example: co_zBGEHYvRfGuT2YSBraY3njGjnde)",
|
|
||||||
[
|
|
||||||
{
|
|
||||||
text: "Cancel",
|
|
||||||
style: "cancel",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: "Join",
|
|
||||||
onPress: (chatId) => {
|
|
||||||
if (chatId) {
|
|
||||||
loadChat(chatId);
|
|
||||||
} else {
|
|
||||||
Alert.alert("Error", "Chat ID cannot be empty.");
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
"plain-text",
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<View className="flex-1 bg-gray-50">
|
|
||||||
<View className="flex-1 justify-center items-center px-6">
|
|
||||||
<View className="w-full max-w-sm bg-white p-8 rounded-lg shadow-lg">
|
|
||||||
<Text className="text-xl font-semibold text-gray-800">
|
|
||||||
Welcome, {user?.emailAddresses[0].emailAddress}
|
|
||||||
</Text>
|
|
||||||
<TouchableOpacity
|
|
||||||
onPress={() => loadChat("new")}
|
|
||||||
className="w-full bg-blue-600 py-4 rounded-md mb-4 mt-4"
|
|
||||||
>
|
|
||||||
<Text className="text-white text-lg font-semibold text-center">
|
|
||||||
Start New Chat
|
|
||||||
</Text>
|
|
||||||
</TouchableOpacity>
|
|
||||||
<TouchableOpacity
|
|
||||||
onPress={joinChat}
|
|
||||||
className="w-full bg-green-500 py-4 rounded-md"
|
|
||||||
>
|
|
||||||
<Text className="text-white text-lg font-semibold text-center">
|
|
||||||
Join Chat
|
|
||||||
</Text>
|
|
||||||
</TouchableOpacity>
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
Before Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 313 KiB |
|
Before Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 5.0 KiB |
|
Before Width: | Height: | Size: 6.2 KiB |
|
Before Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 46 KiB |
@@ -1,9 +0,0 @@
|
|||||||
module.exports = function (api) {
|
|
||||||
api.cache(true);
|
|
||||||
return {
|
|
||||||
presets: [
|
|
||||||
["babel-preset-expo", { jsxImportSource: "nativewind" }],
|
|
||||||
"nativewind/babel",
|
|
||||||
],
|
|
||||||
};
|
|
||||||
};
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
import * as SecureStore from "expo-secure-store";
|
|
||||||
import { Platform } from "react-native";
|
|
||||||
|
|
||||||
export interface TokenCache {
|
|
||||||
getToken: (key: string) => Promise<string | undefined | null>;
|
|
||||||
saveToken: (key: string, token: string) => Promise<void>;
|
|
||||||
clearToken: (key: string) => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
const createTokenCache = (): TokenCache => {
|
|
||||||
return {
|
|
||||||
getToken: async (key: string) => {
|
|
||||||
try {
|
|
||||||
const item = await SecureStore.getItemAsync(key);
|
|
||||||
if (item) {
|
|
||||||
console.log(`${key} was used 🔐 \n`);
|
|
||||||
} else {
|
|
||||||
console.log("No values stored under key: " + key);
|
|
||||||
}
|
|
||||||
return item;
|
|
||||||
} catch (error) {
|
|
||||||
console.error("secure store get item error: ", error);
|
|
||||||
await SecureStore.deleteItemAsync(key);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
saveToken: (key: string, token: string) => {
|
|
||||||
return SecureStore.setItemAsync(key, token);
|
|
||||||
},
|
|
||||||
clearToken: (key: string) => {
|
|
||||||
return SecureStore.deleteItemAsync(key);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
// SecureStore is not supported on the web
|
|
||||||
// https://github.com/expo/expo/issues/7744#issuecomment-611093485
|
|
||||||
export const tokenCache =
|
|
||||||
Platform.OS !== "web" ? createTokenCache() : undefined;
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
{
|
|
||||||
"cli": {
|
|
||||||
"version": ">= 12.5.1",
|
|
||||||
"appVersionSource": "remote"
|
|
||||||
},
|
|
||||||
"build": {
|
|
||||||
"development": {
|
|
||||||
"developmentClient": true,
|
|
||||||
"distribution": "internal"
|
|
||||||
},
|
|
||||||
"ios-simulator": {
|
|
||||||
"extends": "development",
|
|
||||||
"ios": {
|
|
||||||
"simulator": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"preview": {
|
|
||||||
"distribution": "internal"
|
|
||||||
},
|
|
||||||
"production": {
|
|
||||||
"autoIncrement": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"submit": {
|
|
||||||
"production": {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
@tailwind base;
|
|
||||||
@tailwind components;
|
|
||||||
@tailwind utilities;
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
import "./polyfills";
|
|
||||||
import "expo-router/entry";
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
// Learn more https://docs.expo.dev/guides/monorepos
|
|
||||||
const { getDefaultConfig } = require("expo/metro-config");
|
|
||||||
const { withNativeWind } = require("nativewind/metro");
|
|
||||||
const { FileStore } = require("metro-cache");
|
|
||||||
const path = require("path");
|
|
||||||
|
|
||||||
// eslint-disable-next-line no-undef
|
|
||||||
const projectRoot = __dirname;
|
|
||||||
const workspaceRoot = path.resolve(projectRoot, "../..");
|
|
||||||
|
|
||||||
const config = getDefaultConfig(projectRoot);
|
|
||||||
|
|
||||||
// Since we are using pnpm, we have to setup the monorepo manually for Metro
|
|
||||||
// #1 - Watch all files in the monorepo
|
|
||||||
config.watchFolders = [workspaceRoot];
|
|
||||||
// #2 - Try resolving with project modules first, then workspace modules
|
|
||||||
config.resolver.nodeModulesPaths = [
|
|
||||||
path.resolve(projectRoot, "node_modules"),
|
|
||||||
path.resolve(workspaceRoot, "node_modules"),
|
|
||||||
];
|
|
||||||
config.resolver.sourceExts = ["mjs", "js", "json", "ts", "tsx"];
|
|
||||||
config.resolver.requireCycleIgnorePatterns = [
|
|
||||||
/(^|\/|\\)node_modules($|\/|\\)/,
|
|
||||||
/(^|\/|\\)packages($|\/|\\)/,
|
|
||||||
];
|
|
||||||
|
|
||||||
// Use turborepo to restore the cache when possible
|
|
||||||
config.cacheStores = [
|
|
||||||
new FileStore({
|
|
||||||
root: path.join(projectRoot, "node_modules", ".cache", "metro"),
|
|
||||||
}),
|
|
||||||
];
|
|
||||||
|
|
||||||
// module.exports = config;
|
|
||||||
module.exports = withNativeWind(config, { input: "./global.css" });
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
/// <reference types="nativewind/types" />
|
|
||||||
@@ -1,65 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "chat-rn-expo-clerk",
|
|
||||||
"main": "index.js",
|
|
||||||
"scripts": {
|
|
||||||
"build": "expo export -p ios",
|
|
||||||
"start": "expo start",
|
|
||||||
"format-and-lint": "biome check .",
|
|
||||||
"format-and-lint:fix": "biome check . --write",
|
|
||||||
"android": "expo run:android",
|
|
||||||
"ios": "expo prebuild && pnpx pod-install && expo run:ios",
|
|
||||||
"web": "expo start --web",
|
|
||||||
"run:ios": "pnpm expo prebuild && npx pod-install && pnpm expo run:ios"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"@azure/core-asynciterator-polyfill": "^1.0.2",
|
|
||||||
"@bacons/text-decoder": "0.0.0",
|
|
||||||
"@bam.tech/react-native-image-resizer": "^3.0.11",
|
|
||||||
"@clerk/clerk-expo": "^2.2.21",
|
|
||||||
"@expo/vector-icons": "^14.1.0",
|
|
||||||
"@react-native-community/netinfo": "11.4.1",
|
|
||||||
"@react-navigation/native": "7.0.19",
|
|
||||||
"@react-navigation/native-stack": "7.2.1",
|
|
||||||
"clsx": "^2.0.0",
|
|
||||||
"expo": "^53.0.8",
|
|
||||||
"expo-build-properties": "~0.14.6",
|
|
||||||
"expo-clipboard": "~7.1.4",
|
|
||||||
"expo-constants": "~17.1.6",
|
|
||||||
"expo-crypto": "~14.1.4",
|
|
||||||
"expo-dev-client": "~5.1.8",
|
|
||||||
"expo-file-system": "^18.1.9",
|
|
||||||
"expo-font": "~13.3.1",
|
|
||||||
"expo-image-picker": "~16.1.4",
|
|
||||||
"expo-linking": "~7.1.4",
|
|
||||||
"expo-router": "~5.0.6",
|
|
||||||
"expo-secure-store": "~14.2.3",
|
|
||||||
"expo-splash-screen": "~0.30.8",
|
|
||||||
"expo-sqlite": "15.2.9",
|
|
||||||
"expo-status-bar": "~2.2.3",
|
|
||||||
"expo-web-browser": "~14.1.6",
|
|
||||||
"jazz-expo": "workspace:*",
|
|
||||||
"jazz-react-native-media-images": "workspace:*",
|
|
||||||
"jazz-tools": "workspace:*",
|
|
||||||
"nativewind": "^4.1.21",
|
|
||||||
"react": "19.0.0",
|
|
||||||
"react-dom": "19.0.0",
|
|
||||||
"react-native": "0.79.2",
|
|
||||||
"react-native-gesture-handler": "~2.24.0",
|
|
||||||
"react-native-get-random-values": "^1.11.0",
|
|
||||||
"react-native-reanimated": "~3.17.5",
|
|
||||||
"react-native-safe-area-context": "5.4.0",
|
|
||||||
"react-native-screens": "4.10.0",
|
|
||||||
"react-native-url-polyfill": "^2.0.0",
|
|
||||||
"react-native-web": "~0.20.0",
|
|
||||||
"readable-stream": "4.7.0"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@babel/core": "^7.25.2",
|
|
||||||
"@types/react": "~19.0.14",
|
|
||||||
"@types/react-test-renderer": "^19.0.0",
|
|
||||||
"react-test-renderer": "18.3.1",
|
|
||||||
"tailwindcss": "^3.4.17",
|
|
||||||
"typescript": "5.8.3"
|
|
||||||
},
|
|
||||||
"private": true
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
export const apiKey = "chat-rn-expo-clerk-example-jazz@garden.co";
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
import { useClerk } from "@clerk/clerk-expo";
|
|
||||||
import { JazzProviderWithClerk } from "jazz-expo/auth/clerk";
|
|
||||||
import React, { PropsWithChildren } from "react";
|
|
||||||
import { apiKey } from "./apiKey";
|
|
||||||
|
|
||||||
export function JazzAndAuth({ children }: PropsWithChildren) {
|
|
||||||
const clerk = useClerk();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<JazzProviderWithClerk
|
|
||||||
clerk={clerk}
|
|
||||||
sync={{
|
|
||||||
peer: `wss://cloud.jazz.tools/?key=${apiKey}`,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</JazzProviderWithClerk>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
/** @type {import('tailwindcss').Config} */
|
|
||||||
module.exports = {
|
|
||||||
// NOTE: Update this to include the paths to all of your component files.
|
|
||||||
content: [
|
|
||||||
"./app/**/*.{js,jsx,ts,tsx}",
|
|
||||||
"./components/**/*.{js,jsx,ts,tsx}",
|
|
||||||
"./src/**/*.{js,jsx,ts,tsx}",
|
|
||||||
],
|
|
||||||
presets: [require("nativewind/preset")],
|
|
||||||
theme: {
|
|
||||||
extend: {},
|
|
||||||
},
|
|
||||||
plugins: [],
|
|
||||||
};
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
{
|
|
||||||
"extends": "expo/tsconfig.base",
|
|
||||||
"compilerOptions": {
|
|
||||||
"strict": true,
|
|
||||||
"moduleResolution": "bundler",
|
|
||||||
"paths": {
|
|
||||||
"@/*": ["./*"]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"include": ["**/*.ts", "**/*.tsx", "nativewind-env.d.ts"]
|
|
||||||
}
|
|
||||||
@@ -13,15 +13,13 @@
|
|||||||
"@bacons/text-decoder": "^0.0.0",
|
"@bacons/text-decoder": "^0.0.0",
|
||||||
"@bam.tech/react-native-image-resizer": "^3.0.11",
|
"@bam.tech/react-native-image-resizer": "^3.0.11",
|
||||||
"@react-native-community/netinfo": "11.4.1",
|
"@react-native-community/netinfo": "11.4.1",
|
||||||
"expo": "~53.0.9",
|
"expo": "catalog:expo",
|
||||||
"expo-clipboard": "^7.1.4",
|
"expo-clipboard": "catalog:expo",
|
||||||
"expo-secure-store": "~14.2.3",
|
"expo-secure-store": "catalog:expo",
|
||||||
"expo-sqlite": "~15.2.10",
|
"expo-sqlite": "catalog:expo",
|
||||||
"expo-status-bar": "~2.2.3",
|
|
||||||
"jazz-expo": "workspace:*",
|
|
||||||
"jazz-tools": "workspace:*",
|
"jazz-tools": "workspace:*",
|
||||||
"react": "19.0.0",
|
"react": "catalog:expo",
|
||||||
"react-native": "0.79.2",
|
"react-native": "catalog:expo",
|
||||||
"react-native-get-random-values": "^1.11.0",
|
"react-native-get-random-values": "^1.11.0",
|
||||||
"readable-stream": "^4.7.0"
|
"readable-stream": "^4.7.0"
|
||||||
},
|
},
|
||||||
@@ -31,4 +29,4 @@
|
|||||||
"typescript": "~5.8.3"
|
"typescript": "~5.8.3"
|
||||||
},
|
},
|
||||||
"private": true
|
"private": true
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import { JazzProvider } from "jazz-expo";
|
import { JazzExpoProvider } from "jazz-tools/expo";
|
||||||
import React, { StrictMode } from "react";
|
import React, { StrictMode } from "react";
|
||||||
import { apiKey } from "./apiKey";
|
import { apiKey } from "./apiKey";
|
||||||
import ChatScreen from "./chat";
|
import ChatScreen from "./chat";
|
||||||
@@ -6,13 +6,13 @@ import ChatScreen from "./chat";
|
|||||||
export default function App() {
|
export default function App() {
|
||||||
return (
|
return (
|
||||||
<StrictMode>
|
<StrictMode>
|
||||||
<JazzProvider
|
<JazzExpoProvider
|
||||||
sync={{
|
sync={{
|
||||||
peer: `wss://cloud.jazz.tools/?key=${apiKey}`,
|
peer: `wss://cloud.jazz.tools/?key=${apiKey}`,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<ChatScreen />
|
<ChatScreen />
|
||||||
</JazzProvider>
|
</JazzExpoProvider>
|
||||||
</StrictMode>
|
</StrictMode>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import React, {
|
|||||||
StyleSheet,
|
StyleSheet,
|
||||||
} from "react-native";
|
} from "react-native";
|
||||||
|
|
||||||
import { useAccount, useCoState } from "jazz-expo";
|
import { useAccount, useCoState } from "jazz-tools/expo";
|
||||||
import { Chat, Message } from "./schema";
|
import { Chat, Message } from "./schema";
|
||||||
|
|
||||||
export default function ChatScreen() {
|
export default function ChatScreen() {
|
||||||
|
|||||||
@@ -11,11 +11,11 @@ react {
|
|||||||
// The root of your project, i.e. where "package.json" lives. Default is '../..'
|
// The root of your project, i.e. where "package.json" lives. Default is '../..'
|
||||||
// root = file("../../")
|
// root = file("../../")
|
||||||
// The folder where the react-native NPM package is. Default is ../../node_modules/react-native
|
// The folder where the react-native NPM package is. Default is ../../node_modules/react-native
|
||||||
// reactNativeDir = file("../../node_modules/react-native")
|
reactNativeDir = file("../../../../node_modules/react-native")
|
||||||
// The folder where the react-native Codegen package is. Default is ../../node_modules/@react-native/codegen
|
// The folder where the react-native Codegen package is. Default is ../../node_modules/@react-native/codegen
|
||||||
// codegenDir = file("../../node_modules/@react-native/codegen")
|
codegenDir = file("../../../../node_modules/@react-native/codegen")
|
||||||
// The cli.js file which is the React Native CLI entrypoint. Default is ../../node_modules/react-native/cli.js
|
// The cli.js file which is the React Native CLI entrypoint. Default is ../../node_modules/react-native/cli.js
|
||||||
// cliFile = file("../../node_modules/react-native/cli.js")
|
cliFile = file("../../../../node_modules/react-native/cli.js")
|
||||||
|
|
||||||
/* Variants */
|
/* Variants */
|
||||||
// The list of variants to that are debuggable. For those we're going to
|
// The list of variants to that are debuggable. For those we're going to
|
||||||
@@ -63,14 +63,14 @@ def enableProguardInReleaseBuilds = false
|
|||||||
* The preferred build flavor of JavaScriptCore (JSC)
|
* The preferred build flavor of JavaScriptCore (JSC)
|
||||||
*
|
*
|
||||||
* For example, to use the international variant, you can use:
|
* For example, to use the international variant, you can use:
|
||||||
* `def jscFlavor = 'org.webkit:android-jsc-intl:+'`
|
* `def jscFlavor = io.github.react-native-community:jsc-android-intl:2026004.+`
|
||||||
*
|
*
|
||||||
* The international variant includes ICU i18n library and necessary data
|
* The international variant includes ICU i18n library and necessary data
|
||||||
* allowing to use e.g. `Date.toLocaleString` and `String.localeCompare` that
|
* allowing to use e.g. `Date.toLocaleString` and `String.localeCompare` that
|
||||||
* give correct results when using with locales other than en-US. Note that
|
* give correct results when using with locales other than en-US. Note that
|
||||||
* this variant is about 6MiB larger per architecture than default.
|
* this variant is about 6MiB larger per architecture than default.
|
||||||
*/
|
*/
|
||||||
def jscFlavor = 'org.webkit:android-jsc:+'
|
def jscFlavor = 'io.github.react-native-community:jsc-android:2026004.+'
|
||||||
|
|
||||||
android {
|
android {
|
||||||
ndkVersion rootProject.ext.ndkVersion
|
ndkVersion rootProject.ext.ndkVersion
|
||||||
|
|||||||
@@ -4,13 +4,11 @@ import android.app.Application
|
|||||||
import com.facebook.react.PackageList
|
import com.facebook.react.PackageList
|
||||||
import com.facebook.react.ReactApplication
|
import com.facebook.react.ReactApplication
|
||||||
import com.facebook.react.ReactHost
|
import com.facebook.react.ReactHost
|
||||||
|
import com.facebook.react.ReactNativeApplicationEntryPoint.loadReactNative
|
||||||
import com.facebook.react.ReactNativeHost
|
import com.facebook.react.ReactNativeHost
|
||||||
import com.facebook.react.ReactPackage
|
import com.facebook.react.ReactPackage
|
||||||
import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.load
|
|
||||||
import com.facebook.react.defaults.DefaultReactHost.getDefaultReactHost
|
import com.facebook.react.defaults.DefaultReactHost.getDefaultReactHost
|
||||||
import com.facebook.react.defaults.DefaultReactNativeHost
|
import com.facebook.react.defaults.DefaultReactNativeHost
|
||||||
import com.facebook.react.soloader.OpenSourceMergedSoMapping
|
|
||||||
import com.facebook.soloader.SoLoader
|
|
||||||
|
|
||||||
class MainApplication : Application(), ReactApplication {
|
class MainApplication : Application(), ReactApplication {
|
||||||
|
|
||||||
@@ -35,10 +33,6 @@ class MainApplication : Application(), ReactApplication {
|
|||||||
|
|
||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
super.onCreate()
|
super.onCreate()
|
||||||
SoLoader.init(this, OpenSourceMergedSoMapping)
|
loadReactNative(this)
|
||||||
if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
|
|
||||||
// If you opted-in for the New Architecture, we load the native entry point for this app.
|
|
||||||
load()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,9 +3,9 @@ buildscript {
|
|||||||
buildToolsVersion = "35.0.0"
|
buildToolsVersion = "35.0.0"
|
||||||
minSdkVersion = 24
|
minSdkVersion = 24
|
||||||
compileSdkVersion = 35
|
compileSdkVersion = 35
|
||||||
targetSdkVersion = 34
|
targetSdkVersion = 35
|
||||||
ndkVersion = "26.1.10909125"
|
ndkVersion = "27.1.12297006"
|
||||||
kotlinVersion = "1.9.25"
|
kotlinVersion = "2.1.20"
|
||||||
}
|
}
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-all.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.1-bin.zip
|
||||||
networkTimeout=10000
|
networkTimeout=10000
|
||||||
validateDistributionUrl=true
|
validateDistributionUrl=true
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
|||||||
9
examples/chat-rn/android/gradlew
vendored
@@ -86,8 +86,7 @@ done
|
|||||||
# shellcheck disable=SC2034
|
# shellcheck disable=SC2034
|
||||||
APP_BASE_NAME=${0##*/}
|
APP_BASE_NAME=${0##*/}
|
||||||
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
||||||
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s
|
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
|
||||||
' "$PWD" ) || exit
|
|
||||||
|
|
||||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||||
MAX_FD=maximum
|
MAX_FD=maximum
|
||||||
@@ -115,7 +114,7 @@ case "$( uname )" in #(
|
|||||||
NONSTOP* ) nonstop=true ;;
|
NONSTOP* ) nonstop=true ;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
CLASSPATH="\\\"\\\""
|
||||||
|
|
||||||
|
|
||||||
# Determine the Java command to use to start the JVM.
|
# Determine the Java command to use to start the JVM.
|
||||||
@@ -206,7 +205,7 @@ fi
|
|||||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||||
|
|
||||||
# Collect all arguments for the java command:
|
# Collect all arguments for the java command:
|
||||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
|
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
|
||||||
# and any embedded shellness will be escaped.
|
# and any embedded shellness will be escaped.
|
||||||
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
|
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
|
||||||
# treated as '${Hostname}' itself on the command line.
|
# treated as '${Hostname}' itself on the command line.
|
||||||
@@ -214,7 +213,7 @@ DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
|||||||
set -- \
|
set -- \
|
||||||
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||||
-classpath "$CLASSPATH" \
|
-classpath "$CLASSPATH" \
|
||||||
org.gradle.wrapper.GradleWrapperMain \
|
-jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
|
||||||
"$@"
|
"$@"
|
||||||
|
|
||||||
# Stop when "xargs" is not available.
|
# Stop when "xargs" is not available.
|
||||||
|
|||||||
9
examples/chat-rn/android/gradlew.bat
vendored
@@ -1,3 +1,8 @@
|
|||||||
|
@REM Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||||
|
@REM
|
||||||
|
@REM This source code is licensed under the MIT license found in the
|
||||||
|
@REM LICENSE file in the root directory of this source tree.
|
||||||
|
|
||||||
@rem
|
@rem
|
||||||
@rem Copyright 2015 the original author or authors.
|
@rem Copyright 2015 the original author or authors.
|
||||||
@rem
|
@rem
|
||||||
@@ -70,11 +75,11 @@ goto fail
|
|||||||
:execute
|
:execute
|
||||||
@rem Setup the command line
|
@rem Setup the command line
|
||||||
|
|
||||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
set CLASSPATH=
|
||||||
|
|
||||||
|
|
||||||
@rem Execute Gradle
|
@rem Execute Gradle
|
||||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
|
||||||
|
|
||||||
:end
|
:end
|
||||||
@rem End local scope for the variables with windows NT shell
|
@rem End local scope for the variables with windows NT shell
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
pluginManagement { includeBuild("../node_modules/@react-native/gradle-plugin") }
|
pluginManagement { includeBuild("../../../node_modules/@react-native/gradle-plugin") }
|
||||||
plugins { id("com.facebook.react.settings") }
|
plugins { id("com.facebook.react.settings") }
|
||||||
extensions.configure(com.facebook.react.ReactSettingsExtension){ ex -> ex.autolinkLibrariesFromCommand() }
|
extensions.configure(com.facebook.react.ReactSettingsExtension){ ex -> ex.autolinkLibrariesFromCommand() }
|
||||||
rootProject.name = 'ChatRN'
|
rootProject.name = 'ChatRN'
|
||||||
include ':app'
|
include ':app'
|
||||||
includeBuild('../node_modules/@react-native/gradle-plugin')
|
includeBuild('../../../node_modules/@react-native/gradle-plugin')
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
presets: ["module:@react-native/babel-preset"],
|
presets: ["module:@react-native/babel-preset"],
|
||||||
|
plugins: ["@babel/plugin-transform-export-namespace-from"],
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -7,56 +7,27 @@
|
|||||||
objects = {
|
objects = {
|
||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
00E356F31AD99517003FC87E /* ChatRNTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00E356F21AD99517003FC87E /* ChatRNTests.m */; };
|
|
||||||
0C80B921A6F3F58F76C31292 /* libPods-ChatRN.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5DCACB8F33CDC322A6C60F78 /* libPods-ChatRN.a */; };
|
0C80B921A6F3F58F76C31292 /* libPods-ChatRN.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5DCACB8F33CDC322A6C60F78 /* libPods-ChatRN.a */; };
|
||||||
13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.mm */; };
|
|
||||||
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
|
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
|
||||||
13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
|
761780ED2CA45674006654EE /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 761780EC2CA45674006654EE /* AppDelegate.swift */; };
|
||||||
7699B88040F8A987B510C191 /* libPods-ChatRN-ChatRNTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 19F6CBCC0A4E27FBF8BF4A61 /* libPods-ChatRN-ChatRNTests.a */; };
|
|
||||||
81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; };
|
81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; };
|
||||||
FDBE82F8CEBB429FCE591919 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB81A68108700A75B9A /* PrivacyInfo.xcprivacy */; };
|
927557B966FCFCEE5896C589 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB81A68108700A75B9A /* PrivacyInfo.xcprivacy */; };
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
/* Begin PBXContainerItemProxy section */
|
|
||||||
00E356F41AD99517003FC87E /* PBXContainerItemProxy */ = {
|
|
||||||
isa = PBXContainerItemProxy;
|
|
||||||
containerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */;
|
|
||||||
proxyType = 1;
|
|
||||||
remoteGlobalIDString = 13B07F861A680F5B00A75B9A;
|
|
||||||
remoteInfo = ChatRN;
|
|
||||||
};
|
|
||||||
/* End PBXContainerItemProxy section */
|
|
||||||
|
|
||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
00E356EE1AD99517003FC87E /* ChatRNTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ChatRNTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
|
||||||
00E356F11AD99517003FC87E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
|
||||||
00E356F21AD99517003FC87E /* ChatRNTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ChatRNTests.m; sourceTree = "<group>"; };
|
|
||||||
13B07F961A680F5B00A75B9A /* ChatRN.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ChatRN.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
13B07F961A680F5B00A75B9A /* ChatRN.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ChatRN.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = ChatRN/AppDelegate.h; sourceTree = "<group>"; };
|
|
||||||
13B07FB01A68108700A75B9A /* AppDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = AppDelegate.mm; path = ChatRN/AppDelegate.mm; sourceTree = "<group>"; };
|
|
||||||
13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = ChatRN/Images.xcassets; sourceTree = "<group>"; };
|
13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = ChatRN/Images.xcassets; sourceTree = "<group>"; };
|
||||||
13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = ChatRN/Info.plist; sourceTree = "<group>"; };
|
13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = ChatRN/Info.plist; sourceTree = "<group>"; };
|
||||||
13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = ChatRN/main.m; sourceTree = "<group>"; };
|
|
||||||
13B07FB81A68108700A75B9A /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = PrivacyInfo.xcprivacy; path = ChatRN/PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
|
13B07FB81A68108700A75B9A /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = PrivacyInfo.xcprivacy; path = ChatRN/PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
|
||||||
19F6CBCC0A4E27FBF8BF4A61 /* libPods-ChatRN-ChatRNTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-ChatRN-ChatRNTests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
|
||||||
3B4392A12AC88292D35C810B /* Pods-ChatRN.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ChatRN.debug.xcconfig"; path = "Target Support Files/Pods-ChatRN/Pods-ChatRN.debug.xcconfig"; sourceTree = "<group>"; };
|
3B4392A12AC88292D35C810B /* Pods-ChatRN.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ChatRN.debug.xcconfig"; path = "Target Support Files/Pods-ChatRN/Pods-ChatRN.debug.xcconfig"; sourceTree = "<group>"; };
|
||||||
5709B34CF0A7D63546082F79 /* Pods-ChatRN.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ChatRN.release.xcconfig"; path = "Target Support Files/Pods-ChatRN/Pods-ChatRN.release.xcconfig"; sourceTree = "<group>"; };
|
5709B34CF0A7D63546082F79 /* Pods-ChatRN.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ChatRN.release.xcconfig"; path = "Target Support Files/Pods-ChatRN/Pods-ChatRN.release.xcconfig"; sourceTree = "<group>"; };
|
||||||
5B7EB9410499542E8C5724F5 /* Pods-ChatRN-ChatRNTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ChatRN-ChatRNTests.debug.xcconfig"; path = "Target Support Files/Pods-ChatRN-ChatRNTests/Pods-ChatRN-ChatRNTests.debug.xcconfig"; sourceTree = "<group>"; };
|
|
||||||
5DCACB8F33CDC322A6C60F78 /* libPods-ChatRN.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-ChatRN.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
5DCACB8F33CDC322A6C60F78 /* libPods-ChatRN.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-ChatRN.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
761780EC2CA45674006654EE /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = AppDelegate.swift; path = ChatRN/AppDelegate.swift; sourceTree = "<group>"; };
|
||||||
81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = ChatRN/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = ChatRN/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||||
89C6BE57DB24E9ADA2F236DE /* Pods-ChatRN-ChatRNTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ChatRN-ChatRNTests.release.xcconfig"; path = "Target Support Files/Pods-ChatRN-ChatRNTests/Pods-ChatRN-ChatRNTests.release.xcconfig"; sourceTree = "<group>"; };
|
|
||||||
ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
|
ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
/* Begin PBXFrameworksBuildPhase section */
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
00E356EB1AD99517003FC87E /* Frameworks */ = {
|
|
||||||
isa = PBXFrameworksBuildPhase;
|
|
||||||
buildActionMask = 2147483647;
|
|
||||||
files = (
|
|
||||||
7699B88040F8A987B510C191 /* libPods-ChatRN-ChatRNTests.a in Frameworks */,
|
|
||||||
);
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
|
||||||
};
|
|
||||||
13B07F8C1A680F5B00A75B9A /* Frameworks */ = {
|
13B07F8C1A680F5B00A75B9A /* Frameworks */ = {
|
||||||
isa = PBXFrameworksBuildPhase;
|
isa = PBXFrameworksBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
@@ -68,32 +39,13 @@
|
|||||||
/* End PBXFrameworksBuildPhase section */
|
/* End PBXFrameworksBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXGroup section */
|
/* Begin PBXGroup section */
|
||||||
00E356EF1AD99517003FC87E /* ChatRNTests */ = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
00E356F21AD99517003FC87E /* ChatRNTests.m */,
|
|
||||||
00E356F01AD99517003FC87E /* Supporting Files */,
|
|
||||||
);
|
|
||||||
path = ChatRNTests;
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
00E356F01AD99517003FC87E /* Supporting Files */ = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
00E356F11AD99517003FC87E /* Info.plist */,
|
|
||||||
);
|
|
||||||
name = "Supporting Files";
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
13B07FAE1A68108700A75B9A /* ChatRN */ = {
|
13B07FAE1A68108700A75B9A /* ChatRN */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
13B07FAF1A68108700A75B9A /* AppDelegate.h */,
|
|
||||||
13B07FB01A68108700A75B9A /* AppDelegate.mm */,
|
|
||||||
13B07FB51A68108700A75B9A /* Images.xcassets */,
|
13B07FB51A68108700A75B9A /* Images.xcassets */,
|
||||||
|
761780EC2CA45674006654EE /* AppDelegate.swift */,
|
||||||
13B07FB61A68108700A75B9A /* Info.plist */,
|
13B07FB61A68108700A75B9A /* Info.plist */,
|
||||||
81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */,
|
81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */,
|
||||||
13B07FB71A68108700A75B9A /* main.m */,
|
|
||||||
13B07FB81A68108700A75B9A /* PrivacyInfo.xcprivacy */,
|
13B07FB81A68108700A75B9A /* PrivacyInfo.xcprivacy */,
|
||||||
);
|
);
|
||||||
name = ChatRN;
|
name = ChatRN;
|
||||||
@@ -104,7 +56,6 @@
|
|||||||
children = (
|
children = (
|
||||||
ED297162215061F000B7C4FE /* JavaScriptCore.framework */,
|
ED297162215061F000B7C4FE /* JavaScriptCore.framework */,
|
||||||
5DCACB8F33CDC322A6C60F78 /* libPods-ChatRN.a */,
|
5DCACB8F33CDC322A6C60F78 /* libPods-ChatRN.a */,
|
||||||
19F6CBCC0A4E27FBF8BF4A61 /* libPods-ChatRN-ChatRNTests.a */,
|
|
||||||
);
|
);
|
||||||
name = Frameworks;
|
name = Frameworks;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -121,7 +72,6 @@
|
|||||||
children = (
|
children = (
|
||||||
13B07FAE1A68108700A75B9A /* ChatRN */,
|
13B07FAE1A68108700A75B9A /* ChatRN */,
|
||||||
832341AE1AAA6A7D00B99B32 /* Libraries */,
|
832341AE1AAA6A7D00B99B32 /* Libraries */,
|
||||||
00E356EF1AD99517003FC87E /* ChatRNTests */,
|
|
||||||
83CBBA001A601CBA00E9B192 /* Products */,
|
83CBBA001A601CBA00E9B192 /* Products */,
|
||||||
2D16E6871FA4F8E400B85C8A /* Frameworks */,
|
2D16E6871FA4F8E400B85C8A /* Frameworks */,
|
||||||
BBD78D7AC51CEA395F1C20DB /* Pods */,
|
BBD78D7AC51CEA395F1C20DB /* Pods */,
|
||||||
@@ -135,7 +85,6 @@
|
|||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
13B07F961A680F5B00A75B9A /* ChatRN.app */,
|
13B07F961A680F5B00A75B9A /* ChatRN.app */,
|
||||||
00E356EE1AD99517003FC87E /* ChatRNTests.xctest */,
|
|
||||||
);
|
);
|
||||||
name = Products;
|
name = Products;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -145,8 +94,6 @@
|
|||||||
children = (
|
children = (
|
||||||
3B4392A12AC88292D35C810B /* Pods-ChatRN.debug.xcconfig */,
|
3B4392A12AC88292D35C810B /* Pods-ChatRN.debug.xcconfig */,
|
||||||
5709B34CF0A7D63546082F79 /* Pods-ChatRN.release.xcconfig */,
|
5709B34CF0A7D63546082F79 /* Pods-ChatRN.release.xcconfig */,
|
||||||
5B7EB9410499542E8C5724F5 /* Pods-ChatRN-ChatRNTests.debug.xcconfig */,
|
|
||||||
89C6BE57DB24E9ADA2F236DE /* Pods-ChatRN-ChatRNTests.release.xcconfig */,
|
|
||||||
);
|
);
|
||||||
path = Pods;
|
path = Pods;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -154,27 +101,6 @@
|
|||||||
/* End PBXGroup section */
|
/* End PBXGroup section */
|
||||||
|
|
||||||
/* Begin PBXNativeTarget section */
|
/* Begin PBXNativeTarget section */
|
||||||
00E356ED1AD99517003FC87E /* ChatRNTests */ = {
|
|
||||||
isa = PBXNativeTarget;
|
|
||||||
buildConfigurationList = 00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget "ChatRNTests" */;
|
|
||||||
buildPhases = (
|
|
||||||
A55EABD7B0C7F3A422A6CC61 /* [CP] Check Pods Manifest.lock */,
|
|
||||||
00E356EA1AD99517003FC87E /* Sources */,
|
|
||||||
00E356EB1AD99517003FC87E /* Frameworks */,
|
|
||||||
00E356EC1AD99517003FC87E /* Resources */,
|
|
||||||
C59DA0FBD6956966B86A3779 /* [CP] Embed Pods Frameworks */,
|
|
||||||
F6A41C54EA430FDDC6A6ED99 /* [CP] Copy Pods Resources */,
|
|
||||||
);
|
|
||||||
buildRules = (
|
|
||||||
);
|
|
||||||
dependencies = (
|
|
||||||
00E356F51AD99517003FC87E /* PBXTargetDependency */,
|
|
||||||
);
|
|
||||||
name = ChatRNTests;
|
|
||||||
productName = ChatRNTests;
|
|
||||||
productReference = 00E356EE1AD99517003FC87E /* ChatRNTests.xctest */;
|
|
||||||
productType = "com.apple.product-type.bundle.unit-test";
|
|
||||||
};
|
|
||||||
13B07F861A680F5B00A75B9A /* ChatRN */ = {
|
13B07F861A680F5B00A75B9A /* ChatRN */ = {
|
||||||
isa = PBXNativeTarget;
|
isa = PBXNativeTarget;
|
||||||
buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "ChatRN" */;
|
buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "ChatRN" */;
|
||||||
@@ -204,10 +130,6 @@
|
|||||||
attributes = {
|
attributes = {
|
||||||
LastUpgradeCheck = 1210;
|
LastUpgradeCheck = 1210;
|
||||||
TargetAttributes = {
|
TargetAttributes = {
|
||||||
00E356ED1AD99517003FC87E = {
|
|
||||||
CreatedOnToolsVersion = 6.2;
|
|
||||||
TestTargetID = 13B07F861A680F5B00A75B9A;
|
|
||||||
};
|
|
||||||
13B07F861A680F5B00A75B9A = {
|
13B07F861A680F5B00A75B9A = {
|
||||||
LastSwiftMigration = 1120;
|
LastSwiftMigration = 1120;
|
||||||
};
|
};
|
||||||
@@ -227,26 +149,18 @@
|
|||||||
projectRoot = "";
|
projectRoot = "";
|
||||||
targets = (
|
targets = (
|
||||||
13B07F861A680F5B00A75B9A /* ChatRN */,
|
13B07F861A680F5B00A75B9A /* ChatRN */,
|
||||||
00E356ED1AD99517003FC87E /* ChatRNTests */,
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
/* End PBXProject section */
|
/* End PBXProject section */
|
||||||
|
|
||||||
/* Begin PBXResourcesBuildPhase section */
|
/* Begin PBXResourcesBuildPhase section */
|
||||||
00E356EC1AD99517003FC87E /* Resources */ = {
|
|
||||||
isa = PBXResourcesBuildPhase;
|
|
||||||
buildActionMask = 2147483647;
|
|
||||||
files = (
|
|
||||||
);
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
|
||||||
};
|
|
||||||
13B07F8E1A680F5B00A75B9A /* Resources */ = {
|
13B07F8E1A680F5B00A75B9A /* Resources */ = {
|
||||||
isa = PBXResourcesBuildPhase;
|
isa = PBXResourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */,
|
81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */,
|
||||||
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */,
|
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */,
|
||||||
FDBE82F8CEBB429FCE591919 /* PrivacyInfo.xcprivacy in Resources */,
|
927557B966FCFCEE5896C589 /* PrivacyInfo.xcprivacy in Resources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
@@ -286,28 +200,6 @@
|
|||||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-ChatRN/Pods-ChatRN-frameworks.sh\"\n";
|
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-ChatRN/Pods-ChatRN-frameworks.sh\"\n";
|
||||||
showEnvVarsInLog = 0;
|
showEnvVarsInLog = 0;
|
||||||
};
|
};
|
||||||
A55EABD7B0C7F3A422A6CC61 /* [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-ChatRN-ChatRNTests-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;
|
|
||||||
};
|
|
||||||
C38B50BA6285516D6DCD4F65 /* [CP] Check Pods Manifest.lock */ = {
|
C38B50BA6285516D6DCD4F65 /* [CP] Check Pods Manifest.lock */ = {
|
||||||
isa = PBXShellScriptBuildPhase;
|
isa = PBXShellScriptBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
@@ -330,23 +222,6 @@
|
|||||||
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";
|
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;
|
showEnvVarsInLog = 0;
|
||||||
};
|
};
|
||||||
C59DA0FBD6956966B86A3779 /* [CP] Embed Pods Frameworks */ = {
|
|
||||||
isa = PBXShellScriptBuildPhase;
|
|
||||||
buildActionMask = 2147483647;
|
|
||||||
files = (
|
|
||||||
);
|
|
||||||
inputFileListPaths = (
|
|
||||||
"${PODS_ROOT}/Target Support Files/Pods-ChatRN-ChatRNTests/Pods-ChatRN-ChatRNTests-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
|
||||||
);
|
|
||||||
name = "[CP] Embed Pods Frameworks";
|
|
||||||
outputFileListPaths = (
|
|
||||||
"${PODS_ROOT}/Target Support Files/Pods-ChatRN-ChatRNTests/Pods-ChatRN-ChatRNTests-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
|
||||||
);
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
|
||||||
shellPath = /bin/sh;
|
|
||||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-ChatRN-ChatRNTests/Pods-ChatRN-ChatRNTests-frameworks.sh\"\n";
|
|
||||||
showEnvVarsInLog = 0;
|
|
||||||
};
|
|
||||||
E235C05ADACE081382539298 /* [CP] Copy Pods Resources */ = {
|
E235C05ADACE081382539298 /* [CP] Copy Pods Resources */ = {
|
||||||
isa = PBXShellScriptBuildPhase;
|
isa = PBXShellScriptBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
@@ -364,105 +239,20 @@
|
|||||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-ChatRN/Pods-ChatRN-resources.sh\"\n";
|
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-ChatRN/Pods-ChatRN-resources.sh\"\n";
|
||||||
showEnvVarsInLog = 0;
|
showEnvVarsInLog = 0;
|
||||||
};
|
};
|
||||||
F6A41C54EA430FDDC6A6ED99 /* [CP] Copy Pods Resources */ = {
|
|
||||||
isa = PBXShellScriptBuildPhase;
|
|
||||||
buildActionMask = 2147483647;
|
|
||||||
files = (
|
|
||||||
);
|
|
||||||
inputFileListPaths = (
|
|
||||||
"${PODS_ROOT}/Target Support Files/Pods-ChatRN-ChatRNTests/Pods-ChatRN-ChatRNTests-resources-${CONFIGURATION}-input-files.xcfilelist",
|
|
||||||
);
|
|
||||||
name = "[CP] Copy Pods Resources";
|
|
||||||
outputFileListPaths = (
|
|
||||||
"${PODS_ROOT}/Target Support Files/Pods-ChatRN-ChatRNTests/Pods-ChatRN-ChatRNTests-resources-${CONFIGURATION}-output-files.xcfilelist",
|
|
||||||
);
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
|
||||||
shellPath = /bin/sh;
|
|
||||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-ChatRN-ChatRNTests/Pods-ChatRN-ChatRNTests-resources.sh\"\n";
|
|
||||||
showEnvVarsInLog = 0;
|
|
||||||
};
|
|
||||||
/* End PBXShellScriptBuildPhase section */
|
/* End PBXShellScriptBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXSourcesBuildPhase section */
|
/* Begin PBXSourcesBuildPhase section */
|
||||||
00E356EA1AD99517003FC87E /* Sources */ = {
|
|
||||||
isa = PBXSourcesBuildPhase;
|
|
||||||
buildActionMask = 2147483647;
|
|
||||||
files = (
|
|
||||||
00E356F31AD99517003FC87E /* ChatRNTests.m in Sources */,
|
|
||||||
);
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
|
||||||
};
|
|
||||||
13B07F871A680F5B00A75B9A /* Sources */ = {
|
13B07F871A680F5B00A75B9A /* Sources */ = {
|
||||||
isa = PBXSourcesBuildPhase;
|
isa = PBXSourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */,
|
761780ED2CA45674006654EE /* AppDelegate.swift in Sources */,
|
||||||
13B07FC11A68108700A75B9A /* main.m in Sources */,
|
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
/* End PBXSourcesBuildPhase section */
|
/* End PBXSourcesBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXTargetDependency section */
|
|
||||||
00E356F51AD99517003FC87E /* PBXTargetDependency */ = {
|
|
||||||
isa = PBXTargetDependency;
|
|
||||||
target = 13B07F861A680F5B00A75B9A /* ChatRN */;
|
|
||||||
targetProxy = 00E356F41AD99517003FC87E /* PBXContainerItemProxy */;
|
|
||||||
};
|
|
||||||
/* End PBXTargetDependency section */
|
|
||||||
|
|
||||||
/* Begin XCBuildConfiguration section */
|
/* Begin XCBuildConfiguration section */
|
||||||
00E356F61AD99517003FC87E /* Debug */ = {
|
|
||||||
isa = XCBuildConfiguration;
|
|
||||||
baseConfigurationReference = 5B7EB9410499542E8C5724F5 /* Pods-ChatRN-ChatRNTests.debug.xcconfig */;
|
|
||||||
buildSettings = {
|
|
||||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
|
||||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
|
||||||
"DEBUG=1",
|
|
||||||
"$(inherited)",
|
|
||||||
);
|
|
||||||
INFOPLIST_FILE = ChatRNTests/Info.plist;
|
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 15.1;
|
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
|
||||||
"$(inherited)",
|
|
||||||
"@executable_path/Frameworks",
|
|
||||||
"@loader_path/Frameworks",
|
|
||||||
);
|
|
||||||
OTHER_LDFLAGS = (
|
|
||||||
"-ObjC",
|
|
||||||
"-lc++",
|
|
||||||
"$(inherited)",
|
|
||||||
);
|
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)";
|
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
|
||||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/ChatRN.app/ChatRN";
|
|
||||||
};
|
|
||||||
name = Debug;
|
|
||||||
};
|
|
||||||
00E356F71AD99517003FC87E /* Release */ = {
|
|
||||||
isa = XCBuildConfiguration;
|
|
||||||
baseConfigurationReference = 89C6BE57DB24E9ADA2F236DE /* Pods-ChatRN-ChatRNTests.release.xcconfig */;
|
|
||||||
buildSettings = {
|
|
||||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
|
||||||
COPY_PHASE_STRIP = NO;
|
|
||||||
INFOPLIST_FILE = ChatRNTests/Info.plist;
|
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 15.1;
|
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
|
||||||
"$(inherited)",
|
|
||||||
"@executable_path/Frameworks",
|
|
||||||
"@loader_path/Frameworks",
|
|
||||||
);
|
|
||||||
OTHER_LDFLAGS = (
|
|
||||||
"-ObjC",
|
|
||||||
"-lc++",
|
|
||||||
"$(inherited)",
|
|
||||||
);
|
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)";
|
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
|
||||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/ChatRN.app/ChatRN";
|
|
||||||
};
|
|
||||||
name = Release;
|
|
||||||
};
|
|
||||||
13B07F941A680F5B00A75B9A /* Debug */ = {
|
13B07F941A680F5B00A75B9A /* Debug */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
baseConfigurationReference = 3B4392A12AC88292D35C810B /* Pods-ChatRN.debug.xcconfig */;
|
baseConfigurationReference = 3B4392A12AC88292D35C810B /* Pods-ChatRN.debug.xcconfig */;
|
||||||
@@ -672,15 +462,6 @@
|
|||||||
/* End XCBuildConfiguration section */
|
/* End XCBuildConfiguration section */
|
||||||
|
|
||||||
/* Begin XCConfigurationList section */
|
/* Begin XCConfigurationList section */
|
||||||
00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget "ChatRNTests" */ = {
|
|
||||||
isa = XCConfigurationList;
|
|
||||||
buildConfigurations = (
|
|
||||||
00E356F61AD99517003FC87E /* Debug */,
|
|
||||||
00E356F71AD99517003FC87E /* Release */,
|
|
||||||
);
|
|
||||||
defaultConfigurationIsVisible = 0;
|
|
||||||
defaultConfigurationName = Release;
|
|
||||||
};
|
|
||||||
13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "ChatRN" */ = {
|
13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "ChatRN" */ = {
|
||||||
isa = XCConfigurationList;
|
isa = XCConfigurationList;
|
||||||
buildConfigurations = (
|
buildConfigurations = (
|
||||||
|
|||||||
7
examples/chat-rn/ios/ChatRN.xcodeproj/project.xcworkspace/contents.xcworkspacedata
generated
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Workspace
|
||||||
|
version = "1.0">
|
||||||
|
<FileRef
|
||||||
|
location = "self:">
|
||||||
|
</FileRef>
|
||||||
|
</Workspace>
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
#import <RCTAppDelegate.h>
|
|
||||||
#import <UIKit/UIKit.h>
|
|
||||||
|
|
||||||
@interface AppDelegate : RCTAppDelegate
|
|
||||||
|
|
||||||
@end
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
#import "AppDelegate.h"
|
|
||||||
|
|
||||||
#import <React/RCTBundleURLProvider.h>
|
|
||||||
|
|
||||||
@implementation AppDelegate
|
|
||||||
|
|
||||||
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
|
|
||||||
{
|
|
||||||
self.moduleName = @"ChatRN";
|
|
||||||
// You can add your custom initial props in the dictionary below.
|
|
||||||
// They will be passed down to the ViewController used by React Native.
|
|
||||||
self.initialProps = @{};
|
|
||||||
|
|
||||||
return [super application:application didFinishLaunchingWithOptions:launchOptions];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
|
|
||||||
{
|
|
||||||
return [self bundleURL];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSURL *)bundleURL
|
|
||||||
{
|
|
||||||
#if DEBUG
|
|
||||||
return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index"];
|
|
||||||
#else
|
|
||||||
return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
|
||||||
48
examples/chat-rn/ios/ChatRN/AppDelegate.swift
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
import UIKit
|
||||||
|
import React
|
||||||
|
import React_RCTAppDelegate
|
||||||
|
import ReactAppDependencyProvider
|
||||||
|
|
||||||
|
@main
|
||||||
|
class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||||
|
var window: UIWindow?
|
||||||
|
|
||||||
|
var reactNativeDelegate: ReactNativeDelegate?
|
||||||
|
var reactNativeFactory: RCTReactNativeFactory?
|
||||||
|
|
||||||
|
func application(
|
||||||
|
_ application: UIApplication,
|
||||||
|
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil
|
||||||
|
) -> Bool {
|
||||||
|
let delegate = ReactNativeDelegate()
|
||||||
|
let factory = RCTReactNativeFactory(delegate: delegate)
|
||||||
|
delegate.dependencyProvider = RCTAppDependencyProvider()
|
||||||
|
|
||||||
|
reactNativeDelegate = delegate
|
||||||
|
reactNativeFactory = factory
|
||||||
|
|
||||||
|
window = UIWindow(frame: UIScreen.main.bounds)
|
||||||
|
|
||||||
|
factory.startReactNative(
|
||||||
|
withModuleName: "ChatRN",
|
||||||
|
in: window,
|
||||||
|
launchOptions: launchOptions
|
||||||
|
)
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ReactNativeDelegate: RCTDefaultReactNativeFactoryDelegate {
|
||||||
|
override func sourceURL(for bridge: RCTBridge) -> URL? {
|
||||||
|
self.bundleURL()
|
||||||
|
}
|
||||||
|
|
||||||
|
override func bundleURL() -> URL? {
|
||||||
|
#if DEBUG
|
||||||
|
RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: "index")
|
||||||
|
#else
|
||||||
|
Bundle.main.url(forResource: "main", withExtension: "jsbundle")
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -34,6 +34,8 @@
|
|||||||
</dict>
|
</dict>
|
||||||
<key>NSLocationWhenInUseUsageDescription</key>
|
<key>NSLocationWhenInUseUsageDescription</key>
|
||||||
<string></string>
|
<string></string>
|
||||||
|
<key>RCTNewArchEnabled</key>
|
||||||
|
<true/>
|
||||||
<key>UILaunchStoryboardName</key>
|
<key>UILaunchStoryboardName</key>
|
||||||
<string>LaunchScreen</string>
|
<string>LaunchScreen</string>
|
||||||
<key>UIRequiredDeviceCapabilities</key>
|
<key>UIRequiredDeviceCapabilities</key>
|
||||||
|
|||||||
@@ -1,10 +0,0 @@
|
|||||||
#import <UIKit/UIKit.h>
|
|
||||||
|
|
||||||
#import "AppDelegate.h"
|
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
|
||||||
{
|
|
||||||
@autoreleasepool {
|
|
||||||
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -23,11 +23,6 @@ target 'ChatRN' do
|
|||||||
:app_path => "#{Pod::Config.instance.installation_root}/.."
|
:app_path => "#{Pod::Config.instance.installation_root}/.."
|
||||||
)
|
)
|
||||||
|
|
||||||
target 'ChatRNTests' do
|
|
||||||
inherit! :complete
|
|
||||||
# Pods for testing
|
|
||||||
end
|
|
||||||
|
|
||||||
post_install do |installer|
|
post_install do |installer|
|
||||||
# https://github.com/facebook/react-native/blob/main/packages/react-native/scripts/react_native_pods.rb#L197-L202
|
# https://github.com/facebook/react-native/blob/main/packages/react-native/scripts/react_native_pods.rb#L197-L202
|
||||||
react_native_post_install(
|
react_native_post_install(
|
||||||
|
|||||||
@@ -12,45 +12,38 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@azure/core-asynciterator-polyfill": "^1.0.2",
|
"@azure/core-asynciterator-polyfill": "^1.0.2",
|
||||||
"@bacons/text-decoder": "0.0.0",
|
"@bacons/text-decoder": "0.0.0",
|
||||||
"@op-engineering/op-sqlite": "^11.4.8",
|
"@op-engineering/op-sqlite": "14.1.0",
|
||||||
"@react-native-clipboard/clipboard": "1.16.1",
|
"@react-native-clipboard/clipboard": "1.16.3",
|
||||||
"@react-native-community/netinfo": "11.4.1",
|
"@react-native-community/netinfo": "11.4.1",
|
||||||
"@react-navigation/native": "7.0.19",
|
"@react-navigation/native": "7.1.14",
|
||||||
"@react-navigation/native-stack": "7.2.1",
|
"@react-navigation/native-stack": "7.3.19",
|
||||||
"clsx": "^2.0.0",
|
|
||||||
"cojson": "workspace:*",
|
|
||||||
"cojson-transport-ws": "workspace:*",
|
|
||||||
"jazz-react-native": "workspace:*",
|
|
||||||
"jazz-tools": "workspace:*",
|
"jazz-tools": "workspace:*",
|
||||||
"react": "19.0.0",
|
"react": "catalog:rn",
|
||||||
"react-native": "0.79.2",
|
"react-native": "catalog:rn",
|
||||||
"react-native-get-random-values": "^1.11.0",
|
"react-native-get-random-values": "^1.11.0",
|
||||||
"react-native-mmkv": "^3.2.0",
|
"react-native-mmkv": "3.3.0",
|
||||||
"react-native-polyfill-globals": "^3.1.0",
|
"react-native-safe-area-context": "5.5.0",
|
||||||
"react-native-safe-area-context": "4.12.0",
|
"react-native-screens": "4.11.1",
|
||||||
"react-native-screens": "4.4.0",
|
|
||||||
"react-native-url-polyfill": "^2.0.0",
|
|
||||||
"readable-stream": "4.7.0"
|
"readable-stream": "4.7.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.25.2",
|
"@babel/core": "^7.25.2",
|
||||||
|
"@babel/plugin-transform-export-namespace-from": "^7.27.1",
|
||||||
"@babel/preset-env": "^7.25.3",
|
"@babel/preset-env": "^7.25.3",
|
||||||
"@babel/runtime": "^7.25.0",
|
"@babel/runtime": "^7.25.0",
|
||||||
"@react-native-community/cli": "15.0.1",
|
"@react-native-community/cli": "catalog:rn",
|
||||||
"@react-native-community/cli-platform-android": "15.0.1",
|
"@react-native-community/cli-platform-android": "catalog:rn",
|
||||||
"@react-native-community/cli-platform-ios": "15.0.1",
|
"@react-native-community/cli-platform-ios": "catalog:rn",
|
||||||
"@react-native/babel-preset": "0.76.9",
|
"@react-native/babel-preset": "catalog:rn",
|
||||||
"@react-native/eslint-config": "0.76.9",
|
"@react-native/eslint-config": "catalog:rn",
|
||||||
"@react-native/metro-config": "0.76.9",
|
"@react-native/metro-config": "catalog:rn",
|
||||||
"@react-native/typescript-config": "0.76.9",
|
"@react-native/typescript-config": "catalog:rn",
|
||||||
"@rnx-kit/metro-config": "^2.0.1",
|
"@rnx-kit/metro-config": "^2.0.1",
|
||||||
"@rnx-kit/metro-resolver-symlinks": "^0.2.1",
|
"@rnx-kit/metro-resolver-symlinks": "^0.2.5",
|
||||||
"@types/react": "^18.3.12",
|
"@types/react": "catalog:rn",
|
||||||
"@types/react-test-renderer": "^18.0.0",
|
|
||||||
"eslint": "^8.19.0",
|
"eslint": "^8.19.0",
|
||||||
"pod-install": "^0.3.5",
|
"pod-install": "^0.3.5",
|
||||||
"prettier": "2.8.8",
|
"prettier": "2.8.8",
|
||||||
"react-test-renderer": "18.3.1",
|
|
||||||
"typescript": "5.6.2"
|
"typescript": "5.6.2"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import {
|
|||||||
useNavigationContainerRef,
|
useNavigationContainerRef,
|
||||||
} from "@react-navigation/native";
|
} from "@react-navigation/native";
|
||||||
import { createNativeStackNavigator } from "@react-navigation/native-stack";
|
import { createNativeStackNavigator } from "@react-navigation/native-stack";
|
||||||
import { JazzProvider } from "jazz-react-native";
|
import { JazzReactNativeProvider } from "jazz-tools/react-native";
|
||||||
import React, { StrictMode, useEffect, useState } from "react";
|
import React, { StrictMode, useEffect, useState } from "react";
|
||||||
import { Linking } from "react-native";
|
import { Linking } from "react-native";
|
||||||
import { apiKey } from "./apiKey";
|
import { apiKey } from "./apiKey";
|
||||||
@@ -49,7 +49,7 @@ function App() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<StrictMode>
|
<StrictMode>
|
||||||
<JazzProvider
|
<JazzReactNativeProvider
|
||||||
sync={{
|
sync={{
|
||||||
peer: `wss://cloud.jazz.tools/?key=${apiKey}`,
|
peer: `wss://cloud.jazz.tools/?key=${apiKey}`,
|
||||||
}}
|
}}
|
||||||
@@ -67,7 +67,7 @@ function App() {
|
|||||||
/>
|
/>
|
||||||
</Stack.Navigator>
|
</Stack.Navigator>
|
||||||
</NavigationContainer>
|
</NavigationContainer>
|
||||||
</JazzProvider>
|
</JazzReactNativeProvider>
|
||||||
</StrictMode>
|
</StrictMode>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import Clipboard from "@react-native-clipboard/clipboard";
|
import Clipboard from "@react-native-clipboard/clipboard";
|
||||||
import { useAccount, useCoState } from "jazz-react-native";
|
|
||||||
import { CoPlainText, Group, ID, Loaded, Profile } from "jazz-tools";
|
import { CoPlainText, Group, ID, Loaded, Profile } from "jazz-tools";
|
||||||
|
import { useAccount, useCoState } from "jazz-tools/react-native";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
@@ -76,7 +76,9 @@ export function ChatScreen({ navigation }: { navigation: any }) {
|
|||||||
|
|
||||||
const renderMessageItem = ({
|
const renderMessageItem = ({
|
||||||
item,
|
item,
|
||||||
}: { item: Loaded<typeof Message, { text: true }> }) => {
|
}: {
|
||||||
|
item: Loaded<typeof Message, { text: true }>;
|
||||||
|
}) => {
|
||||||
const isMe = item._edits?.text?.by?.isMe;
|
const isMe = item._edits?.text?.by?.isMe;
|
||||||
return (
|
return (
|
||||||
<View
|
<View
|
||||||
|
|||||||
@@ -1,14 +1,10 @@
|
|||||||
import { useAcceptInvite } from "jazz-react-native";
|
import { useAcceptInviteNative } from "jazz-tools/react-native";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { Text } from "react-native";
|
import { Text } from "react-native";
|
||||||
import { Chat } from "./schema";
|
import { Chat } from "./schema";
|
||||||
|
|
||||||
export function HandleInviteScreen({
|
export function HandleInviteScreen({ navigation }: { navigation: any }) {
|
||||||
navigation,
|
useAcceptInviteNative({
|
||||||
}: {
|
|
||||||
navigation: any;
|
|
||||||
}) {
|
|
||||||
useAcceptInvite({
|
|
||||||
invitedObjectSchema: Chat,
|
invitedObjectSchema: Chat,
|
||||||
onAccept: async (chatId) => {
|
onAccept: async (chatId) => {
|
||||||
navigation.navigate("ChatScreen", { chatId });
|
navigation.navigate("ChatScreen", { chatId });
|
||||||
|
|||||||
@@ -1,5 +1,235 @@
|
|||||||
# passkey-svelte
|
# passkey-svelte
|
||||||
|
|
||||||
|
## 0.0.118
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [5963658]
|
||||||
|
- jazz-tools@0.17.5
|
||||||
|
|
||||||
|
## 0.0.117
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [7dd3d00]
|
||||||
|
- jazz-tools@0.17.4
|
||||||
|
|
||||||
|
## 0.0.116
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-tools@0.17.3
|
||||||
|
|
||||||
|
## 0.0.115
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [794681a]
|
||||||
|
- Updated dependencies [83fc22f]
|
||||||
|
- jazz-tools@0.17.2
|
||||||
|
|
||||||
|
## 0.0.114
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [0bcbf55]
|
||||||
|
- Updated dependencies [d1bdbf5]
|
||||||
|
- Updated dependencies [4b73834]
|
||||||
|
- jazz-tools@0.17.1
|
||||||
|
|
||||||
|
## 0.0.113
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [fcaf4b9]
|
||||||
|
- jazz-tools@0.17.0
|
||||||
|
|
||||||
|
## 0.0.112
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [67e0968]
|
||||||
|
- Updated dependencies [2c8120d]
|
||||||
|
- jazz-tools@0.16.6
|
||||||
|
|
||||||
|
## 0.0.111
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [3cd1586]
|
||||||
|
- Updated dependencies [33ebbf0]
|
||||||
|
- jazz-tools@0.16.5
|
||||||
|
|
||||||
|
## 0.0.110
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [16764f6]
|
||||||
|
- jazz-tools@0.16.4
|
||||||
|
|
||||||
|
## 0.0.109
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [43d3511]
|
||||||
|
- jazz-tools@0.16.3
|
||||||
|
|
||||||
|
## 0.0.108
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-tools@0.16.2
|
||||||
|
|
||||||
|
## 0.0.107
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [c62abef]
|
||||||
|
- jazz-tools@0.16.1
|
||||||
|
|
||||||
|
## 0.0.106
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- 2bbb07b: Introduce a cleaner separation between Zod and CoValue schemas:
|
||||||
|
- Zod schemas and CoValue schemas are fully separated. Zod schemas can only be composed with other Zod schemas. CoValue schemas can be composed with either Zod or other CoValue schemas.
|
||||||
|
- `z.optional()` and `z.discriminatedUnion()` no longer work with CoValue schemas. Use `co.optional()` and `co.discriminatedUnion()` instead.
|
||||||
|
- Internal schema access is now simpler. You no longer need to use Zod’s `.def` to access internals. Use properties like `CoMapSchema.shape`, `CoListSchema.element`, and `CoOptionalSchema.innerType` directly.
|
||||||
|
- CoValue schema types are now namespaced under `co.`. Non-namespaced exports have been removed
|
||||||
|
- CoMap schemas no longer incorrectly inherit from Zod. Previously, methods like `.extend()` and `.partial()` appeared available but could cause unexpected behavior. These methods are now disabled. In their place, `.optional()` has been added, and more Zod-like methods will be introduced in future releases.
|
||||||
|
- Upgraded Zod from `3.25.28` to `3.25.76`.
|
||||||
|
- Removed deprecated `withHelpers` method from CoValue schemas
|
||||||
|
- Removed deprecated `createCoValueObservable` function
|
||||||
|
- Updated dependencies [c09dcdf]
|
||||||
|
- Updated dependencies [2bbb07b]
|
||||||
|
- jazz-tools@0.16.0
|
||||||
|
|
||||||
|
## 0.0.105
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [9633d01]
|
||||||
|
- Updated dependencies [4beafb7]
|
||||||
|
- jazz-tools@0.15.16
|
||||||
|
|
||||||
|
## 0.0.104
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [3fe53a3]
|
||||||
|
- jazz-tools@0.15.15
|
||||||
|
|
||||||
|
## 0.0.103
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [a584590]
|
||||||
|
- Updated dependencies [9acccb5]
|
||||||
|
- jazz-tools@0.15.14
|
||||||
|
|
||||||
|
## 0.0.102
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [6c76ff8]
|
||||||
|
- jazz-tools@0.15.13
|
||||||
|
|
||||||
|
## 0.0.101
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [d1c1b0c]
|
||||||
|
- Updated dependencies [cf4ad72]
|
||||||
|
- jazz-tools@0.15.12
|
||||||
|
|
||||||
|
## 0.0.100
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [bdc9aee]
|
||||||
|
- jazz-tools@0.15.11
|
||||||
|
|
||||||
|
## 0.0.99
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [9815ec6]
|
||||||
|
- Updated dependencies [b4fdab4]
|
||||||
|
- jazz-tools@0.15.10
|
||||||
|
|
||||||
|
## 0.0.98
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [27b4837]
|
||||||
|
- jazz-tools@0.15.9
|
||||||
|
|
||||||
|
## 0.0.97
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [3844666]
|
||||||
|
- jazz-tools@0.15.8
|
||||||
|
|
||||||
|
## 0.0.96
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [c09b636]
|
||||||
|
- jazz-tools@0.15.7
|
||||||
|
|
||||||
|
## 0.0.95
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [a5ceaff]
|
||||||
|
- jazz-tools@0.15.6
|
||||||
|
|
||||||
|
## 0.0.94
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [23bfea5]
|
||||||
|
- Updated dependencies [e4ba23c]
|
||||||
|
- Updated dependencies [4b89838]
|
||||||
|
- jazz-tools@0.15.5
|
||||||
|
|
||||||
|
## 0.0.93
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-tools@0.15.4
|
||||||
|
|
||||||
|
## 0.0.92
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [45f73a7]
|
||||||
|
- jazz-tools@0.15.3
|
||||||
|
|
||||||
|
## 0.0.91
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [0e7e532]
|
||||||
|
- jazz-tools@0.15.2
|
||||||
|
|
||||||
|
## 0.0.90
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [0e3a4d2]
|
||||||
|
- Updated dependencies [b110f00]
|
||||||
|
- jazz-tools@0.15.1
|
||||||
|
|
||||||
|
## 0.0.89
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [1378a1f]
|
||||||
|
- Updated dependencies [0fa051a]
|
||||||
|
- jazz-tools@0.15.0
|
||||||
|
|
||||||
## 0.0.88
|
## 0.0.88
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -65,4 +65,4 @@ If you have feedback, let us know on [Discord](https://discord.gg/utDMjHYg42) or
|
|||||||
|
|
||||||
By default, the example app uses [Jazz Cloud](https://jazz.tools/cloud) (`wss://cloud.jazz.tools`) - so cross-device use, invites and collaboration should just work.
|
By default, the example app uses [Jazz Cloud](https://jazz.tools/cloud) (`wss://cloud.jazz.tools`) - so cross-device use, invites and collaboration should just work.
|
||||||
|
|
||||||
You can also run a local sync server by running `npx jazz-run sync`, and setting the `sync` parameter of `JazzProvider` in [./src/routes/+layout.svelte](./src/routes/+layout.svelte) to `{ peer: "ws://localhost:4200" }`.
|
You can also run a local sync server by running `npx jazz-run sync`, and setting the `sync` parameter of `JazzSvelteProvider` in [./src/routes/+layout.svelte](./src/routes/+layout.svelte) to `{ peer: "ws://localhost:4200" }`.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "chat-svelte",
|
"name": "chat-svelte",
|
||||||
"version": "0.0.88",
|
"version": "0.0.118",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
@@ -25,7 +25,6 @@
|
|||||||
"eslint-config-prettier": "^9.1.0",
|
"eslint-config-prettier": "^9.1.0",
|
||||||
"eslint-plugin-svelte": "^2.46.1",
|
"eslint-plugin-svelte": "^2.46.1",
|
||||||
"globals": "^15.15.0",
|
"globals": "^15.15.0",
|
||||||
"jazz-inspector-element": "workspace:*",
|
|
||||||
"prettier": "^3.5.3",
|
"prettier": "^3.5.3",
|
||||||
"prettier-plugin-svelte": "^3.4.0",
|
"prettier-plugin-svelte": "^3.4.0",
|
||||||
"svelte": "^5.31.1",
|
"svelte": "^5.31.1",
|
||||||
@@ -36,8 +35,6 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@tailwindcss/vite": "^4.1.7",
|
"@tailwindcss/vite": "^4.1.7",
|
||||||
"jazz-browser-media-images": "workspace:*",
|
|
||||||
"jazz-svelte": "workspace:*",
|
|
||||||
"jazz-tools": "workspace:*",
|
"jazz-tools": "workspace:*",
|
||||||
"tailwindcss": "^4.1.7"
|
"tailwindcss": "^4.1.7"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { ImageDefinition, type Loaded } from 'jazz-tools';
|
import { ImageDefinition, type Loaded } from 'jazz-tools';
|
||||||
import { useProgressiveImg } from '$lib/utils/useProgressiveImage.svelte';
|
import { Image } from 'jazz-tools/svelte';
|
||||||
let { image }: { image: Loaded<typeof ImageDefinition> } = $props();
|
let { image }: { image: Loaded<typeof ImageDefinition> } = $props();
|
||||||
const { src } = $derived(
|
|
||||||
useProgressiveImg({
|
|
||||||
image
|
|
||||||
})
|
|
||||||
);
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<img class="h-auto max-h-[20rem] max-w-full rounded-t-xl mb-1" {src} alt="" />
|
<Image
|
||||||
|
imageId={image.id}
|
||||||
|
alt=""
|
||||||
|
class="h-auto max-h-[20rem] max-w-full rounded-t-xl mb-1"
|
||||||
|
/>
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { co, z } from 'jazz-tools';
|
import { co } from 'jazz-tools';
|
||||||
|
|
||||||
export const Message = co.map({
|
export const Message = co.map({
|
||||||
text: co.plainText(),
|
text: co.plainText(),
|
||||||
image: z.optional(co.image())
|
image: co.optional(co.image())
|
||||||
});
|
});
|
||||||
|
|
||||||
export const Chat = co.list(Message);
|
export const Chat = co.list(Message);
|
||||||
|
|||||||
@@ -1,53 +0,0 @@
|
|||||||
import { ImageDefinition, type Loaded } from 'jazz-tools';
|
|
||||||
import { onDestroy } from 'svelte';
|
|
||||||
|
|
||||||
export function useProgressiveImg({
|
|
||||||
image,
|
|
||||||
maxWidth,
|
|
||||||
targetWidth
|
|
||||||
}: {
|
|
||||||
image: Loaded<typeof ImageDefinition> | null | undefined;
|
|
||||||
maxWidth?: number;
|
|
||||||
targetWidth?: number;
|
|
||||||
}) {
|
|
||||||
let current = $state<{
|
|
||||||
src?: string;
|
|
||||||
res?: `${number}x${number}` | 'placeholder';
|
|
||||||
}>();
|
|
||||||
const originalSize = $state(image?.originalSize);
|
|
||||||
|
|
||||||
const unsubscribe = image?.subscribe({}, (update: Loaded<typeof ImageDefinition>) => {
|
|
||||||
const highestRes = ImageDefinition.highestResAvailable(update, { maxWidth, targetWidth });
|
|
||||||
if (highestRes) {
|
|
||||||
if (highestRes.res !== current?.res) {
|
|
||||||
const blob = highestRes.stream.toBlob();
|
|
||||||
if (blob) {
|
|
||||||
const blobURI = URL.createObjectURL(blob);
|
|
||||||
current = { src: blobURI, res: highestRes.res };
|
|
||||||
|
|
||||||
setTimeout(() => URL.revokeObjectURL(blobURI), 200);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
current = {
|
|
||||||
src: update?.placeholderDataURL,
|
|
||||||
res: 'placeholder'
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
onDestroy(() => () => {
|
|
||||||
unsubscribe?.();
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
get src() {
|
|
||||||
return current?.src;
|
|
||||||
},
|
|
||||||
get res() {
|
|
||||||
return current?.res;
|
|
||||||
},
|
|
||||||
|
|
||||||
originalSize
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import 'jazz-tools/inspector/register-custom-element';
|
||||||
|
|
||||||
import '../app.css';
|
import '../app.css';
|
||||||
import { JazzProvider } from 'jazz-svelte';
|
import { JazzSvelteProvider } from 'jazz-tools/svelte';
|
||||||
import 'jazz-inspector-element';
|
|
||||||
import { page } from '$app/state';
|
|
||||||
import { apiKey } from '../apiKey';
|
import { apiKey } from '../apiKey';
|
||||||
import { getRandomUsername } from '$lib/utils';
|
import { getRandomUsername } from '$lib/utils';
|
||||||
let { children } = $props();
|
let { children } = $props();
|
||||||
@@ -14,14 +14,14 @@
|
|||||||
</svelte:head>
|
</svelte:head>
|
||||||
|
|
||||||
<div class="h-full bg-white text-stone-700 dark:text-stone-400 dark:bg-stone-925">
|
<div class="h-full bg-white text-stone-700 dark:text-stone-400 dark:bg-stone-925">
|
||||||
<JazzProvider
|
<JazzSvelteProvider
|
||||||
sync={{
|
sync={{
|
||||||
peer: `wss://cloud.jazz.tools/?key=${apiKey}`
|
peer: `wss://cloud.jazz.tools/?key=${apiKey}`
|
||||||
}}
|
}}
|
||||||
{defaultProfileName}
|
{defaultProfileName}
|
||||||
>
|
>
|
||||||
{@render children?.()}
|
{@render children?.()}
|
||||||
</JazzProvider>
|
</JazzSvelteProvider>
|
||||||
<jazz-inspector></jazz-inspector>
|
<jazz-inspector></jazz-inspector>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { goto } from '$app/navigation';
|
import { goto } from '$app/navigation';
|
||||||
import { Chat } from '$lib/schema';
|
import { Chat } from '$lib/schema';
|
||||||
import { AccountCoState } from 'jazz-svelte';
|
import { AccountCoState } from 'jazz-tools/svelte';
|
||||||
import { Account, Group } from 'jazz-tools';
|
import { Account, Group } from 'jazz-tools';
|
||||||
|
|
||||||
const account = new AccountCoState(Account);
|
const account = new AccountCoState(Account);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { createImage } from 'jazz-browser-media-images';
|
import { createImage } from 'jazz-tools/media';
|
||||||
import { AccountCoState, CoState } from 'jazz-svelte';
|
import { AccountCoState, CoState } from 'jazz-tools/svelte';
|
||||||
import { Account, CoPlainText, type ID } from 'jazz-tools';
|
import { Account, CoPlainText, type ID } from 'jazz-tools';
|
||||||
|
|
||||||
import { page } from '$app/state';
|
import { page } from '$app/state';
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { expect } from 'vitest';
|
|
||||||
import { ChatPage } from './pages/ChatPage';
|
import { ChatPage } from './pages/ChatPage';
|
||||||
import { test } from '@playwright/test';
|
import { test } from '@playwright/test';
|
||||||
|
|
||||||
|
|||||||
@@ -1,40 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div
|
|
||||||
class="p-3 bg-white border-t shadow-2xl mt-auto dark:bg-transparent dark:border-stone-800"
|
|
||||||
>
|
|
||||||
<label class="sr-only" :for="inputId">Type a message and press Enter</label>
|
|
||||||
<input
|
|
||||||
:id="inputId"
|
|
||||||
v-model="inputValue"
|
|
||||||
class="rounded-full py-2 px-4 text-sm border block w-full dark:bg-black dark:text-white dark:border-stone-700"
|
|
||||||
placeholder="Type a message and press Enter"
|
|
||||||
maxlength="2048"
|
|
||||||
@keydown.enter.prevent="submitMessage"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import { defineComponent, ref } from "vue";
|
|
||||||
|
|
||||||
export default defineComponent({
|
|
||||||
name: "ChatInput",
|
|
||||||
emits: ["submit"],
|
|
||||||
setup(_, { emit }) {
|
|
||||||
const inputId = `input-${Math.random().toString(36).substr(2, 9)}`;
|
|
||||||
const inputValue = ref("");
|
|
||||||
|
|
||||||
function submitMessage() {
|
|
||||||
if (!inputValue.value) return;
|
|
||||||
emit("submit", inputValue.value);
|
|
||||||
inputValue.value = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
inputId,
|
|
||||||
inputValue,
|
|
||||||
submitMessage,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
import { DemoAuthBasicUI, JazzProvider } from "jazz-vue";
|
|
||||||
import { createApp, defineComponent, h } from "vue";
|
|
||||||
import App from "./App.vue";
|
|
||||||
import "./index.css";
|
|
||||||
import { apiKey } from "@/apiKey";
|
|
||||||
import router from "./router";
|
|
||||||
|
|
||||||
const RootComponent = defineComponent({
|
|
||||||
name: "RootComponent",
|
|
||||||
setup() {
|
|
||||||
return () =>
|
|
||||||
h(
|
|
||||||
JazzProvider,
|
|
||||||
{
|
|
||||||
sync: {
|
|
||||||
peer: `wss://cloud.jazz.tools/?key=${apiKey}`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
h(
|
|
||||||
DemoAuthBasicUI,
|
|
||||||
{
|
|
||||||
appName: "Jazz Vue Chat",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
default: () => h(App),
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const app = createApp(RootComponent);
|
|
||||||
|
|
||||||
app.use(router);
|
|
||||||
|
|
||||||
app.mount("#app");
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
import { CoList, CoMap, CoPlainText, coField } from "jazz-tools";
|
|
||||||
|
|
||||||
export class Message extends CoMap {
|
|
||||||
text = coField.ref(CoPlainText);
|
|
||||||
}
|
|
||||||
|
|
||||||
export class Chat extends CoList.Of(coField.ref(Message)) {}
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div>Creating a new chat...</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { Group } from "jazz-tools";
|
|
||||||
import { useAccount } from "jazz-vue";
|
|
||||||
import { useRouter } from "vue-router";
|
|
||||||
import { Chat } from "../schema";
|
|
||||||
|
|
||||||
const router = useRouter();
|
|
||||||
const { me } = useAccount();
|
|
||||||
|
|
||||||
if (me.value) {
|
|
||||||
const group = Group.create({ owner: me.value });
|
|
||||||
group.addMember("everyone", "writer");
|
|
||||||
const chat = Chat.create([], { owner: group });
|
|
||||||
router.push(`/chat/${chat.id}`);
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
@@ -60,4 +60,4 @@ If you have feedback, let us know on [Discord](https://discord.gg/utDMjHYg42) or
|
|||||||
|
|
||||||
By default, the example app uses [Jazz Cloud](https://jazz.tools/cloud) (`wss://cloud.jazz.tools`) - so cross-device use, invites and collaboration should just work.
|
By default, the example app uses [Jazz Cloud](https://jazz.tools/cloud) (`wss://cloud.jazz.tools`) - so cross-device use, invites and collaboration should just work.
|
||||||
|
|
||||||
You can also run a local sync server by running `npx jazz-run sync`, and setting the `sync` parameter of `JazzProvider` in [./src/app.tsx](./src/app.tsx) to `{ peer: "ws://localhost:4200" }`.
|
You can also run a local sync server by running `npx jazz-run sync`, and setting the `sync` parameter of `JazzReactProvider` in [./src/app.tsx](./src/app.tsx) to `{ peer: "ws://localhost:4200" }`.
|
||||||
|
|||||||
@@ -14,24 +14,22 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"clsx": "^2.0.0",
|
"clsx": "^2.0.0",
|
||||||
"hash-slash": "workspace:*",
|
"hash-slash": "workspace:*",
|
||||||
"jazz-inspector": "workspace:*",
|
|
||||||
"jazz-react": "workspace:*",
|
|
||||||
"jazz-tools": "workspace:*",
|
"jazz-tools": "workspace:*",
|
||||||
"lucide-react": "^0.274.0",
|
"lucide-react": "^0.536.0",
|
||||||
"react": "19.0.0",
|
"react": "catalog:react",
|
||||||
"react-dom": "19.0.0",
|
"react-dom": "catalog:react",
|
||||||
"zod": "3.25.28"
|
"zod": "3.25.76"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@playwright/test": "^1.50.1",
|
"@playwright/test": "^1.50.1",
|
||||||
"@tailwindcss/postcss": "^4.1.10",
|
"@tailwindcss/postcss": "^4.1.10",
|
||||||
"@types/react": "19.0.0",
|
"@types/react": "catalog:react",
|
||||||
"@types/react-dom": "19.0.0",
|
"@types/react-dom": "catalog:react",
|
||||||
"@vitejs/plugin-react-swc": "^3.10.1",
|
"@vitejs/plugin-react-swc": "^3.10.1",
|
||||||
"is-ci": "^3.0.1",
|
"is-ci": "^3.0.1",
|
||||||
"postcss": "^8.4.40",
|
"postcss": "^8.4.40",
|
||||||
"tailwindcss": "^4.1.10",
|
"tailwindcss": "^4.1.10",
|
||||||
"typescript": "5.6.2",
|
"typescript": "catalog:default",
|
||||||
"vite": "6.3.5"
|
"vite": "catalog:default"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
import { apiKey } from "@/apiKey.ts";
|
import { apiKey } from "@/apiKey.ts";
|
||||||
import { getRandomUsername, inIframe, onChatLoad } from "@/util.ts";
|
import { getRandomUsername, inIframe, onChatLoad } from "@/util.ts";
|
||||||
import { useIframeHashRouter } from "hash-slash";
|
import { useIframeHashRouter } from "hash-slash";
|
||||||
import { JazzInspector } from "jazz-inspector";
|
|
||||||
import { JazzProvider, useAccount } from "jazz-react";
|
|
||||||
import { Group } from "jazz-tools";
|
import { Group } from "jazz-tools";
|
||||||
|
import { JazzInspector } from "jazz-tools/inspector";
|
||||||
|
import { JazzReactProvider, useAccount } from "jazz-tools/react";
|
||||||
import { StrictMode } from "react";
|
import { StrictMode } from "react";
|
||||||
import { createRoot } from "react-dom/client";
|
import { createRoot } from "react-dom/client";
|
||||||
import { ChatScreen } from "./chatScreen.tsx";
|
import { ChatScreen } from "./chatScreen.tsx";
|
||||||
@@ -55,7 +55,7 @@ const defaultProfileName = url.searchParams.get("user") ?? getRandomUsername();
|
|||||||
createRoot(document.getElementById("root")!).render(
|
createRoot(document.getElementById("root")!).render(
|
||||||
<ThemeProvider>
|
<ThemeProvider>
|
||||||
<StrictMode>
|
<StrictMode>
|
||||||
<JazzProvider
|
<JazzReactProvider
|
||||||
sync={{
|
sync={{
|
||||||
peer: `wss://cloud.jazz.tools/?key=${apiKey}`,
|
peer: `wss://cloud.jazz.tools/?key=${apiKey}`,
|
||||||
}}
|
}}
|
||||||
@@ -63,7 +63,7 @@ createRoot(document.getElementById("root")!).render(
|
|||||||
>
|
>
|
||||||
<App />
|
<App />
|
||||||
<JazzInspector />
|
<JazzInspector />
|
||||||
</JazzProvider>
|
</JazzReactProvider>
|
||||||
</StrictMode>
|
</StrictMode>
|
||||||
</ThemeProvider>,
|
</ThemeProvider>,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { createImage, useAccount, useCoState } from "jazz-react";
|
import { Account } from "jazz-tools";
|
||||||
import { Account, co } from "jazz-tools";
|
import { createImage } from "jazz-tools/media";
|
||||||
import { useState } from "react";
|
import { useAccount, useCoState } from "jazz-tools/react";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
import { Chat, Message } from "./schema.ts";
|
import { Chat, Message } from "./schema.ts";
|
||||||
import {
|
import {
|
||||||
BubbleBody,
|
BubbleBody,
|
||||||
@@ -15,14 +16,17 @@ import {
|
|||||||
TextInput,
|
TextInput,
|
||||||
} from "./ui.tsx";
|
} from "./ui.tsx";
|
||||||
|
|
||||||
export function ChatScreen(props: { chatID: string }) {
|
const INITIAL_MESSAGES_TO_SHOW = 30;
|
||||||
const chat = useCoState(Chat, props.chatID, {
|
|
||||||
resolve: { $each: { text: true } },
|
|
||||||
});
|
|
||||||
const account = useAccount();
|
|
||||||
const [showNLastMessages, setShowNLastMessages] = useState(30);
|
|
||||||
|
|
||||||
if (!chat)
|
export function ChatScreen(props: { chatID: string }) {
|
||||||
|
const chat = useCoState(Chat, props.chatID);
|
||||||
|
const { me } = useAccount();
|
||||||
|
const [showNLastMessages, setShowNLastMessages] = useState(
|
||||||
|
INITIAL_MESSAGES_TO_SHOW,
|
||||||
|
);
|
||||||
|
const isLoading = useMessagesPreload(props.chatID);
|
||||||
|
|
||||||
|
if (!chat || isLoading)
|
||||||
return (
|
return (
|
||||||
<div className="flex-1 flex justify-center items-center">Loading...</div>
|
<div className="flex-1 flex justify-center items-center">Loading...</div>
|
||||||
);
|
);
|
||||||
@@ -37,11 +41,15 @@ export function ChatScreen(props: { chatID: string }) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
createImage(file, { owner: chat._owner }).then((image) => {
|
createImage(file, {
|
||||||
|
owner: chat._owner,
|
||||||
|
progressive: true,
|
||||||
|
placeholder: "blur",
|
||||||
|
}).then((image) => {
|
||||||
chat.push(
|
chat.push(
|
||||||
Message.create(
|
Message.create(
|
||||||
{
|
{
|
||||||
text: co.plainText().create(file.name, chat._owner),
|
text: file.name,
|
||||||
image: image,
|
image: image,
|
||||||
},
|
},
|
||||||
chat._owner,
|
chat._owner,
|
||||||
@@ -50,14 +58,23 @@ export function ChatScreen(props: { chatID: string }) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (!me) {
|
||||||
|
return <div>Loading...</div>;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ChatBody>
|
<ChatBody>
|
||||||
{chat.length > 0 ? (
|
{chat.length > 0 ? (
|
||||||
chat
|
chat
|
||||||
|
// We call slice before reverse to avoid mutating the original array
|
||||||
.slice(-showNLastMessages)
|
.slice(-showNLastMessages)
|
||||||
.reverse() // this plus flex-col-reverse on ChatBody gives us scroll-to-bottom behavior
|
// Reverse plus flex-col-reverse on ChatBody gives us scroll-to-bottom behavior
|
||||||
.map((msg) => <ChatBubble me={account.me} msg={msg} key={msg.id} />)
|
.reverse()
|
||||||
|
.map(
|
||||||
|
(msg) =>
|
||||||
|
msg?.text && <ChatBubble me={me} msg={msg} key={msg.id} />,
|
||||||
|
)
|
||||||
) : (
|
) : (
|
||||||
<EmptyChatMessage />
|
<EmptyChatMessage />
|
||||||
)}
|
)}
|
||||||
@@ -76,12 +93,7 @@ export function ChatScreen(props: { chatID: string }) {
|
|||||||
|
|
||||||
<TextInput
|
<TextInput
|
||||||
onSubmit={(text) => {
|
onSubmit={(text) => {
|
||||||
chat.push(
|
chat.push(Message.create({ text }, chat._owner));
|
||||||
Message.create(
|
|
||||||
{ text: co.plainText().create(text, chat._owner) },
|
|
||||||
chat._owner,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</InputBar>
|
</InputBar>
|
||||||
@@ -89,10 +101,7 @@ export function ChatScreen(props: { chatID: string }) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function ChatBubble(props: {
|
function ChatBubble(props: { me: Account; msg: Message }) {
|
||||||
me: Account;
|
|
||||||
msg: co.loaded<typeof Message, { text: true }>;
|
|
||||||
}) {
|
|
||||||
if (!props.me.canRead(props.msg) || !props.msg.text?.toString()) {
|
if (!props.me.canRead(props.msg) || !props.msg.text?.toString()) {
|
||||||
return (
|
return (
|
||||||
<BubbleContainer fromMe={false}>
|
<BubbleContainer fromMe={false}>
|
||||||
@@ -122,3 +131,35 @@ function ChatBubble(props: {
|
|||||||
</BubbleContainer>
|
</BubbleContainer>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Warms the local cache with the initial messages to load only the initial messages
|
||||||
|
* and avoid flickering
|
||||||
|
*/
|
||||||
|
function useMessagesPreload(chatID: string) {
|
||||||
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
preloadChatMessages(chatID).finally(() => {
|
||||||
|
setIsLoading(false);
|
||||||
|
});
|
||||||
|
}, [chatID]);
|
||||||
|
|
||||||
|
return isLoading;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function preloadChatMessages(chatID: string) {
|
||||||
|
const chat = await Chat.load(chatID);
|
||||||
|
|
||||||
|
if (!chat?._refs) return;
|
||||||
|
|
||||||
|
const promises = [];
|
||||||
|
|
||||||
|
for (const msg of Array.from(chat._refs)
|
||||||
|
.reverse()
|
||||||
|
.slice(0, INITIAL_MESSAGES_TO_SHOW)) {
|
||||||
|
promises.push(Message.load(msg.id, { resolve: { text: true } }));
|
||||||
|
}
|
||||||
|
|
||||||
|
await Promise.all(promises);
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { co, z } from "jazz-tools";
|
import { co } from "jazz-tools";
|
||||||
|
|
||||||
export const Message = co.map({
|
export const Message = co.map({
|
||||||
text: co.plainText(),
|
text: co.plainText(),
|
||||||
image: z.optional(co.image()),
|
image: co.optional(co.image()),
|
||||||
});
|
});
|
||||||
export type Message = co.loaded<typeof Message>;
|
export type Message = co.loaded<typeof Message>;
|
||||||
|
|
||||||
|
|||||||