Compare commits
892 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
730729b2f1 | ||
|
b5d2e7806f | ||
|
a48d234c56 | ||
|
34fbe9f018 | ||
|
dc0c931917 | ||
|
af32c09966 | ||
|
584b9e440e | ||
|
2a65be9e33 | ||
|
630dbb486f | ||
|
8ec88e697b | ||
|
987a9d4587 | ||
|
42c5e6c1d7 | ||
|
39f6eb9b51 | ||
|
156186b1c9 | ||
|
e97114eee2 | ||
|
0719075808 | ||
|
aa93296968 | ||
|
5506bf85f9 | ||
|
1b75996fab | ||
|
2057f39390 | ||
|
d9badbe19c | ||
|
6c173507a5 | ||
|
541572809a | ||
|
eafa99f771 | ||
|
48897f71d2 | ||
|
812895129f | ||
|
e5c077bd78 | ||
|
d79bc8c84a | ||
|
efb14d9961 | ||
|
2e4e318e17 | ||
|
26e63a11a5 | ||
|
dfb44ab923 | ||
|
7aa97b6cc7 | ||
|
d02b1d1eef | ||
|
020cfec21b | ||
|
154f5eaa82 | ||
|
2c1dad91de | ||
|
b66871f6bd | ||
|
6a1dd637ce | ||
|
3a8e52ceb0 | ||
|
bf5e999a00 | ||
|
2c0a46abf2 | ||
|
669d808c89 | ||
|
fa3f77ef51 | ||
|
05d6c3cf1a | ||
|
2d9b184bd5 | ||
|
60cfdb38fb | ||
|
f4eb0e604b | ||
|
2b13cf3ce2 | ||
|
afea0a5339 | ||
|
be55d5a675 | ||
|
bdf7bed717 | ||
|
78dbbfbc75 | ||
|
dd9a3e87a3 | ||
|
d4066fc32a | ||
|
5a29338cce | ||
|
ea18e429c9 | ||
|
b16fc2ddec | ||
|
d8f06f1b46 | ||
|
84f1bfa1cc | ||
|
17a8e4a6af | ||
|
e9748dd79f | ||
|
a4e1163e13 | ||
|
3a9c3338e0 | ||
|
b26fd1d381 | ||
|
d2c8150675 | ||
|
17e5377587 | ||
|
df4b1d4461 | ||
|
89a9f1b348 | ||
|
26d48f4fe1 | ||
|
0b0a0a283c | ||
|
b2dc1df6f3 | ||
|
563a316695 | ||
|
c65bdb49e2 | ||
|
3ae1c8c611 | ||
|
be124d22d8 | ||
|
d8584653ce | ||
|
16f4f12810 | ||
|
fae77d8ea1 | ||
|
d8c7992512 | ||
|
2b7a0aa6da | ||
|
1ebbe1e391 | ||
|
f511bc15ec | ||
|
16cda14d9a | ||
|
6ee084e1a0 | ||
|
4126d00920 | ||
|
ac5ec74787 | ||
|
185dfe415a | ||
|
4c2944e89c | ||
|
9f6af155b8 | ||
|
5d442dbe33 | ||
|
011d9d837f | ||
|
75ce9e32a6 | ||
|
13dccf5b30 | ||
|
984cc2c13c | ||
|
5e034880af | ||
|
fb6d55abe9 | ||
|
b60eac426d | ||
|
0df5033f1d | ||
|
749c7f3884 | ||
|
c145dd4a7c | ||
|
53f9d3c62b | ||
|
34b017b66d | ||
|
aaa8761e4d | ||
|
352d3b11e3 | ||
|
4f0c6ef5a5 | ||
|
6f201f9cf5 | ||
|
06cce1a912 | ||
|
eb3a1e099a | ||
|
4a398b0a50 | ||
|
1cec46533d | ||
|
64e5db0c06 | ||
|
774af5843a | ||
|
c4da728abc | ||
|
e8c4147fe7 | ||
|
b9727214a3 | ||
|
9206d0f1f9 | ||
|
45f0ba7e1a | ||
|
87936379fa | ||
|
259a61cb1c | ||
|
6db6825a61 | ||
|
e5132f05cc | ||
|
b134c81c86 | ||
|
99d35b78c5 | ||
|
2514485ca4 | ||
|
deb048d1b3 | ||
|
2af69259fa | ||
|
008877a07b | ||
|
cbe33d9fde | ||
|
f6fb4e7323 | ||
|
e53da83c00 | ||
|
2d1af689a5 | ||
|
a697b2fa25 | ||
|
a8eb24e9a5 | ||
|
02cb5ee3b8 | ||
|
5f322703c3 | ||
|
a922d93cbd | ||
|
fbef596514 | ||
|
019f3cd668 | ||
|
700c32789c | ||
|
58b40d9802 | ||
|
e34f01d0f2 | ||
|
67c9d5b0bf | ||
|
79bd0bdb66 | ||
|
ac687e99dc | ||
|
388d354e81 | ||
|
4d0e9db710 | ||
|
8be234024e | ||
|
895894bb44 | ||
|
47666fbcb0 | ||
|
9592d0d48f | ||
|
515b3331bf | ||
|
3a67194358 | ||
|
20e525f361 | ||
|
77a1241bf5 | ||
|
4127ce580f | ||
|
6cd4916b79 | ||
|
c54d62c956 | ||
|
a1b733d25c | ||
|
b53109388e | ||
|
51ae925c5b | ||
|
b0d5bfeb33 | ||
|
14ad44be66 | ||
|
4c027c3519 | ||
|
1ed6bc4dc4 | ||
|
4614121827 | ||
|
350187cf66 | ||
|
ac44ea966a | ||
|
43f1e24e56 | ||
|
c641e10f41 | ||
|
e3935b7982 | ||
|
9778c7698e | ||
|
35a3a70aec | ||
|
dbd5db9528 | ||
|
dc859b4e31 | ||
|
28bd7c7d38 | ||
|
66977e62b3 | ||
|
8c66cb9e97 | ||
|
7cc1ffe4e3 | ||
|
624c62c009 | ||
|
180bf262c5 | ||
|
6deedababd | ||
|
369d965df9 | ||
|
e02a1b6418 | ||
|
e89d804472 | ||
|
87a3c0e129 | ||
|
2606cbe4af | ||
|
7290ac0005 | ||
|
067da659b6 | ||
|
5e2a52cdda | ||
|
ccc5745ab7 | ||
|
99ae5afa12 | ||
|
0bdf4faf56 | ||
|
2e3134a6ff | ||
|
bfac2f534c | ||
|
08b39010cd | ||
|
4d63117f04 | ||
|
dc8deb95a5 | ||
|
757ab0ae8e | ||
|
72a1b7cc28 | ||
|
8107937833 | ||
|
7b56190877 | ||
|
ec91516f7d | ||
|
489ee0485e | ||
|
1e85fc1da6 | ||
|
3a565003ad | ||
|
660b17e3b9 | ||
|
9d99189ab3 | ||
|
9e4253345c | ||
|
70e51db2c3 | ||
|
e42c32ef83 | ||
|
2e2a8dd99e | ||
|
63b0b9f090 | ||
|
1ab0515271 | ||
|
5b459e0a71 | ||
|
43bb5d337b | ||
|
c54fa1a87c | ||
|
a55b20bd02 | ||
|
6af01cca3e | ||
|
333c710a75 | ||
|
9c56539ffa | ||
|
2598a6eba4 | ||
|
7ea55d93fe | ||
|
b2ccfb76b5 | ||
|
4158c041ab | ||
|
b0f578365d | ||
|
61f6573233 | ||
|
b0efbc775d | ||
|
e66fd63bf2 | ||
|
3dd51d9e6b | ||
|
d54b6db628 | ||
|
680570536e | ||
|
3661d7b286 | ||
|
a15c07eb7f | ||
|
9a77913454 | ||
|
18cd2af907 | ||
|
97c77b6cc7 | ||
|
37379c87d9 | ||
|
a692ef99b8 | ||
|
b544282660 | ||
|
928b732e95 | ||
|
920943f476 | ||
|
8a40d2a7cf | ||
|
33fdb2fe7a | ||
|
1a798f8c03 | ||
|
81e0d671d0 | ||
|
2c5cc54279 | ||
|
39df2a2e6a | ||
|
6bcd50d4cb | ||
|
08eee3736a | ||
|
e0498e50ae | ||
|
2eb37fa75e | ||
|
a54bdc22ab | ||
|
b561190ca2 | ||
|
29ca556d43 | ||
|
f9e6a49144 | ||
|
d340d3d6b8 | ||
|
1da6c6d991 | ||
|
d2aad79ad3 | ||
|
c5af9a5daa | ||
|
b818b56832 | ||
|
2498e086d4 | ||
|
7cd41c3fd4 | ||
|
510eb66b6e | ||
|
7fb8191485 | ||
|
1f22d7b97a | ||
|
5486d703b0 | ||
|
f6948b1ba6 | ||
|
5730710fb6 | ||
|
835c00faf4 | ||
|
4891bd52bf | ||
|
72685e3c6c | ||
|
9a35078679 | ||
|
1b04512fc4 | ||
|
b9bce8bd98 | ||
|
629c2d1c6f | ||
|
a4e40f7dbe | ||
|
058bc900aa | ||
|
a598cd8d8b | ||
|
0762a72c30 | ||
|
d65dfe09ee | ||
|
8ee17a70dc | ||
|
126355fab1 | ||
|
3c4fe7d132 | ||
|
61683bf1c8 | ||
|
194314d049 | ||
|
a1315a6f2b | ||
|
6e870909cc | ||
|
2f54b7fe77 | ||
|
f403050864 | ||
|
2e24ba6954 | ||
|
780881e43d | ||
|
2e9dad004b | ||
|
3a5dbc5e9f | ||
|
86ac79265c | ||
|
282cbfd92a | ||
|
1afef963e7 | ||
|
bdf855c325 | ||
|
14ae878356 | ||
|
59a42dd204 | ||
|
1f65f44134 | ||
|
565edb3fe4 | ||
|
7e80b08a79 | ||
|
3627cc5e16 | ||
|
7da512570e | ||
|
35e91f47c8 | ||
|
a6c5487f3e | ||
|
b0727533c7 | ||
|
8df64b416b | ||
|
95519583f2 | ||
|
cd6c24d0dd | ||
|
44613c4844 | ||
|
eb1cf9652a | ||
|
18ce6f3484 | ||
|
58781a0d44 | ||
|
c40b9416df | ||
|
a74e84c267 | ||
|
b46bb3f119 | ||
|
3139327ab5 | ||
|
45c6e55181 | ||
|
b78c9e5862 | ||
|
683eece5b3 | ||
|
6c2f927106 | ||
|
c84a099c82 | ||
|
c4c16d02a6 | ||
|
cfca0be03b | ||
|
c0ea34a316 | ||
|
93f0bd505e | ||
|
d495809d53 | ||
|
df3f0344f1 | ||
|
69299252a4 | ||
|
dab4e491d7 | ||
|
a67091b621 | ||
|
c9e143c513 | ||
|
d9ffa15289 | ||
|
b27db37ff0 | ||
|
3b0f109324 | ||
|
e5ba6a37d7 | ||
|
ebf3ca269a | ||
|
dd6a6fb1dc | ||
|
217c9f4161 | ||
|
2e9e69f73d | ||
|
5d1f68d2c0 | ||
|
0fdfbae56f | ||
|
8cbcaba1ac | ||
|
51d6aa06b1 | ||
|
5f542ff1c4 | ||
|
25fac4c7c9 | ||
|
ff943638a1 | ||
|
0b8307214c | ||
|
cff533041e | ||
|
f56e76716d | ||
|
cd99aaa02d | ||
|
0dcadc521b | ||
|
e54bbad1d2 | ||
|
393ef20578 | ||
|
ff56c9b8e0 | ||
|
1396db7695 | ||
|
6514c9808a | ||
|
2a559b5d27 | ||
|
7b0f9b4d5d | ||
|
2d9ea81c21 | ||
|
4c614eaa0a | ||
|
3d2967bf5b | ||
|
fe6102cb4b | ||
|
e6f0a7f2af | ||
|
676c02e985 | ||
|
68e3055ecf | ||
|
8c53bdf8e0 | ||
|
5d507189d8 | ||
|
3b48cdbd7c | ||
|
26b1c3ba13 | ||
|
adef4265dc | ||
|
ee1644c2f6 | ||
|
4a8ef07ada | ||
|
c294ce886e | ||
|
f8e4f6021a | ||
|
a07bb31780 | ||
|
12e15f9385 | ||
|
c7409f3edd | ||
|
5866af7c54 | ||
|
3dd548d131 | ||
|
ac457cc236 | ||
|
2514cbea78 | ||
|
c316883c27 | ||
|
edbc7a437b | ||
|
bafe8197d6 | ||
|
3ecb661220 | ||
|
f2eacbd09b | ||
|
a6dad168b1 | ||
|
219a749891 | ||
|
f58ec21af5 | ||
|
6bc2395fd0 | ||
|
ee017a42d9 | ||
|
49b1ad4be0 | ||
|
9ad10551b8 | ||
|
32ba21d4d1 | ||
|
a6da07f2a2 | ||
|
55f044e8df | ||
|
e175abc8dc | ||
|
025a953bb3 | ||
|
b8291cac39 | ||
|
117b5598e7 | ||
|
acec9a96c2 | ||
|
13f0c0c91e | ||
|
5e4b20aef6 | ||
|
7014c34944 | ||
|
b5d4bf9ce1 | ||
|
3a22a513c2 | ||
|
335e8789cf | ||
|
5a2840e86a | ||
|
2fc619f262 | ||
|
1d74df830b | ||
|
8ed5a8c23a | ||
|
408a19a4f6 | ||
|
f2e994bd15 | ||
|
289fc5256a | ||
|
6f4c5082be | ||
|
3589030968 | ||
|
29d05a8045 | ||
|
5a71dbeb2a | ||
|
d4ed20cbe8 | ||
|
06933cc335 | ||
|
706459dee8 | ||
|
8a67d0a94b | ||
|
c7428f48d5 | ||
|
23c6de264f | ||
|
e36f715215 | ||
|
b56c7e9c6b | ||
|
0fc03952b6 | ||
|
20bf5c4338 | ||
|
07ed8db2b5 | ||
|
520c09ae0d | ||
|
0d1a0bb2f4 | ||
|
75c07263e8 | ||
|
e90d3d2b23 | ||
|
9b725a6231 | ||
|
dc62d212ad | ||
|
d48e919ff5 | ||
|
a6bd074a92 | ||
|
ea51f37f0f | ||
|
32eb95d20f | ||
|
495513a841 | ||
|
4d3570fc57 | ||
|
90b03fd8fa | ||
|
2831d4d060 | ||
|
f89137758d | ||
|
711d70ddfd | ||
|
585a15345c | ||
|
5fe420aebd | ||
|
f4e1907f43 | ||
|
f4bc0d0c4c | ||
|
148fd31681 | ||
|
c9bb73a2af | ||
|
a0695507fb | ||
|
71ed0039dc | ||
|
0b73827385 | ||
|
7fd134e099 | ||
|
193b55ab87 | ||
|
f9a7680130 | ||
|
b3737828ae | ||
|
babcd230a6 | ||
|
b91a26f204 | ||
|
f9e10d980c | ||
|
aa8c44c317 | ||
|
5b59cbecc2 | ||
|
7451c4507a | ||
|
cf9450a6c4 | ||
|
d736c9fc26 | ||
|
f90dca046f | ||
|
8c1be02442 | ||
|
743007b8f3 | ||
|
26ad0cfcd6 | ||
|
d23fd8f2e4 | ||
|
86f4a4794f | ||
|
50ffc6acc9 | ||
|
5e74264080 | ||
|
a3d5ae9f0e | ||
|
5f6219caca | ||
|
c40f859edb | ||
|
dd30903c84 | ||
|
d1ea6470d3 | ||
|
fda9be193e | ||
|
545df76cc1 | ||
|
23e154d8e6 | ||
|
cab7cc4916 | ||
|
5b68cecbf3 | ||
|
4011f83f34 | ||
|
3917677706 | ||
|
c44d4a4d00 | ||
|
d4c44b76ae | ||
|
3ed5af1de9 | ||
|
d707be75d3 | ||
|
d1ba596b2c | ||
|
f85a06547b | ||
|
6480f1e573 | ||
|
b39332b6a4 | ||
|
52e566727d | ||
|
466174760f | ||
|
af251cc6cf | ||
|
30f2a460c0 | ||
|
53808c2e10 | ||
|
be39a83b17 | ||
|
ce3f9d92b0 | ||
|
488ce11fc6 | ||
|
b80ac8cd4f | ||
|
0158d7535a | ||
|
98d7abb3a7 | ||
|
51009c7d04 | ||
|
60dcb31949 | ||
|
df1eff5b26 | ||
|
8e9aa911c2 | ||
|
5f097813ba | ||
|
92380dc719 | ||
|
7ca9552f2f | ||
|
05805334c2 | ||
|
e74f337dab | ||
|
8de3874409 | ||
|
b91b0139e3 | ||
|
d43b6e796a | ||
|
910f3b38dd | ||
|
7689965328 | ||
|
f7884f9fce | ||
|
2280cbf451 | ||
|
77799b68cb | ||
|
f7db42512d | ||
|
a074bba0bf | ||
|
8a5c509f8b | ||
|
36bc2eeb75 | ||
|
960276fc68 | ||
|
a6b4b6cd88 | ||
|
43949afed5 | ||
|
401ba4416b | ||
|
24db6449ef | ||
|
3148d51fef | ||
|
97a8c29121 | ||
|
a9b2ab85f2 | ||
|
37d1a02711 | ||
|
ca34702f41 | ||
|
6ea4060cbd | ||
|
992044c517 | ||
|
f4405159c9 | ||
|
62cc7ace36 | ||
|
402773321e | ||
|
de399363dd | ||
|
82fc53a908 | ||
|
43e53130f3 | ||
|
fc92208a2b | ||
|
55e450f78d | ||
|
3f5d2b0ed8 | ||
|
f21aa872cc | ||
|
1257f04dd5 | ||
|
a3c28554a1 | ||
|
5473076ab3 | ||
|
0159856cbd | ||
|
fa40deb025 | ||
|
4aa0325bbb | ||
|
09d8f757d8 | ||
|
d265e09f2f | ||
|
6a46dd458f | ||
|
7c98cb9fe1 | ||
|
3b22679429 | ||
|
18cf48234d | ||
|
587fb7d1e0 | ||
|
5e5d023720 | ||
|
ceb566201f | ||
|
8e2c8df8fe | ||
|
bc7568d397 | ||
|
5260a3f8d3 | ||
|
e8a2c23559 | ||
|
344f7025aa | ||
|
eafad41a6f | ||
|
8a56ff7a59 | ||
|
2042de83d7 | ||
|
132212b57d | ||
|
a34ea0e334 | ||
|
b85c6743bf | ||
|
8012855325 | ||
|
f14d7ba061 | ||
|
d309ff7df3 | ||
|
00be08477e | ||
|
8410bf1e3c | ||
|
8c2db0419f | ||
|
5cf6bb3e89 | ||
|
cdd05f3751 | ||
|
1acd451833 | ||
|
59e12f2206 | ||
|
89145cb657 | ||
|
fd661c5151 | ||
|
6b74fc5a45 | ||
|
36d17cc7de | ||
|
7752c99058 | ||
|
6b0abeec46 | ||
|
d457a64d6e | ||
|
230b0118dd | ||
|
da782e99ad | ||
|
c03e5fbbca | ||
|
8798f36235 | ||
|
681b68aa75 | ||
|
751b416690 | ||
|
a1e594989d | ||
|
969679ecc2 | ||
|
b691e5f843 | ||
|
bdd3cc430f | ||
|
6728f0d338 | ||
|
3479931864 | ||
|
429424d111 | ||
|
cc34f006c6 | ||
|
72c0dd00c8 | ||
|
5b9290be69 | ||
|
66006f4793 | ||
|
dfea582f28 | ||
|
410d828d4e | ||
|
9bfda6e34b | ||
|
ca8847bcd7 | ||
|
933657a91f | ||
|
217aed7652 | ||
|
62c513c293 | ||
|
8123dd550e | ||
|
b9b24f93b7 | ||
|
029732dfe1 | ||
|
16f7194eff | ||
|
99f1f8193a | ||
|
b164990548 | ||
|
69ecc56ddc | ||
|
7d5850678f | ||
|
6c06dfe9a1 | ||
|
1f80777baf | ||
|
8e630f81a4 | ||
|
4c1f9fe77b | ||
|
a02f8742f9 | ||
|
baf2db336e | ||
|
f0c5e3fcd3 | ||
|
bd4d11dfea | ||
|
2e8ee0521c | ||
|
5d75864d7a | ||
|
0755e2e723 | ||
|
30cb1c4d10 | ||
|
b74a8209a7 | ||
|
c530285c0a | ||
|
cc7279e82a | ||
|
162607289d | ||
|
4c99213d14 | ||
|
bb6959b4f0 | ||
|
5fa362d509 | ||
|
450d77b464 | ||
|
3f4e3b6485 | ||
|
e34e25cd2d | ||
|
abd5e15b38 | ||
|
3368c209f6 | ||
|
d41f87d527 | ||
|
7c7cbba3d0 | ||
|
b39633cac6 | ||
|
5989dde726 | ||
|
dff12cab70 | ||
|
76840ffc1f | ||
|
2984aeada4 | ||
|
9e7817c1f2 | ||
|
bb37e2e76f | ||
|
32843f1e53 | ||
|
120cd41d65 | ||
|
5b0ec2923b | ||
|
6aeba9e096 | ||
|
39649c5a3a | ||
|
1d71dfd0ba | ||
|
fbec943ab0 | ||
|
80d04ac891 | ||
|
166d4cb3fa | ||
|
5f51457acf | ||
|
bec5625379 | ||
|
773158b116 | ||
|
20a64e73b1 | ||
|
1452f35daf | ||
|
e2e09cba77 | ||
|
431edb7584 | ||
|
f4c5fe3b29 | ||
|
39d4180814 | ||
|
e1e516ab31 | ||
|
41e4c550e0 | ||
|
5b57afabb4 | ||
|
562188ba65 | ||
|
4d968aa505 | ||
|
ae6b2a501a | ||
|
c64892dea6 | ||
|
e3d9266caf | ||
|
2704a2b3d7 | ||
|
d1cba3bd32 | ||
|
cf1e43774a | ||
|
607ff68784 | ||
|
10c0719c07 | ||
|
5a716eaf5c | ||
|
3d96b395c2 | ||
|
cd6d53b93b | ||
|
b21cc0bde5 | ||
|
875b14dfea | ||
|
c52585da17 | ||
|
b6c389da2f | ||
|
85b5b5079c | ||
|
16f2ebc7cc | ||
|
08ac7d6e1c | ||
|
f92707705e | ||
|
5b98896fce | ||
|
6fe29aca1c | ||
|
4f00ae853e | ||
|
607fb5bb17 | ||
|
819221b2c0 | ||
|
3298e34f3f | ||
|
a7e300c6f2 | ||
|
83298873c5 | ||
|
f1283f337b | ||
|
73ed94bb9c | ||
|
fd83445ce5 | ||
|
a7a46332f0 | ||
|
d357714dd4 | ||
|
6243997f39 | ||
|
7944698f60 | ||
|
4389f4899b | ||
|
f268256ac6 | ||
|
122370d721 | ||
|
1f45363b9a | ||
|
88a366c5d1 | ||
|
a62bcb4620 | ||
|
31a57c902a | ||
|
b77226496f | ||
|
25b37f7b44 | ||
|
098f69829d | ||
|
ee43a34c0c | ||
|
0c7ace8f4f | ||
|
1c6b84c92a | ||
|
492336bfd0 | ||
|
e372693f7f | ||
|
1df1d6cc95 | ||
|
6e8fd98916 | ||
|
18b873c68e | ||
|
9308c36201 | ||
|
cd34bf61bf | ||
|
727baa6cd6 | ||
|
0cb74f33b1 | ||
|
cc60248156 | ||
|
4dd321f7b1 | ||
|
9f8ff9ed47 | ||
|
f586a9759c | ||
|
7b614cdd82 | ||
|
82db1f9324 | ||
|
890ad153b2 | ||
|
e06e98334e | ||
|
8684b56487 | ||
|
31255222f2 | ||
|
c677cbb058 | ||
|
b86cdfb3e6 | ||
|
d7de537d63 | ||
|
e14c482f13 | ||
|
5ee069789b | ||
|
cac9f82cd8 | ||
|
ca2fdbfc03 | ||
|
72515b2a5b | ||
|
1b51fc577d | ||
|
8d7f13d0ec | ||
|
48b50de6b9 | ||
|
65f4c965a0 | ||
|
8b2c58b1f2 | ||
|
08bdfb1c48 | ||
|
97dbd31118 | ||
|
1c7699fc94 | ||
|
e1b361f4d1 | ||
|
5a5ff28bff | ||
|
b2d4caff8f | ||
|
401a7188ab | ||
|
554c83b9cd | ||
|
6497f6c96d | ||
|
d72f5d0442 | ||
|
a187f8b408 | ||
|
6a87b73316 | ||
|
91f07b2a68 | ||
|
df2d632241 | ||
|
88a2d6ab8e | ||
|
ddad04a449 | ||
|
f33142efd6 | ||
|
7aee9d9be8 | ||
|
425abdb751 | ||
|
32b7a7a858 | ||
|
c694fa7fe6 | ||
|
39b43469dd | ||
|
56e515e6e7 | ||
|
ad1322c65f | ||
|
3d13cff95f | ||
|
f6490a7568 | ||
|
08b91296bd | ||
|
159264e8a0 | ||
|
8b7c244dae | ||
|
ef051f9683 | ||
|
4f18fae41f | ||
|
01aadce69a | ||
|
c9e42239d6 | ||
|
df8b07b1ce | ||
|
218ca703d1 | ||
|
71086b1efb | ||
|
369f992ed6 | ||
|
786a5e8960 | ||
|
4d029ab2d6 | ||
|
0f783024c9 | ||
|
c1b3717b51 | ||
|
95766b4f61 | ||
|
8864e001c4 | ||
|
ae0199a564 | ||
|
a809075922 | ||
|
901c5a59ce | ||
|
856a6beed3 | ||
|
a6bb7f2f8f | ||
|
d20917dbf3 | ||
|
4db9c620e6 | ||
|
a650607c7d | ||
|
cc122de653 | ||
|
ce2e1ee8d1 | ||
|
e60526da34 | ||
|
9fe76e3424 | ||
|
be3b19d047 | ||
|
6753befdd4 | ||
|
e5e85ecaf2 | ||
|
33d6fd1424 | ||
|
b319c1939f | ||
|
64145ac4e9 | ||
|
f4cf38f126 | ||
|
eb8397010b | ||
|
e32aadf20d | ||
|
5a1af48ec7 | ||
|
2cf6a07878 | ||
|
2d48c4a063 | ||
|
f7e8099fd7 | ||
|
3feb76268d | ||
|
0e6c00db34 | ||
|
a974347655 | ||
|
76822f26fc | ||
|
48c7f3c055 | ||
|
c34c038807 | ||
|
470849ddb5 | ||
|
dcb4b9e8c8 | ||
|
55dd70cd72 | ||
|
e018f8e3e0 | ||
|
37141243d2 | ||
|
aaf9446641 | ||
|
eb420c4c94 | ||
|
3b49e88194 | ||
|
1ccf6c8647 | ||
|
f0d0b58707 | ||
|
93f26d84bc | ||
|
740fa108ce | ||
|
f455d76b42 | ||
|
b874a03449 | ||
|
bc07f439b9 | ||
|
fc8a772060 | ||
|
2c1f708422 | ||
|
66d0ee0f9e | ||
|
fe31767315 | ||
|
331c94e70d | ||
|
48e0f27007 | ||
|
bd0ad7b0be | ||
|
b62b018822 | ||
|
d26a161eb2 | ||
|
686659d9f2 | ||
|
6a775c84ea | ||
|
532e5517d1 | ||
|
625dbef7d5 | ||
|
b2e7fe5a60 | ||
|
643de1c403 | ||
|
9feb406040 | ||
|
e63bf22996 | ||
|
3c77de53ae | ||
|
bb1fe918c1 | ||
|
6aa9262207 | ||
|
b8fad26604 | ||
|
0ae6710723 | ||
|
4cf107b91f | ||
|
84d34baa4c | ||
|
6987d76917 | ||
|
2399389ba5 | ||
|
4e9008f214 | ||
|
f33c053e34 | ||
|
5f75cc7217 | ||
|
3669d28c95 | ||
|
4feb851ccc | ||
|
cb20a224f1 | ||
|
657c2984c4 | ||
|
d0b17fc529 | ||
|
12078fae6e | ||
|
89d619a070 | ||
|
654710c395 | ||
|
d9446d4817 | ||
|
10f597df4c | ||
|
2b1435e0b8 | ||
|
004659579d | ||
|
818cc4d94a |
@ -12,3 +12,12 @@ indent_size = 2
|
||||
|
||||
[{Makefile,**.mk}]
|
||||
indent_style = tab
|
||||
|
||||
[*.py]
|
||||
indent_size = 4
|
||||
|
||||
[*.rs]
|
||||
indent_size = 4
|
||||
|
||||
[*.vala]
|
||||
indent_size = 4
|
||||
|
@ -1,6 +1,4 @@
|
||||
build/
|
||||
install/
|
||||
flatpak/
|
||||
node_modules/
|
||||
repo/
|
||||
src/lib/
|
||||
src/lib
|
||||
troll
|
||||
flatpak
|
||||
demos
|
||||
|
73
.eslintrc.yaml
Normal file
@ -0,0 +1,73 @@
|
||||
root: true
|
||||
env:
|
||||
es2023: true
|
||||
parser: "@babel/eslint-parser"
|
||||
parserOptions:
|
||||
sourceType: module
|
||||
requireConfigFile: false
|
||||
babelOptions:
|
||||
plugins:
|
||||
- "@babel/plugin-syntax-import-attributes"
|
||||
extends:
|
||||
- eslint:recommended
|
||||
- plugin:import/errors
|
||||
- plugin:import/warnings
|
||||
- plugin:prettier/recommended
|
||||
globals:
|
||||
__DEV__: readonly
|
||||
pkg: readonly
|
||||
# gjs
|
||||
ARGV: readonly
|
||||
Debugger: readonly
|
||||
GIRepositoryGType: readonly
|
||||
globalThis: readonly
|
||||
imports: readonly
|
||||
Intl: readonly
|
||||
log: readonly
|
||||
logError: readonly
|
||||
print: readonly
|
||||
printerr: readonly
|
||||
window: readonly
|
||||
TextEncoder: readonly
|
||||
TextDecoder: readonly
|
||||
console: readonly
|
||||
setTimeout: readonly
|
||||
setInterval: readonly
|
||||
clearTimeout: readonly
|
||||
clearInterval: readonly
|
||||
rules:
|
||||
# Possible Problems
|
||||
# https://eslint.org/docs/latest/rules/#possible-problems
|
||||
array-callback-return: [error] # https://eslint.org/docs/latest/rules/array-callback-return
|
||||
no-duplicate-imports: [error] # https://eslint.org/docs/latest/rules/no-duplicate-imports
|
||||
no-new-native-nonconstructor: [error] # https://eslint.org/docs/latest/rules/no-new-native-nonconstructor
|
||||
no-restricted-globals: # https://eslint.org/docs/rules/no-restricted-globals
|
||||
- error
|
||||
- window
|
||||
- printerr
|
||||
- print
|
||||
- imports
|
||||
- logError
|
||||
- log
|
||||
no-unused-vars: # https://eslint.org/docs/latest/rules/no-unused-vars
|
||||
- error
|
||||
- vars: all
|
||||
args: all
|
||||
argsIgnorePattern: "^_"
|
||||
|
||||
# Suggestions
|
||||
# https://eslint.org/docs/latest/rules/#suggestions
|
||||
eqeqeq: [error, always] # https://eslint.org/docs/rules/eqeqeq
|
||||
no-implicit-globals: [error] # https://eslint.org/docs/latest/rules/no-implicit-globals
|
||||
no-var: [error] # https://eslint.org/docs/rules/no-var
|
||||
prefer-arrow-callback: [
|
||||
error,
|
||||
{ allowNamedFunctions: true, allowUnboundThis: true },
|
||||
] # https://eslint.org/docs/rules/prefer-arrow-callback
|
||||
prefer-const: [error] # https://eslint.org/docs/rules/prefer-const
|
||||
|
||||
# eslint-plugin-import
|
||||
# https://github.com/benmosher/eslint-plugin-import/
|
||||
import/extensions: ["error", "ignorePackages"]
|
||||
import/no-unresolved:
|
||||
[2, { ignore: ["gi://*", "resource://*", "cairo", "gettext", "system"] }]
|
@ -1,42 +0,0 @@
|
||||
env:
|
||||
es2020: true
|
||||
extends:
|
||||
- "eslint:recommended"
|
||||
- "plugin:import/errors"
|
||||
- "plugin:import/warnings"
|
||||
globals:
|
||||
Debugger: readonly
|
||||
GIRepositoryGType: readonly
|
||||
Intl: readonly
|
||||
imports: readonly
|
||||
pkg: readonly
|
||||
log: readonly
|
||||
logError: readonly
|
||||
print: readonly
|
||||
printerr: readonly
|
||||
ARGV: readonly
|
||||
window: readonly
|
||||
globalThis: readonly
|
||||
console: readonly
|
||||
TextEncoder: readonly
|
||||
TextDecoder: readonly
|
||||
parserOptions:
|
||||
sourceType: module
|
||||
rules:
|
||||
# https://eslint.org/docs/rules/no-unused-vars
|
||||
no-unused-vars: [error, { args: none }]
|
||||
# https://eslint.org/docs/rules/no-restricted-globals
|
||||
no-restricted-globals: [error, window, Intl, Debugger]
|
||||
# https://eslint.org/docs/rules/#strict-mode
|
||||
strict: [error] # https://eslint.org/docs/rules/strict
|
||||
# https://eslint.org/docs/rules/#best-practices
|
||||
eqeqeq: [error, always] # https://eslint.org/docs/rules/eqeqeq
|
||||
no-implicit-globals: error
|
||||
# https://eslint.org/docs/rules/#ecmascript-6
|
||||
no-var: error # https://eslint.org/docs/rules/no-var
|
||||
prefer-arrow-callback: error # https://eslint.org/docs/rules/prefer-arrow-callback
|
||||
prefer-const: error # https://eslint.org/docs/rules/prefer-const
|
||||
# https://github.com/benmosher/eslint-plugin-import/
|
||||
import/extensions: ["error", "ignorePackages"]
|
||||
import/no-unresolved:
|
||||
[2, { ignore: ["gi://*", "cairo", "gettext", "system"] }]
|
4
.gitconfig
Normal file
@ -0,0 +1,4 @@
|
||||
[re.sonny.Commit]
|
||||
title-length-hint=72
|
||||
body-length-wrap=50
|
||||
auto-capitalize-title=true
|
16
.github/CODEOWNERS
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
/src/langs/javascript/ @sonnyp
|
||||
*.js @sonnyp
|
||||
|
||||
/src/langs/vala/ @lw64
|
||||
*.vala @lw64
|
||||
|
||||
/src/langs/rust/ @Hofer-Julian
|
||||
*.rs @Hofer-Julian
|
||||
Cargo.toml @Hofer-Julian
|
||||
Cargo.lock @Hofer-Julian
|
||||
|
||||
/src/langs/python/ @theCapypara
|
||||
*.py @theCapypara
|
||||
|
||||
*.c @andyholmes
|
||||
*.h @andyholmes
|
59
.github/workflows/CI.yaml
vendored
Normal file
@ -0,0 +1,59 @@
|
||||
name: CI
|
||||
|
||||
# See also https://github.com/flatpak/flatpak-github-actions
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [main]
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
CI:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 20
|
||||
cache: "npm"
|
||||
|
||||
- name: Install host dependencies
|
||||
run: |
|
||||
sudo apt-get install flatpak mutter flatpak-builder
|
||||
|
||||
# Restore caches
|
||||
- name: Restore Flatpak dependencies
|
||||
uses: actions/cache/restore@v3
|
||||
with:
|
||||
path: ~/.local/share/flatpak
|
||||
key: ${{ runner.os }}-flatpak-dependencies-${{ github.run_id }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-flatpak-dependencies-
|
||||
- name: Restore .flatpak-builder
|
||||
uses: actions/cache/restore@v3
|
||||
with:
|
||||
path: .flatpak-builder
|
||||
key: ${{ runner.os }}-flatpak-builder-${{ github.run_id }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-flatpak-builder-
|
||||
|
||||
- run: mutter --wayland --no-x11 --headless --wayland-display=wayland-0 --virtual-monitor 1280x720 > /tmp/mutter.log 2>&1 &
|
||||
- run: make ci
|
||||
- run: cat /tmp/mutter.log
|
||||
|
||||
# Save caches
|
||||
- name: Save Flatpak dependencies
|
||||
uses: actions/cache/save@v3
|
||||
if: always()
|
||||
with:
|
||||
path: ~/.local/share/flatpak
|
||||
key: ${{ runner.os }}-flatpak-dependencies-${{ github.run_id }}
|
||||
- name: Save .flatpak-builder
|
||||
uses: actions/cache/save@v3
|
||||
if: always()
|
||||
with:
|
||||
path: .flatpak-builder
|
||||
key: ${{ runner.os }}-flatpak-builder-${{ github.run_id }}
|
32
.github/workflows/deploy.yaml
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
name: Deploy
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
flatpak:
|
||||
name: "Flatpak"
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: bilelmoussaoui/flatpak-github-actions:gnome-nightly
|
||||
options: --privileged
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- uses: flatpak/flatpak-github-actions/flatpak-builder@v6
|
||||
name: "Build"
|
||||
with:
|
||||
bundle: re.sonny.Workbench.Devel.flatpak
|
||||
manifest-path: build-aux/re.sonny.Workbench.Devel.json
|
||||
cache-key: flatpak-builder-${{ github.sha }}
|
||||
|
||||
- uses: flatpak/flatpak-github-actions/flat-manager@v6
|
||||
name: "Deploy"
|
||||
with:
|
||||
repository: nightly
|
||||
flat-manager-url: https://flat-manager.gnome.org/
|
||||
token: ${{ secrets.GNOME_NIGHTLY_TOKEN }}
|
13
.gitignore
vendored
@ -9,4 +9,15 @@ install
|
||||
.eslintcache
|
||||
*~
|
||||
*.compiled
|
||||
Workbench.flatpak
|
||||
*.flatpak
|
||||
.fenv
|
||||
.venv
|
||||
__pycache__
|
||||
*.pyc
|
||||
*.gresource
|
||||
.frun
|
||||
|
||||
# IDEs / editors
|
||||
.idea
|
||||
|
||||
target
|
||||
|
13
.gitmodules
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
[submodule "troll"]
|
||||
path = troll
|
||||
url = https://github.com/sonnyp/troll.git
|
||||
[submodule "demos"]
|
||||
path = demos
|
||||
url = https://github.com/workbenchdev/demos.git
|
||||
[submodule "blueprint-compiler"]
|
||||
path = blueprint-compiler
|
||||
url = https://gitlab.gnome.org/jwestman/blueprint-compiler.git
|
||||
[submodule "src/langs/typescript/template/gi-types"]
|
||||
path = gi-types
|
||||
url = https://gitlab.gnome.org/BrainBlasted/gi-typescript-definitions.git
|
||||
branch = nightly
|
4
.husky/pre-commit
Executable file
@ -0,0 +1,4 @@
|
||||
#!/usr/bin/env sh
|
||||
. "$(dirname -- "$0")/_/husky.sh"
|
||||
|
||||
npx lint-staged
|
@ -1,7 +1,2 @@
|
||||
_build/
|
||||
install/
|
||||
flatpak/
|
||||
.flatpak/
|
||||
node_modules/
|
||||
repo/
|
||||
src/lib
|
||||
troll
|
||||
|
18
.vscode/extensions.json
vendored
@ -1,8 +1,14 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"bilelmoussaoui.flatpak-vscode",
|
||||
"editorconfig.editorconfig",
|
||||
"dbaeumer.vscode-eslint",
|
||||
"esbenp.prettier-vscode"
|
||||
]
|
||||
"recommendations": [
|
||||
"bilelmoussaoui.flatpak-vscode",
|
||||
"editorconfig.editorconfig",
|
||||
"esbenp.prettier-vscode",
|
||||
"mrorz.language-gettext",
|
||||
"yzhang.markdown-all-in-one",
|
||||
"mesonbuild.mesonbuild",
|
||||
"prince781.vala",
|
||||
"bodil.blueprint-gtk",
|
||||
"dbaeumer.vscode-eslint",
|
||||
"charliermarsh.ruff"
|
||||
]
|
||||
}
|
||||
|
51
.vscode/settings.json
vendored
@ -1,14 +1,39 @@
|
||||
{
|
||||
"editor.formatOnSave": true,
|
||||
"files.watcherExclude": {
|
||||
"**/.git/objects/**": true,
|
||||
"**/.git/subtree-cache/**": true,
|
||||
"**/node_modules/*/**": true,
|
||||
"**/.hg/store/**": true,
|
||||
"**/.flatpak": true,
|
||||
"**/src/lib": true,
|
||||
".flatpak": true,
|
||||
".flatpak/**": true,
|
||||
"_build/**": true
|
||||
}
|
||||
}
|
||||
"editor.formatOnSave": true,
|
||||
"javascript.preferences.importModuleSpecifierEnding": "js",
|
||||
"typescript.preferences.importModuleSpecifierEnding": "js",
|
||||
"files.watcherExclude": {
|
||||
"**/.git/objects/**": true,
|
||||
"**/.git/subtree-cache/**": true,
|
||||
"**/.hg/store/**": true,
|
||||
"**/node_modules/*/**": true,
|
||||
"**/.flatpak": true,
|
||||
"**/src/lib": true,
|
||||
".flatpak": true,
|
||||
".flatpak/**": true,
|
||||
"_build/**": true
|
||||
},
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"[yaml]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[json]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"rust-analyzer.server.path": "${workspaceFolder}/.flatpak/rust-analyzer.sh",
|
||||
"rust-analyzer.runnables.command": "${workspaceFolder}/.flatpak/cargo.sh",
|
||||
"rust-analyzer.files.excludeDirs": [
|
||||
".flatpak",
|
||||
".flatpak-builder",
|
||||
"_build",
|
||||
"build",
|
||||
"builddir"
|
||||
],
|
||||
"vala.languageServerPath": "${workspaceFolder}/.flatpak/vala-language-server.sh",
|
||||
"[meson]": {
|
||||
"editor.defaultFormatter": "mesonbuild.mesonbuild"
|
||||
},
|
||||
"mesonbuild.configureOnOpen": false,
|
||||
"mesonbuild.buildFolder": "_build",
|
||||
"mesonbuild.mesonPath": "${workspaceFolder}/.flatpak/meson.sh"
|
||||
}
|
||||
|
88
CONTRIBUTING.md
Normal file
@ -0,0 +1,88 @@
|
||||
# Contributing
|
||||
|
||||
If you are interested in contributing to the Library/demos, please head over to https://github.com/workbenchdev/demos instead.
|
||||
|
||||
Either way, don't hesitate to [get in touch](https://matrix.to/#/%23workbench:gnome.org).
|
||||
|
||||
## Getting started
|
||||
|
||||
The following is the recommended setup:
|
||||
|
||||
1. Install [GNOME Builder from Flathub](https://flathub.org/apps/details/org.gnome.Builder)
|
||||
2. Open Builder and select "Clone Repository..."
|
||||
3. Clone `https://github.com/workbenchdev/Workbench.git` (or your fork)
|
||||
4. Press the Run ▶ button
|
||||
|
||||
Make sure that you're building the development target `re.sonny.Workbench.Devel`.
|
||||
|
||||
If you know what you are doing you can also use VSCode with the extensions recommended in this workspace or anything else you are comfortable with. Don't forget to fetch the submodules.
|
||||
|
||||
## Setup
|
||||
|
||||
We provide a couple of tools to make the development process pleasant.
|
||||
|
||||
- Code formatter that runs automatically on git commit
|
||||
- Single command to run all the tests locally
|
||||
|
||||
```sh
|
||||
# Ubuntu requirements
|
||||
# sudo apt install flatpak flatpak-builder nodejs make gcc g++
|
||||
|
||||
# Fedora requirements
|
||||
# sudo dnf install flatpak flatpak-builder nodejs make gcc gcc-c++
|
||||
|
||||
cd Workbench
|
||||
make
|
||||
```
|
||||
|
||||
Before submitting a PR, we recommend running tests locally with
|
||||
|
||||
```sh
|
||||
make test
|
||||
```
|
||||
|
||||
## Submitting a contribution
|
||||
|
||||
- Unless you don't want too - add your name to [the list of contributors](./src/about.js)
|
||||
- Open a pull request
|
||||
- Make sure to review your own changes
|
||||
- Commits are squashed into a single commit on merge
|
||||
|
||||
## Debugging
|
||||
|
||||
To view debug logs, use the following command in [`src/workbench`](../src/workbench).
|
||||
|
||||
```sh
|
||||
--command "G_MESSAGES_DEBUG=\"@app_id@\" @app_id@ $@"
|
||||
```
|
||||
|
||||
See also
|
||||
|
||||
- [GJS Logging](https://gitlab.gnome.org/GNOME/gjs/-/blob/master/doc/Logging.md)
|
||||
- [Flatpak Debugging](https://docs.flatpak.org/en/latest/debugging.html)
|
||||
|
||||
## Translation
|
||||
|
||||
Workbench doesn't currently support translations for its user interface. GNOME documentation is only available in English and we do not want to mislead non-English speakers.
|
||||
|
||||
<!--
|
||||
If you'd like to help translating Workbench into your language, please head over to [Weblate](https://hosted.weblate.org/engage/workbench/).
|
||||
|
||||
<a href="https://hosted.weblate.org/engage/workbench/">
|
||||
<img src="https://hosted.weblate.org/widgets/workbench/-/workbench/multi-auto.svg" alt="Translation status" />
|
||||
</a>
|
||||
|
||||
Thank you for your help!
|
||||
-->
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### The app won't build/run anymore - even on clean `main`
|
||||
|
||||
Clean the build directory. On GNOME Builder, open the search palette with `Ctrl+Enter` and search/select `Clean`.
|
||||
|
||||
If that doesn't solve it - remove the GNOME Builder cache directory
|
||||
|
||||
```sh
|
||||
rm -r ~/.var/app/org.gnome.Builder/cache/
|
||||
```
|
96
Makefile
Normal file
@ -0,0 +1,96 @@
|
||||
SHELL:=/bin/bash -O globstar
|
||||
.PHONY: setup build lint unit test ci sandbox flatpak
|
||||
.DEFAULT_GOAL := setup
|
||||
|
||||
setup:
|
||||
flatpak remote-add --user --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo
|
||||
flatpak install --or-update --user --noninteractive flathub org.gnome.Sdk//48 org.flatpak.Builder org.freedesktop.Sdk.Extension.rust-stable//24.08 org.freedesktop.Sdk.Extension.vala//24.08 org.freedesktop.Sdk.Extension.llvm18//24.08 org.freedesktop.Sdk.Extension.node20//24.08 org.freedesktop.Sdk.Extension.typescript//24.08
|
||||
# flatpak remote-add --user --if-not-exists flathub-beta https://flathub.org/beta-repo/flathub-beta.flatpakrepo
|
||||
# flatpak remote-add --user --if-not-exists gnome-nightly https://nightly.gnome.org/gnome-nightly.flatpakrepo
|
||||
# flatpak install --or-update --user --noninteractive gnome-nightly org.gnome.Sdk//master
|
||||
git submodule update --init
|
||||
npm install --no-fund
|
||||
@echo "✅ You can use "make build" to build Workbench"
|
||||
|
||||
stable:
|
||||
# flatpak --user run org.flatpak.Builder --delete-build-dirs --disable-updates --build-only --ccache --force-clean flatpak build-aux/re.sonny.Workbench.json
|
||||
flatpak-builder --delete-build-dirs --disable-updates --build-only --ccache --force-clean flatpak build-aux/re.sonny.Workbench.json
|
||||
|
||||
devel:
|
||||
# flatpak --user run org.flatpak.Builder --delete-build-dirs --disable-updates --build-only --ccache --force-clean flatpak build-aux/re.sonny.Workbench.Devel.json
|
||||
flatpak-builder --delete-build-dirs --disable-updates --build-only --ccache --force-clean flatpak build-aux/re.sonny.Workbench.Devel.json
|
||||
|
||||
|
||||
build: devel
|
||||
|
||||
cli:
|
||||
./troll/gjspack/bin/gjspack src/cli/main.js --appid=re.sonny.Workbench.cli --prefix=/re/sonny/Workbench --resource-root=src/ --no-executable flatpak/files/share/re.sonny.Workbench.cli/
|
||||
cp src/cli/bin.js flatpak/files/bin/workbench-cli
|
||||
|
||||
lint:
|
||||
# JavaScript
|
||||
./node_modules/.bin/eslint --max-warnings=0 src
|
||||
# Rust
|
||||
./build-aux/fun rustfmt --check --edition 2021 src/**/*.rs
|
||||
# Python
|
||||
./build-aux/fun ruff check --config=src/langs/python/ruff.toml src/**/*.py
|
||||
./build-aux/fun ruff format --config=src/langs/python/ruff.toml --check src/**/*.py
|
||||
# Blueprint
|
||||
./build-aux/fun blueprint-compiler format src/**/*.blp
|
||||
./build-aux/fun workbench-cli check blueprint src/**/*.blp
|
||||
# Vala
|
||||
# ./build-aux/fun workbench-cli check vala src/**/*.vala
|
||||
# CSS
|
||||
./build-aux/fun workbench-cli check css src/**/*.css
|
||||
# Flatpak manifests
|
||||
flatpak run --user --command=flatpak-builder-lint org.flatpak.Builder manifest --exceptions --user-exceptions ./build-aux/exceptions.json build-aux/re.sonny.Workbench.json
|
||||
flatpak run --user --command=flatpak-builder-lint org.flatpak.Builder manifest --exceptions --user-exceptions ./build-aux/exceptions.json build-aux/re.sonny.Workbench.Devel.json
|
||||
|
||||
unit:
|
||||
./build-aux/fun gjs -m ./troll/tst/bin.js test/*.test.js
|
||||
#./build-aux/wip/run.js build-aux/re.sonny.Workbench.Devel.json -- gjs -m ./troll/tst/bin.js test/*.test.js
|
||||
|
||||
# https://github.com/ximion/appstream/issues/398#issuecomment-1129454985
|
||||
# flatpak run org.freedesktop.appstream.cli validate --override=release-time-missing=info --no-net data/app.metainfo.xml
|
||||
# desktop-file-validate --no-hints data/app.desktop
|
||||
# https://discourse.gnome.org/t/gtk-builder-tool-requires-and-libraries/9222
|
||||
# gtk-builder-tool validate src/*.ui
|
||||
# flatpak run org.flathub.flatpak-external-data-checker re.sonny.Workbench.json
|
||||
# flatpak run org.flathub.flatpak-external-data-checker re.sonny.Workbench.Devel.json
|
||||
# as used by Flathub
|
||||
# flatpak run --env=G_DEBUG=fatal-criticals --command=appstream-util org.flatpak.Builder validate data/app.metainfo.xml
|
||||
|
||||
test: unit lint
|
||||
./build-aux/fun workbench-cli ci demos/src/Welcome
|
||||
# ./build-aux/wip/run.js build-aux/re.sonny.Workbench.Devel.json -- workbench-cli ci demos/src/Welcome/
|
||||
|
||||
ci: setup build test
|
||||
# See Permissions.js
|
||||
# flatpak override --user --share=network --socket=pulseaudio --device=input re.sonny.Workbench.Devel
|
||||
./build-aux/fun workbench-cli ci demos/src/*
|
||||
|
||||
# Note that if you have Sdk extensions installed they will be used
|
||||
# make sure to test without the sdk extensions installed
|
||||
sandbox: setup
|
||||
flatpak run org.flatpak.Builder --ccache --user --install --force-clean flatpak build-aux/re.sonny.Workbench.Devel.json
|
||||
# flatpak remove --noninteractive org.freedesktop.Sdk.Extension.rust-stable//24.08 org.freedesktop.Sdk.Extension.vala//24.08 org.freedesktop.Sdk.Extension.llvm18//24.08
|
||||
flatpak run --command="bash" re.sonny.Workbench.Devel
|
||||
|
||||
flatpak:
|
||||
flatpak run org.flatpak.Builder --ccache --force-clean flatpak build-aux/re.sonny.Workbench.Devel.json
|
||||
# This is what Flathub does - consider moving to lint
|
||||
flatpak run --env=G_DEBUG=fatal-criticals --command=appstream-util org.flatpak.Builder validate flatpak/files/share/appdata/re.sonny.Workbench.Devel.appdata.xml
|
||||
flatpak run --command="desktop-file-validate" --filesystem=host:ro org.freedesktop.Sdk//24.08 flatpak/files/share/applications/re.sonny.Workbench.Devel.desktop
|
||||
# appstreamcli validate --override=release-time-missing=info /path/to/your/app.metainfo.xml
|
||||
flatpak run org.flatpak.Builder --run flatpak build-aux/re.sonny.Workbench.Devel.json bash
|
||||
|
||||
# Sync with .gitignore
|
||||
clean:
|
||||
rm -f re.sonny.Workbench.Devel.flatpak
|
||||
rm -f re.sonny.Workbench.flatpak
|
||||
rm -rf _build
|
||||
rm -rf .flatpak
|
||||
rm -rf .flatpak-builder
|
||||
rm -rf flatpak
|
||||
rm -rf flatpak-builder
|
||||
rm -rf repo
|
147
README.md
@ -1,86 +1,131 @@
|
||||
<img style="vertical-align: middle;" src="data/icons/re.sonny.Workbench.svg" width="120" height="120" align="left">
|
||||
<img style="vertical-align: middle;" src="data/icons/hicolor/scalable/apps/re.sonny.Workbench.svg" width="120" height="120" align="left">
|
||||
|
||||
# Workbench
|
||||
|
||||
A sandbox to learn and prototype with GNOME technologies
|
||||
Learn and prototype with GNOME technologies
|
||||
|
||||

|
||||

|
||||
|
||||
<a href='https://flathub.org/apps/details/re.sonny.Workbench'><img width='180' height='60' alt='Download on Flathub' src='https://flathub.org/assets/badges/flathub-badge-en.svg'/></a>
|
||||
<a href='https://flathub.org/apps/re.sonny.Workbench'><img width='240' alt='Download on Flathub' src='https://flathub.org/api/badge?svg&locale=en'/></a>
|
||||
|
||||
Workbench goal is to let you experiment with GNOME technologies, no matter if tinkering for the first time or building and testing a custom GTK widget.
|
||||
Workbench lets you experiment with GNOME technologies, no matter if tinkering for the first time or building and testing a GTK user interface.
|
||||
|
||||
Among other things, Workbench comes with
|
||||
|
||||
- realtime GTK/CSS preview
|
||||
- JavaScript for quick and easy scripting
|
||||
- Syntax highlighting, undo/redo, autosave
|
||||
- code fomatter
|
||||
- terminal
|
||||
- Live GTK/CSS preview
|
||||
- Library of 100+ examples
|
||||
<!-- - JavaScript, TypeScript, Rust, Python and Vala support -->
|
||||
- JavaScript, Rust, Python and Vala support
|
||||
- Declarative user interface syntax
|
||||
- Autosave, sessions and projects
|
||||
- Code diagnostics, completion and formatter
|
||||
- Terminal output
|
||||
|
||||
ℹ️ Workbench is made possible by Flatpak. Only Flathub Workbench is supported.
|
||||
|
||||
**Testimonials**
|
||||
|
||||
> **“** It is an essential tool for those who develop applications with GTK **”** • **“** as someone who is learning GTK, Workbench is definitely a must have! **”** • **“** created a simple mockup using the amazing Workbench app **”** • **“** It used to be hard but Workbench helps me learn GTK. **”** • **“** I recommend it even to those who are new to GTK **”** • **“** This tool has simplified my life by saving my time drastically. **”** • **“** Gone too wild playing with Workbench **”**
|
||||
|
||||
## Language support
|
||||
|
||||
| | Formatter | Linter | Library demos[1] |
|
||||
| ---------- | --------- | ------ | ---------------- |
|
||||
| JavaScript | ✅ | ✅ | 103 |
|
||||
| Python | ✅ | ✅ | 98 |
|
||||
| Vala | ✅ | ✅ | 92 |
|
||||
| Rust | ✅ | ✅ | 52 |
|
||||
| Blueprint | ✅ | ✅ | |
|
||||
| CSS | ✅ | ✅ | |
|
||||
|
||||
[1] As of 2024-06-16 <!--counted with `~/go/bin/scc demos/src`-->
|
||||
|
||||
## Tips and tricks
|
||||
|
||||
<details>
|
||||
<summary>Disable code formatting</summary>
|
||||
|
||||
Workbench uses the [prettier](https://prettier.io/) code formatter. If you need to exclude some code you can use special comments.
|
||||
|
||||
[JavaScript](https://prettier.io/docs/en/ignore.html#javascript)
|
||||
|
||||
```js
|
||||
// prettier-ignore
|
||||
matrix(
|
||||
1, 0, 0,
|
||||
0, 1, 0,
|
||||
0, 0, 1
|
||||
);
|
||||
```
|
||||
|
||||
[XML](https://github.com/prettier/plugin-xml#ignore-ranges)
|
||||
|
||||
```xml
|
||||
<foo>
|
||||
<!-- prettier-ignore-start -->
|
||||
<this-content-will-not-be-formatted />
|
||||
<!-- prettier-ignore-end -->
|
||||
</foo>
|
||||
```
|
||||
[JavaScript](https://biomejs.dev/formatter/#ignore-code)
|
||||
|
||||
[CSS](https://prettier.io/docs/en/ignore.html#css)
|
||||
|
||||
```css
|
||||
/* prettier-ignore */
|
||||
.my ugly rule
|
||||
{
|
||||
</details>
|
||||
|
||||
}
|
||||
```
|
||||
<details>
|
||||
<summary>Turn a prototype made in Workbench into an application</summary>
|
||||
|
||||
Use GNOME Builder to start a new project using the appropriate GNOME Application template and copy paste your Workbench code.
|
||||
|
||||
</details>
|
||||
|
||||
## Development
|
||||
## Code of conduct
|
||||
|
||||
1. Install [GNOME Builder](https://apps.gnome.org/app/org.gnome.Builder/)
|
||||
2. Open Builder and select "Clone Repository..."
|
||||
3. Clone `https://github.com/sonnyp/Workbench.git`
|
||||
4. Press the Run ▶ button
|
||||
Workbench follows the [GNOME Code of Conduct](https://conduct.gnome.org/).
|
||||
|
||||
## Packaging
|
||||
- **Be friendly.** Use welcoming and inclusive language.
|
||||
- **Be empathetic.** Be respectful of differing viewpoints and experiences.
|
||||
- **Be respectful.** When we disagree, we do so in a polite and constructive manner.
|
||||
- **Be considerate.** Remember that decisions are often a difficult choice between competing priorities.
|
||||
- **Be patient and generous.** If someone asks for help it is because they need it.
|
||||
- **Try to be concise.** Read the discussion before commenting.
|
||||
|
||||
Please do not attempt to package Workbench any other way than as a Flatpak application.
|
||||
## Credits
|
||||
|
||||
It is unsupported and may put users at risk.
|
||||
Workbench is made of many components.
|
||||
|
||||
## Contributing
|
||||
Thank you Flatpak, GTK, GLib, GtkSourceView, libadwaita, VTE, GJS, Blueprint, icon-development-kit, Vala, GTKCssLanguageServer, gtk-rs, PyGObject
|
||||
|
||||
If you can help, here is a list of issues that would make Workbench better
|
||||
|
||||
- [GtkSourceView - Make URIs clickable](https://gitlab.gnome.org/GNOME/gtksourceview/-/issues/125)
|
||||
and the GNOME community 🖤
|
||||
|
||||
## Copyright
|
||||
|
||||
© 2022 [Sonny Piers](https://github.com/sonnyp)
|
||||
© 2022 [Sonny Piers](https://github.com/sonnyp) and contributors
|
||||
|
||||
## License
|
||||
|
||||
GPLv3. Please see [COPYING](COPYING) file.
|
||||
|
||||
Except for everything under src/Library/demos which is in the public domain under the terms of [CC0 1.0](https://creativecommons.org/publicdomain/zero/1.0/).
|
||||
|
||||
<details>
|
||||
<summary>
|
||||
Testimonials
|
||||
</summary>
|
||||
|
||||
From [Mirko Brombin](https://mirko.pm/) creator of [Bottles](https://usebottles.com/)
|
||||
|
||||
> My favorite tool is definitely Workbench, an application that allows me to compose GTK interfaces with XML/Blueprint, JavaScript, and CSS, seeing the results in real-time. This tool has simplified my life by reducing my time drastically. It is an essential tool for those who develop applications with GTK and I recommend it even to those who are new to GTK.
|
||||
|
||||
https://console.substack.com/p/console-112
|
||||
|
||||
---
|
||||
|
||||
From [Marco Melorio](https://twitter.com/melix9999) creator of [Telgrand](https://github.com/melix99/telegrand)
|
||||
|
||||
> GSoC coding period started on Monday, so this is a good time to blog about what I’ve started working on and what’s my milestone to finish the project. First off, I’ve created a simple mockup using Sonny Piers’ amazing Workbench app. This is the first step in knowing how we want the UI to look like, at least in the first iteration.
|
||||
|
||||
https://melix99.wordpress.com/2022/06/17/gsoc-update-1-planning/
|
||||
|
||||
---
|
||||
|
||||
> Workbench has been great! It used to be hard to mess around with GTK but Workbench helps me to learn GTK.
|
||||
|
||||
https://twitter.com/synthesizedecho/status/1528958932911280129
|
||||
|
||||
> Gone too wild playing with Workbench and Blueprint.
|
||||
|
||||
https://mastodon.online/@waimus/108582108701889960
|
||||
|
||||
> as someone who is learning GTK, I can confirm that Workbench is definitely a must have for me!
|
||||
|
||||
https://fosstodon.org/@TheEvilSkeleton/108598098682948266
|
||||
|
||||
> I'm really new to development and workbench its being a fantastic help not just to code itself, but to understand the gtk logic.
|
||||
|
||||
https://matrix.to/#/!kDBZrVKCdhrVuWxbGe:matrix.org/$XmIz7FA-UwpoiwHxDyzve1P-J1ecMHkL0x8Br23mUxg
|
||||
|
||||
> Installed this (again) a short while ago this is for sure the most fun I've had with a development tool
|
||||
|
||||
https://floss.social/@agavi@hachyderm.io/110594674482784960
|
||||
|
||||
</details>
|
||||
|
@ -4,21 +4,27 @@
|
||||
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
|
||||
xmlns:foaf="http://xmlns.com/foaf/0.1/"
|
||||
xmlns:gnome="http://api.gnome.org/doap-extensions#"
|
||||
xmlns="http://usefulinc.com/ns/doap#"
|
||||
>
|
||||
xmlns="http://usefulinc.com/ns/doap#">
|
||||
<name>Workbench</name>
|
||||
<shortdesc>Sandbox to learn and prototype with GNOME technologies</shortdesc>
|
||||
<description
|
||||
>Something clever.</description>
|
||||
<shortdesc>Learn and prototype with GNOME technologies</shortdesc>
|
||||
<description>Workbench goal is to let you experiment with GNOME technologies, no matter if tinkering for the first time or building and testing a custom GTK widget.</description>
|
||||
|
||||
<homepage rdf:resource="https://workbench.sonny.re" />
|
||||
<bug-database rdf:resource="https://workbench.sonny.re/feedback" />
|
||||
<programming-language>JavaScript</programming-language>
|
||||
<programming-language>Vala</programming-language>
|
||||
<programming-language>C</programming-language>
|
||||
<programming-language>Rust</programming-language>
|
||||
<programming-language>Python</programming-language>
|
||||
|
||||
<platform>GTK 4</platform>
|
||||
<platform>Libadwaita</platform>
|
||||
|
||||
<maintainer>
|
||||
<foaf:Person>
|
||||
<foaf:name>Sonny Piers</foaf:name>
|
||||
<foaf:mbox rdf:resource="mailto:sonny@fastmail.net" />
|
||||
<foaf:mbox rdf:resource="mailto:sonnyp@gnome.org" />
|
||||
<gnome:userid>sonnyp</gnome:userid>
|
||||
<foaf:account>
|
||||
<foaf:OnlineAccount>
|
||||
<foaf:accountServiceHomepage rdf:resource="https://github.com/" />
|
||||
@ -27,12 +33,29 @@
|
||||
</foaf:account>
|
||||
<foaf:account>
|
||||
<foaf:OnlineAccount>
|
||||
<foaf:accountServiceHomepage
|
||||
rdf:resource="https://gitlab.gnome.org"
|
||||
/>
|
||||
<foaf:accountServiceHomepage rdf:resource="https://gitlab.gnome.org"/>
|
||||
<foaf:accountName>sonny</foaf:accountName>
|
||||
</foaf:OnlineAccount>
|
||||
</foaf:account>
|
||||
</foaf:Person>
|
||||
</maintainer>
|
||||
<maintainer>
|
||||
<foaf:Person>
|
||||
<foaf:name>Julian Hofer</foaf:name>
|
||||
<foaf:mbox rdf:resource="mailto:julianhofer@gnome.org" />
|
||||
<gnome:userid>julianhofer</gnome:userid>
|
||||
<foaf:account>
|
||||
<foaf:OnlineAccount>
|
||||
<foaf:accountServiceHomepage rdf:resource="https://github.com/" />
|
||||
<foaf:accountName>Hofer-Julian</foaf:accountName>
|
||||
</foaf:OnlineAccount>
|
||||
</foaf:account>
|
||||
<foaf:account>
|
||||
<foaf:OnlineAccount>
|
||||
<foaf:accountServiceHomepage rdf:resource="https://gitlab.gnome.org"/>
|
||||
<foaf:accountName>Hofer-Julian</foaf:accountName>
|
||||
</foaf:OnlineAccount>
|
||||
</foaf:account>
|
||||
</foaf:Person>
|
||||
</maintainer>
|
||||
</Project>
|
||||
|
1
blueprint-compiler
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 04ef0944db56ab01307a29aaa7303df6067cb3c0
|
40
build-aux/README.md
Normal file
@ -0,0 +1,40 @@
|
||||
# Build Utilities
|
||||
|
||||
This directory contains the Flatpak Manifest and other build utilities.
|
||||
|
||||
## Workbench Flatpak Manifests
|
||||
|
||||
### Python Modules
|
||||
|
||||
The `modules/python-*.json` files contain Flatpak modules to install Python dependencies.
|
||||
|
||||
These files are (sometimes partially, see below) auto-generated. Here is how to generate it:
|
||||
|
||||
1. Obtain an up-to-date copy of [flatpak-builder-tools](https://github.com/flatpak/flatpak-builder-tools).
|
||||
2. Make sure you have a Python virtualenv activated with the dependencies for the `pip` generator from the repo above.
|
||||
3. Run `python3 <...>/flatpak-builder-tools/pip/flatpak-pip-generator <package> -o modules/python-<package> --build-isolation`
|
||||
|
||||
You will notice that Workbench will not build after auto-generating these files as described above.
|
||||
This is due to these issues:
|
||||
|
||||
- https://github.com/flatpak/flatpak-builder-tools/issues/380
|
||||
- https://github.com/pypa/pip/issues/7863
|
||||
|
||||
This means that the generated JSON file now needs its build dependencies manually added. Check the build dependencies
|
||||
of the package and their dependencies and add them to the JSON as well. Brute-forcing the build to obtain missing packages
|
||||
may help as does referencing old commits of the file. You can also use the generator command to generate dependencies
|
||||
for them and then merge it into the file by hand, but note that you will also need to manually collect their build
|
||||
dependencies too.
|
||||
|
||||
In some cases you may also need to manually remove some packages the generator adds (such as `packaging` with `rope`,
|
||||
as the SDK and Runtime already contain a version of these packages that can not be replaced. Make sure the package
|
||||
you want to install is actually compatible with the version of that dependency in the SDK/Runtime.
|
||||
|
||||
#### Python packages with Maturin as build system
|
||||
|
||||
Python packages with Maturin as build system need some additional manual steps to get working. You will have to have
|
||||
Rust enabled for compilation and pull in additional dependencies. See `modules/python-ruff.json` for example.
|
||||
|
||||
You can generate Maturin's dependencies with another generator provided by the Flatpak Builder Tools. Clone
|
||||
the Maturin repo in the corresponding version you need and run:
|
||||
`python3 <...>/flatpak-builder-tools/cargo/flatpak-cargo-generator.py <...>/Cargo.lock -o modules/cargo-sources-maturin.json`
|
4
build-aux/exceptions.json
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"re.sonny.Workbench": ["external-gitmodule-url-found"],
|
||||
"re.sonny.Workbench.Devel": ["external-gitmodule-url-found"]
|
||||
}
|
5
build-aux/fun
Executable file
@ -0,0 +1,5 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
# fun stands for Flatpak Run
|
||||
flatpak-builder --run $(dirname $0)/../flatpak $(dirname $0)/re.sonny.Workbench.Devel.json "$@"
|
||||
# flatpak-builder --env=G_MESSAGES_DEBUG=workbench-cli --run flatpak build-aux/re.sonny.Workbench.Devel.json "$@"
|
250
build-aux/library.js
Executable file
@ -0,0 +1,250 @@
|
||||
#!/usr/bin/env -S gjs -m
|
||||
|
||||
import Gio from "gi://Gio";
|
||||
import GLib from "gi://GLib";
|
||||
import { programArgs, exit } from "system";
|
||||
|
||||
Gio._promisify(
|
||||
Gio.File.prototype,
|
||||
"enumerate_children_async",
|
||||
"enumerate_children_finish",
|
||||
);
|
||||
|
||||
Gio._promisify(
|
||||
Gio.File.prototype,
|
||||
"replace_contents_async",
|
||||
"replace_contents_finish",
|
||||
);
|
||||
|
||||
Gio._promisify(
|
||||
Gio.File.prototype,
|
||||
"make_directory_async",
|
||||
"make_directory_finish",
|
||||
);
|
||||
|
||||
Gio._promisify(Gio.File.prototype, "copy_async", "copy_finish");
|
||||
|
||||
const loop = new GLib.MainLoop(null, false);
|
||||
|
||||
const [pkgdatadir] = programArgs;
|
||||
GLib.mkdir_with_parents(
|
||||
Gio.File.new_for_path(pkgdatadir).get_child("demos").get_path(),
|
||||
0o755,
|
||||
);
|
||||
|
||||
const demos_dir = Gio.File.new_for_path(
|
||||
GLib.getenv("MESON_SOURCE_ROOT"),
|
||||
).get_child("demos/src");
|
||||
const demos = [];
|
||||
|
||||
(async () => {
|
||||
const enumerator = await demos_dir.enumerate_children_async(
|
||||
`${Gio.FILE_ATTRIBUTE_STANDARD_NAME},${Gio.FILE_ATTRIBUTE_STANDARD_IS_HIDDEN}`,
|
||||
Gio.FileQueryInfoFlags.NOFOLLOW_SYMLINKS,
|
||||
GLib.PRIORITY_DEFAULT,
|
||||
null,
|
||||
);
|
||||
for (const file_info of enumerator) {
|
||||
if (file_info.get_is_hidden()) continue;
|
||||
if (file_info.get_file_type() !== Gio.FileType.DIRECTORY) continue;
|
||||
|
||||
const demo_dir = enumerator.get_child(file_info);
|
||||
|
||||
let str;
|
||||
try {
|
||||
str = new TextDecoder().decode(
|
||||
demo_dir.get_child("main.json").load_contents(null)[1],
|
||||
);
|
||||
} catch (err) {
|
||||
console.warn(err);
|
||||
continue;
|
||||
}
|
||||
|
||||
const demo = JSON.parse(str);
|
||||
demo.name = file_info.get_name();
|
||||
|
||||
if (!isDemoCompatible(demo)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const languages = [];
|
||||
if (demo_dir.get_child("main.js").query_exists(null)) {
|
||||
languages.push("javascript");
|
||||
}
|
||||
if (demo_dir.get_child("main.ts").query_exists(null)) {
|
||||
languages.push("typescript");
|
||||
}
|
||||
if (demo_dir.get_child("main.vala").query_exists(null)) {
|
||||
languages.push("vala");
|
||||
}
|
||||
if (demo_dir.get_child("code.rs").query_exists(null)) {
|
||||
languages.push("rust");
|
||||
}
|
||||
if (demo_dir.get_child("main.py").query_exists(null)) {
|
||||
languages.push("python");
|
||||
}
|
||||
demo.languages = languages;
|
||||
|
||||
await copyDemo(
|
||||
demo_dir,
|
||||
Gio.File.new_for_path(pkgdatadir)
|
||||
.get_child("demos")
|
||||
.get_child(demo_dir.get_basename()),
|
||||
);
|
||||
|
||||
demos.push(demo);
|
||||
}
|
||||
|
||||
demos.sort((a, b) => {
|
||||
if (a.name === "Welcome") return -1;
|
||||
if (b.name === "Welcome") return 1;
|
||||
if (a.name === "Platform Tools") return -1;
|
||||
if (b.name === "Platform Tools") return 1;
|
||||
else return a.name.localeCompare(b.name);
|
||||
});
|
||||
|
||||
await Gio.File.new_for_path(pkgdatadir)
|
||||
.get_child("demos/index.json")
|
||||
.replace_contents_async(
|
||||
new TextEncoder().encode(JSON.stringify(demos)),
|
||||
null,
|
||||
false,
|
||||
Gio.FileCreateFlags.NONE,
|
||||
null,
|
||||
);
|
||||
})()
|
||||
.catch((err) => {
|
||||
loop.quit();
|
||||
console.error(err);
|
||||
exit(1);
|
||||
})
|
||||
.then(() => {
|
||||
loop.quit();
|
||||
});
|
||||
|
||||
async function copyDemo(source, destination) {
|
||||
try {
|
||||
destination.make_directory_with_parents(null);
|
||||
} catch (err) {
|
||||
if (!err.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.EXISTS)) {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
const enumerator = await source.enumerate_children_async(
|
||||
`${Gio.FILE_ATTRIBUTE_STANDARD_NAME},${Gio.FILE_ATTRIBUTE_STANDARD_IS_HIDDEN}`,
|
||||
Gio.FileQueryInfoFlags.NOFOLLOW_SYMLINKS,
|
||||
GLib.PRIORITY_DEFAULT,
|
||||
null,
|
||||
);
|
||||
|
||||
for await (const file_info of enumerator) {
|
||||
if (file_info.get_is_hidden()) continue;
|
||||
|
||||
const child = enumerator.get_child(file_info);
|
||||
if (
|
||||
// Sync with demos "make clean" and .gitignore
|
||||
[
|
||||
"Cargo.lock",
|
||||
"Cargo.toml",
|
||||
"lib.rs",
|
||||
"workbench.rs",
|
||||
"workbench.vala",
|
||||
"libworkbenchcode.so",
|
||||
"settings",
|
||||
"main.ui",
|
||||
"icons.gresource",
|
||||
"icons.gresource.xml",
|
||||
].includes(child.get_basename())
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const child_dest = destination.get_child(child.get_basename());
|
||||
|
||||
if (file_info.get_file_type() === Gio.FileType.DIRECTORY) {
|
||||
await copyDirectory(child, child_dest);
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
await child.copy_async(
|
||||
child_dest, // destination
|
||||
Gio.FileCopyFlags.NONE, // flags
|
||||
GLib.PRIORITY_DEFAULT, // priority
|
||||
null, // cancellable
|
||||
null, // progress_callback
|
||||
);
|
||||
} catch (err) {
|
||||
if (!err.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.EXISTS)) {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function copyDirectory(source, destination) {
|
||||
try {
|
||||
await destination.make_directory_async(GLib.PRIORITY_DEFAULT, null);
|
||||
} catch (err) {
|
||||
if (!err.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.EXISTS)) {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
const enumerator = await source.enumerate_children_async(
|
||||
`${Gio.FILE_ATTRIBUTE_STANDARD_NAME},${Gio.FILE_ATTRIBUTE_STANDARD_IS_HIDDEN}`,
|
||||
Gio.FileQueryInfoFlags.NOFOLLOW_SYMLINKS,
|
||||
GLib.PRIORITY_DEFAULT,
|
||||
null,
|
||||
);
|
||||
|
||||
for await (const file_info of enumerator) {
|
||||
if (file_info.get_is_hidden()) continue;
|
||||
|
||||
const child = enumerator.get_child(file_info);
|
||||
const child_dest = destination.get_child(child.get_basename());
|
||||
|
||||
if (file_info.get_file_type() === Gio.FileType.DIRECTORY) {
|
||||
await copyDirectory(child, child_dest);
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
await child.copy_async(
|
||||
child_dest, // destination
|
||||
Gio.FileCopyFlags.NONE, // flags
|
||||
GLib.PRIORITY_DEFAULT, // priority
|
||||
null, // cancellable
|
||||
null, // progress_callback
|
||||
);
|
||||
} catch (err) {
|
||||
if (!err.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.EXISTS)) {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const key_file = new GLib.KeyFile();
|
||||
key_file.load_from_file("/.flatpak-info", GLib.KeyFileFlags.NONE);
|
||||
// runtime/org.gnome.Sdk/x86_64/master
|
||||
const [, , , runtime_version] = key_file
|
||||
.get_string("Application", "runtime")
|
||||
.split("/");
|
||||
|
||||
function isDemoCompatible(demo) {
|
||||
const demo_runtime_version = demo["runtime-version"];
|
||||
|
||||
if (demo_runtime_version === "master") {
|
||||
return runtime_version === "master";
|
||||
} else if (runtime_version === "master") {
|
||||
return true;
|
||||
} else if (!demo_runtime_version) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return +runtime_version >= +demo_runtime_version;
|
||||
}
|
||||
|
||||
loop.run();
|
30
build-aux/modules/GTKCssLanguageServer.json
Normal file
@ -0,0 +1,30 @@
|
||||
{
|
||||
"name": "GTKCssLanguageServer",
|
||||
"config-opts": ["--buildtype=release"],
|
||||
"buildsystem": "meson",
|
||||
"sources": [
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://github.com/JCWasmx86/GTKCssLanguageServer",
|
||||
"commit": "dcbe75012d2d26fbca2729cee014e4860e31fa53"
|
||||
}
|
||||
],
|
||||
"modules": [
|
||||
{
|
||||
"name": "jsonrpc-glib",
|
||||
"config-opts": [
|
||||
"--libdir=/app/lib",
|
||||
"--buildtype=release",
|
||||
"-Denable_tests=false"
|
||||
],
|
||||
"buildsystem": "meson",
|
||||
"sources": [
|
||||
{
|
||||
"type": "archive",
|
||||
"url": "https://download.gnome.org/sources/jsonrpc-glib/3.44/jsonrpc-glib-3.44.1.tar.xz",
|
||||
"sha256": "1361d17e9c805646afe5102e59baf8ca450238600fcabd01586c654b78bb30df"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
21
build-aux/modules/biome.json
Normal file
@ -0,0 +1,21 @@
|
||||
{
|
||||
"name": "biome",
|
||||
"buildsystem": "simple",
|
||||
"build-commands": ["chmod +x biome", "cp biome /app/bin/biome"],
|
||||
"sources": [
|
||||
{
|
||||
"type": "file",
|
||||
"dest-filename": "biome",
|
||||
"only-arches": ["aarch64"],
|
||||
"url": "https://github.com/biomejs/biome/releases/download/cli%2Fv1.9.4/biome-linux-arm64",
|
||||
"sha256": "f0f0f3e7cdec78420a600b05bfc364aa9b804811bd3bbae04e7bf090828ae970"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"dest-filename": "biome",
|
||||
"only-arches": ["x86_64"],
|
||||
"url": "https://github.com/biomejs/biome/releases/download/cli%2Fv1.9.4/biome-linux-x64",
|
||||
"sha256": "ce247fb644999ef52e5111dd6fd6e471019669fc9c4a44b5699721e39b7032c3"
|
||||
}
|
||||
]
|
||||
}
|
10
build-aux/modules/blueprint-compiler.json
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"name": "blueprint-compiler",
|
||||
"buildsystem": "meson",
|
||||
"sources": [
|
||||
{
|
||||
"type": "dir",
|
||||
"path": "../../blueprint-compiler"
|
||||
}
|
||||
]
|
||||
}
|
12
build-aux/modules/gom.json
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"name": "gom",
|
||||
"buildsystem": "meson",
|
||||
"config-opts": ["--libdir=/app/lib", "-Denable-gtk-doc=false"],
|
||||
"sources": [
|
||||
{
|
||||
"type": "archive",
|
||||
"url": "https://download.gnome.org/sources/gom/0.5/gom-0.5.3.tar.xz",
|
||||
"sha256": "069d0909fbdc6b4d27edf7a879366194e3ab508b03548bf5b89ff63546d20177"
|
||||
}
|
||||
]
|
||||
}
|
19
build-aux/modules/libportal.json
Normal file
@ -0,0 +1,19 @@
|
||||
{
|
||||
"name": "libportal",
|
||||
"buildsystem": "meson",
|
||||
"config-opts": [
|
||||
"--libdir=/app/lib",
|
||||
"-Dtests=false",
|
||||
"-Dbackend-gtk3=disabled",
|
||||
"-Dbackend-gtk4=enabled",
|
||||
"-Dbackend-qt5=disabled",
|
||||
"-Ddocs=false"
|
||||
],
|
||||
"sources": [
|
||||
{
|
||||
"type": "archive",
|
||||
"url": "https://github.com/flatpak/libportal/releases/download/0.9.1/libportal-0.9.1.tar.xz",
|
||||
"sha256": "de801ee349ed3c255a9af3c01b1a401fab5b3fc1c35eb2fd7dfb35d4b8194d7f"
|
||||
}
|
||||
]
|
||||
}
|
38
build-aux/modules/libshumate.json
Normal file
@ -0,0 +1,38 @@
|
||||
{
|
||||
"name": "libshumate",
|
||||
"buildsystem": "meson",
|
||||
"config-opts": ["--libdir=/app/lib", "-Ddemos=false", "-Dgtk_doc=false"],
|
||||
"sources": [
|
||||
{
|
||||
"type": "archive",
|
||||
"url": "https://download.gnome.org/sources/libshumate/1.4/libshumate-1.4.rc.tar.xz",
|
||||
"sha256": "a57b97dbbda55bcb07c6f0197ff006128518c2b2c88fbee8bea5168acbc9baee"
|
||||
}
|
||||
],
|
||||
"modules": [
|
||||
{
|
||||
"name": "protobuf",
|
||||
"buildsystem": "autotools",
|
||||
"config-opts": ["DIST_LANG=cpp"],
|
||||
"cleanup": ["/bin/protoc*", "/lib/libprotoc*", "/lib/libprotobuf-lite*"],
|
||||
"sources": [
|
||||
{
|
||||
"type": "archive",
|
||||
"url": "https://github.com/protocolbuffers/protobuf/releases/download/v3.17.3/protobuf-all-3.17.3.tar.gz",
|
||||
"sha256": "77ad26d3f65222fd96ccc18b055632b0bfedf295cb748b712a98ba1ac0b704b2"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "protobuf-c",
|
||||
"buildsystem": "autotools",
|
||||
"sources": [
|
||||
{
|
||||
"type": "archive",
|
||||
"url": "https://github.com/protobuf-c/protobuf-c/releases/download/v1.4.0/protobuf-c-1.4.0.tar.gz",
|
||||
"sha256": "26d98ee9bf18a6eba0d3f855ddec31dbe857667d269bc0b6017335572f85bbcb"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
12
build-aux/modules/libspelling.json
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"name": "libspelling",
|
||||
"buildsystem": "meson",
|
||||
"config-opts": ["--libdir=/app/lib", "-Ddocs=false"],
|
||||
"sources": [
|
||||
{
|
||||
"type": "archive",
|
||||
"url": "https://download.gnome.org/sources/libspelling/0.4/libspelling-0.4.6.tar.xz",
|
||||
"sha256": "3248a9b5336ea2f727d2db912d2f0083accc0505ce707679b3d9b8266c0101f5"
|
||||
}
|
||||
]
|
||||
}
|
64
build-aux/modules/python-python-lsp-ruff.json
Normal file
@ -0,0 +1,64 @@
|
||||
{
|
||||
"name": "python3-python-lsp-ruff",
|
||||
"buildsystem": "simple",
|
||||
"build-commands": [
|
||||
"pip3 install --verbose --exists-action=i --no-index --find-links=\"file://${PWD}\" --prefix=${FLATPAK_DEST} \"python-lsp-ruff\""
|
||||
],
|
||||
"sources": [
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/e1/c7/247d04257d391251f32a7179cb74b418954022f1e9e276b5933e6ac1d3b1/python_lsp_ruff-2.2.0-py3-none-any.whl",
|
||||
"sha256": "fe0487c7997b38a59862c44e19cb815e24bb1b2f7cef4f1f32c61cf623a5ce94"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/b3/0d/cd4a4071c7f38385dc5ba91286723b4d1090b87815db48216212c6c6c30e/cattrs-23.2.3-py3-none-any.whl",
|
||||
"sha256": "0341994d94971052e9ee70662542699a3162ea1e0c62f7ce1b4a57f563685108"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/8d/37/2351e48cb3309673492d3a8c59d407b75fb6630e560eb27ecd4da03adc9a/lsprotocol-2023.0.1-py3-none-any.whl",
|
||||
"sha256": "c75223c9e4af2f24272b14c6375787438279369236cd568f596d4951052a60f2"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/91/f7/3b9c3a588e46bbdc2671d8fd07ecee118a672db50d72656b5726fbeffbcd/python_lsp_server-1.10.0-py3-none-any.whl",
|
||||
"sha256": "1a9f338bd7cf3cdde5ae85a2bd93fd5be9e55249f6482d88f99fb6227215424a"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/e0/44/827b2a91a5816512fcaf3cc4ebc465ccd5d598c45cefa6703fcf4a79018f/attrs-23.2.0-py3-none-any.whl",
|
||||
"sha256": "99b87a485a5820b23b879f04c2305b44b951b502fd64be915879d77a7e8fc6f1"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/20/9f/bc63f0f0737ad7a60800bfd472a4836661adae21f9c2535f3957b1e54ceb/jedi-0.19.1-py2.py3-none-any.whl",
|
||||
"sha256": "e983c654fe5c02867aef4cdfce5a2fbb4a50adc0af145f70504238f18ef5e7e0"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/a5/5b/0cc789b59e8cc1bf288b38111d002d8c5917123194d45b29dcdac64723cc/pluggy-1.4.0-py3-none-any.whl",
|
||||
"sha256": "7db9f7b503d67d1c5b95f59773ebb58a8c1c288129a88665838012cfb07b8981"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/cb/d9/656659d5b5d5f402b2b174cd0ba9bc827e07ce3c0bf88da65424baf64af8/python_lsp_jsonrpc-1.1.2-py3-none-any.whl",
|
||||
"sha256": "7339c2e9630ae98903fdaea1ace8c47fba0484983794d6aafd0bd8989be2b03c"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/6e/54/6f2bdac7117e89a47de4511c9f01732a283457ab1bf856e1e51aa861619e/ujson-5.9.0.tar.gz",
|
||||
"sha256": "89cc92e73d5501b8a7f48575eeb14ad27156ad092c2e9fc7e3cf949f07e75532"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/c1/cf/4eee59f6c4111b3e80cc32cf6bac483a90646f5c8693e84496c9855e8e38/docstring_to_markdown-0.15-py3-none-any.whl",
|
||||
"sha256": "27afb3faedba81e34c33521c32bbd258d7fbb79eedf7d29bc4e81080e854aec0"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/05/63/8011bd08a4111858f79d2b09aad86638490d62fbf881c44e434a6dfca87b/parso-0.8.3-py2.py3-none-any.whl",
|
||||
"sha256": "c001d4636cd3aecdaf33cbb40aebb59b094be2a74c556778ef5576c175e19e75"
|
||||
}
|
||||
]
|
||||
}
|
69
build-aux/modules/python-python-lsp-server.json
Normal file
@ -0,0 +1,69 @@
|
||||
{
|
||||
"name": "python3-python-lsp-server",
|
||||
"buildsystem": "simple",
|
||||
"build-commands": [
|
||||
"pip3 install --verbose --exists-action=i --no-index --find-links=\"file://${PWD}\" --prefix=${FLATPAK_DEST} \"python-lsp-server\""
|
||||
],
|
||||
"sources": [
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/be/4f/1b6eb5a6d92ae52f3798e9fdffd225f1bcd017172bb732743315390a9025/docstring_to_markdown-0.13-py3-none-any.whl",
|
||||
"sha256": "aa487059d0883e70e54da25c7b230e918d9e4d40f23d6dfaa2b73e4225b2d7dd"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/20/9f/bc63f0f0737ad7a60800bfd472a4836661adae21f9c2535f3957b1e54ceb/jedi-0.19.1-py2.py3-none-any.whl",
|
||||
"sha256": "e983c654fe5c02867aef4cdfce5a2fbb4a50adc0af145f70504238f18ef5e7e0"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/05/63/8011bd08a4111858f79d2b09aad86638490d62fbf881c44e434a6dfca87b/parso-0.8.3-py2.py3-none-any.whl",
|
||||
"sha256": "c001d4636cd3aecdaf33cbb40aebb59b094be2a74c556778ef5576c175e19e75"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/05/b8/42ed91898d4784546c5f06c60506400548db3f7a4b3fb441cba4e5c17952/pluggy-1.3.0-py3-none-any.whl",
|
||||
"sha256": "d89c696a773f8bd377d18e5ecda92b7a3793cbe66c87060a6fb58c7b6e1061f7"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/cb/d9/656659d5b5d5f402b2b174cd0ba9bc827e07ce3c0bf88da65424baf64af8/python_lsp_jsonrpc-1.1.2-py3-none-any.whl",
|
||||
"sha256": "7339c2e9630ae98903fdaea1ace8c47fba0484983794d6aafd0bd8989be2b03c"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/83/49/355783384945708c604f4ad4c773d4ec93bc609b691698e5d8ecfc51d01c/python_lsp_server-1.9.0-py3-none-any.whl",
|
||||
"sha256": "6b947cf9dc33d7bed9abc936bb173140fcf606b6eb50cf02e27d4cb09f10d3fb"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/6e/54/6f2bdac7117e89a47de4511c9f01732a283457ab1bf856e1e51aa861619e/ujson-5.9.0.tar.gz",
|
||||
"sha256": "89cc92e73d5501b8a7f48575eeb14ad27156ad092c2e9fc7e3cf949f07e75532"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/ec/1a/610693ac4ee14fcdf2d9bf3c493370e4f2ef7ae2e19217d7a237ff42367d/packaging-23.2-py3-none-any.whl",
|
||||
"sha256": "8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/0e/a3/b9a8b0adfe672bf0df5901707aa929d30a97ee390ba651910186776746d2/setuptools_scm-8.0.4-py3-none-any.whl",
|
||||
"sha256": "b47844cd2a84b83b3187a5782c71128c28b4c94cad8bfb871da2784a5cb54c4f"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/b7/f4/6a90020cd2d93349b442bfcb657d0dc91eee65491600b2cb1d388bc98e6b/typing_extensions-4.9.0-py3-none-any.whl",
|
||||
"sha256": "af72aea155e91adfc61c3ae9e0e342dbc0cba726d6cba4b6c72c1f34e47291cd"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/bb/e1/ed2dd0850446b8697ad28d118df885ad04140c64ace06c4bd559f7c8a94f/setuptools-69.0.2-py3-none-any.whl",
|
||||
"sha256": "1e8fdff6797d3865f37397be788a4e3cba233608e9b509382a2777d25ebde7f2"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/c7/c3/55076fc728723ef927521abaa1955213d094933dc36d4a2008d5101e1af5/wheel-0.42.0-py3-none-any.whl",
|
||||
"sha256": "177f9c9b0d45c47873b619f5b650346d632cdc35fb5e4d25058e09c9e581433d"
|
||||
}
|
||||
]
|
||||
}
|
48
build-aux/modules/python-ruff.json
Normal file
@ -0,0 +1,48 @@
|
||||
{
|
||||
"name": "python3-ruff",
|
||||
"buildsystem": "simple",
|
||||
"build-commands": [
|
||||
". /usr/lib/sdk/rust-stable/enable.sh && pip3 install --verbose --exists-action=i --no-index --find-links=\"file://${PWD}\" --prefix=${FLATPAK_DEST} \"ruff\""
|
||||
],
|
||||
"build-options": {
|
||||
"env": {
|
||||
"CARGO_HOME": "/run/build/python3-ruff/cargo",
|
||||
"CARGO_NET_OFFLINE": "true"
|
||||
}
|
||||
},
|
||||
"sources": [
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/20/90/43a3aa35f037e91582ec7516a92084a71f84e89e39ef580813bed072b154/maturin-1.4.0.tar.gz",
|
||||
"sha256": "ed12e1768094a7adeafc3a74ebdb8dc2201fa64c4e7e31f14cfc70378bf93790"
|
||||
},
|
||||
"sources/cargo-sources-maturin.json",
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/ef/cc/93f7213b2ab5ed383f98ce8020e632ef256b406b8569606c3f160ed8e1c9/setuptools-68.2.2.tar.gz",
|
||||
"sha256": "4ac1475276d2f1c48684874089fefcd83bd7162ddaafb81fac866ba0db282a87"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/c7/c3/55076fc728723ef927521abaa1955213d094933dc36d4a2008d5101e1af5/wheel-0.42.0-py3-none-any.whl",
|
||||
"sha256": "177f9c9b0d45c47873b619f5b650346d632cdc35fb5e4d25058e09c9e581433d"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/f7/7f/8b1c33598b03ad612b8ced223f9ca54076b789fabf5a66ce37cc096d9cf7/setuptools_rust-1.9.0-py3-none-any.whl",
|
||||
"sha256": "409caf49dcf7ad9bd510b4bf4011fbad504e745fae98f57fe1c06f3a97719638"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/6a/23/8146aad7d88f4fcb3a6218f41a60f6c2d4e3a72de72da1825dc7c8f7877c/semantic_version-2.10.0-py2.py3-none-any.whl",
|
||||
"sha256": "de78a3b8e0feda74cabc54aab2da702113e33ac9d9eb9d2389bcf1f58b7d9177"
|
||||
},
|
||||
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/61/b0/5fb64bc79464823ca94e566c9000143ddc11f9396c6e20202315059dd64f/ruff-0.3.0.tar.gz",
|
||||
"sha256": "0886184ba2618d815067cf43e005388967b67ab9c80df52b32ec1152ab49f53a"
|
||||
},
|
||||
"sources/cargo-sources-ruff.json"
|
||||
]
|
||||
}
|
3986
build-aux/modules/sources/cargo-sources-maturin.json
Normal file
4584
build-aux/modules/sources/cargo-sources-ruff.json
Normal file
32
build-aux/modules/vte.json
Normal file
@ -0,0 +1,32 @@
|
||||
{
|
||||
"name": "vte",
|
||||
"buildsystem": "meson",
|
||||
"config-opts": [
|
||||
"--libdir=/app/lib",
|
||||
"-Ddocs=false",
|
||||
"-Dgtk3=false",
|
||||
"-Dgtk4=true",
|
||||
"-Dvapi=true",
|
||||
"-Dglade=false"
|
||||
],
|
||||
"sources": [
|
||||
{
|
||||
"type": "archive",
|
||||
"url": "https://download.gnome.org/sources/vte/0.79/vte-0.79.91.tar.xz",
|
||||
"sha256": "adca667d40ae1839ba258b63701cd05fba249303d72258711cc69294b2cb8646"
|
||||
}
|
||||
],
|
||||
"modules": [
|
||||
{
|
||||
"name": "fast_float",
|
||||
"buildsystem": "cmake-ninja",
|
||||
"sources": [
|
||||
{
|
||||
"type": "archive",
|
||||
"url": "https://github.com/fastfloat/fast_float/archive/refs/tags/v6.1.6.tar.gz",
|
||||
"sha256": "4458aae4b0eb55717968edda42987cabf5f7fc737aee8fede87a70035dba9ab0"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
62
build-aux/re.sonny.Workbench.Devel.json
Normal file
@ -0,0 +1,62 @@
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/flatpak/flatpak-builder/main/data/flatpak-manifest.schema.json",
|
||||
"id": "re.sonny.Workbench.Devel",
|
||||
"runtime": "org.gnome.Sdk",
|
||||
"runtime-version": "48",
|
||||
"sdk": "org.gnome.Sdk",
|
||||
"sdk-extensions": [
|
||||
"org.freedesktop.Sdk.Extension.vala",
|
||||
"org.freedesktop.Sdk.Extension.rust-stable",
|
||||
"org.freedesktop.Sdk.Extension.llvm18",
|
||||
"org.freedesktop.Sdk.Extension.node20",
|
||||
"org.freedesktop.Sdk.Extension.typescript"
|
||||
],
|
||||
"build-options": {
|
||||
"append-path": "/usr/lib/sdk/vala/bin:/usr/lib/sdk/rust-stable/bin:/usr/lib/sdk/node20/bin:/usr/lib/sdk/typescript/bin",
|
||||
"append-ld-library-path": "/usr/lib/sdk/vala/lib"
|
||||
},
|
||||
"command": "workbench",
|
||||
"separate-locales": false,
|
||||
"finish-args": [
|
||||
"--share=ipc",
|
||||
"--socket=fallback-x11",
|
||||
"--socket=wayland",
|
||||
"--device=dri"
|
||||
],
|
||||
"cleanup": [
|
||||
"#/include",
|
||||
"#/lib/pkgconfig",
|
||||
"/man",
|
||||
"/share/doc",
|
||||
"/share/gtk-doc",
|
||||
"/share/man",
|
||||
"#/share/pkgconfig",
|
||||
"/share/installed-tests",
|
||||
"*.la",
|
||||
"*.a"
|
||||
],
|
||||
"modules": [
|
||||
"modules/blueprint-compiler.json",
|
||||
"modules/biome.json",
|
||||
"modules/vte.json",
|
||||
"modules/libshumate.json",
|
||||
"modules/libportal.json",
|
||||
"modules/libspelling.json",
|
||||
"modules/gom.json",
|
||||
"modules/GTKCssLanguageServer.json",
|
||||
"modules/python-python-lsp-server.json",
|
||||
"modules/python-ruff.json",
|
||||
"modules/python-python-lsp-ruff.json",
|
||||
{
|
||||
"name": "Workbench",
|
||||
"buildsystem": "meson",
|
||||
"config-opts": ["-Dprofile=development"],
|
||||
"sources": [
|
||||
{
|
||||
"type": "dir",
|
||||
"path": ".."
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
62
build-aux/re.sonny.Workbench.json
Normal file
@ -0,0 +1,62 @@
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/flatpak/flatpak-builder/main/data/flatpak-manifest.schema.json",
|
||||
"id": "re.sonny.Workbench",
|
||||
"runtime": "org.gnome.Sdk",
|
||||
"runtime-version": "48",
|
||||
"sdk": "org.gnome.Sdk",
|
||||
"sdk-extensions": [
|
||||
"org.freedesktop.Sdk.Extension.vala",
|
||||
"org.freedesktop.Sdk.Extension.rust-stable",
|
||||
"org.freedesktop.Sdk.Extension.llvm18",
|
||||
"org.freedesktop.Sdk.Extension.node20",
|
||||
"org.freedesktop.Sdk.Extension.typescript"
|
||||
],
|
||||
"build-options": {
|
||||
"append-path": "/usr/lib/sdk/vala/bin:/usr/lib/sdk/rust-stable/bin:/usr/lib/sdk/node20/bin:/usr/lib/sdk/typescript/bin",
|
||||
"append-ld-library-path": "/usr/lib/sdk/vala/lib"
|
||||
},
|
||||
"command": "workbench",
|
||||
"separate-locales": false,
|
||||
"finish-args": [
|
||||
"--share=ipc",
|
||||
"--socket=fallback-x11",
|
||||
"--socket=wayland",
|
||||
"--device=dri"
|
||||
],
|
||||
"cleanup": [
|
||||
"#/include",
|
||||
"#/lib/pkgconfig",
|
||||
"/man",
|
||||
"/share/doc",
|
||||
"/share/gtk-doc",
|
||||
"/share/man",
|
||||
"#/share/pkgconfig",
|
||||
"/share/installed-tests",
|
||||
"*.la",
|
||||
"*.a"
|
||||
],
|
||||
"modules": [
|
||||
"modules/blueprint-compiler.json",
|
||||
"modules/biome.json",
|
||||
"modules/vte.json",
|
||||
"modules/libshumate.json",
|
||||
"modules/libportal.json",
|
||||
"modules/libspelling.json",
|
||||
"modules/gom.json",
|
||||
"modules/GTKCssLanguageServer.json",
|
||||
"modules/python-python-lsp-server.json",
|
||||
"modules/python-ruff.json",
|
||||
"modules/python-python-lsp-ruff.json",
|
||||
{
|
||||
"name": "Workbench",
|
||||
"buildsystem": "meson",
|
||||
"config-opts": ["-Dprofile=default"],
|
||||
"sources": [
|
||||
{
|
||||
"type": "dir",
|
||||
"path": ".."
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
308
build-aux/wip/minimist.js
Normal file
@ -0,0 +1,308 @@
|
||||
/* eslint-disable */
|
||||
|
||||
// https://github.com/minimistjs/minimist/blob/bedaa8b9ab5a901fa342aad4494cbbf676b11a21/index.js
|
||||
|
||||
function hasKey(obj, keys) {
|
||||
var o = obj;
|
||||
keys.slice(0, -1).forEach(function (key) {
|
||||
o = o[key] || {};
|
||||
});
|
||||
|
||||
var key = keys[keys.length - 1];
|
||||
return key in o;
|
||||
}
|
||||
|
||||
function isNumber(x) {
|
||||
if (typeof x === "number") {
|
||||
return true;
|
||||
}
|
||||
if (/^0x[0-9a-f]+$/i.test(x)) {
|
||||
return true;
|
||||
}
|
||||
return /^[-+]?(?:\d+(?:\.\d*)?|\.\d+)(e[-+]?\d+)?$/.test(x);
|
||||
}
|
||||
|
||||
function isConstructorOrProto(obj, key) {
|
||||
return (
|
||||
(key === "constructor" && typeof obj[key] === "function") ||
|
||||
key === "__proto__"
|
||||
);
|
||||
}
|
||||
|
||||
export default function minimist(args, opts) {
|
||||
if (!opts) {
|
||||
opts = {};
|
||||
}
|
||||
|
||||
var flags = {
|
||||
bools: {},
|
||||
strings: {},
|
||||
unknownFn: null,
|
||||
};
|
||||
|
||||
if (typeof opts.unknown === "function") {
|
||||
flags.unknownFn = opts.unknown;
|
||||
}
|
||||
|
||||
if (typeof opts.boolean === "boolean" && opts.boolean) {
|
||||
flags.allBools = true;
|
||||
} else {
|
||||
[]
|
||||
.concat(opts.boolean)
|
||||
.filter(Boolean)
|
||||
.forEach(function (key) {
|
||||
flags.bools[key] = true;
|
||||
});
|
||||
}
|
||||
|
||||
var aliases = {};
|
||||
|
||||
function isBooleanKey(key) {
|
||||
if (flags.bools[key]) {
|
||||
return true;
|
||||
}
|
||||
if (!aliases[key]) {
|
||||
return false;
|
||||
}
|
||||
return aliases[key].some(function (x) {
|
||||
return flags.bools[x];
|
||||
});
|
||||
}
|
||||
|
||||
Object.keys(opts.alias || {}).forEach(function (key) {
|
||||
aliases[key] = [].concat(opts.alias[key]);
|
||||
aliases[key].forEach(function (x) {
|
||||
aliases[x] = [key].concat(
|
||||
aliases[key].filter(function (y) {
|
||||
return x !== y;
|
||||
}),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
[]
|
||||
.concat(opts.string)
|
||||
.filter(Boolean)
|
||||
.forEach(function (key) {
|
||||
flags.strings[key] = true;
|
||||
if (aliases[key]) {
|
||||
[].concat(aliases[key]).forEach(function (k) {
|
||||
flags.strings[k] = true;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
var defaults = opts.default || {};
|
||||
|
||||
var argv = { _: [] };
|
||||
|
||||
function argDefined(key, arg) {
|
||||
return (
|
||||
(flags.allBools && /^--[^=]+$/.test(arg)) ||
|
||||
flags.strings[key] ||
|
||||
flags.bools[key] ||
|
||||
aliases[key]
|
||||
);
|
||||
}
|
||||
|
||||
function setKey(obj, keys, value) {
|
||||
var o = obj;
|
||||
for (var i = 0; i < keys.length - 1; i++) {
|
||||
var key = keys[i];
|
||||
if (isConstructorOrProto(o, key)) {
|
||||
return;
|
||||
}
|
||||
if (o[key] === undefined) {
|
||||
o[key] = {};
|
||||
}
|
||||
if (
|
||||
o[key] === Object.prototype ||
|
||||
o[key] === Number.prototype ||
|
||||
o[key] === String.prototype
|
||||
) {
|
||||
o[key] = {};
|
||||
}
|
||||
if (o[key] === Array.prototype) {
|
||||
o[key] = [];
|
||||
}
|
||||
o = o[key];
|
||||
}
|
||||
|
||||
var lastKey = keys[keys.length - 1];
|
||||
if (isConstructorOrProto(o, lastKey)) {
|
||||
return;
|
||||
}
|
||||
if (
|
||||
o === Object.prototype ||
|
||||
o === Number.prototype ||
|
||||
o === String.prototype
|
||||
) {
|
||||
o = {};
|
||||
}
|
||||
if (o === Array.prototype) {
|
||||
o = [];
|
||||
}
|
||||
if (
|
||||
o[lastKey] === undefined ||
|
||||
isBooleanKey(lastKey) ||
|
||||
typeof o[lastKey] === "boolean"
|
||||
) {
|
||||
o[lastKey] = value;
|
||||
} else if (Array.isArray(o[lastKey])) {
|
||||
o[lastKey].push(value);
|
||||
} else {
|
||||
o[lastKey] = [o[lastKey], value];
|
||||
}
|
||||
}
|
||||
|
||||
function setArg(key, val, arg) {
|
||||
if (arg && flags.unknownFn && !argDefined(key, arg)) {
|
||||
if (flags.unknownFn(arg) === false) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
var value = !flags.strings[key] && isNumber(val) ? Number(val) : val;
|
||||
setKey(argv, key.split("."), value);
|
||||
|
||||
(aliases[key] || []).forEach(function (x) {
|
||||
setKey(argv, x.split("."), value);
|
||||
});
|
||||
}
|
||||
|
||||
// Set booleans to false by default.
|
||||
Object.keys(flags.bools).forEach(function (key) {
|
||||
setArg(key, false);
|
||||
});
|
||||
// Set booleans to user defined default if supplied.
|
||||
Object.keys(defaults)
|
||||
.filter(isBooleanKey)
|
||||
.forEach(function (key) {
|
||||
setArg(key, defaults[key]);
|
||||
});
|
||||
var notFlags = [];
|
||||
|
||||
if (args.indexOf("--") !== -1) {
|
||||
notFlags = args.slice(args.indexOf("--") + 1);
|
||||
args = args.slice(0, args.indexOf("--"));
|
||||
}
|
||||
|
||||
for (var i = 0; i < args.length; i++) {
|
||||
var arg = args[i];
|
||||
var key;
|
||||
var next;
|
||||
|
||||
if (/^--.+=/.test(arg)) {
|
||||
// Using [\s\S] instead of . because js doesn't support the
|
||||
// 'dotall' regex modifier. See:
|
||||
// http://stackoverflow.com/a/1068308/13216
|
||||
var m = arg.match(/^--([^=]+)=([\s\S]*)$/);
|
||||
key = m[1];
|
||||
var value = m[2];
|
||||
if (isBooleanKey(key)) {
|
||||
value = value !== "false";
|
||||
}
|
||||
setArg(key, value, arg);
|
||||
} else if (/^--no-.+/.test(arg)) {
|
||||
key = arg.match(/^--no-(.+)/)[1];
|
||||
setArg(key, false, arg);
|
||||
} else if (/^--.+/.test(arg)) {
|
||||
key = arg.match(/^--(.+)/)[1];
|
||||
next = args[i + 1];
|
||||
if (
|
||||
next !== undefined &&
|
||||
!/^(-|--)[^-]/.test(next) &&
|
||||
!isBooleanKey(key) &&
|
||||
!flags.allBools
|
||||
) {
|
||||
setArg(key, next, arg);
|
||||
i += 1;
|
||||
} else if (/^(true|false)$/.test(next)) {
|
||||
setArg(key, next === "true", arg);
|
||||
i += 1;
|
||||
} else {
|
||||
setArg(key, flags.strings[key] ? "" : true, arg);
|
||||
}
|
||||
} else if (/^-[^-]+/.test(arg)) {
|
||||
var letters = arg.slice(1, -1).split("");
|
||||
|
||||
var broken = false;
|
||||
for (var j = 0; j < letters.length; j++) {
|
||||
next = arg.slice(j + 2);
|
||||
|
||||
if (next === "-") {
|
||||
setArg(letters[j], next, arg);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (/[A-Za-z]/.test(letters[j]) && next[0] === "=") {
|
||||
setArg(letters[j], next.slice(1), arg);
|
||||
broken = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (
|
||||
/[A-Za-z]/.test(letters[j]) &&
|
||||
/-?\d+(\.\d*)?(e-?\d+)?$/.test(next)
|
||||
) {
|
||||
setArg(letters[j], next, arg);
|
||||
broken = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (letters[j + 1] && letters[j + 1].match(/\W/)) {
|
||||
setArg(letters[j], arg.slice(j + 2), arg);
|
||||
broken = true;
|
||||
break;
|
||||
} else {
|
||||
setArg(letters[j], flags.strings[letters[j]] ? "" : true, arg);
|
||||
}
|
||||
}
|
||||
|
||||
key = arg.slice(-1)[0];
|
||||
if (!broken && key !== "-") {
|
||||
if (
|
||||
args[i + 1] &&
|
||||
!/^(-|--)[^-]/.test(args[i + 1]) &&
|
||||
!isBooleanKey(key)
|
||||
) {
|
||||
setArg(key, args[i + 1], arg);
|
||||
i += 1;
|
||||
} else if (args[i + 1] && /^(true|false)$/.test(args[i + 1])) {
|
||||
setArg(key, args[i + 1] === "true", arg);
|
||||
i += 1;
|
||||
} else {
|
||||
setArg(key, flags.strings[key] ? "" : true, arg);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!flags.unknownFn || flags.unknownFn(arg) !== false) {
|
||||
argv._.push(flags.strings._ || !isNumber(arg) ? arg : Number(arg));
|
||||
}
|
||||
if (opts.stopEarly) {
|
||||
argv._.push.apply(argv._, args.slice(i + 1));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Object.keys(defaults).forEach(function (k) {
|
||||
if (!hasKey(argv, k.split("."))) {
|
||||
setKey(argv, k.split("."), defaults[k]);
|
||||
|
||||
(aliases[k] || []).forEach(function (x) {
|
||||
setKey(argv, x.split("."), defaults[k]);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
if (opts["--"]) {
|
||||
argv["--"] = notFlags.slice();
|
||||
} else {
|
||||
notFlags.forEach(function (k) {
|
||||
argv._.push(k);
|
||||
});
|
||||
}
|
||||
|
||||
return argv;
|
||||
}
|
264
build-aux/wip/run.js
Executable file
@ -0,0 +1,264 @@
|
||||
#!/usr/bin/env -S gjs -m
|
||||
|
||||
import Gio from "gi://Gio";
|
||||
import { exit, programArgs, programInvocationName } from "system";
|
||||
import GLib from "gi://GLib";
|
||||
import minimist from "./minimist.js";
|
||||
|
||||
// export G_MESSAGES_DEBUG=Gjs-Console && ./run.js
|
||||
|
||||
Gio._promisify(
|
||||
Gio.File.prototype,
|
||||
"load_contents_async",
|
||||
"load_contents_finish",
|
||||
);
|
||||
|
||||
Gio._promisify(
|
||||
Gio.Subprocess.prototype,
|
||||
"wait_check_async",
|
||||
"wait_check_finish",
|
||||
);
|
||||
|
||||
const path = GLib.get_current_dir();
|
||||
console.debug(programInvocationName, programArgs);
|
||||
const argv = minimist(programArgs, { boolean: true, "--": true });
|
||||
console.debug(argv);
|
||||
|
||||
const [manifest_path] = argv._;
|
||||
if (!manifest_path) {
|
||||
// eslint-disable-next-line no-restricted-globals
|
||||
print(`${programInvocationName} [--verbose] [--debug] MANIFEST [-- command]`);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
const home = GLib.get_home_dir();
|
||||
|
||||
const manifest_file = Gio.File.new_for_path(manifest_path);
|
||||
const [contents] = await manifest_file.load_contents_async(null);
|
||||
const manifest = JSON.parse(new TextDecoder().decode(contents));
|
||||
|
||||
// console.log(JSON.parse(manifest));
|
||||
|
||||
const flatpak_id = manifest.id;
|
||||
// We assume the last module is the app itself
|
||||
const app_module = manifest.modules.at(-1);
|
||||
|
||||
function exists(path) {
|
||||
const result = Gio.File.new_for_path(path).query_exists(null);
|
||||
console.debug(`${path} ${result ? "exists" : "non existant"}`);
|
||||
return result;
|
||||
}
|
||||
|
||||
if (!exists(`${path}/.flatpak/repo`)) {
|
||||
const { runtime, sdk } = manifest;
|
||||
const runtime_version = manifest["runtime-version"];
|
||||
// initializes repo
|
||||
await run([
|
||||
"flatpak",
|
||||
"build-init",
|
||||
`${path}/.flatpak/repo`,
|
||||
flatpak_id,
|
||||
sdk,
|
||||
runtime,
|
||||
runtime_version,
|
||||
]);
|
||||
}
|
||||
|
||||
const prefix = [
|
||||
"flatpak-builder",
|
||||
"--ccache",
|
||||
"--force-clean",
|
||||
"--disable-updates",
|
||||
];
|
||||
const suffix = [
|
||||
`--state-dir=${path}/.flatpak/flatpak-builder`,
|
||||
`--stop-at=${app_module.name}`,
|
||||
`${path}/.flatpak/repo`,
|
||||
Gio.File.new_for_path(path).get_relative_path(manifest_file),
|
||||
];
|
||||
|
||||
// de-initializes
|
||||
async function downloadSources() {
|
||||
await run([...prefix, "--download-only", ...suffix]);
|
||||
}
|
||||
|
||||
// de-initializes
|
||||
async function buildModules() {
|
||||
await run([
|
||||
...prefix,
|
||||
"--disable-download",
|
||||
"--build-only",
|
||||
"--keep-build-dirs",
|
||||
...suffix,
|
||||
]);
|
||||
}
|
||||
|
||||
if (!exists(`${path}/.flatpak/flatpak-builder`)) {
|
||||
await downloadSources();
|
||||
await buildModules();
|
||||
}
|
||||
|
||||
// builds workbench
|
||||
if (!exists(`${path}/_build`)) {
|
||||
await buildModules();
|
||||
await buildCommand([
|
||||
"meson",
|
||||
"--prefix",
|
||||
"/app",
|
||||
"_build",
|
||||
"-Dprofile=development",
|
||||
]);
|
||||
}
|
||||
|
||||
await buildCommand(["meson", "install", "-C", "_build"]);
|
||||
// await buildCommand([
|
||||
// `troll/gjspack/bin/gjspack`,
|
||||
// `--appid=${flatpak_id}`,
|
||||
// "--prefix=/re/sonny/Workbench",
|
||||
// `--project-root=.`,
|
||||
// `--resource-root=./src`,
|
||||
// "--blueprint-compiler=/app/bin/blueprint-compiler",
|
||||
// "--no-executable",
|
||||
// `${path}/src/main.js`,
|
||||
// `/app/share/${flatpak_id}.src.gresource`,
|
||||
// ]);
|
||||
|
||||
// starts workbench
|
||||
const command = argv["--"].length ? argv["--"] : [manifest.command];
|
||||
await runCommand(command);
|
||||
|
||||
function buildCommand(argv) {
|
||||
let PATH =
|
||||
"/app/bin:/app/bin:/app/bin:/usr/bin:${home}/.var/app/com.visualstudio.code/data/node_modules/bin:/app/bin:/usr/bin";
|
||||
const append_path = manifest["build-options"]?.["append-path"];
|
||||
if (append_path) PATH += `:${append_path}`;
|
||||
|
||||
let LD_LIBRARY_PATH = "/app/lib:/app/lib";
|
||||
const append_ld_library_path =
|
||||
manifest["build-options"]?.["append-ls-library-path"];
|
||||
if (append_ld_library_path) LD_LIBRARY_PATH += `:${append_ld_library_path}`;
|
||||
|
||||
const PKG_CONFIG_PATH =
|
||||
"/usr/local/lib64/pkgconfig:/usr/local/lib/pkgconfig:/usr/local/share/pkgconfig:/usr/lib64/pkgconfig:/usr/lib/pkgconfig:/usr/share/pkgconfig:/app/lib/pkgconfig:/app/share/pkgconfig:/usr/lib/pkgconfig:/usr/share/pkgconfig";
|
||||
|
||||
return run([
|
||||
"flatpak",
|
||||
"build",
|
||||
"--share=network",
|
||||
`--filesystem=${path}`,
|
||||
`--filesystem=${path}/.flatpak/repo`,
|
||||
`--env=PATH=${PATH}`,
|
||||
`--env=LD_LIBRARY_PATH=${LD_LIBRARY_PATH}`,
|
||||
`--env=PKG_CONFIG_PATH=${PKG_CONFIG_PATH}`,
|
||||
`--filesystem=${path}/_build`,
|
||||
`${path}/.flatpak/repo`,
|
||||
...argv,
|
||||
]);
|
||||
}
|
||||
|
||||
async function runCommand(argv) {
|
||||
await exec(
|
||||
[
|
||||
"flatpak",
|
||||
"build",
|
||||
"--with-appdir",
|
||||
"--allow=devel",
|
||||
`--bind-mount=/run/user/1000/doc=/run/user/1000/doc/by-app/${flatpak_id}`,
|
||||
...manifest["finish-args"],
|
||||
|
||||
// Non default permissions, see Permissions.js
|
||||
// consider getting installed overrides instead with
|
||||
// flatpak override --user --show re.sonny.Workbench.Devel
|
||||
"--share=network",
|
||||
"--socket=pulseaudio",
|
||||
"--device=input",
|
||||
|
||||
"--talk-name=org.freedesktop.portal.*",
|
||||
"--talk-name=org.a11y.Bus",
|
||||
"--bind-mount=/run/flatpak/at-spi-bus=/run/user/1000/at-spi/bus",
|
||||
"--env=AT_SPI_BUS_ADDRESS=unix:path=/run/flatpak/at-spi-bus",
|
||||
...getHostEnv(),
|
||||
"--bind-mount=/run/host/fonts=/usr/share/fonts",
|
||||
"--bind-mount=/run/host/fonts-cache=/usr/lib/fontconfig/cache",
|
||||
`--filesystem=${home}/.local/share/fonts:ro`,
|
||||
`--filesystem=${home}/.cache/fontconfig:ro`,
|
||||
`--bind-mount=/run/host/user-fonts-cache=${home}/.cache/fontconfig`,
|
||||
`--bind-mount=/run/host/font-dirs.xml=${home}/.cache/font-dirs.xml`,
|
||||
`${path}/.flatpak/repo`,
|
||||
...argv,
|
||||
],
|
||||
{ verbose: true },
|
||||
);
|
||||
}
|
||||
|
||||
function getHostEnv() {
|
||||
// https://github.com/bilelmoussaoui/flatpak-vscode/blob/6424e7d8f53924faa33c9043153e08b0aedf6225/src/utils.ts#L88
|
||||
const forwarded_env_keys = [
|
||||
"COLORTERM",
|
||||
"DESKTOP_SESSION",
|
||||
"LANG",
|
||||
"WAYLAND_DISPLAY",
|
||||
"XDG_CURRENT_DESKTOP",
|
||||
"XDG_SEAT",
|
||||
"XDG_SESSION_DESKTOP",
|
||||
"XDG_SESSION_ID",
|
||||
"XDG_SESSION_TYPE",
|
||||
"XDG_VTNR",
|
||||
"AT_SPI_BUS_ADDRESS",
|
||||
];
|
||||
|
||||
const env_vars = [];
|
||||
forwarded_env_keys.forEach((key) => {
|
||||
const value = GLib.getenv(key);
|
||||
if (value === undefined) env_vars.push(key + "=" + value);
|
||||
});
|
||||
|
||||
return env_vars;
|
||||
}
|
||||
|
||||
async function run(_) {
|
||||
return exec(_, { verbose: argv.verbose });
|
||||
}
|
||||
|
||||
async function exec(argv, { cancellable = null /*, verbose = false*/ }) {
|
||||
argv = argv.map((arg) => {
|
||||
return arg.toString();
|
||||
});
|
||||
|
||||
console.debug(`$ ${argv.join(" ")}`);
|
||||
|
||||
let cancelId = 0;
|
||||
|
||||
// meson uses stdout for logs
|
||||
// const flags = verbose
|
||||
// ? Gio.SubprocessFlags.NONE
|
||||
// : Gio.SubprocessFlags.STDOUT_SILENCE;
|
||||
|
||||
const flags = Gio.SubprocessFlags.NONE;
|
||||
|
||||
const proc = new Gio.Subprocess({
|
||||
argv,
|
||||
flags,
|
||||
});
|
||||
proc.init(cancellable);
|
||||
|
||||
if (cancellable instanceof Gio.Cancellable)
|
||||
cancelId = cancellable.connect(() => proc.force_exit());
|
||||
|
||||
try {
|
||||
const success = await proc.wait_check_async(null);
|
||||
|
||||
if (!success) {
|
||||
const status = proc.get_exit_status();
|
||||
throw new Gio.IOErrorEnum({
|
||||
code: Gio.IOErrorEnum.FAILED,
|
||||
message: `Command '${argv}' failed with exit code ${status}`,
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
console.debug(err);
|
||||
exit(1);
|
||||
} finally {
|
||||
if (cancelId > 0) cancellable.disconnect(cancelId);
|
||||
}
|
||||
}
|
34
build-aux/wip/run.sh
Executable file
@ -0,0 +1,34 @@
|
||||
set -eux
|
||||
|
||||
flatpak_id=re.sonny.Workbench.Devel
|
||||
path=/home/sonny/Projects/Workbench
|
||||
manifest=$path/build-aux/$flatpak_id.json
|
||||
module_name=Workbench
|
||||
command=workbench
|
||||
|
||||
function run_build_command {
|
||||
flatpak build --share=network --filesystem=$path --filesystem=$path/.flatpak/repo --env=PATH=/app/bin:/app/bin:/app/bin:/usr/bin:/home/sonny/.var/app/com.visualstudio.code/data/node_modules/bin:/app/bin:/usr/bin:/usr/lib/sdk/vala/bin:/usr/lib/sdk/rust-stable/bin:/usr/lib/sdk/node20/bin:/usr/lib/sdk/typescript/bin --env=LD_LIBRARY_PATH=/app/lib:/app/lib:/usr/lib/sdk/vala/lib --env=PKG_CONFIG_PATH=/usr/local/lib64/pkgconfig:/usr/local/lib/pkgconfig:/usr/local/share/pkgconfig:/usr/lib64/pkgconfig:/usr/lib/pkgconfig:/usr/share/pkgconfig:/app/lib/pkgconfig:/app/share/pkgconfig:/usr/lib/pkgconfig:/usr/share/pkgconfig --filesystem=$path/_build $path/.flatpak/repo $1
|
||||
}
|
||||
|
||||
if [ ! -d "$path/.flatpak/repo" ]; then
|
||||
# initializes repo
|
||||
flatpak build-init $path/.flatpak/repo $flatpak_id org.gnome.Sdk org.gnome.Sdk 47
|
||||
fi
|
||||
|
||||
if [ ! -d "$path/.flatpak/flatpak-builder" ]; then
|
||||
# downloads sources (de-initializes)
|
||||
flatpak-builder --ccache --force-clean --disable-updates --download-only --state-dir=$path/.flatpak/flatpak-builder --stop-at=$module_name $path/.flatpak/repo $manifest
|
||||
# builds modules (de-initializes)
|
||||
flatpak-builder --ccache --force-clean --disable-updates --disable-download --build-only --keep-build-dirs --state-dir=$path/.flatpak/flatpak-builder --stop-at=$module_name $path/.flatpak/repo $manifest
|
||||
fi
|
||||
|
||||
# builds Workbench module
|
||||
if [ ! -d "$path/_build" ]; then
|
||||
run_build_command "meson --prefix /app _build -Dprofile=development"
|
||||
else
|
||||
time run_build_command "meson install -C _build"
|
||||
# time run_build_command "$path/troll/gjspack/bin/gjspack --appid=$flatpak_id --prefix=/re.sonny.Workbench --project-root=$path --resource-root=$path/src --blueprint-compiler=/app/bin/blueprint-compiler --no-executable $path/src/main.js /app/share/$flatpak_id.src.gresource"
|
||||
fi
|
||||
|
||||
# starts workbench
|
||||
flatpak build --with-appdir --allow=devel --bind-mount=/run/user/1000/doc=/run/user/1000/doc/by-app/$flatpak_id --share=ipc --socket=fallback-x11 --socket=wayland --device=dri --share=network --socket=pulseaudio --talk-name='org.freedesktop.portal.*' --talk-name=org.a11y.Bus --bind-mount=/run/flatpak/at-spi-bus=/run/user/1000/at-spi/bus --env=AT_SPI_BUS_ADDRESS=unix:path=/run/flatpak/at-spi-bus --env=AT_SPI_BUS_ADDRESS=unix:path=/run/flatpak/at-spi-bus --env=COLORTERM=truecolor --env=DESKTOP_SESSION=gnome --env=LANG=en_US.UTF-8 --env=WAYLAND_DISPLAY=wayland-0 --env=XDG_CURRENT_DESKTOP=GNOME --env=XDG_SESSION_DESKTOP=gnome --env=XDG_SESSION_TYPE=wayland --bind-mount=/run/host/fonts=/usr/share/fonts --bind-mount=/run/host/fonts-cache=/usr/lib/fontconfig/cache --filesystem=/home/sonny/.local/share/fonts:ro --filesystem=/home/sonny/.cache/fontconfig:ro --bind-mount=/run/host/user-fonts-cache=/home/sonny/.cache/fontconfig --bind-mount=/run/host/font-dirs.xml=/home/sonny/.cache/font-dirs.xml $path/.flatpak/repo $command
|
@ -1,14 +1,13 @@
|
||||
[Desktop Entry]
|
||||
# TRANSLATORS: Don't translate
|
||||
Name=Workbench
|
||||
Comment=Sandbox to learn and prototype with GNOME technologies
|
||||
Comment=Learn and prototype with GNOME technologies
|
||||
Exec=workbench %U
|
||||
Terminal=false
|
||||
Type=Application
|
||||
Categories=WebDevelopment;Development;IDE;GNOME;GTK;
|
||||
Icon=re.sonny.Workbench
|
||||
Icon=@app_id@
|
||||
# TRANSLATORS: Don't translate
|
||||
Keywords=CSS;JavaScript;GJS;
|
||||
Keywords=CSS;JavaScript;GJS;Blueprint;builder;Vala;GTK;libadwaita;Python;PyGObject;Rust;doc;playground;code;TypeScript;
|
||||
DBusActivatable=true
|
||||
StartupNotify=true
|
||||
MimeType=text/javascript;application/javascript;application/x-gtk-builder;text/css;
|
75
data/app.gschema.xml
Normal file
@ -0,0 +1,75 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<schemalist>
|
||||
<enum id="re.sonny.Workbench.UserInterfaceLanguage">
|
||||
<value nick="blueprint" value="0"/>
|
||||
<value nick="xml" value="1"/>
|
||||
</enum>
|
||||
|
||||
<schema id="@app_id@" path="/re/sonny/Workbench/">
|
||||
<key name="color-scheme" type="i">
|
||||
<default>0</default>
|
||||
</key>
|
||||
<key name="recent-code-language" type="i">
|
||||
<default>0</default>
|
||||
</key>
|
||||
<key name="recent-projects" type="as">
|
||||
<default>[]</default>
|
||||
</key>
|
||||
<key name="first-run" type="b">
|
||||
<default>true</default>
|
||||
</key>
|
||||
<key name="typescript" type="b">
|
||||
<default>true</default>
|
||||
</key>
|
||||
</schema>
|
||||
<schema id="@app_id@.Session" path="/re/sonny/Workbench/">
|
||||
<key name="show-code" type="b">
|
||||
<default>false</default>
|
||||
</key>
|
||||
<key name="show-style" type="b">
|
||||
<default>false</default>
|
||||
</key>
|
||||
<key name="name" type="s">
|
||||
<default>''</default>
|
||||
</key>
|
||||
<key name="show-ui" type="b">
|
||||
<default>true</default>
|
||||
</key>
|
||||
<key name="show-preview" type="b">
|
||||
<default>true</default>
|
||||
</key>
|
||||
<key name="show-console" type="b">
|
||||
<default>true</default>
|
||||
</key>
|
||||
<key name="code-language" type="i">
|
||||
<default>0</default>
|
||||
</key>
|
||||
<key name="user-interface-language" enum="re.sonny.Workbench.UserInterfaceLanguage">
|
||||
<default>'blueprint'</default>
|
||||
</key>
|
||||
<key name="preview-align" type="i">
|
||||
<default>0</default>
|
||||
</key>
|
||||
<key name="auto-preview" type="b">
|
||||
<default>true</default>
|
||||
</key>
|
||||
<key name="safe-mode" type="b">
|
||||
<default>false</default>
|
||||
</key>
|
||||
<key name="edited" type="b">
|
||||
<default>false</default>
|
||||
</key>
|
||||
<key name="window-width" type="i">
|
||||
<default>0</default>
|
||||
</key>
|
||||
<key name="window-height" type="i">
|
||||
<default>0</default>
|
||||
</key>
|
||||
<key name="window-maximized" type="b">
|
||||
<default>false</default>
|
||||
</key>
|
||||
<key name="window-fullscreened" type="b">
|
||||
<default>false</default>
|
||||
</key>
|
||||
</schema>
|
||||
</schemalist>
|
706
data/app.metainfo.xml
Normal file
@ -0,0 +1,706 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<component type="desktop">
|
||||
<id>@app_id@</id>
|
||||
<launchable type="desktop-id">@app_id@.desktop</launchable>
|
||||
<name translatable="no">Workbench</name>
|
||||
<developer id="re.sonny">
|
||||
<name translatable="no">Sonny Piers</name>
|
||||
</developer>
|
||||
<update_contact>sonnyp@gnome.org</update_contact>
|
||||
<metadata_license>CC0-1.0</metadata_license>
|
||||
<project_license>GPL-3.0</project_license>
|
||||
<summary>Prototype with GNOME technologies</summary>
|
||||
<description>
|
||||
<p>Workbench is for learning and prototyping with GNOME technologies, no matter if tinkering for the first time or building and testing a GTK user interface.</p>
|
||||
<p>Among other things, Workbench comes with</p>
|
||||
<ul>
|
||||
<li>Live GTK/CSS preview</li>
|
||||
<li>Library of 100+ examples</li>
|
||||
<li>JavaScript, Rust, Python and Vala support</li>
|
||||
<li>Declarative user interface syntax</li>
|
||||
<li>Autosave, sessions and projects</li>
|
||||
<li>Code diagnostics, completion and formatter</li>
|
||||
<li>Terminal output</li>
|
||||
</ul>
|
||||
</description>
|
||||
<url type="homepage">https://workbench.sonny.re</url>
|
||||
<url type="bugtracker">https://workbench.sonny.re/feedback</url>
|
||||
<url type="donation">https://workbench.sonny.re/donate</url>
|
||||
<url type="vcs-browser">https://workbench.sonny.re/source</url>
|
||||
<screenshots>
|
||||
<screenshot type="default">
|
||||
<image>https://raw.githubusercontent.com/workbenchdev/Workbench/main/data/screenshots/welcome.png</image>
|
||||
<caption>Welcome screen</caption>
|
||||
</screenshot>
|
||||
<screenshot>
|
||||
<image>https://raw.githubusercontent.com/workbenchdev/Workbench/main/data/screenshots/code.png</image>
|
||||
<caption>Drawing Area demo</caption>
|
||||
</screenshot>
|
||||
<screenshot>
|
||||
<image>https://raw.githubusercontent.com/workbenchdev/Workbench/main/data/screenshots/library.png</image>
|
||||
<caption>Library window</caption>
|
||||
</screenshot>
|
||||
</screenshots>
|
||||
<content_rating type="oars-1.1" />
|
||||
<releases>
|
||||
<release version="48.0" date="2025-04-xx">
|
||||
<description translatable="no">
|
||||
<ul>
|
||||
<li>Use GNOME 48</li>
|
||||
</ul>
|
||||
<p>Library:</p>
|
||||
<ul>
|
||||
<li>Add "Shortcuts Window" demo</li>
|
||||
</ul>
|
||||
<p>Dependencies:</p>
|
||||
<ul>
|
||||
<!-- <li>Update Jsonrpc-GLib to 3.44.1</li> -->
|
||||
<li>Update libportal to 0.9.1</li>
|
||||
<li>Update libshumate to 1.4</li>
|
||||
<li>Update libspelling to 0.4.6</li>
|
||||
<li>Update vte to 0.80.0</li>
|
||||
</ul>
|
||||
</description>
|
||||
</release>
|
||||
|
||||
<release version="47.1" date="2025-01-24">
|
||||
<description translatable="no">
|
||||
<ul>
|
||||
<li>Fix permissions dialog</li>
|
||||
<li>Update Blueprint to 0.16.0</li>
|
||||
<li>Update libportal to 0.9.0</li>
|
||||
</ul>
|
||||
<p>Library:</p>
|
||||
<ul>
|
||||
<li>Replace GTK syntax with CSS variables</li>
|
||||
<li>Fix year sorting in "Column View" Python</li>
|
||||
</ul>
|
||||
</description>
|
||||
</release>
|
||||
|
||||
<release version="47.0" date="2024-12-11">
|
||||
<description translatable="no">
|
||||
<ul>
|
||||
<li>Use GNOME 47</li>
|
||||
<li>Add code suggestions/completions support</li>
|
||||
<li>Add Language and Category filters to the Library</li>
|
||||
<li>Add action to create new blank project</li>
|
||||
<li>Add experimental TypeScript support</li>
|
||||
</ul>
|
||||
<p>Library:</p>
|
||||
<ul>
|
||||
<li>Add "Button Row" demo</li>
|
||||
<li>Add "Gamepad" demo</li>
|
||||
<li>Add "List View with Sections" demo</li>
|
||||
<li>Add "List View with a Tree" demo</li>
|
||||
<li>Add "Bottom Sheet" demo</li>
|
||||
<li>Add "Database" demo</li>
|
||||
<li>Update "Spinner" to use AdwSpinner</li>
|
||||
<li>Port "Dialog" to Python</li>
|
||||
<li>Port "List View" to Python</li>
|
||||
<li>Port "Grid View" to Python</li>
|
||||
<li>Port "Level Bars" to Rust</li>
|
||||
<li>Port "Text Fields" to Rust</li>
|
||||
<li>Port "Column View" to Rust</li>
|
||||
<li>Port "Clamp" to Rust</li>
|
||||
<li>Port "List View" to Rust</li>
|
||||
<li>Port "Frame" to Rust</li>
|
||||
<li>Port "Audio" to Rust</li>
|
||||
<li>Port "File Monitor" to Vala</li>
|
||||
<li>Port "Scrolled Window" to Vala</li>
|
||||
<li>Port "Menu" to Vala</li>
|
||||
<li>Port "HTTP Server" to Vala</li>
|
||||
<li>Port "Map" to Vala</li>
|
||||
<li>Port "Session Monitor and Inhibit" to Vala</li>
|
||||
<li>Port "Save File" to Vala</li>
|
||||
<li>Port "Spin Button" to Vala</li>
|
||||
<li>Port "Progress Bar" to Vala</li>
|
||||
<li>Port "Label" to Vala</li>
|
||||
<li>Port "Power Profile Monitor" to Vala</li>
|
||||
<li>Port "Drawing Area" to Vala</li>
|
||||
<li>Port "Font Dialog" to Vala</li>
|
||||
<li>Port "Select Folder" to Vala</li>
|
||||
<li>Port "Network Monitor" to Vala</li>
|
||||
<li>Port "Toggle Button" to Vala</li>
|
||||
<li>Port "Tooltip" to Vala</li>
|
||||
<li>Port "Spell Checker" to Vala</li>
|
||||
<li>Port "Popovers" to Vala</li>
|
||||
<li>Port "Menu Button" to Vala</li>
|
||||
<li>Port "Frame" to Vala</li>
|
||||
<li>Port "Actions" to Vala</li>
|
||||
<li>Port "Dialog" to Vala</li>
|
||||
<li>Port "CSS Gradients" to Vala</li>
|
||||
<li>Port "Snapshot" to Vala</li>
|
||||
</ul>
|
||||
<p>Dependencies:</p>
|
||||
<ul>
|
||||
<!-- <li>Replace Biome with TypeScript Language Server</li> -->
|
||||
<li>Add GOM dependency 0.5.3</li>
|
||||
<li>Update Biome to 1.9.4</li>
|
||||
<li>Update libshumate to 1.3</li>
|
||||
<li>Update Blueprint to 0.14.0</li>
|
||||
<li>Update vte to 0.78.2</li>
|
||||
<li>Update libspelling to 0.4.5</li>
|
||||
<li>Update libportal to 0.8.1</li>
|
||||
</ul>
|
||||
</description>
|
||||
</release>
|
||||
|
||||
<release version="46.1" date="2024-04-30">
|
||||
<description translatable="no">
|
||||
<ul>
|
||||
<li>Add "Find" to search for code in the current editor</li>
|
||||
<li>Save and restore the session window dimensions</li>
|
||||
<li>Add "Reveal in Folder" to browse project files</li>
|
||||
<li>Remove Icon Library, please refer to the "Using Icons" entry</li>
|
||||
<li>List editor shortcuts in Shortcuts</li>
|
||||
<li>Fix Vala and Rust extensions detection on "Run"</li>
|
||||
<li>Library: Add "Using Icons"</li>
|
||||
<li>Library: Add "SVG"</li>
|
||||
<li>Library: Split "List View Widget" into "List View" and "Grid View"</li>
|
||||
<li>Library: Port "Animation" to Python</li>
|
||||
<li>Library: Port "Radio Buttons" to Vala</li>
|
||||
<li>Library: Port "Switch" to Vala</li>
|
||||
<li>Library: Port "Revealer" to Vala</li>
|
||||
<li>Library: Port "Styling with CSS" to Vala</li>
|
||||
<li>Library: Port "Separator" to Vala</li>
|
||||
<li>Library: Port "Level Bars" to Vala</li>
|
||||
<li>Library: Port "Link Button" to Vala</li>
|
||||
</ul>
|
||||
</description>
|
||||
</release>
|
||||
|
||||
<release version="46" date="2024-03-20">
|
||||
<description translatable="no">
|
||||
<ul>
|
||||
<li>Use GNOME 46</li>
|
||||
<li>Add basic Rust diagnostics</li>
|
||||
<li>Add basic Python diagnostics</li>
|
||||
<li>Replace Python formatter Black with Ruff</li>
|
||||
<li>Support libadwaita dialogs</li>
|
||||
<li>Stop adding a superfluous newlines to end of files</li>
|
||||
<li>Optimize opening Library entries</li>
|
||||
<li>Open project windows maximized</li>
|
||||
<li>Fix dangling bwrap processes after quitting Workbench</li>
|
||||
<li>Modernize the Extensions window</li>
|
||||
<li>Update Biome to 1.6.0</li>
|
||||
<li>Update libspelling to 0.2.1</li>
|
||||
<li>Update gst-plugin-gtk4 to 0.12.1</li>
|
||||
<li>Update libshumate to 1.2</li>
|
||||
<li>Update VTE to 0.76</li>
|
||||
<li>Update Blueprint to 0.12.0</li>
|
||||
<li>Update GTKCssLanguageServer</li>
|
||||
<li>Update icon-development-kit</li>
|
||||
<li>Library: Adapt demos to use GNOME 46 features</li>
|
||||
<li>Library: Add FileFilter example to "Open File" demo</li>
|
||||
<li>Library: Add "Snapshot" demo</li>
|
||||
<li>Library: Port "Scrolled Window" demo to Python</li>
|
||||
<li>Library: Port "HTTP Image" demo to Python</li>
|
||||
<li>Library: Port "HTTP Request" demo to Python</li>
|
||||
<li>Library: Port "HTTP Server" demo to Python</li>
|
||||
<li>Library: Port "Font Dialog" demo to Python</li>
|
||||
<li>Library: Port "Box" demo to Python</li>
|
||||
<li>Library: Port "Frame" demo to Python</li>
|
||||
<li>Library: Port "Grid" demo to Python</li>
|
||||
<li>Library: Port "Web View" demo to Python</li>
|
||||
<li>Library: Port "Network Monitor" demo to Python</li>
|
||||
<li>Library: Port "Navigation View" demo to Python</li>
|
||||
<li>Library: Port "Launcher" demo to Python</li>
|
||||
<li>Library: Port "Audio" demo to Python</li>
|
||||
<li>Library: Port "Map" demo to Python</li>
|
||||
<li>Library: Port "File Monitor" demo to Python</li>
|
||||
<li>Library: Port "WebSocket Client" demo to Python</li>
|
||||
<li>Library: Port "Screencast" demo to Python</li>
|
||||
<li>Library: Port "Progress Bar" demo to Python</li>
|
||||
<li>Library: Port "Camera" demo to Python</li>
|
||||
<li>Library: Port "Location" demo to Python</li>
|
||||
<li>Library: Port "List Model" demo to Python</li>
|
||||
<li>Library: Port "Drop Down" demo to Python</li>
|
||||
<li>Library: Port "Drawing Area" demo to Python</li>
|
||||
<li>Library: Port "Session Monitor and Inhibit" demo to Python</li>
|
||||
<li>Library: Port "View Switcher" demo to Python</li>
|
||||
<li>Library: Port "View Switcher" demo to Python</li>
|
||||
<li>Library: Port "Checkboxes" demo to Vala</li>
|
||||
<li>Library: Port "Action Bar" demo to Vala</li>
|
||||
<li>Library: Port "Clamp" demo to Vala</li>
|
||||
<li>Library: Port "Banner" demo to Vala</li>
|
||||
<li>Library: Port "Emoji Chooser" demo to Vala</li>
|
||||
</ul>
|
||||
</description>
|
||||
</release>
|
||||
<release version="45.4" date="2024-01-14">
|
||||
<description translatable="no">
|
||||
<ul>
|
||||
<li>Restore on-disk projects when starting Workbench</li>
|
||||
<li>Open the Library on start if there are no sessions to restore</li>
|
||||
<li>Restore scroll and cusor positions on format and Run</li>
|
||||
<li>Add "Copy" and "Select All" to Console</li>
|
||||
<li>Add Vala formatter support</li>
|
||||
<li>Add WebP image format support</li>
|
||||
<li>Use Biome instead of prettier as JavaScript formatter</li>
|
||||
<li>Use GTKCssLanguageServer instead of prettier as CSS formatter</li>
|
||||
<li>Fix Console style when toggling dark mode</li>
|
||||
<li>Fix blank preview on demos with no code</li>
|
||||
<li>Fix Style affecting other windows</li>
|
||||
<li>Update Biome to 1.4.1</li>
|
||||
<li>Update gst-plugin-gtk4 to 0.11.2</li>
|
||||
<li>Update libshumate 1.1.2</li>
|
||||
<li>Library: Add "Context Menu" entry</li>
|
||||
<li>Library: Add "HTTP Server" entry</li>
|
||||
<li>Library: Fix "Open File" entry</li>
|
||||
<li>Library: Replace deprecated ViewSwitcherTitle</li>
|
||||
<li>Library: Port "Accessibility" entry to Python</li>
|
||||
<li>Library: Port "Account" entry to Python</li>
|
||||
<li>Library: Port "Email" entry to Python</li>
|
||||
<li>Library: Port "Overlay Split View" entry to Python</li>
|
||||
<li>Library: Port "Label Bars" entry to Python</li>
|
||||
<li>Library: Port "Context Menu" entry to Python</li>
|
||||
<li>Library: Port "Wallpaper" entry to Python</li>
|
||||
<li>Library: Port "Drop Zone" entry to Python</li>
|
||||
<li>Library: Port "Column View" entry to Python</li>
|
||||
<li>Library: Port "Screenshot" entry to Python</li>
|
||||
<li>Library: Port "Event Controllers" entry to Python</li>
|
||||
<li>Library: Port "Drag and Drop" entry to Python</li>
|
||||
<li>Library: Port "Context Menu" entry to Vala</li>
|
||||
<li>Library: Port "Search" entry to Vala</li>
|
||||
<li>Library: Port "Grid" entry to Vala</li>
|
||||
<li>Library: Port "Accessibility" entry to Vala</li>
|
||||
<li>Library: Port "Animation" entry to Rust</li>
|
||||
<li>Library: Port "Context Menu" entry to Rust</li>
|
||||
</ul>
|
||||
</description>
|
||||
</release>
|
||||
<release version="45.3" date="2023-11-16">
|
||||
<description translatable="no">
|
||||
<ul>
|
||||
<li>Add Python support</li>
|
||||
<li>Add Blueprint formatter support</li>
|
||||
<li>Replace Manuals with "Biblioteca" available on Flathub</li>
|
||||
<li>Show which languages are available for each Library entry</li>
|
||||
<li>Allow opening Library entries in a specific language</li>
|
||||
<li>Make Library faster to launch</li>
|
||||
<li>Each Workbench window has its own title</li>
|
||||
<li>Do not exit if Library is the last window open</li>
|
||||
<li>Improve JavaScript linting</li>
|
||||
<li>Fix an issue with some libadwaita style classes not working</li>
|
||||
<li>Library: Port entries to libadwaita SpinRow</li>
|
||||
<li>Library: Fix "Preferences Window" adaptiveness</li>
|
||||
<li>Library: Simplify "HTP Request" entry</li>
|
||||
<li>Library: Simplify "Column View" entry</li>
|
||||
<li>Library: Simplify "Status Page" entry</li>
|
||||
<li>Library: Modernize "HTTP Image" entry</li>
|
||||
<li>Library: Make the "Save File" entry actually save a file</li>
|
||||
<li>Library: Port "Welcome" entry to Python</li>
|
||||
<li>Library: Port "Actions" entry to Python</li>
|
||||
<li>Library: Port "Spinner" entry to Python</li>
|
||||
<li>Library: Port "Styling with CSS" entry to Python</li>
|
||||
<li>Library: Port "Breakpoints" entry to Python</li>
|
||||
<li>Library: Port "Overlay" entry to Python</li>
|
||||
<li>Library: Port "Popovers" entry to Python</li>
|
||||
<li>Library: Port "Emoji Chooser" entry to Python</li>
|
||||
<li>Library: Port "Image" entry to Python</li>
|
||||
<li>Library: Port "Separator" entry to Python</li>
|
||||
<li>Library: Port "Menu Button" entry to Python</li>
|
||||
<li>Library: Port "Radio Buttons" entry to Python</li>
|
||||
<li>Library: Port "Link Button" entry to Python</li>
|
||||
<li>Library: Port "About Window" entry to Python</li>
|
||||
<li>Library: Port "Avatar" entry to Python</li>
|
||||
<li>Library: Port "Button" entry to Python</li>
|
||||
<li>Library: Port "Calendar" entry to Python</li>
|
||||
<li>Library: Port "Checkboxes" entry to Python</li>
|
||||
<li>Library: Port "Tooltip" entry to Python</li>
|
||||
<li>Library: Port "Toggle Button" entry to Python</li>
|
||||
<li>Library: Port "Carousel" entry to Python</li>
|
||||
<li>Library: Port "CSS Gradients" entry to Python</li>
|
||||
<li>Library: Port "Color Dialog" entry to Python</li>
|
||||
<li>Library: Port "Memory Monitor" entry to Python</li>
|
||||
<li>Library: Port "Video" entry to Python</li>
|
||||
<li>Library: Port "Text Fields" entry to Python</li>
|
||||
<li>Library: Port "Toolbar View" entry to Python</li>
|
||||
<li>Library: Port "Tab View" entry to Python</li>
|
||||
<li>Library: Port "Text View" entry to Python</li>
|
||||
<li>Library: Port "Text Colors" entry to Python</li>
|
||||
<li>Library: Port "Search" entry to Python</li>
|
||||
<li>Library: Port "Color Picker" entry to Python</li>
|
||||
<li>Library: Port "Dialogs" entry to Python</li>
|
||||
<li>Library: Port "Label" entry to Python</li>
|
||||
<li>Library: Port "Open File" entry to Python</li>
|
||||
<li>Library: Port "Flow Box" entry to Python</li>
|
||||
<li>Library: Port "Revealer" entry to Python</li>
|
||||
<li>Library: Port "Menu" entry to Python</li>
|
||||
<li>Library: Port "Switch" entry to Python</li>
|
||||
<li>Library: Port "Stack" entry to Python</li>
|
||||
<li>Library: Port "Picture" entry to Python</li>
|
||||
<li>Library: Port "Power Profile Monitor" entry to Python</li>
|
||||
<li>Library: Port "Spin Button" entry to Python</li>
|
||||
<li>Library: Port "Source View" entry to Python</li>
|
||||
<li>Library: Port "Preferences Window" entry to Python</li>
|
||||
<li>Library: Port "Clamp" entry to Python</li>
|
||||
<li>Library: Port "Banner" entry to Python</li>
|
||||
<li>Library: Port "Save File" entry to Python</li>
|
||||
<li>Library: Port "Action Bar" entry to Python</li>
|
||||
<li>Library: Port "Scale" entry to Python</li>
|
||||
<li>Library: Port "Spell Checker" entry to Python</li>
|
||||
<li>Library: Port "Select Folder" entry to Python</li>
|
||||
<li>Library: Port "Avatar" entry to Rust</li>
|
||||
<li>Library: Port "Actions" entry to Rust</li>
|
||||
<li>Library: Port "Animation" entry to Vala</li>
|
||||
<li>Library: Port "Overlay Split View" entry to Vala</li>
|
||||
<li>Library: Port "Text Colors" entry to Vala</li>
|
||||
<li>Library: Port "Tab View" entry to Vala</li>
|
||||
<li>Library: Port "Navigation View" entry to Vala</li>
|
||||
<li>Library: Port "Open File" entry to Vala</li>
|
||||
<li>Library: Port "Avatar" entry to Vala</li>
|
||||
<li>Library: Port "Memory Monitor" entry to Vala</li>
|
||||
<li>Library: Port "Launcher" entry to Vala</li>
|
||||
<li>Library: Port "Calendar" entry to Vala</li>
|
||||
<li>Library: Port "Column View" entry to Vala</li>
|
||||
<li>Library: Port "HTTP Request" entry to Vala</li>
|
||||
<li>Library: Port "Web View" entry to Vala</li>
|
||||
</ul>
|
||||
</description>
|
||||
</release>
|
||||
<release version="45.2" date="2023-10-11">
|
||||
<description translatable="no">
|
||||
<ul>
|
||||
<li>Rust: Fix the issue of compiling fails after updating Workbench</li>
|
||||
<li>Manuals: Fix a couple of minor issues</li>
|
||||
<li>Library: Port "Web View" entry to Rust</li>
|
||||
<li>Library: Port "HTTP Image" entry to Rust</li>
|
||||
<li>Library: Port "HTTP Image" entry to Rust</li>
|
||||
<li>Library: Port "WebSocket Client" entry to Rust</li>
|
||||
<li>Library: Port "Audio" entry to Vala</li>
|
||||
<li>Library: Port "Video" entry to Vala</li>
|
||||
<li>Library: Port "Picture" entry to Vala</li>
|
||||
<li>Library: Port "Flow Box" entry to Vala</li>
|
||||
<li>Library: Port "Box" entry to Vala</li>
|
||||
</ul>
|
||||
</description>
|
||||
</release>
|
||||
<release version="45.1" date="2023-10-02">
|
||||
<description translatable="no">
|
||||
<ul>
|
||||
<li>Add "Extensions" to enable Rust and Vala support</li>
|
||||
<li>Add Keyboard Shortcuts to Manuals; the documentation viewer</li>
|
||||
<li>Update and refresh UI</li>
|
||||
<li>Add audio permission</li>
|
||||
<li>Make Workbench smaller and faster to download</li>
|
||||
<li>Library: Add CSS gradientts demo</li>
|
||||
<li>Library: Add Property Row</li>
|
||||
<li>Library: Update entries to use SpinRow and SwitchRow </li>
|
||||
<li>Library: Port Map entry to Rust</li>
|
||||
<li>Library: Port Emoji Chooser to Rust</li>
|
||||
<li>Library: Fix Souce View entry</li>
|
||||
<li>Library: Use GLib.format_size() for file sizes</li>
|
||||
</ul>
|
||||
</description>
|
||||
</release>
|
||||
<release version="45.0" date="2023-09-22">
|
||||
<description translatable="no">
|
||||
<ul>
|
||||
<li>Use GNOME 45</li>
|
||||
<li>Support Rust</li>
|
||||
<li>Add multi windows and sessions support</li>
|
||||
<li>Support saving and opening a project</li>
|
||||
<li>Add offline documentation viewer "Manuals"</li>
|
||||
<li>Use GTKCssLanguageServer</li>
|
||||
<li>Add a workbench.resolve API</li>
|
||||
<li>Allow running Vala without UI code</li>
|
||||
<li>Update to Blueprint 0.10.0</li>
|
||||
<li>Update to vte 0.74</li>
|
||||
<li>Update to libportal 0.7</li>
|
||||
<li>Update Icon Development Kit</li>
|
||||
<li>Replace Rome Language Server with Biome Language Server</li>
|
||||
<li>New Library entry: Map</li>
|
||||
<li>New Library entry: Search</li>
|
||||
<li>New Library entry: Audio</li>
|
||||
<li>New Library entry: Event Controllers</li>
|
||||
<li>New Library entry: Action Bar</li>
|
||||
<li>New Library entry: Location</li>
|
||||
<li>New Library entry: Checkboxes</li>
|
||||
<li>New Library entry: Radio Buttons</li>
|
||||
<li>New Library entry: Accessibility</li>
|
||||
<li>New Library entry: List View</li>
|
||||
<li>New Library entry: Separator</li>
|
||||
<li>New Library entry: Link Button</li>
|
||||
<li>New Library entry: Actions</li>
|
||||
<li>New Library entry: Tooltip</li>
|
||||
<li>New Library entry: Flow Box</li>
|
||||
<li>New Library entry: Emoji Chooser</li>
|
||||
<li>New Library entry: Editable Label</li>
|
||||
<li>New Library entry: Drop Zone</li>
|
||||
<li>New Library entry: Label</li>
|
||||
<li>New Library entry: Menu Button</li>
|
||||
<li>New Library entry: Image</li>
|
||||
<li>New Library entry: Column View</li>
|
||||
<li>New Library entry: Menu</li>
|
||||
<li>New Library entry: Laucher (File / Uri)</li>
|
||||
<li>New Library entry: Navigation Split View</li>
|
||||
<li>New Library entry: Overlay Split View</li>
|
||||
<li>New Library entry: Navigation View</li>
|
||||
<li>New Library entry: Scrolled Window</li>
|
||||
<li>New Library entry: Power Profile Monitor</li>
|
||||
<li>New Library entry: Network Monitor Demo</li>
|
||||
<li>New Library entry: Clamp</li>
|
||||
<li>New Library entry: Source View</li>
|
||||
<li>New Library entry: Breakpoint</li>
|
||||
<li>New Library entry: Screencast</li>
|
||||
<li>New Library entry: Toolbar View</li>
|
||||
<li>New Library entry: Picture</li>
|
||||
<li>New Library entry: Memory Monitor</li>
|
||||
<li>New Library entry: Camera</li>
|
||||
<li>New Library entry: Center Box</li>
|
||||
<li>New Library entry: File Monitor</li>
|
||||
<li>New Library entry: Session Monitor and Inhibit</li>
|
||||
<li>New Library entry: Open File</li>
|
||||
<li>New Library entry: Save File</li>
|
||||
<li>New Library entry: Select Folder</li>
|
||||
<li>New Library entry: Spell Checker</li>
|
||||
<li>New Library entry: HTTP Request</li>
|
||||
</ul>
|
||||
</description>
|
||||
</release>
|
||||
<release version="44.2" date="2023-06-23">
|
||||
<description translatable="no">
|
||||
<ul>
|
||||
<li>Improve Screenshot Preview</li>
|
||||
<li>Fix a bug causing preview to update on certain events</li>
|
||||
<li>Fix a crash related to GtkStackPage</li>
|
||||
<li>New Library entry: Popover</li>
|
||||
<li>New Library entry: Screenshot</li>
|
||||
<li>New Library entry: Header Bar</li>
|
||||
<li>New Library entry: Font Dialog</li>
|
||||
<li>New Library entry: Preferences Window</li>
|
||||
<li>New Library entry: Web View</li>
|
||||
<li>New Library entry: Boxed Lists</li>
|
||||
<li>New Library entry: Drag and Drop</li>
|
||||
<li>New Library entry: Tab View</li>
|
||||
<li>New Library entry: Drawing Area</li>
|
||||
<li>New Library entry: Advanced Buttons</li>
|
||||
<li>New Library entry: About Window</li>
|
||||
<li>New Library entry: Animation</li>
|
||||
<li>New Library entry: TextView</li>
|
||||
<li>New Library entry: Styling with CSS</li>
|
||||
<li>New Library entry: Spin Button</li>
|
||||
<li>New Library entry: Banner</li>
|
||||
<li>New Library entry: Carousel</li>
|
||||
<li>New Library entry: Color Picker</li>
|
||||
<li>New Library entry: Email</li>
|
||||
<li>New Library entry: Progress Bar</li>
|
||||
<li>New Library entry: Wallpaper</li>
|
||||
<li>New Library entry: Drop Down</li>
|
||||
<li>New Library entry: Video</li>
|
||||
<li>New Library entry: Revealer</li>
|
||||
<li>New Library entry: Account</li>
|
||||
<li>New Library entry: Stack</li>
|
||||
<li>New Library entry: Status Page</li>
|
||||
<li>New Library entry: Frame</li>
|
||||
<li>New Library entry: Account</li>
|
||||
</ul>
|
||||
</description>
|
||||
</release>
|
||||
<release version="44.1" date="2023-05-17">
|
||||
<description translatable="no">
|
||||
<ul>
|
||||
<li>Update icon-development-kit; adds 143 new icons</li>
|
||||
<li>Update to Blueprint to 0.8.1</li>
|
||||
<li>Update to VTE 0.72.1</li>
|
||||
<li>Update to Rome tools 12.1.1</li>
|
||||
</ul>
|
||||
</description>
|
||||
</release>
|
||||
<release version="44.0" date="2023-04-15">
|
||||
<description translatable="no">
|
||||
<ul>
|
||||
<li>GNOME 44</li>
|
||||
<li>Workbench is now fully sandboxed and will be considered safe</li>
|
||||
<li>18 new Library entries</li>
|
||||
<li>Add a setting to disable Auto-Update of Preview</li>
|
||||
<li>Improve previewer and add a Safe Mode</li>
|
||||
<li>Update Blueprint, vte, vls and Rome</li>
|
||||
<li>The library window is now independant</li>
|
||||
<li>Improve feedback</li>
|
||||
<li>Fix preview of large Blueprint</li>
|
||||
</ul>
|
||||
</description>
|
||||
</release>
|
||||
<release version="43.3" date="2023-01-23">
|
||||
<description translatable="no">
|
||||
<ul>
|
||||
<li>Switching between XML and Blueprint will now export</li>
|
||||
<li>Add support for JavaScript diagnostics and linting</li>
|
||||
<li>Optimize Blueprint preview</li>
|
||||
<li>Update Blueprint 0.4.0 to 0.6.0</li>
|
||||
<li>Fix preview of non GtkBuildable objects</li>
|
||||
<li>Prevent GtkBuilder related crashes</li>
|
||||
<li>Reset top-level windows on update</li>
|
||||
<li>Destroy Vala top-level objects on close</li>
|
||||
</ul>
|
||||
</description>
|
||||
</release>
|
||||
<release version="43.2" date="2022-11-20">
|
||||
<description translatable="no">
|
||||
<ul>
|
||||
<li>Fix application not starting</li>
|
||||
</ul>
|
||||
</description>
|
||||
</release>
|
||||
<release version="43.1" date="2022-11-18">
|
||||
<description translatable="no">
|
||||
<ul>
|
||||
<li>Use Vala Language Server for diagnostics</li>
|
||||
<li>Move Icon Browser to the main application menu</li>
|
||||
<li>Reset window preview on close</li>
|
||||
<li>Add a warning about Blueprint being experimental</li>
|
||||
<li>Fix loading and running code with Blueprint UI</li>
|
||||
<li>Fix crash when using abstract UI types</li>
|
||||
<li>Fix "No UI definition loaded yet." preview error when using Vala</li>
|
||||
<li>Fix error message when hovering text with no diagnostic</li>
|
||||
<li>VTE 0.70.1</li>
|
||||
</ul>
|
||||
</description>
|
||||
</release>
|
||||
<release version="43.0" date="2022-09-21">
|
||||
<description translatable="no">
|
||||
<ul>
|
||||
<li>GNOME 43</li>
|
||||
<li>Display CSS errors inline</li>
|
||||
<li>Fix responsiveness when working on large Blueprint files</li>
|
||||
<li>Use AdwAboutWindow</li>
|
||||
<li>Blueprint 0.4.0</li>
|
||||
<li>VTE 0.70.0</li>
|
||||
<li>Various bug and crash fixes</li>
|
||||
</ul>
|
||||
</description>
|
||||
</release>
|
||||
<release version="42.3" date="2022-08-22">
|
||||
<description translatable="no">
|
||||
<ul>
|
||||
<li>Show tooltip hints in Blueprint UI code</li>
|
||||
<li>Improve XML formatter</li>
|
||||
<li>Add Ctrl+Shift+Return shortcut to format</li>
|
||||
<li>Apply Style CSS to windowed preview</li>
|
||||
<li>Improve application design</li>
|
||||
<li>Prevent crash for templates with GtkWidget parent</li>
|
||||
<li>Update VTE and icon-development-kit</li>
|
||||
</ul>
|
||||
</description>
|
||||
</release>
|
||||
<release version="42.2" date="2022-07-19">
|
||||
<description translatable="no">
|
||||
<ul>
|
||||
<li>Underline errors in Blueprint UI code</li>
|
||||
<li>Fix bugs and crashes</li>
|
||||
</ul>
|
||||
</description>
|
||||
</release>
|
||||
<release version="42.1" date="2022-07-07">
|
||||
<description translatable="no">
|
||||
<ul>
|
||||
<li
|
||||
>Add an Icon Browser to find the right icons for your prototypes</li>
|
||||
<li>Add a Platform tools Library demo</li>
|
||||
<li>Improve the style switcher</li>
|
||||
<li>Replace confirmation dialogs with toasts and undo</li>
|
||||
<li>Support updates on root objects</li>
|
||||
<li>Support binding signal handlers from UI</li>
|
||||
<li>Add APIs to allow using templates from Code</li>
|
||||
<li>Add Center/Fill preview modes for templates</li>
|
||||
<li
|
||||
>Open external preview with the dimensions of the internal preview</li>
|
||||
<li>64 new icons available</li>
|
||||
<li>Update Blueprint to 0.2.0</li>
|
||||
<li>Fix empty preview on first load</li>
|
||||
<li>Fix style scheme switch when system preference is light</li>
|
||||
<li>Remove grid pattern on the source editors</li>
|
||||
</ul>
|
||||
</description>
|
||||
</release>
|
||||
<release version="42.0" date="2022-06-04">
|
||||
<description translatable="no">
|
||||
<p>Highlights</p>
|
||||
<ul>
|
||||
<li>Add Blueprint markup syntax for UI</li>
|
||||
<li>Add Vala programming language for Code</li>
|
||||
<li>Add support for previewing templates</li>
|
||||
<li>Add support for previewing signal handlers</li>
|
||||
<li>Include all icons from icon-development-kit</li>
|
||||
<li>Improve application design</li>
|
||||
<li>Distribute Library examples under CC0-1.0</li>
|
||||
<li>Respect system preference for color scheme</li>
|
||||
<li>Add proper light/dark color schemes for Console</li>
|
||||
<li>Fix error when importing files</li>
|
||||
</ul>
|
||||
<p>Other changes</p>
|
||||
<ul>
|
||||
<li>Silence platform tools</li>
|
||||
<li>Remove GTK Icon browser platform tool</li>
|
||||
<li>Make Library examples only open relevant panels</li>
|
||||
<li>Always open the Console when opening a Library example</li>
|
||||
<li>Prevent running Code if the panel is not visible</li>
|
||||
<li>Add icons and mnemonics for all buttons</li>
|
||||
<li>Move Bookmarks to the main menu</li>
|
||||
<li>Enable scrollbar and kinetic scrolling on Console</li>
|
||||
<li>Improve Library examples</li>
|
||||
<li>Performance optimizations</li>
|
||||
<li>Show a placeholder when all panels are invisible</li>
|
||||
<li>Crash fixes</li>
|
||||
<li>Use org.gnome.Sdk runtime</li>
|
||||
</ul>
|
||||
</description>
|
||||
</release>
|
||||
<release version="1.2.0" date="2022-05-06">
|
||||
<description translatable="no">
|
||||
<ul>
|
||||
<li>Add a Library of examples</li>
|
||||
<li>Add an example of WebSocket client</li>
|
||||
<li>Add an example of toasts</li>
|
||||
<li>Add an example of application window</li>
|
||||
<li>Add an example of desktop notification</li>
|
||||
<li
|
||||
>Add Adwaita Demo, GTK Demo, GTK Widget Factory and GTK Icon Browser</li>
|
||||
<li>The Console can be collapsed by resizing it</li>
|
||||
<li>Prevent system.exit from quitting Workbench</li>
|
||||
<li>Allow calling GObject.registerClass multiple times</li>
|
||||
<li>Prevent crash caused by using non GtkBuildable objects</li>
|
||||
<li>Allow using DBus and Gio.Application</li>
|
||||
<li>Allow using network</li>
|
||||
<li>Enable GtkWindow objects preview</li>
|
||||
</ul>
|
||||
</description>
|
||||
</release>
|
||||
<release version="1.1.0" date="2022-03-24">
|
||||
<description translatable="no">
|
||||
<ul>
|
||||
<li>Take a png screenshot of the preview</li>
|
||||
<li>The console is now resizable</li>
|
||||
<li>Redesign the dark/light mode switcher</li>
|
||||
<li>Show platform and dependencies in about dialog</li>
|
||||
<li>Update to GNOME platform 42</li>
|
||||
<li>Various fixes</li>
|
||||
</ul>
|
||||
</description>
|
||||
</release>
|
||||
<release version="1.0.0" date="2022-03-02">
|
||||
<description
|
||||
>This is the first release of Workbench. We hope you like it.</description>
|
||||
</release>
|
||||
</releases>
|
||||
<kudos>
|
||||
<kudo>HiDpiIcon</kudo>
|
||||
<kudo>HighContrast</kudo>
|
||||
<kudo>ModernToolkit</kudo>
|
||||
</kudos>
|
||||
<branding>
|
||||
<color type="primary" scheme_preference="light">#57e389</color>
|
||||
<color type="primary" scheme_preference="dark">#26a269</color>
|
||||
</branding>
|
||||
<requires>
|
||||
<display_length compare="ge">1024</display_length>
|
||||
</requires>
|
||||
<recommends>
|
||||
<control>keyboard</control>
|
||||
<control>pointing</control>
|
||||
<control>touch</control>
|
||||
</recommends>
|
||||
</component>
|
@ -1,3 +1,3 @@
|
||||
[D-BUS Service]
|
||||
Name=re.sonny.Workbench
|
||||
Name=@app_id@
|
||||
Exec=@bindir@/workbench --gapplication-service
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.9 KiB |
@ -1,53 +1,46 @@
|
||||
desktop_file = i18n.merge_file(
|
||||
input: 're.sonny.Workbench.desktop',
|
||||
output: 're.sonny.Workbench.desktop',
|
||||
type: 'desktop',
|
||||
po_dir: '../po',
|
||||
install: true,
|
||||
install_dir: join_paths(get_option('datadir'), 'applications')
|
||||
desktop_file = configure_file(
|
||||
input: 'app.desktop',
|
||||
output: '@0@.desktop'.format(app_id),
|
||||
configuration: { 'app_id': app_id },
|
||||
install_dir: get_option('datadir') / 'applications'
|
||||
)
|
||||
|
||||
desktop_utils = find_program('desktop-file-validate', required: false)
|
||||
if desktop_utils.found()
|
||||
test('Validate desktop file', desktop_utils,
|
||||
args: [desktop_file]
|
||||
)
|
||||
endif
|
||||
|
||||
appstream_file = i18n.merge_file(
|
||||
input: 're.sonny.Workbench.metainfo.xml',
|
||||
output: 're.sonny.Workbench.metainfo.xml',
|
||||
po_dir: '../po',
|
||||
install: true,
|
||||
install_dir: join_paths(get_option('datadir'), 'metainfo')
|
||||
desktop_utils = find_program('desktop-file-validate', required: true)
|
||||
test('Validate desktop file', desktop_utils,
|
||||
args: [desktop_file]
|
||||
)
|
||||
|
||||
service_conf = configuration_data()
|
||||
service_conf.set('bindir', bindir)
|
||||
configure_file(
|
||||
input: 're.sonny.Workbench.service',
|
||||
output: 're.sonny.Workbench.service',
|
||||
configuration: service_conf,
|
||||
install_dir: join_paths(get_option('datadir'), 'dbus-1/services')
|
||||
input: 'app.service',
|
||||
output: '@0@.service'.format(app_id),
|
||||
configuration: { 'app_id': app_id, 'bindir': bindir },
|
||||
install_dir: get_option('datadir') / 'dbus-1/services'
|
||||
)
|
||||
|
||||
appstream_util = find_program('appstream-util', required: false)
|
||||
if appstream_util.found()
|
||||
test('Validate appstream file', appstream_util,
|
||||
args: ['validate', appstream_file]
|
||||
)
|
||||
endif
|
||||
|
||||
install_data('re.sonny.Workbench.gschema.xml',
|
||||
install_dir: join_paths(get_option('datadir'), 'glib-2.0/schemas')
|
||||
appstream_file = configure_file(
|
||||
input: 'app.metainfo.xml',
|
||||
output: '@0@.metainfo.xml'.format(app_id),
|
||||
configuration: { 'app_id': app_id },
|
||||
install_dir: get_option('datadir') / 'metainfo'
|
||||
)
|
||||
|
||||
compile_schemas = find_program('glib-compile-schemas', required: false)
|
||||
if compile_schemas.found()
|
||||
test('Validate schema file', compile_schemas,
|
||||
args: ['--strict', '--dry-run', meson.current_source_dir()]
|
||||
)
|
||||
endif
|
||||
appstreamcli = find_program('appstreamcli', required: false)
|
||||
test(
|
||||
'Validate appstream file',
|
||||
appstreamcli,
|
||||
args: ['validate', '--no-net', '--explain', appstream_file],
|
||||
)
|
||||
|
||||
install_data('icons/re.sonny.Workbench.svg', install_dir: join_paths(get_option('datadir'), 'icons/hicolor/scalable/apps'))
|
||||
install_data('icons/re.sonny.Workbench-symbolic.svg', install_dir: join_paths(get_option('datadir'), 'icons/hicolor/symbolic/apps'))
|
||||
configure_file(
|
||||
input: 'app.gschema.xml',
|
||||
output: '@0@.gschema.xml'.format(app_id),
|
||||
configuration: { 'app_id': app_id },
|
||||
install_dir: get_option('datadir') / 'glib-2.0/schemas'
|
||||
)
|
||||
|
||||
compile_schemas = find_program('glib-compile-schemas', required: true)
|
||||
test('Validate schema file', compile_schemas,
|
||||
args: ['--strict', '--dry-run', meson.current_source_dir()]
|
||||
)
|
||||
|
||||
install_subdir('icons/hicolor', install_dir : get_option('datadir') / 'icons')
|
||||
|
@ -1,23 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<schemalist gettext-domain="re.sonny.Workbench">
|
||||
<schema id="re.sonny.Workbench" path="/re/sonny/Workbench/">
|
||||
<key name="toggle-color-scheme" type="b">
|
||||
<default>false</default>
|
||||
</key>
|
||||
<key name="show-code" type="b">
|
||||
<default>true</default>
|
||||
</key>
|
||||
<key name="show-style" type="b">
|
||||
<default>false</default>
|
||||
</key>
|
||||
<key name="show-ui" type="b">
|
||||
<default>true</default>
|
||||
</key>
|
||||
<key name="show-preview" type="b">
|
||||
<default>true</default>
|
||||
</key>
|
||||
<key name="show-devtools" type="b">
|
||||
<default>true</default>
|
||||
</key>
|
||||
</schema>
|
||||
</schemalist>
|
@ -1,65 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<component type="desktop">
|
||||
<id>re.sonny.Workbench</id>
|
||||
<launchable type="desktop-id">re.sonny.Workbench.desktop</launchable>
|
||||
<name translatable="no">Workbench</name>
|
||||
<developer_name translatable="no">Sonny Piers</developer_name>
|
||||
<update_contact>sonny@fastmail.net</update_contact>
|
||||
<metadata_license>CC0-1.0</metadata_license>
|
||||
<project_license>GPL-3.0</project_license>
|
||||
<summary>Sandbox to learn and prototype with GNOME technologies</summary>
|
||||
<translation type="gettext">re.sonny.Workbench</translation>
|
||||
<description>
|
||||
<p
|
||||
>Workbench goal is to let you experiment with GNOME technologies, no matter if tinkering for the first time or building and testing a custom GTK widget.</p>
|
||||
<p>Among other things, Workbench comes with</p>
|
||||
<ul>
|
||||
<li>realtime GTK/CSS preview</li>
|
||||
<li>JavaScript for quick and easy scripting</li>
|
||||
<li>Syntax highlighting, undo/redo, autosave</li>
|
||||
<li>code fomatter</li>
|
||||
<li>terminal</li>
|
||||
</ul>
|
||||
</description>
|
||||
<url type="homepage">https://workbench.sonny.re</url>
|
||||
<url type="bugtracker">https://workbench.sonny.re/feedback</url>
|
||||
<url type="donation">https://workbench.sonny.re/donate</url>
|
||||
<url type="translate">https://workbench.sonny.re/translate</url>
|
||||
<screenshots>
|
||||
<screenshot type="default">
|
||||
<image>
|
||||
https://raw.githubusercontent.com/sonnyp/Workbench/main/data/screenshot.png
|
||||
</image>
|
||||
<caption
|
||||
>Side by side editors with live preview on the right and console in the bottom</caption>
|
||||
</screenshot>
|
||||
</screenshots>
|
||||
<content_rating type="oars-1.1" />
|
||||
<releases>
|
||||
<release version="1.1.0" date="2022-03-24">
|
||||
<description>
|
||||
<ul>Take a png screenshot of the preview</ul>
|
||||
<ul>The console is now resizable</ul>
|
||||
<ul>Redesign the dark/light mode switcher</ul>
|
||||
<ul>Show platform and dependencies in about dialog</ul>
|
||||
<ul>Update to GNOME platform 42</ul>
|
||||
<ul>Various fixes</ul>
|
||||
</description>
|
||||
</release>
|
||||
<release version="1.0.0" date="2022-03-02">
|
||||
<description
|
||||
>This is the first release of Workbench. We hope you like it.</description>
|
||||
</release>
|
||||
</releases>
|
||||
<kudos>
|
||||
<kudo>HiDpiIcon</kudo>
|
||||
<kudo>HighContrast</kudo>
|
||||
<kudo>ModernToolkit</kudo>
|
||||
</kudos>
|
||||
<branding>
|
||||
<color type="primary">#33d17a</color>
|
||||
</branding>
|
||||
<custom>
|
||||
<value key="GnomeSoftware::key-colors">[(51, 209, 122)]</value>
|
||||
</custom>
|
||||
</component>
|
Before Width: | Height: | Size: 283 KiB |
BIN
data/screenshots/code-dark.png
Normal file
After Width: | Height: | Size: 125 KiB |
BIN
data/screenshots/code.png
Normal file
After Width: | Height: | Size: 124 KiB |
BIN
data/screenshots/library-dark.png
Normal file
After Width: | Height: | Size: 54 KiB |
BIN
data/screenshots/library.png
Normal file
After Width: | Height: | Size: 56 KiB |
BIN
data/screenshots/welcome-dark.png
Normal file
After Width: | Height: | Size: 115 KiB |
BIN
data/screenshots/welcome.png
Normal file
After Width: | Height: | Size: 118 KiB |
BIN
data/workbench.gif
Normal file
After Width: | Height: | Size: 400 KiB |
1
demos
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit cd8b209df99294c72a5846ead00797db0bafa862
|
32
docs/design-goals.md
Normal file
@ -0,0 +1,32 @@
|
||||
# Previewer
|
||||
|
||||
Any valid GTK XML or Blueprint `UI` should be able to render in `Preview`.
|
||||
|
||||
At least when it comes to the internal/in-process previwer, the preview should be as helpful as possible. Missing signal handlers or objects shouldn't prevent the preview from updating.
|
||||
|
||||
Triggering signal handlers should log a helpful message.
|
||||
|
||||
Missing objects should present a helpful message.
|
||||
|
||||
Out of process preview/code can crash but not take Workbench down with it.
|
||||
|
||||
# Resilience
|
||||
|
||||
Workbench itself should not crash under any circumstances.
|
||||
|
||||
# Clarity
|
||||
|
||||
When changing the parameters - Workbench should reset to a clean slate
|
||||
|
||||
Changing the parameters includes
|
||||
|
||||
- Changing Code language
|
||||
- Changing UI language
|
||||
- Opening a file
|
||||
- Opening a demo
|
||||
|
||||
Resetting to a clean slate involves
|
||||
|
||||
- re-rend the preview to what CSS/UI dictates
|
||||
- clear the console
|
||||
- scroll console to end
|
27
docs/maintenance.md
Normal file
@ -0,0 +1,27 @@
|
||||
## Maintenance
|
||||
|
||||
Notes and instructions for maintainers.
|
||||
|
||||
## Release
|
||||
|
||||
```sh
|
||||
$V = 45
|
||||
|
||||
git checkout l10n
|
||||
git pull
|
||||
git checkout main
|
||||
git merge --squash l10n
|
||||
meson compile re.sonny.Workbench-pot -C _build
|
||||
meson compile re.sonny.Workbench-update-po -C _build
|
||||
git commit -m 'Update translations'
|
||||
|
||||
# Update version
|
||||
# bump version in meson.build
|
||||
# add release notes to metainfo
|
||||
git add meson.build
|
||||
|
||||
git commit -m '$V'
|
||||
git tag '$V'
|
||||
git push
|
||||
git push origin $V
|
||||
```
|
1
gi-types
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 396fe147142e28a921f0745eff1a562c7a551843
|
41
meson.build
@ -1,24 +1,41 @@
|
||||
project('re.sonny.Workbench',
|
||||
version: '1.1.0',
|
||||
meson_version: '>= 0.59.0',
|
||||
license: 'GPL-3.0-only'
|
||||
project(
|
||||
'Workbench',
|
||||
['vala', 'c', 'rust'],
|
||||
version: '48.0',
|
||||
meson_version: '>= 1.0.0',
|
||||
license: 'GPL-3.0-only',
|
||||
default_options: [
|
||||
'libdir=lib',
|
||||
'warning_level=2',
|
||||
'werror=false',
|
||||
],
|
||||
)
|
||||
|
||||
gnome = import('gnome')
|
||||
i18n = import('i18n')
|
||||
|
||||
application_id = meson.project_name()
|
||||
if get_option('profile') == 'development'
|
||||
app_id = 're.sonny.Workbench.Devel'
|
||||
vcs_tag = run_command('git', 'rev-parse', '--short', 'HEAD').stdout().strip()
|
||||
if vcs_tag == ''
|
||||
version_suffix = '-devel'
|
||||
else
|
||||
version_suffix = '-@0@'.format(vcs_tag)
|
||||
endif
|
||||
else
|
||||
app_id = 're.sonny.Workbench'
|
||||
version_suffix = ''
|
||||
endif
|
||||
|
||||
prefix = get_option('prefix')
|
||||
bindir = join_paths(prefix, 'bin')
|
||||
datadir = join_paths(prefix, get_option('datadir'))
|
||||
pkgdatadir = join_paths(datadir, application_id)
|
||||
bindir = prefix / 'bin'
|
||||
datadir = prefix / get_option('datadir')
|
||||
pkgdatadir = datadir / app_id
|
||||
|
||||
subdir('data')
|
||||
subdir('src')
|
||||
subdir('po')
|
||||
|
||||
gnome.post_install(
|
||||
glib_compile_schemas: true,
|
||||
gtk_update_icon_cache: true,
|
||||
update_desktop_database: true
|
||||
)
|
||||
update_desktop_database: true,
|
||||
)
|
9
meson_options.txt
Normal file
@ -0,0 +1,9 @@
|
||||
option(
|
||||
'profile',
|
||||
type: 'combo',
|
||||
choices: [
|
||||
'default',
|
||||
'development'
|
||||
],
|
||||
value: 'default'
|
||||
)
|
5691
package-lock.json
generated
39
package.json
@ -1,23 +1,36 @@
|
||||
{
|
||||
"private": true,
|
||||
"devDependencies": {
|
||||
"@prettier/plugin-xml": "^1.2.0",
|
||||
"@rollup/plugin-commonjs": "^21.0.1",
|
||||
"@rollup/plugin-json": "^4.1.0",
|
||||
"@rollup/plugin-node-resolve": "^13.1.3",
|
||||
"eslint": "^8.8.0",
|
||||
"eslint-plugin-import": "^2.25.4",
|
||||
"@babel/core": "^7.25.7",
|
||||
"@babel/eslint-parser": "^7.25.7",
|
||||
"@babel/plugin-syntax-import-attributes": "^7.25.7",
|
||||
"@rollup/plugin-commonjs": "^22.0.1",
|
||||
"@rollup/plugin-node-resolve": "^13.3.0",
|
||||
"eslint": "^8.48.0",
|
||||
"eslint-config-prettier": "^9.0.0",
|
||||
"eslint-plugin-import": "^2.28.1",
|
||||
"eslint-plugin-prettier": "^5.0.0",
|
||||
"events": "^3.3.0",
|
||||
"ltx": "^3.0.0",
|
||||
"postcss": "^8.4.6",
|
||||
"prettier": "^2.5.1",
|
||||
"rollup": "^2.67.0",
|
||||
"husky": "^8.0.3",
|
||||
"lint-staged": "^14.0.1",
|
||||
"ltx": "git://github.com/xmppjs/ltx.git#072690a43a51254ddd17b082131a8b9115586e8a",
|
||||
"postcss": "^8.4.14",
|
||||
"prettier": "3.0.3",
|
||||
"rollup": "^2.76.0",
|
||||
"rollup-plugin-ignore": "^1.0.10",
|
||||
"rollup-plugin-node-polyfills": "^0.2.1",
|
||||
"uvu": "^0.5.3"
|
||||
"rollup-plugin-node-polyfills": "^0.2.1"
|
||||
},
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"postinstall": "rollup -c rollup.config.js"
|
||||
"prepare": "husky install"
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.{json,md,yaml,yml}": "prettier --write",
|
||||
"*.{js,cjs,mjs}": "eslint --fix",
|
||||
"*.css": "./build-aux/fun workbench-cli format css",
|
||||
"*.py": "./build-aux/fun workbench-cli format python",
|
||||
"*.rs": "./build-aux/fun rustfmt --edition 2021",
|
||||
"*.blp": "./build-aux/fun workbench-cli format blueprint",
|
||||
"*.vala": "./build-aux/fun workbench-cli format vala"
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +0,0 @@
|
||||
data/re.sonny.Workbench.desktop
|
||||
data/re.sonny.Workbench.gschema.xml
|
||||
data/re.sonny.Workbench.metainfo.xml
|
||||
src/about.js
|
||||
src/shortcutsWindow.ui
|
||||
src/window.js
|
||||
src/window.ui
|
@ -1 +0,0 @@
|
||||
i18n.gettext(application_id, preset: 'glib', args: ['--no-wrap'])
|
@ -1,218 +0,0 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the re.sonny.Workbench package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: re.sonny.Workbench\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2022-03-02 21:32+0100\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"Language: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#. TRANSLATORS: Don't translate
|
||||
#: data/re.sonny.Workbench.desktop:4
|
||||
msgid "Workbench"
|
||||
msgstr ""
|
||||
|
||||
#: data/re.sonny.Workbench.desktop:5 data/re.sonny.Workbench.metainfo.xml:10
|
||||
#: src/about.js:9
|
||||
msgid "Sandbox to learn and prototype with GNOME technologies"
|
||||
msgstr ""
|
||||
|
||||
#. TRANSLATORS: Don't translate
|
||||
#: data/re.sonny.Workbench.desktop:12
|
||||
msgid "CSS;JavaScript;GJS;"
|
||||
msgstr ""
|
||||
|
||||
#: data/re.sonny.Workbench.metainfo.xml:14
|
||||
msgid "Workbench goal is to let you experiment with GNOME technologies, no matter if it's tinkering for the first time or building and testing a custom GTK widget."
|
||||
msgstr ""
|
||||
|
||||
#: data/re.sonny.Workbench.metainfo.xml:15
|
||||
msgid "Among other things, Workbench comes with"
|
||||
msgstr ""
|
||||
|
||||
#: data/re.sonny.Workbench.metainfo.xml:17
|
||||
msgid "realtime GTK/CSS preview"
|
||||
msgstr ""
|
||||
|
||||
#: data/re.sonny.Workbench.metainfo.xml:18
|
||||
msgid "[JavaScript](https://gjs.guide/) for quick and easy scripting"
|
||||
msgstr ""
|
||||
|
||||
#: data/re.sonny.Workbench.metainfo.xml:19
|
||||
msgid "Syntax highlighting, undo/redo, autosave"
|
||||
msgstr ""
|
||||
|
||||
#: data/re.sonny.Workbench.metainfo.xml:20
|
||||
msgid "code fomatter"
|
||||
msgstr ""
|
||||
|
||||
#: data/re.sonny.Workbench.metainfo.xml:21
|
||||
msgid "terminal"
|
||||
msgstr ""
|
||||
|
||||
#. TRANSLATORS: eg. 'Translator Name <your.email@domain.com>' or 'Translator Name https://website.example'
|
||||
#: src/about.js:18
|
||||
msgid "translator-credits"
|
||||
msgstr ""
|
||||
|
||||
#: src/shortcutsWindow.ui:12 src/window.ui:19
|
||||
msgid "Run"
|
||||
msgstr ""
|
||||
|
||||
#: src/shortcutsWindow.ui:20 src/window.ui:363
|
||||
msgid "Inspector"
|
||||
msgstr ""
|
||||
|
||||
#: src/shortcutsWindow.ui:31
|
||||
msgid "Open Console"
|
||||
msgstr ""
|
||||
|
||||
#: src/shortcutsWindow.ui:40
|
||||
msgid "Clear Console"
|
||||
msgstr ""
|
||||
|
||||
#: src/shortcutsWindow.ui:49 src/window.ui:405
|
||||
msgid "Keyboard Shortcuts"
|
||||
msgstr ""
|
||||
|
||||
#: src/shortcutsWindow.ui:55
|
||||
msgid "Quit"
|
||||
msgstr ""
|
||||
|
||||
#: src/window.js:380
|
||||
msgid "Are you sure you want to discard your changes?"
|
||||
msgstr ""
|
||||
|
||||
#: src/window.ui:26 src/window.ui:31
|
||||
msgid "Run (Ctrl+⏎)"
|
||||
msgstr ""
|
||||
|
||||
#: src/window.ui:58
|
||||
msgid "Code"
|
||||
msgstr ""
|
||||
|
||||
#: src/window.ui:84
|
||||
msgid "Style"
|
||||
msgstr ""
|
||||
|
||||
#: src/window.ui:110
|
||||
msgid "UI"
|
||||
msgstr ""
|
||||
|
||||
#: src/window.ui:138
|
||||
msgid "Preview"
|
||||
msgstr ""
|
||||
|
||||
#: src/window.ui:163 src/window.ui:168
|
||||
msgid "Switch between light and dark mode"
|
||||
msgstr ""
|
||||
|
||||
#: src/window.ui:179 src/window.ui:181
|
||||
msgid "Bookmarks"
|
||||
msgstr ""
|
||||
|
||||
#: src/window.ui:205
|
||||
msgid "Code - JavaScript"
|
||||
msgstr ""
|
||||
|
||||
#: src/window.ui:254
|
||||
msgid "Style - CSS"
|
||||
msgstr ""
|
||||
|
||||
#: src/window.ui:303
|
||||
msgid "UI - XML"
|
||||
msgstr ""
|
||||
|
||||
#: src/window.ui:354
|
||||
msgid "Console"
|
||||
msgstr ""
|
||||
|
||||
#: src/window.ui:358
|
||||
msgid "Show logs (Ctrl+Shift+K)"
|
||||
msgstr ""
|
||||
|
||||
#: src/window.ui:367
|
||||
msgid "Open GTK Inspector (Ctrl+Shift+I)"
|
||||
msgstr ""
|
||||
|
||||
#: src/window.ui:372
|
||||
msgid "Clear"
|
||||
msgstr ""
|
||||
|
||||
#: src/window.ui:393
|
||||
msgid "Open File…"
|
||||
msgstr ""
|
||||
|
||||
#: src/window.ui:397
|
||||
msgid "Reset to demo"
|
||||
msgstr ""
|
||||
|
||||
#: src/window.ui:409
|
||||
msgid "About Workbench"
|
||||
msgstr ""
|
||||
|
||||
#: src/window.ui:430
|
||||
msgid "Learn"
|
||||
msgstr ""
|
||||
|
||||
#: src/window.ui:435
|
||||
msgid "GNOME JavaScript (GJS)"
|
||||
msgstr ""
|
||||
|
||||
#: src/window.ui:443
|
||||
msgid "Human Interface Guidelines (HIG)"
|
||||
msgstr ""
|
||||
|
||||
#: src/window.ui:448
|
||||
msgid "UI components"
|
||||
msgstr ""
|
||||
|
||||
#: src/window.ui:458
|
||||
msgid "Platform components"
|
||||
msgstr ""
|
||||
|
||||
#: src/window.ui:466
|
||||
msgid "Reference"
|
||||
msgstr ""
|
||||
|
||||
#: src/window.ui:468
|
||||
msgid "JavaScript"
|
||||
msgstr ""
|
||||
|
||||
#: src/window.ui:475
|
||||
msgid "GJS"
|
||||
msgstr ""
|
||||
|
||||
#: src/window.ui:480
|
||||
msgid "Gtk"
|
||||
msgstr ""
|
||||
|
||||
#: src/window.ui:485
|
||||
msgid "Adwaita"
|
||||
msgstr ""
|
||||
|
||||
#: src/window.ui:493
|
||||
msgid "Get help"
|
||||
msgstr ""
|
||||
|
||||
#: src/window.ui:495
|
||||
msgid "Discourse"
|
||||
msgstr ""
|
||||
|
||||
#: src/window.ui:502
|
||||
msgid "Stack Overflow"
|
||||
msgstr ""
|
||||
|
||||
#: src/window.ui:509
|
||||
msgid "Matrix"
|
||||
msgstr ""
|
@ -1,73 +0,0 @@
|
||||
{
|
||||
"app-id": "re.sonny.Workbench",
|
||||
"runtime": "org.gnome.Platform",
|
||||
"runtime-version": "42",
|
||||
"sdk": "org.gnome.Sdk",
|
||||
"sdk-extensions": ["org.freedesktop.Sdk.Extension.node16"],
|
||||
"command": "workbench",
|
||||
"build-options": {
|
||||
"append-path": "/usr/lib/sdk/node16/bin"
|
||||
},
|
||||
"finish-args": [
|
||||
"--share=ipc",
|
||||
"--socket=fallback-x11",
|
||||
"--socket=wayland",
|
||||
"--device=dri"
|
||||
],
|
||||
"x-run-args": [],
|
||||
"modules": [
|
||||
{
|
||||
"name": "vte",
|
||||
"buildsystem": "meson",
|
||||
"config-opts": [
|
||||
"-Ddocs=false",
|
||||
"-Dgtk3=false",
|
||||
"-Dgtk4=true",
|
||||
"-Dvapi=false",
|
||||
"-Dglade=false"
|
||||
],
|
||||
"sources": [
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://gitlab.gnome.org/GNOME/vte.git",
|
||||
"commit": "f4b915aea367d407f8ac527e1aed9425b8cea9e2"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "gtksourceview",
|
||||
"buildsystem": "meson",
|
||||
"config-opts": ["-Dtests=false", "-Dexamples=false", "-Dvapi=false"],
|
||||
"sources": [
|
||||
{
|
||||
"type": "archive",
|
||||
"url": "https://download.gnome.org/sources/gtksourceview/5.3/gtksourceview-5.3.2.tar.xz",
|
||||
"sha256": "af7736e2ee3cdbc1013090e8caf35fb89d65cf41c9c399cac5d8992d955ded30"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "libportal",
|
||||
"buildsystem": "meson",
|
||||
"config-opts": ["-Ddocs=false", "-Dvapi=false", "-Dbackends=gtk4"],
|
||||
"sources": [
|
||||
{
|
||||
"type": "archive",
|
||||
"url": "https://github.com/flatpak/libportal/releases/download/0.5/libportal-0.5.tar.xz",
|
||||
"sha256": "d8c8cb18a34e5eeb26a39c94044c955995b01de0e139caac5e18c076cf821b3b"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Workbench",
|
||||
"buildsystem": "meson",
|
||||
"builddir": true,
|
||||
"sources": [
|
||||
{
|
||||
"type": "dir",
|
||||
"path": "."
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
@ -1,68 +0,0 @@
|
||||
import { nodeResolve } from "@rollup/plugin-node-resolve";
|
||||
import commonjs from '@rollup/plugin-commonjs';
|
||||
import ignore from "rollup-plugin-ignore"
|
||||
import nodePolyfills from 'rollup-plugin-node-polyfills';
|
||||
import json from '@rollup/plugin-json';
|
||||
|
||||
export default [
|
||||
{
|
||||
input: "node_modules/uvu/dist/index.mjs",
|
||||
output: {
|
||||
file: "test/uvu.js",
|
||||
},
|
||||
plugins: [nodeResolve()],
|
||||
},
|
||||
|
||||
{
|
||||
input: "node_modules/uvu/assert/index.mjs",
|
||||
output: {
|
||||
file: "test/assert.js",
|
||||
},
|
||||
plugins: [nodeResolve()],
|
||||
},
|
||||
|
||||
{
|
||||
input: "node_modules/ltx/src/ltx.js",
|
||||
output: {
|
||||
file: "src/lib/ltx.js",
|
||||
},
|
||||
plugins: [nodePolyfills()]
|
||||
},
|
||||
|
||||
{
|
||||
input: "node_modules/prettier/esm/standalone.mjs",
|
||||
output: {
|
||||
file: "src/lib/prettier.js",
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
input: "node_modules/prettier/esm/parser-babel.mjs",
|
||||
output: {
|
||||
file: "src/lib/prettier-babel.js",
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
input: "node_modules/prettier/esm/parser-postcss.mjs",
|
||||
output: {
|
||||
file: "src/lib/prettier-postcss.js",
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
input: "node_modules/@prettier/plugin-xml/dist/plugin.js",
|
||||
output: {
|
||||
file: "src/lib/prettier-xml.js",
|
||||
},
|
||||
plugins: [commonjs(), json(), ignore(["fs"]), nodeResolve({browser: true})]
|
||||
},
|
||||
|
||||
{
|
||||
input: "node_modules/postcss/lib/postcss.mjs",
|
||||
output: {
|
||||
file: "src/lib/postcss.js",
|
||||
},
|
||||
plugins: [commonjs(), ignore(["picocolors", "source-map-js", "path", "fs", "url"]), nodeResolve({resolveOnly: ['nanoid']})]
|
||||
},
|
||||
];
|
96
src/Devtools.js
Normal file
@ -0,0 +1,96 @@
|
||||
import Gio from "gi://Gio";
|
||||
|
||||
import TermConsole from "./TermConsole.js";
|
||||
|
||||
export default function Devtools({ application, window, builder, settings }) {
|
||||
const button_console = builder.get_object("button_console");
|
||||
const terminal = builder.get_object("terminal");
|
||||
const paned = builder.get_object("paned");
|
||||
const toolbar_devtools = builder.get_object("toolbar_devtools");
|
||||
const devtools = builder.get_object("devtools");
|
||||
|
||||
// For some reasons those don't work
|
||||
// as builder properties
|
||||
paned.set_shrink_start_child(false);
|
||||
paned.set_shrink_end_child(true);
|
||||
paned.set_resize_start_child(true);
|
||||
paned.set_resize_end_child(true);
|
||||
paned.get_start_child().set_size_request(-1, 200);
|
||||
|
||||
settings.bind(
|
||||
"show-console",
|
||||
button_console,
|
||||
"active",
|
||||
Gio.SettingsBindFlags.DEFAULT,
|
||||
);
|
||||
|
||||
let position;
|
||||
|
||||
function uncollapse() {
|
||||
terminal.visible = true;
|
||||
settings.set_boolean("show-console", true);
|
||||
}
|
||||
|
||||
function collapse() {
|
||||
const { height: toolbar_height } = toolbar_devtools.get_allocation();
|
||||
const { height: paned_height } = paned.get_allocation();
|
||||
|
||||
terminal.visible = false;
|
||||
settings.set_boolean("show-console", false);
|
||||
paned.position = paned_height - toolbar_height;
|
||||
}
|
||||
|
||||
function isCollapsed() {
|
||||
const { height: paned_height } = paned.get_allocation();
|
||||
const { height: toolbar_height } = toolbar_devtools.get_allocation();
|
||||
return paned_height <= paned.position + toolbar_height;
|
||||
}
|
||||
|
||||
paned.connect_after("notify::position", () => {
|
||||
const { height: toolbar_height } = toolbar_devtools.get_allocation();
|
||||
const { height: paned_height } = paned.get_allocation();
|
||||
|
||||
if (paned.position + toolbar_height > paned_height - 50) {
|
||||
collapse();
|
||||
} else {
|
||||
uncollapse();
|
||||
}
|
||||
});
|
||||
|
||||
function setupPaned() {
|
||||
const { height: paned_height } = paned.get_allocation();
|
||||
const { height: toolbar_height } = toolbar_devtools.get_allocation();
|
||||
|
||||
if (button_console.active) {
|
||||
terminal.visible = true;
|
||||
if (isCollapsed()) {
|
||||
devtools.set_size_request(-1, 200);
|
||||
paned.position =
|
||||
position >= paned_height - toolbar_height - 50
|
||||
? paned_height - 200
|
||||
: position;
|
||||
}
|
||||
} else {
|
||||
position = paned.position;
|
||||
const { height: toolbar_height } = toolbar_devtools.get_allocation();
|
||||
paned.position = paned_height - toolbar_height;
|
||||
terminal.visible = false;
|
||||
devtools.set_size_request(-1, toolbar_height);
|
||||
}
|
||||
}
|
||||
button_console.connect_after("notify::active", setupPaned);
|
||||
|
||||
const action_console = new Gio.SimpleAction({
|
||||
name: "console",
|
||||
parameter_type: null,
|
||||
});
|
||||
action_console.connect("activate", () => {
|
||||
settings.set_boolean("show-console", !settings.get_boolean("show-console"));
|
||||
});
|
||||
window.add_action(action_console);
|
||||
application.set_accels_for_action("win.console", ["<Control><Shift>K"]);
|
||||
|
||||
return {
|
||||
term_console: TermConsole({ builder, window, application, settings }),
|
||||
};
|
||||
}
|
145
src/Document.js
@ -1,76 +1,89 @@
|
||||
import Source from "gi://GtkSource?version=5";
|
||||
import Source from "gi://GtkSource";
|
||||
import Gio from "gi://Gio";
|
||||
import GLib from "gi://GLib";
|
||||
|
||||
const language_manager = Source.LanguageManager.get_default();
|
||||
export default class Document {
|
||||
handler_id = null;
|
||||
|
||||
export default function Document({
|
||||
data_dir,
|
||||
source_view,
|
||||
lang,
|
||||
placeholder,
|
||||
ext,
|
||||
}) {
|
||||
const { buffer } = source_view;
|
||||
constructor({ session, code_view, lang }) {
|
||||
this.code_view = code_view;
|
||||
this.buffer = code_view.buffer;
|
||||
this.session = session;
|
||||
this.source_view = code_view.source_view;
|
||||
|
||||
buffer.set_language(language_manager.get_language(lang));
|
||||
const file = session.file.get_child(lang.default_file);
|
||||
this.file = file;
|
||||
this.source_file = new Source.File({
|
||||
location: file,
|
||||
});
|
||||
|
||||
const file = Gio.File.new_for_path(
|
||||
GLib.build_filenamev([data_dir, `state.${ext}`])
|
||||
this.start();
|
||||
}
|
||||
|
||||
save() {
|
||||
const { source_file, buffer, session } = this;
|
||||
saveSourceBuffer({ source_file, buffer })
|
||||
.catch(console.error)
|
||||
.finally(() => {
|
||||
try {
|
||||
session.settings.set_boolean("edited", true);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
start() {
|
||||
this.stop();
|
||||
this.handler_id = this.buffer.connect("modified-changed", () => {
|
||||
if (!this.buffer.get_modified()) return;
|
||||
this.save();
|
||||
});
|
||||
}
|
||||
|
||||
stop() {
|
||||
if (this.handler_id !== null) {
|
||||
this.buffer.disconnect(this.handler_id);
|
||||
this.handler_id = null;
|
||||
}
|
||||
}
|
||||
|
||||
load() {
|
||||
const { source_file, buffer } = this;
|
||||
return loadSourceBuffer({ source_file, buffer });
|
||||
}
|
||||
|
||||
format() {}
|
||||
}
|
||||
|
||||
async function saveSourceBuffer({ source_file, buffer }) {
|
||||
const file_saver = new Source.FileSaver({
|
||||
buffer,
|
||||
file: source_file,
|
||||
});
|
||||
const success = await file_saver.save_async(
|
||||
GLib.PRIORITY_DEFAULT,
|
||||
null,
|
||||
null,
|
||||
);
|
||||
|
||||
const source_file = new Source.File({
|
||||
location: file,
|
||||
});
|
||||
|
||||
load();
|
||||
|
||||
buffer.connect("modified-changed", () => {
|
||||
const modified = buffer.get_modified();
|
||||
if (!modified) return;
|
||||
save();
|
||||
});
|
||||
|
||||
function load() {
|
||||
const file_loader = new Source.FileLoader({
|
||||
buffer,
|
||||
file: source_file,
|
||||
});
|
||||
file_loader.load_async(
|
||||
GLib.PRIORITY_DEFAULT,
|
||||
null,
|
||||
null,
|
||||
(self, result) => {
|
||||
let success;
|
||||
try {
|
||||
success = file_loader.load_finish(result);
|
||||
} catch (err) {
|
||||
if (err.code !== Gio.IOErrorEnum.NOT_FOUND) {
|
||||
logError(err);
|
||||
}
|
||||
}
|
||||
if (success) buffer.set_modified(false);
|
||||
if (!success) reset();
|
||||
}
|
||||
);
|
||||
if (success) {
|
||||
buffer.set_modified(false);
|
||||
}
|
||||
|
||||
function save() {
|
||||
const file_saver = new Source.FileSaver({
|
||||
buffer,
|
||||
file: source_file,
|
||||
});
|
||||
file_saver.save_async(GLib.PRIORITY_DEFAULT, null, null, (self, result) => {
|
||||
const success = file_saver.save_finish(result);
|
||||
if (success) buffer.set_modified(false);
|
||||
});
|
||||
}
|
||||
|
||||
function reset() {
|
||||
const decoder = new TextDecoder("utf-8");
|
||||
const text = decoder.decode(placeholder.get_data());
|
||||
buffer.set_text(text, -1);
|
||||
}
|
||||
|
||||
return { reset, source_view };
|
||||
}
|
||||
|
||||
async function loadSourceBuffer({ source_file, buffer }) {
|
||||
const file_loader = new Source.FileLoader({
|
||||
buffer,
|
||||
file: source_file,
|
||||
});
|
||||
try {
|
||||
await file_loader.load_async(GLib.PRIORITY_DEFAULT, null, null);
|
||||
} catch (err) {
|
||||
if (!err.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.NOT_FOUND)) {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
buffer.set_modified(false);
|
||||
}
|
||||
|
60
src/Extensions/Extension.blp
Normal file
@ -0,0 +1,60 @@
|
||||
using Gtk 4.0;
|
||||
|
||||
template $Extension: ListBoxRow {
|
||||
activatable: false;
|
||||
|
||||
Box {
|
||||
orientation: vertical;
|
||||
|
||||
CenterBox {
|
||||
height-request: 55;
|
||||
valign: center;
|
||||
halign: fill;
|
||||
margin-start: 14;
|
||||
margin-end: 14;
|
||||
|
||||
[start]
|
||||
Label label_title {}
|
||||
|
||||
[end]
|
||||
Image image_available {
|
||||
icon-name: "re.sonny.Workbench-test-pass-symbolic";
|
||||
|
||||
styles [
|
||||
"success",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
Box installation_guide {
|
||||
visible: false;
|
||||
margin-start: 14;
|
||||
margin-end: 14;
|
||||
margin-bottom: 14;
|
||||
orientation: vertical;
|
||||
|
||||
Label {
|
||||
wrap: true;
|
||||
xalign: 0;
|
||||
label: _("Run the following command");
|
||||
|
||||
styles [
|
||||
"dim-label",
|
||||
]
|
||||
}
|
||||
|
||||
Label label_command {
|
||||
margin-top: 12;
|
||||
use-markup: true;
|
||||
wrap: true;
|
||||
wrap-mode: word_char;
|
||||
selectable: true;
|
||||
xalign: 0;
|
||||
|
||||
styles [
|
||||
"command_snippet",
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
73
src/Extensions/Extension.js
Normal file
@ -0,0 +1,73 @@
|
||||
import GObject from "gi://GObject";
|
||||
import Gtk from "gi://Gtk";
|
||||
|
||||
import Template from "./Extension.blp" with { type: "uri" };
|
||||
|
||||
export default GObject.registerClass(
|
||||
{
|
||||
GTypeName: "Extension",
|
||||
Template,
|
||||
InternalChildren: [
|
||||
"label_title",
|
||||
"image_available",
|
||||
"installation_guide",
|
||||
"label_command",
|
||||
],
|
||||
Properties: {
|
||||
title: GObject.ParamSpec.string(
|
||||
"title",
|
||||
"",
|
||||
"",
|
||||
GObject.ParamFlags.READWRITE,
|
||||
"",
|
||||
),
|
||||
available: GObject.ParamSpec.boolean(
|
||||
"available",
|
||||
"",
|
||||
"",
|
||||
GObject.ParamFlags.READWRITE,
|
||||
false,
|
||||
),
|
||||
command: GObject.ParamSpec.string(
|
||||
"command",
|
||||
"",
|
||||
"",
|
||||
GObject.ParamFlags.READWRITE,
|
||||
"",
|
||||
),
|
||||
},
|
||||
},
|
||||
class Extension extends Gtk.ListBoxRow {
|
||||
constructor(properties = {}) {
|
||||
super(properties);
|
||||
|
||||
this.bind_property(
|
||||
"title",
|
||||
this._label_title,
|
||||
"label",
|
||||
GObject.BindingFlags.SYNC_CREATE,
|
||||
);
|
||||
|
||||
this.bind_property(
|
||||
"available",
|
||||
this._image_available,
|
||||
"visible",
|
||||
GObject.BindingFlags.SYNC_CREATE,
|
||||
);
|
||||
|
||||
this.bind_property(
|
||||
"available",
|
||||
this._installation_guide,
|
||||
"visible",
|
||||
GObject.BindingFlags.SYNC_CREATE | GObject.BindingFlags.INVERT_BOOLEAN,
|
||||
);
|
||||
|
||||
this.bind_property(
|
||||
"command",
|
||||
this._label_command,
|
||||
"label",
|
||||
GObject.BindingFlags.SYNC_CREATE,
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
93
src/Extensions/Extensions.blp
Normal file
@ -0,0 +1,93 @@
|
||||
using Gtk 4.0;
|
||||
using Adw 1;
|
||||
|
||||
Adw.Dialog dialog {
|
||||
content-height: 750;
|
||||
content-width: 600;
|
||||
title: _("Extensions");
|
||||
|
||||
Adw.ToolbarView {
|
||||
[top]
|
||||
Adw.HeaderBar {}
|
||||
|
||||
content: ScrolledWindow {
|
||||
hscrollbar-policy: never;
|
||||
|
||||
Adw.Clamp {
|
||||
maximum-size: 600;
|
||||
tightening-threshold: 400;
|
||||
margin-start: 14;
|
||||
margin-end: 14;
|
||||
margin-top: 30;
|
||||
margin-bottom: 30;
|
||||
|
||||
Box {
|
||||
orientation: vertical;
|
||||
halign: fill;
|
||||
// Gtk.Picture needs to be wrapped in a box to behave properly
|
||||
Box {
|
||||
halign: center;
|
||||
|
||||
Picture picture_illustration {
|
||||
can-shrink: false;
|
||||
margin-bottom: 30;
|
||||
}
|
||||
}
|
||||
|
||||
ListBox {
|
||||
selection-mode: none;
|
||||
|
||||
styles [
|
||||
"boxed-list",
|
||||
]
|
||||
|
||||
$Extension {
|
||||
title: _("JavaScript");
|
||||
available: true;
|
||||
}
|
||||
|
||||
$Extension {
|
||||
title: _("Python");
|
||||
available: true;
|
||||
}
|
||||
|
||||
$Extension extension_rust {
|
||||
title: _("Rust");
|
||||
}
|
||||
|
||||
$Extension extension_vala {
|
||||
title: _("Vala");
|
||||
}
|
||||
|
||||
$Extension extension_typescript {
|
||||
title: _("TypeScript");
|
||||
}
|
||||
}
|
||||
|
||||
Label restart_hint {
|
||||
label: "To apply changes, restart Workbench once\nthe commands have completed";
|
||||
visible: false;
|
||||
margin-top: 30;
|
||||
justify: center;
|
||||
wrap: true;
|
||||
|
||||
styles [
|
||||
"dim-label",
|
||||
]
|
||||
}
|
||||
|
||||
Label all_set_hint {
|
||||
label: "You’re all set!";
|
||||
margin-top: 30;
|
||||
justify: center;
|
||||
wrap: true;
|
||||
|
||||
styles [
|
||||
"dim-label",
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
89
src/Extensions/Extensions.js
Normal file
@ -0,0 +1,89 @@
|
||||
import Gio from "gi://Gio";
|
||||
|
||||
import { build } from "../../troll/src/main.js";
|
||||
|
||||
import Interface from "./Extensions.blp" with { type: "uri" };
|
||||
import illustration from "./extensions.svg";
|
||||
|
||||
import "./Extension.js";
|
||||
import { settings } from "../util.js";
|
||||
import { getFlatpakInfo } from "../flatpak.js";
|
||||
|
||||
export const action_extensions = new Gio.SimpleAction({
|
||||
name: "extensions",
|
||||
parameter_type: null,
|
||||
});
|
||||
|
||||
export function Extensions({ window }) {
|
||||
const {
|
||||
dialog,
|
||||
picture_illustration,
|
||||
extension_rust,
|
||||
extension_vala,
|
||||
extension_typescript,
|
||||
restart_hint,
|
||||
all_set_hint,
|
||||
} = build(Interface);
|
||||
|
||||
picture_illustration.set_resource(illustration);
|
||||
|
||||
extension_rust.available = isRustAvailable();
|
||||
extension_rust.command = `flatpak install flathub org.freedesktop.Sdk.Extension.rust-stable//${freedesktop_version} org.freedesktop.Sdk.Extension.${llvm}//${freedesktop_version}`;
|
||||
|
||||
extension_vala.available = isValaAvailable();
|
||||
extension_vala.command = `flatpak install flathub org.freedesktop.Sdk.Extension.vala//${freedesktop_version}`;
|
||||
|
||||
extension_typescript.available = isTypeScriptAvailable();
|
||||
extension_typescript.command = `flatpak install flathub org.freedesktop.Sdk.Extension.${node}//${freedesktop_version} org.freedesktop.Sdk.Extension.typescript//${freedesktop_version}`;
|
||||
extension_typescript.visible = isTypeScriptEnabled();
|
||||
|
||||
for (const extension of [
|
||||
extension_rust,
|
||||
extension_vala,
|
||||
extension_typescript,
|
||||
]) {
|
||||
if (!extension.available) {
|
||||
all_set_hint.set_visible(false);
|
||||
restart_hint.set_visible(true);
|
||||
}
|
||||
}
|
||||
|
||||
action_extensions.connect("activate", () => {
|
||||
dialog.present(window);
|
||||
});
|
||||
|
||||
window.add_action(action_extensions);
|
||||
}
|
||||
|
||||
let rust_available = null;
|
||||
export function isRustAvailable() {
|
||||
rust_available ??=
|
||||
Gio.File.new_for_path("/usr/lib/sdk/rust-stable").query_exists(null) &&
|
||||
Gio.File.new_for_path(`/usr/lib/sdk/${llvm}`).query_exists(null);
|
||||
return rust_available;
|
||||
}
|
||||
|
||||
let vala_available = null;
|
||||
export function isValaAvailable() {
|
||||
vala_available ??=
|
||||
Gio.File.new_for_path("/usr/lib/sdk/vala").query_exists(null);
|
||||
return vala_available;
|
||||
}
|
||||
|
||||
let typescript_available = null;
|
||||
export function isTypeScriptAvailable() {
|
||||
typescript_available ??=
|
||||
isTypeScriptEnabled() &&
|
||||
Gio.File.new_for_path("/usr/lib/sdk/typescript").query_exists(null) &&
|
||||
Gio.File.new_for_path(`/usr/lib/sdk/${node}`).query_exists(null);
|
||||
return typescript_available;
|
||||
}
|
||||
|
||||
const llvm = "llvm18";
|
||||
const node = "node20";
|
||||
const runtime = getFlatpakInfo().get_string("Application", "runtime");
|
||||
const freedesktop_version = runtime.endsWith("master") ? "24.08" : "24.08";
|
||||
|
||||
export function isTypeScriptEnabled() {
|
||||
return settings.get_boolean("typescript");
|
||||
}
|
1228
src/Extensions/extensions.svg
Normal file
After Width: | Height: | Size: 2.0 MiB |
55
src/Library/EntryRow.blp
Normal file
@ -0,0 +1,55 @@
|
||||
using Gtk 4.0;
|
||||
using Adw 1;
|
||||
|
||||
template $EntryRow: Adw.ActionRow {
|
||||
activatable: true;
|
||||
|
||||
accessibility {
|
||||
labelled-by: title_label;
|
||||
described-by: description_label;
|
||||
}
|
||||
|
||||
[prefix]
|
||||
Box contents {
|
||||
orientation: horizontal;
|
||||
|
||||
Box labels_box {
|
||||
margin-top: 6;
|
||||
margin-bottom: 6;
|
||||
spacing: 3;
|
||||
orientation: vertical;
|
||||
|
||||
Label title_label {
|
||||
xalign: 0;
|
||||
wrap: true;
|
||||
wrap-mode: word_char;
|
||||
}
|
||||
|
||||
Label description_label {
|
||||
styles [
|
||||
"dim-label",
|
||||
"caption",
|
||||
]
|
||||
|
||||
xalign: 0;
|
||||
wrap: true;
|
||||
wrap-mode: word_char;
|
||||
natural-wrap-mode: none;
|
||||
}
|
||||
|
||||
Box languages_box {
|
||||
orientation: horizontal;
|
||||
spacing: 3;
|
||||
margin-top: 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[suffix]
|
||||
Image {
|
||||
icon-name: "go-next-symbolic";
|
||||
margin-start: 6;
|
||||
hexpand: true;
|
||||
halign: end;
|
||||
}
|
||||
}
|
78
src/Library/EntryRow.js
Normal file
@ -0,0 +1,78 @@
|
||||
import Adw from "gi://Adw";
|
||||
import Gtk from "gi://Gtk";
|
||||
import Gio from "gi://Gio";
|
||||
import GObject from "gi://GObject";
|
||||
|
||||
import { getLanguage } from "../util.js";
|
||||
import Template from "./EntryRow.blp" with { type: "uri" };
|
||||
|
||||
class EntryRow extends Adw.ActionRow {
|
||||
constructor({ demo, ...params } = {}) {
|
||||
super(params);
|
||||
|
||||
this._title_label.label = demo.name;
|
||||
this._description_label.label = demo.description;
|
||||
|
||||
this.#createLanguageTags(demo);
|
||||
|
||||
const action_group = new Gio.SimpleActionGroup();
|
||||
const activate_action = new Gio.SimpleAction({
|
||||
name: "activate",
|
||||
parameter_type: null,
|
||||
});
|
||||
|
||||
activate_action.connect("activate", () => {
|
||||
this.emit("triggered", null);
|
||||
});
|
||||
action_group.add_action(activate_action);
|
||||
|
||||
this.insert_action_group("demo-row", action_group);
|
||||
this.action_name = "demo-row.activate";
|
||||
}
|
||||
|
||||
#createLanguageTags(demo) {
|
||||
demo.languages.forEach((id) => {
|
||||
const language = getLanguage(id);
|
||||
if (!language) return;
|
||||
const language_tag = this.#createLanguageTag(language);
|
||||
this._languages_box.append(language_tag);
|
||||
});
|
||||
}
|
||||
|
||||
#createLanguageTag(language) {
|
||||
const button = new Gtk.Button({
|
||||
label: language.name,
|
||||
valign: Gtk.Align.CENTER,
|
||||
css_classes: ["pill", "small"],
|
||||
});
|
||||
|
||||
button.connect("clicked", () => {
|
||||
this.emit("triggered", language);
|
||||
});
|
||||
|
||||
return button;
|
||||
}
|
||||
}
|
||||
|
||||
export default GObject.registerClass(
|
||||
{
|
||||
GTypeName: "EntryRow",
|
||||
Template,
|
||||
Properties: {
|
||||
demo: GObject.ParamSpec.jsobject(
|
||||
"demo",
|
||||
"",
|
||||
"",
|
||||
GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY,
|
||||
null,
|
||||
),
|
||||
},
|
||||
Signals: {
|
||||
triggered: {
|
||||
param_types: [GObject.TYPE_JSOBJECT],
|
||||
},
|
||||
},
|
||||
InternalChildren: ["title_label", "description_label", "languages_box"],
|
||||
},
|
||||
EntryRow,
|
||||
);
|
130
src/Library/Library.blp
Normal file
@ -0,0 +1,130 @@
|
||||
using Gtk 4.0;
|
||||
using Adw 1;
|
||||
|
||||
Adw.Window window {
|
||||
hide-on-close: true;
|
||||
modal: false;
|
||||
title: _("Workbench — Library");
|
||||
default-height: 700;
|
||||
default-width: 700;
|
||||
|
||||
Adw.ToolbarView toolbar_view {
|
||||
[top]
|
||||
Adw.HeaderBar header_bar {
|
||||
title-widget: Adw.WindowTitle {
|
||||
title: _("Workbench — Library");
|
||||
};
|
||||
}
|
||||
|
||||
content: ScrolledWindow scrolled_window {
|
||||
hscrollbar-policy: never;
|
||||
|
||||
child: Adw.Clamp {
|
||||
maximum-size: 576;
|
||||
margin-end: 12;
|
||||
margin-start: 12;
|
||||
|
||||
child: Box {
|
||||
orientation: vertical;
|
||||
spacing: 12;
|
||||
|
||||
Box {
|
||||
orientation: vertical;
|
||||
|
||||
Box {
|
||||
halign: center;
|
||||
vexpand: false;
|
||||
|
||||
Picture picture_illustration {
|
||||
can-shrink: false;
|
||||
margin-bottom: 32;
|
||||
margin-top: 24;
|
||||
}
|
||||
}
|
||||
|
||||
Label {
|
||||
label: _("Learn, Test, Remix");
|
||||
|
||||
styles [
|
||||
"title-1",
|
||||
]
|
||||
}
|
||||
|
||||
Box {
|
||||
spacing: 6;
|
||||
|
||||
SearchEntry search_entry {
|
||||
search-delay: 100;
|
||||
placeholder-text: _("Search demos");
|
||||
activates-default: true;
|
||||
hexpand: true;
|
||||
margin-top: 32;
|
||||
}
|
||||
|
||||
DropDown dropdown_language {
|
||||
valign: end;
|
||||
|
||||
model: Gtk.StringList {};
|
||||
}
|
||||
|
||||
DropDown dropdown_category {
|
||||
valign: end;
|
||||
|
||||
model: Gtk.StringList {};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ListBox listbox {
|
||||
selection-mode: none;
|
||||
|
||||
styles [
|
||||
"boxed-list",
|
||||
]
|
||||
}
|
||||
|
||||
Box {
|
||||
halign: center;
|
||||
margin-bottom: 24;
|
||||
margin-top: 12;
|
||||
orientation: vertical;
|
||||
|
||||
Box results_empty {
|
||||
orientation: vertical;
|
||||
visible: false;
|
||||
margin-top: 46;
|
||||
margin-bottom: 70;
|
||||
spacing: 6;
|
||||
|
||||
Label {
|
||||
label: _("No results");
|
||||
|
||||
styles [
|
||||
"title-3",
|
||||
]
|
||||
}
|
||||
|
||||
Button button_reset {
|
||||
label: _("Reset filters");
|
||||
halign: center;
|
||||
|
||||
styles [
|
||||
"pill",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
Label {
|
||||
label: _("All examples are dedicated to the public domain\nand <b>can be used freely</b> under the terms of <a href=\"https://creativecommons.org/publicdomain/zero/1.0/\">CC0 1.0</a>");
|
||||
use-markup: true;
|
||||
|
||||
styles [
|
||||
"caption",
|
||||
]
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
230
src/Library/Library.js
Normal file
@ -0,0 +1,230 @@
|
||||
import Gio from "gi://Gio";
|
||||
|
||||
import {
|
||||
decode,
|
||||
demos_dir,
|
||||
getLanguage,
|
||||
settings as global_settings,
|
||||
quitOnLastWindowClose,
|
||||
} from "../util.js";
|
||||
import Window from "../window.js";
|
||||
|
||||
import resource from "./Library.blp" with { type: "uri" };
|
||||
import { createSessionFromDemo } from "../sessions.js";
|
||||
import EntryRow from "./EntryRow.js";
|
||||
|
||||
import illustration from "./library.svg";
|
||||
import { gettext as _ } from "gettext";
|
||||
|
||||
import { build } from "../../troll/src/builder.js";
|
||||
import {
|
||||
needsAdditionalPermissions,
|
||||
showPermissionsDialog,
|
||||
} from "../Permissions/Permissions.js";
|
||||
import { isTypeScriptEnabled } from "../Extensions/Extensions.js";
|
||||
|
||||
export default function Library({ application }) {
|
||||
const objects = build(resource);
|
||||
const {
|
||||
window,
|
||||
picture_illustration,
|
||||
search_entry,
|
||||
dropdown_category,
|
||||
dropdown_language,
|
||||
results_empty,
|
||||
button_reset,
|
||||
listbox,
|
||||
scrolled_window,
|
||||
} = objects;
|
||||
window.application = application;
|
||||
picture_illustration.set_resource(illustration);
|
||||
|
||||
if (__DEV__) {
|
||||
window.add_css_class("devel");
|
||||
}
|
||||
|
||||
let last_triggered;
|
||||
|
||||
window.connect("close-request", quitOnLastWindowClose);
|
||||
|
||||
const categories = [
|
||||
{ id: "all", name: _("Any Category"), index: 0 },
|
||||
{ id: "tools", name: _("Tools"), index: 1 },
|
||||
{ id: "network", name: _("Network"), index: 2 },
|
||||
{ id: "controls", name: _("Controls"), index: 3 },
|
||||
{ id: "layout", name: _("Layout"), index: 4 },
|
||||
{ id: "feedback", name: _("Feedback"), index: 5 },
|
||||
{ id: "navigation", name: _("Navigation"), index: 6 },
|
||||
{ id: "user_interface", name: _("User Interface"), index: 7 },
|
||||
{ id: "platform", name: _("Platform APIs"), index: 8 },
|
||||
];
|
||||
const categories_by_id = Object.fromEntries(
|
||||
categories.map((category) => [category.id, category]),
|
||||
);
|
||||
const categories_by_index = Object.fromEntries(
|
||||
categories.map((category) => [category.index, category]),
|
||||
);
|
||||
const category_all = categories_by_id["all"];
|
||||
|
||||
categories.forEach((category) => {
|
||||
dropdown_category.model.append(category.name);
|
||||
});
|
||||
|
||||
const languages = [
|
||||
{ id: "all", name: _("Any Language"), index: 0 },
|
||||
{ id: "javascript", name: _("JavaScript"), index: 1 },
|
||||
{ id: "python", name: _("Python"), index: 2 },
|
||||
{ id: "rust", name: _("Rust"), index: 3 },
|
||||
{ id: "vala", name: _("Vala"), index: 4 },
|
||||
];
|
||||
if (isTypeScriptEnabled()) {
|
||||
languages.push({ id: "typescript", name: _("TypeScript"), index: 5 });
|
||||
}
|
||||
const languages_by_id = Object.fromEntries(
|
||||
languages.map((language) => [language.id, language]),
|
||||
);
|
||||
const languages_by_index = Object.fromEntries(
|
||||
languages.map((language) => [language.index, language]),
|
||||
);
|
||||
languages.forEach((language) => {
|
||||
dropdown_language.model.append(language.name);
|
||||
});
|
||||
|
||||
const demos = getDemos();
|
||||
const entries = demos.map((demo) => {
|
||||
const entry_row = new EntryRow({ demo });
|
||||
if (demo.name === "Welcome") last_triggered = entry_row;
|
||||
|
||||
entry_row.connect("triggered", (_self, language) => {
|
||||
last_triggered = entry_row;
|
||||
|
||||
openDemo({
|
||||
application,
|
||||
demo_name: demo.name,
|
||||
language,
|
||||
}).catch(console.error);
|
||||
});
|
||||
listbox.append(entry_row);
|
||||
|
||||
const category = categories_by_id[demo.category];
|
||||
const widget = entry_row;
|
||||
const languages = demo.languages.map((lang) => languages_by_id[lang]);
|
||||
|
||||
return { ...demo, category, widget, languages };
|
||||
});
|
||||
|
||||
const language_all = languages_by_id["all"];
|
||||
|
||||
function updateList() {
|
||||
const current_category =
|
||||
categories_by_index[dropdown_category.get_selected()];
|
||||
const current_language =
|
||||
languages_by_index[dropdown_language.get_selected()];
|
||||
|
||||
const search_term = search_entry.get_text().toLowerCase();
|
||||
let results_found = false;
|
||||
entries.forEach(({ name, description, category, languages, widget }) => {
|
||||
const category_match =
|
||||
current_category === category_all || category === current_category;
|
||||
const language_match =
|
||||
current_language === language_all ||
|
||||
languages.includes(current_language);
|
||||
const search_match =
|
||||
search_term === "" ||
|
||||
name.toLowerCase().includes(search_term) ||
|
||||
description.toLowerCase().includes(search_term) ||
|
||||
category.name.toLowerCase().includes(search_term);
|
||||
const is_match = category_match && language_match && search_match;
|
||||
widget.visible = is_match;
|
||||
if (is_match) {
|
||||
results_found = true;
|
||||
}
|
||||
});
|
||||
|
||||
results_empty.visible = !results_found;
|
||||
}
|
||||
|
||||
search_entry.connect("search-changed", updateList);
|
||||
dropdown_category.connect("notify::selected", updateList);
|
||||
dropdown_language.connect("notify::selected", updateList);
|
||||
|
||||
function reset() {
|
||||
scrolled_window.vadjustment = null;
|
||||
search_entry.text = "";
|
||||
dropdown_category.selected = category_all.index;
|
||||
dropdown_language.selected = language_all.index;
|
||||
}
|
||||
button_reset.connect("clicked", reset);
|
||||
window.connect("show", reset);
|
||||
|
||||
const action_library = new Gio.SimpleAction({
|
||||
name: "library",
|
||||
parameter_type: null,
|
||||
});
|
||||
action_library.connect("activate", () => {
|
||||
window.present();
|
||||
last_triggered?.grab_focus();
|
||||
});
|
||||
application.add_action(action_library);
|
||||
application.set_accels_for_action("app.library", ["<Control><Shift>O"]);
|
||||
}
|
||||
|
||||
const getDemos = (() => {
|
||||
let demos;
|
||||
return function getDemos() {
|
||||
if (!demos) {
|
||||
const file = demos_dir.get_child("index.json");
|
||||
const [, data] = file.load_contents(null);
|
||||
demos = JSON.parse(decode(data));
|
||||
}
|
||||
return demos;
|
||||
};
|
||||
})();
|
||||
|
||||
export function getDemo(name) {
|
||||
const demos = getDemos();
|
||||
return demos.find((demo) => demo.name === name);
|
||||
}
|
||||
|
||||
async function openDemo({ application, demo_name, language }) {
|
||||
const demo = getDemo(demo_name);
|
||||
const session = await createSessionFromDemo(demo);
|
||||
|
||||
if (language) {
|
||||
session.settings.set_int("code-language", language.index);
|
||||
global_settings.set_int("recent-code-language", language.index);
|
||||
|
||||
// If the user explicitly requested to open the demo
|
||||
// in a specific language then that's probably what they are interested in
|
||||
// therefore override the demo default and force show the code panel
|
||||
session.settings.set_boolean("show-code", true);
|
||||
}
|
||||
|
||||
const { autorun, languages } = demo;
|
||||
|
||||
// Override the user preferred language if the demo doesn't support it
|
||||
const lang = session.getCodeLanguage();
|
||||
if (languages.length > 0 && !languages.includes(lang.id)) {
|
||||
session.settings.set_int(
|
||||
"code-language",
|
||||
getLanguage(demo.languages[0]).index,
|
||||
);
|
||||
}
|
||||
|
||||
const { load, runCode, window } = Window({
|
||||
application,
|
||||
session,
|
||||
});
|
||||
await load();
|
||||
|
||||
if (needsAdditionalPermissions({ demo })) {
|
||||
showPermissionsDialog({ window });
|
||||
return;
|
||||
}
|
||||
|
||||
const code_language = session.getCodeLanguage();
|
||||
const run = autorun && code_language.id === "javascript";
|
||||
if (run) {
|
||||
await runCode();
|
||||
}
|
||||
}
|
757
src/Library/library.svg
Normal file
@ -0,0 +1,757 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="332"
|
||||
height="200"
|
||||
viewBox="0 0 332 200"
|
||||
version="1.1"
|
||||
id="svg5"
|
||||
inkscape:version="1.3 (0e150ed6c4, 2023-07-21)"
|
||||
sodipodi:docname="library.svg"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview7"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="false"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="false"
|
||||
inkscape:deskcolor="#ffffff"
|
||||
inkscape:document-units="px"
|
||||
showgrid="false"
|
||||
inkscape:zoom="1"
|
||||
inkscape:cx="132"
|
||||
inkscape:cy="102.5"
|
||||
inkscape:current-layer="layer1"
|
||||
showguides="true">
|
||||
<inkscape:grid
|
||||
id="grid1"
|
||||
units="px"
|
||||
originx="0"
|
||||
originy="0"
|
||||
spacingx="1"
|
||||
spacingy="1"
|
||||
empcolor="#0099e5"
|
||||
empopacity="0.30196078"
|
||||
color="#0099e5"
|
||||
opacity="0.14901961"
|
||||
empspacing="4"
|
||||
dotted="false"
|
||||
gridanglex="30"
|
||||
gridanglez="30"
|
||||
visible="false" />
|
||||
</sodipodi:namedview>
|
||||
<defs
|
||||
id="defs2">
|
||||
<linearGradient
|
||||
id="linearGradient1"
|
||||
inkscape:collect="always">
|
||||
<stop
|
||||
style="stop-color:#813d9c;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop1" />
|
||||
<stop
|
||||
style="stop-color:#33d17a;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop2" />
|
||||
</linearGradient>
|
||||
<inkscape:path-effect
|
||||
effect="fillet_chamfer"
|
||||
id="path-effect211"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
nodesatellites_param="F,0,0,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1"
|
||||
radius="0"
|
||||
unit="px"
|
||||
method="auto"
|
||||
mode="F"
|
||||
chamfer_steps="1"
|
||||
flexible="false"
|
||||
use_knot_distance="true"
|
||||
apply_no_radius="true"
|
||||
apply_with_radius="true"
|
||||
only_selected="false"
|
||||
hide_knots="false" />
|
||||
<inkscape:path-effect
|
||||
effect="fillet_chamfer"
|
||||
id="path-effect157"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
nodesatellites_param="F,0,0,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1"
|
||||
radius="0"
|
||||
unit="px"
|
||||
method="auto"
|
||||
mode="F"
|
||||
chamfer_steps="1"
|
||||
flexible="false"
|
||||
use_knot_distance="true"
|
||||
apply_no_radius="true"
|
||||
apply_with_radius="true"
|
||||
only_selected="false"
|
||||
hide_knots="false" />
|
||||
<inkscape:path-effect
|
||||
effect="fillet_chamfer"
|
||||
id="path-effect102"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
nodesatellites_param="F,0,0,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1"
|
||||
radius="0"
|
||||
unit="px"
|
||||
method="auto"
|
||||
mode="F"
|
||||
chamfer_steps="1"
|
||||
flexible="false"
|
||||
use_knot_distance="true"
|
||||
apply_no_radius="true"
|
||||
apply_with_radius="true"
|
||||
only_selected="false"
|
||||
hide_knots="false" />
|
||||
<linearGradient
|
||||
id="linearGradient46"
|
||||
inkscape:collect="always">
|
||||
<stop
|
||||
style="stop-color:#46311f;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop46" />
|
||||
<stop
|
||||
style="stop-color:#553d20;stop-opacity:1;"
|
||||
offset="0.03225805"
|
||||
id="stop50" />
|
||||
<stop
|
||||
style="stop-color:#63452c;stop-opacity:1;"
|
||||
offset="0.0645161"
|
||||
id="stop51" />
|
||||
<stop
|
||||
style="stop-color:#63452c;stop-opacity:1;"
|
||||
offset="0.93548352"
|
||||
id="stop49" />
|
||||
<stop
|
||||
style="stop-color:#845e3b;stop-opacity:1;"
|
||||
offset="0.96774155"
|
||||
id="stop48" />
|
||||
<stop
|
||||
style="stop-color:#b7865d;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop47" />
|
||||
</linearGradient>
|
||||
<inkscape:path-effect
|
||||
effect="fillet_chamfer"
|
||||
id="path-effect39"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
nodesatellites_param="F,0,0,1,0,3.414062,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1"
|
||||
radius="0"
|
||||
unit="px"
|
||||
method="auto"
|
||||
mode="F"
|
||||
chamfer_steps="1"
|
||||
flexible="false"
|
||||
use_knot_distance="true"
|
||||
apply_no_radius="true"
|
||||
apply_with_radius="true"
|
||||
only_selected="false"
|
||||
hide_knots="false" />
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath31">
|
||||
<path
|
||||
style="opacity:1;fill:#865e3c;fill-opacity:1;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:3.57621, 3.57621"
|
||||
d="m 104.57142,32 c -2.53257,0 -4.571424,1.784002 -4.571424,4 V 82 H 227.99999 V 36 c 0,-2.215998 -2.03886,-4 -4.57143,-4 z"
|
||||
id="path32" />
|
||||
</clipPath>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath33">
|
||||
<path
|
||||
style="opacity:1;fill:#865e3c;fill-opacity:1;stroke-width:1.99999;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:3.57621, 3.57621"
|
||||
d="m 99.999997,90 v 46 c 0,2.216 2.102573,4 4.714283,4 h 122.57143 c 2.61171,0 4.71428,-1.784 4.71428,-4 V 90 Z"
|
||||
id="path34" />
|
||||
</clipPath>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient46"
|
||||
id="linearGradient47"
|
||||
x1="64"
|
||||
y1="148"
|
||||
x2="64"
|
||||
y2="23.999954"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(-4,24)" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient1"
|
||||
id="linearGradient2"
|
||||
x1="-2.220446e-16"
|
||||
y1="195.8401"
|
||||
x2="331.99982"
|
||||
y2="4.1599178"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
</defs>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<path
|
||||
id="rect90"
|
||||
style="opacity:0.5;fill:url(#linearGradient2);fill-opacity:1;stroke:none;stroke-width:4.00001;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 56,12.476317 v 0.04737 A 12.476317,12.476317 45 0 0 68.476317,25 H 111.52368 A 12.476317,12.476317 45 0 1 124,37.476317 v 0.04737 A 12.476317,12.476317 135 0 1 111.52368,50 H 72.476317 A 12.476317,12.476317 135 0 0 60,62.476317 v 0.04737 A 12.476317,12.476317 135 0 1 47.523683,75 H 12.476317 A 12.476317,12.476317 135 0 0 0,87.476317 v 0.04737 A 12.476317,12.476317 45 0 0 12.476317,100 h 3.047366 A 12.476317,12.476317 45 0 1 28,112.47632 v 0.0474 A 12.476317,12.476317 135 0 1 15.523683,125 12.00945,12.00945 132.72695 0 0 4,137.47632 v 0.0474 A 12.476317,12.476317 45 0 0 16.476317,150 H 35.523683 A 12.476317,12.476317 45 0 1 48,162.47632 v 0.0474 A 12.476317,12.476317 135 0 1 35.523683,175 H 32.476317 A 12.476317,12.476317 135 0 0 20,187.47632 v 0.0474 A 12.476317,12.476317 45 0 0 32.476317,200 H 187.52368 A 12.476317,12.476317 135 0 0 200,187.52368 v -0.0474 A 12.476317,12.476317 135 0 1 212.47632,175 h 59.04736 A 12.476317,12.476317 135 0 0 284,162.52368 v -0.0474 A 12.476317,12.476317 135 0 1 296.47632,150 h 7.04736 A 12.476317,12.476317 135 0 0 316,137.52368 v -0.0474 A 12.476317,12.476317 45 0 0 303.52368,125 H 284.47632 A 12.476317,12.476317 45 0 1 272,112.52368 v -0.0474 A 12.476317,12.476317 135 0 1 284.47632,100 h 35.04736 A 12.476317,12.476317 135 0 0 332,87.523683 v -0.04737 A 12.476317,12.476317 45 0 0 319.52368,75 H 308.47632 A 12.476317,12.476317 45 0 1 296,62.523683 v -0.04737 A 12.476317,12.476317 135 0 1 308.47632,50 h 7.04736 A 12.476317,12.476317 135 0 0 328,37.523683 v -0.04737 A 12.476317,12.476317 45 0 0 315.52368,25 H 232.47632 A 12.476317,12.476317 45 0 1 220,12.523683 v -0.04737 A 12.476317,12.476317 45 0 0 207.52368,0 H 68.476317 A 12.476317,12.476317 135 0 0 56,12.476317 Z"
|
||||
sodipodi:nodetypes="ccccccccccccccccccccccccccccccccc" />
|
||||
<rect
|
||||
style="opacity:1;fill:url(#linearGradient47);stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:3.57621, 3.57621"
|
||||
id="rect1"
|
||||
width="176"
|
||||
height="124"
|
||||
x="28"
|
||||
y="48"
|
||||
ry="12"
|
||||
rx="12" />
|
||||
<rect
|
||||
style="opacity:1;fill:#9a9996;fill-opacity:1;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:3.57621, 3.57621"
|
||||
id="rect35"
|
||||
width="44"
|
||||
height="8"
|
||||
x="123.98968"
|
||||
y="225.24355"
|
||||
transform="rotate(-30)" />
|
||||
<circle
|
||||
style="opacity:1;fill:#77767b;fill-opacity:1;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:3.57621, 3.57621"
|
||||
id="path35"
|
||||
cx="216"
|
||||
cy="138"
|
||||
r="10" />
|
||||
<rect
|
||||
style="opacity:1;fill:#986a44;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:3.57621, 3.57621"
|
||||
id="rect2"
|
||||
width="128"
|
||||
height="124"
|
||||
x="88"
|
||||
y="48"
|
||||
ry="12"
|
||||
rx="12" />
|
||||
<path
|
||||
style="opacity:1;fill:#63452c;fill-opacity:1;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:3.57621, 3.57621"
|
||||
d="m 96,114 v 46 c 0,2.216 1.784,4 4,4 h 104 c 2.216,0 4,-1.784 4,-4 v -46 z"
|
||||
id="path30" />
|
||||
<path
|
||||
style="opacity:1;fill:#63452c;fill-opacity:1;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:3.57621, 3.57621"
|
||||
d="m 100,56 c -2.216,0 -4,1.784002 -4,4 v 46 H 208 V 60 c 0,-2.215998 -1.784,-4 -4,-4 z"
|
||||
id="rect3" />
|
||||
<g
|
||||
id="g30"
|
||||
clip-path="url(#clipPath31)"
|
||||
transform="translate(-4,24)">
|
||||
<rect
|
||||
style="opacity:1;fill:#deddda;fill-opacity:1;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:3.57621, 3.57621"
|
||||
id="rect15"
|
||||
width="56"
|
||||
height="42"
|
||||
x="168"
|
||||
y="40"
|
||||
ry="6"
|
||||
rx="6.0000005" />
|
||||
<rect
|
||||
style="opacity:1;fill:#f6f5f4;fill-opacity:1;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:3.57621, 3.57621"
|
||||
id="rect9"
|
||||
width="56"
|
||||
height="42"
|
||||
x="166"
|
||||
y="40"
|
||||
ry="6"
|
||||
rx="6.0000005" />
|
||||
<rect
|
||||
style="opacity:1;fill:#241f31;fill-opacity:1;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:3.57621, 3.57621"
|
||||
id="rect14"
|
||||
width="44"
|
||||
height="34"
|
||||
x="160"
|
||||
y="48"
|
||||
ry="6"
|
||||
rx="6" />
|
||||
<rect
|
||||
style="opacity:1;fill:#3d3846;fill-opacity:1;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:3.57621, 3.57621"
|
||||
id="rect8"
|
||||
width="44"
|
||||
height="34"
|
||||
x="158"
|
||||
y="48"
|
||||
ry="6"
|
||||
rx="6" />
|
||||
<rect
|
||||
style="opacity:1;fill:#5e5c64;fill-opacity:1;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect44"
|
||||
width="16.247879"
|
||||
height="6"
|
||||
x="167.75212"
|
||||
y="62"
|
||||
rx="3"
|
||||
ry="3" />
|
||||
<rect
|
||||
style="opacity:1;fill:#5e5c64;fill-opacity:1;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect43"
|
||||
width="16.247879"
|
||||
height="6"
|
||||
x="167.75212"
|
||||
y="71"
|
||||
rx="3"
|
||||
ry="3" />
|
||||
<rect
|
||||
style="opacity:1;fill:#5e5c64;fill-opacity:1;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect45"
|
||||
width="20.247879"
|
||||
height="4"
|
||||
x="167.75212"
|
||||
y="54"
|
||||
rx="2"
|
||||
ry="2" />
|
||||
<rect
|
||||
style="opacity:1;fill:#deddda;fill-opacity:1;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:3.57621, 3.57621"
|
||||
id="rect13"
|
||||
width="48"
|
||||
height="46"
|
||||
x="127.99999"
|
||||
y="36"
|
||||
ry="6"
|
||||
rx="6" />
|
||||
<rect
|
||||
style="opacity:1;fill:#f6f5f4;fill-opacity:1;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:3.57621, 3.57621"
|
||||
id="rect7"
|
||||
width="48"
|
||||
height="46"
|
||||
x="125.99999"
|
||||
y="36"
|
||||
ry="6"
|
||||
rx="6" />
|
||||
<circle
|
||||
style="opacity:1;fill:none;fill-opacity:1;stroke:#c0bfbc;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path42"
|
||||
cx="150"
|
||||
cy="63"
|
||||
r="11" />
|
||||
<rect
|
||||
style="opacity:1;fill:#241f31;fill-opacity:1;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:3.57621, 3.57621"
|
||||
id="rect12"
|
||||
width="40"
|
||||
height="34"
|
||||
x="111.99999"
|
||||
y="48"
|
||||
ry="6"
|
||||
rx="6" />
|
||||
<rect
|
||||
style="opacity:1;fill:#3d3846;fill-opacity:1;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:3.57621, 3.57621"
|
||||
id="rect6"
|
||||
width="40"
|
||||
height="34"
|
||||
x="109.99999"
|
||||
y="48"
|
||||
ry="6"
|
||||
rx="6" />
|
||||
<rect
|
||||
style="opacity:1;fill:#deddda;fill-opacity:1;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:3.57621, 3.57621"
|
||||
id="rect11"
|
||||
width="44"
|
||||
height="40"
|
||||
x="91.999992"
|
||||
y="42"
|
||||
ry="6"
|
||||
rx="6" />
|
||||
<rect
|
||||
style="opacity:1;fill:#f6f5f4;fill-opacity:1;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:3.57621, 3.57621"
|
||||
id="rect5"
|
||||
width="44"
|
||||
height="40"
|
||||
x="89.999992"
|
||||
y="42"
|
||||
ry="6"
|
||||
rx="6" />
|
||||
<rect
|
||||
style="opacity:1;fill:#c0bfbc;fill-opacity:1;stroke-width:1.99999;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:3.5762, 3.5762"
|
||||
id="rect39"
|
||||
width="28.000002"
|
||||
height="4"
|
||||
x="92"
|
||||
y="56"
|
||||
ry="2"
|
||||
rx="2" />
|
||||
<rect
|
||||
style="opacity:1;fill:#3584e4;fill-opacity:1;stroke-width:1.99998;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:3.57621, 3.57621"
|
||||
id="rect40"
|
||||
width="17.999998"
|
||||
height="6"
|
||||
x="97"
|
||||
y="64"
|
||||
ry="3"
|
||||
rx="3" />
|
||||
<rect
|
||||
style="opacity:1;fill:#000000;fill-opacity:0.1;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:3.5762, 3.5762"
|
||||
id="rect34"
|
||||
width="8"
|
||||
height="49.999989"
|
||||
x="94"
|
||||
y="31.999998" />
|
||||
<circle
|
||||
style="opacity:1;fill:#deddda;fill-opacity:0.2;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:3.57621, 3.57621"
|
||||
id="path41"
|
||||
cx="145"
|
||||
cy="53"
|
||||
r="2" />
|
||||
<rect
|
||||
style="opacity:1;fill:#c0bfbc;fill-opacity:1;stroke-width:1.99999;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:3.5762, 3.5762"
|
||||
id="rect42"
|
||||
width="28.000002"
|
||||
height="4"
|
||||
x="135.99998"
|
||||
y="42"
|
||||
ry="2"
|
||||
rx="2" />
|
||||
</g>
|
||||
<g
|
||||
id="g32"
|
||||
clip-path="url(#clipPath33)"
|
||||
transform="translate(-4,24)">
|
||||
<rect
|
||||
style="opacity:1;fill:#deddda;fill-opacity:1;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:3.57621, 3.57621"
|
||||
id="rect27"
|
||||
width="56"
|
||||
height="32"
|
||||
x="168"
|
||||
y="108"
|
||||
ry="6"
|
||||
rx="6.0000005" />
|
||||
<rect
|
||||
style="opacity:1;fill:#f6f5f4;fill-opacity:1;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:3.57621, 3.57621"
|
||||
id="rect17"
|
||||
width="56"
|
||||
height="32"
|
||||
x="166"
|
||||
y="108"
|
||||
ry="6"
|
||||
rx="6.0000005" />
|
||||
<g
|
||||
id="g64"
|
||||
transform="translate(28,6.9999771)">
|
||||
<rect
|
||||
style="fill:#77767b;fill-opacity:1;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect52"
|
||||
width="16"
|
||||
height="8"
|
||||
x="172"
|
||||
y="108"
|
||||
rx="4"
|
||||
ry="4" />
|
||||
<rect
|
||||
style="fill:#3584e4;fill-opacity:1;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect51"
|
||||
width="16"
|
||||
height="8"
|
||||
x="172"
|
||||
y="118"
|
||||
rx="4"
|
||||
ry="4" />
|
||||
<circle
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="circle52"
|
||||
cx="176"
|
||||
cy="112.00001"
|
||||
r="3" />
|
||||
<circle
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path51"
|
||||
cx="184"
|
||||
cy="122.00002"
|
||||
r="3" />
|
||||
</g>
|
||||
<rect
|
||||
style="opacity:1;fill:#deddda;fill-opacity:1;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:3.57621, 3.57621"
|
||||
id="rect28"
|
||||
width="44"
|
||||
height="44"
|
||||
x="160"
|
||||
y="96"
|
||||
ry="5.9999995"
|
||||
rx="6" />
|
||||
<rect
|
||||
style="opacity:1;fill:#f6f5f4;fill-opacity:1;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:3.57621, 3.57621"
|
||||
id="rect19"
|
||||
width="44"
|
||||
height="44"
|
||||
x="158"
|
||||
y="96"
|
||||
ry="5.9999995"
|
||||
rx="6" />
|
||||
<rect
|
||||
style="opacity:1;fill:#9a9996;fill-opacity:1;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect65"
|
||||
width="32"
|
||||
height="22"
|
||||
x="164"
|
||||
y="102"
|
||||
rx="2"
|
||||
ry="2" />
|
||||
<rect
|
||||
style="opacity:1;fill:#c0bfbc;fill-opacity:1;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect66"
|
||||
width="21"
|
||||
height="4"
|
||||
x="167"
|
||||
y="128"
|
||||
rx="2"
|
||||
ry="2" />
|
||||
<rect
|
||||
style="opacity:1;fill:#deddda;fill-opacity:1;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:3.57621, 3.57621"
|
||||
id="rect29"
|
||||
width="41.999992"
|
||||
height="40"
|
||||
x="134"
|
||||
y="100"
|
||||
ry="5.9999995"
|
||||
rx="6" />
|
||||
<rect
|
||||
style="opacity:1;fill:#f6f5f4;fill-opacity:1;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:3.57621, 3.57621"
|
||||
id="rect21"
|
||||
width="41.999992"
|
||||
height="40"
|
||||
x="132"
|
||||
y="100"
|
||||
ry="5.9999995"
|
||||
rx="6" />
|
||||
<rect
|
||||
style="opacity:1;fill:#c0bfbc;fill-opacity:1;stroke:none;stroke-width:4.00001;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect55"
|
||||
width="12"
|
||||
height="12"
|
||||
x="156"
|
||||
y="106"
|
||||
rx="2"
|
||||
ry="2" />
|
||||
<rect
|
||||
style="opacity:1;fill:#deddda;fill-opacity:1;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:3.57621, 3.57621"
|
||||
id="rect30"
|
||||
width="43.999992"
|
||||
height="47.999996"
|
||||
x="110.00001"
|
||||
y="92.000008"
|
||||
ry="6"
|
||||
rx="6" />
|
||||
<rect
|
||||
style="opacity:1;fill:#f6f5f4;fill-opacity:1;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:3.57621, 3.57621"
|
||||
id="rect23"
|
||||
width="43.999992"
|
||||
height="47.999996"
|
||||
x="108.00001"
|
||||
y="92.000008"
|
||||
ry="6"
|
||||
rx="6" />
|
||||
<rect
|
||||
style="opacity:1;fill:#c0bfbc;fill-opacity:1;stroke:none;stroke-width:3.99999;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect54"
|
||||
width="28"
|
||||
height="24"
|
||||
x="116"
|
||||
y="108"
|
||||
ry="2"
|
||||
rx="2" />
|
||||
<rect
|
||||
style="opacity:1;fill:#241f31;fill-opacity:1;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:3.57621, 3.57621"
|
||||
id="rect26"
|
||||
width="54"
|
||||
height="28"
|
||||
x="91.999992"
|
||||
y="112"
|
||||
ry="6"
|
||||
rx="6" />
|
||||
<rect
|
||||
style="opacity:1;fill:#3d3846;fill-opacity:1;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:3.57621, 3.57621"
|
||||
id="rect25"
|
||||
width="54"
|
||||
height="28"
|
||||
x="89.999992"
|
||||
y="112"
|
||||
ry="6"
|
||||
rx="6" />
|
||||
<rect
|
||||
style="opacity:1;fill:#5e5c64;fill-opacity:1;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect61"
|
||||
width="8"
|
||||
height="12"
|
||||
x="108"
|
||||
y="120"
|
||||
rx="2"
|
||||
ry="2" />
|
||||
<rect
|
||||
style="opacity:1;fill:#5e5c64;fill-opacity:1;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect64"
|
||||
width="8.8721447"
|
||||
height="12"
|
||||
x="97.127861"
|
||||
y="120"
|
||||
rx="2"
|
||||
ry="2" />
|
||||
<rect
|
||||
style="fill:#000000;fill-opacity:0.1;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:3.5762, 3.5762"
|
||||
id="rect34-3"
|
||||
width="7.0000024"
|
||||
height="49.999989"
|
||||
x="95"
|
||||
y="90.000015" />
|
||||
<rect
|
||||
style="opacity:1;fill:#5e5c64;fill-opacity:1;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect62"
|
||||
width="12"
|
||||
height="12"
|
||||
x="118"
|
||||
y="120"
|
||||
rx="2"
|
||||
ry="2" />
|
||||
<rect
|
||||
style="opacity:1;fill:#c0bfbc;fill-opacity:1;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect53"
|
||||
width="28"
|
||||
height="4"
|
||||
x="116"
|
||||
y="100"
|
||||
ry="2"
|
||||
rx="2" />
|
||||
<rect
|
||||
style="opacity:1;fill:#5e5c64;fill-opacity:1;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect63"
|
||||
width="8"
|
||||
height="12"
|
||||
x="132"
|
||||
y="120"
|
||||
rx="2"
|
||||
ry="2" />
|
||||
<rect
|
||||
style="opacity:1;fill:#c0bfbc;fill-opacity:1;stroke:none;stroke-width:4.00001;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect68"
|
||||
width="12"
|
||||
height="12"
|
||||
x="156"
|
||||
y="122"
|
||||
rx="2"
|
||||
ry="2" />
|
||||
</g>
|
||||
<rect
|
||||
style="opacity:1;fill:#9a9996;fill-opacity:1;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:3.57621, 3.57621"
|
||||
id="rect36"
|
||||
width="24"
|
||||
height="8"
|
||||
x="-110"
|
||||
y="256"
|
||||
transform="rotate(-90)" />
|
||||
<path
|
||||
id="path102"
|
||||
style="opacity:1;fill:#f26600;fill-opacity:1;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:3.57621, 3.57621"
|
||||
d="M 255.41992 75.861328 C 255.02655 75.872791 254.60183 76.068099 254.19922 76.492188 C 252.81595 77.949248 252.00056 79.907607 252 82 C 252.00713 84.850974 253.53097 87.482721 256 88.908203 L 256 96 L 260 96 L 261 96 L 261 84.771484 L 260 84.771484 C 258.338 84.771484 257 83.43348 257 81.771484 L 257 78 C 257 76.703697 256.28535 75.83611 255.41992 75.861328 z " />
|
||||
<circle
|
||||
style="opacity:1;fill:#77767b;fill-opacity:1;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:3.57621, 3.57621"
|
||||
id="path36"
|
||||
cx="260"
|
||||
cy="114"
|
||||
r="8" />
|
||||
<rect
|
||||
style="fill:#deddda;fill-opacity:1;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:3.57621, 3.57621"
|
||||
id="rect15-6"
|
||||
width="56"
|
||||
height="42"
|
||||
x="-287"
|
||||
y="42"
|
||||
ry="6"
|
||||
rx="6.0000005"
|
||||
transform="scale(-1,1)" />
|
||||
<rect
|
||||
style="fill:#f6f5f4;fill-opacity:1;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:3.57621, 3.57621"
|
||||
id="rect9-7"
|
||||
width="56"
|
||||
height="42"
|
||||
x="-289"
|
||||
y="42"
|
||||
ry="6"
|
||||
rx="6.0000005"
|
||||
transform="scale(-1,1)" />
|
||||
<rect
|
||||
style="opacity:1;fill:#c0bfbc;fill-opacity:1;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect79"
|
||||
width="19"
|
||||
height="4"
|
||||
x="254"
|
||||
y="70"
|
||||
rx="2"
|
||||
ry="2" />
|
||||
<rect
|
||||
style="opacity:1;fill:#c0bfbc;fill-opacity:1;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect80"
|
||||
width="19"
|
||||
height="4"
|
||||
x="254"
|
||||
y="76"
|
||||
rx="2"
|
||||
ry="2" />
|
||||
<path
|
||||
id="path38"
|
||||
style="opacity:1;fill:#ff7800;fill-opacity:1;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:3.57621, 3.57621"
|
||||
d="m 263,78 v 3.771484 c 0,1.661997 -1.338,3 -3,3 V 89 96 h 4 v -7.091797 c 2.46903,-1.425484 3.99287,-4.057226 4,-6.908203 -5.6e-4,-2.092395 -0.81599,-4.050284 -2.19926,-5.507346 C 264.51239,75.135571 263,76.114466 263,78 Z" />
|
||||
<rect
|
||||
style="opacity:1;fill:#986a44;fill-opacity:1;stroke:none;stroke-width:3.99999;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect73"
|
||||
width="16"
|
||||
height="13"
|
||||
x="253"
|
||||
y="47"
|
||||
ry="1.9999999"
|
||||
rx="2" />
|
||||
<rect
|
||||
style="opacity:1;fill:#ff7800;fill-opacity:1;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect75"
|
||||
width="2"
|
||||
height="7"
|
||||
x="265"
|
||||
y="51"
|
||||
rx="0.98211634"
|
||||
ry="0.98211634" />
|
||||
<rect
|
||||
style="opacity:1;fill:#33d17a;fill-opacity:1;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect76"
|
||||
width="2"
|
||||
height="7"
|
||||
x="255"
|
||||
y="49"
|
||||
rx="0.98211634"
|
||||
ry="0.98211634" />
|
||||
<rect
|
||||
style="opacity:1;fill:#deddda;fill-opacity:1;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect77"
|
||||
width="2"
|
||||
height="7"
|
||||
x="260"
|
||||
y="50"
|
||||
rx="0.98211634"
|
||||
ry="0.98211634" />
|
||||
<rect
|
||||
style="opacity:1;fill:#c0bfbc;fill-opacity:1;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect78"
|
||||
width="28"
|
||||
height="4"
|
||||
x="247"
|
||||
y="62"
|
||||
rx="2"
|
||||
ry="2" />
|
||||
<circle
|
||||
style="opacity:1;fill:#c0bfbc;fill-opacity:1;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path80"
|
||||
cx="250"
|
||||
cy="72"
|
||||
r="2" />
|
||||
<circle
|
||||
style="opacity:1;fill:#c0bfbc;fill-opacity:1;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="circle80"
|
||||
cx="250"
|
||||
cy="78"
|
||||
r="2" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 29 KiB |
78
src/PanelCode.js
Normal file
@ -0,0 +1,78 @@
|
||||
import Gio from "gi://Gio";
|
||||
import GObject from "gi://GObject";
|
||||
|
||||
import { makeDropdownFlat, settings as global_settings } from "./util.js";
|
||||
import { setupRustProject } from "./langs/rust/rust.js";
|
||||
import { setupTypeScriptProject } from "./langs/typescript/typescript.js";
|
||||
import { setupJavascriptProject } from "./langs/javascript/javascript.js";
|
||||
|
||||
export default function PanelCode({
|
||||
builder,
|
||||
previewer,
|
||||
session: { settings, file },
|
||||
langs,
|
||||
}) {
|
||||
const panel_code = builder.get_object("panel_code");
|
||||
const button_code = builder.get_object("button_code");
|
||||
const stack_code = builder.get_object("stack_code");
|
||||
|
||||
const dropdown_code_lang = builder.get_object("dropdown_code_lang");
|
||||
makeDropdownFlat(dropdown_code_lang);
|
||||
|
||||
settings.bind(
|
||||
"show-code",
|
||||
button_code,
|
||||
"active",
|
||||
Gio.SettingsBindFlags.DEFAULT,
|
||||
);
|
||||
button_code.bind_property(
|
||||
"active",
|
||||
panel_code,
|
||||
"visible",
|
||||
GObject.BindingFlags.SYNC_CREATE,
|
||||
);
|
||||
|
||||
settings.bind(
|
||||
"code-language",
|
||||
dropdown_code_lang,
|
||||
"selected",
|
||||
Gio.SettingsBindFlags.DEFAULT,
|
||||
);
|
||||
dropdown_code_lang.connect("notify::selected-item", switchLanguage);
|
||||
|
||||
settings.connect("changed::code-language", () => {
|
||||
global_settings.set_int(
|
||||
"recent-code-language",
|
||||
settings.get_int("code-language"),
|
||||
);
|
||||
});
|
||||
|
||||
const panel = {
|
||||
panel: panel_code,
|
||||
};
|
||||
|
||||
function switchLanguage() {
|
||||
panel.language = dropdown_code_lang.selected_item?.string;
|
||||
stack_code.visible_child_name = panel.language;
|
||||
previewer.useInternal().catch(console.error);
|
||||
|
||||
if (panel.language.toLowerCase() === "javascript") {
|
||||
setupJavascriptProject(file, langs.javascript.document).catch(
|
||||
console.error,
|
||||
);
|
||||
}
|
||||
|
||||
if (panel.language.toLowerCase() === "rust") {
|
||||
setupRustProject(file).catch(console.error);
|
||||
}
|
||||
|
||||
if (panel.language.toLowerCase() === "typescript") {
|
||||
setupTypeScriptProject(file, langs.typescript.document).catch(
|
||||
console.error,
|
||||
);
|
||||
}
|
||||
}
|
||||
switchLanguage();
|
||||
|
||||
return panel;
|
||||
}
|
19
src/PanelStyle.js
Normal file
@ -0,0 +1,19 @@
|
||||
import Gio from "gi://Gio";
|
||||
import GObject from "gi://GObject";
|
||||
|
||||
export default function PanelStyle({ builder, settings }) {
|
||||
const button_style = builder.get_object("button_style");
|
||||
const panel_style = builder.get_object("panel_style");
|
||||
settings.bind(
|
||||
"show-style",
|
||||
button_style,
|
||||
"active",
|
||||
Gio.SettingsBindFlags.DEFAULT,
|
||||
);
|
||||
button_style.bind_property(
|
||||
"active",
|
||||
panel_style,
|
||||
"visible",
|
||||
GObject.BindingFlags.SYNC_CREATE,
|
||||
);
|
||||
}
|
191
src/PanelUI.js
Normal file
@ -0,0 +1,191 @@
|
||||
import Gio from "gi://Gio";
|
||||
import GObject from "gi://GObject";
|
||||
import Gtk from "gi://Gtk";
|
||||
|
||||
import { LSPError } from "./lsp/LSP.js";
|
||||
import {
|
||||
unstack,
|
||||
listenProperty,
|
||||
getLanguage,
|
||||
makeDropdownFlat,
|
||||
} from "./util.js";
|
||||
|
||||
import { logBlueprintError } from "./langs/blueprint/blueprint.js";
|
||||
|
||||
// eslint-disable-next-line no-restricted-globals
|
||||
const { addSignalMethods } = imports.signals;
|
||||
|
||||
const lang_blueprint = getLanguage("blueprint");
|
||||
const lang_xml = getLanguage("xml");
|
||||
export const ui_languages = [lang_blueprint, lang_xml];
|
||||
|
||||
export default function PanelUI({
|
||||
application,
|
||||
builder,
|
||||
term_console,
|
||||
document_xml,
|
||||
document_blueprint,
|
||||
settings,
|
||||
}) {
|
||||
let lang;
|
||||
|
||||
const code_view_xml = document_xml.code_view;
|
||||
const code_view_blueprint = document_blueprint.code_view;
|
||||
|
||||
const panel = {
|
||||
xml: "",
|
||||
};
|
||||
addSignalMethods(panel);
|
||||
|
||||
const buffer_blueprint = code_view_blueprint.buffer;
|
||||
const buffer_xml = code_view_xml.buffer;
|
||||
|
||||
const button_ui = builder.get_object("button_ui");
|
||||
const panel_ui = builder.get_object("panel_ui");
|
||||
|
||||
settings.bind("show-ui", button_ui, "active", Gio.SettingsBindFlags.DEFAULT);
|
||||
button_ui.bind_property(
|
||||
"active",
|
||||
panel_ui,
|
||||
"visible",
|
||||
GObject.BindingFlags.SYNC_CREATE,
|
||||
);
|
||||
|
||||
const stack_ui = builder.get_object("stack_ui");
|
||||
const dropdown_ui_lang = builder.get_object("dropdown_ui_lang");
|
||||
makeDropdownFlat(dropdown_ui_lang);
|
||||
dropdown_ui_lang.set_selected(settings.get_enum("user-interface-language"));
|
||||
|
||||
async function convertToXML() {
|
||||
term_console.clear();
|
||||
settings.set_boolean("show-console", true);
|
||||
|
||||
const xml = await document_blueprint.compile(buffer_blueprint.text);
|
||||
code_view_xml.replaceText(xml);
|
||||
}
|
||||
|
||||
async function convertToBlueprint() {
|
||||
term_console.clear();
|
||||
settings.set_boolean("show-console", true);
|
||||
|
||||
const blp = await document_blueprint.decompile(buffer_xml.text);
|
||||
code_view_blueprint.replaceText(blp);
|
||||
}
|
||||
|
||||
const button_ui_experimental_blueprint = builder.get_object(
|
||||
"button_ui_experimental_blueprint",
|
||||
);
|
||||
button_ui_experimental_blueprint.connect("clicked", () => {
|
||||
const dialog = builder.get_object("dialog_blueprint_experimental");
|
||||
dialog.present(application.get_active_window());
|
||||
});
|
||||
const button_blueprint_documentation = builder.get_object(
|
||||
"button_blueprint_documentation",
|
||||
);
|
||||
button_blueprint_documentation.connect("clicked", () => {
|
||||
new Gtk.UriLauncher({
|
||||
uri: "https://jwestman.pages.gitlab.gnome.org/blueprint-compiler/",
|
||||
})
|
||||
.launch(application.get_active_window(), null)
|
||||
.catch(console.error);
|
||||
});
|
||||
|
||||
let handler_id_xml = null;
|
||||
let handler_id_blueprint = null;
|
||||
|
||||
// FIXME we should wait for previewer update instead
|
||||
// when loading demo
|
||||
async function update() {
|
||||
if (lang === lang_blueprint) {
|
||||
onXML(await document_blueprint.compile());
|
||||
} else if (lang === lang_xml) {
|
||||
onXML(buffer_xml.text);
|
||||
}
|
||||
}
|
||||
|
||||
function onXML(xml) {
|
||||
panel.xml = xml || "";
|
||||
panel.emit("updated");
|
||||
}
|
||||
|
||||
const onBlueprint = unstack(function onBlueprint() {
|
||||
return document_blueprint.compile().then(onXML);
|
||||
}, console.error);
|
||||
|
||||
function start() {
|
||||
stop();
|
||||
lang = getLanguage(settings.get_string("user-interface-language"));
|
||||
handler_id_xml = code_view_xml.connect("changed", () => {
|
||||
if (lang !== lang_xml) return;
|
||||
onXML(code_view_xml.buffer.text);
|
||||
});
|
||||
handler_id_blueprint = code_view_blueprint.connect("changed", onBlueprint);
|
||||
}
|
||||
|
||||
function stop() {
|
||||
if (handler_id_xml !== null) {
|
||||
code_view_xml.disconnect(handler_id_xml);
|
||||
handler_id_xml = null;
|
||||
}
|
||||
if (handler_id_blueprint !== null) {
|
||||
code_view_blueprint.disconnect(handler_id_blueprint);
|
||||
handler_id_blueprint = null;
|
||||
}
|
||||
}
|
||||
|
||||
const dropdown_selected_signal = listenProperty(
|
||||
dropdown_ui_lang,
|
||||
"selected",
|
||||
(value) => {
|
||||
const lang = ui_languages[value];
|
||||
onChangeLang(lang).catch(console.error);
|
||||
},
|
||||
);
|
||||
|
||||
async function onChangeLang(lang) {
|
||||
if (lang === lang_xml) {
|
||||
try {
|
||||
await convertToXML();
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
// FIXME: Looks like the block() calls don't work
|
||||
// and the notify::selected signal is emitted
|
||||
dropdown_selected_signal.block();
|
||||
dropdown_ui_lang.set_selected(ui_languages.indexOf(lang_blueprint));
|
||||
dropdown_selected_signal.unblock();
|
||||
return;
|
||||
}
|
||||
} else if (lang === lang_blueprint) {
|
||||
try {
|
||||
await convertToBlueprint();
|
||||
} catch (err) {
|
||||
if (err instanceof LSPError) {
|
||||
logBlueprintError(err);
|
||||
} else {
|
||||
console.error(err);
|
||||
}
|
||||
dropdown_selected_signal.block();
|
||||
dropdown_ui_lang.set_selected(ui_languages.indexOf(lang_xml));
|
||||
dropdown_selected_signal.unblock();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
settings.set_string("user-interface-language", lang.id);
|
||||
setupLanguage();
|
||||
}
|
||||
|
||||
function setupLanguage() {
|
||||
start();
|
||||
stack_ui.set_visible_child_name(lang.id);
|
||||
button_ui_experimental_blueprint.visible = lang === lang_blueprint;
|
||||
}
|
||||
setupLanguage();
|
||||
|
||||
panel.start = start;
|
||||
panel.stop = stop;
|
||||
panel.update = update;
|
||||
panel.panel = panel_ui;
|
||||
|
||||
return panel;
|
||||
}
|
155
src/Permissions/Permissions.blp
Normal file
@ -0,0 +1,155 @@
|
||||
using Gtk 4.0;
|
||||
using Adw 1;
|
||||
|
||||
Adw.Dialog dialog {
|
||||
content-height: 750;
|
||||
content-width: 600;
|
||||
|
||||
Adw.ToolbarView {
|
||||
[top]
|
||||
Adw.HeaderBar {}
|
||||
|
||||
content: ScrolledWindow {
|
||||
hscrollbar-policy: never;
|
||||
|
||||
Adw.Clamp {
|
||||
maximum-size: 520;
|
||||
tightening-threshold: 400;
|
||||
margin-start: 12;
|
||||
margin-end: 12;
|
||||
margin-bottom: 24;
|
||||
|
||||
Box {
|
||||
orientation: vertical;
|
||||
halign: fill;
|
||||
spacing: 24;
|
||||
// Gtk.Picture needs to be wrapped in a box to behave properly
|
||||
Box {
|
||||
halign: center;
|
||||
|
||||
Picture picture_illustration {
|
||||
can-shrink: false;
|
||||
margin-bottom: 24;
|
||||
}
|
||||
}
|
||||
|
||||
Label {
|
||||
label: _("Permissions Needed");
|
||||
|
||||
styles [
|
||||
"title-1",
|
||||
]
|
||||
}
|
||||
|
||||
Label {
|
||||
label: _("Workbench needs additional permissions. Please run the following command in a terminal and restart Workbench.");
|
||||
wrap: true;
|
||||
justify: center;
|
||||
}
|
||||
|
||||
Label label_command {
|
||||
use-markup: true;
|
||||
wrap: true;
|
||||
wrap-mode: word_char;
|
||||
selectable: true;
|
||||
xalign: 0;
|
||||
|
||||
styles [
|
||||
"command_snippet",
|
||||
]
|
||||
}
|
||||
|
||||
Box {
|
||||
orientation: vertical;
|
||||
|
||||
Box {
|
||||
margin-bottom: 6;
|
||||
|
||||
Label {
|
||||
label: _("What it does");
|
||||
halign: start;
|
||||
hexpand: true;
|
||||
|
||||
styles [
|
||||
"heading",
|
||||
]
|
||||
}
|
||||
|
||||
Button button_info {
|
||||
icon-name: "re.sonny.Workbench-external-link-symbolic";
|
||||
|
||||
styles [
|
||||
"flat",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
ListBox {
|
||||
selection-mode: none;
|
||||
|
||||
styles [
|
||||
"boxed-list",
|
||||
]
|
||||
|
||||
Adw.ActionRow {
|
||||
[prefix]
|
||||
Image {
|
||||
icon-name: "re.sonny.Workbench-person-symbolic";
|
||||
}
|
||||
|
||||
title: _("--user");
|
||||
subtitle: _("Grant for your account only");
|
||||
|
||||
styles [
|
||||
"property",
|
||||
]
|
||||
}
|
||||
|
||||
Adw.ActionRow {
|
||||
[prefix]
|
||||
Image {
|
||||
icon-name: "re.sonny.Workbench-network-wireless-symbolic";
|
||||
}
|
||||
|
||||
title: _("--share-network");
|
||||
subtitle: _("Network access");
|
||||
|
||||
styles [
|
||||
"property",
|
||||
]
|
||||
}
|
||||
|
||||
Adw.ActionRow {
|
||||
[prefix]
|
||||
Image {
|
||||
icon-name: "re.sonny.Workbench-speakers-symbolic";
|
||||
}
|
||||
|
||||
title: _("--socket=pulseaudio");
|
||||
subtitle: _("Record and play audio");
|
||||
|
||||
styles [
|
||||
"property",
|
||||
]
|
||||
}
|
||||
|
||||
Adw.ActionRow action_row_device {
|
||||
[prefix]
|
||||
Image {
|
||||
icon-name: "re.sonny.Workbench-gamepad-symbolic";
|
||||
}
|
||||
|
||||
// title: _("--device=input");
|
||||
subtitle: _("Access to input device such as gamepads");
|
||||
|
||||
styles [
|
||||
"property",
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
72
src/Permissions/Permissions.js
Normal file
@ -0,0 +1,72 @@
|
||||
import Gio from "gi://Gio";
|
||||
import Gtk from "gi://Gtk";
|
||||
|
||||
import { build } from "../../troll/src/main.js";
|
||||
|
||||
import Interface from "./Permissions.blp" with { type: "uri" };
|
||||
|
||||
import illustration from "./permissions.svg";
|
||||
|
||||
import {
|
||||
getFlatpakId,
|
||||
getFlatpakInfo,
|
||||
isDeviceInputOverrideAvailable,
|
||||
} from "../flatpak.js";
|
||||
|
||||
const device = isDeviceInputOverrideAvailable() ? "input" : "all";
|
||||
|
||||
const action_permissions = new Gio.SimpleAction({
|
||||
name: "permissions",
|
||||
parameter_type: null,
|
||||
});
|
||||
|
||||
export function Permissions({ window }) {
|
||||
const {
|
||||
dialog,
|
||||
picture_illustration,
|
||||
label_command,
|
||||
button_info,
|
||||
action_row_device,
|
||||
} = build(Interface);
|
||||
|
||||
picture_illustration.set_resource(illustration);
|
||||
|
||||
label_command.label = `flatpak override --user --share=network --socket=pulseaudio --device=${device} ${getFlatpakId()}`;
|
||||
action_row_device.title = `--input=${device}`;
|
||||
|
||||
button_info.connect("clicked", () => {
|
||||
new Gtk.UriLauncher({
|
||||
uri: "https://docs.flatpak.org/en/latest/sandbox-permissions.html",
|
||||
})
|
||||
.launch(window, null)
|
||||
.catch(console.error);
|
||||
});
|
||||
|
||||
action_permissions.connect("activate", () => {
|
||||
dialog.present(window);
|
||||
});
|
||||
|
||||
window.add_action(action_permissions);
|
||||
}
|
||||
|
||||
const missing_permissions = (() => {
|
||||
const flatpak_info = getFlatpakInfo();
|
||||
const shared = flatpak_info.get_string_list("Context", "shared");
|
||||
const sockets = flatpak_info.get_string_list("Context", "sockets");
|
||||
const devices = flatpak_info.get_string_list("Context", "devices");
|
||||
|
||||
return (
|
||||
!shared.includes("network") ||
|
||||
!sockets.includes("pulseaudio") ||
|
||||
!devices.includes(device)
|
||||
);
|
||||
})();
|
||||
|
||||
export function needsAdditionalPermissions({ demo }) {
|
||||
if (!demo["flatpak-finish-args"]) return false;
|
||||
return missing_permissions;
|
||||
}
|
||||
|
||||
export function showPermissionsDialog({ window }) {
|
||||
window.activate_action("permissions", null);
|
||||
}
|
568
src/Permissions/permissions.svg
Normal file
@ -0,0 +1,568 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="332"
|
||||
height="200"
|
||||
viewBox="0 0 332 200"
|
||||
version="1.1"
|
||||
id="svg5"
|
||||
inkscape:version="1.3.2 (091e20ef0f, 2023-11-25)"
|
||||
sodipodi:docname="permissions.svg"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview7"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="false"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="false"
|
||||
inkscape:deskcolor="#ffffff"
|
||||
inkscape:document-units="px"
|
||||
showgrid="false"
|
||||
inkscape:zoom="0.099784977"
|
||||
inkscape:cx="-661.42221"
|
||||
inkscape:cy="-65.140066"
|
||||
inkscape:current-layer="layer1"
|
||||
showguides="false"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1011"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1">
|
||||
<inkscape:grid
|
||||
id="grid1"
|
||||
units="px"
|
||||
originx="0"
|
||||
originy="0"
|
||||
spacingx="1"
|
||||
spacingy="1"
|
||||
empcolor="#0099e5"
|
||||
empopacity="0.30196078"
|
||||
color="#0099e5"
|
||||
opacity="0.14901961"
|
||||
empspacing="4"
|
||||
dotted="false"
|
||||
gridanglex="30"
|
||||
gridanglez="30"
|
||||
visible="false" />
|
||||
</sodipodi:namedview>
|
||||
<defs
|
||||
id="defs2">
|
||||
<inkscape:path-effect
|
||||
effect="fillet_chamfer"
|
||||
id="path-effect65"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
nodesatellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,21.13606,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,9.1490264,0,1"
|
||||
radius="0"
|
||||
unit="px"
|
||||
method="auto"
|
||||
mode="F"
|
||||
chamfer_steps="1"
|
||||
flexible="false"
|
||||
use_knot_distance="true"
|
||||
apply_no_radius="true"
|
||||
apply_with_radius="true"
|
||||
only_selected="false"
|
||||
hide_knots="false" />
|
||||
<linearGradient
|
||||
id="linearGradient63"
|
||||
inkscape:collect="always">
|
||||
<stop
|
||||
style="stop-color:#fbe47c;stop-opacity:0.6635828;"
|
||||
offset="0"
|
||||
id="stop63" />
|
||||
<stop
|
||||
style="stop-color:#87e8b5;stop-opacity:0.7638889;"
|
||||
offset="1"
|
||||
id="stop64" />
|
||||
</linearGradient>
|
||||
<inkscape:path-effect
|
||||
effect="fillet_chamfer"
|
||||
id="path-effect62"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
nodesatellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,4,0,1 @ F,0,0,1,0,4,0,1 @ F,0,0,1,0,4,0,1 @ F,0,1,1,0,4,0,1 @ F,0,0,1,0,4,0,1 @ F,0,0,1,0,4,0,1 @ F,0,0,1,0,4,0,1 @ F,0,0,1,0,4,0,1 @ F,0,0,1,0,0,0,1"
|
||||
radius="0"
|
||||
unit="px"
|
||||
method="auto"
|
||||
mode="F"
|
||||
chamfer_steps="1"
|
||||
flexible="false"
|
||||
use_knot_distance="true"
|
||||
apply_no_radius="true"
|
||||
apply_with_radius="true"
|
||||
only_selected="false"
|
||||
hide_knots="false" />
|
||||
<inkscape:path-effect
|
||||
effect="fillet_chamfer"
|
||||
id="path-effect60"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
nodesatellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,2,0,1 @ F,0,1,1,0,2,0,1"
|
||||
radius="0"
|
||||
unit="px"
|
||||
method="auto"
|
||||
mode="F"
|
||||
chamfer_steps="1"
|
||||
flexible="false"
|
||||
use_knot_distance="true"
|
||||
apply_no_radius="true"
|
||||
apply_with_radius="true"
|
||||
only_selected="false"
|
||||
hide_knots="false" />
|
||||
<inkscape:path-effect
|
||||
effect="fillet_chamfer"
|
||||
id="path-effect58"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
nodesatellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,6,0,1 @ F,0,1,1,0,6,0,1"
|
||||
radius="0"
|
||||
unit="px"
|
||||
method="auto"
|
||||
mode="F"
|
||||
chamfer_steps="1"
|
||||
flexible="false"
|
||||
use_knot_distance="true"
|
||||
apply_no_radius="true"
|
||||
apply_with_radius="true"
|
||||
only_selected="false"
|
||||
hide_knots="false" />
|
||||
<inkscape:path-effect
|
||||
effect="fillet_chamfer"
|
||||
id="path-effect56"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
nodesatellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,4,0,1 @ F,0,0,1,0,4,0,1 @ F,0,0,1,0,4,0,1 @ F,0,1,1,0,4,0,1 @ F,0,0,1,0,4,0,1 @ F,0,0,1,0,4,0,1 @ F,0,0,1,0,4,0,1 @ F,0,0,1,0,4,0,1 @ F,0,0,1,0,0,0,1"
|
||||
radius="0"
|
||||
unit="px"
|
||||
method="auto"
|
||||
mode="F"
|
||||
chamfer_steps="1"
|
||||
flexible="false"
|
||||
use_knot_distance="true"
|
||||
apply_no_radius="true"
|
||||
apply_with_radius="true"
|
||||
only_selected="false"
|
||||
hide_knots="false" />
|
||||
<linearGradient
|
||||
id="linearGradient26"
|
||||
inkscape:collect="always">
|
||||
<stop
|
||||
style="stop-color:#2177df;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop26" />
|
||||
<stop
|
||||
style="stop-color:#1a5fb4;stop-opacity:1;"
|
||||
offset="0.09090688"
|
||||
id="stop28" />
|
||||
<stop
|
||||
style="stop-color:#1a5fb4;stop-opacity:1;"
|
||||
offset="0.9090907"
|
||||
id="stop29" />
|
||||
<stop
|
||||
style="stop-color:#15498a;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop27" />
|
||||
</linearGradient>
|
||||
<inkscape:path-effect
|
||||
effect="fillet_chamfer"
|
||||
id="path-effect23"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
nodesatellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,4,0,1 @ F,0,0,1,0,4,0,1 @ F,0,0,1,0,4,0,1 @ F,0,1,1,0,4,0,1 @ F,0,0,1,0,4,0,1 @ F,0,0,1,0,4,0,1 @ F,0,0,1,0,4,0,1 @ F,0,0,1,0,4,0,1 @ F,0,0,1,0,0,0,1"
|
||||
radius="0"
|
||||
unit="px"
|
||||
method="auto"
|
||||
mode="F"
|
||||
chamfer_steps="1"
|
||||
flexible="false"
|
||||
use_knot_distance="true"
|
||||
apply_no_radius="true"
|
||||
apply_with_radius="true"
|
||||
only_selected="false"
|
||||
hide_knots="false" />
|
||||
<linearGradient
|
||||
id="linearGradient5"
|
||||
inkscape:collect="always">
|
||||
<stop
|
||||
style="stop-color:#5e5c64;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop5" />
|
||||
<stop
|
||||
style="stop-color:#4d4c50;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop6" />
|
||||
</linearGradient>
|
||||
<inkscape:path-effect
|
||||
effect="fillet_chamfer"
|
||||
id="path-effect5"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
nodesatellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,2,0,1 @ F,0,1,1,0,2,0,1"
|
||||
radius="0"
|
||||
unit="px"
|
||||
method="auto"
|
||||
mode="F"
|
||||
chamfer_steps="1"
|
||||
flexible="false"
|
||||
use_knot_distance="true"
|
||||
apply_no_radius="true"
|
||||
apply_with_radius="true"
|
||||
only_selected="false"
|
||||
hide_knots="false" />
|
||||
<inkscape:path-effect
|
||||
effect="fillet_chamfer"
|
||||
id="path-effect3"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
nodesatellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,6,0,1 @ F,0,1,1,0,6,0,1"
|
||||
radius="0"
|
||||
unit="px"
|
||||
method="auto"
|
||||
mode="F"
|
||||
chamfer_steps="1"
|
||||
flexible="false"
|
||||
use_knot_distance="true"
|
||||
apply_no_radius="true"
|
||||
apply_with_radius="true"
|
||||
only_selected="false"
|
||||
hide_knots="false" />
|
||||
<inkscape:path-effect
|
||||
effect="fillet_chamfer"
|
||||
id="path-effect2"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
nodesatellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,8,0,1 @ F,0,0,1,0,8.2101528,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1"
|
||||
radius="0"
|
||||
unit="px"
|
||||
method="auto"
|
||||
mode="F"
|
||||
chamfer_steps="1"
|
||||
flexible="false"
|
||||
use_knot_distance="true"
|
||||
apply_no_radius="true"
|
||||
apply_with_radius="true"
|
||||
only_selected="false"
|
||||
hide_knots="false" />
|
||||
<inkscape:path-effect
|
||||
effect="fillet_chamfer"
|
||||
id="path-effect211"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
nodesatellites_param="F,0,0,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1"
|
||||
radius="0"
|
||||
unit="px"
|
||||
method="auto"
|
||||
mode="F"
|
||||
chamfer_steps="1"
|
||||
flexible="false"
|
||||
use_knot_distance="true"
|
||||
apply_no_radius="true"
|
||||
apply_with_radius="true"
|
||||
only_selected="false"
|
||||
hide_knots="false" />
|
||||
<inkscape:path-effect
|
||||
effect="fillet_chamfer"
|
||||
id="path-effect157"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
nodesatellites_param="F,0,0,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1"
|
||||
radius="0"
|
||||
unit="px"
|
||||
method="auto"
|
||||
mode="F"
|
||||
chamfer_steps="1"
|
||||
flexible="false"
|
||||
use_knot_distance="true"
|
||||
apply_no_radius="true"
|
||||
apply_with_radius="true"
|
||||
only_selected="false"
|
||||
hide_knots="false" />
|
||||
<inkscape:path-effect
|
||||
effect="fillet_chamfer"
|
||||
id="path-effect102"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
nodesatellites_param="F,0,0,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1 @ F,0,1,1,0,12.476317,0,1"
|
||||
radius="0"
|
||||
unit="px"
|
||||
method="auto"
|
||||
mode="F"
|
||||
chamfer_steps="1"
|
||||
flexible="false"
|
||||
use_knot_distance="true"
|
||||
apply_no_radius="true"
|
||||
apply_with_radius="true"
|
||||
only_selected="false"
|
||||
hide_knots="false" />
|
||||
<inkscape:path-effect
|
||||
effect="fillet_chamfer"
|
||||
id="path-effect39"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
nodesatellites_param="F,0,0,1,0,3.414062,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1"
|
||||
radius="0"
|
||||
unit="px"
|
||||
method="auto"
|
||||
mode="F"
|
||||
chamfer_steps="1"
|
||||
flexible="false"
|
||||
use_knot_distance="true"
|
||||
apply_no_radius="true"
|
||||
apply_with_radius="true"
|
||||
only_selected="false"
|
||||
hide_knots="false" />
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath31">
|
||||
<path
|
||||
style="opacity:1;fill:#865e3c;fill-opacity:1;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:3.57621, 3.57621"
|
||||
d="m 104.57142,32 c -2.53257,0 -4.571424,1.784002 -4.571424,4 V 82 H 227.99999 V 36 c 0,-2.215998 -2.03886,-4 -4.57143,-4 z"
|
||||
id="path32" />
|
||||
</clipPath>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath33">
|
||||
<path
|
||||
style="opacity:1;fill:#865e3c;fill-opacity:1;stroke-width:1.99999;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:3.57621, 3.57621"
|
||||
d="m 99.999997,90 v 46 c 0,2.216 2.102573,4 4.714283,4 h 122.57143 c 2.61171,0 4.71428,-1.784 4.71428,-4 V 90 Z"
|
||||
id="path34" />
|
||||
</clipPath>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient5"
|
||||
id="linearGradient6"
|
||||
x1="176.92285"
|
||||
y1="156"
|
||||
x2="176.92285"
|
||||
y2="164"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(1.4984166,0,0,1.4984166,-49.616298,-72.451818)" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient26"
|
||||
id="linearGradient27"
|
||||
x1="100"
|
||||
y1="120.00011"
|
||||
x2="100"
|
||||
y2="164"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(1.4984166,0,0,1.4984166,-49.616298,-72.451818)" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient63"
|
||||
id="linearGradient65"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(-35.382733,-4.2152026)"
|
||||
x1="248.07971"
|
||||
y1="113.07767"
|
||||
x2="85.016251"
|
||||
y2="113.07767" />
|
||||
</defs>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<path
|
||||
id="circle65"
|
||||
style="fill:url(#linearGradient65);stroke:none;stroke-width:1.46117;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 131.16602,27.330078 c -45.029881,-8.12e-4 -81.534017,36.503321 -81.533208,81.533202 2.7e-4,45.02912 36.504089,81.53206 81.533208,81.53125 8.38262,-0.006 16.67054,-1.30441 24.58233,-3.81292 11.09609,-3.51812 26.47255,-2.63586 37.20566,1.85535 9.07487,3.79734 18.86926,5.80785 28.84287,5.84038 41.61705,-7.5e-4 75.35384,-33.73841 75.35351,-75.35546 -7.4e-4,-41.616289 -33.73722,-75.352772 -75.35351,-75.353521 -8.35948,0.02724 -16.6344,1.44503 -24.49097,4.175374 -4.76994,1.657664 -11.30579,0.572701 -15.25124,-2.579772 -14.3779,-11.488134 -32.30568,-17.832988 -50.88865,-17.833883 z"
|
||||
transform="matrix(-1.0569476,0,0,1.0569476,354.87042,-13.797304)" />
|
||||
<path
|
||||
style="fill:none;fill-opacity:1;stroke:#1a5fb4;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 85.947825,152 H 64 a 4,4 135 0 0 -4,4 4,4 45 0 0 4,4 h 4 a 4,4 45 0 1 4,4 4,4 135 0 1 -4,4 H 56 a 4,4 135 0 0 -4,4 4,4 45 0 0 4,4 l 28,0 a 4,4 135 0 0 4,-4 4,4 135 0 1 4,-4 h 20"
|
||||
id="path23"
|
||||
sodipodi:nodetypes="cccccccccc"
|
||||
transform="matrix(1.4984165,0,0,1.4984165,-49.616294,-72.451812)" />
|
||||
<g
|
||||
id="g21"
|
||||
transform="matrix(1.4984165,0,0,1.4984165,-291.25069,-41.061959)"
|
||||
style="fill:#5e5c64">
|
||||
<path
|
||||
id="path16"
|
||||
style="color:#000000;fill:#5e5c64;stroke-linecap:square;-inkscape-stroke:none"
|
||||
d="m 296.00007,60.838426 -15.15429,45.460934 a 1.0001,1.0001 0 0 0 -0.002,0.008 l -10.51757,31.55664 -0.72461,2.16992 -0.31641,0.94726 1.89844,0.63282 0.3164,-0.94922 0.61719,-1.85156 23.88281,-19.40625 23.88282,19.40625 0.18554,0.55468 0.5,-0.16601 a 1,1 0 0 0 0.86328,-0.28906 l 0.53321,-0.17774 -0.31446,-0.94726 -10.49414,-31.48047 v -0.004 a 1.0001,1.0001 0 0 0 -0.004,-0.008 l -0.006,-0.0195 a 1,1 0 0 0 -0.004,-0.008 z m 0,6.326172 6.58204,19.748047 h -13.16407 z m -5.23046,21.748047 h 10.46093 l -5.23047,4.40625 z m -2.25586,0.712891 5.93359,5 -10.56836,8.902344 z m 14.97461,0 4.63281,13.904294 -10.56836,-8.904294 z m -7.48829,6.308593 11.45704,9.650391 h -22.91407 z m -11.3789,11.650391 h 22.75781 l -11.37891,9.24609 z m -2.32422,0.6875 12.11719,9.84766 -21.11914,17.16015 z m 27.40625,0 9.00195,27.00781 -21.11914,-17.16015 z" />
|
||||
</g>
|
||||
<circle
|
||||
style="fill:#deddda;fill-opacity:1;stroke:none;stroke-width:1.49841;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="circle82"
|
||||
cx="152.28058"
|
||||
cy="56.836697"
|
||||
r="15.564472" />
|
||||
<path
|
||||
id="path1"
|
||||
style="fill:#3d3846;stroke-width:2;stroke-dasharray:2, 2"
|
||||
d="m 278,104 h 55.8457 l 8.80509,-38.153666 A 4.7730278,4.7730278 51.497589 0 0 338,60 l -44,0 a 7.5166441,7.5166441 141.40213 0 0 -7.32973,5.850797 z"
|
||||
transform="matrix(1.4984165,0,0,1.4984165,-217.43895,5.4658483)" />
|
||||
<path
|
||||
id="path2"
|
||||
style="fill:url(#linearGradient6);stroke-width:2.99683;stroke-dasharray:2.99683, 2.99683"
|
||||
d="m 148.1747,161.30117 c 0,6.62041 5.3669,11.98733 11.98733,11.98733 h 107.57109 c 7.20105,0 13.44901,-4.9706 15.06784,-11.98733 z"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<path
|
||||
id="path3"
|
||||
style="fill:#77767b;stroke-width:2.99683;stroke-dasharray:2.99683, 2.99683"
|
||||
d="m 232.08602,161.30117 c 0,6.62041 5.3669,11.98733 11.98733,11.98733 h 23.65977 c 7.20105,0 13.44901,-4.9706 15.06784,-11.98733 z"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<path
|
||||
id="path4"
|
||||
style="fill:#99c1f1;stroke-width:2;stroke-dasharray:2, 2"
|
||||
d="m 282,104 h 47.8457 l 8.70812,-38.050404 A 1.5939923,1.5939923 51.445289 0 0 337,64 h -44 a 2.5,2.5 141.34019 0 0 -2.43902,1.95122 z"
|
||||
sodipodi:nodetypes="ccccc"
|
||||
transform="matrix(1.4984165,0,0,1.4984165,-217.43895,5.4658483)" />
|
||||
<rect
|
||||
style="fill:url(#linearGradient27);stroke:none;stroke-width:2.99683;stroke-linecap:round;stroke-dasharray:none"
|
||||
id="rect7"
|
||||
width="59.936661"
|
||||
height="65.930313"
|
||||
x="70.257019"
|
||||
y="107.35817"
|
||||
ry="6.3252244"
|
||||
rx="6.3252244" />
|
||||
<rect
|
||||
style="fill:#62a0ea;fill-opacity:1;stroke:none;stroke-width:2.99683;stroke-linecap:round;stroke-dasharray:none"
|
||||
id="rect6"
|
||||
width="47.949329"
|
||||
height="65.930313"
|
||||
x="88.238022"
|
||||
y="107.35818"
|
||||
ry="6.3252249"
|
||||
rx="6.3252244" />
|
||||
<circle
|
||||
style="fill:#1a5fb4;fill-opacity:1;stroke:none;stroke-width:2.99683;stroke-linecap:round;stroke-dasharray:none"
|
||||
id="circle7"
|
||||
cx="112.21269"
|
||||
cy="155.30748"
|
||||
r="11.987332" />
|
||||
<circle
|
||||
style="fill:#1a5fb4;fill-opacity:1;stroke:none;stroke-width:2.99683;stroke-linecap:round;stroke-dasharray:none"
|
||||
id="circle8"
|
||||
cx="112.21269"
|
||||
cy="125.33916"
|
||||
r="11.987332" />
|
||||
<circle
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2.99683;stroke-linecap:round;stroke-dasharray:none"
|
||||
id="path8"
|
||||
cx="112.21269"
|
||||
cy="125.33916"
|
||||
r="4.4952497" />
|
||||
<circle
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2.99683;stroke-linecap:round;stroke-dasharray:none"
|
||||
id="circle9"
|
||||
cx="112.21269"
|
||||
cy="155.30748"
|
||||
r="4.4952497" />
|
||||
<circle
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.49841;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path22"
|
||||
cx="152.28058"
|
||||
cy="54.836697"
|
||||
r="15.564472" />
|
||||
<circle
|
||||
style="fill:#77767b;fill-opacity:1;stroke:none;stroke-width:2.99683;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="circle22"
|
||||
cx="152.28058"
|
||||
cy="54.836697"
|
||||
r="3.1248076" />
|
||||
<rect
|
||||
style="fill:#f6f5f4;fill-opacity:1;stroke:none;stroke-width:1.49841;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect24"
|
||||
width="14.984165"
|
||||
height="2.9968331"
|
||||
x="115.20953"
|
||||
y="177.78374"
|
||||
ry="1.4984165"
|
||||
rx="1.4984165" />
|
||||
<rect
|
||||
style="fill:#1a5fb4;fill-opacity:1;stroke:none;stroke-width:1.49841;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect23"
|
||||
width="13.485737"
|
||||
height="5.9936943"
|
||||
x="106.21901"
|
||||
y="176.28529"
|
||||
ry="2.9968472" />
|
||||
<rect
|
||||
style="fill:#c0bfbc;fill-opacity:1;stroke:none;stroke-width:1.49841;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect25"
|
||||
width="1.4984146"
|
||||
height="2.9968281"
|
||||
x="122.70161"
|
||||
y="177.78374" />
|
||||
<rect
|
||||
style="fill:#c0bfbc;fill-opacity:1;stroke:none;stroke-width:1.49841;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect26"
|
||||
width="1.4984146"
|
||||
height="2.9968281"
|
||||
x="125.69843"
|
||||
y="177.78374" />
|
||||
<circle
|
||||
style="fill:#bf61ca;fill-opacity:0.48627451;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:0.443622"
|
||||
id="path71"
|
||||
cx="150.07011"
|
||||
cy="33.371632"
|
||||
r="1.7915844" />
|
||||
<circle
|
||||
style="fill:#bf61ca;fill-opacity:0.48627451;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:0.443622"
|
||||
id="circle71"
|
||||
cx="150.07011"
|
||||
cy="26.488079"
|
||||
r="1.7915844" />
|
||||
<circle
|
||||
style="fill:#bf61ca;fill-opacity:0.48627451;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:0.443622"
|
||||
id="circle72"
|
||||
cx="150.07011"
|
||||
cy="19.604527"
|
||||
r="1.7915844" />
|
||||
<circle
|
||||
style="fill:#bf61ca;fill-opacity:0.48627451;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:0.443622"
|
||||
id="circle77"
|
||||
cx="150.07011"
|
||||
cy="12.720974"
|
||||
r="1.7915844" />
|
||||
<circle
|
||||
style="fill:#c061cb;fill-opacity:0.484565;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:0.443622"
|
||||
id="circle78"
|
||||
cx="154.56282"
|
||||
cy="30.071247"
|
||||
r="1.7915844" />
|
||||
<circle
|
||||
style="fill:#c061cb;fill-opacity:0.484565;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:0.443622"
|
||||
id="circle79"
|
||||
cx="154.56282"
|
||||
cy="23.187695"
|
||||
r="1.7915844" />
|
||||
<circle
|
||||
style="fill:#c061cb;fill-opacity:0.484565;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:0.443622"
|
||||
id="circle80"
|
||||
cx="154.56282"
|
||||
cy="16.304142"
|
||||
r="1.7915844" />
|
||||
<circle
|
||||
style="fill:#c061cb;fill-opacity:0.484565;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:0.443622"
|
||||
id="circle81"
|
||||
cx="154.56282"
|
||||
cy="9.4205904"
|
||||
r="1.7915844" />
|
||||
<g
|
||||
fill="#222222"
|
||||
id="g2"
|
||||
transform="matrix(1.7236266,0,-0.3679857,1.7236266,234.34039,117.54652)"
|
||||
style="fill:#62a0ea;stroke-width:0.580172">
|
||||
<path
|
||||
d="M 9.492188,0.140625 C 8.640625,-0.0234375 7.769531,-0.0429688 6.917969,0.0742188 5.21875,0.304688 3.589844,1.082031 2.316406,2.367188 -0.230469,4.933594 -0.734375,8.90625 1.085938,12.03125 c 1.824218,3.121094 5.53125,4.636719 9.019531,3.683594 3.488281,-0.949219 5.90625,-4.132813 5.890625,-7.75 0,-0.550782 -0.453125,-1 -1.003906,-0.996094 -0.550782,0.00391 -0.996094,0.453125 -0.996094,1.003906 0.01563,2.722656 -1.792969,5.097656 -4.417969,5.816406 C 6.953125,14.503906 4.1875,13.371094 2.816406,11.023438 1.445312,8.671875 1.820312,5.707031 3.738281,3.773438 5.652344,1.84375 8.613281,1.4375 10.976562,2.789062 11.453125,3.0625 12.066406,2.898438 12.339844,2.417969 12.613281,1.9375 12.449219,1.328125 11.96875,1.050781 11.183594,0.605469 10.347656,0.300781 9.492188,0.140625 Z m 0,0"
|
||||
id="path1-6"
|
||||
style="fill:#62a0ea;stroke-width:0.580172" />
|
||||
<path
|
||||
d="M 15.753906,3.65625 C 15.929688,3.457031 16.015625,3.195312 16,2.933594 15.980469,2.667969 15.859375,2.421875 15.660156,2.246094 15.460938,2.070312 15.199219,1.980469 14.933594,2 14.667969,2.015625 14.421875,2.140625 14.246094,2.339844 L 7.949219,9.535156 5.707031,7.289062 C 5.316406,6.898438 4.683594,6.898438 4.292969,7.289062 4.105469,7.476562 4,7.734375 4,8 4,8.265625 4.105469,8.519531 4.292969,8.707031 l 3,3 C 7.488281,11.902344 7.757812,12.007812 8.035156,12 8.3125,11.988281 8.570312,11.867188 8.753906,11.65625 Z m 0,0"
|
||||
id="path2-7"
|
||||
style="fill:#62a0ea;stroke-width:0.580172" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 24 KiB |
126
src/Previewer/DBusPreviewer.js
Normal file
@ -0,0 +1,126 @@
|
||||
import Gio from "gi://Gio";
|
||||
|
||||
import previewer_xml from "./previewer.xml" with { type: "string" };
|
||||
import { buildRuntimePath } from "../util.js";
|
||||
|
||||
const PREVIEWER_TYPE_VALA = "vala";
|
||||
const PREVIEWER_TYPE_PYTHON = "python";
|
||||
|
||||
const nodeInfo = Gio.DBusNodeInfo.new_for_xml(previewer_xml);
|
||||
const interface_info = nodeInfo.interfaces[0];
|
||||
|
||||
const guid = Gio.dbus_generate_guid();
|
||||
const path = buildRuntimePath(`workbench_preview_dbus_socket_${Date.now()}`);
|
||||
const server = Gio.DBusServer.new_sync(
|
||||
`unix:path=${path}`,
|
||||
Gio.DBusServerFlags.AUTHENTICATION_REQUIRE_SAME_USER,
|
||||
guid,
|
||||
null,
|
||||
null,
|
||||
);
|
||||
|
||||
server.start();
|
||||
|
||||
let current_proxy = null;
|
||||
let current_sub_process = null;
|
||||
let current_type = null;
|
||||
|
||||
async function startProcess(type) {
|
||||
let executable_name;
|
||||
switch (type) {
|
||||
case PREVIEWER_TYPE_VALA:
|
||||
executable_name = "workbench-previewer-module";
|
||||
break;
|
||||
case PREVIEWER_TYPE_PYTHON:
|
||||
executable_name = "workbench-python-previewer";
|
||||
break;
|
||||
default:
|
||||
throw Error(`invalid dbus previewer type: ${type}`);
|
||||
}
|
||||
|
||||
current_sub_process = Gio.Subprocess.new(
|
||||
[executable_name, server.get_client_address()],
|
||||
Gio.SubprocessFlags.NONE,
|
||||
);
|
||||
current_type = type;
|
||||
|
||||
const connection = await new Promise((resolve) => {
|
||||
const _handler_id = server.connect(
|
||||
"new-connection",
|
||||
(_self, connection) => {
|
||||
server.disconnect(_handler_id);
|
||||
// FIXME: Just because the connection is established does not mean the Previewer has had time yet
|
||||
// to expose the object. Add a better way to detect if the object exists yet.
|
||||
setTimeout(() => resolve(connection), 100);
|
||||
return true;
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
console.debug(
|
||||
"new-connection",
|
||||
connection.get_peer_credentials().to_string(),
|
||||
);
|
||||
|
||||
connection.connect("closed", (_self, remote_peer_vanished, error) => {
|
||||
current_proxy = null;
|
||||
current_type = null;
|
||||
console.debug(
|
||||
"connection closed",
|
||||
connection.get_peer_credentials().to_string(),
|
||||
remote_peer_vanished,
|
||||
);
|
||||
if (error) console.error(error);
|
||||
});
|
||||
|
||||
const proxy = await Gio.DBusProxy.new(
|
||||
connection,
|
||||
Gio.DBusProxyFlags.NONE,
|
||||
interface_info,
|
||||
null,
|
||||
"/re/sonny/workbench/previewer_module", // object path
|
||||
"re.sonny.Workbench.previewer_module", // interface name
|
||||
null,
|
||||
);
|
||||
|
||||
proxy.connectSignal("CssParserError", (_proxy, _name_owner, ...args) => {
|
||||
dbus_previewer.onCssParserError?.(...args);
|
||||
});
|
||||
|
||||
proxy.connectSignal("WindowOpen", (_proxy, _name_owner, ...args) => {
|
||||
dbus_previewer.onWindowOpen?.(...args);
|
||||
});
|
||||
|
||||
return proxy;
|
||||
}
|
||||
|
||||
const dbus_previewer = {
|
||||
onCssParserError: null, // set in External.js
|
||||
onWindowOpen: null, // set in External.js
|
||||
async getProxy(type) {
|
||||
if (current_type !== type) {
|
||||
await this.stop();
|
||||
current_proxy = startProcess(type);
|
||||
}
|
||||
return current_proxy;
|
||||
},
|
||||
|
||||
async stop() {
|
||||
const connection = current_proxy?.["g-connection"];
|
||||
|
||||
if (connection) {
|
||||
await connection.close(null);
|
||||
}
|
||||
|
||||
if (current_sub_process) {
|
||||
// The vala process is set to exit when the connection close
|
||||
// but let's send a SIGTERM anyway just to be safe
|
||||
current_sub_process.send_signal(15);
|
||||
await current_sub_process.wait_async(null);
|
||||
}
|
||||
|
||||
current_sub_process = null;
|
||||
},
|
||||
};
|
||||
|
||||
export default dbus_previewer;
|
134
src/Previewer/External.js
Normal file
@ -0,0 +1,134 @@
|
||||
import Adw from "gi://Adw";
|
||||
import dbus_previewer from "./DBusPreviewer.js";
|
||||
|
||||
export default function External({ output, builder, onWindowChange }) {
|
||||
const stack = builder.get_object("stack_preview");
|
||||
let dbus_proxy;
|
||||
|
||||
dbus_previewer.onWindowOpen = ([open]) => {
|
||||
onWindowChange(open);
|
||||
};
|
||||
|
||||
dbus_previewer.onCssParserError = (error) => {
|
||||
builder
|
||||
.get_object("code_view_css")
|
||||
.handleDiagnostics([getCssDiagnostic(error)]);
|
||||
};
|
||||
|
||||
async function start(language) {
|
||||
if (language === "rust") {
|
||||
language = "vala"; // Rust uses the Vala previewer.
|
||||
}
|
||||
try {
|
||||
dbus_proxy = await dbus_previewer.getProxy(language);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
|
||||
async function open() {
|
||||
updateColorScheme();
|
||||
stack.set_visible_child_name("close_window");
|
||||
try {
|
||||
await dbus_proxy.OpenWindowAsync(output.get_width(), output.get_height());
|
||||
} catch (err) {
|
||||
console.debug(err);
|
||||
}
|
||||
}
|
||||
|
||||
async function close() {
|
||||
try {
|
||||
await dbus_proxy.CloseWindowAsync();
|
||||
} catch (err) {
|
||||
console.debug(err);
|
||||
return;
|
||||
}
|
||||
stack.set_visible_child_name("open_window");
|
||||
}
|
||||
|
||||
function stop() {
|
||||
close()
|
||||
.then(() => {
|
||||
return dbus_previewer.stop();
|
||||
})
|
||||
.catch(console.error);
|
||||
}
|
||||
|
||||
async function updateXML({ xml, target_id, original_id }) {
|
||||
try {
|
||||
await dbus_proxy.UpdateUiAsync(xml, target_id, original_id || "");
|
||||
} catch (err) {
|
||||
console.debug(err);
|
||||
}
|
||||
}
|
||||
|
||||
async function openInspector() {
|
||||
try {
|
||||
await dbus_proxy.EnableInspectorAsync(true);
|
||||
} catch (err) {
|
||||
console.debug(err);
|
||||
}
|
||||
}
|
||||
|
||||
async function closeInspector() {
|
||||
try {
|
||||
await dbus_proxy.EnableInspectorAsync(false);
|
||||
} catch (err) {
|
||||
console.debug(err);
|
||||
}
|
||||
}
|
||||
|
||||
const style_manager = Adw.StyleManager.get_default();
|
||||
function updateColorScheme() {
|
||||
try {
|
||||
dbus_proxy.ColorScheme = style_manager.color_scheme;
|
||||
} catch (err) {
|
||||
console.debug(err);
|
||||
}
|
||||
}
|
||||
style_manager.connect("notify::color-scheme", updateColorScheme);
|
||||
|
||||
return {
|
||||
start,
|
||||
stop,
|
||||
open,
|
||||
close,
|
||||
openInspector,
|
||||
closeInspector,
|
||||
updateXML,
|
||||
async updateCSS(css) {
|
||||
try {
|
||||
await dbus_proxy.UpdateCssAsync(css);
|
||||
} catch (err) {
|
||||
console.debug(err);
|
||||
}
|
||||
},
|
||||
async screenshot({ path }) {
|
||||
return dbus_proxy.ScreenshotAsync(path);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
// Converts a CssParserError to an LSP diagnostic object
|
||||
function getCssDiagnostic([
|
||||
message,
|
||||
start_line,
|
||||
start_char,
|
||||
end_line,
|
||||
end_char,
|
||||
]) {
|
||||
return {
|
||||
message,
|
||||
range: {
|
||||
start: {
|
||||
line: start_line,
|
||||
character: start_char,
|
||||
},
|
||||
end: {
|
||||
line: end_line,
|
||||
character: end_char,
|
||||
},
|
||||
},
|
||||
severity: 1,
|
||||
};
|
||||
}
|
298
src/Previewer/Internal.js
Normal file
@ -0,0 +1,298 @@
|
||||
import Gtk from "gi://Gtk";
|
||||
import * as postcss from "../lib/postcss.js";
|
||||
import Graphene from "gi://Graphene";
|
||||
import GObject from "gi://GObject";
|
||||
import Adw from "gi://Adw";
|
||||
|
||||
import { once } from "../../troll/src/async.js";
|
||||
import { build } from "../../troll/src/builder.js";
|
||||
|
||||
// eslint-disable-next-line no-restricted-globals
|
||||
const { addSignalMethods } = imports.signals;
|
||||
|
||||
export default function Internal({
|
||||
onWindowChange,
|
||||
output,
|
||||
builder,
|
||||
window,
|
||||
application,
|
||||
dropdown_preview_align,
|
||||
panel_ui,
|
||||
session,
|
||||
}) {
|
||||
const inline_css_scope_target = output.get_parent();
|
||||
inline_css_scope_target.name = `workbench_output-${session.id}`;
|
||||
|
||||
let css_scope_target = inline_css_scope_target;
|
||||
|
||||
const bus = {};
|
||||
addSignalMethods(bus);
|
||||
|
||||
const stack = builder.get_object("stack_preview");
|
||||
|
||||
let css_provider = null;
|
||||
let object_root = null;
|
||||
|
||||
async function open() {
|
||||
// The flow for internal preview is complicated after the window has been destroyed (on close)
|
||||
// Internal cannot rebuild it on its own so it calls panel_ui.update which will endup trigering internal.updateXML.
|
||||
// instead - Internal could work like the Vala previwer and take a XML string that it can parse whenever it needs
|
||||
if (!object_root) {
|
||||
try {
|
||||
await panel_ui.update();
|
||||
await once(bus, "object_root", { timeout: 5000 });
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
object_root.present();
|
||||
onWindowChange(true);
|
||||
}
|
||||
|
||||
async function close() {
|
||||
object_root?.close();
|
||||
}
|
||||
|
||||
function stop() {
|
||||
close();
|
||||
if (css_provider) {
|
||||
Gtk.StyleContext.remove_provider_for_display(
|
||||
output.get_display(),
|
||||
css_provider,
|
||||
);
|
||||
css_provider = null;
|
||||
}
|
||||
object_root?.destroy();
|
||||
object_root = null;
|
||||
}
|
||||
|
||||
function preview(object) {
|
||||
output.set_child(object);
|
||||
}
|
||||
|
||||
async function updateXML({ builder, object_preview, original_id, template }) {
|
||||
globalThis.workbench = {
|
||||
window,
|
||||
application,
|
||||
builder,
|
||||
template,
|
||||
resolve(path) {
|
||||
return session.file.resolve_relative_path(path).get_uri();
|
||||
},
|
||||
preview(object) {
|
||||
dropdown_preview_align.visible = false;
|
||||
dropdown_preview_align.selected = 0;
|
||||
preview(object);
|
||||
},
|
||||
build(params) {
|
||||
console.warn("workbench.build is experimental");
|
||||
return build(panel_ui.xml, params);
|
||||
},
|
||||
};
|
||||
|
||||
let obj;
|
||||
if (object_preview instanceof Gtk.Root) {
|
||||
obj = updateBuilderRoot(object_preview);
|
||||
} else {
|
||||
obj = updateBuilderNonRoot(object_preview);
|
||||
}
|
||||
|
||||
if (original_id) {
|
||||
builder.expose_object(original_id, obj);
|
||||
}
|
||||
}
|
||||
|
||||
function setObjectRoot(object) {
|
||||
object_root = object;
|
||||
object_root.connect("close-request", () => {
|
||||
object_root = null;
|
||||
onWindowChange(false);
|
||||
});
|
||||
bus.emit("object_root");
|
||||
}
|
||||
|
||||
function updateBuilderRoot(object_preview) {
|
||||
stack.set_visible_child_name("open_window");
|
||||
|
||||
if (!object_root) {
|
||||
setObjectRoot(object_preview);
|
||||
} else if (
|
||||
object_root.constructor.$gtype !== object_preview.constructor.$gtype
|
||||
) {
|
||||
object_root.destroy();
|
||||
setObjectRoot(object_preview);
|
||||
} else {
|
||||
for (const prop of object_root.constructor.list_properties()) {
|
||||
if (!(prop.flags & GObject.ParamFlags.WRITABLE)) continue;
|
||||
if (!(prop.flags & GObject.ParamFlags.READABLE)) continue;
|
||||
if (prop.flags & GObject.ParamFlags.CONSTRUCT_ONLY) continue;
|
||||
|
||||
const prop_name = prop.get_name();
|
||||
// AdwWindow and AdwApplicationWindow have child and titlebar properties but do not support setting them
|
||||
// "Using gtk_window_get_titlebar() and gtk_window_set_titlebar() is not supported and will result in a crash."
|
||||
// https://gnome.pages.gitlab.gnome.org/libadwaita/doc/1.6/class.Window.html
|
||||
// https://github.com/workbenchdev/Workbench/issues/130
|
||||
if (
|
||||
(object_preview instanceof Adw.Window ||
|
||||
object_preview instanceof Adw.ApplicationWindow) &&
|
||||
["child", "titlebar"].includes(prop_name)
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (
|
||||
[
|
||||
// The new window does not have "csd" at this time
|
||||
"css-classes",
|
||||
// Triggers
|
||||
// Gtk-CRITICAL Widget of type “GtkApplicationWindow” already has an accessible role of type “GTK_ACCESSIBLE_ROLE_WIDGET”
|
||||
"accessible-role",
|
||||
// These properties override current window size
|
||||
"default-width",
|
||||
"default-height",
|
||||
].includes(prop_name)
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const new_value = object_preview[prop_name];
|
||||
if (new_value instanceof Gtk.Widget) {
|
||||
// Remove parent widget to prevent
|
||||
// Can't set new parent 0x5649879daa40 on widget GtkHeaderBar 0x564987790d90, which already has parent GtkApplicationWindow 0x564988f31a40
|
||||
object_preview[prop_name] = null;
|
||||
}
|
||||
|
||||
const old_value = object_root[prop_name];
|
||||
if (!old_value !== new_value) {
|
||||
object_root[prop_name] = new_value;
|
||||
}
|
||||
}
|
||||
|
||||
// Toplevel windows returned by these functions will stay around
|
||||
// until the user explicitly destroys them with gtk_window_destroy().
|
||||
// https://docs.gtk.org/gtk4/class.Builder.html
|
||||
if (object_preview instanceof Gtk.Window) {
|
||||
object_preview.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
if (!object_root.name) {
|
||||
object_root.name = `workbench_output-${session.id}`;
|
||||
}
|
||||
|
||||
css_scope_target = object_root;
|
||||
|
||||
return object_root;
|
||||
}
|
||||
|
||||
function updateBuilderNonRoot(object_preview) {
|
||||
object_root?.destroy();
|
||||
object_root = null;
|
||||
css_scope_target = inline_css_scope_target;
|
||||
|
||||
stack.set_visible_child_name("inline");
|
||||
preview(object_preview);
|
||||
return object_preview;
|
||||
}
|
||||
|
||||
async function updateCSS(css) {
|
||||
if (css_provider) {
|
||||
Gtk.StyleContext.remove_provider_for_display(
|
||||
output.get_display(),
|
||||
css_provider,
|
||||
);
|
||||
css_provider = null;
|
||||
}
|
||||
|
||||
let style = css;
|
||||
if (!style) return;
|
||||
// Workaround https://github.com/workbenchdev/Workbench/issues/147
|
||||
if (style.match(/#$/g)) return;
|
||||
|
||||
try {
|
||||
style = scopeStylesheet(style, css_scope_target.name);
|
||||
} catch (err) {
|
||||
console.debug(err);
|
||||
// logError(err);
|
||||
}
|
||||
|
||||
css_provider = new Gtk.CssProvider();
|
||||
css_provider.load_from_string(style);
|
||||
Gtk.StyleContext.add_provider_for_display(
|
||||
output.get_display(),
|
||||
css_provider,
|
||||
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION,
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
async start(_language) {},
|
||||
open,
|
||||
close,
|
||||
stop,
|
||||
updateXML,
|
||||
updateCSS,
|
||||
async openInspector() {
|
||||
Gtk.Window.set_interactive_debugging(true);
|
||||
},
|
||||
async closeInspector() {
|
||||
Gtk.Window.set_interactive_debugging(false);
|
||||
},
|
||||
async screenshot({ path }) {
|
||||
return screenshot({ widget: object_root || output, path });
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
// We are using postcss because it's also a dependency of prettier
|
||||
// it would be great to keep the ast around and pass that to prettier
|
||||
// so there is no need to re-parse but that's not supported yet
|
||||
// https://github.com/prettier/prettier/issues/9114
|
||||
// We are not using https://github.com/pazams/postcss-scopify
|
||||
// because it's not compatible with postcss 8
|
||||
function scopeStylesheet(style, id) {
|
||||
const ast = postcss.parse(style);
|
||||
for (const node of ast.nodes) {
|
||||
if (node.selector === "window") {
|
||||
node.selector = `#${id}`;
|
||||
} else if (!node.selector.startsWith(":")) {
|
||||
node.selector = `#${id} ${node.selector}`;
|
||||
}
|
||||
}
|
||||
|
||||
let str = "";
|
||||
postcss.stringify(ast, (s) => {
|
||||
str += s;
|
||||
});
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
function screenshot({ widget, path }) {
|
||||
const paintable = new Gtk.WidgetPaintable({ widget });
|
||||
const width = widget.get_width();
|
||||
const height = widget.get_height();
|
||||
|
||||
const snapshot = Gtk.Snapshot.new();
|
||||
paintable.snapshot(snapshot, width, height);
|
||||
|
||||
const node = snapshot.to_node();
|
||||
|
||||
if (!node) {
|
||||
console.log("Could not get node snapshot", { width, height });
|
||||
return false;
|
||||
}
|
||||
|
||||
const renderer = widget.get_native().get_renderer();
|
||||
const rect = new Graphene.Rect({
|
||||
origin: new Graphene.Point({ x: 0, y: 0 }),
|
||||
size: new Graphene.Size({ width, height }),
|
||||
});
|
||||
const texture = renderer.render_texture(node, rect);
|
||||
|
||||
texture.save_to_png(path);
|
||||
|
||||
return true;
|
||||
}
|
486
src/Previewer/Previewer.js
Normal file
@ -0,0 +1,486 @@
|
||||
import Gtk from "gi://Gtk";
|
||||
import Gdk from "gi://Gdk";
|
||||
import GObject from "gi://GObject";
|
||||
import GLib from "gi://GLib";
|
||||
import Gio from "gi://Gio";
|
||||
import { gettext as _ } from "gettext";
|
||||
|
||||
import * as xml from "../langs/xml/xml.js";
|
||||
|
||||
import {
|
||||
encode,
|
||||
unstack,
|
||||
data_dir,
|
||||
getNowForFilename,
|
||||
ensureDir,
|
||||
makeDropdownFlat,
|
||||
} from "../util.js";
|
||||
|
||||
import Internal from "./Internal.js";
|
||||
import External from "./External.js";
|
||||
import { getClassNameType, registerClass } from "../overrides.js";
|
||||
|
||||
import { assertBuildable, detectCrash, isPreviewable } from "./utils.js";
|
||||
|
||||
/*
|
||||
Always default to in-process preview
|
||||
Switch to out-of-process preview when Vala is run
|
||||
Switch back to in-process preview if any of the following happens
|
||||
• A demo is loaded
|
||||
• The out-of-process preview Window closed
|
||||
• Switching language
|
||||
* A file is open
|
||||
*/
|
||||
|
||||
export default function Previewer({
|
||||
output,
|
||||
builder,
|
||||
panel_ui,
|
||||
window,
|
||||
application,
|
||||
term_console,
|
||||
settings,
|
||||
session,
|
||||
}) {
|
||||
let panel_code;
|
||||
|
||||
let current;
|
||||
let current_external_language = null;
|
||||
|
||||
const dropdown_preview_align = builder.get_object("dropdown_preview_align");
|
||||
makeDropdownFlat(dropdown_preview_align);
|
||||
|
||||
const internal = Internal({
|
||||
onWindowChange(open) {
|
||||
if (current !== internal) return;
|
||||
if (open) {
|
||||
stack.set_visible_child_name("close_window");
|
||||
} else {
|
||||
stack.set_visible_child_name("open_window");
|
||||
}
|
||||
},
|
||||
output,
|
||||
builder,
|
||||
window,
|
||||
application,
|
||||
dropdown_preview_align,
|
||||
panel_ui,
|
||||
session,
|
||||
});
|
||||
const external = External({
|
||||
onWindowChange(open) {
|
||||
if (current !== external) return;
|
||||
if (open) {
|
||||
stack.set_visible_child_name("close_window");
|
||||
} else {
|
||||
stack.set_visible_child_name("open_window");
|
||||
useInternal().catch(console.error);
|
||||
}
|
||||
},
|
||||
output,
|
||||
builder,
|
||||
panel_ui,
|
||||
session,
|
||||
});
|
||||
|
||||
const code_view_css = builder.get_object("code_view_css");
|
||||
|
||||
let handler_id_ui = null;
|
||||
let handler_id_css = null;
|
||||
let handler_id_button_open;
|
||||
let handler_id_button_close;
|
||||
|
||||
const stack = builder.get_object("stack_preview");
|
||||
const button_open = builder.get_object("button_open_preview_window");
|
||||
const button_close = builder.get_object("button_close_preview_window");
|
||||
|
||||
settings.bind(
|
||||
"preview-align",
|
||||
dropdown_preview_align,
|
||||
"selected",
|
||||
Gio.SettingsBindFlags.DEFAULT,
|
||||
);
|
||||
dropdown_preview_align.connect("notify::selected", setPreviewAlign);
|
||||
function setPreviewAlign() {
|
||||
const alignment =
|
||||
dropdown_preview_align.selected === 1 ? Gtk.Align.CENTER : Gtk.Align.FILL;
|
||||
output.halign = alignment;
|
||||
output.valign = alignment;
|
||||
}
|
||||
setPreviewAlign();
|
||||
|
||||
function start() {
|
||||
stop();
|
||||
if (handler_id_ui === null) {
|
||||
handler_id_ui = panel_ui.connect("updated", () => schedule_update());
|
||||
}
|
||||
if (handler_id_css === null) {
|
||||
handler_id_css = code_view_css.connect("changed", () =>
|
||||
schedule_update(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function stop() {
|
||||
if (handler_id_ui) {
|
||||
panel_ui.disconnect(handler_id_ui);
|
||||
handler_id_ui = null;
|
||||
}
|
||||
if (handler_id_css) {
|
||||
code_view_css.disconnect(handler_id_css);
|
||||
handler_id_css = null;
|
||||
}
|
||||
}
|
||||
|
||||
// Using this custom scope we make sure that previewing UI definitions
|
||||
// with signals doesn't fail - in addition, checkout registerSignals
|
||||
const BuilderScope = registerClass(
|
||||
{
|
||||
Implements: [Gtk.BuilderScope],
|
||||
},
|
||||
class extends GObject.Object {
|
||||
noop() {}
|
||||
// https://docs.gtk.org/gtk4/vfunc.BuilderScope.create_closure.html
|
||||
vfunc_create_closure(_builder, function_name, flags, _object) {
|
||||
if (
|
||||
panel_code.panel.visible &&
|
||||
panel_code.language === "JavaScript" &&
|
||||
flags & Gtk.BuilderClosureFlags.SWAPPED
|
||||
) {
|
||||
console.warn('Signal flag "swapped" is unsupported in JavaScript.');
|
||||
}
|
||||
return this[function_name] || this.noop;
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
settings.connect("changed::auto-preview", () => {
|
||||
if (settings.get_boolean("auto-preview")) schedule_update();
|
||||
});
|
||||
let symbols = null;
|
||||
async function update(force = false) {
|
||||
if (!(force || settings.get_boolean("auto-preview"))) return;
|
||||
let text = panel_ui.xml.trim();
|
||||
let target_id;
|
||||
let tree;
|
||||
let original_id;
|
||||
let template;
|
||||
|
||||
if (!text) {
|
||||
text = `<?xml version="1.0" encoding="UTF-8"?><interface><object class="GtkBox"></object></interface>";`;
|
||||
}
|
||||
|
||||
try {
|
||||
tree = xml.parse(text);
|
||||
({ target_id, text, original_id, template } = targetBuildable(tree));
|
||||
} catch (err) {
|
||||
// console.error(err);
|
||||
console.debug(err);
|
||||
}
|
||||
|
||||
if (!target_id) return;
|
||||
|
||||
try {
|
||||
assertBuildable(tree);
|
||||
} catch (err) {
|
||||
console.warn(err.message);
|
||||
return;
|
||||
}
|
||||
|
||||
if (settings.get_boolean("safe-mode")) {
|
||||
// console.time("detectCrash");
|
||||
const crashed = await detectCrash(text, target_id);
|
||||
if (crashed) return;
|
||||
// console.timeEnd("detectCrash");
|
||||
}
|
||||
|
||||
const builder = new Gtk.Builder();
|
||||
const scope = new BuilderScope();
|
||||
builder.set_scope(scope);
|
||||
|
||||
registerSignals({ tree, scope, symbols, template });
|
||||
|
||||
term_console.clear();
|
||||
|
||||
try {
|
||||
builder.add_from_string(text, -1);
|
||||
} catch (err) {
|
||||
if (err instanceof GLib.MarkupError || err instanceof Gtk.BuilderError) {
|
||||
console.warn(err.message);
|
||||
return;
|
||||
}
|
||||
console.error(err);
|
||||
return;
|
||||
}
|
||||
|
||||
const object_preview = builder.get_object(target_id);
|
||||
if (!object_preview) return;
|
||||
|
||||
if (!dropdown_preview_align.visible) {
|
||||
dropdown_preview_align.selected = template ? 1 : 0;
|
||||
}
|
||||
dropdown_preview_align.visible = !!template;
|
||||
|
||||
await current.updateXML({
|
||||
xml: text,
|
||||
builder,
|
||||
object_preview,
|
||||
target_id,
|
||||
original_id,
|
||||
template,
|
||||
});
|
||||
code_view_css.clearDiagnostics();
|
||||
await current.updateCSS(code_view_css.buffer.text);
|
||||
symbols = null;
|
||||
}
|
||||
|
||||
const schedule_update = unstack(update, console.error);
|
||||
|
||||
async function useExternal(language) {
|
||||
if (current !== external || language !== current_external_language) {
|
||||
await setPreviewer(external, language);
|
||||
}
|
||||
current_external_language = language;
|
||||
stack.set_visible_child_name("close_window");
|
||||
await update(true);
|
||||
}
|
||||
|
||||
async function useInternal() {
|
||||
if (current !== internal) {
|
||||
await setPreviewer(internal);
|
||||
}
|
||||
await update(true);
|
||||
}
|
||||
|
||||
async function setPreviewer(previewer, language) {
|
||||
if (handler_id_button_open) {
|
||||
button_open.disconnect(handler_id_button_open);
|
||||
}
|
||||
if (handler_id_button_close) {
|
||||
button_close.disconnect(handler_id_button_close);
|
||||
}
|
||||
|
||||
try {
|
||||
await current?.closeInspector();
|
||||
} catch {
|
||||
/* */
|
||||
}
|
||||
|
||||
try {
|
||||
await current?.stop();
|
||||
} catch {
|
||||
/* */
|
||||
}
|
||||
|
||||
current = previewer;
|
||||
|
||||
handler_id_button_open = button_open.connect("clicked", async () => {
|
||||
try {
|
||||
await current.open();
|
||||
stack.set_visible_child_name("close_window");
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
});
|
||||
|
||||
handler_id_button_close = button_close.connect("clicked", async () => {
|
||||
try {
|
||||
await current.close();
|
||||
stack.set_visible_child_name("open_window");
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
await current.start(language);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
|
||||
builder.get_object("button_screenshot").connect("clicked", () => {
|
||||
screenshot({ application, window, current }).catch(console.error);
|
||||
});
|
||||
|
||||
setPreviewer(internal);
|
||||
start();
|
||||
|
||||
return {
|
||||
start,
|
||||
stop,
|
||||
update,
|
||||
open() {
|
||||
return current.open();
|
||||
},
|
||||
close() {
|
||||
return current.close();
|
||||
},
|
||||
openInspector() {
|
||||
return current.openInspector();
|
||||
},
|
||||
useExternal,
|
||||
useInternal,
|
||||
setPanelCode(v) {
|
||||
panel_code = v;
|
||||
},
|
||||
setSymbols(_symbols) {
|
||||
symbols = _symbols;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function getTemplate(tree) {
|
||||
const template = tree.getChild("template");
|
||||
if (!template) return;
|
||||
|
||||
const { parent } = template.attrs;
|
||||
if (!parent) return;
|
||||
|
||||
if (!isPreviewable(parent)) return null;
|
||||
|
||||
template.attrs.class = getClassNameType(template.attrs.class);
|
||||
const original = tree.toString();
|
||||
tree.remove(template);
|
||||
|
||||
const target_id = makeWorkbenchTargetId();
|
||||
const el = new xml.Element("object", {
|
||||
class: parent,
|
||||
id: target_id,
|
||||
});
|
||||
template.children.forEach((child) => {
|
||||
el.cnode(child);
|
||||
});
|
||||
tree.cnode(el);
|
||||
|
||||
return {
|
||||
target_id: el.attrs.id,
|
||||
text: tree.toString(),
|
||||
original_id: undefined,
|
||||
template: encode(original),
|
||||
};
|
||||
}
|
||||
|
||||
function findPreviewable(tree) {
|
||||
for (const child of tree.getChildren("object")) {
|
||||
const class_name = child.attrs.class;
|
||||
if (!class_name) continue;
|
||||
|
||||
if (isPreviewable(class_name)) return child;
|
||||
}
|
||||
}
|
||||
|
||||
function targetBuildable(tree) {
|
||||
const template = getTemplate(tree);
|
||||
if (template) return template;
|
||||
|
||||
const child = findPreviewable(tree);
|
||||
if (!child) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const original_id = child.attrs.id;
|
||||
const target_id = makeWorkbenchTargetId();
|
||||
child.attrs.id = target_id;
|
||||
|
||||
return { target_id, text: tree.toString(), original_id, template: null };
|
||||
}
|
||||
|
||||
function makeSignalHandler(
|
||||
{ name, handler, after, id, type },
|
||||
{ symbols, template },
|
||||
) {
|
||||
return function (object, ...args) {
|
||||
const symbol = symbols?.[handler];
|
||||
const registered_handler = typeof symbol === "function";
|
||||
if (registered_handler) {
|
||||
symbol(object, ...args);
|
||||
}
|
||||
|
||||
const object_name = `${type}${id ? `$${id}` : ""}`;
|
||||
// const object_name = object.toString(); // [object instance wrapper GIName:Gtk.Button jsobj@0x2937abc5c4c0 native@0x55fbfe53f620]
|
||||
const handler_type = (() => {
|
||||
if (template) return "Template";
|
||||
if (registered_handler) return "Registered";
|
||||
return "Unregistered";
|
||||
})();
|
||||
const handler_when = after ? "after" : "for";
|
||||
|
||||
console.log(
|
||||
`${handler_type} handler "${handler}" triggered ${handler_when} signal "${name}" on ${object_name}`,
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
function registerSignals({ tree, scope, symbols, template }) {
|
||||
try {
|
||||
const signals = findSignals(tree);
|
||||
for (const signal of signals) {
|
||||
scope[signal.handler] = makeSignalHandler(signal, { symbols, template });
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
|
||||
function findSignals(tree, signals = []) {
|
||||
for (const object of tree.getChildren("object")) {
|
||||
const signal_elements = object.getChildren("signal");
|
||||
signals.push(
|
||||
...signal_elements.map((el) => {
|
||||
let id = object.attrs.id;
|
||||
if (id && isWorkbenchTargetId(id)) id = "";
|
||||
return {
|
||||
id,
|
||||
type: object.attrs.class,
|
||||
...el.attrs,
|
||||
};
|
||||
}),
|
||||
);
|
||||
|
||||
for (const child of object.getChildren("child")) {
|
||||
findSignals(child, signals);
|
||||
}
|
||||
}
|
||||
return signals;
|
||||
}
|
||||
|
||||
const target_id_prefix = "workbench_";
|
||||
function makeWorkbenchTargetId() {
|
||||
return target_id_prefix + GLib.uuid_string_random();
|
||||
}
|
||||
function isWorkbenchTargetId(id) {
|
||||
return id.startsWith(target_id_prefix);
|
||||
}
|
||||
|
||||
async function screenshot({ application, window, current }) {
|
||||
const file = data_dir
|
||||
.get_child("screenshots")
|
||||
.get_child(`${getNowForFilename()}.png`);
|
||||
|
||||
ensureDir(file.get_parent());
|
||||
|
||||
const success = await current.screenshot({ window, path: file.get_path() });
|
||||
if (!success) return;
|
||||
|
||||
const texture = Gdk.Texture.new_from_file(file);
|
||||
const clipboard = Gdk.Display.get_default().get_clipboard();
|
||||
|
||||
const value = new GObject.Value();
|
||||
value.init(Gdk.Texture);
|
||||
value.set_object(texture);
|
||||
|
||||
clipboard.set(value);
|
||||
|
||||
const notification = new Gio.Notification();
|
||||
const action = Gio.Action.print_detailed_name(
|
||||
"app.show-screenshot",
|
||||
new GLib.Variant("s", file.get_uri()),
|
||||
);
|
||||
notification.set_icon(new Gio.ThemedIcon({ name: "re.sonny.Workbench" }));
|
||||
notification.set_title(_("Workbench Screenshot captured"));
|
||||
notification.set_body(_("You can paste the image from the clipboard."));
|
||||
notification.set_default_action(action);
|
||||
notification.add_button(_("Show in Files"), action);
|
||||
application.send_notification(null, notification);
|
||||
}
|
14
src/Previewer/crasher.vala
Normal file
@ -0,0 +1,14 @@
|
||||
public void main (string[] args) {
|
||||
Adw.init ();
|
||||
|
||||
var builder = new Gtk.Builder ();
|
||||
var output = new Gtk.Window ();
|
||||
|
||||
try {
|
||||
builder.add_from_string (args[1], -1);
|
||||
var object = builder.get_object (args[2]) as Gtk.Widget;
|
||||
output.set_child (object);
|
||||
} catch (Error e) {
|
||||
GLib.error (e.message);
|
||||
}
|
||||
}
|
16
src/Previewer/meson.build
Normal file
@ -0,0 +1,16 @@
|
||||
executable('workbench-previewer-module',
|
||||
'previewer.vala',
|
||||
dependencies: [ dependency('gtksourceview-5'), dependency('gmodule-2.0'), dependency('libadwaita-1'), dependency('shumate-1.0'), dependency('webkitgtk-6.0'), libworkbench_vapi ],
|
||||
# vala_args: [ '--gresourcesdir=' + meson.current_build_dir() ],
|
||||
install: true,
|
||||
link_with: libworkbench,
|
||||
)
|
||||
|
||||
executable('workbench-crasher',
|
||||
'crasher.vala',
|
||||
dependencies: [ dependency('gio-2.0'), dependency('gmodule-2.0'), dependency('libadwaita-1') ],
|
||||
# vala_args: [ '--gresourcesdir=' + meson.current_build_dir() ],
|
||||
install: true,
|
||||
)
|
||||
|
||||
install_data('previewer.xml', install_dir: pkgdatadir)
|
263
src/Previewer/previewer.vala
Normal file
@ -0,0 +1,263 @@
|
||||
namespace Workbench {
|
||||
|
||||
[DBus (name = "re.sonny.Workbench.previewer_module")]
|
||||
public class Previewer : Object {
|
||||
construct {
|
||||
this.notify["ColorScheme"].connect (() => {
|
||||
this.style_manager.color_scheme = this.ColorScheme;
|
||||
});
|
||||
|
||||
// See application.js
|
||||
var icon_theme = Gtk.IconTheme.get_for_display(Gdk.Display.get_default());
|
||||
string[] resource_path = {"/org/gtk/libgtk/icons/", "/org/gnome/Adwaita/icons/", "/re/sonny/Workbench/icons/"};
|
||||
icon_theme.resource_path = resource_path;
|
||||
string [] search_path = {"/usr/share/icons", "/app/share/icons"};
|
||||
icon_theme.search_path = search_path;
|
||||
}
|
||||
|
||||
private void ensure_window () {
|
||||
if (this.window != null) {
|
||||
return;
|
||||
}
|
||||
var window = new Workbench.PreviewWindow ();
|
||||
this.set_window (window);
|
||||
}
|
||||
|
||||
private void set_window (Gtk.Window window) {
|
||||
this.window?.destroy ();
|
||||
this.window = window;
|
||||
this.window.close_request.connect (this.on_window_closed);
|
||||
}
|
||||
|
||||
private bool on_window_closed () {
|
||||
this.window_open (false);
|
||||
this.window = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool screenshot (string path) {
|
||||
Gtk.Widget widget = this.target;
|
||||
var paintable = new Gtk.WidgetPaintable (widget);
|
||||
int width = widget.get_width ();
|
||||
int height = widget.get_height ();
|
||||
var snapshot = new Gtk.Snapshot ();
|
||||
paintable.snapshot (snapshot, width, height);
|
||||
Gsk.RenderNode? node = snapshot.to_node ();
|
||||
if (node == null) {
|
||||
debug (@"Could not get node snapshot, width: $width, height: $height");
|
||||
return false;
|
||||
}
|
||||
Gsk.Renderer? renderer = widget.get_native () ? .get_renderer ();
|
||||
var rect = Graphene.Rect () {
|
||||
origin = Graphene.Point.zero (),
|
||||
size = Graphene.Size () {
|
||||
width = width,
|
||||
height = height
|
||||
}
|
||||
};
|
||||
Gdk.Texture texture = renderer.render_texture (node, rect);
|
||||
texture.save_to_png (path);
|
||||
return true;
|
||||
}
|
||||
|
||||
// This registers GObjects so that they can be found by GtkBuilder
|
||||
void ensure_types () {
|
||||
typeof (Shumate.SimpleMap).ensure ();
|
||||
typeof (WebKit.WebView).ensure ();
|
||||
}
|
||||
|
||||
public void update_ui (string content, string target_id, string original_id = "") {
|
||||
this.ensure_types ();
|
||||
this.builder = new Gtk.Builder.from_string (content, content.length);
|
||||
var target = this.builder.get_object (target_id) as Gtk.Widget;
|
||||
if (target == null) {
|
||||
stderr.printf (@"Widget with target_id='$target_id' could not be found.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
this.target = target;
|
||||
|
||||
if (original_id != "") {
|
||||
this.builder.expose_object (original_id, target);
|
||||
}
|
||||
|
||||
// Not a Root/Window
|
||||
if (!(target is Gtk.Root)) {
|
||||
this.ensure_window ();
|
||||
((Workbench.PreviewWindow) this.window).set_content (target);
|
||||
return;
|
||||
}
|
||||
|
||||
// Set target as window directly
|
||||
if (this.window == null || this.window.get_type () != target.get_type ()) {
|
||||
this.set_window (target as Gtk.Window);
|
||||
return;
|
||||
}
|
||||
|
||||
if (target is Adw.Window) {
|
||||
var child = ((Adw.Window) target).content;
|
||||
((Adw.Window) target).content = null;
|
||||
((Adw.Window) this.window).content = child;
|
||||
} else if (target is Adw.ApplicationWindow) {
|
||||
var child = ((Adw.ApplicationWindow) target).content;
|
||||
((Adw.ApplicationWindow) target).content = null;
|
||||
((Adw.ApplicationWindow) this.window).content = child;
|
||||
} else if (target is Gtk.Window) {
|
||||
var child = ((Gtk.Window) target).child;
|
||||
((Gtk.Window) target).child = null;
|
||||
this.window.child = child;
|
||||
}
|
||||
|
||||
// Toplevel windows returned by these functions will stay around
|
||||
// until the user explicitly destroys them with gtk_window_destroy().
|
||||
// https://docs.gtk.org/gtk4/class.Builder.html
|
||||
if (target is Gtk.Window) {
|
||||
((Gtk.Window) target).destroy ();
|
||||
}
|
||||
}
|
||||
|
||||
public void update_css (string content) {
|
||||
if (this.css != null)
|
||||
Gtk.StyleContext.remove_provider_for_display (Gdk.Display.get_default (), this.css);
|
||||
this.css = new Gtk.CssProvider ();
|
||||
this.css.parsing_error.connect ((self, section, error) => {
|
||||
var start = section.get_start_location ();
|
||||
var end = section.get_end_location ();
|
||||
this.css_parser_error (error.message, (int) start.lines, (int) start.line_chars, (int) end.lines, (int) end.line_chars);
|
||||
});
|
||||
this.css.load_from_string (content);
|
||||
Gtk.StyleContext.add_provider_for_display (
|
||||
Gdk.Display.get_default (),
|
||||
this.css,
|
||||
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
|
||||
}
|
||||
|
||||
public void run (string filename, string uri) {
|
||||
if (this.module != null) {
|
||||
this.module.close ();
|
||||
}
|
||||
|
||||
this.module = Module.open (filename, ModuleFlags.LAZY);
|
||||
if (this.module == null) {
|
||||
stderr.printf ("Module loading failed.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
this.reload_icons (uri);
|
||||
|
||||
void* function;
|
||||
|
||||
this.module.symbol ("set_base_uri", out function);
|
||||
var set_base_uri = (BaseUriFunction) function;
|
||||
set_base_uri (uri);
|
||||
|
||||
this.module.symbol ("set_builder", out function);
|
||||
var set_builder = (BuilderFunction) function;
|
||||
if (this.builder != null) {
|
||||
set_builder (this.builder);
|
||||
}
|
||||
|
||||
this.module.symbol ("set_window", out function);
|
||||
var set_window = (WindowFunction) function;
|
||||
if (this.window != null) {
|
||||
set_window (this.window);
|
||||
}
|
||||
|
||||
this.module.symbol ("main", out function);
|
||||
if (function == null) {
|
||||
stderr.printf (@"Function 'main' not found.\n");
|
||||
return;
|
||||
}
|
||||
var main_function = (MainFunction) function;
|
||||
main_function ();
|
||||
}
|
||||
|
||||
public async void reload_icons (string uri) {
|
||||
if (this.resource_icons != null) {
|
||||
this.resource_icons._unregister ();
|
||||
this.resource_icons = null;
|
||||
}
|
||||
try {
|
||||
this.resource_icons = Resource.load (File.new_for_uri(uri).get_child("icons.gresource").get_path());
|
||||
this.resource_icons._register ();
|
||||
} catch {}
|
||||
}
|
||||
|
||||
public void close_window () {
|
||||
if (this.window == null) {
|
||||
return;
|
||||
}
|
||||
this.window.close ();
|
||||
}
|
||||
|
||||
public async void open_window (int width, int height) {
|
||||
this.window.default_width = width;
|
||||
this.window.default_height = height;
|
||||
this.window.present ();
|
||||
this.window_open (true);
|
||||
}
|
||||
|
||||
public void enable_inspector (bool enabled) {
|
||||
Gtk.Window.set_interactive_debugging (enabled);
|
||||
}
|
||||
|
||||
public Adw.ColorScheme ColorScheme { get; set; default = Adw.ColorScheme.DEFAULT; }
|
||||
|
||||
public signal void window_open (bool open);
|
||||
|
||||
public signal void css_parser_error (string message, int start_line, int start_char, int end_line, int end_char);
|
||||
|
||||
[CCode (has_target = false)]
|
||||
private delegate void MainFunction ();
|
||||
|
||||
[CCode (has_target = false)]
|
||||
private delegate void BuilderFunction (Gtk.Builder builder);
|
||||
|
||||
[CCode (has_target = false)]
|
||||
private delegate void WindowFunction (Gtk.Window window);
|
||||
|
||||
[CCode (has_target = false)]
|
||||
private delegate void BaseUriFunction (string uri);
|
||||
|
||||
private Gtk.Window? window;
|
||||
private Gtk.Widget? target;
|
||||
private Gtk.CssProvider? css = null;
|
||||
private Module module;
|
||||
private Gtk.Builder? builder = null;
|
||||
private Adw.StyleManager style_manager = Adw.StyleManager.get_default ();
|
||||
private GLib.Resource? resource_icons = null;
|
||||
}
|
||||
|
||||
void main (string[] args) {
|
||||
if (!Module.supported ()) {
|
||||
stderr.printf ("This system does not support loadable modules.\n");
|
||||
Process.exit (1);
|
||||
}
|
||||
|
||||
var app_id = GLib.Environment.get_variable("FLATPAK_ID");
|
||||
var resource = Resource.load (@"/app/share/$app_id/re.sonny.Workbench.libworkbench.gresource");
|
||||
GLib.resources_register (resource);
|
||||
|
||||
|
||||
var loop = new MainLoop ();
|
||||
|
||||
Adw.init ();
|
||||
|
||||
var connection = new DBusConnection.for_address_sync (
|
||||
args[1],
|
||||
DBusConnectionFlags.AUTHENTICATION_CLIENT,
|
||||
null,
|
||||
null
|
||||
);
|
||||
|
||||
var previewer = new Previewer ();
|
||||
|
||||
connection.on_closed.connect (() => {
|
||||
loop.quit ();
|
||||
});
|
||||
|
||||
connection.register_object ("/re/sonny/workbench/previewer_module", previewer);
|
||||
|
||||
loop.run ();
|
||||
}
|
||||
}
|
40
src/Previewer/previewer.xml
Normal file
@ -0,0 +1,40 @@
|
||||
<node>
|
||||
<interface name="re.sonny.Workbench.previewer_module">
|
||||
<method name="UpdateUi">
|
||||
<arg type="s" name="content" direction="in"/>
|
||||
<arg type="s" name="target_id" direction="in"/>
|
||||
<arg type="s" name="original_id" direction="in"/>
|
||||
</method>
|
||||
<method name="UpdateCss">
|
||||
<arg type="s" name="content" direction="in"/>
|
||||
</method>
|
||||
<method name="Run">
|
||||
<arg type="s" name="filename" direction="in"/>
|
||||
<arg type="s" name="uri" direction="in"/>
|
||||
</method>
|
||||
<method name="CloseWindow">
|
||||
</method>
|
||||
<method name="OpenWindow">
|
||||
<arg type="i" name="width" direction="in"/>
|
||||
<arg type="i" name="height" direction="in"/>
|
||||
</method>
|
||||
<method name="Screenshot">
|
||||
<arg type="s" name="path" direction="in"/>
|
||||
<arg type="b" name="success" direction="out"/>
|
||||
</method>
|
||||
<method name="EnableInspector">
|
||||
<arg type="b" name="enabled" direction="in"/>
|
||||
</method>
|
||||
<signal name="WindowOpen">
|
||||
<arg type="b" name="open"/>
|
||||
</signal>
|
||||
<signal name="CssParserError">
|
||||
<arg type="s" name="message"/>
|
||||
<arg type="i" name="start_line"/>
|
||||
<arg type="i" name="start_char"/>
|
||||
<arg type="i" name="end_line"/>
|
||||
<arg type="i" name="end_char"/>
|
||||
</signal>
|
||||
<property type="i" name="ColorScheme" access="readwrite"/>
|
||||
</interface>
|
||||
</node>
|