Compare commits
904 Commits
Author | SHA1 | Date | |
---|---|---|---|
a714970344 | |||
77df714a08 | |||
693a6ba8a9 | |||
5a8122bc8a | |||
c382fc5050 | |||
d69a82d167 | |||
a30ca46fef | |||
a56226c08d | |||
87d34ba030 | |||
091917b765 | |||
aea09c1830 | |||
5e9eec61c5 | |||
a34f765681 | |||
2ae78fe6b8 | |||
33207f33e5 | |||
a487e102ef | |||
a6ffa99ceb | |||
d2aa02c259 | |||
563d76b90a | |||
b433585403 | |||
576f37171a | |||
0bd92a433d | |||
2d5f3421ba | |||
7956c6e6a1 | |||
1f7a56a451 | |||
0ea4583b20 | |||
4bccb435f7 | |||
749c2111d2 | |||
96991447f8 | |||
22f36a623b | |||
8a47793f48 | |||
5cfedf7343 | |||
13383e6232 | |||
165cd0c67e | |||
9c8886116e | |||
fc495b928e | |||
17644d4947 | |||
068ea80a45 | |||
7a86bbd6b9 | |||
78fffe0e01 | |||
7bf1a29c83 | |||
446ef4d7b7 | |||
ca3e3a43a5 | |||
2225be7af1 | |||
1ce863df96 | |||
68ae9864a9 | |||
8cd670b22a | |||
a36038a048 | |||
9d4b31fe4d | |||
3ea6d1e6bb | |||
1698c4a012 | |||
2c39e249f9 | |||
c486a9db94 | |||
816438fa79 | |||
5edd06c9b9 | |||
a114dc32e7 | |||
019bc34d90 | |||
0676d780ab | |||
96e23d99b2 | |||
15b1f95394 | |||
552b0d8165 | |||
faed492a87 | |||
0ce1738653 | |||
f5cabe6e94 | |||
f2e7a640f1 | |||
7fb057af66 | |||
c0b9329401 | |||
c04ddbb459 | |||
4aac4ef92d | |||
979b2b892a | |||
4c3f9910f7 | |||
9aef584966 | |||
e62d15ba85 | |||
adf97d9b5c | |||
2bb6c6ae27 | |||
0919eff0c5 | |||
e31279938b | |||
2655843b74 | |||
527d323ea7 | |||
5d40a48477 | |||
850fb54f52 | |||
6bb35c1a72 | |||
6569231ba6 | |||
a3a1c8a480 | |||
c90dfaa6e7 | |||
02cd0e1da3 | |||
0f9dde0c4e | |||
1e0cd48316 | |||
d959282c68 | |||
d513ad7713 | |||
b7da28285e | |||
dbaf406703 | |||
2cb467f22b | |||
9585e2276d | |||
a591d9f072 | |||
471a30ca3d | |||
205b94afe8 | |||
18caf554e9 | |||
67cdf16fe4 | |||
bdbe8371dd | |||
21a36eb9ee | |||
376b20b035 | |||
7ce41b52aa | |||
46f7831e7c | |||
dda29a5cb6 | |||
6e4f4595a2 | |||
cdbe1e513b | |||
ae15c9a656 | |||
d993ff3a9d | |||
13785a2438 | |||
4dfb77fcd7 | |||
70deffb665 | |||
41a148de28 | |||
886e071d7f | |||
8a58d664c3 | |||
71d1155f21 | |||
167c1d8fce | |||
e59ae37954 | |||
72a621ec8b | |||
d6ff930333 | |||
54a7ac81ea | |||
e5d985dbf1 | |||
9db91d89d6 | |||
1fa9bf12d5 | |||
61bab257eb | |||
2e90b351da | |||
801bd6c7a0 | |||
777ba40899 | |||
0d11c16ecf | |||
9c1628b977 | |||
953b362b34 | |||
8b40850a94 | |||
fc3a02cc41 | |||
80f2ff6757 | |||
6f790d167c | |||
ac7502074a | |||
50473255a8 | |||
910772d54e | |||
33f12f9ecc | |||
01fa4ef53a | |||
3858b0a0a0 | |||
da30afb121 | |||
086bcf372f | |||
236e7337e2 | |||
4cf223271f | |||
10180f4729 | |||
618dd33221 | |||
7356e5e52e | |||
a59d148eb5 | |||
34ce687bbd | |||
5e241ed566 | |||
dcb2b21e66 | |||
95669e174a | |||
aca7d6113d | |||
ef4b06a087 | |||
afa69c23c4 | |||
8229e71d0a | |||
93770e5821 | |||
cb8e28beb0 | |||
8c7e6055ff | |||
8450db55ac | |||
c63e2c85f1 | |||
d8fc11a688 | |||
847a29848d | |||
39f4372ee5 | |||
a8bbbea8ed | |||
91a8d05e45 | |||
3ecedd3a32 | |||
b6390d77dd | |||
e8f9e0f023 | |||
2bacb58fdd | |||
af8babfea2 | |||
1ee6274100 | |||
7448db5b98 | |||
983645403b | |||
7a9f382bee | |||
e59fd8469b | |||
008c886de9 | |||
c87fa30738 | |||
dd9d1299fa | |||
6a7d1bd95c | |||
dfe270d259 | |||
6deb0683b6 | |||
0a746f5bbe | |||
066408c317 | |||
90f7b229d1 | |||
c54e0b0e9d | |||
ea088ac828 | |||
29cf4d3e53 | |||
6d637eefd7 | |||
6310e96ac2 | |||
dbb1e31822 | |||
5376bc2dce | |||
57bd293df8 | |||
e570d46755 | |||
d37f284fce | |||
b716226889 | |||
1bd19cc1a0 | |||
ac8c9c5e85 | |||
057260c483 | |||
568ae32f81 | |||
ae605ff829 | |||
f25ddb1085 | |||
f175f973f0 | |||
c7e5fa490e | |||
61a29f7c67 | |||
50293fc654 | |||
a9ecadaf09 | |||
6e56107eb5 | |||
1f077beb65 | |||
8fff762156 | |||
cebded2526 | |||
13f53d730a | |||
8adcab1cab | |||
8cb5f442f9 | |||
96448d5237 | |||
30f01bb0ac | |||
3d0b397de2 | |||
e0de55d689 | |||
7637a98f07 | |||
95f94e0886 | |||
9a2367cf8e | |||
15fecb77c4 | |||
4f69bbabfb | |||
8351ed0513 | |||
c34b0a1aeb | |||
9bcd44d7e4 | |||
3403da8ce8 | |||
39c146329f | |||
8d0d0a7e9a | |||
61b3783dd4 | |||
da16428842 | |||
359c456577 | |||
b3d9c167e1 | |||
78398b220f | |||
a656fbbd7b | |||
e681cc8c97 | |||
03beec9c49 | |||
1600644be5 | |||
a3dd64eb4c | |||
b865cce44e | |||
dc42900c7f | |||
dcc3bd95fe | |||
61e63831aa | |||
5651c3b9ba | |||
a562557bca | |||
d890c05229 | |||
4340e1f7ed | |||
e2e4c68f85 | |||
3f6a3089f1 | |||
84a0c0fe56 | |||
5237b86cf5 | |||
473950e491 | |||
fd33610511 | |||
47ea4e01d2 | |||
16199cfcea | |||
8a4556e70c | |||
bfc2641637 | |||
ef7fdc2ef7 | |||
a8b427fd89 | |||
79c23e2e2a | |||
4070d4e691 | |||
7048156b46 | |||
c11acce579 | |||
f79551073e | |||
232758805b | |||
211d4e5538 | |||
374d8c590d | |||
c6c133ef9e | |||
817e86f5aa | |||
19e33d029d | |||
e3671ca809 | |||
1f3a2ab6fe | |||
dad3e89577 | |||
df9d3c4444 | |||
edc489c83d | |||
fb29af8011 | |||
516def7a3f | |||
b5cb8deb93 | |||
658083b4eb | |||
1441129355 | |||
2b87b26f00 | |||
741facc769 | |||
41a5bc72a1 | |||
9d5e93b879 | |||
32e0cb0fe8 | |||
a224259e74 | |||
c144f3a15d | |||
a3fa07463f | |||
aa20f2fa4d | |||
4a1399de59 | |||
0b8e5c12c3 | |||
445066776b | |||
6cb204c548 | |||
6ed6a525fd | |||
ba6dc9f136 | |||
98bc8d2a27 | |||
58d0e238e3 | |||
ae17d4380e | |||
f79b726f87 | |||
0f3c7b8c0f | |||
dac6f5af73 | |||
99fb074952 | |||
66ba26586f | |||
e27c4de108 | |||
f19a110953 | |||
626055d3eb | |||
9085c98c7f | |||
85e3148f23 | |||
60f8dd8228 | |||
c2e37a2c6e | |||
b4ad4819a5 | |||
d9f2c7cc42 | |||
15638d2767 | |||
5ecd20583b | |||
4c27d62796 | |||
90da72a8de | |||
8f50beb938 | |||
52527dd584 | |||
fc0faf5181 | |||
cd9589e562 | |||
a34bcee7a2 | |||
d011cdb37e | |||
af7c51b954 | |||
a65e71f3b1 | |||
89e899cc79 | |||
b37e823b57 | |||
8cb31daa48 | |||
a984778dfd | |||
008cbf543f | |||
61ee841431 | |||
e856d59235 | |||
32753d3395 | |||
7b11a04727 | |||
6d6c053e4f | |||
1008fdd371 | |||
ddc2b7437b | |||
b9c95ebb1e | |||
b16d02ec66 | |||
38fb36087a | |||
5dbbc2266f | |||
2a22001e02 | |||
214ff25995 | |||
f4768d99ff | |||
8792f9fe36 | |||
3d45bef910 | |||
3de6b33163 | |||
3f1c03ea51 | |||
a4063d636d | |||
92b5b76171 | |||
51d285b0b0 | |||
4d8afdd3ae | |||
13b21ad275 | |||
d90a43a6d8 | |||
6fd14e718d | |||
c79f043529 | |||
3a676c7151 | |||
0023710209 | |||
0756091e8c | |||
8144df0023 | |||
b2137e2622 | |||
39b30c8ae1 | |||
1c5d6316cc | |||
6d4d681898 | |||
7053fd1490 | |||
e7a49acac0 | |||
d76cfb6e2e | |||
538f08052d | |||
b6fed71c58 | |||
6c86f98b66 | |||
26797545c6 | |||
3ce8aa1f47 | |||
8b46698f50 | |||
47401e947c | |||
718cc9d530 | |||
b83d777144 | |||
cfb9acea34 | |||
53189830a1 | |||
67da22c135 | |||
7c7014a25f | |||
851f395ec9 | |||
a343cbd065 | |||
a2c042f715 | |||
a4a97f31cb | |||
5bd6a384ae | |||
943393dfa3 | |||
7089aa9c54 | |||
bd9e456bc5 | |||
ea82d066c9 | |||
bb8338a0f0 | |||
b24b65abcd | |||
2cc0523f9a | |||
a78f7f9601 | |||
b1cf3246ae | |||
24eb6f64db | |||
0c99eaf7bf | |||
8eb3376cf5 | |||
b863d5663d | |||
aeb4cb6a17 | |||
fd88e0b7f0 | |||
ea0d2d4d02 | |||
adff537013 | |||
19fc284884 | |||
5d9f85828d | |||
9f31637000 | |||
8e811b913e | |||
269254796d | |||
46995cbd54 | |||
380488528f | |||
aca863f436 | |||
a1ec25fd79 | |||
3e9d6d5895 | |||
719370f6b0 | |||
2780497d4f | |||
3eeaf2eddc | |||
eb3e91420c | |||
38cd913020 | |||
9159c297a5 | |||
851687dba8 | |||
28b8006ec5 | |||
271128c075 | |||
a04ca0d715 | |||
8b89fe721d | |||
1baf04b1fd | |||
6c7f0f911c | |||
f2008f9263 | |||
62127f7269 | |||
740cedd978 | |||
4278ff2b37 | |||
e7bea34d95 | |||
825409b697 | |||
8f72ac0094 | |||
8a6bb610e3 | |||
94dc141062 | |||
286dd1e50b | |||
6451d9add9 | |||
fd1dcde86b | |||
99947a9e21 | |||
a69239abed | |||
fd06fae050 | |||
7fbb056edf | |||
06758863fb | |||
ad8af16a5a | |||
70dd6bcac5 | |||
b103423a53 | |||
a82a44e587 | |||
e6f612283f | |||
fcd60876ab | |||
5daa9a0bb6 | |||
4fb3926073 | |||
73932f4619 | |||
c99138b02e | |||
64d584681a | |||
9788dd49cc | |||
9d15c4e270 | |||
fe7b06d763 | |||
0e0275e496 | |||
ffd4d96539 | |||
a6b4c9645a | |||
a9141d027f | |||
807e581c3d | |||
41a4dfeb68 | |||
4430391e87 | |||
81667f4df5 | |||
835048132c | |||
00217305c2 | |||
85e8a70f76 | |||
bbdf27de5a | |||
3e63d4083e | |||
d1b8e3c752 | |||
1164feb754 | |||
9ebd9d4f04 | |||
9fd2a3a3e6 | |||
7f40889103 | |||
ee37b4a959 | |||
99d05ec91b | |||
412e5bd034 | |||
141420d337 | |||
084f83ba1b | |||
8601eff170 | |||
5da4d74a2a | |||
4215574a7c | |||
da9d986a3e | |||
7481b9c24c | |||
de5def8dde | |||
dd011b977a | |||
20d0dd91ad | |||
825c6d57e7 | |||
b3edb81d3c | |||
78089da134 | |||
3aef765d35 | |||
f4727f12c9 | |||
a36cb65aa5 | |||
3b16e59ee1 | |||
f2c43c74ac | |||
1c4c93dc60 | |||
d73847bfba | |||
4e46682489 | |||
ab7aa00747 | |||
2bebb6056d | |||
22046c417c | |||
dc8afa6d45 | |||
22e2ab5ad9 | |||
f365726a8e | |||
e329b3bd2e | |||
d7b709e97b | |||
9714ec46e9 | |||
20ef54f565 | |||
554df0bce9 | |||
6c89dddef6 | |||
23f91895f7 | |||
3f83cda087 | |||
7e79635413 | |||
56e1cf91ac | |||
f9f96f33f0 | |||
0b33073be1 | |||
65594842fc | |||
c6ed665f84 | |||
79462deb24 | |||
5c05f3e241 | |||
4f7dd75fbe | |||
338e507b51 | |||
601231a5dc | |||
f0850336e5 | |||
a6b2187ec5 | |||
28ae4f4230 | |||
09933b6a8d | |||
45bb6e7cb3 | |||
33c234a87e | |||
e9aa343d67 | |||
d83039430c | |||
5b2e877aef | |||
c5b28f5b8e | |||
e765021bf9 | |||
dbcd9e535c | |||
cff88d67ad | |||
3f241e8bc9 | |||
69c3d2d249 | |||
bc04d30595 | |||
63a26835b1 | |||
79113115e0 | |||
573ed7f6f2 | |||
61da1032d6 | |||
36d455c693 | |||
42c766b6d7 | |||
6f00384891 | |||
8440f7c763 | |||
8a8e864f99 | |||
7a3402b782 | |||
5e9a5b29f4 | |||
aff9d1ee60 | |||
8add7e8efb | |||
e7dfd0531b | |||
d2b1f70ce2 | |||
fbf7513c44 | |||
e9bdc26d15 | |||
52fafe9359 | |||
971dca6c96 | |||
a761c27b19 | |||
a062a85c7f | |||
a9865a731a | |||
ba4095ac9c | |||
8606a00701 | |||
bf57ba2902 | |||
4cd61cd96a | |||
c4139a862f | |||
ca3cd1de22 | |||
d7f22bc8e6 | |||
28b28d0b52 | |||
0ee2b285c0 | |||
d5cb085264 | |||
c055a5d329 | |||
8fe8b78f4c | |||
f627f125c0 | |||
7d3254477a | |||
3149ed4c1d | |||
baeafcdebe | |||
12754acc54 | |||
329baaf9a4 | |||
47efcfb41f | |||
e2d1b8a55c | |||
579eb29ce3 | |||
ada9560642 | |||
7b352b3a58 | |||
a5d5836ea2 | |||
57dc26a127 | |||
3e37b03808 | |||
d035713786 | |||
6e4a71b2f4 | |||
0b4dd534ab | |||
ed07f0baad | |||
004d34b5df | |||
aa380baf1c | |||
5123a962d9 | |||
7dcd770508 | |||
ead4d32446 | |||
a51a14022a | |||
05098252ed | |||
8e74965964 | |||
63913c2182 | |||
c55716e148 | |||
dd94442555 | |||
56f6a2fa56 | |||
4ca9df141c | |||
a29e06abce | |||
43e4d06fd9 | |||
3c8027425a | |||
3f66870688 | |||
1f32a4851e | |||
478b1c84de | |||
20ac14fdf6 | |||
c805d67cf6 | |||
943c2e7716 | |||
298a37e576 | |||
327d52014c | |||
6a5cfae5ff | |||
64ebb5c8c3 | |||
bb97b57b01 | |||
534e3723d2 | |||
ad6ef04b1f | |||
2c09b7794f | |||
4941ce1694 | |||
aa6a965f59 | |||
1831c30050 | |||
df5989760c | |||
e942fb5733 | |||
6a7f65894c | |||
f56e9369dd | |||
e23c5e019f | |||
1aa08f63fe | |||
8ef94d2854 | |||
797474063d | |||
b76622542b | |||
6a1415b3e1 | |||
2d09aef287 | |||
3ce1fa9b6e | |||
155bbb25f7 | |||
5fb3da5a77 | |||
5b682cd8d9 | |||
4755f0953c | |||
bdcd299805 | |||
3e23fe4814 | |||
3782d26e64 | |||
84a29eec65 | |||
299efaf0f2 | |||
33c60b467b | |||
81f74f07b2 | |||
583b08df28 | |||
01f80b67bc | |||
a890d2a357 | |||
0d1b91afc3 | |||
5c0d37d718 | |||
c81e56613e | |||
4cc7215d35 | |||
8751d2aaa1 | |||
af91622dda | |||
45d4caf595 | |||
a8e1d2a86c | |||
5099b11823 | |||
37e0307698 | |||
1b15eefa5a | |||
a4eccaf4f9 | |||
5981863e3f | |||
9ac7a4c522 | |||
9f1c3ee13c | |||
8b9c3d71d5 | |||
6d726b7499 | |||
b5da5afd1d | |||
420898e98c | |||
f6b392356c | |||
f4896f8d7c | |||
4dbd691146 | |||
2742dba0c4 | |||
5bea47a094 | |||
835a4b5cf0 | |||
055704b3ef | |||
60107aa7ce | |||
787ab021a7 | |||
f56a70f502 | |||
4ec6749ee6 | |||
8413b61397 | |||
ecbb970983 | |||
36e6570296 | |||
92c63b615a | |||
f71267c988 | |||
38fc0f8099 | |||
8c7238eab3 | |||
2baca30184 | |||
ac56979142 | |||
ff72858c42 | |||
deac587164 | |||
7a0a2fbd0a | |||
79c32097b5 | |||
26c20d9fc3 | |||
fe826a508a | |||
62d2140d24 | |||
499d619faf | |||
c178e58260 | |||
d242501fe6 | |||
37a438735d | |||
b862cfc4ec | |||
31002ae1a8 | |||
e8a3a2f676 | |||
e6baf8c35e | |||
b72ff9fe4f | |||
58f79ea617 | |||
ed6d343992 | |||
92b46d5c7b | |||
9cf7f08ae2 | |||
3b05b8f2f6 | |||
774d614d79 | |||
545f715eeb | |||
45b480c6dd | |||
7cc93507d9 | |||
80d3f67e6c | |||
dfbea2719b | |||
ce5da6bf80 | |||
d8d2129685 | |||
5dd37a1494 | |||
6cfe39dac3 | |||
660b22b398 | |||
b9a24a4542 | |||
af5bf6e04e | |||
ecc71a3295 | |||
0834402b18 | |||
8edd8ac73a | |||
1207a91a7f | |||
727490668c | |||
f068b3d204 | |||
205a486e58 | |||
f3bfd41a75 | |||
8d5c5daaaf | |||
83cfe8f534 | |||
9378e5e90c | |||
8617f0f3b4 | |||
0ecf3dc2b4 | |||
76005841fa | |||
7bf00ff139 | |||
82e34d852c | |||
7cd8ee1e23 | |||
a91a87b628 | |||
9d71f46e78 | |||
ccf405e64c | |||
c0a75d1845 | |||
e65a521bd4 | |||
1f203269ff | |||
18feea45bb | |||
597f0c895b | |||
5f21789d90 | |||
64826db4aa | |||
b150ee873f | |||
34effcefc6 | |||
68be2384d9 | |||
2629192bdb | |||
67b5afd73a | |||
5d8193301c | |||
adf21fee6f | |||
20f3e1d24e | |||
bf8f38fe38 | |||
3e3b8ebec5 | |||
8faeeffecf | |||
343968cf09 | |||
ca92f787e8 | |||
49a67e73be | |||
11af897c3d | |||
08cd04b2c8 | |||
c1656cf441 | |||
8f3c585588 | |||
dd181e4178 | |||
ff3689e92d | |||
fffcf0f809 | |||
240162370e | |||
98238caffb | |||
f55977a51d | |||
91938f156a | |||
eb01245cce | |||
17cbea9989 | |||
22c03dfd7a | |||
cf3e8684d5 | |||
cd0b2a646f | |||
d7528c09e3 | |||
e055484492 | |||
947d69da48 | |||
07822c47a3 | |||
25d6746b7e | |||
7cb85ff459 | |||
73d18c8d39 | |||
74b6d99ab1 | |||
491ff29e40 | |||
d1db619c8d | |||
733996f83e | |||
4a624cb365 | |||
637ea17f8e | |||
f8d6bd280e | |||
b91de5bad2 | |||
d7c3433bb2 | |||
43456e9a53 | |||
081244218f | |||
6ae39f192b | |||
ed5263f248 | |||
f1ee861eb4 | |||
2ce2fd95ba | |||
741f94ce6c | |||
4b7e415ae7 | |||
3efbb4fbde | |||
4d9450dd06 | |||
910870e46f | |||
b664df4208 | |||
c660277a23 | |||
0416d88d59 | |||
4f822e3cda | |||
20d4e473ff | |||
e45190922e | |||
1df118fa19 | |||
8ba27ccc2d | |||
ff646d32b5 | |||
75d99b324c | |||
ece91d980a | |||
a6a9f25e86 | |||
cc5330bf3d | |||
4a9e1466e6 | |||
fa947036f0 | |||
0b0884a7eb | |||
d5b2a21d16 | |||
fe28dd9b92 | |||
cfcbe8fb41 | |||
d86f820a57 | |||
ace1ddb00b | |||
96be411ba2 | |||
f24f7c2279 | |||
0130a7753e | |||
54b72ba312 | |||
7bced60466 | |||
041b10ef04 | |||
0e08b58f84 | |||
dd14489f47 | |||
6d6c2b5e99 | |||
251f382e8e | |||
887a652a06 | |||
bbbb1ea6bc | |||
2c399f198a | |||
54213cf554 | |||
0c67cd8e8b | |||
a0a23a261c | |||
20c7a16524 | |||
0a722b2196 | |||
4a537b1ce8 | |||
cf0372aeaa | |||
918d2f1a3a | |||
c1a6c1c66a | |||
7a2c4f0056 | |||
23eefb28d2 | |||
2ab2535966 | |||
bb20c1780b | |||
764505d2ca | |||
62b6b8e9eb | |||
beac252620 | |||
6e62acb384 | |||
b5afe25387 | |||
ebea6b29f3 | |||
f4eca66648 | |||
a6e6dd8287 | |||
d94c7e0157 | |||
4657263abb | |||
a6c2b24e8d | |||
31651f9a11 | |||
43c7692a8f | |||
7f05de734c | |||
fe39eec686 | |||
655fa0fde8 | |||
2841df6950 | |||
713dfec949 | |||
23c4087830 | |||
de293be4fc | |||
4e54649ce7 | |||
caeef2f1e1 | |||
f3d7693a26 | |||
2ceece6cdf | |||
c2913aea82 | |||
bf90e01e7e | |||
bbee53607b | |||
e94e2e7dc4 | |||
02a0839a4e | |||
67ea6c01f2 | |||
5b5cac878b | |||
56301d2d6f | |||
f8e80e6a9d | |||
d1f314d790 | |||
27f39b4458 | |||
0c40f79dec | |||
346ec3d1a6 | |||
5a2896808e | |||
4a34edeab0 | |||
5c2833978b | |||
edfc2274a2 | |||
899c9fd8d6 | |||
13f63c2f46 | |||
8841c47638 | |||
c6f5a8dcc6 | |||
786c5f9733 | |||
0cdedd02b4 | |||
aba028b1e8 | |||
3049c88d5b | |||
8239329c2e |
15
.gitignore
vendored
@ -1,14 +1,21 @@
|
||||
node_modules
|
||||
yotta_modules
|
||||
yotta_targets
|
||||
pxt_modules
|
||||
built
|
||||
typings
|
||||
tmp
|
||||
temp
|
||||
projects/**
|
||||
win10/app/bin
|
||||
win10/app/bld
|
||||
win10/*.opendb
|
||||
clients/win10/app/AppPackages
|
||||
clients/win10/app/BundlePackages
|
||||
clients/win10/app/BundleArtifacts
|
||||
clients/win10/app/bin
|
||||
clients/win10/app/bld
|
||||
clients/win10/*.opendb
|
||||
clients/**/bin/**
|
||||
clients/**/obj/**
|
||||
clients/electron/projects
|
||||
|
||||
*.user
|
||||
*.sw?
|
||||
@ -16,4 +23,4 @@ win10/*.opendb
|
||||
*.tgz
|
||||
*.db
|
||||
*.suo
|
||||
*.log
|
||||
*.log
|
||||
|
@ -4,8 +4,12 @@ node_js:
|
||||
script:
|
||||
- "node node_modules/pxt-core/built/pxt.js travis"
|
||||
- "(cd libs/lang-test0; node ../../node_modules/pxt-core/built/pxt.js run)"
|
||||
- "(cd libs/lang-test1; node ../../node_modules/pxt-core/built/pxt.js run)"
|
||||
- "(cd libs/lang-test0; node ../../node_modules/pxt-core/built/pxt.js test)"
|
||||
- "(cd libs/lang-test1; node ../../node_modules/pxt-core/built/pxt.js test)"
|
||||
- "node node_modules/pxt-core/built/pxt.js testdir tests"
|
||||
- "node node_modules/pxt-core/built/pxt.js uploaddoc"
|
||||
- "(cd libs/hello; node ../../node_modules/pxt-core/built/pxt.js testconv ../../testconv.json)"
|
||||
- "(cd libs/hello; node ../../node_modules/pxt-core/built/pxt.js testconv https://az851932.vo.msecnd.net/files/td-converter-tests-v1.json)"
|
||||
sudo: false
|
||||
notifications:
|
||||
email:
|
||||
@ -14,4 +18,5 @@ cache:
|
||||
directories:
|
||||
- node_modules
|
||||
- built/cache
|
||||
- libs/hello/built/cache
|
||||
|
||||
|
15
.vscode/settings.json
vendored
@ -1,5 +1,20 @@
|
||||
// Place your settings in this file to overwrite default and user settings.
|
||||
{
|
||||
"file.autoSave": "afterDelay",
|
||||
"files.watcherExclude": {
|
||||
"**/.git/objects/**": true,
|
||||
"**/built/**": true,
|
||||
"**/node_modules/**": true,
|
||||
"**/yotta_modules/**": true,
|
||||
"**/yotta_targets": true,
|
||||
"**/pxt_modules/**": true
|
||||
},
|
||||
"search.exclude": {
|
||||
"**/node_modules": true,
|
||||
"**/yotta_modules/**": true,
|
||||
"**/yotta_targets": true,
|
||||
"**/pxt_modules/**": true
|
||||
},
|
||||
"tslint.enable": true,
|
||||
"tslint.rulesDirectory": "node_modules/tslint-microsoft-contrib"
|
||||
}
|
44
README.md
@ -3,17 +3,25 @@
|
||||
This target allow to program a [BBC micro:bit](https://www.microbit.co.uk/) using
|
||||
PXT ([Microsoft Programming Experience Toolkit](https://github.com/Microsoft/pxt)).
|
||||
|
||||
* [Try it live](https://m.pxt.io)
|
||||
* [Try it live](https://codethemicrobit.com)
|
||||
|
||||
[](https://travis-ci.org/Microsoft/pxt-microbit)
|
||||
|
||||
## Local server
|
||||
|
||||
The local server allows to run the editor and the documentation from your computer.
|
||||
|
||||
### Setup
|
||||
|
||||
The following commands are a 1-time setup after synching the repo on your machine.
|
||||
|
||||
* install the PXT command line
|
||||
* if not yet installed, install [Node.js 4.4.5 or higher](https://nodejs.org/en/download/)
|
||||
* [clone this repo](https://help.github.com/articles/cloning-a-repository/) to your computer and go in the project folder
|
||||
```
|
||||
git clone https://github.com/microsoft/pxt-microbit
|
||||
cd pxt-microbit
|
||||
```
|
||||
* install the PXT command line (add ``sudo`` for Mac/Linux shells).
|
||||
```
|
||||
npm install -g pxt
|
||||
```
|
||||
@ -36,19 +44,37 @@ If you need modify the `.cpp` files, turn on yotta compilation with the ``-yt``
|
||||
pxt serve -yt
|
||||
```
|
||||
|
||||
To make sure you're running the latest tools, run (add ``sudo`` for Mac/Linux shells)
|
||||
## Updates
|
||||
|
||||
To update your PXT version and make sure you're running the latest tools, run (add ``sudo`` for Mac/Linux shells)
|
||||
```
|
||||
pxt update
|
||||
```
|
||||
|
||||
More instructions at https://github.com/Microsoft/pxt#running-a-target-from-localhost
|
||||
|
||||
## Universal Windows App
|
||||
|
||||
The Windows 10 app is a [Universal Windows Hosted Web App](https://microsoftedge.github.io/WebAppsDocs/en-US/win10/CreateHWA.htm)
|
||||
that wraps ``m.pxt.io`` and provides additional features.
|
||||
|
||||
### Building
|
||||
|
||||
* Install Visual Studio 2015 Update 2 or higher. Make sure the Windows 10 templates are installed.
|
||||
* open the ``win10/app.sln`` solution and launch the ``m.pxt.io`` project.
|
||||
* open the ``win10/app.sln`` solution and launch the ``codethemicrobit`` project.
|
||||
|
||||
## Testing
|
||||
|
||||
The build automatically runs the following:
|
||||
|
||||
* make sure the built-in packages compile
|
||||
* `pxt run` in `libs/lang-test*` - this will run the test in command line runner;
|
||||
there is a number of asserts in both of these
|
||||
* `pxt testdir` in `tests` - this makes sure all the files compile and generates .hex files
|
||||
* run the TD->TS converter on a number of test scripts from `microbit.co.uk` and make sure the results compile
|
||||
|
||||
To test something on the device:
|
||||
|
||||
* do a `pxt deploy` in `libs/lang-test*` - they should show `1` or `2` on the screen (and not unhappy face)
|
||||
* run `pxt testdir` in `tests` and deploy some of the hex files from `tests/built`
|
||||
|
||||
The `lang-test0` source comes from the `pxt-core` package. It's also tested with `pxt run` there.
|
||||
|
||||
## Code of Conduct
|
||||
|
||||
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
|
||||
|
26
clients/chrome/README.md
Normal file
@ -0,0 +1,26 @@
|
||||
# microbit-chrome
|
||||
Prototype chrome addon that exposes the micro:bit's serial output to webpages.
|
||||
* watch the [demo video](https://vimeo.com/146207766)
|
||||
|
||||
# Installation
|
||||
See [developer.chrome.com](https://developer.chrome.com/extensions/getstarted#unpacked)
|
||||
for instructions on how to install the local version into your chrome browser.
|
||||
|
||||
# Requirements
|
||||
* Chrome 48 or later.
|
||||
|
||||
# Sample page
|
||||
The `demo.html` webpage goes along with the
|
||||
https://github.com/Microsoft/microbit-touchdevelop/blob/master/examples/tcs34725.cpp
|
||||
program. Run `http-server` from this directory, then visit
|
||||
http://localhost:8080/demo.html
|
||||
(keep in mind that pages served from `file://` cannot open ports).
|
||||
|
||||
# Building
|
||||
|
||||
Open a command prompt and run the following commands.
|
||||
|
||||
````
|
||||
npm install
|
||||
typings update
|
||||
````
|
68
clients/chrome/background.js
Normal file
@ -0,0 +1,68 @@
|
||||
///<reference path='typings/browser.d.ts'/>
|
||||
var connections = [];
|
||||
// A list of "ports", i.e. connected clients (such as web pages). Multiple web
|
||||
// pages can connect to our service: they all receive the same data.
|
||||
var ports = [];
|
||||
function byPath(path) {
|
||||
return connections.filter(function (x) { return x.path == path; });
|
||||
}
|
||||
function byId(id) {
|
||||
return connections.filter(function (x) { return x.id == id; });
|
||||
}
|
||||
function onReceive(data, id) {
|
||||
if (ports.length == 0)
|
||||
return;
|
||||
var view = new DataView(data);
|
||||
var decoder = new TextDecoder("utf-8");
|
||||
var decodedString = decoder.decode(view);
|
||||
ports.forEach(function (port) { return port.postMessage({
|
||||
type: "serial",
|
||||
data: decodedString,
|
||||
id: id
|
||||
}); });
|
||||
}
|
||||
function findNewDevices() {
|
||||
chrome.serial.getDevices(function (serialPorts) {
|
||||
serialPorts.forEach(function (serialPort) {
|
||||
if (byPath(serialPort.path).length == 0 &&
|
||||
serialPort.displayName == "mbed Serial Port") {
|
||||
chrome.serial.connect(serialPort.path, { bitrate: 115200 }, function (info) {
|
||||
// In case the [connect] operation takes more than five seconds...
|
||||
if (info && byPath(serialPort.path).length == 0)
|
||||
connections.push({
|
||||
id: info.connectionId,
|
||||
path: serialPort.path
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
function main() {
|
||||
// Register new clients in the [ports] global variable.
|
||||
chrome.runtime.onConnectExternal.addListener(function (port) {
|
||||
if (/^(micro:bit|touchdevelop|yelm|pxt|codemicrobit|codethemicrobit)$/.test(port.name)) {
|
||||
ports.push(port);
|
||||
port.onDisconnect.addListener(function () {
|
||||
ports = ports.filter(function (x) { return x != port; });
|
||||
});
|
||||
}
|
||||
});
|
||||
// When receiving data for one of the connections that we're tracking, forward
|
||||
// it to all connected clients.
|
||||
chrome.serial.onReceive.addListener(function (info) {
|
||||
if (byId(info.connectionId).length > 0)
|
||||
onReceive(info.data, info.connectionId);
|
||||
});
|
||||
// When it looks like we've been disconnected, drop the corresponding
|
||||
// connection object from the [connections] global variable.
|
||||
chrome.serial.onReceiveError.addListener(function (info) {
|
||||
if (info.error == "system_error" || info.error == "disconnected" || info.error == "device_lost")
|
||||
connections = connections.filter(function (x) { return x.id != info.connectionId; });
|
||||
});
|
||||
// Probe serial connections at regular intervals. In case we find an mbed port
|
||||
// we haven't yet connected to, connect to it.
|
||||
setInterval(findNewDevices, 5000);
|
||||
findNewDevices();
|
||||
}
|
||||
document.addEventListener("DOMContentLoaded", main);
|
92
clients/chrome/background.ts
Normal file
@ -0,0 +1,92 @@
|
||||
// A list of: {
|
||||
// id: number;
|
||||
// path: string;
|
||||
// } where [id] is the [connectionId] (internal to Chrome) and [path] is the
|
||||
// OS' name for the device (e.g. "COM4").
|
||||
interface Connection {
|
||||
id: string;
|
||||
path: string;
|
||||
}
|
||||
let connections: Connection[] = [];
|
||||
|
||||
// A list of "ports", i.e. connected clients (such as web pages). Multiple web
|
||||
// pages can connect to our service: they all receive the same data.
|
||||
let ports = [];
|
||||
|
||||
interface Message {
|
||||
type: string;
|
||||
data: string;
|
||||
id: string;
|
||||
}
|
||||
|
||||
function byPath(path: string): Connection[] {
|
||||
return connections.filter((x) => x.path == path);
|
||||
}
|
||||
|
||||
function byId(id: string): Connection[] {
|
||||
return connections.filter((x) => x.id == id);
|
||||
}
|
||||
|
||||
function onReceive(data, id: string) {
|
||||
if (ports.length == 0) return;
|
||||
|
||||
let view = new DataView(data);
|
||||
let decoder = new TextDecoder("utf-8");
|
||||
let decodedString = decoder.decode(view);
|
||||
ports.forEach(port => port.postMessage(<Message>{
|
||||
type: "serial",
|
||||
data: decodedString,
|
||||
id: id,
|
||||
}));
|
||||
}
|
||||
|
||||
function findNewDevices() {
|
||||
chrome.serial.getDevices(function (serialPorts) {
|
||||
serialPorts.forEach(function (serialPort) {
|
||||
if (byPath(serialPort.path).length == 0 &&
|
||||
serialPort.displayName == "mbed Serial Port") {
|
||||
chrome.serial.connect(serialPort.path, { bitrate: 115200 }, function (info) {
|
||||
// In case the [connect] operation takes more than five seconds...
|
||||
if (info && byPath(serialPort.path).length == 0)
|
||||
connections.push({
|
||||
id: info.connectionId,
|
||||
path: serialPort.path
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function main() {
|
||||
// Register new clients in the [ports] global variable.
|
||||
chrome.runtime.onConnectExternal.addListener(function (port) {
|
||||
if (/^(micro:bit|touchdevelop|yelm|pxt|codemicrobit|codethemicrobit)$/.test(port.name)) {
|
||||
ports.push(port);
|
||||
port.onDisconnect.addListener(function () {
|
||||
ports = ports.filter(function (x) { return x != port });
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// When receiving data for one of the connections that we're tracking, forward
|
||||
// it to all connected clients.
|
||||
chrome.serial.onReceive.addListener(function (info) {
|
||||
if (byId(info.connectionId).length > 0)
|
||||
onReceive(info.data, info.connectionId);
|
||||
});
|
||||
|
||||
// When it looks like we've been disconnected, drop the corresponding
|
||||
// connection object from the [connections] global variable.
|
||||
chrome.serial.onReceiveError.addListener(function (info) {
|
||||
if (info.error == "system_error" || info.error == "disconnected" || info.error == "device_lost")
|
||||
connections = connections.filter((x) => x.id != info.connectionId);
|
||||
});
|
||||
|
||||
// Probe serial connections at regular intervals. In case we find an mbed port
|
||||
// we haven't yet connected to, connect to it.
|
||||
setInterval(findNewDevices, 5000);
|
||||
findNewDevices();
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", main);
|
BIN
clients/chrome/logo128.png
Normal file
After Width: | Height: | Size: 5.9 KiB |
BIN
clients/chrome/logo48.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
30
clients/chrome/manifest.json
Normal file
@ -0,0 +1,30 @@
|
||||
{
|
||||
"app": {
|
||||
"background": {
|
||||
"scripts": [ "background.js" ]
|
||||
}
|
||||
},
|
||||
|
||||
"manifest_version": 2,
|
||||
"name": "code the micro:bit",
|
||||
"version": "0.6.0",
|
||||
"author": "Microsoft Corporation",
|
||||
"short_name": "code the micro:bit",
|
||||
|
||||
"description": "Extension for https://codethemicrobit.com.",
|
||||
"homepage_url": "https://codethemicrobit.com",
|
||||
"offline_enabled": "true",
|
||||
"icons": {
|
||||
"48": "logo48.png",
|
||||
"128": "logo128.png"
|
||||
},
|
||||
|
||||
"permissions": [
|
||||
"serial",
|
||||
"usb"
|
||||
],
|
||||
|
||||
"externally_connectable": {
|
||||
"matches": [ "*://localhost/*", "https://codethemicrobit.com/*", "https://*.codethemicrobit.com/*" ]
|
||||
}
|
||||
}
|
BIN
clients/chrome/screenshot.png
Normal file
After Width: | Height: | Size: 138 KiB |
7
clients/chrome/tsconfig.json
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"compiler-options": {
|
||||
"target": "ES5",
|
||||
"module": "amd",
|
||||
"sourceMap": false
|
||||
}
|
||||
}
|
2
clients/electron/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
node_modules
|
||||
projects
|
5
clients/electron/README.md
Normal file
@ -0,0 +1,5 @@
|
||||
# PXT micro:bit Electron app
|
||||
|
||||
A very basic wrapper around the web app. To install, copy the contents of this
|
||||
directory to somewhere outside the main `pxt-microbit` repository. Then run `npm
|
||||
install && npm start`.
|
15
clients/electron/index.html
Normal file
@ -0,0 +1,15 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>code the micro:bit</title>
|
||||
</head>
|
||||
<body>
|
||||
<webview id="webview" style="position:absolute; left:0; top:0; right:0; bottom:0"/>
|
||||
<script>
|
||||
const webview = document.getElementById("webview")
|
||||
const url = `http://localhost:3232/${window.location.hash}`
|
||||
webview.src = url
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
39
clients/electron/main.js
Normal file
@ -0,0 +1,39 @@
|
||||
const {app, BrowserWindow, Menu} = require('electron')
|
||||
const pxt = require('pxt-core')
|
||||
const path = require('path')
|
||||
|
||||
let win
|
||||
|
||||
const cliPath = path.join(process.cwd(), "node_modules/pxt-microbit")
|
||||
|
||||
function startServerAndCreateWindow() {
|
||||
pxt.mainCli(cliPath, ["serve", "-no-browser"])
|
||||
createWindow()
|
||||
}
|
||||
|
||||
function createWindow () {
|
||||
win = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
title: "code the micro:bit"
|
||||
})
|
||||
Menu.setApplicationMenu(null)
|
||||
win.loadURL(`file://${__dirname}/index.html#local_token=${pxt.globalConfig.localToken}`)
|
||||
win.on('closed', () => {
|
||||
win = null
|
||||
})
|
||||
}
|
||||
|
||||
app.on('ready', startServerAndCreateWindow)
|
||||
|
||||
app.on('window-all-closed', () => {
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit()
|
||||
}
|
||||
})
|
||||
|
||||
app.on('activate', () => {
|
||||
if (win === null) {
|
||||
createWindow()
|
||||
}
|
||||
})
|
14
clients/electron/package.json
Normal file
@ -0,0 +1,14 @@
|
||||
{
|
||||
"name" : "code-the-microbit",
|
||||
"version" : "1.0.0",
|
||||
"description": "Blocks / Javascript editor",
|
||||
"author": "Microsoft",
|
||||
"main" : "main.js",
|
||||
"scripts": {
|
||||
"start": "node_modules/.bin/electron ."
|
||||
},
|
||||
"devDependencies": {
|
||||
"electron": "*",
|
||||
"pxt-microbit": "*"
|
||||
}
|
||||
}
|
137
clients/macuploader/.gitignore
vendored
Normal file
@ -0,0 +1,137 @@
|
||||
|
||||
# Created by https://www.gitignore.io/api/osx,xcode,objective-c,vim
|
||||
|
||||
### OSX ###
|
||||
*.DS_Store
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
|
||||
# Icon must end with two \r
|
||||
Icon
|
||||
|
||||
|
||||
# Thumbnails
|
||||
._*
|
||||
|
||||
# Files that might appear in the root of a volume
|
||||
.DocumentRevisions-V100
|
||||
.fseventsd
|
||||
.Spotlight-V100
|
||||
.TemporaryItems
|
||||
.Trashes
|
||||
.VolumeIcon.icns
|
||||
.com.apple.timemachine.donotpresent
|
||||
|
||||
# Directories potentially created on remote AFP share
|
||||
.AppleDB
|
||||
.AppleDesktop
|
||||
Network Trash Folder
|
||||
Temporary Items
|
||||
.apdisk
|
||||
|
||||
|
||||
### Xcode ###
|
||||
# Xcode
|
||||
#
|
||||
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
|
||||
|
||||
## Build generated
|
||||
build/
|
||||
DerivedData/
|
||||
|
||||
## Various settings
|
||||
*.pbxuser
|
||||
!default.pbxuser
|
||||
*.mode1v3
|
||||
!default.mode1v3
|
||||
*.mode2v3
|
||||
!default.mode2v3
|
||||
*.perspectivev3
|
||||
!default.perspectivev3
|
||||
xcuserdata/
|
||||
|
||||
## Other
|
||||
*.moved-aside
|
||||
*.xccheckout
|
||||
*.xcscmblueprint
|
||||
|
||||
|
||||
### Objective-C ###
|
||||
# Xcode
|
||||
#
|
||||
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
|
||||
|
||||
## Build generated
|
||||
build/
|
||||
DerivedData/
|
||||
|
||||
## Various settings
|
||||
*.pbxuser
|
||||
!default.pbxuser
|
||||
*.mode1v3
|
||||
!default.mode1v3
|
||||
*.mode2v3
|
||||
!default.mode2v3
|
||||
*.perspectivev3
|
||||
!default.perspectivev3
|
||||
xcuserdata/
|
||||
|
||||
## Other
|
||||
*.moved-aside
|
||||
*.xcuserstate
|
||||
|
||||
## Obj-C/Swift specific
|
||||
*.hmap
|
||||
*.ipa
|
||||
*.dSYM.zip
|
||||
*.dSYM
|
||||
|
||||
# CocoaPods
|
||||
#
|
||||
# We recommend against adding the Pods directory to your .gitignore. However
|
||||
# you should judge for yourself, the pros and cons are mentioned at:
|
||||
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
|
||||
#
|
||||
# Pods/
|
||||
|
||||
# Carthage
|
||||
#
|
||||
# Add this line if you want to avoid checking in source code from Carthage dependencies.
|
||||
# Carthage/Checkouts
|
||||
|
||||
Carthage/Build
|
||||
|
||||
# fastlane
|
||||
#
|
||||
# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
|
||||
# screenshots whenever they are needed.
|
||||
# For more information about the recommended setup visit:
|
||||
# https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md
|
||||
|
||||
fastlane/report.xml
|
||||
fastlane/Preview.html
|
||||
fastlane/screenshots
|
||||
fastlane/test_output
|
||||
|
||||
# Code Injection
|
||||
#
|
||||
# After new code Injection tools there's a generated folder /iOSInjectionProject
|
||||
# https://github.com/johnno1962/injectionforxcode
|
||||
|
||||
iOSInjectionProject/
|
||||
|
||||
### Objective-C Patch ###
|
||||
*.xcscmblueprint
|
||||
|
||||
|
||||
### Vim ###
|
||||
# swap
|
||||
[._]*.s[a-w][a-z]
|
||||
[._]s[a-w][a-z]
|
||||
# session
|
||||
Session.vim
|
||||
# temporary
|
||||
.netrwhist
|
||||
*~
|
||||
# auto-generated tag files
|
||||
tags
|
BIN
clients/macuploader/Graphics/appicon.sketch
Normal file
BIN
clients/macuploader/Graphics/export.png
Normal file
After Width: | Height: | Size: 40 KiB |
BIN
clients/macuploader/Graphics/menubar.sketch
Normal file
307
clients/macuploader/Microbit Uploader.xcodeproj/project.pbxproj
Normal file
@ -0,0 +1,307 @@
|
||||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 46;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
E93040071D895D1F00D931CA /* DirectoryWatcher.m in Sources */ = {isa = PBXBuildFile; fileRef = E93040061D895D1F00D931CA /* DirectoryWatcher.m */; };
|
||||
E930400A1D89620900D931CA /* Uploader.m in Sources */ = {isa = PBXBuildFile; fileRef = E93040091D89620900D931CA /* Uploader.m */; };
|
||||
E9F4FEE21D8709980071D783 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = E9F4FEE11D8709980071D783 /* AppDelegate.m */; };
|
||||
E9F4FEE51D8709980071D783 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = E9F4FEE41D8709980071D783 /* main.m */; };
|
||||
E9F4FEE71D8709980071D783 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E9F4FEE61D8709980071D783 /* Assets.xcassets */; };
|
||||
E9F4FEEA1D8709980071D783 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = E9F4FEE81D8709980071D783 /* MainMenu.xib */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
E93040051D895D1F00D931CA /* DirectoryWatcher.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DirectoryWatcher.h; sourceTree = "<group>"; };
|
||||
E93040061D895D1F00D931CA /* DirectoryWatcher.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DirectoryWatcher.m; sourceTree = "<group>"; };
|
||||
E93040081D89620900D931CA /* Uploader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Uploader.h; sourceTree = "<group>"; };
|
||||
E93040091D89620900D931CA /* Uploader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Uploader.m; sourceTree = "<group>"; };
|
||||
E9F4FEDD1D8709980071D783 /* Microbit Uploader.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Microbit Uploader.app"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
E9F4FEE01D8709980071D783 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
|
||||
E9F4FEE11D8709980071D783 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
|
||||
E9F4FEE41D8709980071D783 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
|
||||
E9F4FEE61D8709980071D783 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
E9F4FEE91D8709980071D783 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = "<group>"; };
|
||||
E9F4FEEB1D8709980071D783 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
E9F4FEDA1D8709980071D783 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
E9F4FED41D8709980071D783 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
E9F4FEDF1D8709980071D783 /* Microbit Uploader */,
|
||||
E9F4FEDE1D8709980071D783 /* Products */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
E9F4FEDE1D8709980071D783 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
E9F4FEDD1D8709980071D783 /* Microbit Uploader.app */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
E9F4FEDF1D8709980071D783 /* Microbit Uploader */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
E9F4FEE01D8709980071D783 /* AppDelegate.h */,
|
||||
E9F4FEE11D8709980071D783 /* AppDelegate.m */,
|
||||
E9F4FEE61D8709980071D783 /* Assets.xcassets */,
|
||||
E9F4FEE81D8709980071D783 /* MainMenu.xib */,
|
||||
E9F4FEEB1D8709980071D783 /* Info.plist */,
|
||||
E9F4FEE31D8709980071D783 /* Supporting Files */,
|
||||
E93040051D895D1F00D931CA /* DirectoryWatcher.h */,
|
||||
E93040061D895D1F00D931CA /* DirectoryWatcher.m */,
|
||||
E93040081D89620900D931CA /* Uploader.h */,
|
||||
E93040091D89620900D931CA /* Uploader.m */,
|
||||
);
|
||||
path = "Microbit Uploader";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
E9F4FEE31D8709980071D783 /* Supporting Files */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
E9F4FEE41D8709980071D783 /* main.m */,
|
||||
);
|
||||
name = "Supporting Files";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
E9F4FEDC1D8709980071D783 /* Microbit Uploader */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = E9F4FEEE1D8709980071D783 /* Build configuration list for PBXNativeTarget "Microbit Uploader" */;
|
||||
buildPhases = (
|
||||
E9F4FED91D8709980071D783 /* Sources */,
|
||||
E9F4FEDA1D8709980071D783 /* Frameworks */,
|
||||
E9F4FEDB1D8709980071D783 /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = "Microbit Uploader";
|
||||
productName = "Microbit Uploader";
|
||||
productReference = E9F4FEDD1D8709980071D783 /* Microbit Uploader.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
E9F4FED51D8709980071D783 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 0800;
|
||||
ORGANIZATIONNAME = thomasdenney;
|
||||
TargetAttributes = {
|
||||
E9F4FEDC1D8709980071D783 = {
|
||||
CreatedOnToolsVersion = 7.3.1;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = E9F4FED81D8709980071D783 /* Build configuration list for PBXProject "Microbit Uploader" */;
|
||||
compatibilityVersion = "Xcode 3.2";
|
||||
developmentRegion = English;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
Base,
|
||||
);
|
||||
mainGroup = E9F4FED41D8709980071D783;
|
||||
productRefGroup = E9F4FEDE1D8709980071D783 /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
E9F4FEDC1D8709980071D783 /* Microbit Uploader */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
E9F4FEDB1D8709980071D783 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
E9F4FEE71D8709980071D783 /* Assets.xcassets in Resources */,
|
||||
E9F4FEEA1D8709980071D783 /* MainMenu.xib in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
E9F4FED91D8709980071D783 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
E9F4FEE51D8709980071D783 /* main.m in Sources */,
|
||||
E930400A1D89620900D931CA /* Uploader.m in Sources */,
|
||||
E9F4FEE21D8709980071D783 /* AppDelegate.m in Sources */,
|
||||
E93040071D895D1F00D931CA /* DirectoryWatcher.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXVariantGroup section */
|
||||
E9F4FEE81D8709980071D783 /* MainMenu.xib */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
E9F4FEE91D8709980071D783 /* Base */,
|
||||
);
|
||||
name = MainMenu.xib;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXVariantGroup section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
E9F4FEEC1D8709980071D783 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
CODE_SIGN_IDENTITY = "-";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.11;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = macosx;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
E9F4FEED1D8709980071D783 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
CODE_SIGN_IDENTITY = "-";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.11;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = macosx;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
E9F4FEEF1D8709980071D783 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
INFOPLIST_FILE = "Microbit Uploader/Info.plist";
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "org.thomasdenney.Microbit-Uploader";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
E9F4FEF01D8709980071D783 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
INFOPLIST_FILE = "Microbit Uploader/Info.plist";
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "org.thomasdenney.Microbit-Uploader";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
E9F4FED81D8709980071D783 /* Build configuration list for PBXProject "Microbit Uploader" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
E9F4FEEC1D8709980071D783 /* Debug */,
|
||||
E9F4FEED1D8709980071D783 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
E9F4FEEE1D8709980071D783 /* Build configuration list for PBXNativeTarget "Microbit Uploader" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
E9F4FEEF1D8709980071D783 /* Debug */,
|
||||
E9F4FEF01D8709980071D783 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = E9F4FED51D8709980071D783 /* Project object */;
|
||||
}
|
7
clients/macuploader/Microbit Uploader.xcodeproj/project.xcworkspace/contents.xcworkspacedata
generated
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "self:Microbit Uploader.xcodeproj">
|
||||
</FileRef>
|
||||
</Workspace>
|
6
clients/macuploader/Microbit Uploader/AppDelegate.h
Normal file
@ -0,0 +1,6 @@
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
@interface AppDelegate : NSObject <NSApplicationDelegate>
|
||||
|
||||
@end
|
||||
|
130
clients/macuploader/Microbit Uploader/AppDelegate.m
Normal file
@ -0,0 +1,130 @@
|
||||
#import "AppDelegate.h"
|
||||
#import "DirectoryWatcher.h"
|
||||
#import "Uploader.h"
|
||||
|
||||
@interface AppDelegate ()<DirectoryWatcherDelegate, UploaderDelegate, NSUserNotificationCenterDelegate>
|
||||
|
||||
@property DirectoryWatcher * watcher;
|
||||
@property Uploader * uploader;
|
||||
@property NSStatusItem * menubarItem;
|
||||
|
||||
@end
|
||||
|
||||
@implementation AppDelegate
|
||||
|
||||
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
|
||||
// Insert code here to initialize your application
|
||||
self.watcher = [[DirectoryWatcher alloc] initWithPath:[self downloadsDirectory]];
|
||||
self.watcher.delegate = self;
|
||||
[self.watcher startWatching];
|
||||
|
||||
self.uploader = [[Uploader alloc] init];
|
||||
self.uploader.delegate = self;
|
||||
|
||||
[NSUserNotificationCenter defaultUserNotificationCenter].delegate = self;
|
||||
|
||||
[self createMenuBarIcon];
|
||||
[self configureVolumeMountNotifications];
|
||||
[self showActiveMicroBits];
|
||||
}
|
||||
|
||||
- (void)applicationWillTerminate:(NSNotification *)aNotification {
|
||||
// Insert code here to tear down your application
|
||||
[self.watcher stopWatching];
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
[[NSWorkspace sharedWorkspace].notificationCenter removeObserver:self];
|
||||
}
|
||||
|
||||
#pragma mark - Directory
|
||||
|
||||
- (void)watcher:(DirectoryWatcher *)watcher observedNewFileAtPath:(NSString *)path {
|
||||
NSString * fullPath = [watcher.path stringByAppendingPathComponent:path];
|
||||
if ([self.uploader shouldUploadFileAtPath:fullPath]) {
|
||||
[self.uploader uploadFile:fullPath];
|
||||
}
|
||||
}
|
||||
|
||||
- (NSString*)downloadsDirectory {
|
||||
NSArray * paths = NSSearchPathForDirectoriesInDomains(NSDownloadsDirectory, NSUserDomainMask, YES);
|
||||
return paths.firstObject;
|
||||
}
|
||||
|
||||
#pragma mark - Uploader delegate
|
||||
|
||||
- (void)uploader:(Uploader *)uploader transferredFile:(NSString *)file toMicroBit:(NSString *)microbit {
|
||||
[self showNotification:@"micro:bit upload" withDescription:[NSString stringWithFormat:@"%@ uploaded to %@", file.lastPathComponent, microbit]];
|
||||
}
|
||||
|
||||
- (void)uploader:(Uploader *)uploader failedToTransferFile:(NSString *)file toMicroBit:(NSString *)microbit {
|
||||
[self showNotification:@"micro:bit upload failed" withDescription:[NSString stringWithFormat:@"Couldn't transfer %@ to %@", file.lastPathComponent, microbit]];
|
||||
}
|
||||
|
||||
- (void)showNotification:(NSString*)title withDescription:(NSString*)description {
|
||||
NSUserNotification * notification = [NSUserNotification new];
|
||||
notification.title = title;
|
||||
notification.informativeText = description;
|
||||
notification.soundName = NSUserNotificationDefaultSoundName;
|
||||
[[NSUserNotificationCenter defaultUserNotificationCenter] deliverNotification:notification];
|
||||
}
|
||||
|
||||
#pragma mark - NSUserNotificationCenterDelegate
|
||||
|
||||
- (BOOL)userNotificationCenter:(NSUserNotificationCenter *)center shouldPresentNotification:(NSUserNotification *)notification {
|
||||
return YES;
|
||||
}
|
||||
|
||||
#pragma mark - Volume mount/unmount notification
|
||||
|
||||
- (void)configureVolumeMountNotifications {
|
||||
[[NSWorkspace sharedWorkspace].notificationCenter addObserver:self selector:@selector(volumeMountNotification:) name:NSWorkspaceDidRenameVolumeNotification object:nil];
|
||||
[[NSWorkspace sharedWorkspace].notificationCenter addObserver:self selector:@selector(volumeMountNotification:) name:NSWorkspaceDidMountNotification object:nil];
|
||||
[[NSWorkspace sharedWorkspace].notificationCenter addObserver:self selector:@selector(volumeMountNotification:) name:NSWorkspaceDidUnmountNotification object:nil];
|
||||
}
|
||||
|
||||
- (void)volumeMountNotification:(NSNotification*)sender {
|
||||
//Delay upadting the menu to give the chance for the disk to fully mount or unmount
|
||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
||||
[self showActiveMicroBits];
|
||||
});
|
||||
}
|
||||
|
||||
#pragma mark - Menu bar app
|
||||
|
||||
- (void)createMenuBarIcon {
|
||||
self.menubarItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSSquareStatusItemLength];
|
||||
self.menubarItem.button.image = [NSImage imageNamed:@"menubar"];
|
||||
}
|
||||
|
||||
- (void)showActiveMicroBits {
|
||||
NSMenu * menu = [NSMenu new];
|
||||
NSString * countString;
|
||||
NSUInteger count = self.uploader.microBitPaths.count;
|
||||
if (count == 0) {
|
||||
countString = @"No connect micro:bits";
|
||||
}
|
||||
else if (count == 1) {
|
||||
countString = @"1 connected micro:bit";
|
||||
}
|
||||
else {
|
||||
countString = [NSString stringWithFormat:@"%lu connected micro:bits", count];
|
||||
}
|
||||
NSMenuItem * microBitCount = [[NSMenuItem alloc] initWithTitle:countString action:nil keyEquivalent:@""];
|
||||
microBitCount.enabled = NO;
|
||||
[menu addItem:microBitCount];
|
||||
|
||||
NSMenuItem * websiteItem = [[NSMenuItem alloc] initWithTitle:@"Editor" action:@selector(launchEditor:) keyEquivalent:@"e"];
|
||||
[menu addItem:websiteItem];
|
||||
|
||||
NSMenuItem * quitItem = [[NSMenuItem alloc] initWithTitle:@"Quit" action:@selector(terminate:) keyEquivalent:@"q"];
|
||||
[menu addItem:quitItem];
|
||||
|
||||
self.menubarItem.menu = menu;
|
||||
}
|
||||
|
||||
- (void)launchEditor:(id)sender {
|
||||
[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@"https://codethemicrobit.com/"]];
|
||||
}
|
||||
|
||||
@end
|
@ -0,0 +1,68 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"size" : "16x16",
|
||||
"idiom" : "mac",
|
||||
"filename" : "icon_16x16.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"size" : "16x16",
|
||||
"idiom" : "mac",
|
||||
"filename" : "icon_16x16@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "32x32",
|
||||
"idiom" : "mac",
|
||||
"filename" : "icon_32x32.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"size" : "32x32",
|
||||
"idiom" : "mac",
|
||||
"filename" : "icon_32x32@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "128x128",
|
||||
"idiom" : "mac",
|
||||
"filename" : "icon_128x128.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"size" : "128x128",
|
||||
"idiom" : "mac",
|
||||
"filename" : "icon_128x128@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "256x256",
|
||||
"idiom" : "mac",
|
||||
"filename" : "icon_256x256.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"size" : "256x256",
|
||||
"idiom" : "mac",
|
||||
"filename" : "icon_256x256@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "512x512",
|
||||
"idiom" : "mac",
|
||||
"filename" : "icon_512x512.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"size" : "512x512",
|
||||
"idiom" : "mac",
|
||||
"filename" : "icon_512x512@2x.png",
|
||||
"scale" : "2x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 574 B |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 55 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 4.0 KiB |
After Width: | Height: | Size: 55 KiB |
After Width: | Height: | Size: 136 KiB |
@ -0,0 +1,6 @@
|
||||
{
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
15
clients/macuploader/Microbit Uploader/Assets.xcassets/menubar.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"filename" : "menubar.pdf"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
},
|
||||
"properties" : {
|
||||
"template-rendering-intent" : "template"
|
||||
}
|
||||
}
|
BIN
clients/macuploader/Microbit Uploader/Assets.xcassets/menubar.imageset/menubar.pdf
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="11201" systemVersion="15G1004" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="11201"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<customObject id="-2" userLabel="File's Owner" customClass="NSApplication">
|
||||
<connections>
|
||||
<outlet property="delegate" destination="Voe-Tx-rLC" id="GzC-gU-4Uq"/>
|
||||
</connections>
|
||||
</customObject>
|
||||
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
|
||||
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
|
||||
<customObject id="Voe-Tx-rLC" customClass="AppDelegate"/>
|
||||
<customObject id="YLy-65-1bz" customClass="NSFontManager"/>
|
||||
</objects>
|
||||
</document>
|
24
clients/macuploader/Microbit Uploader/DirectoryWatcher.h
Normal file
@ -0,0 +1,24 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@class DirectoryWatcher;
|
||||
|
||||
@protocol DirectoryWatcherDelegate <NSObject>
|
||||
|
||||
- (void)watcher:(DirectoryWatcher*)watcher observedNewFileAtPath:(NSString*)path;
|
||||
|
||||
@end
|
||||
|
||||
@interface DirectoryWatcher : NSObject
|
||||
|
||||
- (instancetype)initWithPath:(NSString*)path;
|
||||
|
||||
@property (readonly) NSString * path;
|
||||
|
||||
@property id<DirectoryWatcherDelegate> delegate;
|
||||
|
||||
- (void)startWatching;
|
||||
|
||||
//Automatically called when deallocated
|
||||
- (void)stopWatching;
|
||||
|
||||
@end
|
75
clients/macuploader/Microbit Uploader/DirectoryWatcher.m
Normal file
@ -0,0 +1,75 @@
|
||||
#import "DirectoryWatcher.h"
|
||||
#import <CoreServices/CoreServices.h>
|
||||
|
||||
void callback(ConstFSEventStreamRef streamRef, void * info, size_t numEvents, void * eventPaths, const FSEventStreamEventFlags eventFlags[], const FSEventStreamEventId eventIds[]);
|
||||
|
||||
@interface DirectoryWatcher ()
|
||||
|
||||
@property NSString * path;
|
||||
@property NSMutableSet<NSString*>* knownFiles;
|
||||
@property FSEventStreamRef stream;
|
||||
|
||||
- (void)rescanPathWithEvents:(BOOL)sendEvents;
|
||||
|
||||
@end
|
||||
|
||||
@implementation DirectoryWatcher
|
||||
|
||||
- (instancetype)initWithPath:(NSString *)path {
|
||||
if (!path) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
self = [super init];
|
||||
if (self) {
|
||||
self.path = path;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
[self stopWatching];
|
||||
}
|
||||
|
||||
- (void)startWatching {
|
||||
self.knownFiles = [NSMutableSet new];
|
||||
[self rescanPathWithEvents:NO];
|
||||
|
||||
CFStringRef path = (__bridge CFStringRef)(self.path);
|
||||
CFArrayRef pathsToWatch = CFArrayCreate(NULL, (const void**)&path, 1, NULL);
|
||||
CFAbsoluteTime latency = 1;
|
||||
FSEventStreamContext context = { 0, (__bridge void * _Nullable)(self), NULL, NULL, NULL };
|
||||
self.stream = FSEventStreamCreate(NULL, &callback, &context, pathsToWatch, kFSEventStreamEventIdSinceNow, latency, kFSEventStreamCreateFlagNone);
|
||||
FSEventStreamScheduleWithRunLoop(self.stream, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
|
||||
FSEventStreamStart(self.stream);
|
||||
}
|
||||
|
||||
- (void)stopWatching {
|
||||
if (self.stream) {
|
||||
FSEventStreamStop(self.stream);
|
||||
FSEventStreamInvalidate(self.stream);
|
||||
FSEventStreamRelease(self.stream);
|
||||
self.stream = nil;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)rescanPathWithEvents:(BOOL)sendEvents {
|
||||
NSArray<NSString*>* downloadFiles = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:self.path error:nil];
|
||||
NSMutableSet<NSString*>* fullSet = [NSMutableSet new];
|
||||
for (NSString * file in downloadFiles) {
|
||||
[fullSet addObject:file];
|
||||
if (![self.knownFiles containsObject:file]) {
|
||||
if (sendEvents) {
|
||||
[self.delegate watcher:self observedNewFileAtPath:file];
|
||||
}
|
||||
}
|
||||
}
|
||||
self.knownFiles = fullSet;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
void callback(ConstFSEventStreamRef streamRef, void * info, size_t numEvents, void * eventPaths, const FSEventStreamEventFlags eventFlags[], const FSEventStreamEventId eventIds[]) {
|
||||
DirectoryWatcher * watcher = (__bridge DirectoryWatcher*)info;
|
||||
[watcher rescanPathWithEvents:YES];
|
||||
}
|
36
clients/macuploader/Microbit Uploader/Info.plist
Normal file
@ -0,0 +1,36 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string></string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.01</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>2</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
|
||||
<key>LSUIElement</key>
|
||||
<true/>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string>Copyright © 2016 Thomas Denney. All rights reserved.</string>
|
||||
<key>NSMainNibFile</key>
|
||||
<string>MainMenu</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string>NSApplication</string>
|
||||
</dict>
|
||||
</plist>
|
21
clients/macuploader/Microbit Uploader/Uploader.h
Normal file
@ -0,0 +1,21 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@class Uploader;
|
||||
|
||||
@protocol UploaderDelegate <NSObject>
|
||||
|
||||
- (void)uploader:(Uploader*)uploader transferredFile:(NSString*)file toMicroBit:(NSString*)microbit;
|
||||
- (void)uploader:(Uploader*)uploader failedToTransferFile:(NSString*)file toMicroBit:(NSString*)microbit;
|
||||
|
||||
@end
|
||||
|
||||
@interface Uploader : NSObject
|
||||
|
||||
@property id<UploaderDelegate> delegate;
|
||||
|
||||
- (BOOL)shouldUploadFileAtPath:(NSString*)path;
|
||||
- (NSArray<NSString*>*)microBitPaths;
|
||||
- (void)uploadFile:(NSString*)file;
|
||||
- (void)uploadFile:(NSString*)file toMicroBit:(NSString*)path;
|
||||
|
||||
@end
|
74
clients/macuploader/Microbit Uploader/Uploader.m
Normal file
@ -0,0 +1,74 @@
|
||||
#import "Uploader.h"
|
||||
|
||||
@interface Uploader ()
|
||||
|
||||
@property NSOperationQueue * backgroundCopyQueue;
|
||||
|
||||
@end
|
||||
|
||||
@implementation Uploader
|
||||
|
||||
- (instancetype)init {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
self.backgroundCopyQueue = [NSOperationQueue new];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (BOOL)shouldUploadFileAtPath:(NSString *)path {
|
||||
//Whilst Safari is downloading the file it appends .download to the name
|
||||
NSRegularExpression * ignoreDownload = [NSRegularExpression regularExpressionWithPattern:@".download$" options:NSRegularExpressionCaseInsensitive error:nil];
|
||||
if ([ignoreDownload numberOfMatchesInString:path.lastPathComponent options:0 range:NSMakeRange(0, path.lastPathComponent.length)] > 0) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
//Chrome and Firefox create .hex files
|
||||
NSRegularExpression * hexFiles = [NSRegularExpression regularExpressionWithPattern:@".hex$" options:NSRegularExpressionCaseInsensitive error:nil];
|
||||
if ([hexFiles numberOfMatchesInString:path.lastPathComponent options:0 range:NSMakeRange(0, path.lastPathComponent.length)] > 0) {
|
||||
return YES;
|
||||
}
|
||||
|
||||
//Safari tends to just name files 'Unknown X'
|
||||
NSRegularExpression * unknownFiles = [NSRegularExpression regularExpressionWithPattern:@"^Unknown(( |-)[0-9]+)?" options:NSRegularExpressionCaseInsensitive error:nil];
|
||||
if ([unknownFiles numberOfMatchesInString:path.lastPathComponent options:0 range:NSMakeRange(0, path.lastPathComponent.length)]) {
|
||||
return YES;
|
||||
}
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (NSArray<NSString*>*)microBitPaths {
|
||||
NSArray<NSURL*>* allVolumes = [[NSFileManager defaultManager] mountedVolumeURLsIncludingResourceValuesForKeys:nil options:NSVolumeEnumerationSkipHiddenVolumes];
|
||||
NSMutableArray<NSString*>* microbitPaths = [NSMutableArray new];
|
||||
NSRegularExpression * microbitRegex = [NSRegularExpression regularExpressionWithPattern:@"^MICROBIT" options:NSRegularExpressionCaseInsensitive error:nil];
|
||||
for (NSURL * volume in allVolumes) {
|
||||
NSString * lastPathComponent = volume.lastPathComponent;
|
||||
if ([microbitRegex numberOfMatchesInString:lastPathComponent options:0 range:NSMakeRange(0, lastPathComponent.length)] > 0) {
|
||||
[microbitPaths addObject:volume.path];
|
||||
}
|
||||
}
|
||||
|
||||
return microbitPaths;
|
||||
}
|
||||
|
||||
- (void)uploadFile:(NSString *)file {
|
||||
for (NSString * microbit in [self microBitPaths]) {
|
||||
[self uploadFile:file toMicroBit:microbit];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)uploadFile:(NSString *)file toMicroBit:(NSString *)path {
|
||||
[self.backgroundCopyQueue addOperationWithBlock:^{
|
||||
NSError * copyError;
|
||||
NSString * destination = [path stringByAppendingPathComponent:file.lastPathComponent];
|
||||
if (![[NSFileManager defaultManager] copyItemAtPath:file toPath:destination error:©Error]) {
|
||||
[self.delegate uploader:self failedToTransferFile:file toMicroBit:path.lastPathComponent];
|
||||
}
|
||||
else {
|
||||
[self.delegate uploader:self transferredFile:file toMicroBit:path.lastPathComponent];
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
@end
|
5
clients/macuploader/Microbit Uploader/main.m
Normal file
@ -0,0 +1,5 @@
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
int main(int argc, const char * argv[]) {
|
||||
return NSApplicationMain(argc, argv);
|
||||
}
|
40
clients/macuploader/README.md
Normal file
@ -0,0 +1,40 @@
|
||||
# micro:bit uploader for OS X
|
||||
|
||||

|
||||
|
||||
This project is a clone of the [Windows
|
||||
uploader](https://codethemicrobit.com/uploader), but for OS X. Once launched,
|
||||
the app runs in your menu bar and will automatically deploy any HEX files to
|
||||
your `micro:bit`. Like the Windows version, it is compatible with any browser
|
||||
that can run [codethemicrobit.com](http://codethemicrobit.com).
|
||||
|
||||
## Install the built version
|
||||
|
||||
1. Download the latest `.zip` release from the `Release` directory
|
||||
2. Unzip it
|
||||
3. Drag `Microbit Uploader` to your Applications folder and launch it
|
||||
|
||||
## Building
|
||||
|
||||
To build the project you'll need a copy of OS X 10.11 or higher and Xcode 8 or
|
||||
higher (you may be able to build on earlier OSes or versions of Xcode, but this
|
||||
remains untested). Once you have a development environment set up, just build
|
||||
and run `Microbit Uploader.xcodeproj`.
|
||||
|
||||
## Distributing
|
||||
|
||||
1. Open the Xcode project
|
||||
2. Product > Archive
|
||||
3. Export:
|
||||
|
||||

|
||||
|
||||
4. You will then have the option of either signing or not-signing the
|
||||
application:
|
||||
|
||||
a) If you have an Apple developer account, select 'Export a Developer
|
||||
ID-signed Application'
|
||||
|
||||
b) If you don't have a developer ID, select 'Export as a macOS App'
|
||||
|
||||
5. Zip the produced app and upload to CDN or equivalent
|
BIN
clients/macuploader/Release/Microbit Uploader v1.0.zip
Normal file
BIN
clients/macuploader/Release/Microbit Uploader v1.01.zip
Normal file
@ -20,22 +20,18 @@
|
||||
<ProjectConfiguration Include="Release|AnyCPU">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>AnyCPU</Platform>
|
||||
<UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|ARM">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>ARM</Platform>
|
||||
<UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
<UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x86">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x86</Platform>
|
||||
<UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
48
clients/win10/app/codethemicrobitapp.sln
Normal file
@ -0,0 +1,48 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 14
|
||||
VisualStudioVersion = 14.0.25123.0
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "codethemicrobitapp", "codethemicrobitapp.jsproj", "{39122940-AB16-4CD4-A0CE-79A3EB863ECF}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Debug|ARM = Debug|ARM
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|Any CPU = Release|Any CPU
|
||||
Release|ARM = Release|ARM
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{39122940-AB16-4CD4-A0CE-79A3EB863ECF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{39122940-AB16-4CD4-A0CE-79A3EB863ECF}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{39122940-AB16-4CD4-A0CE-79A3EB863ECF}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
|
||||
{39122940-AB16-4CD4-A0CE-79A3EB863ECF}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{39122940-AB16-4CD4-A0CE-79A3EB863ECF}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{39122940-AB16-4CD4-A0CE-79A3EB863ECF}.Debug|ARM.Deploy.0 = Debug|ARM
|
||||
{39122940-AB16-4CD4-A0CE-79A3EB863ECF}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{39122940-AB16-4CD4-A0CE-79A3EB863ECF}.Debug|x64.Build.0 = Debug|x64
|
||||
{39122940-AB16-4CD4-A0CE-79A3EB863ECF}.Debug|x64.Deploy.0 = Debug|x64
|
||||
{39122940-AB16-4CD4-A0CE-79A3EB863ECF}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{39122940-AB16-4CD4-A0CE-79A3EB863ECF}.Debug|x86.Build.0 = Debug|x86
|
||||
{39122940-AB16-4CD4-A0CE-79A3EB863ECF}.Debug|x86.Deploy.0 = Debug|x86
|
||||
{39122940-AB16-4CD4-A0CE-79A3EB863ECF}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{39122940-AB16-4CD4-A0CE-79A3EB863ECF}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{39122940-AB16-4CD4-A0CE-79A3EB863ECF}.Release|Any CPU.Deploy.0 = Release|Any CPU
|
||||
{39122940-AB16-4CD4-A0CE-79A3EB863ECF}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{39122940-AB16-4CD4-A0CE-79A3EB863ECF}.Release|ARM.Build.0 = Release|ARM
|
||||
{39122940-AB16-4CD4-A0CE-79A3EB863ECF}.Release|ARM.Deploy.0 = Release|ARM
|
||||
{39122940-AB16-4CD4-A0CE-79A3EB863ECF}.Release|x64.ActiveCfg = Release|x64
|
||||
{39122940-AB16-4CD4-A0CE-79A3EB863ECF}.Release|x64.Build.0 = Release|x64
|
||||
{39122940-AB16-4CD4-A0CE-79A3EB863ECF}.Release|x64.Deploy.0 = Release|x64
|
||||
{39122940-AB16-4CD4-A0CE-79A3EB863ECF}.Release|x86.ActiveCfg = Release|x86
|
||||
{39122940-AB16-4CD4-A0CE-79A3EB863ECF}.Release|x86.Build.0 = Release|x86
|
||||
{39122940-AB16-4CD4-A0CE-79A3EB863ECF}.Release|x86.Deploy.0 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 7.4 KiB After Width: | Height: | Size: 7.4 KiB |
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 8.4 KiB After Width: | Height: | Size: 8.4 KiB |
@ -1,9 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Package xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10" xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest" xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10" IgnorableNamespaces="uap mp">
|
||||
<Identity Name="39122940-ab16-4cd4-a0ce-79a3eb863ecf" Version="0.1.4.0" Publisher="CN=jhalleux" />
|
||||
<Identity Name="39122940-ab16-4cd4-a0ce-79a3eb863ecf" Version="0.1.5.0" Publisher="CN=jhalleux" />
|
||||
<mp:PhoneIdentity PhoneProductId="39122940-ab16-4cd4-a0ce-79a3eb863ecf" PhonePublisherId="00000000-0000-0000-0000-000000000000" />
|
||||
<Properties>
|
||||
<DisplayName>codemicrobitapp</DisplayName>
|
||||
<DisplayName>codethemicrobit</DisplayName>
|
||||
<PublisherDisplayName>Microsoft</PublisherDisplayName>
|
||||
<Logo>images\storelogo.png</Logo>
|
||||
</Properties>
|
||||
@ -14,14 +14,14 @@
|
||||
<Resource Language="x-generate" />
|
||||
</Resources>
|
||||
<Applications>
|
||||
<Application Id="App" StartPage="https://m.pxt.io/">
|
||||
<Application Id="App" StartPage="https://codethemicrobit.com">
|
||||
<uap:ApplicationContentUriRules>
|
||||
<uap:Rule Match="https://m.pxt.io/" Type="include" WindowsRuntimeAccess="all" />
|
||||
<uap:Rule Match="https://codemicrobit.com/" Type="include" WindowsRuntimeAccess="all" />
|
||||
<uap:Rule Match="https://codethemicrobit.com/" Type="include" WindowsRuntimeAccess="all" />
|
||||
</uap:ApplicationContentUriRules>
|
||||
<uap:VisualElements DisplayName="m.pxt.io" Description="Code editors for the BBC micro:bit" BackgroundColor="white" Square150x150Logo="images\Square150x150Logo.png" Square44x44Logo="images\Square44x44Logo.png">
|
||||
<uap:DefaultTile Wide310x150Logo="images\Wide310x150Logo.png" ShortName="m.pxt.io">
|
||||
<uap:VisualElements DisplayName="code the micro:bit" Description="A code editor for the BBC micro:bit with Blocks or Javascript." BackgroundColor="white" Square150x150Logo="images\Square150x150Logo.png" Square44x44Logo="images\Square44x44Logo.png">
|
||||
<uap:DefaultTile Wide310x150Logo="images\Wide310x150Logo.png" ShortName="code the micro:bit">
|
||||
</uap:DefaultTile>
|
||||
<uap:SplashScreen Image="images\splashscreen.png" />
|
||||
</uap:VisualElements>
|
||||
@ -29,7 +29,6 @@
|
||||
<uap:Extension Category="windows.fileTypeAssociation">
|
||||
<uap:FileTypeAssociation Name="microbithex">
|
||||
<uap:DisplayName>BBC micro:bit binary file</uap:DisplayName>
|
||||
<uap:InfoTip>.hex file created with m.pxt.io or microbit.co.uk</uap:InfoTip>
|
||||
<uap:SupportedFileTypes>
|
||||
<uap:FileType ContentType="application/x-microbit-hex">.hex</uap:FileType>
|
||||
</uap:SupportedFileTypes>
|
BIN
clients/win10/store/desktopblocks1366x768.png
Normal file
After Width: | Height: | Size: 172 KiB |
BIN
clients/win10/store/desktopjavascript1366x768.png
Normal file
After Width: | Height: | Size: 121 KiB |
BIN
clients/win10/store/mobileblocks480x800.png
Normal file
After Width: | Height: | Size: 54 KiB |
40
clients/winuploader/CodeTheMicroBit.sln
Normal file
@ -0,0 +1,40 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 14
|
||||
VisualStudioVersion = 14.0.25123.0
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeTheMicrobit", "Microbit.Uploader\CodeTheMicrobit.csproj", "{7DC6CA45-FD75-44BC-805E-708C812CD4BF}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Debug|ARM = Debug|ARM
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|Any CPU = Release|Any CPU
|
||||
Release|ARM = Release|ARM
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{7DC6CA45-FD75-44BC-805E-708C812CD4BF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{7DC6CA45-FD75-44BC-805E-708C812CD4BF}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{7DC6CA45-FD75-44BC-805E-708C812CD4BF}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{7DC6CA45-FD75-44BC-805E-708C812CD4BF}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{7DC6CA45-FD75-44BC-805E-708C812CD4BF}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{7DC6CA45-FD75-44BC-805E-708C812CD4BF}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{7DC6CA45-FD75-44BC-805E-708C812CD4BF}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{7DC6CA45-FD75-44BC-805E-708C812CD4BF}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{7DC6CA45-FD75-44BC-805E-708C812CD4BF}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{7DC6CA45-FD75-44BC-805E-708C812CD4BF}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{7DC6CA45-FD75-44BC-805E-708C812CD4BF}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{7DC6CA45-FD75-44BC-805E-708C812CD4BF}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{7DC6CA45-FD75-44BC-805E-708C812CD4BF}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{7DC6CA45-FD75-44BC-805E-708C812CD4BF}.Release|x64.Build.0 = Release|Any CPU
|
||||
{7DC6CA45-FD75-44BC-805E-708C812CD4BF}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{7DC6CA45-FD75-44BC-805E-708C812CD4BF}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
7
clients/winuploader/Microbit.Uploader/App.config
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<configuration>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0"/>
|
||||
<supportedRuntime version="v2.0.50727"/>
|
||||
</startup>
|
||||
</configuration>
|
123
clients/winuploader/Microbit.Uploader/CodeTheMicrobit.csproj
Normal file
@ -0,0 +1,123 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{7DC6CA45-FD75-44BC-805E-708C812CD4BF}</ProjectGuid>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Microsoft.MicroBit</RootNamespace>
|
||||
<AssemblyName>CodeTheMicrobit</AssemblyName>
|
||||
<TargetFrameworkVersion>v2.0</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<RunCodeAnalysis>true</RunCodeAnalysis>
|
||||
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<ApplicationIcon>
|
||||
</ApplicationIcon>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<SignAssembly>false</SignAssembly>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<DelaySign>false</DelaySign>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup />
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.VisualBasic" />
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Deployment" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Management" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Settings.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Settings.Designer.cs">
|
||||
<DependentUpon>Settings.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="GlobalSuppressions.cs" />
|
||||
<Compile Include="KnownFolders.cs" />
|
||||
<Compile Include="LicenseDialog.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="LicenseDialog.Designer.cs">
|
||||
<DependentUpon>LicenseDialog.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="MainForm.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="MainForm.Designer.cs">
|
||||
<DependentUpon>MainForm.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="SingleInstanceAppHelper.cs" />
|
||||
<Compile Include="SingleInstanceAppStarter.cs" />
|
||||
<EmbeddedResource Include="LicenseDialog.resx">
|
||||
<DependentUpon>LicenseDialog.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="MainForm.resx">
|
||||
<DependentUpon>MainForm.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Properties\Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
<SubType>Designer</SubType>
|
||||
</EmbeddedResource>
|
||||
<Compile Include="Properties\Resources.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
<DesignTime>True</DesignTime>
|
||||
</Compile>
|
||||
<EmbeddedResource Include="Settings.resx">
|
||||
<DependentUpon>Settings.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="MSFT_logo_png.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
<None Include="Resources\MSR-LA - 2576.rtf" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="favicon.ico" />
|
||||
<EmbeddedResource Include="microbit.red.png" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
BIN
clients/winuploader/Microbit.Uploader/GlobalSuppressions.cs
Normal file
33
clients/winuploader/Microbit.Uploader/KnownFolders.cs
Normal file
@ -0,0 +1,33 @@
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Management;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security;
|
||||
|
||||
namespace Microsoft.MicroBit
|
||||
{
|
||||
/// <summary>
|
||||
/// Class containing methods to retrieve specific file system paths.
|
||||
/// </summary>
|
||||
internal static class KnownFoldersNativeMethods
|
||||
{
|
||||
[SecurityCritical]
|
||||
[SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")]
|
||||
public static string GetDownloadPath()
|
||||
{
|
||||
IntPtr outPath;
|
||||
int result = SHGetKnownFolderPath(new Guid("{374DE290-123F-4565-9164-39C4925E467B}"), 0x00004000, new IntPtr(0), out outPath);
|
||||
if (result >= 0)
|
||||
return Marshal.PtrToStringUni(outPath);
|
||||
else return null;
|
||||
}
|
||||
|
||||
[SuppressMessage("Microsoft.Security", "CA5122:PInvokesShouldNotBeSafeCriticalFxCopRule")]
|
||||
[DllImport("Shell32.dll")]
|
||||
[SecurityCritical]
|
||||
private static extern int SHGetKnownFolderPath(
|
||||
[MarshalAs(UnmanagedType.LPStruct)]Guid rfid, uint dwFlags, IntPtr hToken,
|
||||
out IntPtr ppszPath);
|
||||
}
|
||||
|
||||
}
|
93
clients/winuploader/Microbit.Uploader/LicenseDialog.Designer.cs
generated
Normal file
@ -0,0 +1,93 @@
|
||||
namespace Microsoft.MicroBit
|
||||
{
|
||||
partial class LicenseDialog
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Windows Form Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.textBox = new System.Windows.Forms.RichTextBox();
|
||||
this.acceptButton = new System.Windows.Forms.Button();
|
||||
this.exitButton = new System.Windows.Forms.Button();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// textBox
|
||||
//
|
||||
this.textBox.BorderStyle = System.Windows.Forms.BorderStyle.None;
|
||||
this.textBox.Location = new System.Drawing.Point(13, 13);
|
||||
this.textBox.Name = "textBox";
|
||||
this.textBox.ReadOnly = true;
|
||||
this.textBox.Size = new System.Drawing.Size(465, 438);
|
||||
this.textBox.TabIndex = 0;
|
||||
this.textBox.Text = "";
|
||||
//
|
||||
// acceptButton
|
||||
//
|
||||
this.acceptButton.Location = new System.Drawing.Point(322, 457);
|
||||
this.acceptButton.Name = "acceptButton";
|
||||
this.acceptButton.Size = new System.Drawing.Size(75, 23);
|
||||
this.acceptButton.TabIndex = 1;
|
||||
this.acceptButton.Text = "Accept";
|
||||
this.acceptButton.UseVisualStyleBackColor = true;
|
||||
this.acceptButton.Click += new System.EventHandler(this.acceptButton_Click);
|
||||
//
|
||||
// exitButton
|
||||
//
|
||||
this.exitButton.DialogResult = System.Windows.Forms.DialogResult.Cancel;
|
||||
this.exitButton.Location = new System.Drawing.Point(403, 457);
|
||||
this.exitButton.Name = "exitButton";
|
||||
this.exitButton.Size = new System.Drawing.Size(75, 23);
|
||||
this.exitButton.TabIndex = 2;
|
||||
this.exitButton.Text = "Exit";
|
||||
this.exitButton.UseVisualStyleBackColor = true;
|
||||
this.exitButton.Click += new System.EventHandler(this.exitButton_Click);
|
||||
//
|
||||
// LicenseDialog
|
||||
//
|
||||
this.AcceptButton = this.acceptButton;
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.CancelButton = this.exitButton;
|
||||
this.ClientSize = new System.Drawing.Size(490, 492);
|
||||
this.ControlBox = false;
|
||||
this.Controls.Add(this.exitButton);
|
||||
this.Controls.Add(this.acceptButton);
|
||||
this.Controls.Add(this.textBox);
|
||||
this.MaximizeBox = false;
|
||||
this.MinimizeBox = false;
|
||||
this.Name = "LicenseDialog";
|
||||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
|
||||
this.Text = "code the micro:bit terms of use";
|
||||
this.ResumeLayout(false);
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.RichTextBox textBox;
|
||||
private System.Windows.Forms.Button acceptButton;
|
||||
private System.Windows.Forms.Button exitButton;
|
||||
}
|
||||
}
|
32
clients/winuploader/Microbit.Uploader/LicenseDialog.cs
Normal file
@ -0,0 +1,32 @@
|
||||
using Microsoft.MicroBit.Properties;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Data;
|
||||
using System.Drawing;
|
||||
using System.Text;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Microsoft.MicroBit
|
||||
{
|
||||
public partial class LicenseDialog : Form
|
||||
{
|
||||
public LicenseDialog()
|
||||
{
|
||||
InitializeComponent();
|
||||
this.textBox.Text = Resources.MSR_LA___2576;
|
||||
}
|
||||
|
||||
private void acceptButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
this.DialogResult = DialogResult.Yes;
|
||||
this.Close();
|
||||
}
|
||||
|
||||
private void exitButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
this.DialogResult = DialogResult.No;
|
||||
this.Close();
|
||||
}
|
||||
}
|
||||
}
|
120
clients/winuploader/Microbit.Uploader/LicenseDialog.resx
Normal file
@ -0,0 +1,120 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
BIN
clients/winuploader/Microbit.Uploader/MSFT_logo_png.png
Normal file
After Width: | Height: | Size: 6.8 KiB |
173
clients/winuploader/Microbit.Uploader/MainForm.Designer.cs
generated
Normal file
@ -0,0 +1,173 @@
|
||||
namespace Microsoft.MicroBit
|
||||
{
|
||||
partial class MainForm
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Windows Form Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.components = new System.ComponentModel.Container();
|
||||
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm));
|
||||
this.statusLabel = new System.Windows.Forms.Label();
|
||||
this.backgroundPictureBox = new System.Windows.Forms.PictureBox();
|
||||
this.trayIcon = new System.Windows.Forms.NotifyIcon(this.components);
|
||||
this.versionLabel = new System.Windows.Forms.LinkLabel();
|
||||
this.label1 = new System.Windows.Forms.Label();
|
||||
this.SettingsLabel = new System.Windows.Forms.LinkLabel();
|
||||
this.pictureBox1 = new System.Windows.Forms.PictureBox();
|
||||
this.linkLabel1 = new System.Windows.Forms.LinkLabel();
|
||||
((System.ComponentModel.ISupportInitialize)(this.backgroundPictureBox)).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// statusLabel
|
||||
//
|
||||
this.statusLabel.BackColor = System.Drawing.SystemColors.Window;
|
||||
this.statusLabel.Font = new System.Drawing.Font("Consolas", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.statusLabel.Location = new System.Drawing.Point(11, 30);
|
||||
this.statusLabel.Name = "statusLabel";
|
||||
this.statusLabel.Size = new System.Drawing.Size(364, 23);
|
||||
this.statusLabel.TabIndex = 1;
|
||||
this.statusLabel.Text = "loading...";
|
||||
//
|
||||
// backgroundPictureBox
|
||||
//
|
||||
this.backgroundPictureBox.BackColor = System.Drawing.Color.White;
|
||||
this.backgroundPictureBox.Cursor = System.Windows.Forms.Cursors.Hand;
|
||||
this.backgroundPictureBox.Image = global::Microsoft.MicroBit.Properties.Resources.MSFT_logo_png;
|
||||
this.backgroundPictureBox.InitialImage = null;
|
||||
this.backgroundPictureBox.Location = new System.Drawing.Point(226, 91);
|
||||
this.backgroundPictureBox.Name = "backgroundPictureBox";
|
||||
this.backgroundPictureBox.Size = new System.Drawing.Size(149, 52);
|
||||
this.backgroundPictureBox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
|
||||
this.backgroundPictureBox.TabIndex = 0;
|
||||
this.backgroundPictureBox.TabStop = false;
|
||||
this.backgroundPictureBox.Click += new System.EventHandler(this.backgroundPictureBox_Click);
|
||||
//
|
||||
// trayIcon
|
||||
//
|
||||
this.trayIcon.Icon = ((System.Drawing.Icon)(resources.GetObject("trayIcon.Icon")));
|
||||
this.trayIcon.Visible = true;
|
||||
this.trayIcon.Click += new System.EventHandler(this.trayIcon_Click);
|
||||
//
|
||||
// versionLabel
|
||||
//
|
||||
this.versionLabel.AutoSize = true;
|
||||
this.versionLabel.Location = new System.Drawing.Point(12, 121);
|
||||
this.versionLabel.Name = "versionLabel";
|
||||
this.versionLabel.Size = new System.Drawing.Size(28, 13);
|
||||
this.versionLabel.TabIndex = 2;
|
||||
this.versionLabel.TabStop = true;
|
||||
this.versionLabel.Text = "v0.9";
|
||||
this.versionLabel.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.versionLabel_LinkClicked);
|
||||
//
|
||||
// label1
|
||||
//
|
||||
this.label1.AutoSize = true;
|
||||
this.label1.Font = new System.Drawing.Font("Microsoft Sans Serif", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.label1.Location = new System.Drawing.Point(12, 103);
|
||||
this.label1.Name = "label1";
|
||||
this.label1.Size = new System.Drawing.Size(169, 15);
|
||||
this.label1.TabIndex = 3;
|
||||
this.label1.Text = "Automatic upload of .hex files.";
|
||||
//
|
||||
// SettingsLabel
|
||||
//
|
||||
this.SettingsLabel.AutoSize = true;
|
||||
this.SettingsLabel.Location = new System.Drawing.Point(151, 121);
|
||||
this.SettingsLabel.Name = "SettingsLabel";
|
||||
this.SettingsLabel.Size = new System.Drawing.Size(43, 13);
|
||||
this.SettingsLabel.TabIndex = 4;
|
||||
this.SettingsLabel.TabStop = true;
|
||||
this.SettingsLabel.Text = "settings";
|
||||
this.SettingsLabel.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.SettingsLabel_LinkClicked);
|
||||
//
|
||||
// pictureBox1
|
||||
//
|
||||
this.pictureBox1.BackColor = System.Drawing.Color.White;
|
||||
this.pictureBox1.Cursor = System.Windows.Forms.Cursors.Hand;
|
||||
this.pictureBox1.Image = global::Microsoft.MicroBit.Properties.Resources.microbit_red;
|
||||
this.pictureBox1.InitialImage = null;
|
||||
this.pictureBox1.Location = new System.Drawing.Point(226, 6);
|
||||
this.pictureBox1.Name = "pictureBox1";
|
||||
this.pictureBox1.Size = new System.Drawing.Size(149, 79);
|
||||
this.pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
|
||||
this.pictureBox1.TabIndex = 5;
|
||||
this.pictureBox1.TabStop = false;
|
||||
this.pictureBox1.Click += new System.EventHandler(this.pictureBox1_Click);
|
||||
//
|
||||
// linkLabel1
|
||||
//
|
||||
this.linkLabel1.AutoSize = true;
|
||||
this.linkLabel1.Location = new System.Drawing.Point(62, 121);
|
||||
this.linkLabel1.Name = "linkLabel1";
|
||||
this.linkLabel1.Size = new System.Drawing.Size(60, 13);
|
||||
this.linkLabel1.TabIndex = 6;
|
||||
this.linkLabel1.TabStop = true;
|
||||
this.linkLabel1.Text = "open editor";
|
||||
this.linkLabel1.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabel1_LinkClicked);
|
||||
//
|
||||
// MainForm
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.BackColor = System.Drawing.Color.White;
|
||||
this.ClientSize = new System.Drawing.Size(388, 143);
|
||||
this.Controls.Add(this.linkLabel1);
|
||||
this.Controls.Add(this.pictureBox1);
|
||||
this.Controls.Add(this.SettingsLabel);
|
||||
this.Controls.Add(this.label1);
|
||||
this.Controls.Add(this.versionLabel);
|
||||
this.Controls.Add(this.statusLabel);
|
||||
this.Controls.Add(this.backgroundPictureBox);
|
||||
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
|
||||
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
|
||||
this.MaximizeBox = false;
|
||||
this.Name = "MainForm";
|
||||
this.ShowInTaskbar = false;
|
||||
this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;
|
||||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
|
||||
this.Text = "code the micro:bit";
|
||||
this.Load += new System.EventHandler(this.MainForm_Load);
|
||||
((System.ComponentModel.ISupportInitialize)(this.backgroundPictureBox)).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit();
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.PictureBox backgroundPictureBox;
|
||||
private System.Windows.Forms.Label statusLabel;
|
||||
private System.Windows.Forms.NotifyIcon trayIcon;
|
||||
private System.Windows.Forms.LinkLabel versionLabel;
|
||||
private System.Windows.Forms.Label label1;
|
||||
private System.Windows.Forms.LinkLabel SettingsLabel;
|
||||
private System.Windows.Forms.PictureBox pictureBox1;
|
||||
private System.Windows.Forms.LinkLabel linkLabel1;
|
||||
}
|
||||
}
|
||||
|
267
clients/winuploader/Microbit.Uploader/MainForm.cs
Normal file
@ -0,0 +1,267 @@
|
||||
using Microsoft.Win32;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Security;
|
||||
using System.Threading;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Microsoft.MicroBit
|
||||
{
|
||||
internal partial class MainForm : Form
|
||||
{
|
||||
FileSystemWatcher watcher;
|
||||
private string customcopypath = "";
|
||||
|
||||
public MainForm()
|
||||
{
|
||||
InitializeComponent();
|
||||
var v = typeof(MainForm).Assembly.GetName().Version;
|
||||
this.versionLabel.Text = "v" + v.Major + "." + v.Minor;
|
||||
}
|
||||
|
||||
private void MainForm_Load(object sender, EventArgs e)
|
||||
{
|
||||
this.initializeFileWatch();
|
||||
customcopypath = (string)Application.UserAppDataRegistry.GetValue("CustomDirectory", "");
|
||||
this.openEditor();
|
||||
}
|
||||
|
||||
private void openEditor()
|
||||
{
|
||||
// lanch editor
|
||||
try { Process.Start("https://codethemicrobit.com#uploader"); } catch (Exception) { }
|
||||
}
|
||||
|
||||
private void initializeFileWatch()
|
||||
{
|
||||
if (!checkTOU()) return;
|
||||
|
||||
var downloads = KnownFoldersNativeMethods.GetDownloadPath();
|
||||
if (downloads == null)
|
||||
{
|
||||
this.updateStatus("oops, can't find the `Downloads` folder");
|
||||
return;
|
||||
}
|
||||
|
||||
this.watcher = new FileSystemWatcher(downloads);
|
||||
this.watcher.Renamed += (sender, e) => this.handleFileEvent(e);
|
||||
this.watcher.Created += (sender, e) => this.handleFileEvent(e);
|
||||
this.watcher.EnableRaisingEvents = true;
|
||||
|
||||
this.waitingForHexFileStatus();
|
||||
}
|
||||
|
||||
private void waitingForHexFileStatus()
|
||||
{
|
||||
this.updateStatus("waiting for .hex file...");
|
||||
this.trayIcon.ShowBalloonTip(3000, "ready...", "waiting for .hex file...", ToolTipIcon.None);
|
||||
}
|
||||
|
||||
static bool checkTOU()
|
||||
{
|
||||
var v = (int)Application.UserAppDataRegistry.GetValue("TermOfUse", 0);
|
||||
if (v != 1)
|
||||
{
|
||||
using (var f = new LicenseDialog())
|
||||
{
|
||||
var r = f.ShowDialog();
|
||||
if (r != DialogResult.Yes)
|
||||
{
|
||||
Application.Exit();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Application.UserAppDataRegistry.SetValue("TermOfUse", 1, RegistryValueKind.DWord);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
delegate void Callback();
|
||||
|
||||
private void updateStatus(string value)
|
||||
{
|
||||
Callback a = (Callback)(() =>
|
||||
{
|
||||
this.statusLabel.Text = value;
|
||||
this.trayIcon.Text = value;
|
||||
});
|
||||
this.Invoke(a);
|
||||
}
|
||||
|
||||
void handleFileEvent(FileSystemEventArgs e)
|
||||
{
|
||||
this.handleFile(e.FullPath);
|
||||
}
|
||||
|
||||
volatile int copying;
|
||||
void handleFile(string fullPath)
|
||||
{
|
||||
try
|
||||
{
|
||||
// In case this is data-url download, at least Chrome will not rename file, but instead write to it
|
||||
// directly. This mean we may catch it in the act. Let's leave it some time to finish writing.
|
||||
Thread.Sleep(500);
|
||||
|
||||
var info = new System.IO.FileInfo(fullPath);
|
||||
Trace.WriteLine("download: " + info.FullName);
|
||||
|
||||
if (info.Extension != ".hex") return;
|
||||
|
||||
var infoName = info.Name;
|
||||
Trace.WriteLine("download name: " + info.Name);
|
||||
if (!infoName.StartsWith("microbit-", StringComparison.OrdinalIgnoreCase)) return;
|
||||
if (info.Name.EndsWith(".uploaded.hex", StringComparison.OrdinalIgnoreCase)) return;
|
||||
if (info.Length > 1000000) return; // make sure we don't try to copy large files
|
||||
|
||||
|
||||
// already copying?
|
||||
if (Interlocked.Exchange(ref this.copying, 1) == 1)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
var driveletters = getMicrobitDrives();
|
||||
List<String> drives = new List<String>();
|
||||
foreach (var d in driveletters)
|
||||
{
|
||||
drives.Add(d.RootDirectory.FullName);
|
||||
}
|
||||
if (!String.IsNullOrEmpty(customcopypath) && Directory.Exists(customcopypath))
|
||||
{
|
||||
drives.Add(customcopypath);
|
||||
}
|
||||
if (drives.Count == 0)
|
||||
{
|
||||
this.updateStatus("no board found");
|
||||
this.trayIcon.ShowBalloonTip(3000, "cancelled uploading...", "no board found", ToolTipIcon.None);
|
||||
return;
|
||||
}
|
||||
|
||||
this.updateStatus("uploading .hex file");
|
||||
this.trayIcon.ShowBalloonTip(3000, "uploading...", "uploading .hex file", ToolTipIcon.None);
|
||||
|
||||
// copy to all boards
|
||||
copyFirmware(info.FullName, drives);
|
||||
|
||||
// move away hex file
|
||||
var temp = System.IO.Path.ChangeExtension(info.FullName, ".uploaded.hex");
|
||||
try
|
||||
{
|
||||
File.Copy(info.FullName, temp, true);
|
||||
File.Delete(info.FullName);
|
||||
}
|
||||
catch (IOException) { }
|
||||
catch (NotSupportedException) { }
|
||||
catch (UnauthorizedAccessException) { }
|
||||
catch (ArgumentException) { }
|
||||
|
||||
// update ui
|
||||
this.updateStatus("uploading done");
|
||||
this.waitingForHexFileStatus();
|
||||
}
|
||||
finally
|
||||
{
|
||||
Interlocked.Exchange(ref this.copying, 0);
|
||||
}
|
||||
}
|
||||
catch (IOException) { }
|
||||
catch (NotSupportedException) { }
|
||||
catch (UnauthorizedAccessException) { }
|
||||
catch (ArgumentException) { }
|
||||
}
|
||||
|
||||
static void copyFirmware(string file, List<string> drives)
|
||||
{
|
||||
var waitHandles = new List<WaitHandle>();
|
||||
foreach (var drive in drives)
|
||||
{
|
||||
var ev = new AutoResetEvent(false);
|
||||
waitHandles.Add(ev);
|
||||
ThreadPool.QueueUserWorkItem((state) =>
|
||||
{
|
||||
try
|
||||
{
|
||||
var trg = System.IO.Path.Combine(drive, "firmware.hex");
|
||||
File.Copy(file, trg, true);
|
||||
}
|
||||
catch (IOException) { }
|
||||
catch (NotSupportedException) { }
|
||||
catch (UnauthorizedAccessException) { }
|
||||
catch (ArgumentException) { }
|
||||
ev.Set();
|
||||
}, ev);
|
||||
}
|
||||
|
||||
//waits for all the threads (waitHandles) to call the .Set() method
|
||||
//and inform that the execution has finished.
|
||||
WaitHandle.WaitAll(waitHandles.ToArray());
|
||||
}
|
||||
|
||||
static DriveInfo[] getMicrobitDrives()
|
||||
{
|
||||
var drives = System.IO.DriveInfo.GetDrives();
|
||||
var r = new System.Collections.Generic.List<DriveInfo>();
|
||||
foreach (var di in drives)
|
||||
{
|
||||
var label = getVolumeLabel(di);
|
||||
if (label.StartsWith("MICROBIT", StringComparison.Ordinal))
|
||||
r.Add(di);
|
||||
}
|
||||
return r.ToArray();
|
||||
}
|
||||
|
||||
static string getVolumeLabel(DriveInfo di)
|
||||
{
|
||||
try { return di.VolumeLabel; }
|
||||
catch (IOException) { }
|
||||
catch (SecurityException) { }
|
||||
catch (UnauthorizedAccessException) { }
|
||||
return "";
|
||||
}
|
||||
|
||||
private void trayIcon_Click(object sender, EventArgs e)
|
||||
{
|
||||
this.WindowState = FormWindowState.Minimized;
|
||||
this.WindowState = FormWindowState.Normal;
|
||||
this.Show();
|
||||
this.Activate();
|
||||
}
|
||||
|
||||
private void versionLabel_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
Process.Start("https://codethemicrobit.com/uploader");
|
||||
}
|
||||
catch (IOException) { }
|
||||
}
|
||||
|
||||
private void backgroundPictureBox_Click(object sender, EventArgs e)
|
||||
{
|
||||
this.openEditor();
|
||||
}
|
||||
|
||||
private void SettingsLabel_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
|
||||
{
|
||||
var settings = new Settings(customcopypath);
|
||||
settings.ShowDialog();
|
||||
customcopypath = settings.CustomCopyPath;
|
||||
Application.UserAppDataRegistry.SetValue("CustomDirectory", customcopypath, RegistryValueKind.String);
|
||||
}
|
||||
|
||||
private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
|
||||
{
|
||||
this.openEditor();
|
||||
}
|
||||
|
||||
private void pictureBox1_Click(object sender, EventArgs e)
|
||||
{
|
||||
this.openEditor();
|
||||
}
|
||||
}
|
||||
}
|
172
clients/winuploader/Microbit.Uploader/MainForm.resx
Normal file
@ -0,0 +1,172 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<metadata name="trayIcon.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>17, 17</value>
|
||||
</metadata>
|
||||
<assembly alias="System.Drawing" name="System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<data name="trayIcon.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>
|
||||
AAABAAEAEBAAAAAAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAQAAMIOAADCDgAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAN6bIZTOkxoUtj62FL5W1hTWpzYUvlbWFLY+thTKgwoUxnb+FLY6shS6TsoUzpMaFL5a1hS2P
|
||||
rYUxnb6FNZ2+ZTCTsvkriaf/KYKe/yuIpf8uk7L/K4il/ymBnP8tjqz/K4qn/yiBnP8qhaL/KoWh/yqG
|
||||
o/8ogJv/JXeQ/yqDnvkRMjz/Di02/wofJv8MJS3/Di02/wskLP8HGB3/Di43/w0qM/8HFxz/CyMr/w4s
|
||||
Nv8MJi7/CiAm/w4sNv8RMTv/BQsN/wUQE/8BAgL/AQQF/wYRFP8EBgf/AgIA/xAYJv8TGy3/AgIA/wMF
|
||||
Bv8HEhX/AQUG/wECAv8FEBT/BQsN/wYFD/8LByT/AQAC/wAAAP8CAgL/AwMD/woKEv8LCxT/DAwY/woK
|
||||
Ev8DAwT/AgIC/wAAAP8AAAD/AAAA/wICAv8JCA//IBs//wwMEP8AAAD/AgIC/wQEBv8bGzf/BgYK/wQE
|
||||
Bf8bGzj/BgYJ/wMDA/8AAAD/CgoK/xEREf8HBwf/Li4u/1FRUf9ERET/AQEA/wwMGf8UFCj/BAQE/wMD
|
||||
Av8DAwL/BAQE/xAQIP8RESL/AAAA/z8/P/9SUlH/NTU1/y4uLv9QUFD/QUFB/wEBAP8LCxf/EhIk/wIC
|
||||
Af8JCRH/CwsV/wICAf8PDx3/Dw8f/wAAAP89PT3/UVFQ/zQ0M/8FBQX/DAwM/wgICP8AAAD/CwsW/xIS
|
||||
JP8FBQb/Dg4b/xERIv8FBQb/Dw8d/w8PHv8AAAD/CAgK/xwXO/8KCRT/BAMI/wAAAP8AAAD/AAAA/wIC
|
||||
Av8EBAX/HR06/wgIEP8GBgv/HR07/wYGCf8DAwL/AAAA/wAAAP8JBh3/BwUS/y0fhf8FBBD/AAAA/wAA
|
||||
AP8AAAD/AAAA/xIOMv8fFVz/HhVa/xQPOP8AAQD/AAAA/wAAAP8AAAD/AAAA/wICAv9UO/v/MiKX/wUD
|
||||
D/8FAw7/AwIK/wAAAP8RCzP/IBZi/yAWYP8TDTr/AAAA/wAAAP8AAAD/AAAA/wAAAP8CAgL/VTz/+FQ6
|
||||
/P8yI5j/IBZg/ywehf8MCCX/BAMN/wUEEP8GBBH/AQED/wAAAP8AAAD/AAAA/wAAAP8AAAD/AgIC9Vc+
|
||||
/2BVOv9+Ujj0fTwptH5ONul9OCapfRUOPn4AAAB+AAAAfQAAAH4AAAB+AAAAfQAAAH4AAAB+AAAAfgQE
|
||||
BFkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAA//8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAA//8AAA==
|
||||
</value>
|
||||
</data>
|
||||
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>
|
||||
AAABAAEAEBAAAAAAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAQAAMIOAADCDgAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAN6bIZTOkxoUtj62FL5W1hTWpzYUvlbWFLY+thTKgwoUxnb+FLY6shS6TsoUzpMaFL5a1hS2P
|
||||
rYUxnb6FNZ2+ZTCTsvkriaf/KYKe/yuIpf8uk7L/K4il/ymBnP8tjqz/K4qn/yiBnP8qhaL/KoWh/yqG
|
||||
o/8ogJv/JXeQ/yqDnvkRMjz/Di02/wofJv8MJS3/Di02/wskLP8HGB3/Di43/w0qM/8HFxz/CyMr/w4s
|
||||
Nv8MJi7/CiAm/w4sNv8RMTv/BQsN/wUQE/8BAgL/AQQF/wYRFP8EBgf/AgIA/xAYJv8TGy3/AgIA/wMF
|
||||
Bv8HEhX/AQUG/wECAv8FEBT/BQsN/wYFD/8LByT/AQAC/wAAAP8CAgL/AwMD/woKEv8LCxT/DAwY/woK
|
||||
Ev8DAwT/AgIC/wAAAP8AAAD/AAAA/wICAv8JCA//IBs//wwMEP8AAAD/AgIC/wQEBv8bGzf/BgYK/wQE
|
||||
Bf8bGzj/BgYJ/wMDA/8AAAD/CgoK/xEREf8HBwf/Li4u/1FRUf9ERET/AQEA/wwMGf8UFCj/BAQE/wMD
|
||||
Av8DAwL/BAQE/xAQIP8RESL/AAAA/z8/P/9SUlH/NTU1/y4uLv9QUFD/QUFB/wEBAP8LCxf/EhIk/wIC
|
||||
Af8JCRH/CwsV/wICAf8PDx3/Dw8f/wAAAP89PT3/UVFQ/zQ0M/8FBQX/DAwM/wgICP8AAAD/CwsW/xIS
|
||||
JP8FBQb/Dg4b/xERIv8FBQb/Dw8d/w8PHv8AAAD/CAgK/xwXO/8KCRT/BAMI/wAAAP8AAAD/AAAA/wIC
|
||||
Av8EBAX/HR06/wgIEP8GBgv/HR07/wYGCf8DAwL/AAAA/wAAAP8JBh3/BwUS/y0fhf8FBBD/AAAA/wAA
|
||||
AP8AAAD/AAAA/xIOMv8fFVz/HhVa/xQPOP8AAQD/AAAA/wAAAP8AAAD/AAAA/wICAv9UO/v/MiKX/wUD
|
||||
D/8FAw7/AwIK/wAAAP8RCzP/IBZi/yAWYP8TDTr/AAAA/wAAAP8AAAD/AAAA/wAAAP8CAgL/VTz/+FQ6
|
||||
/P8yI5j/IBZg/ywehf8MCCX/BAMN/wUEEP8GBBH/AQED/wAAAP8AAAD/AAAA/wAAAP8AAAD/AgIC9Vc+
|
||||
/2BVOv9+Ujj0fTwptH5ONul9OCapfRUOPn4AAAB+AAAAfQAAAH4AAAB+AAAAfQAAAH4AAAB+AAAAfgQE
|
||||
BFkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAA//8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAA//8AAA==
|
||||
</value>
|
||||
</data>
|
||||
</root>
|
30
clients/winuploader/Microbit.Uploader/Program.cs
Normal file
@ -0,0 +1,30 @@
|
||||
using Microsoft.VisualBasic.ApplicationServices;
|
||||
using System;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Microsoft.MicroBit
|
||||
{
|
||||
static class Program
|
||||
{
|
||||
/// <summary>
|
||||
/// The main entry point for the application.
|
||||
/// </summary>
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope")]
|
||||
[STAThread]
|
||||
static void Main()
|
||||
{
|
||||
Application.EnableVisualStyles();
|
||||
Application.SetCompatibleTextRenderingDefault(false);
|
||||
SingleInstanceAppStarter.Start(new MainForm(), StartNewInstance);
|
||||
}
|
||||
|
||||
// The handler when attempting to start another instance of this application
|
||||
// We can customize the logic here for which form to activate in different
|
||||
// conditions. Like in this sample, we will be selectively activate the LoginForm
|
||||
// or MainForm based on the login state of the user.
|
||||
static void StartNewInstance(object sender, StartupNextInstanceEventArgs e)
|
||||
{
|
||||
e.BringToForeground = true;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Resources;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("Code The micro:bit Uploader")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("Microsoft")]
|
||||
[assembly: AssemblyProduct("MicrosoftMicrobitUploader")]
|
||||
[assembly: AssemblyCopyright("Copyright © Microsoft 2016")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("7dc6ca45-fd75-44bc-805e-708c812cd4bf")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("0.10.0.0")]
|
||||
[assembly: AssemblyFileVersion("0.10.0.0")]
|
||||
[assembly: CLSCompliant(true)]
|
||||
[assembly: NeutralResourcesLanguage("en-US")]
|