mirror of
https://github.com/coderaiser/cloudcmd.git
synced 2026-01-24 03:05:41 +00:00
Compare commits
6971 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
78e87796df | ||
|
|
75ad4415c4 | ||
|
|
c5d9bd7c1f | ||
|
|
f437a52ff0 | ||
|
|
7192a56e94 | ||
|
|
b9dd4f2676 | ||
|
|
e8cf3c92f9 | ||
|
|
d574a93d6d | ||
|
|
8a769fd512 | ||
|
|
3b409074c1 | ||
|
|
3b6b0b5a5b | ||
|
|
8876f050e0 | ||
|
|
8507282d55 | ||
|
|
f61b21eecc | ||
|
|
242820b7cf | ||
|
|
dd240ba9b2 | ||
|
|
4b945c0047 | ||
|
|
23a6a6981a | ||
|
|
9cebb2416f | ||
|
|
a94fa0d465 | ||
|
|
3bdf47a5bb | ||
|
|
0ccd109a50 | ||
|
|
6b0bd2e1de | ||
|
|
c23a6a12c8 | ||
|
|
a523ef65f5 | ||
|
|
0971ac4e94 | ||
|
|
64654e8d5c | ||
|
|
a063353a27 | ||
|
|
add31607f9 | ||
|
|
e36de00ce8 | ||
|
|
2c1210bbb1 | ||
|
|
85ebf21122 | ||
|
|
450f14614d | ||
|
|
f75bf4a401 | ||
|
|
d979e94927 | ||
|
|
8de9bd0847 | ||
|
|
e178321be9 | ||
|
|
4b84d20bb0 | ||
|
|
6e778a35ba | ||
|
|
e27ef51d43 | ||
|
|
917f585137 | ||
|
|
9950cacad9 | ||
|
|
457e23f31d | ||
|
|
cfa0b5e382 | ||
|
|
f903c5c9c5 | ||
|
|
08dd5ac183 | ||
|
|
9e2c5ac635 | ||
|
|
6856207d0d | ||
|
|
f0dcbe946f | ||
|
|
008279df57 | ||
|
|
dc99417c27 | ||
|
|
12751646fe | ||
|
|
8234201a39 | ||
|
|
4bb7d704b4 | ||
|
|
feb5aad36b | ||
|
|
c231fca334 | ||
|
|
14452d05b6 | ||
|
|
5c1ad5f8ff | ||
|
|
5b4bb90d61 | ||
|
|
5cc6f79d6a | ||
|
|
024bc41345 | ||
|
|
fb115c675e | ||
|
|
53f6f9e76f | ||
|
|
6d21c539d4 | ||
|
|
253389ea7b | ||
|
|
cdf11f7483 | ||
|
|
0ff16314d7 | ||
|
|
cc889bda4f | ||
|
|
43edba8cb8 | ||
|
|
06f3b78256 | ||
|
|
dfcd655780 | ||
|
|
ab20a462db | ||
|
|
2ec57132ed | ||
|
|
0222d177fc | ||
|
|
db0e0aef73 | ||
|
|
14ec19e80a | ||
|
|
e6a00979ff | ||
|
|
5b5352c7d9 | ||
|
|
78ddbd8a39 | ||
|
|
0067653109 | ||
|
|
5a2ac765d4 | ||
|
|
3ceb9a8c59 | ||
|
|
2a525e9bbb | ||
|
|
a49e963dc9 | ||
|
|
1037a1a264 | ||
|
|
8477f3e466 | ||
|
|
e5d004c0af | ||
|
|
836e908e11 | ||
|
|
9fd4a451ab | ||
|
|
f4386a6f0f | ||
|
|
91f9c0a1aa | ||
|
|
babeb9fb85 | ||
|
|
2e667ba693 | ||
|
|
07d18cfe96 | ||
|
|
60c56164b0 | ||
|
|
d8453236c2 | ||
|
|
efe81320e1 | ||
|
|
14e6754be3 | ||
|
|
3033aed2e3 | ||
|
|
5b972e2e4a | ||
|
|
543e08a837 | ||
|
|
2a8109f090 | ||
|
|
39a24028ac | ||
|
|
3f3c644500 | ||
|
|
38dd510158 | ||
|
|
64df81bc45 | ||
|
|
8366b3bbe2 | ||
|
|
66db798c35 | ||
|
|
56ed1cd535 | ||
|
|
c5aed16f63 | ||
|
|
1537fa73fc | ||
|
|
511347d3ef | ||
|
|
c963ffefee | ||
|
|
fc6304a1c6 | ||
|
|
a05ecdb406 | ||
|
|
9e4d66df4d | ||
|
|
3f7e17721e | ||
|
|
50b19dcc44 | ||
|
|
7fb130cdbd | ||
|
|
5970f10a84 | ||
|
|
84a51a932c | ||
|
|
b0360d8ef4 | ||
|
|
00a20129de | ||
|
|
5e657e9bd1 | ||
|
|
2559343eef | ||
|
|
ddf9e45567 | ||
|
|
84bfef562d | ||
|
|
2e7bdb8aa0 | ||
|
|
a2f66951a8 | ||
|
|
03631d95f7 | ||
|
|
1fc57fdb91 | ||
|
|
09408af5dd | ||
|
|
4eb47f9d42 | ||
|
|
4fcaf2885d | ||
|
|
eaea183536 | ||
|
|
c69ec16ef0 | ||
|
|
3cf13a92c0 | ||
|
|
08d13c6d6b | ||
|
|
df79dda4d0 | ||
|
|
b4792fc3f2 | ||
|
|
c164766895 | ||
|
|
0584f4f431 | ||
|
|
67e4b8f0e4 | ||
|
|
876bbfded5 | ||
|
|
15b71c1485 | ||
|
|
d252fe5fcb | ||
|
|
25119ac6ea | ||
|
|
fc20b9a4e1 | ||
|
|
faa2f9c765 | ||
|
|
08b5c6b2b5 | ||
|
|
83a1e527e5 | ||
|
|
a6d18ddb88 | ||
|
|
7db31363ff | ||
|
|
2077468a85 | ||
|
|
e3fcb7f24e | ||
|
|
64e4aba414 | ||
|
|
899266a62a | ||
|
|
d568a4d896 | ||
|
|
884c83eb60 | ||
|
|
b34ee44bb1 | ||
|
|
c3251bf5e1 | ||
|
|
54bbd4e34d | ||
|
|
3d13b9c5f8 | ||
|
|
61107329fc | ||
|
|
f0bc286aea | ||
|
|
8eb724b58c | ||
|
|
784bb2ebdd | ||
|
|
8f52376d3f | ||
|
|
ed31dd2409 | ||
|
|
8200874912 | ||
|
|
4b8568b264 | ||
|
|
de41aec77d | ||
|
|
74f5eb0cae | ||
|
|
1d983e9950 | ||
|
|
f9b3844153 | ||
|
|
546d061068 | ||
|
|
b1e231a5bb | ||
|
|
121b114e89 | ||
|
|
8592cedce0 | ||
|
|
a53ab67b7d | ||
|
|
de2cedd99d | ||
|
|
da545ea418 | ||
|
|
db6e8334b8 | ||
|
|
2f0c1a616c | ||
|
|
e100dcf627 | ||
|
|
76c4000890 | ||
|
|
fb5e5a320f | ||
|
|
8551cd54a6 | ||
|
|
c93803190b | ||
|
|
ddc94adbf1 | ||
|
|
ef42330848 | ||
|
|
a54caa1d7c | ||
|
|
9eafa189a8 | ||
|
|
baaf47e62f | ||
|
|
0d61a972fb | ||
|
|
af77eeed8d | ||
|
|
e99d084728 | ||
|
|
b77e9c91d4 | ||
|
|
4b476a6dff | ||
|
|
2057065dbf | ||
|
|
a87e5ceaf6 | ||
|
|
2eb3dc6692 | ||
|
|
5f0391fc44 | ||
|
|
1679b788c2 | ||
|
|
9a4cf388d3 | ||
|
|
f4b0f92f05 | ||
|
|
4ab4be124b | ||
|
|
99ad0c217d | ||
|
|
8ccec23d6c | ||
|
|
2a97ac66fb | ||
|
|
b26c8bba37 | ||
|
|
4b78d70b5c | ||
|
|
8450bfa611 | ||
|
|
84c6935ae4 | ||
|
|
9f52ed795d | ||
|
|
f7379c0562 | ||
|
|
51f51b54de | ||
|
|
e87418adde | ||
|
|
08ab63d704 | ||
|
|
e7cc9b92ae | ||
|
|
368c9bb814 | ||
|
|
43fd5ed660 | ||
|
|
f774d5b290 | ||
|
|
b0a7fc1648 | ||
|
|
f1193955fb | ||
|
|
2d21001e55 | ||
|
|
99118e65a6 | ||
|
|
8ff0ee6a1a | ||
|
|
ac9a27b333 | ||
|
|
84719365b1 | ||
|
|
34fb175d63 | ||
|
|
dbd8c6ab7c | ||
|
|
716765104c | ||
|
|
51a4cee688 | ||
|
|
b2f113bf0a | ||
|
|
2e02ba46e8 | ||
|
|
38666cbb8b | ||
|
|
53acae1a63 | ||
|
|
e2591061af | ||
|
|
3d52ce80f2 | ||
|
|
a598ef3ed0 | ||
|
|
e71550d557 | ||
|
|
56d621b1ff | ||
|
|
a38b3a79ce | ||
|
|
7ae60605bb | ||
|
|
7492b4bfc7 | ||
|
|
3adfec81c2 | ||
|
|
c68a3a7f07 | ||
|
|
4eaeccba1c | ||
|
|
2dea0a3b2d | ||
|
|
467f0a79c3 | ||
|
|
353a1fb6c1 | ||
|
|
8e98b778bd | ||
|
|
3ad6720f5f | ||
|
|
b0be119474 | ||
|
|
161d4f952b | ||
|
|
301252906f | ||
|
|
ddd1722f39 | ||
|
|
907afc6e4a | ||
|
|
d8da7922d9 | ||
|
|
2fc503f71f | ||
|
|
ad8e55d824 | ||
|
|
5d22722010 | ||
|
|
13cb970a55 | ||
|
|
94ebbf84cb | ||
|
|
100e940e4b | ||
|
|
a6ce6d3953 | ||
|
|
da0e99ad8c | ||
|
|
dff0267239 | ||
|
|
03e3ba6ad8 | ||
|
|
4c73315b5c | ||
|
|
71dc8dd6be | ||
|
|
f2ef160ca8 | ||
|
|
be4f6271f4 | ||
|
|
a733d81441 | ||
|
|
06cf0eebce | ||
|
|
59024eea98 | ||
|
|
62af673117 | ||
|
|
f22120dc38 | ||
|
|
1a0af863a2 | ||
|
|
0446a74d28 | ||
|
|
5562b47d84 | ||
|
|
7309ceff37 | ||
|
|
ac9abbd385 | ||
|
|
4bc5a7834e | ||
|
|
0f5fe2d4fe | ||
|
|
f5015e75e8 | ||
|
|
ddf4542b75 | ||
|
|
9dbd812b3d | ||
|
|
3d03efbe63 | ||
|
|
a522c49c1f | ||
|
|
9ec94dee15 | ||
|
|
62ed8411ae | ||
|
|
75a75365cf | ||
|
|
ac3f20c5d1 | ||
|
|
9109511e95 | ||
|
|
b63d6fccde | ||
|
|
88df2f0518 | ||
|
|
5e93bcca1e | ||
|
|
74d1eb7e28 | ||
|
|
544e30dbf8 | ||
|
|
282b3d5cca | ||
|
|
a6aa9bbc44 | ||
|
|
3140b7f998 | ||
|
|
d70362fbf1 | ||
|
|
6e8348b843 | ||
|
|
61ca7f36a4 | ||
|
|
b5e9ae5ad9 | ||
|
|
ba2d0b36af | ||
|
|
4cc47e30de | ||
|
|
d8451e56aa | ||
|
|
6abf327d0d | ||
|
|
79fb49479e | ||
|
|
2ae6ad34fc | ||
|
|
14d9618a64 | ||
|
|
05ef0ae452 | ||
|
|
883eee96a2 | ||
|
|
9c8c0533a4 | ||
|
|
14d46c007b | ||
|
|
25872c3b11 | ||
|
|
610ba8827f | ||
|
|
154b4bd627 | ||
|
|
c409a2db82 | ||
|
|
52df5bfcf4 | ||
|
|
2428853613 | ||
|
|
6fb2102099 | ||
|
|
37ab7068d9 | ||
|
|
d061aa82ea | ||
|
|
b088b84eb1 | ||
|
|
fceddc20f8 | ||
|
|
f7a6a36696 | ||
|
|
91de9b3d27 | ||
|
|
2d37f6c6e9 | ||
|
|
d75818297b | ||
|
|
faa2cb3f90 | ||
|
|
29914c09f1 | ||
|
|
7f5e5c6825 | ||
|
|
6bc4f3ec26 | ||
|
|
35622082a9 | ||
|
|
65cf97a7be | ||
|
|
cf9ed97c3e | ||
|
|
cc134464a4 | ||
|
|
e3f89e8845 | ||
|
|
c45b23fe55 | ||
|
|
b1f74c0057 | ||
|
|
bf2e8f9a7d | ||
|
|
f5f34a85ea | ||
|
|
04e5d5b7e0 | ||
|
|
3e565109b3 | ||
|
|
770a0812aa | ||
|
|
25d8faea63 | ||
|
|
98e0011e8e | ||
|
|
401a669aca | ||
|
|
4e32241d83 | ||
|
|
cfa3d69538 | ||
|
|
e01ee4575b | ||
|
|
a03185e14e | ||
|
|
564de89333 | ||
|
|
0655988ed7 | ||
|
|
c7f9090126 | ||
|
|
1bef0d4381 | ||
|
|
fcce26d4e1 | ||
|
|
6e99c7e3c5 | ||
|
|
3f83f6f09a | ||
|
|
bf90bf2295 | ||
|
|
043ba29b32 | ||
|
|
95c36b0a37 | ||
|
|
98d3a4cc56 | ||
|
|
46c8accd84 | ||
|
|
57d2f8e93d | ||
|
|
e080a54022 | ||
|
|
eff34215ee | ||
|
|
4503237ac4 | ||
|
|
bf614e1dc9 | ||
|
|
857c97006d | ||
|
|
b2478a8145 | ||
|
|
3c5ca3dca4 | ||
|
|
a92a5a0d34 | ||
|
|
c51ba1d8f6 | ||
|
|
a57833aaf8 | ||
|
|
0bcff30faa | ||
|
|
10d6d2e247 | ||
|
|
2047cb7ad8 | ||
|
|
6b793cca04 | ||
|
|
5fa9fcc57c | ||
|
|
bc617c17ef | ||
|
|
0ecd1853d0 | ||
|
|
dc2d3146a1 | ||
|
|
266aff4ffb | ||
|
|
a407e0c3fa | ||
|
|
97627dc2ff | ||
|
|
683c865eda | ||
|
|
b795a1f5dd | ||
|
|
d928c0b83d | ||
|
|
1d3567f3a3 | ||
|
|
33201dade2 | ||
|
|
5ced36b0d6 | ||
|
|
7ce954503c | ||
|
|
1c73e525ff | ||
|
|
da967f080c | ||
|
|
f0a6109a7d | ||
|
|
e84c7dcbab | ||
|
|
796ee627e7 | ||
|
|
aca4119fb1 | ||
|
|
ed95dec964 | ||
|
|
5324a41abd | ||
|
|
d453a1b291 | ||
|
|
71b915bed3 | ||
|
|
1ac4191c66 | ||
|
|
4f25500351 | ||
|
|
a0c398264c | ||
|
|
d79a577611 | ||
|
|
8d92aa91e9 | ||
|
|
5ab5576e68 | ||
|
|
c5cfe68c8a | ||
|
|
2fc241a9fa | ||
|
|
81a6b18165 | ||
|
|
084c84a277 | ||
|
|
ba9915a1df | ||
|
|
60b682b62a | ||
|
|
a3d310a3e4 | ||
|
|
bbaad041be | ||
|
|
b22ad537e2 | ||
|
|
154e3b078e | ||
|
|
a02d288df9 | ||
|
|
3314f9b94f | ||
|
|
a6afa205a9 | ||
|
|
e600c05d18 | ||
|
|
99c009542a | ||
|
|
afdf74342a | ||
|
|
552d95013b | ||
|
|
eb606bb608 | ||
|
|
f4a3add818 | ||
|
|
4462f26925 | ||
|
|
0cc76bd4f7 | ||
|
|
949a09340f | ||
|
|
5d6bed3d66 | ||
|
|
656ebd87e0 | ||
|
|
72df4288ef | ||
|
|
48dba5fa7e | ||
|
|
8a85f99eb2 | ||
|
|
2c7782c06a | ||
|
|
fb2d081402 | ||
|
|
f8f6377551 | ||
|
|
b04cbcd8c5 | ||
|
|
094df666f4 | ||
|
|
75bf8a1275 | ||
|
|
93aa7278b7 | ||
|
|
af9c916e08 | ||
|
|
01dccbfd07 | ||
|
|
ea86bd6a2f | ||
|
|
7857fb720d | ||
|
|
900d4307bb | ||
|
|
570cb8c094 | ||
|
|
828d10a8ee | ||
|
|
88908b3528 | ||
|
|
93f4a07ec6 | ||
|
|
a5f93523c1 | ||
|
|
99980c7f1d | ||
|
|
3b0941bc87 | ||
|
|
0dca7b6419 | ||
|
|
35dedfdf95 | ||
|
|
c37979801a | ||
|
|
3c93b29b86 | ||
|
|
7e2587459f | ||
|
|
621f52da2f | ||
|
|
8ab7e468a8 | ||
|
|
eb3f037a02 | ||
|
|
55032ebd7d | ||
|
|
ee5a0fb4b2 | ||
|
|
34258c6f27 | ||
|
|
47893e3b83 | ||
|
|
4c7dd74abd | ||
|
|
224e539708 | ||
|
|
ea929465a8 | ||
|
|
4b9267f375 | ||
|
|
809ef1cf60 | ||
|
|
354c137de6 | ||
|
|
574b425c02 | ||
|
|
e353fff711 | ||
|
|
4b74b8f286 | ||
|
|
339560fab2 | ||
|
|
ba7133f2e6 | ||
|
|
e8ca8cedc5 | ||
|
|
f9aa9911d5 | ||
|
|
fcd06769b2 | ||
|
|
24dcf78be8 | ||
|
|
13279299c4 | ||
|
|
20a00481d6 | ||
|
|
d55b6fb393 | ||
|
|
d63169ccc0 | ||
|
|
bb9276bec5 | ||
|
|
9aed5f751e | ||
|
|
10f564a315 | ||
|
|
c4f56c59d0 | ||
|
|
6b9d43e9ab | ||
|
|
7aacf203a0 | ||
|
|
4717e035ee | ||
|
|
f1279666b5 | ||
|
|
0e663e1dc5 | ||
|
|
ff9265b78b | ||
|
|
22aa337ac0 | ||
|
|
13350b5517 | ||
|
|
ce196abf1e | ||
|
|
3e18f6be28 | ||
|
|
deedca28a9 | ||
|
|
a1bf40bd83 | ||
|
|
d011b13d30 | ||
|
|
ef6088531a | ||
|
|
895d19a153 | ||
|
|
67c0b81067 | ||
|
|
235dc1b8db | ||
|
|
d0e5fc0cbd | ||
|
|
bd7dfd0c28 | ||
|
|
a6c400ae1c | ||
|
|
b336a4726a | ||
|
|
019e15b8bd | ||
|
|
643543002e | ||
|
|
2743788002 | ||
|
|
49280722d1 | ||
|
|
6b22b2412b | ||
|
|
14b05d1b14 | ||
|
|
88da092fdb | ||
|
|
8e25a02568 | ||
|
|
bdddc5752d | ||
|
|
d7e43d8a18 | ||
|
|
656000e7e0 | ||
|
|
ce49d9d6ad | ||
|
|
ed9af6d7a6 | ||
|
|
fd1eb1dc27 | ||
|
|
a27e4ecf61 | ||
|
|
203117d2b9 | ||
|
|
4a38c64cd6 | ||
|
|
31e1eeea50 | ||
|
|
cf41d7d1dd | ||
|
|
2bfd32a1bd | ||
|
|
5b5889dcf7 | ||
|
|
40f17bb670 | ||
|
|
871b05d4d5 | ||
|
|
2f6b07c469 | ||
|
|
fecfa9fa58 | ||
|
|
09de19b46e | ||
|
|
924f8696d0 | ||
|
|
3135314686 | ||
|
|
c83a5222ad | ||
|
|
7fe5a998c4 | ||
|
|
519aec8afe | ||
|
|
8126b51831 | ||
|
|
1309d825e4 | ||
|
|
e28215ddf3 | ||
|
|
026c292bae | ||
|
|
c2c7c74ae8 | ||
|
|
52f47a2434 | ||
|
|
f5df731491 | ||
|
|
d7ab5b912d | ||
|
|
6f737e83da | ||
|
|
18f0f55a64 | ||
|
|
4e52bb1371 | ||
|
|
e9ab141e30 | ||
|
|
ebadb8deeb | ||
|
|
63ecdcbd86 | ||
|
|
10045f6ffb | ||
|
|
bec0d44429 | ||
|
|
0a345a34a1 | ||
|
|
42ddee49a7 | ||
|
|
0c8bf9f3d0 | ||
|
|
b70aa0cb9c | ||
|
|
3aa52812ab | ||
|
|
35a46d0d07 | ||
|
|
5c84d1616c | ||
|
|
24fbeec62d | ||
|
|
a5229fae06 | ||
|
|
1195e570e4 | ||
|
|
c101b039ea | ||
|
|
444f659076 | ||
|
|
de15ed6766 | ||
|
|
d0a8e2daac | ||
|
|
f085c0eb06 | ||
|
|
cb86e78f8b | ||
|
|
10bd261a3f | ||
|
|
c337e4507d | ||
|
|
ba2d02bd3d | ||
|
|
9f644f82b1 | ||
|
|
b6797907a8 | ||
|
|
33827fea5e | ||
|
|
45d44dc74d | ||
|
|
50c3f04dcd | ||
|
|
404142cc40 | ||
|
|
ab6b93ddca | ||
|
|
2c9b23db4e | ||
|
|
8cc9b0ec66 | ||
|
|
ddee470eba | ||
|
|
bf3a9acc86 | ||
|
|
391269b1ed | ||
|
|
e44e4fa47d | ||
|
|
7fdac390de | ||
|
|
9f4a23e0f1 | ||
|
|
42e8e255c0 | ||
|
|
c345d8b7ef | ||
|
|
975d4eb8a0 | ||
|
|
ef10ebe97c | ||
|
|
81e76857da | ||
|
|
b12e0690cd | ||
|
|
3d4ba373a6 | ||
|
|
ed0c2ad45a | ||
|
|
4e406d758f | ||
|
|
18adf0852d | ||
|
|
42248bc0f4 | ||
|
|
b3f3510b2d | ||
|
|
bbf0c04f55 | ||
|
|
6af8f19bb6 | ||
|
|
95ede62e81 | ||
|
|
0c28633bbd | ||
|
|
42c8fd7bfe | ||
|
|
e129ab6a79 | ||
|
|
6e4667aa85 | ||
|
|
46a84c54ea | ||
|
|
c5e3134f37 | ||
|
|
aa0c15f6b6 | ||
|
|
23fcc2b8f7 | ||
|
|
f5f3048908 | ||
|
|
d8d9025286 | ||
|
|
66fdb550a6 | ||
|
|
e59f3cfa71 | ||
|
|
44422a5206 | ||
|
|
b67b7cf73d | ||
|
|
3ba6d4ae53 | ||
|
|
69c8eecaf1 | ||
|
|
b65b3ff940 | ||
|
|
4f06e6398f | ||
|
|
62d39841b1 | ||
|
|
2cfc4908a2 | ||
|
|
177771df6a | ||
|
|
23171f967e | ||
|
|
09f4090a4b | ||
|
|
f2db9bf2d5 | ||
|
|
0ff8470278 | ||
|
|
9b0ce7c7b7 | ||
|
|
e68b3232d9 | ||
|
|
c32ba39f43 | ||
|
|
c7371d9c3a | ||
|
|
3269cff066 | ||
|
|
75b35139e4 | ||
|
|
838b2e29cf | ||
|
|
9adc0778a9 | ||
|
|
130ce433f4 | ||
|
|
cac774d7ce | ||
|
|
7053e6be0b | ||
|
|
2743f78cd3 | ||
|
|
49f4e5bec7 | ||
|
|
228744bec8 | ||
|
|
2654197681 | ||
|
|
205d641e75 | ||
|
|
5accfeeaa7 | ||
|
|
a024dcdb61 | ||
|
|
5b661140fc | ||
|
|
ed14250fe2 | ||
|
|
21e9736c81 | ||
|
|
8097d96c72 | ||
|
|
efb686c332 | ||
|
|
bd5a8afdd5 | ||
|
|
d15134b272 | ||
|
|
b9b4af0454 | ||
|
|
18eeec0165 | ||
|
|
b2a7a6770c | ||
|
|
c40d2bb096 | ||
|
|
c7242199e7 | ||
|
|
f1fcde75c3 | ||
|
|
0f17c11c04 | ||
|
|
57390d541f | ||
|
|
e4cf91ac1d | ||
|
|
8fc0731900 | ||
|
|
ae552ede60 | ||
|
|
3dd9d6e454 | ||
|
|
7258013b88 | ||
|
|
3172759ca0 | ||
|
|
85015881d0 | ||
|
|
977d9d057f | ||
|
|
111eba8c31 | ||
|
|
8f466b4c9a | ||
|
|
057ec42b25 | ||
|
|
eab9df4490 | ||
|
|
b6549a6484 | ||
|
|
883b4487e0 | ||
|
|
699deb86c6 | ||
|
|
8fcfaec8a0 | ||
|
|
a5ea620ca8 | ||
|
|
c798b42a64 | ||
|
|
13f7fb2200 | ||
|
|
7ca9b8cece | ||
|
|
c2e51f75a1 | ||
|
|
4d9878b574 | ||
|
|
abe512c655 | ||
|
|
b67526f09b | ||
|
|
e236e87171 | ||
|
|
26fad02507 | ||
|
|
e73c327687 | ||
|
|
f3e0337584 | ||
|
|
1736ec7be2 | ||
|
|
fbc8ae25ad | ||
|
|
f92152195c | ||
|
|
bbe790e551 | ||
|
|
954f2c047c | ||
|
|
baac531655 | ||
|
|
262c72d44a | ||
|
|
5e63a524c1 | ||
|
|
5d93d5752c | ||
|
|
241efe971b | ||
|
|
8c59333a02 | ||
|
|
9a724a4bba | ||
|
|
8c8ac3bab4 | ||
|
|
843c319b1e | ||
|
|
879bc2ff8c | ||
|
|
3e303253d2 | ||
|
|
ad689ece31 | ||
|
|
1801689ef7 | ||
|
|
e77d8a709a | ||
|
|
b090b498a8 | ||
|
|
b5618412c3 | ||
|
|
bb3e07def3 | ||
|
|
a3f0f4ecae | ||
|
|
df60dd7ba0 | ||
|
|
21e7ea7d4c | ||
|
|
a091a382ca | ||
|
|
0edbffa093 | ||
|
|
08cc5dbba4 | ||
|
|
edbebd983e | ||
|
|
90eae0e944 | ||
|
|
3976056ee8 | ||
|
|
8f12c6c25f | ||
|
|
c92815d78d | ||
|
|
2fe6dcf166 | ||
|
|
33f2572979 | ||
|
|
a71dca0e70 | ||
|
|
cb37ab871b | ||
|
|
f391a3391f | ||
|
|
ce511812d5 | ||
|
|
89af33fb9d | ||
|
|
fec91e7093 | ||
|
|
a092a2fc9d | ||
|
|
775850c004 | ||
|
|
1a5dc6228c | ||
|
|
6622d508af | ||
|
|
a6a1e80afb | ||
|
|
40f885e7c4 | ||
|
|
f0fd4031bb | ||
|
|
0831723565 | ||
|
|
71a7e9dd93 | ||
|
|
07fe299ad6 | ||
|
|
b18c738f5b | ||
|
|
bcc11bda74 | ||
|
|
a108bd82b5 | ||
|
|
e3d373acf9 | ||
|
|
2a5ebe300d | ||
|
|
04e54f2794 | ||
|
|
2e75ca18f4 | ||
|
|
d8f0e92727 | ||
|
|
70c8ab537c | ||
|
|
f97677f384 | ||
|
|
bbb6d46c09 | ||
|
|
0c7cc3c0a2 | ||
|
|
0128014f51 | ||
|
|
75361de125 | ||
|
|
98be1b01f1 | ||
|
|
3ac0bf23e4 | ||
|
|
983ccac4d1 | ||
|
|
47883b8751 | ||
|
|
955b7f0c4c | ||
|
|
77bd89f8f7 | ||
|
|
135edafaee | ||
|
|
fce254f724 | ||
|
|
60607184d4 | ||
|
|
5e545c87b3 | ||
|
|
2b9705d9fc | ||
|
|
0d79531b69 | ||
|
|
b4f279d07c | ||
|
|
3cd1d67e58 | ||
|
|
2fc6c6e1a1 | ||
|
|
a63ce70d49 | ||
|
|
bc80069f18 | ||
|
|
996d99cbac | ||
|
|
a39ea0d61c | ||
|
|
3b81abed36 | ||
|
|
1b5a6a3721 | ||
|
|
b3b618b2ca | ||
|
|
7d1a35d8b2 | ||
|
|
dae05277d6 | ||
|
|
ac85786b62 | ||
|
|
325706756c | ||
|
|
ee5cbb13b0 | ||
|
|
b0e63fd3fd | ||
|
|
fd32f76bf0 | ||
|
|
49f298bc46 | ||
|
|
a3c18dcdb2 | ||
|
|
38d29a6b27 | ||
|
|
e3cac1a892 | ||
|
|
9b9070b69b | ||
|
|
84b5019dd0 | ||
|
|
ee81cd1533 | ||
|
|
5edd57a390 | ||
|
|
f261a0ea08 | ||
|
|
6182f621d6 | ||
|
|
72ed5bbe4e | ||
|
|
fac9b347c2 | ||
|
|
48ae1c2e63 | ||
|
|
d785952b7e | ||
|
|
5f13f380e9 | ||
|
|
99b93e760a | ||
|
|
11cc63adcd | ||
|
|
c057b950c8 | ||
|
|
b6f30d1ccb | ||
|
|
546b511a9a | ||
|
|
ddef087328 | ||
|
|
2355618409 | ||
|
|
28461fbe19 | ||
|
|
cdb719eb2a | ||
|
|
da692a4798 | ||
|
|
c002fc37c5 | ||
|
|
4e86f7f308 | ||
|
|
462d7bf3b5 | ||
|
|
eb2c15ba17 | ||
|
|
635b195d48 | ||
|
|
301bfa3234 | ||
|
|
4b51f363ae | ||
|
|
57485b5b4b | ||
|
|
cd7bf0fe01 | ||
|
|
595805eeaf | ||
|
|
a2c17e5e0e | ||
|
|
af2548acd1 | ||
|
|
82c576c850 | ||
|
|
0ec17645b6 | ||
|
|
b35a3e029f | ||
|
|
0037ec9606 | ||
|
|
cbd5a2786c | ||
|
|
226d7c93bd | ||
|
|
a2c82c56fb | ||
|
|
dd91c810ad | ||
|
|
fcdb2e3a28 | ||
|
|
b06c9499a3 | ||
|
|
394bf46eca | ||
|
|
0967ad12e8 | ||
|
|
fdcc060861 | ||
|
|
77384f35c4 | ||
|
|
59338a16ac | ||
|
|
a91344595c | ||
|
|
a2586424f9 | ||
|
|
d08921bde3 | ||
|
|
9214bb4f31 | ||
|
|
77aff31bcc | ||
|
|
89570857bb | ||
|
|
84d1db5f1e | ||
|
|
a87fb57188 | ||
|
|
95db6de63c | ||
|
|
bbffe1a9bd | ||
|
|
9d6b6b7c93 | ||
|
|
76e0eab94c | ||
|
|
9a13502597 | ||
|
|
77d02c7844 | ||
|
|
c3339d8ea2 | ||
|
|
7371871f15 | ||
|
|
8f0f6db9d6 | ||
|
|
27ddaf726d | ||
|
|
e6c1d928ec | ||
|
|
ae360b1db3 | ||
|
|
b5be1f3933 | ||
|
|
006344b58a | ||
|
|
b18b6af4dc | ||
|
|
4d8f489b18 | ||
|
|
76380a1f04 | ||
|
|
332593c23e | ||
|
|
fd818c5f31 | ||
|
|
1b7b163a66 | ||
|
|
1c9ca22b93 | ||
|
|
5a1a39478f | ||
|
|
983609f19a | ||
|
|
c719e37cc1 | ||
|
|
4c7f8cc6b6 | ||
|
|
1e853b040d | ||
|
|
fcc59c0674 | ||
|
|
ee091a33c9 | ||
|
|
13e7af779b | ||
|
|
a9e9dd7270 | ||
|
|
75c6abb2b1 | ||
|
|
ca7acdd812 | ||
|
|
57750689ee | ||
|
|
ecd7423ac0 | ||
|
|
f74d3e71a2 | ||
|
|
eba20025fe | ||
|
|
30da4bcd85 | ||
|
|
ab7f266e2b | ||
|
|
32f97392bb | ||
|
|
382ac94a1f | ||
|
|
42046eff3a | ||
|
|
154030c5fa | ||
|
|
38fa908872 | ||
|
|
fd5b2cc6c6 | ||
|
|
514644269c | ||
|
|
6d1b18da07 | ||
|
|
d918ed1f52 | ||
|
|
175d01f3d1 | ||
|
|
1dbc978916 | ||
|
|
14dc7ac3a3 | ||
|
|
f434bd1133 | ||
|
|
d8c2ac4708 | ||
|
|
79f68d01c8 | ||
|
|
b8a83868da | ||
|
|
0b74250248 | ||
|
|
8932378e07 | ||
|
|
1e4761a10a | ||
|
|
0a7c52c75d | ||
|
|
c61681c331 | ||
|
|
19888b3ee5 | ||
|
|
6d7f274bde | ||
|
|
706b823c4a | ||
|
|
aeb5906de3 | ||
|
|
c8d2098e5b | ||
|
|
6cb0da0ce8 | ||
|
|
d181b84c3b | ||
|
|
5732752350 | ||
|
|
0f93c4fa1b | ||
|
|
92e0e4bb91 | ||
|
|
291dc39c25 | ||
|
|
750b7571f5 | ||
|
|
87f4022759 | ||
|
|
d053e60ed2 | ||
|
|
5041930685 | ||
|
|
13307f3861 | ||
|
|
b081dc8b18 | ||
|
|
7fd5e2bc90 | ||
|
|
e973f5fd4e | ||
|
|
b2fa10f2de | ||
|
|
222ce237c5 | ||
|
|
27df34f000 | ||
|
|
50e0152ced | ||
|
|
c49d25229c | ||
|
|
28ceb7f7ff | ||
|
|
d8dd9f5738 | ||
|
|
16a1eade2a | ||
|
|
807a1bc26d | ||
|
|
e7feb83f76 | ||
|
|
a117867307 | ||
|
|
e08a6bead8 | ||
|
|
2ed1c3a9dc | ||
|
|
378d694871 | ||
|
|
8bb746aa0e | ||
|
|
c30bc69f5d | ||
|
|
73dc17318e | ||
|
|
d23118f692 | ||
|
|
b48507d92a | ||
|
|
7d82ef92e9 | ||
|
|
8f9c6906a1 | ||
|
|
f506801337 | ||
|
|
e6c51f61ca | ||
|
|
75a1f9db17 | ||
|
|
e13ec9aaf7 | ||
|
|
5db9bc1606 | ||
|
|
ca06ebc233 | ||
|
|
57b5243509 | ||
|
|
5f95018abe | ||
|
|
2a8b8b57e1 | ||
|
|
13d0b149d1 | ||
|
|
d7a58ae791 | ||
|
|
67eef31520 | ||
|
|
82f3198bdd | ||
|
|
429045e419 | ||
|
|
a645b9317e | ||
|
|
a9e19d3b4b | ||
|
|
2267b3e6b2 | ||
|
|
5d589ee31d | ||
|
|
28caa05292 | ||
|
|
faef643956 | ||
|
|
dee9f02cf5 | ||
|
|
44a5235d30 | ||
|
|
00eecbf7c8 | ||
|
|
798d974677 | ||
|
|
545b5a5135 | ||
|
|
a8bd28318f | ||
|
|
67138dab0f | ||
|
|
2a170584e2 | ||
|
|
b596376051 | ||
|
|
24ab06c005 | ||
|
|
511e40fa72 | ||
|
|
754d4087b4 | ||
|
|
de9a26f8ff | ||
|
|
f69a6ea82b | ||
|
|
0098fb9975 | ||
|
|
b483481c81 | ||
|
|
5b9e250c95 | ||
|
|
2efba6c0d7 | ||
|
|
1614901631 | ||
|
|
96744e9857 | ||
|
|
2d08fb98b7 | ||
|
|
12e813c432 | ||
|
|
1ca0905c52 | ||
|
|
f9f5a948b8 | ||
|
|
31eff2fc92 | ||
|
|
04df87c992 | ||
|
|
ce503c8e9a | ||
|
|
0d3f777507 | ||
|
|
a5aa85acb1 | ||
|
|
8e2bea4230 | ||
|
|
4ce883c507 | ||
|
|
fe163ef5fb | ||
|
|
901fd252f1 | ||
|
|
ed58853acc | ||
|
|
defc0486a5 | ||
|
|
c463960bc1 | ||
|
|
575b9ab425 | ||
|
|
7444678eb3 | ||
|
|
87555ce7ba | ||
|
|
7648aee85f | ||
|
|
83dfba2eb6 | ||
|
|
6f570722f4 | ||
|
|
999412e2da | ||
|
|
d7f20c4b3b | ||
|
|
add3f456c7 | ||
|
|
88d5071400 | ||
|
|
a9ba166bd4 | ||
|
|
8a92a94a3e | ||
|
|
59bc7c4cd4 | ||
|
|
2f6cb2d2ad | ||
|
|
54f9e1271a | ||
|
|
2be3459b08 | ||
|
|
31d7609858 | ||
|
|
7fcc860bea | ||
|
|
a4c8736663 | ||
|
|
ba6dd8e50e | ||
|
|
8f819f1eea | ||
|
|
d5e3621a2a | ||
|
|
e5c33037e5 | ||
|
|
d0fdf1686d | ||
|
|
7eb31f9412 | ||
|
|
aeb6f76611 | ||
|
|
03cfca8a4b | ||
|
|
4aef2b6c38 | ||
|
|
395e4a1ee4 | ||
|
|
c1cf8b414f | ||
|
|
ba0179e62f | ||
|
|
075568d3ec | ||
|
|
132a837717 | ||
|
|
9d6784cebd | ||
|
|
a6e8a83366 | ||
|
|
dbf6167aba | ||
|
|
1abf7c5749 | ||
|
|
2d64b64d68 | ||
|
|
0ba7df4064 | ||
|
|
20e930dd81 | ||
|
|
d836c0a99f | ||
|
|
98734e345f | ||
|
|
314f200477 | ||
|
|
321d3ad306 | ||
|
|
2215cace30 | ||
|
|
56381ccd55 | ||
|
|
e86b5ce0cf | ||
|
|
8b6f93625b | ||
|
|
4be2a53509 | ||
|
|
4dffca0184 | ||
|
|
7fb2435f6b | ||
|
|
a62fef46a0 | ||
|
|
e3d141a619 | ||
|
|
037da11545 | ||
|
|
9778111c58 | ||
|
|
9311918278 | ||
|
|
c1a08d8ad3 | ||
|
|
4dd28a27d3 | ||
|
|
44d82a6c54 | ||
|
|
1ec55052e6 | ||
|
|
3560f5483e | ||
|
|
c44b1f66ee | ||
|
|
d0e2b83b54 | ||
|
|
9e284e1de0 | ||
|
|
0cfdc600e7 | ||
|
|
151cfd85ed | ||
|
|
b72df1d64c | ||
|
|
d062b8c32f | ||
|
|
4749163d9c | ||
|
|
bc2a2a72be | ||
|
|
2538f46dfd | ||
|
|
bb9fc8ba83 | ||
|
|
794caced01 | ||
|
|
d473a7e187 | ||
|
|
43ccc76960 | ||
|
|
e38766f0fa | ||
|
|
8b6d0f27d8 | ||
|
|
22593cd544 | ||
|
|
719119b793 | ||
|
|
edd1665c55 | ||
|
|
b803021ce2 | ||
|
|
8992a1c7bc | ||
|
|
626440523d | ||
|
|
116c965cb4 | ||
|
|
3b2e2a2232 | ||
|
|
0b36981c3c | ||
|
|
4a70219ba4 | ||
|
|
ca12b927b5 | ||
|
|
58cb265c61 | ||
|
|
777b7e7aaf | ||
|
|
29afda8b3a | ||
|
|
6e4bedca2d | ||
|
|
e0df785ece | ||
|
|
cd5188c71e | ||
|
|
715fe59ee5 | ||
|
|
8c318fce0e | ||
|
|
4fd5b38832 | ||
|
|
68d186e686 | ||
|
|
8210c4f05d | ||
|
|
f17af9a920 | ||
|
|
b35c692e3b | ||
|
|
160114a364 | ||
|
|
83cf1b6990 | ||
|
|
2157bbf05f | ||
|
|
be8c584e84 | ||
|
|
5b14794690 | ||
|
|
e2687af6ef | ||
|
|
0ac1724f05 | ||
|
|
a52b0b4115 | ||
|
|
ba78be247e | ||
|
|
e0e1a2480d | ||
|
|
7a2ebe7f13 | ||
|
|
2291e35358 | ||
|
|
9876611eef | ||
|
|
7e29a2f4ee | ||
|
|
3fff765adf | ||
|
|
b543965f35 | ||
|
|
68cda2cd46 | ||
|
|
6879c17edd | ||
|
|
dda32c3a40 | ||
|
|
1f07a199db | ||
|
|
c495db4bc6 | ||
|
|
950028af92 | ||
|
|
089bdc64a0 | ||
|
|
32628ec43f | ||
|
|
139a91b094 | ||
|
|
18111aa744 | ||
|
|
857fe1d950 | ||
|
|
e46d104cc7 | ||
|
|
560dd8fddc | ||
|
|
a29b6d172a | ||
|
|
4b3afb5223 | ||
|
|
ca083963e9 | ||
|
|
33c1fdf629 | ||
|
|
a8793dbbc5 | ||
|
|
3ac7ee4b76 | ||
|
|
7e6b3c6ba5 | ||
|
|
137673c551 | ||
|
|
f22829ef4f | ||
|
|
9abb48526b | ||
|
|
57984fe2d6 | ||
|
|
98e284074c | ||
|
|
99e3f5d95e | ||
|
|
8ba1340e92 | ||
|
|
511cceb9d9 | ||
|
|
64e6b8387a | ||
|
|
b8592d35c0 | ||
|
|
cc76eb9d2b | ||
|
|
4189d20961 | ||
|
|
98a9801644 | ||
|
|
63be7c8743 | ||
|
|
7d5b3463cc | ||
|
|
eee2cb1b10 | ||
|
|
36b8e5903d | ||
|
|
9301506d82 | ||
|
|
bba2f7b570 | ||
|
|
f989880d48 | ||
|
|
b083de710b | ||
|
|
ce8eea7b78 | ||
|
|
196ccb29fc | ||
|
|
a92948ee7e | ||
|
|
9f2989fb62 | ||
|
|
1ab5b189dc | ||
|
|
a493e5a4d1 | ||
|
|
a8e679bf03 | ||
|
|
a61eb22b62 | ||
|
|
b93e759ba6 | ||
|
|
66e0acbb8f | ||
|
|
e75948ec01 | ||
|
|
a3ef3ae60d | ||
|
|
a021090dc9 | ||
|
|
3c87ce0fa3 | ||
|
|
86417d4781 | ||
|
|
7c52d622ba | ||
|
|
ab183d89eb | ||
|
|
4b98fa70c0 | ||
|
|
96cb2875c0 | ||
|
|
74ee33ee4c | ||
|
|
a6c7d443ae | ||
|
|
551fc98498 | ||
|
|
ecd2624d2b | ||
|
|
b4629a86e4 | ||
|
|
af28ddf201 | ||
|
|
2f2cd58c30 | ||
|
|
ed3bdf1586 | ||
|
|
d4ff1f97a9 | ||
|
|
f662ec0e67 | ||
|
|
9483fbeb5d | ||
|
|
fd6d384ba2 | ||
|
|
6d69cd3a48 | ||
|
|
ea8ec97f49 | ||
|
|
83a138f38c | ||
|
|
bed4f1ae13 | ||
|
|
aaeb90372e | ||
|
|
669f412869 | ||
|
|
62053d9a34 | ||
|
|
e4e05e2013 | ||
|
|
1fb920e039 | ||
|
|
b35762b1ec | ||
|
|
17498dbc07 | ||
|
|
d52fe75e43 | ||
|
|
aca5ad0c4b | ||
|
|
b6ed7da0a7 | ||
|
|
2abe7d688d | ||
|
|
ce794fe0be | ||
|
|
d81149dd15 | ||
|
|
f9c659612a | ||
|
|
fe9723fa15 | ||
|
|
4914c22b5d | ||
|
|
8961841847 | ||
|
|
554023c839 | ||
|
|
71ce9fea5a | ||
|
|
24aa355ed0 | ||
|
|
3273c1abe5 | ||
|
|
303213c48b | ||
|
|
744983cfc4 | ||
|
|
3a16715e03 | ||
|
|
a360301759 | ||
|
|
c212acd90b | ||
|
|
b374437fb6 | ||
|
|
fc8eda07f7 | ||
|
|
9149f77a37 | ||
|
|
fc747792a1 | ||
|
|
035a63f19e | ||
|
|
4382d8ca73 | ||
|
|
e1de247dbb | ||
|
|
d617dbfc03 | ||
|
|
0b0f9e80e4 | ||
|
|
10cc40ec5a | ||
|
|
8859587768 | ||
|
|
070ccc4fbb | ||
|
|
f80f87d77d | ||
|
|
093966f692 | ||
|
|
76184c0251 | ||
|
|
7b6e767ccb | ||
|
|
8ac3211a86 | ||
|
|
ef38bd7aa3 | ||
|
|
7e98ad725d | ||
|
|
ba72727fba | ||
|
|
19239655ed | ||
|
|
ee59fbf8d2 | ||
|
|
f7e47d2167 | ||
|
|
a979d532d5 | ||
|
|
9ff5dee979 | ||
|
|
edf525f269 | ||
|
|
1b174d5f2f | ||
|
|
9ff5982a5b | ||
|
|
5fb5652f3d | ||
|
|
dbbeb063e7 | ||
|
|
aa8c944fe9 | ||
|
|
21ac9bb45b | ||
|
|
0b3348ee77 | ||
|
|
6574d45939 | ||
|
|
ffd8a54d1e | ||
|
|
601a7f9310 | ||
|
|
1dbcf92336 | ||
|
|
a727d6f6ea | ||
|
|
e6f173df37 | ||
|
|
f4f88da945 | ||
|
|
aedafe1f4b | ||
|
|
e7f8769f61 | ||
|
|
ee809e1fe7 | ||
|
|
bb73d81256 | ||
|
|
ffbb96301e | ||
|
|
eb4f7c0d7c | ||
|
|
f60af287d3 | ||
|
|
1f97fd27a0 | ||
|
|
c8bbc2400b | ||
|
|
57142324ed | ||
|
|
0876469030 | ||
|
|
f6dcdb72ec | ||
|
|
cde38e3bb0 | ||
|
|
632abeef87 | ||
|
|
370182e3aa | ||
|
|
4ad101dca1 | ||
|
|
9db56a7fd7 | ||
|
|
d1af83e258 | ||
|
|
0e39ecaa77 | ||
|
|
2c6449b14d | ||
|
|
1cfb58d922 | ||
|
|
d94d448ee4 | ||
|
|
372395575c | ||
|
|
768d4bbab8 | ||
|
|
0922649988 | ||
|
|
39318354d3 | ||
|
|
813f1c70b7 | ||
|
|
6df78e1c9b | ||
|
|
3cf12de6c0 | ||
|
|
46102d1a76 | ||
|
|
841e9578b7 | ||
|
|
31e8c85d99 | ||
|
|
009628c3ee | ||
|
|
7da7bc8606 | ||
|
|
d71066b95e | ||
|
|
5f53da58e7 | ||
|
|
e32e3ff47d | ||
|
|
648997851c | ||
|
|
9e2e19dfa8 | ||
|
|
e571c22891 | ||
|
|
c1a3575d44 | ||
|
|
6382044f1e | ||
|
|
0a553558c4 | ||
|
|
6d8e58c5d8 | ||
|
|
f7134f6e2d | ||
|
|
7bffaa8cc3 | ||
|
|
943924adef | ||
|
|
916b971e77 | ||
|
|
16e0b19df7 | ||
|
|
3175d8ab47 | ||
|
|
4121cc49da | ||
|
|
76c7443d07 | ||
|
|
fa6de0ce67 | ||
|
|
c3bbc05f8d | ||
|
|
e4caeb66b4 | ||
|
|
3bac819760 | ||
|
|
d6674aed3e | ||
|
|
f20c7b15a4 | ||
|
|
17b9bde6e5 | ||
|
|
018c97f497 | ||
|
|
6841da5557 | ||
|
|
f9bf2dcbcd | ||
|
|
e6774023ce | ||
|
|
aac1c7ad43 | ||
|
|
32de52042d | ||
|
|
62e2ca2a64 | ||
|
|
d3ecafe0ea | ||
|
|
e17dcd11c9 | ||
|
|
d82e08281e | ||
|
|
19763bb84d | ||
|
|
ea08b92e8b | ||
|
|
4447d43c89 | ||
|
|
d33ee8a7f0 | ||
|
|
d93875b751 | ||
|
|
90cec0169f | ||
|
|
040b2c2914 | ||
|
|
b62984d540 | ||
|
|
ba5fee3f94 | ||
|
|
28277e3c54 | ||
|
|
79a08a36fa | ||
|
|
f223cd7959 | ||
|
|
6d0f129949 | ||
|
|
8dcd80ce67 | ||
|
|
653a7bf2fa | ||
|
|
d5d67b108f | ||
|
|
02f8d75273 | ||
|
|
74d56f795d | ||
|
|
64bf5681e8 | ||
|
|
d0a486d7e7 | ||
|
|
f6ab3ffd39 | ||
|
|
8eeb122a38 | ||
|
|
0ca918d814 | ||
|
|
455f4e77e0 | ||
|
|
d92f5f6cf6 | ||
|
|
d31a8188f5 | ||
|
|
f2b98ba803 | ||
|
|
4c4ec32261 | ||
|
|
bb5898835d | ||
|
|
4d52059c7d | ||
|
|
0c24bb1937 | ||
|
|
ca10cf257c | ||
|
|
4c91d27cd2 | ||
|
|
d925634e17 | ||
|
|
160c4a8864 | ||
|
|
29d1338a6d | ||
|
|
2aafe438fb | ||
|
|
96d8489170 | ||
|
|
b0148003b7 | ||
|
|
a86edf1497 | ||
|
|
e6dee77695 | ||
|
|
4da7e07703 | ||
|
|
47ef82aca1 | ||
|
|
e05fcf07b5 | ||
|
|
1f691f1d7f | ||
|
|
9df87b827b | ||
|
|
0fdbd9052a | ||
|
|
cbfce19f73 | ||
|
|
94ad930187 | ||
|
|
afa34f7bcd | ||
|
|
39822883d2 | ||
|
|
0592e0f653 | ||
|
|
065c2b78d5 | ||
|
|
d9febd8117 | ||
|
|
416d01f6df | ||
|
|
497f7bcd40 | ||
|
|
2f56d2b5ca | ||
|
|
e6195302e2 | ||
|
|
551f0753e8 | ||
|
|
d16e345064 | ||
|
|
cc6e2e626b | ||
|
|
00ddcfe6f1 | ||
|
|
2a01876c9e | ||
|
|
ae6936d3c2 | ||
|
|
bdf344fc2e | ||
|
|
e47d7e48d9 | ||
|
|
f297defea8 | ||
|
|
de3ce19eb9 | ||
|
|
57c57b7243 | ||
|
|
18080f878f | ||
|
|
3721e6ab40 | ||
|
|
eb6a79cf97 | ||
|
|
4ff7973d43 | ||
|
|
4472ea7832 | ||
|
|
14f0fb91ea | ||
|
|
1ed504154b | ||
|
|
8c7cd6f0de | ||
|
|
938938f053 | ||
|
|
c2bdb129e6 | ||
|
|
0908837392 | ||
|
|
ef116a9a53 | ||
|
|
f713c24ff8 | ||
|
|
5505bf238d | ||
|
|
34b659693e | ||
|
|
bb9dde869e | ||
|
|
7fc4e2f807 | ||
|
|
dccf79dc55 | ||
|
|
a9635b49ef | ||
|
|
d4d9a5d30f | ||
|
|
a6f0a8723c | ||
|
|
8ccbff16a9 | ||
|
|
96600b6616 | ||
|
|
b782c0aec1 | ||
|
|
7217b73e4a | ||
|
|
5e9db8eb3c | ||
|
|
6e65ad615b | ||
|
|
9345d80b17 | ||
|
|
f8caecf221 | ||
|
|
a452931ccd | ||
|
|
6348be150a | ||
|
|
359a0344f8 | ||
|
|
63987a0585 | ||
|
|
1302274bba | ||
|
|
c5c99a6f12 | ||
|
|
ded3999a12 | ||
|
|
6d856d1463 | ||
|
|
9450e3468b | ||
|
|
96009cecd9 | ||
|
|
51ee3773f7 | ||
|
|
8a92c97485 | ||
|
|
b4e2ded876 | ||
|
|
9b30b0d30a | ||
|
|
35630621b6 | ||
|
|
c5cd7a2f1d | ||
|
|
562c82dd62 | ||
|
|
9677dcb6bd | ||
|
|
08a296b867 | ||
|
|
aae0025047 | ||
|
|
0d882d31ad | ||
|
|
e630e636ad | ||
|
|
092396cc07 | ||
|
|
0b346cc0cb | ||
|
|
6493cc359f | ||
|
|
2774016518 | ||
|
|
cfc2c84409 | ||
|
|
b7bdb67eb4 | ||
|
|
f38d6221c6 | ||
|
|
b8e354b56c | ||
|
|
1a3c535e89 | ||
|
|
d4ced2f734 | ||
|
|
026233c804 | ||
|
|
2673e745f4 | ||
|
|
c3dd2cb44d | ||
|
|
a2f952ff0e | ||
|
|
7c9d773c73 | ||
|
|
8379a4a9bf | ||
|
|
c73e4f1e29 | ||
|
|
1b8c0e2749 | ||
|
|
131b86c93a | ||
|
|
51c7e414ff | ||
|
|
ca700b82c2 | ||
|
|
8db0a03081 | ||
|
|
77862a55f6 | ||
|
|
49661297ab | ||
|
|
17629f1f15 | ||
|
|
aacf36babd | ||
|
|
2b9fca8485 | ||
|
|
f4a0624470 | ||
|
|
08e5e34815 | ||
|
|
846f4aa78f | ||
|
|
e18ddb2e18 | ||
|
|
52ffc2ac28 | ||
|
|
03685ee390 | ||
|
|
4428cc2232 | ||
|
|
1e40d759fe | ||
|
|
485ba7b8ac | ||
|
|
901f75a499 | ||
|
|
4091346ae3 | ||
|
|
e4d22db19d | ||
|
|
399e9c8f1d | ||
|
|
828830c660 | ||
|
|
331952a8f5 | ||
|
|
9c2ed05bab | ||
|
|
d72ff58fe7 | ||
|
|
b94cd7d1a1 | ||
|
|
b5f9261504 | ||
|
|
15abceefeb | ||
|
|
421b860da5 | ||
|
|
03fda24c03 | ||
|
|
207c9dde45 | ||
|
|
f070833144 | ||
|
|
5048a20760 | ||
|
|
3ef7ba9fdf | ||
|
|
91ab03c0ed | ||
|
|
f1c8082252 | ||
|
|
d367eb46f0 | ||
|
|
ecea6c04e9 | ||
|
|
60ee31a074 | ||
|
|
9218553df5 | ||
|
|
7d552b4089 | ||
|
|
8660c06097 | ||
|
|
3e7021b93e | ||
|
|
5dc31e46bf | ||
|
|
ba760ab52b | ||
|
|
bd33a9d1df | ||
|
|
500cfafca3 | ||
|
|
f7b39ab754 | ||
|
|
5c2c5321bc | ||
|
|
217f3112e4 | ||
|
|
add71a9a7e | ||
|
|
ec97df9a59 | ||
|
|
1705fb7b80 | ||
|
|
a232da999d | ||
|
|
d3b965ec38 | ||
|
|
4a8b6e4f66 | ||
|
|
33828dd155 | ||
|
|
63a0c1e806 | ||
|
|
1865b26b58 | ||
|
|
a1a8f90fdb | ||
|
|
432c571f55 | ||
|
|
abc6f7b22e | ||
|
|
da5bf3ce40 | ||
|
|
3eb3976b54 | ||
|
|
0c5bde5a89 | ||
|
|
2d7722c19f | ||
|
|
95c160ca55 | ||
|
|
df302a799c | ||
|
|
5818cd4375 | ||
|
|
2ed62021f6 | ||
|
|
8872d419e2 | ||
|
|
434b0f30e8 | ||
|
|
f20a781c0b | ||
|
|
8ab8adb400 | ||
|
|
ec2591bff2 | ||
|
|
4cb8a57494 | ||
|
|
35d5e36421 | ||
|
|
99a93d77b3 | ||
|
|
d0f528892b | ||
|
|
2d7b97986f | ||
|
|
537c303a18 | ||
|
|
a7ac83cbd3 | ||
|
|
3db3e61e81 | ||
|
|
507054c9ff | ||
|
|
de42d38b31 | ||
|
|
2935181452 | ||
|
|
f04808c709 | ||
|
|
ce0938ea11 | ||
|
|
c356bc76f4 | ||
|
|
adbfb95012 | ||
|
|
dd7e94cde8 | ||
|
|
e337a34cd7 | ||
|
|
98be918c0f | ||
|
|
3778c80fd6 | ||
|
|
58986eb52e | ||
|
|
ef0a14ba63 | ||
|
|
6e9acd781f | ||
|
|
6cbdddcd61 | ||
|
|
03977fb928 | ||
|
|
aaecb99d36 | ||
|
|
4981220d83 | ||
|
|
ed7255ea0e | ||
|
|
a0a85df559 | ||
|
|
b1c4d5bad0 | ||
|
|
0e8e1edb8e | ||
|
|
f0bfc6cbf8 | ||
|
|
8b10dd3e3d | ||
|
|
c0ff6d7e08 | ||
|
|
7981d4a257 | ||
|
|
c83cbeeb22 | ||
|
|
3250c07a16 | ||
|
|
954db9ad07 | ||
|
|
c1e5b5b1e5 | ||
|
|
e5f9b50d21 | ||
|
|
c9e9dd2854 | ||
|
|
1ca08c33fd | ||
|
|
5daf1124a1 | ||
|
|
9d7d66fc99 | ||
|
|
62412c6d9f | ||
|
|
6f1c834e48 | ||
|
|
ecfb4ff31e | ||
|
|
76368ca861 | ||
|
|
3b6788fc16 | ||
|
|
4887224e45 | ||
|
|
9d20120497 | ||
|
|
2ad2fc4023 | ||
|
|
b8e4f9659a | ||
|
|
571df9cd06 | ||
|
|
3a740330ec | ||
|
|
46c6ca51cf | ||
|
|
eb11192ab7 | ||
|
|
2d5453a532 | ||
|
|
7173808ce4 | ||
|
|
c731f706f8 | ||
|
|
b965ae338c | ||
|
|
d4f2308d77 | ||
|
|
f0a1721069 | ||
|
|
c054033c54 | ||
|
|
441d8ed35e | ||
|
|
7643d11f74 | ||
|
|
ab3a53a4ec | ||
|
|
a69f639541 | ||
|
|
0471d99d13 | ||
|
|
4c453e22be | ||
|
|
2ad777025a | ||
|
|
22da4860f7 | ||
|
|
0e14b02109 | ||
|
|
e034f7c1b6 | ||
|
|
279fff4395 | ||
|
|
13d501b75b | ||
|
|
3b6f5a0abf | ||
|
|
d5266070e7 | ||
|
|
def7a08855 | ||
|
|
619e0828af | ||
|
|
6957a876e8 | ||
|
|
75bbb2399c | ||
|
|
c7baed8395 | ||
|
|
c02b4e35ba | ||
|
|
f32c6fcac8 | ||
|
|
e77d995b35 | ||
|
|
e40d03114f | ||
|
|
4e332163e2 | ||
|
|
df59469aa3 | ||
|
|
bf8523b948 | ||
|
|
ff9eccc38c | ||
|
|
48779742e3 | ||
|
|
01a09a5f90 | ||
|
|
aacb1af6b5 | ||
|
|
ae468b4de5 | ||
|
|
fc8cbf0f07 | ||
|
|
af4df5e64f | ||
|
|
0732063e18 | ||
|
|
374d96053b | ||
|
|
872e4b17b4 | ||
|
|
467d862215 | ||
|
|
e91620d17f | ||
|
|
37d0d70482 | ||
|
|
dc781447a8 | ||
|
|
15e5fb6951 | ||
|
|
133c1484f6 | ||
|
|
3e310724ff | ||
|
|
4b528280ba | ||
|
|
146b32b215 | ||
|
|
1330acbf22 | ||
|
|
5592e9dba5 | ||
|
|
75f6fac284 | ||
|
|
71c65d7354 | ||
|
|
040b45394a | ||
|
|
aa645cdfd2 | ||
|
|
153e2a63e0 | ||
|
|
fa619b59d6 | ||
|
|
255621073d | ||
|
|
5580bcde0b | ||
|
|
97c50d588f | ||
|
|
aa8916aea5 | ||
|
|
9bc578fbbe | ||
|
|
d3cbd442e7 | ||
|
|
1ce28fd500 | ||
|
|
e12359fdaa | ||
|
|
9feb4f0fcd | ||
|
|
cfa7a8b640 | ||
|
|
0202192fc0 | ||
|
|
76c3db3e5f | ||
|
|
37a6ee08dc | ||
|
|
55488ae292 | ||
|
|
a5c7db711c | ||
|
|
62d6095edb | ||
|
|
9f653d0371 | ||
|
|
d401a6c33b | ||
|
|
2239f47d45 | ||
|
|
f7f0b07361 | ||
|
|
d43e0b3e59 | ||
|
|
c015ce6ce3 | ||
|
|
772b82857b | ||
|
|
e2cdcbd5ce | ||
|
|
b5ff6695e1 | ||
|
|
8f5d7f1e7f | ||
|
|
70e6836f35 | ||
|
|
40bf54aec1 | ||
|
|
3a46607c0f | ||
|
|
11eb619fc6 | ||
|
|
54ce29d33e | ||
|
|
82807b2c5c | ||
|
|
ddd44e7753 | ||
|
|
e5d2f75606 | ||
|
|
9da17585e8 | ||
|
|
20185d0fad | ||
|
|
accdcc885d | ||
|
|
0323dd3a91 | ||
|
|
293e8eb6c5 | ||
|
|
b175ea18e2 | ||
|
|
2fb5bc8f5b | ||
|
|
90c96791be | ||
|
|
ff9834cf24 | ||
|
|
530d0ee14c | ||
|
|
4aedc1d481 | ||
|
|
950e54c990 | ||
|
|
b2960285bf | ||
|
|
ad7f7fcc37 | ||
|
|
2fc08a1c6c | ||
|
|
3954bbe862 | ||
|
|
2d028b4969 | ||
|
|
93047e67c0 | ||
|
|
66ef51a47d | ||
|
|
4dd54bab8e | ||
|
|
a2416003d6 | ||
|
|
7e14d61a34 | ||
|
|
0cb953af85 | ||
|
|
dc781a04c0 | ||
|
|
234f7bcac0 | ||
|
|
58c10e201a | ||
|
|
28892b3933 | ||
|
|
62f166f15c | ||
|
|
a193943480 | ||
|
|
dee8810f3a | ||
|
|
16905fd42c | ||
|
|
979a8f32dc | ||
|
|
4118f90b6b | ||
|
|
550f76461e | ||
|
|
b3fbba10b2 | ||
|
|
e5526572ac | ||
|
|
5944521719 | ||
|
|
835717a084 | ||
|
|
907b0aacdf | ||
|
|
e77e2dbcce | ||
|
|
d6c3a240b5 | ||
|
|
f98027e64b | ||
|
|
c45ddd7c7c | ||
|
|
0f3692928a | ||
|
|
5f86875ef2 | ||
|
|
2e0f8604e5 | ||
|
|
2c5ef742cc | ||
|
|
cdc7fed69c | ||
|
|
24ef843b65 | ||
|
|
9b2c276036 | ||
|
|
9c18764178 | ||
|
|
4e99372e6f | ||
|
|
bb44a14780 | ||
|
|
493edf8cc5 | ||
|
|
c25dd8d774 | ||
|
|
6e4115a8d0 | ||
|
|
40f86c1b5a | ||
|
|
f1bc32617d | ||
|
|
e10eab4de4 | ||
|
|
f92964f578 | ||
|
|
9963577a65 | ||
|
|
697df5846f | ||
|
|
c793082ec8 | ||
|
|
1b7811c185 | ||
|
|
fe00e26cc7 | ||
|
|
d54ba5e25f | ||
|
|
aba4dbec0a | ||
|
|
7ee202d666 | ||
|
|
0c7b727c9f | ||
|
|
03a27ecaa9 | ||
|
|
6ffd299343 | ||
|
|
a494028746 | ||
|
|
3425b58855 | ||
|
|
8adca517ce | ||
|
|
5acf252c45 | ||
|
|
88acb4c9a8 | ||
|
|
2ba0fffe85 | ||
|
|
b6e046f223 | ||
|
|
7163f2df4e | ||
|
|
da25d21898 | ||
|
|
4a78738b2a | ||
|
|
56c16666c3 | ||
|
|
7978318992 | ||
|
|
10ed681608 | ||
|
|
f9075ce252 | ||
|
|
753db12b2d | ||
|
|
20afb1c1c9 | ||
|
|
942fa6ff6e | ||
|
|
f11b22d248 | ||
|
|
6b3283e5b2 | ||
|
|
f604927cb6 | ||
|
|
9f0d3b2c4e | ||
|
|
b7262f954b | ||
|
|
44f5a062f7 | ||
|
|
396919fe6c | ||
|
|
6a67e57344 | ||
|
|
5479dce7da | ||
|
|
48c36eb5d3 | ||
|
|
183700a7d4 | ||
|
|
9dcbd7790d | ||
|
|
23f4d4702c | ||
|
|
c413d0ba6e | ||
|
|
44e2ec7f90 | ||
|
|
55c5375067 | ||
|
|
7a4a277aad | ||
|
|
9bda8031d0 | ||
|
|
8ab347f262 | ||
|
|
59d9dc2275 | ||
|
|
9fe2bdee0a | ||
|
|
05af6770b2 | ||
|
|
33b8e65002 | ||
|
|
11184ae086 | ||
|
|
446095591b | ||
|
|
9632b671be | ||
|
|
b5b6931e6b | ||
|
|
34041bb6d2 | ||
|
|
7745fb0e9b | ||
|
|
c7f14d37e9 | ||
|
|
2008f55166 | ||
|
|
fb79abcab7 | ||
|
|
cb0494d2dc | ||
|
|
cf4a273e83 | ||
|
|
f17d5b149a | ||
|
|
e3470dcad9 | ||
|
|
b42715950f | ||
|
|
6f208c5dfb | ||
|
|
567a14f93d | ||
|
|
1e716ef64f | ||
|
|
3b17a16217 | ||
|
|
7eff4f7e41 | ||
|
|
11c249c8f0 | ||
|
|
f694857e63 | ||
|
|
e9b56e5887 | ||
|
|
afcbc17250 | ||
|
|
dd60a3e43f | ||
|
|
f248e29405 | ||
|
|
31737ec68f | ||
|
|
745e9b732c | ||
|
|
ab83db8059 | ||
|
|
0dd475fcff | ||
|
|
63fe6beac2 | ||
|
|
eb13b764cf | ||
|
|
a36f862938 | ||
|
|
e688e9d39e | ||
|
|
21c829adc2 | ||
|
|
bc25f1babb | ||
|
|
cccffc57ba | ||
|
|
eab4d3cc57 | ||
|
|
bfcb075480 | ||
|
|
68e9bd813e | ||
|
|
c0442ce5cf | ||
|
|
cb3bfefd83 | ||
|
|
5568d8f777 | ||
|
|
2283ce9cbd | ||
|
|
c03b465051 | ||
|
|
dd53d178ea | ||
|
|
407892e995 | ||
|
|
293043999c | ||
|
|
f680180d95 | ||
|
|
d4d667a99d | ||
|
|
5aee086b6b | ||
|
|
d9c6da1c5f | ||
|
|
3817ee7ae2 | ||
|
|
92960e7f8a | ||
|
|
6a704a81b8 | ||
|
|
2c467919ed | ||
|
|
62461ad338 | ||
|
|
b269ce95b4 | ||
|
|
d10c024d8d | ||
|
|
05341e2bcb | ||
|
|
016b92381c | ||
|
|
1665b607cf | ||
|
|
f25ccaf67d | ||
|
|
b232a936fb | ||
|
|
22142e00ba | ||
|
|
712e80d53b | ||
|
|
a41fd8cea5 | ||
|
|
dadc294765 | ||
|
|
d6bd52e866 | ||
|
|
efab57df8b | ||
|
|
a5554933f0 | ||
|
|
22f8fbbf95 | ||
|
|
178446a8b3 | ||
|
|
b1bb35bfd9 | ||
|
|
128078ad6f | ||
|
|
1407a9849a | ||
|
|
36f95702e1 | ||
|
|
172b2f9ea2 | ||
|
|
dce3efe71b | ||
|
|
b5f98be162 | ||
|
|
6c9913e5f1 | ||
|
|
8f9867d028 | ||
|
|
9293d7599c | ||
|
|
73ae281bba | ||
|
|
0a8ed76315 | ||
|
|
239f537742 | ||
|
|
a37cb35829 | ||
|
|
7a95e0439e | ||
|
|
dfee961458 | ||
|
|
54a72bd714 | ||
|
|
cd0fad79e8 | ||
|
|
cd1fe7db29 | ||
|
|
44dc379053 | ||
|
|
1887b0e13c | ||
|
|
41e0d3ad8b | ||
|
|
b39bc5a218 | ||
|
|
895e34856d | ||
|
|
196b72448d | ||
|
|
2cd1bd9201 | ||
|
|
8b3d894df1 | ||
|
|
ed2cbfed65 | ||
|
|
06e55831f1 | ||
|
|
3f2cf39f45 | ||
|
|
1e4a58da2a | ||
|
|
73c7f8713b | ||
|
|
7acf191f61 | ||
|
|
c427244469 | ||
|
|
5bf10b60b1 | ||
|
|
103276eda3 | ||
|
|
4ca0be8c21 | ||
|
|
94747c9932 | ||
|
|
10ffddc2f1 | ||
|
|
1a424162c7 | ||
|
|
491e6220ca | ||
|
|
0cea45164e | ||
|
|
ed5aeff441 | ||
|
|
e547187490 | ||
|
|
b972b5eff3 | ||
|
|
60fb02f387 | ||
|
|
c8e9e291ad | ||
|
|
e6e0b6d3be | ||
|
|
5cfd640131 | ||
|
|
e92f791c81 | ||
|
|
0803780a30 | ||
|
|
ce8b075f46 | ||
|
|
1cab380c83 | ||
|
|
f195f8cee1 | ||
|
|
c04867451b | ||
|
|
da48b5a146 | ||
|
|
b8a7cebf08 | ||
|
|
eda607ff21 | ||
|
|
7179f426e2 | ||
|
|
f0dce68553 | ||
|
|
bcb726144f | ||
|
|
5ab570f1f3 | ||
|
|
8f1757bd39 | ||
|
|
0d92aa21fb | ||
|
|
ca53e56ee1 | ||
|
|
5a70d3ddfe | ||
|
|
b2b55dc151 | ||
|
|
ee172502fe | ||
|
|
91590b69ef | ||
|
|
c03fbbf11f | ||
|
|
aa707d9afb | ||
|
|
81f4a207a7 | ||
|
|
af70eb5ee6 | ||
|
|
53d79bfda8 | ||
|
|
d3b6a7505f | ||
|
|
b64ed343c2 | ||
|
|
0d48c6b1e9 | ||
|
|
9c050b3c6e | ||
|
|
45b6d20aaa | ||
|
|
1419a85f83 | ||
|
|
31889030f1 | ||
|
|
b676c67b96 | ||
|
|
a088a6718e | ||
|
|
ca284ed72f | ||
|
|
69807a729d | ||
|
|
81262a0711 | ||
|
|
bdb7bee0b0 | ||
|
|
cc30178aaa | ||
|
|
65cbc8455a | ||
|
|
c5a4914103 | ||
|
|
7c326bcac5 | ||
|
|
a315e2d8c6 | ||
|
|
0b8d271536 | ||
|
|
016b5c79f9 | ||
|
|
10255164d5 | ||
|
|
430307e574 | ||
|
|
c4859cbd03 | ||
|
|
e9fa175d91 | ||
|
|
62c6acbd0c | ||
|
|
5d613886fe | ||
|
|
89efc7b4b3 | ||
|
|
dae5e69f7e | ||
|
|
87ea05ba9a | ||
|
|
64e8a7bae8 | ||
|
|
3d874b9326 | ||
|
|
35b954ab46 | ||
|
|
38291f1fc3 | ||
|
|
ecbf8f2fe5 | ||
|
|
ba7cefc48b | ||
|
|
bba55adcb9 | ||
|
|
eb549a5515 | ||
|
|
691aa7ad04 | ||
|
|
56c2c389c7 | ||
|
|
b3a1f8bd8b | ||
|
|
2d93350d03 | ||
|
|
4d93472df0 | ||
|
|
4f1e70a06b | ||
|
|
430c408383 | ||
|
|
0303129006 | ||
|
|
0c88313682 | ||
|
|
4662bd7312 | ||
|
|
11c6ccb025 | ||
|
|
1ece504bd6 | ||
|
|
83440e6da8 | ||
|
|
193448929f | ||
|
|
b51682fce4 | ||
|
|
74e351475e | ||
|
|
09059a0fe8 | ||
|
|
fb990f4ba7 | ||
|
|
34d266b0fb | ||
|
|
733ac56aa4 | ||
|
|
772f8abc98 | ||
|
|
6a0759227f | ||
|
|
7985c2db16 | ||
|
|
b633688bbd | ||
|
|
3562b6cd6f | ||
|
|
c2c66fb29f | ||
|
|
13495b8c63 | ||
|
|
619b00c8b5 | ||
|
|
d4c520d97a | ||
|
|
9ca6cfcaba | ||
|
|
cce6cd417c | ||
|
|
625e9b7183 | ||
|
|
598817a02e | ||
|
|
6255bed777 | ||
|
|
fb5fb3df16 | ||
|
|
e5e8a566e2 | ||
|
|
743b76d3ec | ||
|
|
df28ac7a78 | ||
|
|
e3e9e92b44 | ||
|
|
1005690acb | ||
|
|
132bfc5d05 | ||
|
|
671101d201 | ||
|
|
29ac0677af | ||
|
|
7c460fc13b | ||
|
|
1283a0c5a9 | ||
|
|
30991d7d49 | ||
|
|
0c2adc7f4b | ||
|
|
c8cbe8c871 | ||
|
|
0cef0c5971 | ||
|
|
192a5dfdcc | ||
|
|
f983a2b405 | ||
|
|
b940d95a01 | ||
|
|
b3aba1f5e3 | ||
|
|
0a5cf9dbc3 | ||
|
|
f20debdc48 | ||
|
|
750ba5571f | ||
|
|
7f7489c6a7 | ||
|
|
588025aa88 | ||
|
|
c86c7a8c88 | ||
|
|
2edf7f8321 | ||
|
|
3693f6f799 | ||
|
|
305e0845ae | ||
|
|
150375160f | ||
|
|
63edc5697e | ||
|
|
dad0b7b904 | ||
|
|
8d4083f038 | ||
|
|
9ff3c0938a | ||
|
|
324022743b | ||
|
|
dc79ab4a25 | ||
|
|
752020de1a | ||
|
|
c039fae343 | ||
|
|
26e1e276ff | ||
|
|
408ad49dc0 | ||
|
|
ed8a88bae3 | ||
|
|
02f3d3b271 | ||
|
|
8bf1ea1d4a | ||
|
|
ee434d9376 | ||
|
|
744b4d0919 | ||
|
|
4a9fa84d77 | ||
|
|
fb349a964e | ||
|
|
02e026c09a | ||
|
|
3b5b023dbb | ||
|
|
fb9b8727a0 | ||
|
|
b3355f1de5 | ||
|
|
a777b33389 | ||
|
|
8ca69c669f | ||
|
|
fc5b454ad3 | ||
|
|
6dba4ba186 | ||
|
|
ad380bb233 | ||
|
|
dd256a9252 | ||
|
|
594d3770b2 | ||
|
|
56a833516d | ||
|
|
f1b750f73b | ||
|
|
4a2f8dd3fe | ||
|
|
2af3fbc31e | ||
|
|
d6bb29d962 | ||
|
|
848502448e | ||
|
|
d39850809b | ||
|
|
e06b2d01ca | ||
|
|
4efdf94daa | ||
|
|
d0e9edccf2 | ||
|
|
8b28bdca22 | ||
|
|
824309f626 | ||
|
|
ef62697950 | ||
|
|
9fc3529511 | ||
|
|
9d6e83875d | ||
|
|
cc1205f6b4 | ||
|
|
98609fde69 | ||
|
|
a0f8d02993 | ||
|
|
83ab65396f | ||
|
|
b8153e9f20 | ||
|
|
4808a18305 | ||
|
|
d2229e965a | ||
|
|
f1bb0bfa71 | ||
|
|
a466c19af1 | ||
|
|
832527d0dc | ||
|
|
cc29c2a318 | ||
|
|
d0a017f6bf | ||
|
|
08d131a2f1 | ||
|
|
b63604882c | ||
|
|
8b7b3f27ed | ||
|
|
abc051cad1 | ||
|
|
e2b1351424 | ||
|
|
8c01cd4605 | ||
|
|
406030544c | ||
|
|
1a5abdef7b | ||
|
|
42c6c37ed8 | ||
|
|
5283af224f | ||
|
|
e0a656864e | ||
|
|
a8fafbf87b | ||
|
|
9dd993fe3f | ||
|
|
7cb681f293 | ||
|
|
b695420114 | ||
|
|
9fde2e3361 | ||
|
|
62f66c0c01 | ||
|
|
73e464848f | ||
|
|
697d256730 | ||
|
|
1197bcfdd4 | ||
|
|
19096e2f14 | ||
|
|
c4b279c9be | ||
|
|
a3f64221df | ||
|
|
afc2569f38 | ||
|
|
d156cf87ec | ||
|
|
b232d4c27e | ||
|
|
a5656d15b4 | ||
|
|
7147e0a85c | ||
|
|
1ffc212583 | ||
|
|
172c6efbf9 | ||
|
|
1fdc441e56 | ||
|
|
868c424f52 | ||
|
|
99e022728d | ||
|
|
9cdca9efe5 | ||
|
|
9ef0dd02dd | ||
|
|
1521abf34b | ||
|
|
9c16e62deb | ||
|
|
98de9c6bfd | ||
|
|
cf36456303 | ||
|
|
99d8487b29 | ||
|
|
dbd09e5f32 | ||
|
|
d5718b5e52 | ||
|
|
d206d5d3cf | ||
|
|
e8b5f46dfd | ||
|
|
df9b7b32cb | ||
|
|
05f8b0b524 | ||
|
|
7b281df7ae | ||
|
|
6c92415de8 | ||
|
|
0787491822 | ||
|
|
11717b61a2 | ||
|
|
3c223e63e6 | ||
|
|
d8a599832c | ||
|
|
a7e139c5f8 | ||
|
|
7a128d4ba4 | ||
|
|
a8005ad4ec | ||
|
|
b6537a5cfd | ||
|
|
3f065f4241 | ||
|
|
3638d2aa94 | ||
|
|
04c13c16ab | ||
|
|
3af24aa339 | ||
|
|
5b758818b6 | ||
|
|
185460341e | ||
|
|
20e76dfc1c | ||
|
|
7d01a4be3d | ||
|
|
3c759b7c14 | ||
|
|
c2a61c1584 | ||
|
|
ab751b7ac8 | ||
|
|
7a43ae5e9d | ||
|
|
03dbb4489b | ||
|
|
039b535098 | ||
|
|
d98156faed | ||
|
|
ea7219f37b | ||
|
|
a76f6d6dee | ||
|
|
18bf29bdcc | ||
|
|
e6cc96e901 | ||
|
|
21ffe6957d | ||
|
|
503b0c0f6e | ||
|
|
e238d52444 | ||
|
|
3137a23a1c | ||
|
|
2b5ec2a949 | ||
|
|
ac33f904c3 | ||
|
|
7e36d208cd | ||
|
|
58763a62d7 | ||
|
|
8162523549 | ||
|
|
1e0d104cda | ||
|
|
616867b3b5 | ||
|
|
981d5b9380 | ||
|
|
103e51bee0 | ||
|
|
d209ad08ea | ||
|
|
fcd327ce7d | ||
|
|
fba5df03d9 | ||
|
|
18c2c4797b | ||
|
|
f9a4770f4c | ||
|
|
6ea54f25c9 | ||
|
|
70986f5a51 | ||
|
|
64e6048d7b | ||
|
|
97c471b71b | ||
|
|
706008fcd7 | ||
|
|
6ab971d51b | ||
|
|
da8281e387 | ||
|
|
56a359a823 | ||
|
|
e6a882d265 | ||
|
|
5b1a514db7 | ||
|
|
6706d359f4 | ||
|
|
63f00db931 | ||
|
|
71d366a6a1 | ||
|
|
ca5a614a55 | ||
|
|
b307461d46 | ||
|
|
8d27102a46 | ||
|
|
84f775620f | ||
|
|
6ccb4f0be1 | ||
|
|
8132bbe3a3 | ||
|
|
fc0c528037 | ||
|
|
4a7b11de86 | ||
|
|
4860e467cb | ||
|
|
7efcf6c93d | ||
|
|
d5d6c5fe77 | ||
|
|
ec9665cdca | ||
|
|
3ec89e0d72 | ||
|
|
fd7a548afb | ||
|
|
22f1ed41f7 | ||
|
|
6e8fb09aa1 | ||
|
|
88dac21b21 | ||
|
|
a5559b1d35 | ||
|
|
8bfecf21f7 | ||
|
|
a73fddfeb2 | ||
|
|
d50823e6a1 | ||
|
|
c9a1441c6d | ||
|
|
708b7251b6 | ||
|
|
77a680ac37 | ||
|
|
c91b4a7e52 | ||
|
|
f47e224d3f | ||
|
|
f5da939bfa | ||
|
|
c41efde6a6 | ||
|
|
4b41832be7 | ||
|
|
052134d392 | ||
|
|
30bdde839f | ||
|
|
0e30e972d1 | ||
|
|
6109edea6e | ||
|
|
190b797751 | ||
|
|
ce73cbfbe7 | ||
|
|
60fe5b600e | ||
|
|
6be2c41823 | ||
|
|
a741795ef3 | ||
|
|
e2f3f83265 | ||
|
|
49622faa7e | ||
|
|
06c9663ae9 | ||
|
|
c068a99e76 | ||
|
|
0cab93c2c2 | ||
|
|
48cc504124 | ||
|
|
daa45cc516 | ||
|
|
e54a722ec5 | ||
|
|
c72c325417 | ||
|
|
ea297fc23e | ||
|
|
fe0210d573 | ||
|
|
8db7a77fdf | ||
|
|
999c79559f | ||
|
|
7ed91a6084 | ||
|
|
d82c49b0d6 | ||
|
|
3ed9b30994 | ||
|
|
32076acbad | ||
|
|
02e4ca294f | ||
|
|
fb9d7cac53 | ||
|
|
9b70958c0c | ||
|
|
fe2e8398c3 | ||
|
|
2c7245298f | ||
|
|
5e209bff32 | ||
|
|
e0855bee7b | ||
|
|
ae5cd0a99d | ||
|
|
0c64282391 | ||
|
|
3d3a479a59 | ||
|
|
16e1fbd9a9 | ||
|
|
1c934d5a82 | ||
|
|
a127ac9b53 | ||
|
|
8548c72d22 | ||
|
|
914ab93ab8 | ||
|
|
124cc050f3 | ||
|
|
0aa54010a9 | ||
|
|
5c1870e9f7 | ||
|
|
958973b57c | ||
|
|
c71d087695 | ||
|
|
bb9b131b2f | ||
|
|
9ac60549c7 | ||
|
|
75a590a411 | ||
|
|
ad65f25950 | ||
|
|
f37ad00984 | ||
|
|
86ce735062 | ||
|
|
0b6897c1ed | ||
|
|
eaa58a5ba0 | ||
|
|
c3d3242001 | ||
|
|
827200c6f9 | ||
|
|
84478220e9 | ||
|
|
5ec7d838ac | ||
|
|
82e379ee7f | ||
|
|
10307291a3 | ||
|
|
a260a921ba | ||
|
|
62b0d2a971 | ||
|
|
ac598c7f95 | ||
|
|
9641415a00 | ||
|
|
4f61036847 | ||
|
|
46a09116ea | ||
|
|
75a62b741e | ||
|
|
67b5cae29f | ||
|
|
905876f865 | ||
|
|
d20128add5 | ||
|
|
110e421dd6 | ||
|
|
b13f1f4de7 | ||
|
|
7b240cab34 | ||
|
|
a3ce48f14f | ||
|
|
3b8500c410 | ||
|
|
37f8c5e48f | ||
|
|
b4f51d1353 | ||
|
|
1cabb14bcc | ||
|
|
d59c998b71 | ||
|
|
f8e868eaaf | ||
|
|
7c38e5b8c6 | ||
|
|
d164830770 | ||
|
|
5232186a3b | ||
|
|
828ab6cf4b | ||
|
|
45a6a08fc1 | ||
|
|
25c480ae22 | ||
|
|
78ac25b752 | ||
|
|
5de00da3ec | ||
|
|
6cddde08eb | ||
|
|
e2950fbdef | ||
|
|
02bac76d1a | ||
|
|
7474ed9b4f | ||
|
|
8b4bc7cdc9 | ||
|
|
27cbed207b | ||
|
|
b781f90046 | ||
|
|
520aa075fa | ||
|
|
0aab46588d | ||
|
|
02e835eb06 | ||
|
|
668a0dad9a | ||
|
|
8249756bcf | ||
|
|
2e4c1dfe4d | ||
|
|
51481fb054 | ||
|
|
3044ac0c88 | ||
|
|
b8334d3463 | ||
|
|
95ac0d9f8f | ||
|
|
6c2ef63847 | ||
|
|
ae3bf436b4 | ||
|
|
084bc60d5e | ||
|
|
ac1c8efd8e | ||
|
|
445bcb70b7 | ||
|
|
d01682da21 | ||
|
|
1404ceb38f | ||
|
|
9a545a9e7c | ||
|
|
91fee46a59 | ||
|
|
8fcb28a0dd | ||
|
|
1e2b9f0623 | ||
|
|
be0f596abe | ||
|
|
5f1c9dbf1f | ||
|
|
076077223a | ||
|
|
f1310f303f | ||
|
|
85676cf023 | ||
|
|
ecc7da732b | ||
|
|
db2a58ca44 | ||
|
|
9c80c0f3ac | ||
|
|
7b7ea2ab5f | ||
|
|
3418bcc3a9 | ||
|
|
55c1299619 | ||
|
|
6242966f44 | ||
|
|
f5fb8497bc | ||
|
|
c165021b49 | ||
|
|
dfc1d2e5cd | ||
|
|
fe36d60c66 | ||
|
|
f765b285f0 | ||
|
|
3d9656c4c2 | ||
|
|
8daa190351 | ||
|
|
b2c73f6d1a | ||
|
|
44aa8ed11b | ||
|
|
6681d17624 | ||
|
|
40097efbb5 | ||
|
|
0f70b5da31 | ||
|
|
02a19fecbf | ||
|
|
4dc5f6a249 | ||
|
|
ebe0183de0 | ||
|
|
62899daa17 | ||
|
|
75b36463f1 | ||
|
|
5f5f72b65d | ||
|
|
e21c920507 | ||
|
|
93bef66767 | ||
|
|
12642d523d | ||
|
|
96e7b665f7 | ||
|
|
d721b41b95 | ||
|
|
7fa1db8982 | ||
|
|
c334873c26 | ||
|
|
9e95d5fe97 | ||
|
|
f6043b5477 | ||
|
|
729dc8464e | ||
|
|
c761d083a7 | ||
|
|
79c171655b | ||
|
|
73a5d22041 | ||
|
|
f53bef95bf | ||
|
|
9bc577a83a | ||
|
|
189d1c7c1d | ||
|
|
9073e4b987 | ||
|
|
56d37467d1 | ||
|
|
3d05a6ee1e | ||
|
|
ab196b35a6 | ||
|
|
1f519121f8 | ||
|
|
08d34a9efe | ||
|
|
4cd8781fd8 | ||
|
|
74ff48840b | ||
|
|
a6e8aa6d01 | ||
|
|
6069c461e8 | ||
|
|
ad67c2958e | ||
|
|
a7dec45c8e | ||
|
|
fa58e1f79b | ||
|
|
b772c6351c | ||
|
|
4e66ceffc3 | ||
|
|
2d669b4361 | ||
|
|
5fd6bc9984 | ||
|
|
5b05c870fb | ||
|
|
d051dc2560 | ||
|
|
14644f91a6 | ||
|
|
36d2fb8723 | ||
|
|
5c99214ae3 | ||
|
|
1aaf9e63ec | ||
|
|
5fbbb114c8 | ||
|
|
f71da9fb42 | ||
|
|
7439befa31 | ||
|
|
c95adcbd01 | ||
|
|
ddd91341b6 | ||
|
|
279fa2ff20 | ||
|
|
f56035caa3 | ||
|
|
d8d5cf21aa | ||
|
|
b29e0b82d1 | ||
|
|
70224401c5 | ||
|
|
354acbbdf6 | ||
|
|
4a35054446 | ||
|
|
60ff870274 | ||
|
|
05659e5873 | ||
|
|
005d6e6cff | ||
|
|
19bb696722 | ||
|
|
3ea5b0ee37 | ||
|
|
4acbab01b6 | ||
|
|
750ab79d4c | ||
|
|
fe1978d289 | ||
|
|
208fb75e1e | ||
|
|
a7d77a9cc7 | ||
|
|
66763faef8 | ||
|
|
5f6d331965 | ||
|
|
cd291cbcac | ||
|
|
07c31ce81e | ||
|
|
59d501a2f0 | ||
|
|
1dfee4eac7 | ||
|
|
56999599ed | ||
|
|
726d38b442 | ||
|
|
57ac38fb09 | ||
|
|
2461cfd745 | ||
|
|
98463a3ce6 | ||
|
|
f25bea90f1 | ||
|
|
774241a179 | ||
|
|
4293eadf63 | ||
|
|
210f49cb4a | ||
|
|
56d92f5c93 | ||
|
|
fb9f96a54b | ||
|
|
fd7111f802 | ||
|
|
5215b50c73 | ||
|
|
4ca3cfe1a5 | ||
|
|
d875cafb78 | ||
|
|
1bf8fbc52b | ||
|
|
ec8cb4c19a | ||
|
|
18222286f0 | ||
|
|
b3988c9aa1 | ||
|
|
7c857fd537 | ||
|
|
efb381eb97 | ||
|
|
56882ee489 | ||
|
|
1b1f2b0bb1 | ||
|
|
f4d1181d99 | ||
|
|
b4193e24b5 | ||
|
|
a676df2c6c | ||
|
|
44efdff9ec | ||
|
|
710ac88a43 | ||
|
|
5a989cd62f | ||
|
|
8bc07ca700 | ||
|
|
9b14d0b4a6 | ||
|
|
9d67bae487 | ||
|
|
95d3cc67cb | ||
|
|
2ecdc752e4 | ||
|
|
6a5b254a75 | ||
|
|
8944d1522e | ||
|
|
3524485249 | ||
|
|
70e713d68b | ||
|
|
16616c65a6 | ||
|
|
01fa5ffec8 | ||
|
|
cb1fb02d86 | ||
|
|
914402aa2a | ||
|
|
04a63da6ab | ||
|
|
61eba36c67 | ||
|
|
82e38cb7c4 | ||
|
|
e88fe2ed61 | ||
|
|
556570a51a | ||
|
|
41cf5904e5 | ||
|
|
ebe949b585 | ||
|
|
2bfaa0092d | ||
|
|
d5aee29558 | ||
|
|
d3caa9dcd4 | ||
|
|
e909c929b1 | ||
|
|
cbad4f651e | ||
|
|
a13e8c4544 | ||
|
|
1994b84810 | ||
|
|
263e9b7337 | ||
|
|
ce7210ea8b | ||
|
|
c121fad03f | ||
|
|
8d81ed3baa | ||
|
|
d6616c8b76 | ||
|
|
18ee400d6f | ||
|
|
d0db63c3b0 | ||
|
|
f603de9030 | ||
|
|
74d12c4303 | ||
|
|
cce68c323e | ||
|
|
a3540aef6f | ||
|
|
7e5fe95928 | ||
|
|
10df024bb2 | ||
|
|
bbb8ca15c6 | ||
|
|
2769ac2ef5 | ||
|
|
e047f62511 | ||
|
|
5f6a94247e | ||
|
|
81357e15e4 | ||
|
|
46233883c3 | ||
|
|
5481454bf6 | ||
|
|
bb0b1f2bce | ||
|
|
ffa8a44320 | ||
|
|
7a9f50c0da | ||
|
|
7888a1e725 | ||
|
|
117ebfd097 | ||
|
|
76487a1244 | ||
|
|
018aec0150 | ||
|
|
c33ccaba98 | ||
|
|
14dcd69a1d | ||
|
|
aea236bd18 | ||
|
|
4e01d3acd6 | ||
|
|
c35f7da532 | ||
|
|
163bd0328a | ||
|
|
94cc923d01 | ||
|
|
01735954dc | ||
|
|
affd9258c5 | ||
|
|
cffa342841 | ||
|
|
596ac24499 | ||
|
|
634def86ee | ||
|
|
6e7e99201e | ||
|
|
ce92cddf0e | ||
|
|
322b103481 | ||
|
|
f35585b3ac | ||
|
|
fc058fcfa7 | ||
|
|
f4332c779e | ||
|
|
7036cb8ea2 | ||
|
|
f1af8a76e5 | ||
|
|
d638ecd111 | ||
|
|
a8b4ef9230 | ||
|
|
cc2a46a19b | ||
|
|
3f603be776 | ||
|
|
e7c5830c48 | ||
|
|
9da829723d | ||
|
|
978b79f38a | ||
|
|
076b2e2ae1 | ||
|
|
ecaf1cba88 | ||
|
|
54619917ae | ||
|
|
bf63b3dc2b | ||
|
|
fa8356aec1 | ||
|
|
53f0f51c7b | ||
|
|
d3ea853e4c | ||
|
|
90ff40fbf0 | ||
|
|
86b6b8ed50 | ||
|
|
55bbf70d3f | ||
|
|
ca2c61ee64 | ||
|
|
f4033c69bd | ||
|
|
a5818e43b5 | ||
|
|
3c18636e23 | ||
|
|
2917bf9fda | ||
|
|
2abb1097e3 | ||
|
|
05fea68f82 | ||
|
|
b5eda738c9 | ||
|
|
4a97a0f999 | ||
|
|
04681237c0 | ||
|
|
5926c4392f | ||
|
|
bfe2879893 | ||
|
|
2ff05c4837 | ||
|
|
3a100f96e7 | ||
|
|
69bfc3f47e | ||
|
|
e3db6c60de | ||
|
|
449eaf70f0 | ||
|
|
4b8f772538 | ||
|
|
485923abd7 | ||
|
|
f24f5cbdd6 | ||
|
|
32ef28f1e6 | ||
|
|
2286436602 | ||
|
|
53a5a88bfa | ||
|
|
f46f7e1e74 | ||
|
|
3e1db58144 | ||
|
|
807813ecdb | ||
|
|
a4b2e18052 | ||
|
|
b72f5d06b6 | ||
|
|
cffc96ca8a | ||
|
|
86d1b4929e | ||
|
|
7bc51655b9 | ||
|
|
2c6a2f232d | ||
|
|
3f72e53bc4 | ||
|
|
272c5b62c2 | ||
|
|
8e3e40d790 | ||
|
|
c6cdd7c66a | ||
|
|
9b36fe0bc8 | ||
|
|
4c0bbba6f7 | ||
|
|
de2144819e | ||
|
|
62618ca6b3 | ||
|
|
5d8e70da95 | ||
|
|
ed3dddd5a5 | ||
|
|
a3cbbd4617 | ||
|
|
b71ec29db6 | ||
|
|
8326475a9f | ||
|
|
5023fc5c90 | ||
|
|
59e9ae9480 | ||
|
|
0ab099825d | ||
|
|
8bca529bd3 | ||
|
|
88ab57eba7 | ||
|
|
383f0ce39f | ||
|
|
3931915ee8 | ||
|
|
82fa47fc6c | ||
|
|
7667b4daa6 | ||
|
|
f63772668e | ||
|
|
f05755d55c | ||
|
|
cc78d19fc9 | ||
|
|
10ecf62ed5 | ||
|
|
47ff924184 | ||
|
|
1c3d7438c1 | ||
|
|
45d7dd7dd9 | ||
|
|
31caeea6d4 | ||
|
|
1f3298b2e5 | ||
|
|
aef6803a76 | ||
|
|
ba93a87eed | ||
|
|
4d14071ede | ||
|
|
39934033b8 | ||
|
|
5a98059387 | ||
|
|
eddb8bec4a | ||
|
|
e8f91f4908 | ||
|
|
94fcdfcded | ||
|
|
741563fa62 | ||
|
|
0feb8c7a3c | ||
|
|
08506e011f | ||
|
|
4d2f54f5df | ||
|
|
34a5022f0c | ||
|
|
40b2265cdc | ||
|
|
32371bf2a7 | ||
|
|
b39c7b2cf0 | ||
|
|
b91054e783 | ||
|
|
913ff1bd63 | ||
|
|
5fdf235ae2 | ||
|
|
851728e46d | ||
|
|
b3ef6ca846 | ||
|
|
0371173830 | ||
|
|
53cc837dcb | ||
|
|
d1a99eee6b | ||
|
|
ce2c45aa44 | ||
|
|
c1ac8c2fbd | ||
|
|
89765d28bb | ||
|
|
4c764ea54a | ||
|
|
cf6b7989b6 | ||
|
|
54eac655af | ||
|
|
377149948e | ||
|
|
ad4d087dde | ||
|
|
0f2e551c7a | ||
|
|
689dd037c1 | ||
|
|
a4d8c19247 | ||
|
|
ec269d9671 | ||
|
|
ccb691edd8 | ||
|
|
084a7292a1 | ||
|
|
e0ad32c044 | ||
|
|
7c3e5aba0c | ||
|
|
324c502ce3 | ||
|
|
76125f45ae | ||
|
|
2c024d10ba | ||
|
|
dabf142759 | ||
|
|
f9a7ca4d19 | ||
|
|
721a427351 | ||
|
|
a6e613bdec | ||
|
|
558096748f | ||
|
|
51fbd7c620 | ||
|
|
629967b7d1 | ||
|
|
7a23dbfb30 | ||
|
|
043aadcb2c | ||
|
|
301a12b57d | ||
|
|
a228944434 | ||
|
|
f59e733fe2 | ||
|
|
c3c008ff72 | ||
|
|
6b26b26115 | ||
|
|
7c4a6caa9a | ||
|
|
9d3556e557 | ||
|
|
e22e09122c | ||
|
|
b4c5b5a77a | ||
|
|
0f79fc3037 | ||
|
|
12bb87931e | ||
|
|
b259102d6c | ||
|
|
91c6396dac | ||
|
|
fe7d9baa38 | ||
|
|
ea8743fa99 | ||
|
|
9e11f02a45 | ||
|
|
0ac7aabf9a | ||
|
|
1488accbe3 | ||
|
|
bd91b28335 | ||
|
|
adc9eb5b09 | ||
|
|
8e5368f83f | ||
|
|
390db416d8 | ||
|
|
1d1a427c7b | ||
|
|
8695bef4f4 | ||
|
|
551584d7e9 | ||
|
|
668561f006 | ||
|
|
79141e173c | ||
|
|
7a6fe0d91e | ||
|
|
efd68b6453 | ||
|
|
a7b861e4be | ||
|
|
b304d86fc4 | ||
|
|
76d18490f2 | ||
|
|
4f1e642eb8 | ||
|
|
e4b28b4d61 | ||
|
|
5ee5366b4b | ||
|
|
be370beb05 | ||
|
|
87895ab946 | ||
|
|
7645daa9f6 | ||
|
|
ac7b345de7 | ||
|
|
3a9963c81b | ||
|
|
b265d1b432 | ||
|
|
41f7b8ee47 | ||
|
|
b2310cfa75 | ||
|
|
41c22deb91 | ||
|
|
8cabdb80ee | ||
|
|
704d33d956 | ||
|
|
bbdb5a72da | ||
|
|
16aa1ebf2c | ||
|
|
96dd511773 | ||
|
|
4b6fc40588 | ||
|
|
8aff5a7f8b | ||
|
|
ff64a49a40 | ||
|
|
8c1da2dd43 | ||
|
|
49a714e3b8 | ||
|
|
c18921a5c2 | ||
|
|
86e5f8dd49 | ||
|
|
aad2e38603 | ||
|
|
5becf2c98c | ||
|
|
2dbbf69a4c | ||
|
|
5364befc75 | ||
|
|
6f0c50312b | ||
|
|
af753bba8a | ||
|
|
335af65709 | ||
|
|
592afff827 | ||
|
|
6d8e1e754f | ||
|
|
a010787d26 | ||
|
|
ae16e052d3 | ||
|
|
a2fd2b8bd8 | ||
|
|
47b12bb07a | ||
|
|
7479ef770c | ||
|
|
8cfd6d6652 | ||
|
|
89163b09e7 | ||
|
|
b6d7d4309a | ||
|
|
19eec3e108 | ||
|
|
d3391efc2b | ||
|
|
b1c370f959 | ||
|
|
c887486970 | ||
|
|
9ece2de5ba | ||
|
|
e7467199f2 | ||
|
|
7dab795f76 | ||
|
|
3c37cede17 | ||
|
|
4582640d68 | ||
|
|
d4afb33d48 | ||
|
|
bbe9c6b77e | ||
|
|
42b187a0ed | ||
|
|
04176f3f23 | ||
|
|
af9d3d3f8a | ||
|
|
eceb0ac2af | ||
|
|
2164a025f3 | ||
|
|
15a02f5664 | ||
|
|
a056753edc | ||
|
|
6a101b4053 | ||
|
|
2299eee106 | ||
|
|
b3f10dd6eb | ||
|
|
383d6f0057 | ||
|
|
20d14c0bdd | ||
|
|
ca81c35486 | ||
|
|
958cd9321a | ||
|
|
8d9f15ca3e | ||
|
|
dbbf061121 | ||
|
|
40f1eb46cc | ||
|
|
ee1c264aac | ||
|
|
2acd7c30f4 | ||
|
|
f69036f5a3 | ||
|
|
caa6bd61cd | ||
|
|
b23a230e4d | ||
|
|
cb753ec048 | ||
|
|
14e3ce8c06 | ||
|
|
8db16c5100 | ||
|
|
5e352fe3e6 | ||
|
|
4e0cccbce0 | ||
|
|
e570d4c93a | ||
|
|
28ad50e43b | ||
|
|
2a1b5c6cd1 | ||
|
|
0ec091a5c8 | ||
|
|
0edd99a0fd | ||
|
|
4e34a96649 | ||
|
|
4ac2fbe0b7 | ||
|
|
13f27e2597 | ||
|
|
32a59c0c26 | ||
|
|
1dc7698746 | ||
|
|
a96ee4a2dd | ||
|
|
c5d76a2cc0 | ||
|
|
3c3954139c | ||
|
|
5151f878f5 | ||
|
|
8044cf04e4 | ||
|
|
857f4e117d | ||
|
|
d60a24c241 | ||
|
|
bb46a77302 | ||
|
|
6876908e4f | ||
|
|
a5e1a9b03d | ||
|
|
dd66e315a7 | ||
|
|
da541ef962 | ||
|
|
55174a60bb | ||
|
|
cb3bb62177 | ||
|
|
2e03d0f81e | ||
|
|
82bb9c63b8 | ||
|
|
d266f7521c | ||
|
|
4d01c50084 | ||
|
|
6b18113cf7 | ||
|
|
50d41031e4 | ||
|
|
5b4f7368ad | ||
|
|
1ce8a78e04 | ||
|
|
0fe40b5283 | ||
|
|
2229be3ca0 | ||
|
|
6af8409f00 | ||
|
|
5db8e18f44 | ||
|
|
a7324f761b | ||
|
|
9ea2fa0517 | ||
|
|
510dbd686a | ||
|
|
e2de114767 | ||
|
|
bf15897cc0 | ||
|
|
a95e6e73e5 | ||
|
|
1e78af657b | ||
|
|
bc4d84f441 | ||
|
|
79dba0f0f2 | ||
|
|
f7629d8ea0 | ||
|
|
ac64f93d77 | ||
|
|
99f1c318b6 | ||
|
|
e86748f193 | ||
|
|
6dd26f2709 | ||
|
|
6b9fdd1204 | ||
|
|
eaed8ccd05 | ||
|
|
22708ce445 | ||
|
|
4e23f1e032 | ||
|
|
ef4fa58b7c | ||
|
|
2c5e217468 | ||
|
|
5c953c81d4 | ||
|
|
a79b221f75 | ||
|
|
fed1b4e1f3 | ||
|
|
30b659ac80 | ||
|
|
4ef13d8670 | ||
|
|
5b9e0f40b5 | ||
|
|
ec68852f4e | ||
|
|
1847024267 | ||
|
|
66fa7006d9 | ||
|
|
7bc38ef685 | ||
|
|
b351135438 | ||
|
|
50a6abd339 | ||
|
|
9febe08fbd | ||
|
|
25277600b0 | ||
|
|
72ee4790a5 | ||
|
|
f3a223bf48 | ||
|
|
49da4272c6 | ||
|
|
f6f4ec33fb | ||
|
|
d4b79c40ae | ||
|
|
26d86f6a99 | ||
|
|
6dd3c9a587 | ||
|
|
68af062875 | ||
|
|
36dcb9a074 | ||
|
|
d2cc38dd50 | ||
|
|
c473a25a48 | ||
|
|
42ed9c70e2 | ||
|
|
71bb6f64ab | ||
|
|
26ee40697b | ||
|
|
2a215481ba | ||
|
|
a71aa83150 | ||
|
|
f9622e5913 | ||
|
|
0dc964854d | ||
|
|
7167c7081a | ||
|
|
481bfe3b2e | ||
|
|
efaec030e6 | ||
|
|
0d272342f2 | ||
|
|
ec5f4d1898 | ||
|
|
94cfadda5e | ||
|
|
f976be0d94 | ||
|
|
853ddd7d68 | ||
|
|
b69684457f | ||
|
|
f751a179a0 | ||
|
|
8c09521bb4 | ||
|
|
ae41963c87 | ||
|
|
4a362d1ba6 | ||
|
|
6699f0e5c2 | ||
|
|
40216c919d | ||
|
|
cf779b78e9 | ||
|
|
ed4f7ed5fe | ||
|
|
759a6573b9 | ||
|
|
ee1627a37e | ||
|
|
a6a10be4e6 | ||
|
|
e20ad2083d | ||
|
|
0164eb4c56 | ||
|
|
3f4c3edbfe | ||
|
|
1c5906d9da | ||
|
|
e29e8b4264 | ||
|
|
02a061ff11 | ||
|
|
dbf0b6bb05 | ||
|
|
19d047d5de | ||
|
|
0efec5ae7d | ||
|
|
efb5cda657 | ||
|
|
2a5002dc8d | ||
|
|
4e3f730254 | ||
|
|
7c82f88055 | ||
|
|
c4a246293e | ||
|
|
34ab8e4aac | ||
|
|
38a6e8113b | ||
|
|
747d61dff6 | ||
|
|
56fe6f2efe | ||
|
|
ea990330e6 | ||
|
|
60a648f501 | ||
|
|
2f1e097599 | ||
|
|
b74e4d4efa | ||
|
|
58f5d14593 | ||
|
|
84fe10a652 | ||
|
|
92e4e1a76d | ||
|
|
923ebcb3a8 | ||
|
|
f33125154f | ||
|
|
0d54074f6b | ||
|
|
343716ce0e | ||
|
|
36e8bbb5f6 | ||
|
|
5826f748a4 | ||
|
|
c4bd976c57 | ||
|
|
f214183042 | ||
|
|
253a0ef51b | ||
|
|
a2a8144ebb | ||
|
|
a906439ab7 | ||
|
|
5944a966e2 | ||
|
|
52a151f4b0 | ||
|
|
704dacb0cf | ||
|
|
b087466feb | ||
|
|
fef8267916 | ||
|
|
1b87f477af | ||
|
|
8c002ab803 | ||
|
|
b924cbddbe | ||
|
|
ce71828a9a | ||
|
|
df88022556 | ||
|
|
bdc68756a2 | ||
|
|
48775ff050 | ||
|
|
7880eecfad | ||
|
|
a6a0e40df0 | ||
|
|
36954a0ae2 | ||
|
|
ad1dc1445f | ||
|
|
995860b963 | ||
|
|
4e7a211b75 | ||
|
|
ea991297bd | ||
|
|
feda90a7f7 | ||
|
|
683e0363e0 | ||
|
|
65c063548e | ||
|
|
db4323427b | ||
|
|
5a2d4a692c | ||
|
|
b2dd1638f6 | ||
|
|
ef936837a9 | ||
|
|
412c57911c | ||
|
|
03c76bf1e8 | ||
|
|
4b19e76fff | ||
|
|
61da12a012 | ||
|
|
22d30ab8aa | ||
|
|
8b692e0e88 | ||
|
|
935612bfb5 | ||
|
|
1c969fedc4 | ||
|
|
6b771e9858 | ||
|
|
842947fef8 | ||
|
|
796ecb4799 | ||
|
|
c2dba516e1 | ||
|
|
8de2880d2d | ||
|
|
b682e9d89d | ||
|
|
ccea2d28c7 | ||
|
|
8ef751f06f | ||
|
|
2248ec193f | ||
|
|
165596255c | ||
|
|
99174b68d0 | ||
|
|
0541d555cc | ||
|
|
39143b6dfc | ||
|
|
055ebafe73 | ||
|
|
9b2a8dbad9 | ||
|
|
d556948c87 | ||
|
|
2ab0df4965 | ||
|
|
54352af728 | ||
|
|
f1ec9fadb6 | ||
|
|
4c7de2edc5 | ||
|
|
5d1f1c4acf | ||
|
|
e1f615c16e | ||
|
|
bf81c27860 | ||
|
|
abcd969443 | ||
|
|
4865b3c8c0 | ||
|
|
7637cf740a | ||
|
|
f08381be21 | ||
|
|
6d5ee6d20c | ||
|
|
c0e193726e | ||
|
|
305fa8a7f4 | ||
|
|
01e0a64ab3 | ||
|
|
765e2e0fcb | ||
|
|
053f9d2ff9 | ||
|
|
015ae51b19 | ||
|
|
395b4ab51d | ||
|
|
d169adb4d0 | ||
|
|
d632ac6f20 | ||
|
|
fb42ab8113 | ||
|
|
8cf54b7e04 | ||
|
|
839fb561bf | ||
|
|
94e24ad98a | ||
|
|
a60fb964f6 | ||
|
|
9bf97a900e | ||
|
|
8eeeb3e6c6 | ||
|
|
de1d74ba37 | ||
|
|
bd3a2a32dc | ||
|
|
b142ebdabd | ||
|
|
b6c116fb4c | ||
|
|
2e9910ddd3 | ||
|
|
7badb3eea0 | ||
|
|
95c63a3e4f | ||
|
|
35930c2a5c | ||
|
|
392a640ea6 | ||
|
|
14b8acda97 | ||
|
|
a1ae289c58 | ||
|
|
0e1da1a631 | ||
|
|
56aef95c0f | ||
|
|
4040e47c21 | ||
|
|
97ada5a4e0 | ||
|
|
b3b06f9d6f | ||
|
|
4a67f4537c | ||
|
|
0f3829fefe | ||
|
|
f3f45130b2 | ||
|
|
7132e362e4 | ||
|
|
52090ddcc3 | ||
|
|
caf20ca7b1 | ||
|
|
955aae36d4 | ||
|
|
5c57c3619b | ||
|
|
e1683f6743 | ||
|
|
7f212b116b | ||
|
|
09440ce56d | ||
|
|
d4e86aea73 | ||
|
|
81ed67d236 | ||
|
|
5198b13904 | ||
|
|
39ffeb2cf5 | ||
|
|
ca587620a1 | ||
|
|
86f82e0b50 | ||
|
|
787e54f22f | ||
|
|
b0c867e283 | ||
|
|
d0f7722606 | ||
|
|
9170b8b6a7 | ||
|
|
8cce30c9ad | ||
|
|
8dff85e291 | ||
|
|
f96723a420 | ||
|
|
148b575c0d | ||
|
|
254350668a | ||
|
|
8d6bcd1c86 | ||
|
|
db9415b699 | ||
|
|
3294c636c0 | ||
|
|
70b8f1ed15 | ||
|
|
fd5ac24a7c | ||
|
|
683da55ad6 | ||
|
|
51685d413d | ||
|
|
af60205bb1 | ||
|
|
7d2809273a | ||
|
|
49f1291086 | ||
|
|
22c511d360 | ||
|
|
0ea9ed49c4 | ||
|
|
8066cab451 | ||
|
|
83a1e9a7ea | ||
|
|
28a2d233fa | ||
|
|
4ed9b256a7 | ||
|
|
6b7d85e49b | ||
|
|
80b337a0fa | ||
|
|
582fbb3125 | ||
|
|
32f2779a6c | ||
|
|
a82aabb0ca | ||
|
|
15a5e57197 | ||
|
|
6bc6c6cdf3 | ||
|
|
7041487b2c | ||
|
|
2e488303b0 | ||
|
|
837868999a | ||
|
|
1a13296ef3 | ||
|
|
ff89f99fcb | ||
|
|
77c29f5bd9 | ||
|
|
cfc1a1e912 | ||
|
|
2c4b0d274a | ||
|
|
033b4c8e3d | ||
|
|
e620cdfb24 | ||
|
|
a494f8e700 | ||
|
|
87b75735c0 | ||
|
|
b6d8395666 | ||
|
|
842fb43e3a | ||
|
|
49302a7f6f | ||
|
|
1e3882506a | ||
|
|
3f60915732 | ||
|
|
3eb1b22937 | ||
|
|
88507156c2 | ||
|
|
b2af840ea3 | ||
|
|
249b8c5729 | ||
|
|
0b942f70d6 | ||
|
|
6514aa9833 | ||
|
|
1718129044 | ||
|
|
57062d6072 | ||
|
|
a14c89d7a1 | ||
|
|
2788671d45 | ||
|
|
e09a8fb0b9 | ||
|
|
7df126ec39 | ||
|
|
e741a6358e | ||
|
|
c1c0389544 | ||
|
|
9f034d8ede | ||
|
|
5a36067bab | ||
|
|
ed6f8b0ee8 | ||
|
|
696ee9e146 | ||
|
|
11b7613c52 | ||
|
|
500b778f09 | ||
|
|
df996ffb47 | ||
|
|
2e4c64ac69 | ||
|
|
b716d30b00 | ||
|
|
ee79a19bed | ||
|
|
a28b985423 | ||
|
|
7e1970c598 | ||
|
|
2a8d7be8e2 | ||
|
|
1c3a117d02 | ||
|
|
5fc8127230 | ||
|
|
ca35d4e6c6 | ||
|
|
2d972468fe | ||
|
|
9325b22198 | ||
|
|
625c257c42 | ||
|
|
0e0d1e2973 | ||
|
|
cec53f5de5 | ||
|
|
cf98f47e8c | ||
|
|
960430c848 | ||
|
|
8414dcec9c | ||
|
|
2656eb9903 | ||
|
|
22f5da680c | ||
|
|
b6f4227553 | ||
|
|
e47a6f1a05 | ||
|
|
d44c079116 | ||
|
|
4d13ac9f4e | ||
|
|
cc4002c182 | ||
|
|
c7a5f943ad | ||
|
|
732d4fa658 | ||
|
|
3e148bf4ec | ||
|
|
50d698a985 | ||
|
|
744d0fa453 | ||
|
|
e9f5d257f1 | ||
|
|
8c1f3ad99e | ||
|
|
63ebe53865 | ||
|
|
f4f3f65701 | ||
|
|
ba26351338 | ||
|
|
54a12b724e | ||
|
|
1d3fcd84c8 | ||
|
|
a7933b755c | ||
|
|
d9c67255a3 | ||
|
|
f7c566a85a | ||
|
|
2ebfba7261 | ||
|
|
67b2c76136 | ||
|
|
5a5f97e687 | ||
|
|
9a0c3056a5 | ||
|
|
8cbb379b6e | ||
|
|
8c793b162b | ||
|
|
983ff4959d | ||
|
|
e297c55e7b | ||
|
|
0ce42cfc9d | ||
|
|
ca1f7c6a26 | ||
|
|
4f5b34eff5 | ||
|
|
e88420c525 | ||
|
|
ea45c6cefe | ||
|
|
e4b345919b | ||
|
|
b99befe1b1 | ||
|
|
d487273990 | ||
|
|
87d7805714 | ||
|
|
7d70fe6d78 | ||
|
|
28e2663aa5 | ||
|
|
28705aa986 | ||
|
|
b8ae309e15 | ||
|
|
8a15d707c7 | ||
|
|
f3088d3947 | ||
|
|
85fd114404 | ||
|
|
635dec1787 | ||
|
|
395e25729f | ||
|
|
23d3441bbd | ||
|
|
91518ab4c7 | ||
|
|
116ed88683 | ||
|
|
a74731f9b1 | ||
|
|
0f9032a190 | ||
|
|
e2db6fc25d | ||
|
|
7ef2eb1037 | ||
|
|
1ae1c5f307 | ||
|
|
aef41a20c4 | ||
|
|
85145b3205 | ||
|
|
3b2efffb2d | ||
|
|
6d42fe9e35 | ||
|
|
555460a13a | ||
|
|
fca61f7314 | ||
|
|
4e1079f272 | ||
|
|
4c306025b4 | ||
|
|
6257910000 | ||
|
|
4850eaf586 | ||
|
|
dee5abc100 | ||
|
|
53b08abc57 | ||
|
|
af9e70a7f1 | ||
|
|
6be62338cb | ||
|
|
7e137538bb | ||
|
|
36bb5cd484 | ||
|
|
7f9acde217 | ||
|
|
077988efac | ||
|
|
4b9863e55e | ||
|
|
01d150185b | ||
|
|
505d343025 | ||
|
|
883b9154d7 | ||
|
|
e8ced37128 | ||
|
|
65cf658652 | ||
|
|
cb3189d443 | ||
|
|
122430dfef | ||
|
|
9095aac713 | ||
|
|
7fa6b8c51c | ||
|
|
dba345859f | ||
|
|
1982625e2f | ||
|
|
63c40e995c | ||
|
|
2c65ee4224 | ||
|
|
116f7359df | ||
|
|
410cb62fac | ||
|
|
ae547ccd23 | ||
|
|
1f3f582217 | ||
|
|
5d3f697c81 | ||
|
|
94432e2803 | ||
|
|
1c8c387d8e | ||
|
|
857fcdef7b | ||
|
|
ab55c8a383 | ||
|
|
baf8291a47 | ||
|
|
d0c5dacdd8 | ||
|
|
f080eeb1e3 | ||
|
|
8149939d6f | ||
|
|
c74618fa5f | ||
|
|
1086ece85d | ||
|
|
34310684f2 | ||
|
|
2bfff528ed | ||
|
|
bba819970a | ||
|
|
71eb4388d1 | ||
|
|
b93209c107 | ||
|
|
83d0ebcba4 | ||
|
|
e276ee0974 | ||
|
|
8ae6e8b8cf | ||
|
|
93e304f5d0 | ||
|
|
49004caa12 | ||
|
|
bc7b2a7b9f | ||
|
|
5c9182a84c | ||
|
|
356094b19c | ||
|
|
cd46dd4a81 | ||
|
|
f5bd52bac9 | ||
|
|
5ff1de40d7 | ||
|
|
4f2a507f2e | ||
|
|
5cb7311b30 | ||
|
|
3a3018a8d2 | ||
|
|
7e0d44b480 | ||
|
|
d7957002ee | ||
|
|
d62049cd59 | ||
|
|
6b3fbbe9fd | ||
|
|
5bdd5f0c17 | ||
|
|
ba24d1251d | ||
|
|
dd5ac3e361 | ||
|
|
8f43c23b96 | ||
|
|
18551c74b5 | ||
|
|
4461463d9d | ||
|
|
a7d6974872 | ||
|
|
4d73f86474 | ||
|
|
83542b8dc4 | ||
|
|
3e52f7f954 | ||
|
|
5b8a83c398 | ||
|
|
b5ee03c816 | ||
|
|
46cc5c2326 | ||
|
|
5547094315 | ||
|
|
81f5cd4446 | ||
|
|
06788687c3 | ||
|
|
c9b692382f | ||
|
|
9c231ad7ed | ||
|
|
24dce00f16 | ||
|
|
4298137694 | ||
|
|
8bc6a98574 | ||
|
|
2bab935044 | ||
|
|
eb4f541400 | ||
|
|
de2c8f6b97 | ||
|
|
1cd136e029 | ||
|
|
5a8252886c | ||
|
|
131c59bfb9 | ||
|
|
ce6be2b141 | ||
|
|
37ca047bff | ||
|
|
cb7212e7d2 | ||
|
|
799029a2bc | ||
|
|
a4a18fe920 | ||
|
|
afeb59b1ca | ||
|
|
1322993cc9 | ||
|
|
1585ddca89 | ||
|
|
d882699045 | ||
|
|
7ca07cdc1d | ||
|
|
8b4fbb1998 | ||
|
|
45b4c8a132 | ||
|
|
c500e7a4c6 | ||
|
|
ab052f52f0 | ||
|
|
ce97ddfd33 | ||
|
|
f2da10d1ca | ||
|
|
253dc5224e | ||
|
|
aa9b722d38 | ||
|
|
1d8998a133 | ||
|
|
ae62423fe0 | ||
|
|
4f14e236cc | ||
|
|
198fd8e638 | ||
|
|
724264d755 | ||
|
|
08df9580f5 | ||
|
|
98bb57a6d9 | ||
|
|
4f8c3591f5 | ||
|
|
44531adfc6 | ||
|
|
2790799b98 | ||
|
|
4378d4f6e2 | ||
|
|
60a8503e76 | ||
|
|
d872a4f0c8 | ||
|
|
bea26927e0 | ||
|
|
2fea5ae5a2 | ||
|
|
65be11a298 | ||
|
|
8345457acc | ||
|
|
844303be04 | ||
|
|
75cd36f7c8 | ||
|
|
d43150ff47 | ||
|
|
c122fb3412 | ||
|
|
6efbef5210 | ||
|
|
08ed4e6621 | ||
|
|
bb42e9b2a0 | ||
|
|
537bff0569 | ||
|
|
f0283aa2ff | ||
|
|
0626522738 | ||
|
|
3f88a0c3f5 | ||
|
|
e5d51cb13e | ||
|
|
88808ccce0 | ||
|
|
450c2598fa | ||
|
|
6081f7a1c4 | ||
|
|
fd2dbbdaa3 | ||
|
|
27ca342407 | ||
|
|
4ae8713f63 | ||
|
|
b96e31f083 | ||
|
|
9a78ce3fe5 | ||
|
|
7c4d5da9d2 | ||
|
|
da80935798 | ||
|
|
2b307fe6dd | ||
|
|
b91aea942b | ||
|
|
7e9ed37b18 | ||
|
|
2c9b092191 | ||
|
|
3da31a2a53 | ||
|
|
043bf9c874 | ||
|
|
70c6d2b970 | ||
|
|
11d9e1fef2 | ||
|
|
6c8c128b38 | ||
|
|
f19c28f69e | ||
|
|
68c663b3b2 | ||
|
|
d05dc44197 | ||
|
|
91b73dafce | ||
|
|
a4d292a988 | ||
|
|
327fa421a0 | ||
|
|
0f4244756e | ||
|
|
12b2c40817 | ||
|
|
48993d235b | ||
|
|
ec8eeff462 | ||
|
|
4365d70411 | ||
|
|
cc8693be60 | ||
|
|
54bf705240 | ||
|
|
73dbba8f17 | ||
|
|
ffba931c1b | ||
|
|
ab6c3543dd | ||
|
|
cbcda32df2 | ||
|
|
6f7155e4d0 | ||
|
|
993c59f398 | ||
|
|
c39e343357 | ||
|
|
05f25e994e | ||
|
|
e685b5739b | ||
|
|
161a363b04 | ||
|
|
ef0fb11a23 | ||
|
|
3c538da449 | ||
|
|
89621c21f5 | ||
|
|
526975c9b9 | ||
|
|
6d73b87ad4 | ||
|
|
97c4c85fc7 | ||
|
|
c27579181d | ||
|
|
e740d2dd04 | ||
|
|
fed8522972 | ||
|
|
fadc651d86 | ||
|
|
592f5b32b9 | ||
|
|
c14c2ac696 | ||
|
|
9219339417 | ||
|
|
b9177e7aec | ||
|
|
239073b97b | ||
|
|
2b7c0069bb | ||
|
|
f6dd602d2e | ||
|
|
e896e84e1f | ||
|
|
61c7afa635 | ||
|
|
080a458712 | ||
|
|
f8973e26c0 | ||
|
|
8ad5359b5b | ||
|
|
59f122f099 | ||
|
|
3544a6c8eb | ||
|
|
82e7f8a220 | ||
|
|
de7f6c56dc | ||
|
|
fb0376e5c5 | ||
|
|
e74a44b68f | ||
|
|
ca4d83f44a | ||
|
|
b9eab52f8b | ||
|
|
74a1da51ff | ||
|
|
a74e49f4ab | ||
|
|
67d9b7981e | ||
|
|
12522095a0 | ||
|
|
9802533a6b | ||
|
|
abf66cba73 | ||
|
|
1f220c8761 | ||
|
|
9257cb4490 | ||
|
|
f0456d15b9 | ||
|
|
6e9c509a4f | ||
|
|
60e80e7f14 | ||
|
|
1849cc227f | ||
|
|
9a7ca5cc27 | ||
|
|
f33cb44306 | ||
|
|
90cc76e6c7 | ||
|
|
ebb4ce2479 | ||
|
|
3eecfd4b96 | ||
|
|
4b5110bb51 | ||
|
|
df122dbcbe | ||
|
|
b9a0e4e409 | ||
|
|
8df7a8a019 | ||
|
|
86357ae748 | ||
|
|
896f9347a1 | ||
|
|
3634e6abe7 | ||
|
|
cb42053a1b | ||
|
|
ce5a9f6796 | ||
|
|
52f6705de6 | ||
|
|
060d430856 | ||
|
|
1b94d1e511 | ||
|
|
ae75d3449f | ||
|
|
81a958c31a | ||
|
|
275d89cf89 | ||
|
|
d533a4259d | ||
|
|
c9bbf0cf2b | ||
|
|
653d0492ae | ||
|
|
5f22fc64cb | ||
|
|
6a41110288 | ||
|
|
92fdfb9803 | ||
|
|
a8ae90934b | ||
|
|
73e6c69c0c | ||
|
|
b274fd17ad | ||
|
|
224bdc4eae | ||
|
|
8fe4ff628b | ||
|
|
2a2a9fbae4 | ||
|
|
e761f4c8c8 | ||
|
|
3fd5ad8682 | ||
|
|
0ebc50479c | ||
|
|
f7b42a3ee9 | ||
|
|
8a5c56db84 | ||
|
|
33f884e206 | ||
|
|
e2d4a95c44 | ||
|
|
0020afcf92 | ||
|
|
bd5ae84ba9 | ||
|
|
2bfb7bb04b | ||
|
|
9ac3eeb332 | ||
|
|
256cf20ab6 | ||
|
|
b53691f91a | ||
|
|
87e77c2654 | ||
|
|
aec152d793 | ||
|
|
9361dac428 | ||
|
|
99edc05cdf | ||
|
|
b823ea371a | ||
|
|
ba04ec275b | ||
|
|
9902e13c11 | ||
|
|
1bcd27db77 | ||
|
|
140efc2a78 | ||
|
|
95b3db34e3 | ||
|
|
43d87a6115 | ||
|
|
1103cde6b3 | ||
|
|
1dc0b60c22 | ||
|
|
e7630f46c7 | ||
|
|
987870eb26 | ||
|
|
53c35c0e02 | ||
|
|
a2eb14a79b | ||
|
|
8ac7231e74 | ||
|
|
bd7259cfe4 | ||
|
|
ff471d0ba4 | ||
|
|
1b8e05c861 | ||
|
|
49af9e3a1e | ||
|
|
83e2a187de | ||
|
|
394314dd3d | ||
|
|
bac66c5e19 | ||
|
|
0c14c78775 | ||
|
|
48c4f3cd6e | ||
|
|
73c699eb2b | ||
|
|
9faa6462b4 | ||
|
|
2c5ab6844a | ||
|
|
3e85d3314f | ||
|
|
17d6efff4d | ||
|
|
2f82c2407f | ||
|
|
66211a7ab2 | ||
|
|
67ad1f9564 | ||
|
|
ab570a9f05 | ||
|
|
4fdbb13010 | ||
|
|
2ac9f3806d | ||
|
|
b0ee5b5f35 | ||
|
|
546a44f216 | ||
|
|
67d3f1f574 | ||
|
|
7673d5934b | ||
|
|
d38f2e2f0e | ||
|
|
8ddec5f792 | ||
|
|
e97365de03 | ||
|
|
7a27b40068 | ||
|
|
1438f2f36a | ||
|
|
d51cd46d1d | ||
|
|
479c1553b8 | ||
|
|
def70b77aa | ||
|
|
4ff7ba5225 | ||
|
|
a41bf555cf | ||
|
|
b199b2fb98 | ||
|
|
e02ffbfd94 | ||
|
|
3b4aa37413 | ||
|
|
38ebf18e1b | ||
|
|
e5c4755b4b | ||
|
|
f787331d19 | ||
|
|
688c7117e8 | ||
|
|
914ac6999d | ||
|
|
20065858fc | ||
|
|
4e7d460716 | ||
|
|
677553f5f0 | ||
|
|
8cb0a95695 | ||
|
|
16cd7f0bf6 | ||
|
|
c2f087a93d | ||
|
|
b210a784e1 | ||
|
|
da7f8fc7f9 | ||
|
|
b22e8e96de | ||
|
|
ba3b80e834 | ||
|
|
b28e45af25 | ||
|
|
da2768d56b | ||
|
|
cb219ae64e | ||
|
|
f63a14aa18 | ||
|
|
ca824c07eb | ||
|
|
d58a3db44c | ||
|
|
f7ab752bcf | ||
|
|
43df69cb9b | ||
|
|
de84664427 | ||
|
|
ecb8b40184 | ||
|
|
44e6cc0384 | ||
|
|
f40f49ba8b | ||
|
|
8a9d20921d | ||
|
|
64ba44e4d2 | ||
|
|
83b7b8b268 | ||
|
|
0e5e4a8f03 | ||
|
|
10cbb16645 | ||
|
|
c8de19c7b4 | ||
|
|
1eaa6f5a47 | ||
|
|
5e1875d355 | ||
|
|
4b712c95c6 | ||
|
|
5441ac8470 | ||
|
|
b02cf140c0 | ||
|
|
11c26c8014 | ||
|
|
dd9db1fe78 | ||
|
|
8e49de26c3 | ||
|
|
fe422743bb | ||
|
|
63a5ad275b | ||
|
|
8e94045cc0 | ||
|
|
30cddd45f5 | ||
|
|
f2f96e1015 | ||
|
|
aca7a36989 | ||
|
|
f9b83e267e | ||
|
|
ea53b519b9 | ||
|
|
094682be87 | ||
|
|
187076c10a | ||
|
|
8df6e4dddd | ||
|
|
04a315bc52 | ||
|
|
1266e99d77 | ||
|
|
9fa1b1accc | ||
|
|
310328febc | ||
|
|
6cd01a0ca1 | ||
|
|
74be4c92d0 | ||
|
|
68114e5ac5 | ||
|
|
6b8235c002 | ||
|
|
8a97369103 | ||
|
|
748bb1b7b2 | ||
|
|
29c63f1f2b | ||
|
|
e36df63a0b | ||
|
|
a3e44763df | ||
|
|
f27a3b7474 | ||
|
|
285632e8ff | ||
|
|
66344a0aaf | ||
|
|
c9e5921173 | ||
|
|
f40162232f | ||
|
|
ccbe94e5cc | ||
|
|
5f3cca5fd3 | ||
|
|
682490ae61 | ||
|
|
6fcbf51cd5 | ||
|
|
0caf78841d | ||
|
|
c4b8ca79f2 | ||
|
|
6327b9fa17 | ||
|
|
61e84764a0 | ||
|
|
57dc28ed73 | ||
|
|
5afcd10313 | ||
|
|
3c9c97560f | ||
|
|
8c6cbcf860 | ||
|
|
b4e24b4b78 | ||
|
|
8d43463215 | ||
|
|
8ce4d0621e | ||
|
|
efc0479d25 | ||
|
|
9ad0be3f9f | ||
|
|
0b5df380d1 | ||
|
|
a5b205cb85 | ||
|
|
86273c129e | ||
|
|
3b546f92ac | ||
|
|
c60c87fef6 | ||
|
|
78092dc067 | ||
|
|
3f39e4ac11 | ||
|
|
0a983e6f7f | ||
|
|
89449e9c02 | ||
|
|
6310fc7fd1 | ||
|
|
092892289c | ||
|
|
e1c4b6eca1 | ||
|
|
2e21e3aa91 | ||
|
|
43cabc4889 | ||
|
|
2d8374fc5c | ||
|
|
53e9227f4a | ||
|
|
685e9b1da5 | ||
|
|
046b4bde90 | ||
|
|
9698dd4dcc | ||
|
|
d00f60f40e | ||
|
|
ab407b22bd | ||
|
|
cb4d00828c | ||
|
|
72598b88f6 | ||
|
|
f0043ca20b | ||
|
|
03319626be | ||
|
|
03402e7a55 | ||
|
|
7c46655843 | ||
|
|
d6e9fa7c88 | ||
|
|
99d55be497 | ||
|
|
29beabb114 | ||
|
|
0c76d2dbdf | ||
|
|
142daeb924 | ||
|
|
3a8c71d363 | ||
|
|
100edf8b41 | ||
|
|
2e6474cf8f | ||
|
|
4334b34637 | ||
|
|
0026971da2 | ||
|
|
2ac5a353aa | ||
|
|
a3cfadb84c | ||
|
|
ca7b3d81e5 | ||
|
|
64f0f4bd23 | ||
|
|
261a568cc6 | ||
|
|
2cbb4f8684 | ||
|
|
2accaf286b | ||
|
|
99796d4f55 | ||
|
|
c17b1add9e | ||
|
|
047556ecb9 | ||
|
|
85d067a753 | ||
|
|
50718c424f | ||
|
|
6b4da4978d | ||
|
|
14d3acc73c | ||
|
|
932c644676 | ||
|
|
11297e03a9 | ||
|
|
695c67d2d4 | ||
|
|
3713b7c4bf | ||
|
|
3e6c802608 | ||
|
|
2d55437bfa | ||
|
|
3dc4a50949 | ||
|
|
b27c9c589a | ||
|
|
2beeb3b7e9 | ||
|
|
ea4860d239 | ||
|
|
cbe2416eb0 | ||
|
|
885c8c03fd | ||
|
|
b5928c3be9 | ||
|
|
ffda8aaddf | ||
|
|
8b7080cc4d | ||
|
|
15b2a62217 | ||
|
|
897f0099b2 | ||
|
|
ed29320b90 | ||
|
|
0e9f15a7c3 | ||
|
|
4b50c00028 | ||
|
|
bb924c86fa | ||
|
|
c12cd62ce7 | ||
|
|
d2c0afccab | ||
|
|
8de9f4b85c | ||
|
|
8ea6c6360e | ||
|
|
54ee683838 | ||
|
|
249e6ccb0d | ||
|
|
b531c82567 | ||
|
|
b716e390e1 | ||
|
|
194796432b | ||
|
|
6146ac8710 | ||
|
|
d1f967b851 | ||
|
|
03e9cbe7f3 | ||
|
|
2cfacf60c0 | ||
|
|
d775b6d736 | ||
|
|
4c06854897 | ||
|
|
56a7c49cbc | ||
|
|
83db9f078b | ||
|
|
58888f57d0 | ||
|
|
2b981f1b1a | ||
|
|
1c0d885603 | ||
|
|
5b9ec5da26 | ||
|
|
784967800f | ||
|
|
45590f2cc1 | ||
|
|
f57c1f3c7e | ||
|
|
1a0ffd499e | ||
|
|
f81b643f29 | ||
|
|
0675da97a2 | ||
|
|
b6d1c7dcd1 | ||
|
|
e03ac50239 | ||
|
|
60ce673ef9 | ||
|
|
66a8e34547 | ||
|
|
e90b59e37f | ||
|
|
cd38a2fff1 | ||
|
|
28928d6271 | ||
|
|
950c66bd44 | ||
|
|
8790ca11ed | ||
|
|
7ad6348542 | ||
|
|
c395c301f3 | ||
|
|
24a0729033 | ||
|
|
9ab74dd5e4 | ||
|
|
f9111d1c61 | ||
|
|
39483316c6 | ||
|
|
8fedd88408 | ||
|
|
a84f140114 | ||
|
|
d1908b5769 | ||
|
|
ec07038446 | ||
|
|
6d2b445867 | ||
|
|
7ed1afa775 | ||
|
|
3da7e63da2 | ||
|
|
15a0da37f2 | ||
|
|
626b741729 | ||
|
|
91daf6edf5 | ||
|
|
af3bf577e4 | ||
|
|
482770af77 | ||
|
|
0d23199136 | ||
|
|
fef6d1a078 | ||
|
|
260f988d2a | ||
|
|
5d8ddc9b57 | ||
|
|
2653a2293e | ||
|
|
3410a98f93 | ||
|
|
fc0b8bdba3 | ||
|
|
281f906e0c | ||
|
|
851b802bbb | ||
|
|
4049116775 | ||
|
|
113dc28e9c | ||
|
|
0a0a5f3d7c | ||
|
|
f695894343 | ||
|
|
8a74b1022d | ||
|
|
1cabc3e582 | ||
|
|
de1c2e207e | ||
|
|
b5ba15a9aa | ||
|
|
d31345203f | ||
|
|
d82ea49e94 | ||
|
|
ca739bb5e0 | ||
|
|
400dbb8b3a | ||
|
|
643b2e07c7 | ||
|
|
7ddf054d9e | ||
|
|
2add21548a | ||
|
|
412537a7ae | ||
|
|
5de8ffc4d9 | ||
|
|
939114466f | ||
|
|
7fd5cf1f10 | ||
|
|
128ef5be05 | ||
|
|
c4f5a251a3 | ||
|
|
797b226345 | ||
|
|
968e90a564 | ||
|
|
1c2ca087f5 | ||
|
|
0406714095 | ||
|
|
22e78638af | ||
|
|
697e08efd1 | ||
|
|
488340857b | ||
|
|
ff3425981c | ||
|
|
97b02eb090 | ||
|
|
d289ad7e49 | ||
|
|
0a19e803b8 | ||
|
|
ed9763a257 | ||
|
|
3b516ea7c7 | ||
|
|
7a7a25d67e | ||
|
|
817d54e591 | ||
|
|
70c9f64e88 | ||
|
|
6cbd251035 | ||
|
|
f8299fa556 | ||
|
|
4e0451bb1c | ||
|
|
e9d2c509a8 | ||
|
|
10af92ec77 | ||
|
|
0cb501c39c | ||
|
|
82d4c5ab29 | ||
|
|
25fb224613 | ||
|
|
2897cb4b4a | ||
|
|
0603393a52 | ||
|
|
01656051e2 | ||
|
|
3483196b3b | ||
|
|
ae1d393dd8 | ||
|
|
4b12c5c2e3 | ||
|
|
57ee959182 | ||
|
|
731c4fefad | ||
|
|
3e53743f1b | ||
|
|
1283a3cd39 | ||
|
|
4ff6373b2c | ||
|
|
f5c67b6773 | ||
|
|
b413796475 | ||
|
|
6f13f2b654 | ||
|
|
bdf50943a4 | ||
|
|
4ed9654f11 | ||
|
|
02953e520d | ||
|
|
e6455767ca | ||
|
|
afb898ac87 | ||
|
|
0f8eeba740 | ||
|
|
0cbca5294d | ||
|
|
14a1ef6f11 | ||
|
|
f62f2f07e2 | ||
|
|
e6eaadf4fc | ||
|
|
0231b83505 | ||
|
|
e0233c27ae | ||
|
|
71bbcbfd96 | ||
|
|
46a76d5412 | ||
|
|
f9c80c709c | ||
|
|
744a9d03a5 | ||
|
|
96b822ef82 | ||
|
|
b1c6233e13 | ||
|
|
3321e948de | ||
|
|
d11724c616 | ||
|
|
6f709ccd58 | ||
|
|
43a4f582d2 | ||
|
|
5328c372bb | ||
|
|
346136d1a4 | ||
|
|
f1d3681cd8 | ||
|
|
ba74104b78 | ||
|
|
b79011f1b0 | ||
|
|
834f565a7d | ||
|
|
c0853c4560 | ||
|
|
a2a308f5ef | ||
|
|
13ab7ef911 | ||
|
|
a8f8ad14ca | ||
|
|
c4a50f97d6 | ||
|
|
4b70db56cf | ||
|
|
ebd4bdd5f3 | ||
|
|
1a5ab92c05 | ||
|
|
ea97da2931 | ||
|
|
55fe83265f | ||
|
|
e64c1fced2 | ||
|
|
9d1a799c23 | ||
|
|
24578ce569 | ||
|
|
a2bb1a48a2 | ||
|
|
cf8f662060 | ||
|
|
fc1b9ebaa6 | ||
|
|
03d0c8c05c | ||
|
|
60971d7cce | ||
|
|
5e0bbf3ecb | ||
|
|
cc8309d046 | ||
|
|
54be194305 | ||
|
|
ec42e12457 | ||
|
|
1392f73ce5 | ||
|
|
a62faf3a3f | ||
|
|
cf1b8d99d5 | ||
|
|
2454d2d781 | ||
|
|
cf42ba4ea4 | ||
|
|
83c8ea7e06 | ||
|
|
1103ea7e4d | ||
|
|
e59745c22c | ||
|
|
cc1f856bc2 | ||
|
|
1a62909eb2 | ||
|
|
859aee9a27 | ||
|
|
480a80f052 | ||
|
|
aed8c978d2 | ||
|
|
01339fd31a | ||
|
|
154ce27239 | ||
|
|
499fca99b6 | ||
|
|
d20291a17f | ||
|
|
6bf04403ae | ||
|
|
dea4abb7a1 | ||
|
|
4aac30c32c | ||
|
|
d1edb8a9c9 | ||
|
|
887c126b02 | ||
|
|
d3ebd0550d | ||
|
|
7975babde3 | ||
|
|
44abe48661 | ||
|
|
919e87315e | ||
|
|
54e6c5a59c | ||
|
|
fd48eb6c96 | ||
|
|
a9223e5336 | ||
|
|
8898ca54a8 | ||
|
|
1150aa7133 | ||
|
|
798e0688d4 | ||
|
|
b718897ff8 | ||
|
|
7d2e04db2f | ||
|
|
8c4577ea93 | ||
|
|
eefeace2eb | ||
|
|
2c7c5e0b3a | ||
|
|
ffba14d2c1 | ||
|
|
043a2b9613 | ||
|
|
fbef38149f | ||
|
|
7b479f7803 | ||
|
|
13526b0916 | ||
|
|
26def8359d | ||
|
|
d9a54469ff | ||
|
|
cd4a7460b0 | ||
|
|
42ab825f46 | ||
|
|
2792d57c28 | ||
|
|
3179b6feea | ||
|
|
c532a818b7 | ||
|
|
302b7fa13e | ||
|
|
71b6ba02a1 | ||
|
|
8a3271af4e | ||
|
|
04bc27438d | ||
|
|
19d0baa26f | ||
|
|
964f7899e9 | ||
|
|
ee6837b953 | ||
|
|
ffa4572ee4 | ||
|
|
22e3e6c50c | ||
|
|
26a3769220 | ||
|
|
c75e8ad6e1 | ||
|
|
47909b13e1 | ||
|
|
7ea7f09e16 | ||
|
|
0e0df8ad95 | ||
|
|
14a84c8956 | ||
|
|
dcdaa89ac1 | ||
|
|
a9947a2e74 | ||
|
|
d9c20ab381 | ||
|
|
c83c7096e7 | ||
|
|
1f04ecc6dc | ||
|
|
4a50e8bff0 | ||
|
|
59c71cf5c0 | ||
|
|
74ae6958d1 | ||
|
|
3392698c79 | ||
|
|
bf6dffe74b | ||
|
|
1fb2824cf3 | ||
|
|
6376a6e97d | ||
|
|
7d19747fa4 | ||
|
|
cb2d09ab07 | ||
|
|
032a8d574c | ||
|
|
82a5ff966e | ||
|
|
b8d4404aac | ||
|
|
897173b721 | ||
|
|
9b6e06fa61 | ||
|
|
592925ffa3 | ||
|
|
dd1df950cc | ||
|
|
b65dfc663e | ||
|
|
f739563699 | ||
|
|
7e1b537b0e | ||
|
|
ece8637275 | ||
|
|
57624cbe73 | ||
|
|
08c5f0471d | ||
|
|
bc1bca7922 | ||
|
|
3a62894312 | ||
|
|
7de1fcf1f4 | ||
|
|
3388c3dfcc | ||
|
|
d66b159793 | ||
|
|
c33435b692 | ||
|
|
a1daf8e884 | ||
|
|
b8d146c62e | ||
|
|
6194b1e96d | ||
|
|
f803a76bfa | ||
|
|
5922b91824 | ||
|
|
d6a4d61c9f | ||
|
|
e219c99dd5 | ||
|
|
e5f4e48471 | ||
|
|
d03196aa96 | ||
|
|
f157c67756 | ||
|
|
c4832161d4 | ||
|
|
4a5ad589eb | ||
|
|
f3e30608fa | ||
|
|
1f01e77072 | ||
|
|
7d846cfe2e | ||
|
|
5462e24c83 | ||
|
|
0f0f4a15a7 | ||
|
|
18594919e2 | ||
|
|
e3e79062fd | ||
|
|
e460b57518 | ||
|
|
0089286b66 | ||
|
|
3f41d0e1f5 | ||
|
|
8913daa21b | ||
|
|
d65a39f722 | ||
|
|
e3dc4b65bf | ||
|
|
be1a18bfe4 | ||
|
|
e1b6bd0467 | ||
|
|
bb6800ec90 | ||
|
|
7857c14c1d | ||
|
|
478cc28731 | ||
|
|
a645f0a3a4 | ||
|
|
7fe855edfe | ||
|
|
102ec0731a | ||
|
|
32b47b9966 | ||
|
|
55d382b0c1 | ||
|
|
fcf758be3c | ||
|
|
ef34412277 | ||
|
|
ca22d8f9ba | ||
|
|
e7822af805 | ||
|
|
ea949f0b81 | ||
|
|
a586640e8d | ||
|
|
28f0283cab | ||
|
|
a832a84f66 | ||
|
|
4bd43154c7 | ||
|
|
24be2e5803 | ||
|
|
52f41017d1 | ||
|
|
0cf714bf59 | ||
|
|
8b7f93cc69 | ||
|
|
68a34f6224 | ||
|
|
9601355097 | ||
|
|
0f8b224f15 | ||
|
|
051b7d2ab5 | ||
|
|
78cbf94668 | ||
|
|
78a1c10421 | ||
|
|
aa2abf7c31 | ||
|
|
56893eacb1 | ||
|
|
58e973c0dd | ||
|
|
2021c85989 | ||
|
|
c26032f088 | ||
|
|
7eca5063d2 | ||
|
|
3474059d00 | ||
|
|
7dfcd38a05 | ||
|
|
083817692a | ||
|
|
190062635b | ||
|
|
bf400be243 | ||
|
|
90997adad2 | ||
|
|
a81d2e3c42 | ||
|
|
f0eb586e38 | ||
|
|
764dcf8464 | ||
|
|
fb73fb1af3 | ||
|
|
40ded6b424 | ||
|
|
35ad8de19d | ||
|
|
faba464a18 | ||
|
|
d99b04009b | ||
|
|
a135c38280 | ||
|
|
01e887ec65 | ||
|
|
bcffb91cd0 | ||
|
|
7feadb6207 | ||
|
|
9ee13cfbbf | ||
|
|
0a7fedba00 | ||
|
|
8ac1cc5837 | ||
|
|
6d84f734d2 | ||
|
|
98a880c621 | ||
|
|
8053b81db7 | ||
|
|
ef90c67ac2 | ||
|
|
21ababdb09 | ||
|
|
acb3e45414 | ||
|
|
2562fc37f1 | ||
|
|
bc4945f804 | ||
|
|
86db4b273e | ||
|
|
18f10740d8 | ||
|
|
1c92735129 | ||
|
|
f38d65c93f | ||
|
|
846f91997b | ||
|
|
220da11388 | ||
|
|
a9eba43418 | ||
|
|
c1888a0a1d | ||
|
|
f1539bc692 | ||
|
|
6cc887d590 | ||
|
|
10e6ae8678 | ||
|
|
c5279d4896 | ||
|
|
b7e979dae4 | ||
|
|
3896abe972 | ||
|
|
6f1d49fcca | ||
|
|
3bdcf2f628 | ||
|
|
4e2631c555 | ||
|
|
9167facd1a | ||
|
|
63b05020b3 | ||
|
|
2dec75e7d9 | ||
|
|
d9647017ae | ||
|
|
eea2b783f7 | ||
|
|
edd2070967 | ||
|
|
82725c0fcc | ||
|
|
308a307408 | ||
|
|
2773466f0f | ||
|
|
709ffd7631 | ||
|
|
8eda081d64 | ||
|
|
6b8c8d9c33 | ||
|
|
bc5df75b30 | ||
|
|
400689bab3 | ||
|
|
b6bec9e9c1 | ||
|
|
9f119eff89 | ||
|
|
75b9ff94ac | ||
|
|
edaa2d1396 | ||
|
|
d4d8e9560b | ||
|
|
d449e86d0e | ||
|
|
27e956175e | ||
|
|
d28d401c6c | ||
|
|
4b2a22dc3b | ||
|
|
138806375a | ||
|
|
ea5b8052fd | ||
|
|
4fb129b7dd | ||
|
|
7e21a44db4 | ||
|
|
4bb4b19cae | ||
|
|
8e94b38103 | ||
|
|
bf825d6bf9 | ||
|
|
38fd38f582 | ||
|
|
275e96ffd2 | ||
|
|
3ad288adf1 | ||
|
|
1c6f2dfd82 | ||
|
|
1a8eba304d | ||
|
|
7292a20e3b | ||
|
|
e5b82e0358 | ||
|
|
ecda4cd323 | ||
|
|
f8dc9614c5 | ||
|
|
db5c4cef06 | ||
|
|
0e2ed81a31 | ||
|
|
828311a18d | ||
|
|
5f4b0d9e64 | ||
|
|
b9d1249ec8 | ||
|
|
06c39ecd5d | ||
|
|
adad842d7e | ||
|
|
b98b2e9037 | ||
|
|
1d9d6eef8b | ||
|
|
776f8a5158 | ||
|
|
822d444964 | ||
|
|
fdce2eb201 | ||
|
|
cb707129f5 | ||
|
|
2c443a0145 | ||
|
|
b6216c4c0f | ||
|
|
a3e067481e | ||
|
|
6be2025a66 | ||
|
|
3572866bd3 | ||
|
|
50cca39a04 | ||
|
|
52142ed141 | ||
|
|
bbf8443b9c | ||
|
|
88d28816fd | ||
|
|
bbdf35a17f | ||
|
|
f9ef655429 | ||
|
|
40d3c596e1 | ||
|
|
4debada2db | ||
|
|
c96a57c310 | ||
|
|
0d2c2cb99f | ||
|
|
9e5a44231d | ||
|
|
517b5a7f6f | ||
|
|
a3c10ebe6f | ||
|
|
d678d51257 | ||
|
|
ab424fef82 | ||
|
|
2debe0d5c5 | ||
|
|
f630a95b23 | ||
|
|
de30cfd10a | ||
|
|
813da6a0f7 | ||
|
|
a29cdd64d0 | ||
|
|
6d3c16871f | ||
|
|
eb192455fb | ||
|
|
4f3f7f4a36 | ||
|
|
825d58a3ae | ||
|
|
0640fdb734 | ||
|
|
3e88d6b23e | ||
|
|
27747d6d69 | ||
|
|
05ebb7312a | ||
|
|
a489725fec | ||
|
|
f85877a37f | ||
|
|
0a34c5c533 | ||
|
|
6651359529 | ||
|
|
14c8d9709a | ||
|
|
bf9fdcc472 | ||
|
|
c170d136a3 | ||
|
|
6ad6a3bcc5 | ||
|
|
2d9067f488 | ||
|
|
4d9626e2f9 | ||
|
|
97404e50c3 | ||
|
|
96419627e6 | ||
|
|
a516ee7b37 | ||
|
|
77ece7d6cb | ||
|
|
e04500a9a5 | ||
|
|
80e08707e2 | ||
|
|
70b91d47c3 | ||
|
|
88b1a529b8 | ||
|
|
2c21d5c05b | ||
|
|
0dd92d5826 | ||
|
|
61a7150c87 | ||
|
|
d66d756bf8 | ||
|
|
261be70cae | ||
|
|
7f1a85ed6c | ||
|
|
47e0dbfdca | ||
|
|
29341eb1ec | ||
|
|
6747c48321 | ||
|
|
e42ee15564 | ||
|
|
3976ffed2d | ||
|
|
806ec25d8e | ||
|
|
77244abfb1 | ||
|
|
55838d4937 | ||
|
|
c095bc9a2e | ||
|
|
652e443106 | ||
|
|
481dd61949 | ||
|
|
1e27733c38 | ||
|
|
18e6cae27f | ||
|
|
5c5c05fa1a | ||
|
|
027b8e13fc | ||
|
|
30d275ef18 | ||
|
|
a5bc09753b | ||
|
|
e69a4411cb | ||
|
|
1b9ef54701 | ||
|
|
4f0c3a467b | ||
|
|
6dd2038686 | ||
|
|
fe83689024 | ||
|
|
32d084d5a9 | ||
|
|
af789ae8ee | ||
|
|
ae37b43632 | ||
|
|
fa42c9a1ea | ||
|
|
1c3a97fbad | ||
|
|
ca32b296c3 | ||
|
|
47e940c8d2 | ||
|
|
dc3ecd9f56 | ||
|
|
5ce9ceb0f3 | ||
|
|
acfde11f42 | ||
|
|
9339fb08c9 | ||
|
|
41cd8ad96c | ||
|
|
ba880af169 | ||
|
|
a6fd6bda2d | ||
|
|
6b4049d257 | ||
|
|
aaf733eeda | ||
|
|
7e28316a22 | ||
|
|
2a6db8c64f | ||
|
|
7f00b601cc | ||
|
|
d5b50a9383 | ||
|
|
9b9e50efd1 | ||
|
|
d4dfdba158 | ||
|
|
8c5e79496d | ||
|
|
8e5862085e | ||
|
|
ba06cf0ff1 | ||
|
|
746d56a7a8 | ||
|
|
fa9ced60fc | ||
|
|
df2fe7258a | ||
|
|
08e86475f4 | ||
|
|
53603b4971 | ||
|
|
c3ca226457 | ||
|
|
2816763922 | ||
|
|
a423efd7bb | ||
|
|
1687309790 | ||
|
|
ef109c7054 | ||
|
|
77a18695f1 | ||
|
|
9615b6466f | ||
|
|
cb4f2e1b41 | ||
|
|
548bb8d7f1 | ||
|
|
866aa0456d | ||
|
|
69e5d554db | ||
|
|
37cb01230f | ||
|
|
0b546d3aba | ||
|
|
d65a349c70 | ||
|
|
28da3c2e76 | ||
|
|
dd3c3ac441 | ||
|
|
cc494e486f | ||
|
|
4c9637ddc4 | ||
|
|
5d4db87a96 | ||
|
|
ad87145c42 | ||
|
|
216d98816f | ||
|
|
12aef47a06 | ||
|
|
b7de7187ce | ||
|
|
f0e1f214ef | ||
|
|
7ea6d4f618 | ||
|
|
57df106f0a | ||
|
|
329df3e5c6 | ||
|
|
c7e486d3e3 | ||
|
|
86093a5606 | ||
|
|
ee5c15b901 | ||
|
|
3f4340ecb7 | ||
|
|
fbcf17a726 | ||
|
|
5a8e0fe488 | ||
|
|
fafab171c5 | ||
|
|
88cc77c92d | ||
|
|
03416088b5 | ||
|
|
96da0c621b | ||
|
|
1d71be4d2e | ||
|
|
50cbedd9f7 | ||
|
|
ad33e2410e | ||
|
|
2d9b3a542f | ||
|
|
5039e085d8 | ||
|
|
622849d233 | ||
|
|
8e3f7469ed | ||
|
|
14a8f25476 | ||
|
|
cf12d2eb82 | ||
|
|
3041a122fe | ||
|
|
b5f33350fc | ||
|
|
b65cba7410 | ||
|
|
3ee321bbce | ||
|
|
7c6d963b6e | ||
|
|
53da0d0b4c | ||
|
|
cd06779bc9 | ||
|
|
ae8e5379e6 | ||
|
|
86e169a18e | ||
|
|
cc44f2818c | ||
|
|
f850a80931 | ||
|
|
c06fd26a52 | ||
|
|
e05bb10059 | ||
|
|
38f928d0af | ||
|
|
748405092e | ||
|
|
7ebe11034e | ||
|
|
0ebccc2d5d | ||
|
|
7b60c347af | ||
|
|
9894205208 | ||
|
|
3a7ebd0928 | ||
|
|
61e213ec22 | ||
|
|
77d9330151 | ||
|
|
9f76f050c0 | ||
|
|
53e559eaf4 | ||
|
|
f2bd47e519 | ||
|
|
be0b4e583d | ||
|
|
9a3f87fcff | ||
|
|
cff157d7f1 | ||
|
|
2cf35bd8f4 | ||
|
|
4132ffaed4 | ||
|
|
16df73c2d4 | ||
|
|
d622f6602c | ||
|
|
809ad6f05d | ||
|
|
b03529ec75 | ||
|
|
424dc3d82c | ||
|
|
d842c8db5d | ||
|
|
f2b7864464 | ||
|
|
6e9e07cd2e | ||
|
|
1f7a41ced1 | ||
|
|
46f283fb4e | ||
|
|
6a97f1fc01 | ||
|
|
6103fde575 | ||
|
|
42a3a98682 | ||
|
|
5c0ae83d4d | ||
|
|
fb28514257 | ||
|
|
e93cdced47 | ||
|
|
f4539cac1c | ||
|
|
83020e29d3 | ||
|
|
de04d0019a | ||
|
|
a8c9af8af3 | ||
|
|
7ca3f1770d | ||
|
|
5b46d4a66c | ||
|
|
b17682fb6e | ||
|
|
c540036319 | ||
|
|
efb0b8c65d | ||
|
|
3c4d5cb628 | ||
|
|
10df9c8d06 | ||
|
|
39827a6b57 | ||
|
|
4d41d47104 | ||
|
|
d3a401b6d7 | ||
|
|
0894b802eb | ||
|
|
0b440fb8fd | ||
|
|
99d9017991 | ||
|
|
1f913889b4 | ||
|
|
af6d9752c2 | ||
|
|
c2f44c061a | ||
|
|
edc14b5f29 | ||
|
|
77debf311d | ||
|
|
8789920e8f | ||
|
|
08496e576b | ||
|
|
cacec6ad78 | ||
|
|
83e2ba042a | ||
|
|
523bb11605 | ||
|
|
0f55931c5d | ||
|
|
2d2e377eb7 | ||
|
|
6673712daa | ||
|
|
aa2a0a6a57 | ||
|
|
e36578530e | ||
|
|
032985178a | ||
|
|
e48d90edaa | ||
|
|
94a6e11354 | ||
|
|
d5d2b7bd8b | ||
|
|
d59083eb6d | ||
|
|
209af01671 | ||
|
|
affd5034f2 | ||
|
|
23c965f360 | ||
|
|
5e917b65ff | ||
|
|
b43c07c56a | ||
|
|
c1e0d8bb1b | ||
|
|
44a6ebab9a | ||
|
|
a4daff756f | ||
|
|
37abf1e262 | ||
|
|
1e88a5ecc1 | ||
|
|
950a9772ad | ||
|
|
5dc0cac20a | ||
|
|
cbc4bf0dc3 | ||
|
|
1e48e6f2b7 | ||
|
|
f02488633a | ||
|
|
8595f54301 | ||
|
|
80d72abf6e | ||
|
|
3394f256e3 | ||
|
|
6a35824cd9 | ||
|
|
4489840e39 | ||
|
|
efed814d2a | ||
|
|
7d2ac96458 | ||
|
|
8b679c4179 | ||
|
|
8733363a89 | ||
|
|
e77c45be52 | ||
|
|
820c02bec9 | ||
|
|
4c42e8a414 | ||
|
|
84e76dcbd8 | ||
|
|
b7fc3dbd6f | ||
|
|
8868283895 | ||
|
|
30ea708d09 | ||
|
|
4d8adf3ed9 | ||
|
|
3011742fa1 | ||
|
|
62e0acc584 | ||
|
|
b185ff7fee | ||
|
|
c7b8efa4dc | ||
|
|
af97f8e669 | ||
|
|
dd5b1bd645 | ||
|
|
679b8bd070 | ||
|
|
2709b84d59 | ||
|
|
c13d5581cc | ||
|
|
6ec3ef7f68 | ||
|
|
1bdceaac3c | ||
|
|
07ea970eed | ||
|
|
c745add934 | ||
|
|
bb14333ab7 | ||
|
|
a59946d770 | ||
|
|
f9bdcf825b | ||
|
|
d8040d4a19 | ||
|
|
c07101fb4b | ||
|
|
3d57c9805c | ||
|
|
e0a4a725be | ||
|
|
8055c0497d | ||
|
|
15614cb953 | ||
|
|
6b79a5a976 | ||
|
|
7e2b7206b2 | ||
|
|
af441c9c1b | ||
|
|
6fd7134c52 | ||
|
|
c78ad8dc98 | ||
|
|
b40f2e9a7b | ||
|
|
73772278ac | ||
|
|
5ca2431de3 | ||
|
|
b840231d62 | ||
|
|
9f0b42d468 | ||
|
|
f3d9a88da1 | ||
|
|
7f0556ec69 | ||
|
|
37fb85c7d7 | ||
|
|
6fbb625e64 | ||
|
|
92fd247b3b | ||
|
|
98664d568b | ||
|
|
25d5bbb35f | ||
|
|
cd296f84be | ||
|
|
7d93c9930c | ||
|
|
5af958465b | ||
|
|
0470c0a973 | ||
|
|
16bf776ddb | ||
|
|
f3a8fedd29 | ||
|
|
c7592c73eb | ||
|
|
82de5d4ef2 | ||
|
|
b0b6fc396d | ||
|
|
d4159b77bd | ||
|
|
78507986f2 | ||
|
|
2cede5bf21 | ||
|
|
56cacc5e5f | ||
|
|
889d66e75a | ||
|
|
3a55b9fa57 | ||
|
|
2a3805af6a | ||
|
|
5cbfb62dea | ||
|
|
0298a45d4e | ||
|
|
79b27a578a | ||
|
|
160a26fbd4 | ||
|
|
a03e44278b | ||
|
|
d3dd66563c | ||
|
|
cc7bbb4a57 | ||
|
|
270ae38b89 | ||
|
|
394cc1ac53 | ||
|
|
cd6edab845 | ||
|
|
ea947ec35c | ||
|
|
c2f6e24517 | ||
|
|
471624c93c | ||
|
|
6879f1086e | ||
|
|
6fa7d76793 | ||
|
|
b96095f31c | ||
|
|
188989a412 | ||
|
|
c8a4817e1d | ||
|
|
fa51b77de1 | ||
|
|
cf8c40c17a | ||
|
|
f2ff365933 | ||
|
|
8d36d44845 | ||
|
|
935e5216e3 | ||
|
|
5925e336f6 | ||
|
|
76ec811319 | ||
|
|
889d87e26f | ||
|
|
75ea9cfb4e | ||
|
|
04ccfdf685 | ||
|
|
b40164c0f8 | ||
|
|
066ac7543b | ||
|
|
4bf18f5886 | ||
|
|
1517aa3389 | ||
|
|
4f4d64a817 | ||
|
|
1965e31b11 | ||
|
|
82c3601cb1 | ||
|
|
915b718f22 | ||
|
|
91e1a388c3 | ||
|
|
ff198223eb | ||
|
|
999fefa0e5 | ||
|
|
aa0f2e9f4c | ||
|
|
8deda93cd1 | ||
|
|
d9637d8ebd | ||
|
|
b30c039397 | ||
|
|
5198cb5f6e | ||
|
|
37b67c6f0c | ||
|
|
6976d2aa1a | ||
|
|
fe11d1788d | ||
|
|
fe9a2b2574 | ||
|
|
2ead5262e3 | ||
|
|
7a53c54184 | ||
|
|
30e4905ffd | ||
|
|
4e59f4c16e | ||
|
|
43d6766cfa | ||
|
|
585c49dc4a | ||
|
|
5ad1188a30 | ||
|
|
cce748c4e3 | ||
|
|
a14081faa6 | ||
|
|
d52be167d5 | ||
|
|
74b6af858e | ||
|
|
0a83402958 | ||
|
|
e08c09ed6c | ||
|
|
3ffac6da5c | ||
|
|
51e5598d63 | ||
|
|
fa0bd7d6d7 | ||
|
|
52f7da5854 | ||
|
|
765bd1337b | ||
|
|
ffd6ab647f | ||
|
|
5e1818b99f | ||
|
|
5f9bc7aed6 | ||
|
|
cd91a3efa3 | ||
|
|
65192a7698 | ||
|
|
21501736cb | ||
|
|
c96e97f618 | ||
|
|
7866417ebb | ||
|
|
49621e5133 | ||
|
|
02af213f0f | ||
|
|
8e106cebbf | ||
|
|
e704406368 | ||
|
|
dab87f06b7 | ||
|
|
29be58b0f7 | ||
|
|
764ccbd5ed | ||
|
|
aff1e0e519 | ||
|
|
18506dc5aa | ||
|
|
6ffe06cd65 | ||
|
|
61d2cc6555 | ||
|
|
53ff18b38b | ||
|
|
067a07c1ed | ||
|
|
8e7cd876a0 | ||
|
|
ad29806611 | ||
|
|
0c99d9caa9 | ||
|
|
0e8e94324b | ||
|
|
9ac9839b95 | ||
|
|
5213c117dc | ||
|
|
fb543ac62e | ||
|
|
89e449d1ff | ||
|
|
b22a904d02 | ||
|
|
638c0bab6f | ||
|
|
b5a1bac0cd | ||
|
|
56fb614050 | ||
|
|
0e1fc505cf | ||
|
|
9f78bff377 | ||
|
|
b2faf20569 | ||
|
|
1f810293ff | ||
|
|
f56a175101 | ||
|
|
f859d9a3ee | ||
|
|
4b4e3d42f3 | ||
|
|
5985fbae42 | ||
|
|
16afa420a2 | ||
|
|
88a23f4d5a | ||
|
|
18db1ef37c | ||
|
|
059a4f10c2 | ||
|
|
83ad300b1c | ||
|
|
3486b48261 | ||
|
|
6fa84b3c06 | ||
|
|
0e51abc38e | ||
|
|
b8a1176c26 | ||
|
|
8445d32283 | ||
|
|
2b19d34a17 | ||
|
|
d13075a4fd | ||
|
|
40400b7a3b | ||
|
|
283541795f | ||
|
|
d7e3e55445 | ||
|
|
377726fa0a | ||
|
|
5d2e7f394e | ||
|
|
2f2ff1ed35 | ||
|
|
38f7e0b94b | ||
|
|
78cd074370 | ||
|
|
9c934048f8 | ||
|
|
63ae0116d0 | ||
|
|
33119558c3 | ||
|
|
39dc6d6379 | ||
|
|
4fda64eea8 | ||
|
|
ef5e294259 | ||
|
|
b0a890cb93 | ||
|
|
c70ad2d069 | ||
|
|
5deaab7283 | ||
|
|
67d7cd2290 | ||
|
|
ea1ca3eb84 | ||
|
|
193322da5f | ||
|
|
f2cb797ae2 | ||
|
|
a15925e3ce | ||
|
|
ab95ec2b93 | ||
|
|
a104de3509 | ||
|
|
e4cf58b433 | ||
|
|
921e206d56 | ||
|
|
23695fb04b | ||
|
|
1c770f74d0 | ||
|
|
e0d57bf2a7 | ||
|
|
a101490f31 | ||
|
|
49588ced04 | ||
|
|
73a4dc157a | ||
|
|
6d30d4b7bd | ||
|
|
08ce5dde50 | ||
|
|
bba629d19e | ||
|
|
5436b667ff | ||
|
|
510863a4d5 | ||
|
|
5637174389 | ||
|
|
8894bca353 | ||
|
|
dfe097e87a | ||
|
|
5e840d7b53 | ||
|
|
7070091856 | ||
|
|
f12ecf2bb9 | ||
|
|
8efdcf379c | ||
|
|
6dbcac0752 | ||
|
|
e5e716de3c | ||
|
|
02e0477417 | ||
|
|
fe94cb0600 | ||
|
|
c4b7312afb | ||
|
|
0e378ca338 | ||
|
|
080d52ba5b | ||
|
|
44c11740e1 | ||
|
|
487fa135cc | ||
|
|
aec3dcb391 | ||
|
|
8d874e4651 | ||
|
|
f128f54ce7 | ||
|
|
66562245ba | ||
|
|
7b050a1f41 | ||
|
|
a4666d3978 | ||
|
|
e8e730058d | ||
|
|
c8f447b1b8 | ||
|
|
7d5a0cf559 | ||
|
|
9c0991e450 | ||
|
|
1fc1de6df8 | ||
|
|
31ae0acea6 | ||
|
|
3887206fd6 | ||
|
|
181a22f61d | ||
|
|
06e862ff15 | ||
|
|
79ac808e59 | ||
|
|
20febb9a1f | ||
|
|
79a060fecf | ||
|
|
abf5ebf750 | ||
|
|
383a06d9a4 | ||
|
|
8ed21dd853 | ||
|
|
290e51da1f | ||
|
|
beecab0aea | ||
|
|
10b5f62078 | ||
|
|
aa430e9e08 | ||
|
|
9bc0d06d1b | ||
|
|
f24df53aa8 | ||
|
|
c4ff062c66 | ||
|
|
123394de5c | ||
|
|
5b126b9f57 | ||
|
|
118423cf14 | ||
|
|
4cabdd5172 | ||
|
|
b09c9b2ca2 | ||
|
|
9ef5025c22 | ||
|
|
0097ae96f6 | ||
|
|
227b9556df | ||
|
|
846b430008 | ||
|
|
71ad9a63b6 | ||
|
|
8368d59d9f | ||
|
|
80b58d3d60 | ||
|
|
f49d040ae9 | ||
|
|
da7c012fbe | ||
|
|
24e558a569 | ||
|
|
14597a31fa | ||
|
|
bf20f6aadb | ||
|
|
1ae70be714 | ||
|
|
40ed968ba4 | ||
|
|
df0ab548de | ||
|
|
3d017571ca | ||
|
|
af9c24a59d | ||
|
|
507df5d272 | ||
|
|
73fa821b37 | ||
|
|
391db5f83f | ||
|
|
1159d1f4c8 | ||
|
|
275beb68a6 | ||
|
|
5fec8b5abc | ||
|
|
d4b8225030 | ||
|
|
e618258d19 | ||
|
|
330329793c | ||
|
|
0fe62b2a67 | ||
|
|
a7c0c78885 | ||
|
|
96c90587bd | ||
|
|
3921cc0137 | ||
|
|
19183b3506 | ||
|
|
367e84b4b1 | ||
|
|
aaab8a773b | ||
|
|
8693e19eae | ||
|
|
44779f0bb1 | ||
|
|
2114c720a7 | ||
|
|
0c5e77c5d7 | ||
|
|
35dc577615 | ||
|
|
8180e6451c | ||
|
|
582575a899 | ||
|
|
f700482ac1 | ||
|
|
448d8a6fa3 | ||
|
|
a653a9b8c0 | ||
|
|
652abb40e7 | ||
|
|
cf349c8afd | ||
|
|
7d6c56b416 | ||
|
|
83a606c66f | ||
|
|
f48f7f1a2b | ||
|
|
9ae54b7f28 | ||
|
|
cfbeb27c0a | ||
|
|
f8cad8f5f4 | ||
|
|
c78a357d96 | ||
|
|
7cf9fad27e | ||
|
|
7ffef6df72 | ||
|
|
0b4efe42a2 | ||
|
|
b1aea5f7ad | ||
|
|
805f0e3554 | ||
|
|
a6c278a574 | ||
|
|
bf5f132893 | ||
|
|
537f77d9ff | ||
|
|
9e51aeb5b8 | ||
|
|
62bcc1fbf1 | ||
|
|
b2816ff6d6 | ||
|
|
7e5d4a2b12 | ||
|
|
0960232db6 | ||
|
|
9638d38213 | ||
|
|
2647ac5475 | ||
|
|
70881c6ac5 | ||
|
|
7536e1d899 | ||
|
|
0c3b4b0bfb | ||
|
|
e4f71d9369 | ||
|
|
8dbe3adcf6 | ||
|
|
67b4a689ff | ||
|
|
ffdf5ec12f | ||
|
|
9acfeb2506 | ||
|
|
01b5fd0be0 | ||
|
|
1d1cde506f | ||
|
|
5bca1be28d | ||
|
|
f1c31916b0 | ||
|
|
1ffa2d59bd | ||
|
|
8e0a49ce3d | ||
|
|
ad515830e8 | ||
|
|
bd3e1e5e64 | ||
|
|
fcb97fe422 | ||
|
|
4cb36768e5 | ||
|
|
4bdca277d0 | ||
|
|
8375b2ab61 | ||
|
|
ef5cab4987 | ||
|
|
d85c6f8989 | ||
|
|
09737a50e7 | ||
|
|
7952f3f6e5 | ||
|
|
1f4cabf15e | ||
|
|
8cbbc52a74 | ||
|
|
b7452ae846 | ||
|
|
554996eac2 | ||
|
|
36ad2c2bb7 | ||
|
|
985c900b05 | ||
|
|
882252432d | ||
|
|
5cd04d0191 | ||
|
|
c458f926cb | ||
|
|
0ced823b8b | ||
|
|
89ed94a620 | ||
|
|
86c7767e97 | ||
|
|
66c0d0b441 | ||
|
|
0652c93abd | ||
|
|
153f667ec8 | ||
|
|
906df2f114 | ||
|
|
0f7cc67325 | ||
|
|
2c40a543a6 | ||
|
|
1202c8b68a | ||
|
|
30c8b02cc4 | ||
|
|
381dda922d | ||
|
|
52313ffc46 | ||
|
|
ffe2656b77 | ||
|
|
e2a720425c | ||
|
|
c42c9f8be5 | ||
|
|
ee0735601c | ||
|
|
d5cc93a815 | ||
|
|
bd823896aa | ||
|
|
68d6ce0578 | ||
|
|
8a4787c875 | ||
|
|
26a9d74c7a | ||
|
|
b37c1ee1d6 | ||
|
|
40890b353d | ||
|
|
749562c46f | ||
|
|
4730a2056e | ||
|
|
848dac0df1 | ||
|
|
4c9e9fbfec | ||
|
|
f41ff4bbca | ||
|
|
510330554f | ||
|
|
dfbb1ccd4f | ||
|
|
66ca7111a4 | ||
|
|
d2908cc08d | ||
|
|
bc6b814517 | ||
|
|
651902b243 | ||
|
|
fcb512a49f | ||
|
|
7ebfd53ec3 | ||
|
|
2775d4cfc6 | ||
|
|
5d363564a3 | ||
|
|
215a13872a | ||
|
|
3361603a70 | ||
|
|
ddfccd54fb | ||
|
|
3bf1811998 | ||
|
|
2f726a0468 | ||
|
|
e88d7e3320 | ||
|
|
ffbf1d6a4d | ||
|
|
d67311bc60 | ||
|
|
02eeba121e | ||
|
|
0a354c9dfb | ||
|
|
fb8371d0cd | ||
|
|
bfff1224e0 | ||
|
|
0b1f69ba89 | ||
|
|
f8a564f2c8 | ||
|
|
af209c0fe4 | ||
|
|
7d19de318c | ||
|
|
07c39de889 | ||
|
|
a72222d19a | ||
|
|
5fbdf29515 | ||
|
|
901f63a866 | ||
|
|
3e1dc7c582 | ||
|
|
9d569288da | ||
|
|
e4faac2b49 | ||
|
|
db889f9fa4 | ||
|
|
545947d4e7 | ||
|
|
f8be93f8c4 | ||
|
|
668c51d250 | ||
|
|
2bee80d764 | ||
|
|
ec1a7c5f99 | ||
|
|
9cab2fcba4 | ||
|
|
16e419d59f | ||
|
|
d91072da73 | ||
|
|
c938dcc2d3 | ||
|
|
24c4fa166c | ||
|
|
65ef7f32cb | ||
|
|
9a5f6a3a8a | ||
|
|
aa5e5ce789 | ||
|
|
2241ef0573 | ||
|
|
10103817a1 | ||
|
|
2ea3cffad6 | ||
|
|
c16062a983 | ||
|
|
2be1bd0463 | ||
|
|
33180db13d | ||
|
|
e384e85fdf | ||
|
|
84e40e95f8 | ||
|
|
f79001b972 | ||
|
|
b1387bc941 | ||
|
|
09c528ae99 | ||
|
|
af1acc4899 | ||
|
|
16305362c8 | ||
|
|
ded5720b48 | ||
|
|
385855bd5d | ||
|
|
e1efb3b79f | ||
|
|
a30d187ec2 | ||
|
|
b3d024f0da | ||
|
|
94125cbc9b | ||
|
|
b6b96b4ba5 | ||
|
|
e97f5e94eb | ||
|
|
314fcca806 | ||
|
|
cd936ac686 | ||
|
|
8f6892c59f | ||
|
|
81e75d9ca5 | ||
|
|
a8cd16b06a | ||
|
|
185f459d22 | ||
|
|
8264c4afa0 | ||
|
|
5e12b475bb | ||
|
|
e7dad86f91 | ||
|
|
a9400ce06b | ||
|
|
075c94673b | ||
|
|
e5c45f1225 | ||
|
|
251c57874a | ||
|
|
77dd63ef7e | ||
|
|
a151dbcf6f | ||
|
|
5c2092da78 | ||
|
|
b0ff3fff6f | ||
|
|
8fe8ba6bf1 | ||
|
|
11d6fa7cbe | ||
|
|
cafa2191aa | ||
|
|
1751bf8f14 | ||
|
|
e023165f75 | ||
|
|
9246e35a5d | ||
|
|
ab13f6b793 | ||
|
|
15c5edec57 | ||
|
|
36bd0ffc75 | ||
|
|
d07a2bda7a | ||
|
|
424c0413fb | ||
|
|
a601d09d4f | ||
|
|
2343677277 | ||
|
|
5f6ec6d9f3 | ||
|
|
c06c77bf5e | ||
|
|
75bc7134a4 | ||
|
|
3822b3bc79 | ||
|
|
e1291a62a2 | ||
|
|
3574cd2ddf | ||
|
|
2a63c745fc | ||
|
|
da8fb030e2 | ||
|
|
75e1821b48 | ||
|
|
f9e1ebfb47 | ||
|
|
0fde796de8 | ||
|
|
a0bb32ae66 | ||
|
|
ce72ccacbe | ||
|
|
7dac169e12 | ||
|
|
3f7f344d3a | ||
|
|
a41398464c | ||
|
|
f03f13f1d3 | ||
|
|
d92892b84c | ||
|
|
d245733864 | ||
|
|
950dd5651a | ||
|
|
7b29c5a9d8 | ||
|
|
a23004fa8b | ||
|
|
721d2085ee | ||
|
|
19c8fd600d | ||
|
|
a267eac253 | ||
|
|
795b1c3d64 | ||
|
|
c34b6c57fb | ||
|
|
35f88f1e20 | ||
|
|
b16c910995 | ||
|
|
ca4fae0cad | ||
|
|
f44153577e | ||
|
|
f22e7e02f1 | ||
|
|
557906c403 | ||
|
|
982d95a0fd | ||
|
|
3de0d5e2b0 | ||
|
|
5cf298caf2 | ||
|
|
4994b1b86a | ||
|
|
5b65baf15f | ||
|
|
1cdf63bc22 | ||
|
|
bbf81a756a | ||
|
|
2ddc818819 | ||
|
|
20f2bff9b5 | ||
|
|
2605aefe06 | ||
|
|
59b43c59f7 | ||
|
|
aef0451013 | ||
|
|
320affbb38 | ||
|
|
b387b65cdb | ||
|
|
41d3d0f5cd | ||
|
|
978cfb3c5f | ||
|
|
1452488945 | ||
|
|
83e90dc75c | ||
|
|
8b2eba700c | ||
|
|
36cdd97aca | ||
|
|
c4e53d623c | ||
|
|
6669172ae8 | ||
|
|
42e3488577 | ||
|
|
f0ba21248f | ||
|
|
a46dd3b315 | ||
|
|
6af872885b | ||
|
|
5d450d11c4 | ||
|
|
2798f41d80 | ||
|
|
797446b6c0 | ||
|
|
1f533b9eeb | ||
|
|
bcedc6b7b5 | ||
|
|
dc2a0ca3e6 | ||
|
|
a32e431a6d | ||
|
|
4df9fdaa2d | ||
|
|
9a54951652 | ||
|
|
13e22e9898 | ||
|
|
08e9862839 | ||
|
|
396f320791 | ||
|
|
7501d70b81 | ||
|
|
9edc769c11 | ||
|
|
b4870295ab | ||
|
|
9a6626aca6 | ||
|
|
63cf7b8387 | ||
|
|
67f25439be | ||
|
|
01a3362313 | ||
|
|
422fe12973 | ||
|
|
44671a8561 | ||
|
|
74a9aa2e49 | ||
|
|
674b8f4b50 | ||
|
|
f2c9ed92c6 | ||
|
|
62aa322513 | ||
|
|
2323f12ddd | ||
|
|
85e8911b0d | ||
|
|
30d02fc790 | ||
|
|
3d5ddacc0c | ||
|
|
da023c4e9c | ||
|
|
0cd1b17266 | ||
|
|
fd5a89c450 | ||
|
|
e4e3844c2a | ||
|
|
ca6d06805e | ||
|
|
7364775cb7 | ||
|
|
21b6ccec39 | ||
|
|
d109ab625d | ||
|
|
e265214051 | ||
|
|
6b11242c53 | ||
|
|
8a2006b8a2 | ||
|
|
84c3e3932c | ||
|
|
26776f225b | ||
|
|
5278d5bc5b | ||
|
|
fc5512f80f | ||
|
|
6fca4a77aa | ||
|
|
b4d9d84a4a | ||
|
|
5ce2121d31 | ||
|
|
7f0844689f | ||
|
|
e4783deb97 | ||
|
|
5bfaa0f74c | ||
|
|
617f22b0d7 | ||
|
|
64023c89e3 | ||
|
|
7bc583c4ff | ||
|
|
fc446a3df1 | ||
|
|
6eb7a29ec1 | ||
|
|
0ca6eb2a9a | ||
|
|
90fbdcb2df | ||
|
|
75c00b3356 | ||
|
|
ba40fdc50e | ||
|
|
ee407cfdd2 | ||
|
|
79859c1431 | ||
|
|
0f038a38d7 | ||
|
|
f333cd8061 | ||
|
|
d7e0060876 | ||
|
|
eb68274d2c | ||
|
|
2bd64f98fc | ||
|
|
29147257fb | ||
|
|
30a19d23ea | ||
|
|
5d3989c1e9 | ||
|
|
6af58a7403 | ||
|
|
24dd34275c | ||
|
|
b9623f4c13 | ||
|
|
c0b4204f5e | ||
|
|
34aabbc1be | ||
|
|
813406e52b | ||
|
|
5c0911d84e | ||
|
|
daca02e7e1 | ||
|
|
684fa80750 | ||
|
|
01fa9b8035 | ||
|
|
ec95aad451 | ||
|
|
d14730b4da | ||
|
|
c5c159c789 | ||
|
|
8d97640fee | ||
|
|
677eca4d7e | ||
|
|
7788e6b0f7 | ||
|
|
41720c208b | ||
|
|
2173f203f1 | ||
|
|
e9c594cce0 | ||
|
|
6ad7b2666d | ||
|
|
6023910162 | ||
|
|
6e40506f7c | ||
|
|
bf71013a37 | ||
|
|
178f7415bc | ||
|
|
bd4917adae | ||
|
|
2e0731c2d4 | ||
|
|
91e94d592d | ||
|
|
52b780eb92 | ||
|
|
50dbc67ee1 | ||
|
|
1bb2d16f76 | ||
|
|
a4f0c52db3 | ||
|
|
e8c7ffa909 | ||
|
|
db87b9f024 | ||
|
|
69014c1d05 | ||
|
|
a7956d4a2a | ||
|
|
cb47f728fd | ||
|
|
082144c64d | ||
|
|
b5a84eb5cc | ||
|
|
e0a0a4b47d | ||
|
|
cd19573c0d | ||
|
|
f6205ee266 | ||
|
|
3554ea8ff7 | ||
|
|
fbcd69aea0 | ||
|
|
ced6c3d9fd | ||
|
|
0e9e0c227c | ||
|
|
b08aa7be7c | ||
|
|
243e1f12bf | ||
|
|
ce0ce29d6d | ||
|
|
648ceea602 | ||
|
|
90ebc3e653 | ||
|
|
1ad18cb926 | ||
|
|
976c2f4e4a | ||
|
|
3e1fad2c55 | ||
|
|
77aa8e4f6b | ||
|
|
f3ec6246c8 | ||
|
|
2cf8db4018 | ||
|
|
da202afdd9 | ||
|
|
e60a461146 | ||
|
|
3dc1bb2811 | ||
|
|
8a42480e6b | ||
|
|
c9a0c7e59f | ||
|
|
42e43068fb | ||
|
|
aff0090a6e | ||
|
|
9490b87523 | ||
|
|
1bdf045d45 | ||
|
|
dc8d4446d8 | ||
|
|
572e000b6c | ||
|
|
ab2a064544 | ||
|
|
d575b4a83f | ||
|
|
97ea204bb2 | ||
|
|
0dd86b55cb | ||
|
|
fa6019e7ed | ||
|
|
5bec7821c5 | ||
|
|
e25ba0b884 | ||
|
|
b6f5b45279 | ||
|
|
1528ee5a10 | ||
|
|
5a615c72d4 | ||
|
|
9a0a4a437e | ||
|
|
e673c45241 | ||
|
|
c293b301bd | ||
|
|
b46fa75619 | ||
|
|
749838e479 | ||
|
|
b9523dfa65 | ||
|
|
ce693d4fa6 | ||
|
|
6cbed24e7b | ||
|
|
f11e44e792 | ||
|
|
a471f7dbaf | ||
|
|
df634234e0 | ||
|
|
aea9ad99e3 | ||
|
|
c4714f66a0 | ||
|
|
0940046381 | ||
|
|
2e85c784e0 | ||
|
|
f668026771 | ||
|
|
4ea80a38cd | ||
|
|
8d968700ae | ||
|
|
090509ad0e | ||
|
|
8d82d4cac5 | ||
|
|
58bf95248d | ||
|
|
45cc2bd967 | ||
|
|
663f3588b2 | ||
|
|
abc120974e | ||
|
|
1892f12239 | ||
|
|
84efd8a2fd | ||
|
|
caa368333b | ||
|
|
b213c30af2 | ||
|
|
ad548f1796 | ||
|
|
0f97483146 | ||
|
|
d02a183d4d | ||
|
|
04704cd260 | ||
|
|
73a40d15f7 | ||
|
|
bce8b9e206 | ||
|
|
be193bad85 | ||
|
|
458a0bf0c0 | ||
|
|
ccca0ca8f2 | ||
|
|
412f57e982 | ||
|
|
8241d59da0 | ||
|
|
bac14f6694 | ||
|
|
a609a48830 | ||
|
|
5f3c4a9f22 | ||
|
|
e8161e859c | ||
|
|
7c80be01a8 | ||
|
|
52e910d981 | ||
|
|
7c59ae119d | ||
|
|
26196c982b | ||
|
|
5d86e62086 | ||
|
|
93263485d2 | ||
|
|
293ae5ab09 | ||
|
|
63a60c55a8 | ||
|
|
3bf977771c | ||
|
|
abcd8e38bc | ||
|
|
0e2f48d6d7 | ||
|
|
8a562f7b7a | ||
|
|
70b9288f15 | ||
|
|
fade11f10f | ||
|
|
75d3ead833 | ||
|
|
f04226691b | ||
|
|
90b3af9a89 | ||
|
|
bd17fc22f9 | ||
|
|
f422135200 | ||
|
|
b1ef1086b3 | ||
|
|
bf68be6116 | ||
|
|
d3553e9f50 | ||
|
|
0415a304f6 | ||
|
|
60cc3466f7 | ||
|
|
203ccee62a | ||
|
|
18a489e8ba | ||
|
|
6d78a4c651 | ||
|
|
74d1919f68 | ||
|
|
9552baf028 | ||
|
|
fd98f12c65 | ||
|
|
d77ac56f0f | ||
|
|
4a4ab12a5b | ||
|
|
80a8312c06 | ||
|
|
1eaf2140e5 | ||
|
|
9e38885615 | ||
|
|
9b8a161b94 | ||
|
|
84aca85217 | ||
|
|
22a4924df3 | ||
|
|
14a7127df7 | ||
|
|
4217100628 | ||
|
|
5e25df43a9 | ||
|
|
eefdd2ffa1 | ||
|
|
1468c04593 | ||
|
|
f6fa86f598 | ||
|
|
913fc2f7ce | ||
|
|
1cbd959a46 | ||
|
|
b9eb68f792 | ||
|
|
479eddaab6 | ||
|
|
e3424896cb | ||
|
|
e8ba84e707 | ||
|
|
9bcfdf1e95 | ||
|
|
1b943cff28 | ||
|
|
e105fb493d | ||
|
|
1cb8071bc6 | ||
|
|
80f3cda31b | ||
|
|
dc581b1555 | ||
|
|
a3af7dcc77 | ||
|
|
6b58016616 | ||
|
|
ec9a78a27a | ||
|
|
1b000bc063 | ||
|
|
47d475fdb5 | ||
|
|
47691d4002 | ||
|
|
7bd426dace | ||
|
|
9aed0910fc | ||
|
|
0d9fb99e2c | ||
|
|
5654d17332 | ||
|
|
289dd5b676 | ||
|
|
e071a6a9cf | ||
|
|
89cc120017 | ||
|
|
7332c7b325 | ||
|
|
58a3a6ff3e | ||
|
|
099d1bfa82 | ||
|
|
8060ba2b1b | ||
|
|
cd1b9008e4 | ||
|
|
0025e4608e | ||
|
|
5efcf8264f | ||
|
|
4843e36794 | ||
|
|
5593d22f46 | ||
|
|
02d3e2395f | ||
|
|
099d55d4a5 | ||
|
|
2d4c9248e7 | ||
|
|
3e44e9292c | ||
|
|
7c9234b540 | ||
|
|
0b04f0f731 | ||
|
|
8ce8ffaba0 | ||
|
|
89ae01fc6d | ||
|
|
d439bb0ef3 | ||
|
|
65a48ca731 | ||
|
|
2baf29eadc | ||
|
|
f09a90bbf1 | ||
|
|
fc53638c7a | ||
|
|
307e7bd56c | ||
|
|
93b22b9fea | ||
|
|
7554d6c41a | ||
|
|
71321900e3 | ||
|
|
b0eafa16e2 | ||
|
|
fc9f9ab95e | ||
|
|
c90eb19532 | ||
|
|
3e0b2737bf | ||
|
|
82b1a18955 | ||
|
|
87aa17b6d7 | ||
|
|
c6664ae7f2 | ||
|
|
1d523622bb | ||
|
|
ef10353b7d | ||
|
|
8a99584115 | ||
|
|
fdc6509c73 | ||
|
|
b6d8b1a297 | ||
|
|
f41f3974a4 | ||
|
|
1f4caf6bf2 | ||
|
|
6571fc3e4a | ||
|
|
297d6046e2 | ||
|
|
88fc82be86 | ||
|
|
8230d64440 | ||
|
|
6d190308bc | ||
|
|
d67726d5e7 | ||
|
|
e716c830d5 | ||
|
|
18e1f4ce22 | ||
|
|
b01b1be71b | ||
|
|
3e1c915a78 | ||
|
|
558ac32f44 | ||
|
|
2ea87a25cf | ||
|
|
ebc7159c37 | ||
|
|
a2604fdc91 | ||
|
|
2e3e5c1ab7 | ||
|
|
cd5609c45a | ||
|
|
82387c7f27 | ||
|
|
bb5d5040be | ||
|
|
9024119dc6 | ||
|
|
afa89f38fa | ||
|
|
0af0190688 | ||
|
|
4902adbe8f | ||
|
|
b7efa6203f | ||
|
|
afc1c4ec84 | ||
|
|
a58c2931c4 | ||
|
|
3d4b1f3fc2 | ||
|
|
d3fc54b24d | ||
|
|
02b326cdd1 | ||
|
|
5640baeeda | ||
|
|
5e1dd3e16d | ||
|
|
1c30ad888a | ||
|
|
ce53fbc848 | ||
|
|
0e004d80f7 | ||
|
|
248bee3339 | ||
|
|
9a902fc1cf | ||
|
|
e06041f613 | ||
|
|
c952992462 | ||
|
|
28d5945b98 | ||
|
|
0f364fa936 | ||
|
|
10f844dac6 | ||
|
|
0db8107279 | ||
|
|
c2424cd8e8 | ||
|
|
52d62584a6 | ||
|
|
b82476b794 | ||
|
|
d8a90591c6 | ||
|
|
1f30cfbe95 | ||
|
|
e7058eadbc | ||
|
|
ad73ca00bb | ||
|
|
1ce1bfbd37 | ||
|
|
3980819674 | ||
|
|
f9a9059dc5 | ||
|
|
13681b279b | ||
|
|
3b6d977e5a | ||
|
|
cff5ff1019 | ||
|
|
5da0c9e0bd | ||
|
|
cf2e9b8d31 | ||
|
|
dd3f0b133d | ||
|
|
327efb749b | ||
|
|
86b2bfdcb3 | ||
|
|
7a39c27316 | ||
|
|
e028d53479 | ||
|
|
04b7ac5426 | ||
|
|
3525935b9a | ||
|
|
6aa1d1d093 | ||
|
|
e546874045 | ||
|
|
4fcddfdaa9 | ||
|
|
da47dfe358 | ||
|
|
412c6cea8a | ||
|
|
39e52ee701 | ||
|
|
d35857d91e | ||
|
|
97a0389bcd | ||
|
|
1b663e9bdf | ||
|
|
fc3c8b6892 | ||
|
|
d31a166e52 | ||
|
|
8a4d6bb28f | ||
|
|
50de2be0b4 | ||
|
|
9283f7c4a7 | ||
|
|
67438d3bbf | ||
|
|
da9d520f7f | ||
|
|
bfa8a82ac4 | ||
|
|
d589cd5aae | ||
|
|
0ae7a0701b | ||
|
|
3b82890b47 | ||
|
|
996686fd27 | ||
|
|
f81a84d575 | ||
|
|
234eafcd37 | ||
|
|
cb67eee8e8 | ||
|
|
bcef04748b | ||
|
|
860a109b2e | ||
|
|
790eef0df0 | ||
|
|
2a58236024 | ||
|
|
75e0d491aa | ||
|
|
25eda7cb0b | ||
|
|
3d2f0c94aa | ||
|
|
d4f99855af | ||
|
|
6961badb7e | ||
|
|
37d22ae7d8 | ||
|
|
f4ffdffa82 | ||
|
|
b05ae68a03 | ||
|
|
58e49e57ba | ||
|
|
27313074b6 | ||
|
|
0093c8e650 | ||
|
|
757a85bee9 | ||
|
|
12e4beae90 | ||
|
|
37f0b3106a | ||
|
|
0c84ddc50c | ||
|
|
f5174234f4 | ||
|
|
676f2d17af | ||
|
|
05c2257f2c | ||
|
|
37863f90de | ||
|
|
c3db0876b1 | ||
|
|
4a2cec4625 | ||
|
|
59f7ef4c7d | ||
|
|
6b446e08e2 | ||
|
|
88713a9643 | ||
|
|
b9273f9166 | ||
|
|
134c89912d | ||
|
|
35816b5121 | ||
|
|
cd9d89f58f | ||
|
|
86c668281f | ||
|
|
a99e7a89be | ||
|
|
21965eaa1e | ||
|
|
f6cad0bf5b | ||
|
|
0325d5355f | ||
|
|
cfdc998bf4 | ||
|
|
457cf9f5fd | ||
|
|
8b0ae4fca7 | ||
|
|
85eb6a8027 | ||
|
|
4d2ed0542f | ||
|
|
14f312e2ca | ||
|
|
24557d3d48 | ||
|
|
21b11d4485 | ||
|
|
be97852e40 | ||
|
|
b8ee29db7a | ||
|
|
c230918d2d | ||
|
|
85360248a4 | ||
|
|
454b51aa98 | ||
|
|
59dac1fe5b | ||
|
|
ae33207535 | ||
|
|
1575e56cd3 | ||
|
|
b23f04be7c | ||
|
|
70e96d0ab5 | ||
|
|
2938a099b6 | ||
|
|
f148a40ae0 | ||
|
|
e4012d1d1d | ||
|
|
62fef82338 | ||
|
|
6cde663fab | ||
|
|
dc905720b9 | ||
|
|
a41b26b458 | ||
|
|
a42051057c | ||
|
|
8617044939 | ||
|
|
54e25b2aba | ||
|
|
ae7e92e3ed | ||
|
|
3d46a53356 | ||
|
|
e29dcd59e0 | ||
|
|
828154f95b | ||
|
|
625b9fd608 | ||
|
|
94cd76fc04 | ||
|
|
0578b142b4 | ||
|
|
1b2aa95287 | ||
|
|
27577cf890 | ||
|
|
6cfa3a35cd | ||
|
|
8cf5a61a3c | ||
|
|
b1e741cb38 | ||
|
|
99d400843d | ||
|
|
38bca0ae7b | ||
|
|
8867b15df1 | ||
|
|
b443f324cc | ||
|
|
6834a9cd03 | ||
|
|
e304d43cd4 | ||
|
|
82f8a5a314 | ||
|
|
3034c9a8c4 | ||
|
|
257d798db6 | ||
|
|
0c02ab72e0 | ||
|
|
befc8abc22 | ||
|
|
c45b776ce6 | ||
|
|
d5bd02af88 | ||
|
|
5beca6c06d | ||
|
|
195466e0da | ||
|
|
41284e740a | ||
|
|
ffd996bf59 | ||
|
|
f3a3073afb | ||
|
|
7181631450 | ||
|
|
9f881dbdd8 | ||
|
|
eff3adae15 | ||
|
|
3843245bbb | ||
|
|
f00563fa76 | ||
|
|
bd83ba44ca | ||
|
|
0ce853c147 | ||
|
|
c37509cfeb | ||
|
|
124fb53ff5 | ||
|
|
a0df746f12 | ||
|
|
02538e74d4 | ||
|
|
5fa6553ec0 | ||
|
|
6de4a6c8ac | ||
|
|
1e2594e6a1 | ||
|
|
1b9bdd26a7 | ||
|
|
e1b0b939eb | ||
|
|
661ab3a232 | ||
|
|
b1813ff9c3 | ||
|
|
8fd5b5b846 | ||
|
|
4221bd8f4e | ||
|
|
527758b9e9 | ||
|
|
587906a0dc | ||
|
|
38c6bd37f0 | ||
|
|
879baf636e | ||
|
|
eaa8b5c184 | ||
|
|
dbf379a175 | ||
|
|
fe4d806c33 | ||
|
|
dce438d20c | ||
|
|
5c9afe7171 | ||
|
|
47622e2d4d | ||
|
|
c36a125185 | ||
|
|
2b616b9bbb | ||
|
|
5c02a1f735 | ||
|
|
113980d2b6 | ||
|
|
c64b024d59 | ||
|
|
1e5a8ae82b | ||
|
|
c4310904d7 | ||
|
|
06c60c76bc | ||
|
|
20f67639c8 | ||
|
|
457f4d296d | ||
|
|
3ecc3a4362 | ||
|
|
86581245a9 | ||
|
|
1c0f2f6ad5 | ||
|
|
6b4c65fb19 | ||
|
|
5ae59f23e3 | ||
|
|
059e7759e2 | ||
|
|
1e4b8fdf6a | ||
|
|
e78d45d774 | ||
|
|
d12357f880 | ||
|
|
4acf737df4 | ||
|
|
6673f2b997 | ||
|
|
79daddebaf | ||
|
|
396cb86424 | ||
|
|
f244d48345 | ||
|
|
db7075dcd3 | ||
|
|
655d695907 | ||
|
|
7720cf2b28 | ||
|
|
ef0946e4b8 | ||
|
|
8a9fde6f40 | ||
|
|
47813759e6 | ||
|
|
340d230b7c | ||
|
|
b56fb62074 | ||
|
|
6c4bc65bc6 | ||
|
|
cb00e547c6 | ||
|
|
1c39adb275 | ||
|
|
964373e0a7 | ||
|
|
f3ebf2c44f | ||
|
|
9f515dd920 | ||
|
|
3db7dfbf09 | ||
|
|
6432d28e82 | ||
|
|
43f7e19897 | ||
|
|
80136f56ee | ||
|
|
4c3ed845e4 | ||
|
|
2297bb5259 | ||
|
|
66647c09c9 | ||
|
|
7c3cd2258e | ||
|
|
1fb90a2421 | ||
|
|
c7524ea2b2 | ||
|
|
24269434e1 | ||
|
|
2d23b808cb | ||
|
|
2fe3595fc6 | ||
|
|
5d1d9e3433 | ||
|
|
cbe7ad7a10 | ||
|
|
5f9306d8c2 | ||
|
|
ae5a50d58f | ||
|
|
aff299ed1b | ||
|
|
3c35848eb8 | ||
|
|
1c415ea3a8 | ||
|
|
0fc0e9230b | ||
|
|
0b9fc5a803 | ||
|
|
81b18a99c3 | ||
|
|
f05038d55e | ||
|
|
13cab39c4f | ||
|
|
ed5a359327 | ||
|
|
b534b945b6 | ||
|
|
f895f191f0 | ||
|
|
f8972a3a26 | ||
|
|
5d71b17527 | ||
|
|
f85ef76896 | ||
|
|
024a72d421 | ||
|
|
5a7fb8e458 | ||
|
|
1d5d87d2a4 | ||
|
|
a6cfb7c84e | ||
|
|
f6f39856a5 | ||
|
|
217b53218c | ||
|
|
6cb7252145 | ||
|
|
1cb310cada | ||
|
|
2c0881edda | ||
|
|
01a25dab39 | ||
|
|
c953150deb | ||
|
|
f7dbb109d6 | ||
|
|
fd4b88b99b | ||
|
|
36a6a77cca | ||
|
|
5a45bcf99f | ||
|
|
d262fa4abb | ||
|
|
49944f3a43 | ||
|
|
b73cdf19fa | ||
|
|
aeb36f4241 | ||
|
|
0a30d02128 | ||
|
|
57b93bdc1b | ||
|
|
ad7aa8d606 | ||
|
|
1d7409dd14 | ||
|
|
c969fa59ba | ||
|
|
dfaa4f8054 | ||
|
|
fd7b798527 | ||
|
|
802b80432c | ||
|
|
b885223d12 | ||
|
|
582930c2bc | ||
|
|
34afbfe394 | ||
|
|
0eb4ef06ac | ||
|
|
ead6ffc074 | ||
|
|
0fcba48170 | ||
|
|
07d2b700e6 | ||
|
|
6619867159 | ||
|
|
6d20bbbae5 | ||
|
|
5c18ca4295 | ||
|
|
134499ab9b | ||
|
|
a0216aec5f | ||
|
|
3ab2b5c9ae | ||
|
|
415ed01c0c | ||
|
|
16ef530d51 | ||
|
|
900730f8f3 | ||
|
|
e4c2e5132b | ||
|
|
5daffcd1f2 | ||
|
|
3a61ef3764 | ||
|
|
2f57779367 | ||
|
|
278dc7f67c | ||
|
|
3d10349371 | ||
|
|
e78b38c4dc | ||
|
|
ba0fcadb6e | ||
|
|
7e9b3f8d3b | ||
|
|
ddfc5c3187 | ||
|
|
0717607a07 | ||
|
|
0e127ed1dc | ||
|
|
9e6d235cb7 | ||
|
|
901eb2d674 | ||
|
|
828f4faf6f | ||
|
|
4e520d0522 | ||
|
|
598505fa62 | ||
|
|
5a085a38d1 | ||
|
|
0a4b545e21 | ||
|
|
395cb48d9e | ||
|
|
fe5475f126 | ||
|
|
e2dbbf9019 | ||
|
|
1ef8af92cb | ||
|
|
6e618f5089 | ||
|
|
8b7251ba74 | ||
|
|
1f37dfa553 | ||
|
|
0fd1d2a132 | ||
|
|
02027b056a | ||
|
|
bd5e4d1499 | ||
|
|
0f7d4a2e04 | ||
|
|
a7fe59f363 | ||
|
|
b3d9092499 | ||
|
|
df1443ea47 | ||
|
|
176f87205e | ||
|
|
039fcbb62f | ||
|
|
ce661ddcac | ||
|
|
cf1999c6d1 | ||
|
|
35c63f59d3 | ||
|
|
a9c01fe65b | ||
|
|
32aa03bceb | ||
|
|
4a2599988a | ||
|
|
aaa262f593 | ||
|
|
bf616029e8 | ||
|
|
72d5841a9e | ||
|
|
127d06cf64 | ||
|
|
44d8220877 | ||
|
|
13bf4c7b0d | ||
|
|
d4ee6dad5b | ||
|
|
5630053331 | ||
|
|
f7fc89f4a0 | ||
|
|
0bfd0ad2e6 | ||
|
|
c79e785ae4 | ||
|
|
5543727ae0 | ||
|
|
9a7b48eb6a | ||
|
|
06a3936333 | ||
|
|
6ed1651eaf | ||
|
|
6b3687bfaf | ||
|
|
26092bc7d1 | ||
|
|
082c2bf870 | ||
|
|
6db2bdbab6 | ||
|
|
e6174b3595 | ||
|
|
583755570f | ||
|
|
b3406c5957 | ||
|
|
9fbf14da4d | ||
|
|
91a3c07e16 | ||
|
|
519a025d2c | ||
|
|
4fc31d89a9 | ||
|
|
a0a579b84d | ||
|
|
ae5e7ea2ab | ||
|
|
ccd78ede68 | ||
|
|
9113a0e040 | ||
|
|
45af05da0d | ||
|
|
a2313c364b | ||
|
|
c17f1cd15e | ||
|
|
50c1495eab | ||
|
|
010581248a | ||
|
|
03a255285e | ||
|
|
c79ef4efeb | ||
|
|
db35b0cc43 | ||
|
|
eb5b0faf02 | ||
|
|
f08d79ea82 | ||
|
|
d257a8c00c | ||
|
|
22960567fe | ||
|
|
fcd12db54e | ||
|
|
151f6be8ea | ||
|
|
46b971f244 | ||
|
|
34598bb140 | ||
|
|
9073b3f89b | ||
|
|
f625143fd6 | ||
|
|
e840ceaf3b | ||
|
|
4cb22af3da | ||
|
|
886a65f7be | ||
|
|
d79129c856 | ||
|
|
57f5567709 | ||
|
|
2bdb1df5dc | ||
|
|
1b3d7b6e2e | ||
|
|
5c27536155 | ||
|
|
d00af9f145 | ||
|
|
e7424ac8ee | ||
|
|
afb2638cb6 | ||
|
|
1527c983e5 | ||
|
|
d6d24a4a06 | ||
|
|
740eabdd3a | ||
|
|
7b3da5bcf5 | ||
|
|
900f9d18b0 | ||
|
|
e2e7cec932 | ||
|
|
37681a38cf | ||
|
|
bac06892be | ||
|
|
5970609e11 | ||
|
|
fdc9b8cb2c | ||
|
|
c90249c87c | ||
|
|
f7d8bf3b65 | ||
|
|
8f58774bcb | ||
|
|
70e2ee7214 | ||
|
|
41654e09d3 | ||
|
|
83aa10660c | ||
|
|
f5d9360793 | ||
|
|
2713363e99 | ||
|
|
96cd5e4a90 | ||
|
|
6bb769cbb4 | ||
|
|
fd5270990c | ||
|
|
a48bf517a0 | ||
|
|
fef50bca82 | ||
|
|
4070f50b5d | ||
|
|
904da50131 | ||
|
|
f248207dfe | ||
|
|
f68b982c82 | ||
|
|
28f2fa8ed7 | ||
|
|
bc8e120383 | ||
|
|
20e1a3d239 | ||
|
|
7874bfcee3 | ||
|
|
66ae6ff461 | ||
|
|
3aa8af4244 | ||
|
|
8d08257e47 | ||
|
|
68849f13be | ||
|
|
aefd0196d9 | ||
|
|
b72ddec877 | ||
|
|
9f3884beda | ||
|
|
e76a3db695 | ||
|
|
e72df69686 | ||
|
|
539e27457e | ||
|
|
a6f74860fb | ||
|
|
8fcd9cbfa5 | ||
|
|
3d4bfbe62c | ||
|
|
e1f2824025 | ||
|
|
ccfd7339be | ||
|
|
89b60e6c18 | ||
|
|
7729a0bb28 | ||
|
|
6f27ac208f | ||
|
|
2fc392f9a0 | ||
|
|
714cbdbe82 | ||
|
|
4c4c7b5df3 | ||
|
|
700946b066 | ||
|
|
593a4ee128 | ||
|
|
b48f708f91 | ||
|
|
25ae0ed3dd | ||
|
|
d75fb18b62 | ||
|
|
9d3e7a84f6 | ||
|
|
bf283549dd | ||
|
|
e8c9754f19 | ||
|
|
bd94a5e2a5 | ||
|
|
e4d376c61c | ||
|
|
1e825698c3 | ||
|
|
4eddc74341 | ||
|
|
41420c08ec | ||
|
|
cc2aab3b93 | ||
|
|
7d664f9227 | ||
|
|
b6cf544f24 | ||
|
|
7b2423fe3d | ||
|
|
13d11d79cf | ||
|
|
e98ac2f213 | ||
|
|
26ee5fb3a1 | ||
|
|
dadda98fcc | ||
|
|
490764f3c2 | ||
|
|
911eceb3b0 | ||
|
|
dbb4bccc87 | ||
|
|
d3a129063d | ||
|
|
95bba93255 | ||
|
|
3b1f1fec52 | ||
|
|
4c05e0c2ce | ||
|
|
f01a4a0781 | ||
|
|
ffc65146bc | ||
|
|
2295b415a3 | ||
|
|
e6543f10c2 | ||
|
|
eba5b4d946 | ||
|
|
ab55aada7b | ||
|
|
d97b263ccf | ||
|
|
2c03fd02c6 | ||
|
|
feca8bfe9a | ||
|
|
8d8b5be1c6 | ||
|
|
bc3e10b44d | ||
|
|
38934de406 | ||
|
|
b9f8f9589d | ||
|
|
9b0cdc640e | ||
|
|
d417f6630b | ||
|
|
f90f3cb047 | ||
|
|
c10277480a | ||
|
|
4c561cd628 | ||
|
|
b9611f93a4 | ||
|
|
10d6241c6a | ||
|
|
e8b6c98a96 | ||
|
|
cbba7b47f8 | ||
|
|
8b6747ed4b | ||
|
|
0b3b0df132 | ||
|
|
d5c1366e35 | ||
|
|
1e54142914 | ||
|
|
8dbfc7650b | ||
|
|
fd8791af9e | ||
|
|
e64f8d0b2b | ||
|
|
741ecdea53 | ||
|
|
4e1fea08e5 | ||
|
|
c27f30f84b | ||
|
|
3d16dd8137 | ||
|
|
d0fad7dda7 | ||
|
|
c8a223c072 | ||
|
|
79c51c5120 | ||
|
|
3785f9ee1e | ||
|
|
6a502612b8 | ||
|
|
dbaef834a7 | ||
|
|
cc7038f253 | ||
|
|
774c162b90 | ||
|
|
37ead0d34a | ||
|
|
5a6c0f94e4 | ||
|
|
eada8693cf | ||
|
|
cf4b3c3e37 | ||
|
|
e832d6bb2d | ||
|
|
8513625f3f | ||
|
|
b5ba13d257 | ||
|
|
a05870e053 | ||
|
|
68757ec6fd | ||
|
|
351ceac00e | ||
|
|
9e811db06f | ||
|
|
fbe1bf7f51 | ||
|
|
39d45c5894 | ||
|
|
6ddf62d2be | ||
|
|
b5f7c7b414 | ||
|
|
a0447cb849 | ||
|
|
9c45ea053c | ||
|
|
3deebd9d88 | ||
|
|
67f4f3e38f | ||
|
|
9d826a90da | ||
|
|
8c8a9fc98e | ||
|
|
4c45aff2ce | ||
|
|
68b9efb0d1 | ||
|
|
5f92d4208f | ||
|
|
6653feb6f4 | ||
|
|
ea50210887 | ||
|
|
65b8059862 | ||
|
|
ee18f3cb13 | ||
|
|
541115c721 | ||
|
|
287a0fd1dc | ||
|
|
cd1db20a31 | ||
|
|
81fdf2a16a | ||
|
|
fffbb4da5c | ||
|
|
46f9494bf3 | ||
|
|
e0aea2307d | ||
|
|
7a6fb849b1 | ||
|
|
12efafc381 | ||
|
|
b962215d1a | ||
|
|
8810979a64 | ||
|
|
052613a522 | ||
|
|
76d32ab80f | ||
|
|
dabd9f6814 | ||
|
|
a0c4ebca0f | ||
|
|
b74ff62ccd | ||
|
|
95c93c03d7 | ||
|
|
409d1a1c53 | ||
|
|
4dc038b277 | ||
|
|
d85117cc68 | ||
|
|
16da155f31 | ||
|
|
a87618c4e5 | ||
|
|
c8ccbaade9 | ||
|
|
ae4cf5bfb0 | ||
|
|
54e68952d2 | ||
|
|
1c1c933a21 | ||
|
|
09a1c7169e | ||
|
|
dd315361da | ||
|
|
e3a5ccc012 | ||
|
|
9fca915d72 | ||
|
|
e9e4df5042 | ||
|
|
831982faea | ||
|
|
d5bef0e6ce | ||
|
|
ee91a98641 | ||
|
|
ee38bdfe23 | ||
|
|
d86a13cf72 | ||
|
|
9ecf001945 | ||
|
|
a47cb5d0a9 | ||
|
|
2356a9b699 | ||
|
|
8ca8adf93c | ||
|
|
7940f573b5 | ||
|
|
b16dd92a48 | ||
|
|
3239e38e8f | ||
|
|
73806c4eae | ||
|
|
c5e9a4746a | ||
|
|
16eab7de38 | ||
|
|
2e003610e2 | ||
|
|
35d9198e52 | ||
|
|
f8964b4795 | ||
|
|
b5d35a5382 | ||
|
|
7f89ca1b8e | ||
|
|
818ebd3ca8 | ||
|
|
906c19a46a | ||
|
|
a8cbe4b97f | ||
|
|
5853826a4e | ||
|
|
a57d3dd979 | ||
|
|
8b83032af4 | ||
|
|
f5a36d4838 | ||
|
|
2d3721db16 | ||
|
|
47bf6677dd | ||
|
|
3013386eef | ||
|
|
927b14c080 | ||
|
|
9ac020cf01 | ||
|
|
5741936d09 | ||
|
|
d0b1e2dd71 | ||
|
|
eee94df771 | ||
|
|
636a691032 | ||
|
|
2fe6c84d09 | ||
|
|
1cc72bb106 | ||
|
|
1debfaf527 | ||
|
|
66838ebee4 | ||
|
|
00a3f1088d | ||
|
|
cd13b6914f | ||
|
|
cbf0961219 | ||
|
|
bc589e314a | ||
|
|
454b1ffe9d | ||
|
|
77080563c6 | ||
|
|
34d35d6837 | ||
|
|
b146cc7dfd | ||
|
|
defd1231aa | ||
|
|
ea27357b84 | ||
|
|
5f55c962ff | ||
|
|
3cdd3722de | ||
|
|
73a5cdc11d | ||
|
|
6ca324fff2 | ||
|
|
2c5b82acca | ||
|
|
673af7c7f6 | ||
|
|
96b92313b9 | ||
|
|
7dc59f727d | ||
|
|
6ea42da3bb | ||
|
|
c51f1409ae | ||
|
|
36a72157d3 | ||
|
|
15dcc2d8db | ||
|
|
e7aa819500 | ||
|
|
94a153a0a0 | ||
|
|
7efe125916 | ||
|
|
8732b1b50a | ||
|
|
931191ce35 | ||
|
|
cd4f77c3e1 | ||
|
|
5573297965 | ||
|
|
a89eb26c67 | ||
|
|
a0c641183c | ||
|
|
5a56f420ea | ||
|
|
6e88653fb5 | ||
|
|
6eaadb195f | ||
|
|
81621def08 | ||
|
|
beb53b3649 | ||
|
|
aced55b58b | ||
|
|
9cab13e4e4 | ||
|
|
d56c0f9556 | ||
|
|
dea05c51a4 | ||
|
|
e57a0b186b | ||
|
|
e63fa22c75 | ||
|
|
dd46da4005 | ||
|
|
7803c0baa6 | ||
|
|
524ddc510a | ||
|
|
4a8f0b506b | ||
|
|
6fea849020 | ||
|
|
c694209d6c | ||
|
|
ad427276eb | ||
|
|
aecf0e1d14 | ||
|
|
6a96ec99cd | ||
|
|
b11507b642 | ||
|
|
78037c944d | ||
|
|
8ba75b0ab6 | ||
|
|
e6ab6c8f94 | ||
|
|
8d965a7c16 | ||
|
|
e57f182dce | ||
|
|
2dc28c2506 | ||
|
|
b209ca9096 | ||
|
|
2f0634d750 | ||
|
|
3a3704b577 | ||
|
|
1b35591da7 | ||
|
|
7c751e3a2f | ||
|
|
2e3c104033 | ||
|
|
4180e160ba | ||
|
|
9ad14967e7 | ||
|
|
bc266a729a | ||
|
|
ecfe0d253f | ||
|
|
7df0f49b2b | ||
|
|
331585aae8 | ||
|
|
a13363f51a | ||
|
|
ed46a3e1a3 | ||
|
|
8a5d9c9a36 | ||
|
|
07caeb5a80 | ||
|
|
2732f69733 | ||
|
|
7718b2684e | ||
|
|
398b57be77 | ||
|
|
961584ba65 | ||
|
|
059b2f054b | ||
|
|
fe7e85ffa9 | ||
|
|
d95e52c6ce | ||
|
|
046fad5c93 | ||
|
|
34c508646a | ||
|
|
5e89e71c92 | ||
|
|
9bd2cbd5d6 | ||
|
|
0d715a9074 | ||
|
|
85178c09d5 | ||
|
|
1f0d375d2e | ||
|
|
1cf4f0a146 | ||
|
|
86eac9dc83 | ||
|
|
933f90e271 | ||
|
|
5329af7366 | ||
|
|
85143da674 | ||
|
|
9236b99190 | ||
|
|
86028587de | ||
|
|
612ebed2ac | ||
|
|
0bbf5a0e82 | ||
|
|
03a6c2c594 | ||
|
|
956ca1dd62 | ||
|
|
2dcca77c78 | ||
|
|
4b4b71b9d5 | ||
|
|
ce31430f52 | ||
|
|
cad88ad229 | ||
|
|
5baa32871a | ||
|
|
9175e54874 | ||
|
|
bb0adba20f | ||
|
|
4f912e3cb5 | ||
|
|
0a75a616a3 | ||
|
|
d792215480 | ||
|
|
b01de63b23 | ||
|
|
45029a4904 | ||
|
|
221584a2d7 | ||
|
|
510261bbba | ||
|
|
49852b2beb | ||
|
|
554267d9da | ||
|
|
944a71e216 | ||
|
|
33e5205d1c | ||
|
|
2064e9991b | ||
|
|
1fa1d70699 | ||
|
|
451f3d1e84 | ||
|
|
8cc1cea7a3 | ||
|
|
abe827a98f | ||
|
|
326f02f5da | ||
|
|
a27030ab95 | ||
|
|
3b30f054a3 | ||
|
|
2d1e789549 | ||
|
|
923b9a9326 | ||
|
|
fa0c144f1a | ||
|
|
84864f3261 | ||
|
|
2560483e56 | ||
|
|
201112fed4 | ||
|
|
84ce2b7481 | ||
|
|
58a4a4b3ca | ||
|
|
e0bb07eaa7 | ||
|
|
ebf8bf2899 | ||
|
|
a901b8c6c3 | ||
|
|
615f12d73c | ||
|
|
b7eb1d3385 | ||
|
|
9654a454c8 | ||
|
|
69869cfe36 | ||
|
|
4de7b4b0f8 | ||
|
|
a89ce1eb9f | ||
|
|
c0a6d9bf75 | ||
|
|
87bd317f64 | ||
|
|
97567e984e | ||
|
|
3885a18681 | ||
|
|
994d7af9ed | ||
|
|
eed5d0807b | ||
|
|
e022369e26 | ||
|
|
bd5f0d1bc6 | ||
|
|
3957aa6045 | ||
|
|
d60b76fe10 | ||
|
|
5f05bab56f | ||
|
|
959c24564e | ||
|
|
7ed5337aa2 | ||
|
|
67b4417b75 | ||
|
|
148efae86c | ||
|
|
e3b0db07e9 | ||
|
|
42f652e258 | ||
|
|
823c8f3930 | ||
|
|
26bbb9d944 | ||
|
|
6646819746 | ||
|
|
475633ecc6 | ||
|
|
6aacedb656 | ||
|
|
3d4f9a8034 | ||
|
|
3504874726 | ||
|
|
0a5e5a9f02 | ||
|
|
daa8ac9e44 | ||
|
|
ef8b02375a | ||
|
|
2802fbd9b4 | ||
|
|
14d42af6b5 | ||
|
|
24cf39ca95 | ||
|
|
0b989990fa | ||
|
|
c499e433ed | ||
|
|
0fc0b1b8ae | ||
|
|
fadee42a1f | ||
|
|
f4f2630c7a | ||
|
|
444f17e448 | ||
|
|
7ca17e7bac | ||
|
|
05ade24252 | ||
|
|
3b86ca97d3 | ||
|
|
168e29418a | ||
|
|
ae845a8b05 | ||
|
|
6281248304 | ||
|
|
42ef8ae29f | ||
|
|
0b99cb0278 | ||
|
|
9638eccf9b | ||
|
|
881ce04f4b | ||
|
|
bbfff3c704 | ||
|
|
3211117bdf | ||
|
|
3a9b547a2f | ||
|
|
14ccb90b10 | ||
|
|
5f6138d6bb | ||
|
|
bd1ecc950e | ||
|
|
1fc1199f31 | ||
|
|
c1cfd872a1 | ||
|
|
6a9c4e36e9 | ||
|
|
ba1f28c50a | ||
|
|
02efe88e2d | ||
|
|
88564af56b | ||
|
|
181f86405c | ||
|
|
7f59d8055e | ||
|
|
7882e6f4cf | ||
|
|
29888f268a | ||
|
|
47a220d24d | ||
|
|
2bac2857e0 | ||
|
|
749c861f86 | ||
|
|
86cbe86f60 | ||
|
|
b4f39d8797 | ||
|
|
5ba53f850f | ||
|
|
047f6fa925 | ||
|
|
c92f612574 | ||
|
|
f85a054ee0 | ||
|
|
ac09def160 | ||
|
|
90d01bb1a6 | ||
|
|
7445023c01 | ||
|
|
6d03992e1f | ||
|
|
c10c3259ab | ||
|
|
960a8e6807 | ||
|
|
319e2c213b | ||
|
|
6b56606073 | ||
|
|
fe17513bb9 | ||
|
|
17225e4642 | ||
|
|
80c73d6ae8 | ||
|
|
83ed28c686 | ||
|
|
ebcaf450c5 | ||
|
|
e0b56bc322 | ||
|
|
331385f216 | ||
|
|
29a45a6c0e | ||
|
|
caef39b97e | ||
|
|
a507c32f4c | ||
|
|
4e8c524dcb | ||
|
|
5ec1b7833a | ||
|
|
cbf7b2f9fd | ||
|
|
8c4fe43aeb | ||
|
|
08bfe66a26 | ||
|
|
d886af1678 | ||
|
|
16d57dc503 | ||
|
|
c25fb99249 | ||
|
|
f90c154186 | ||
|
|
886cba56f4 | ||
|
|
8cc56ca448 | ||
|
|
ca91d26f49 | ||
|
|
060cdf2297 | ||
|
|
f5f3ca8168 | ||
|
|
5d7e4bb030 | ||
|
|
2a88e371c0 | ||
|
|
65ec5ee755 | ||
|
|
5b2542b623 | ||
|
|
9df8e857db | ||
|
|
000665f7a0 | ||
|
|
10af73fd49 | ||
|
|
3260695785 | ||
|
|
e4938b593e | ||
|
|
03c5906a39 | ||
|
|
75a1b4a5b6 | ||
|
|
f950daad43 | ||
|
|
288e70bd39 | ||
|
|
d05da80b34 | ||
|
|
a1159774a9 | ||
|
|
8a0d695d0a | ||
|
|
9621413fbc | ||
|
|
e20c5de5fc | ||
|
|
37c952b56a | ||
|
|
0bea992779 | ||
|
|
dd5370074f | ||
|
|
974cbb6b1b | ||
|
|
53450a5b31 | ||
|
|
f5db7a8a24 | ||
|
|
2a24cbb64a | ||
|
|
f9640262a6 | ||
|
|
1423afbc66 | ||
|
|
c2cfaf805e | ||
|
|
e38e88ac7d | ||
|
|
1a87898577 | ||
|
|
0a231b2692 | ||
|
|
4d09a99857 | ||
|
|
c0911f5181 | ||
|
|
3231833e67 | ||
|
|
d1921dce96 | ||
|
|
7aea0483a6 | ||
|
|
aa60da9c57 | ||
|
|
2b3b2ccce6 | ||
|
|
3622ccff7a | ||
|
|
f3e38f6613 | ||
|
|
db98cd8b6b | ||
|
|
bb8d9feab6 | ||
|
|
0f0b4fa212 | ||
|
|
4074dd09f6 | ||
|
|
f95c324fd4 | ||
|
|
3c5aaf3378 | ||
|
|
d48b18075a | ||
|
|
06d737162a | ||
|
|
f8c444f580 | ||
|
|
6602c2427a | ||
|
|
6f2d64bddf | ||
|
|
cbd48de81c | ||
|
|
c8d7f88e37 | ||
|
|
b86fa21803 | ||
|
|
794e9412b6 | ||
|
|
fcf8c0c492 | ||
|
|
792d947ebd | ||
|
|
12fabba37f | ||
|
|
fe570f2c90 | ||
|
|
6a69395dbe | ||
|
|
b098bb888c | ||
|
|
32c014f94e | ||
|
|
0445ddeaed | ||
|
|
96c562dbb1 | ||
|
|
98f2d7a28b | ||
|
|
c46928d4df | ||
|
|
7293eee0c0 | ||
|
|
e57a3f4c40 | ||
|
|
1fc64018b2 | ||
|
|
20bf39be8d | ||
|
|
1ca64c4785 | ||
|
|
2006878f43 | ||
|
|
09a7c66868 | ||
|
|
c6fc5c4ec1 | ||
|
|
5f922ba16d | ||
|
|
3678f2ea8d | ||
|
|
0bba21154f | ||
|
|
ff0fe75384 | ||
|
|
ad2dad0613 | ||
|
|
926bff1854 | ||
|
|
f205e5913b | ||
|
|
762da4bb64 | ||
|
|
d4a56f6089 | ||
|
|
517ab00219 | ||
|
|
d5ca8cf7b3 | ||
|
|
47763f5ac5 | ||
|
|
8e8a0618e8 | ||
|
|
48e570c99e | ||
|
|
9463f861fb | ||
|
|
a5a4ad98c1 | ||
|
|
f671238401 | ||
|
|
e2caa26256 | ||
|
|
714647d3a5 | ||
|
|
544e453364 | ||
|
|
da98946873 | ||
|
|
7d5938aba9 | ||
|
|
4b9a0016c2 | ||
|
|
d5ff2471a4 | ||
|
|
aab1e77b1c | ||
|
|
5f8138b184 | ||
|
|
1bb5606bf9 | ||
|
|
a7d32ea752 | ||
|
|
19da3dd9d9 | ||
|
|
2d54df5988 | ||
|
|
7e6d21a52f | ||
|
|
24e4c776f4 | ||
|
|
97689e6c75 | ||
|
|
033c1308d2 | ||
|
|
c54f7d39fb | ||
|
|
f4bc66c57e | ||
|
|
16d4fc6c46 | ||
|
|
88cda37b2c | ||
|
|
c634b44828 | ||
|
|
f562657d58 | ||
|
|
65d3b61668 | ||
|
|
67d03c3b65 | ||
|
|
fde5695c46 | ||
|
|
a0b388c4d0 | ||
|
|
25bf6c0f01 | ||
|
|
ae83d1276a | ||
|
|
17cb534cf3 | ||
|
|
d8a0046e18 | ||
|
|
c5d4fefdf9 | ||
|
|
9a200bc2bf | ||
|
|
c16e42f431 | ||
|
|
197191748c | ||
|
|
0293e0aa50 | ||
|
|
9797af84a3 | ||
|
|
24bea9682d | ||
|
|
535ca32750 | ||
|
|
7c39172140 | ||
|
|
4cce769ffa | ||
|
|
28cb86987b | ||
|
|
e65e169381 | ||
|
|
5cc575d284 | ||
|
|
8990d0c0e7 | ||
|
|
8b42f0a659 | ||
|
|
23f61acfb9 | ||
|
|
ef715e2e7b | ||
|
|
a7ae86b734 | ||
|
|
51b507d1a3 | ||
|
|
070d89bad0 | ||
|
|
0402bbb127 | ||
|
|
48970afb2c | ||
|
|
b3c8cc8b33 | ||
|
|
4f7012d53c | ||
|
|
d3d3200b03 | ||
|
|
68223ed6a6 | ||
|
|
821c85b018 | ||
|
|
acd2eb85a1 | ||
|
|
16293d4158 | ||
|
|
8e5b4b8498 | ||
|
|
095f1eb568 | ||
|
|
5a802d62cb | ||
|
|
cc59637307 | ||
|
|
1d94a2e1c1 | ||
|
|
a50e6ab694 | ||
|
|
d0323c18bf | ||
|
|
63917ba8b5 | ||
|
|
590dc58fe5 | ||
|
|
1e6c7cf2c9 | ||
|
|
70bc78373f | ||
|
|
4372f0ce0f | ||
|
|
dddaaf3ed5 | ||
|
|
961918d444 | ||
|
|
9d4342ae41 | ||
|
|
da79e0fdfd | ||
|
|
c81d6f0285 | ||
|
|
784dc15373 | ||
|
|
b5b06fd13c | ||
|
|
08b881578b | ||
|
|
ecbde3a90a | ||
|
|
6cb083f0a5 | ||
|
|
a721932352 | ||
|
|
e8837d05de | ||
|
|
28f6adc751 | ||
|
|
8cd724eab2 | ||
|
|
0a5f5ce109 | ||
|
|
c23c1bcedc | ||
|
|
d2a116a6d0 | ||
|
|
c17fdf1f11 | ||
|
|
d563d34a7a | ||
|
|
94f8b3598e | ||
|
|
f81becc8ca | ||
|
|
98a3bcd171 | ||
|
|
82f432b06f | ||
|
|
778324be9a | ||
|
|
e549d762ef | ||
|
|
e8844b10d2 | ||
|
|
d097d9408d | ||
|
|
7b42fc260c | ||
|
|
fbbd741c87 | ||
|
|
f15b71f487 | ||
|
|
156d8f4ea9 | ||
|
|
22649cfef3 | ||
|
|
e001f46c98 | ||
|
|
c36428f74f | ||
|
|
acf9601faf | ||
|
|
b7e8c929b6 | ||
|
|
a5e57a2d6f | ||
|
|
bab302c8fc | ||
|
|
0d93a9daae | ||
|
|
114f6d53e4 | ||
|
|
9b4d3cd6e7 | ||
|
|
bfcd1cb2c7 | ||
|
|
a1e013f848 | ||
|
|
748131b90b | ||
|
|
1edb37c2e3 | ||
|
|
3347265837 | ||
|
|
b4eda9f9d1 | ||
|
|
a7dfaeba00 | ||
|
|
f62b5ad750 | ||
|
|
33374f0d37 | ||
|
|
cd2846ef5f | ||
|
|
69cef5f7b8 | ||
|
|
64cc13db1b | ||
|
|
6eaf96e0c1 | ||
|
|
5d44fbf9c0 | ||
|
|
3609c030c6 | ||
|
|
745be9e478 | ||
|
|
3f7afada87 | ||
|
|
8b5281130f | ||
|
|
ef6f0de633 | ||
|
|
8696d5c699 | ||
|
|
280a03a6ea | ||
|
|
f8dced141f | ||
|
|
16a242f468 | ||
|
|
77e539b225 | ||
|
|
ecf023854e | ||
|
|
46170b1c42 | ||
|
|
64ba989bb9 | ||
|
|
7f1e5a7a70 | ||
|
|
fbd969adf0 | ||
|
|
945d6f3f9f | ||
|
|
66a4efb439 | ||
|
|
f6b020b206 | ||
|
|
59a584422c | ||
|
|
6de4b4d601 | ||
|
|
429381e24f | ||
|
|
19e71c5f95 | ||
|
|
aa4476a2e1 | ||
|
|
852c266d6b | ||
|
|
9e8e8c5a2a | ||
|
|
9cb4c28840 | ||
|
|
e1d22955af | ||
|
|
697529ee4f | ||
|
|
426b1771d3 | ||
|
|
b0f6807ba7 | ||
|
|
f44e89d3a4 | ||
|
|
69adbf08b8 | ||
|
|
5a278991d8 | ||
|
|
7e6c109ab6 | ||
|
|
6d411861ae | ||
|
|
7e0853d55b | ||
|
|
3bfc4449df | ||
|
|
fedba5fad8 | ||
|
|
cc45c4b174 | ||
|
|
19c24e8180 | ||
|
|
9870492c0d | ||
|
|
aabd722c42 | ||
|
|
bbebbf53bd | ||
|
|
fb9225d68a | ||
|
|
79f8491754 | ||
|
|
52c0fbf2f8 | ||
|
|
cf601a09e0 | ||
|
|
c68699ff5c | ||
|
|
7ecce39fb8 | ||
|
|
6437e5d547 | ||
|
|
0512f6f233 | ||
|
|
11860f300a | ||
|
|
48106b93d4 | ||
|
|
a5d6f4a623 | ||
|
|
3580b3a94e | ||
|
|
1f6148ef79 | ||
|
|
d15c3d9be3 | ||
|
|
1678fc4f2b | ||
|
|
d88cd4e935 | ||
|
|
1e411b32a4 | ||
|
|
9b5759a32a | ||
|
|
ab374adc76 | ||
|
|
77301c09ad | ||
|
|
8b6b725273 | ||
|
|
c7104249d3 | ||
|
|
d741de75e8 | ||
|
|
3100d370cd | ||
|
|
3cfa218d68 | ||
|
|
3243bbb123 | ||
|
|
31f94f91f1 | ||
|
|
f60f0e1170 | ||
|
|
e39ca3e866 | ||
|
|
a96067a198 | ||
|
|
7197b4f94c | ||
|
|
dc77f978ca | ||
|
|
a1499e72fd | ||
|
|
cd55a17dc3 | ||
|
|
58cc050e97 | ||
|
|
c9a0a3748d | ||
|
|
7e6bc4fb61 | ||
|
|
d91a134a8d | ||
|
|
edc41b880c | ||
|
|
bab6451339 | ||
|
|
8da60a7b1e | ||
|
|
3e0abe0497 | ||
|
|
9f7e919fea | ||
|
|
bfd1a56104 | ||
|
|
8e8daab7b3 | ||
|
|
660f7d7a6f | ||
|
|
1fc2d23943 | ||
|
|
d9fd21d5bb | ||
|
|
6f2e581a4a | ||
|
|
f930e4865a | ||
|
|
2ae80f6161 | ||
|
|
aa84085c6b | ||
|
|
c32de8b4d0 | ||
|
|
da49d9c5bf | ||
|
|
0c91664b78 | ||
|
|
b713bf5c87 | ||
|
|
e7c59aaa68 | ||
|
|
73741cce73 | ||
|
|
a6c2fa183a | ||
|
|
5e0c09b338 | ||
|
|
f99cb5c765 | ||
|
|
615a80a132 | ||
|
|
d82dc61bfe | ||
|
|
4605992cdf | ||
|
|
2cb28da206 | ||
|
|
551958f713 | ||
|
|
2ca1ac53ba | ||
|
|
29f1cbbc5e | ||
|
|
f439393370 | ||
|
|
8a08fef833 | ||
|
|
7385fd6242 | ||
|
|
e46317f1f1 | ||
|
|
14eeffb01f | ||
|
|
424cf51c1a | ||
|
|
15d85997b8 | ||
|
|
40c1d825ad | ||
|
|
45f59f18c2 | ||
|
|
8469c700a7 | ||
|
|
65ef0428ec | ||
|
|
0ac8a9a123 | ||
|
|
0961d775e4 | ||
|
|
47035c6276 | ||
|
|
14df5aab3b | ||
|
|
0384bc8fa8 | ||
|
|
921ac86ca4 | ||
|
|
1e580a75f7 | ||
|
|
6940c0f76f | ||
|
|
a5a29d298b | ||
|
|
025718978b | ||
|
|
530428ec14 | ||
|
|
5f9b6a6699 | ||
|
|
a4ef905bbd | ||
|
|
d849593f19 | ||
|
|
29b07cdedf | ||
|
|
39ca504ebf | ||
|
|
b99d17ffc6 | ||
|
|
b92e1fe81b | ||
|
|
9e3d8e2bf6 | ||
|
|
283ad7bc9f | ||
|
|
4a116312ab | ||
|
|
ead9d2775e | ||
|
|
3e83bc7912 | ||
|
|
204ffc351b | ||
|
|
518bcf756e | ||
|
|
a01bf69776 | ||
|
|
e444e93230 | ||
|
|
a34c680676 | ||
|
|
ea077962ca | ||
|
|
47a5d6ad90 | ||
|
|
8cbc2bcd12 | ||
|
|
63eda23f1a | ||
|
|
482d6a17e6 | ||
|
|
d90427c50e | ||
|
|
0b6dfcb7b3 | ||
|
|
25675ce4d3 | ||
|
|
56372060d7 | ||
|
|
7286d21197 | ||
|
|
ffca56f7cd | ||
|
|
c28bae15cc | ||
|
|
a3cfc0a7ea | ||
|
|
f2f41f9643 | ||
|
|
b21910f2eb | ||
|
|
0dc0b3e74a | ||
|
|
0d93310338 | ||
|
|
1f302296c1 | ||
|
|
03ddc34aee | ||
|
|
5cf62055b9 | ||
|
|
3f9afe5aa1 | ||
|
|
062114fc80 | ||
|
|
9df2503db5 | ||
|
|
41e124ad4c | ||
|
|
9cc4b2b938 | ||
|
|
91e3025efb | ||
|
|
964fc79d06 | ||
|
|
6e3ffecc08 | ||
|
|
802a980e86 | ||
|
|
e7108e130d | ||
|
|
e1fd590894 | ||
|
|
1ed818f363 | ||
|
|
3cb7ca9c51 | ||
|
|
150ed7daf1 | ||
|
|
0419225c5f | ||
|
|
0d3064c406 | ||
|
|
98bcbdb7e8 | ||
|
|
a344339bae | ||
|
|
8f9ad1983a | ||
|
|
264df213a2 | ||
|
|
6bff7fa27f | ||
|
|
8c3075eabf | ||
|
|
1cfab411e2 | ||
|
|
25473fdb51 | ||
|
|
d6996c8eda | ||
|
|
6310b7c135 | ||
|
|
68c9c46d30 | ||
|
|
e0a97708ca | ||
|
|
da889b10bb | ||
|
|
3d80f5aa03 | ||
|
|
738e433124 | ||
|
|
a898f53e52 | ||
|
|
a9f60a8d78 | ||
|
|
abf33b8f4f | ||
|
|
975fca05ff | ||
|
|
f01a7c59d7 | ||
|
|
7006c52c79 | ||
|
|
d64c7a0a3d | ||
|
|
570a117d93 | ||
|
|
0f95277bd5 | ||
|
|
89857f6717 | ||
|
|
f519e15343 | ||
|
|
081740155b | ||
|
|
0937e09863 | ||
|
|
8a5522e305 | ||
|
|
db54cda00c | ||
|
|
b125e049ef | ||
|
|
a1a304d326 | ||
|
|
4b837b54eb | ||
|
|
8ed8c5298d | ||
|
|
3decb610f5 | ||
|
|
265536e105 | ||
|
|
7f3f3c4e73 | ||
|
|
ea4b7d03c5 | ||
|
|
24adfd4bb4 | ||
|
|
b0a453c6df | ||
|
|
cdec597f6e | ||
|
|
0f359cd77c | ||
|
|
dd75959826 | ||
|
|
dd6211f14f | ||
|
|
7e87b35dc6 | ||
|
|
1761a61a81 | ||
|
|
f03cf93ab5 | ||
|
|
bea1e974c4 | ||
|
|
83d6113263 | ||
|
|
2d4ffbedb7 | ||
|
|
7781ef4cc6 | ||
|
|
6c5337fd4f | ||
|
|
a9be41801d | ||
|
|
84e6a23863 | ||
|
|
a81d7ebebb | ||
|
|
2864512018 | ||
|
|
d9957c52d7 | ||
|
|
4662a29dc2 | ||
|
|
597754364f | ||
|
|
d51fbece41 | ||
|
|
cbd651efe3 | ||
|
|
7444211bc2 | ||
|
|
d411793868 | ||
|
|
b621a05832 | ||
|
|
1ad1e7e14c | ||
|
|
e32a316366 | ||
|
|
63c973fc3b | ||
|
|
de3e42baf7 | ||
|
|
f1d9b8dfb5 | ||
|
|
d5801c7e29 | ||
|
|
970ba867a1 | ||
|
|
475f0ccca2 | ||
|
|
4eecd0f4db | ||
|
|
1ed9b01f54 | ||
|
|
12073ee5eb | ||
|
|
ea7445cea0 | ||
|
|
e55f85480b | ||
|
|
6a05dc8eea | ||
|
|
a55c9f1fee | ||
|
|
8fc463836c | ||
|
|
4a469ef1a5 | ||
|
|
772c7ed2ef | ||
|
|
f2f20c0010 | ||
|
|
8b56891fc2 | ||
|
|
c0ab845069 | ||
|
|
ad92457c72 | ||
|
|
5d1c9bb4ab | ||
|
|
1b47867f9c | ||
|
|
c94515d0a2 | ||
|
|
92ff4b614e | ||
|
|
4a3ccac73c | ||
|
|
9cecbdf47a | ||
|
|
a73bc6b16a | ||
|
|
6d5ee1f1d5 | ||
|
|
0b77463f64 | ||
|
|
2b35b44291 | ||
|
|
68a12b2f56 | ||
|
|
60e84ae172 | ||
|
|
e1ff4dc222 | ||
|
|
846b2a46bc | ||
|
|
a02a4a3ee6 | ||
|
|
acf6e2c633 | ||
|
|
5511c6678c | ||
|
|
d13f610f16 | ||
|
|
989373b554 | ||
|
|
6e3cc80b00 | ||
|
|
0894835e6c | ||
|
|
a0430de4ae | ||
|
|
6a3dc106c6 | ||
|
|
b7d4277f6d | ||
|
|
1d42aed7eb | ||
|
|
444eb6041e | ||
|
|
9e36587f7a | ||
|
|
f528c351fa | ||
|
|
325cf98da2 | ||
|
|
7f7c82356b | ||
|
|
1b311f08a4 | ||
|
|
c1a7796843 | ||
|
|
2332b147e5 | ||
|
|
ac6d4d6c91 | ||
|
|
7a0a0b18ea | ||
|
|
6a9e81980e | ||
|
|
0ee645ce04 | ||
|
|
2cea2c70bc | ||
|
|
62546f1eae | ||
|
|
ece4742e9b | ||
|
|
c506da11c7 | ||
|
|
fa2e947a9c | ||
|
|
1a6a1ca3b5 | ||
|
|
7eaf2e266d | ||
|
|
89b416c9f0 | ||
|
|
c49d202183 | ||
|
|
3dbcb08c97 | ||
|
|
4e49eb5095 | ||
|
|
1ae9256a56 | ||
|
|
5cecffda00 | ||
|
|
1ac91bb4a4 | ||
|
|
428e933b49 | ||
|
|
52d09918f5 | ||
|
|
6ada9d6ace | ||
|
|
8d2e0548e9 | ||
|
|
50142b6a48 | ||
|
|
2356403889 | ||
|
|
ae7571fbd3 | ||
|
|
a39d62c45c | ||
|
|
4969c1d433 | ||
|
|
7035a5a52f | ||
|
|
baf5629ddd | ||
|
|
c5e11681f1 | ||
|
|
042e0ba70c | ||
|
|
5d3a4715f1 | ||
|
|
9cb375fcef | ||
|
|
a0b3171e34 | ||
|
|
7ea932359d | ||
|
|
99ac9e6395 | ||
|
|
6696f7e938 | ||
|
|
17cd636f1f | ||
|
|
f381549534 | ||
|
|
ad4e3cc645 | ||
|
|
18671806ad | ||
|
|
b04b09a247 | ||
|
|
50f259bea2 | ||
|
|
9e73fc9482 | ||
|
|
4cb7ec21e5 | ||
|
|
de6f3096ff | ||
|
|
e02455dc8c | ||
|
|
fdac6fb121 | ||
|
|
3f4ed02f40 | ||
|
|
86fd6cd917 | ||
|
|
1b7ca9f7cd | ||
|
|
ab6b780ef7 | ||
|
|
446ce53704 | ||
|
|
071ad9efee | ||
|
|
f257ef42fc | ||
|
|
13c4dfcc69 | ||
|
|
4bf246f7ec | ||
|
|
6e213b35e2 | ||
|
|
2fef19c76e | ||
|
|
52991e1047 | ||
|
|
64c5f477ef | ||
|
|
1bde7dcff0 | ||
|
|
e01e085907 | ||
|
|
66faa8639e | ||
|
|
e0d8345760 | ||
|
|
8ad5d09e01 | ||
|
|
30be394ace | ||
|
|
c8254b07cf | ||
|
|
610cd2c1fa | ||
|
|
abbf260df8 | ||
|
|
21b3756b6e | ||
|
|
d5be099df5 | ||
|
|
609799c490 | ||
|
|
ceb80b4533 | ||
|
|
0296c22687 | ||
|
|
6d765e3809 | ||
|
|
c91187fed5 | ||
|
|
34f2ed7338 | ||
|
|
4cf38c57b8 | ||
|
|
b524149b1d | ||
|
|
4b01334d1d | ||
|
|
770317852b | ||
|
|
1d58d6beef | ||
|
|
7ffa00b7c0 | ||
|
|
2719c82815 | ||
|
|
5568529086 | ||
|
|
cdc6770f86 | ||
|
|
f7f51e386c | ||
|
|
2c5254dc55 | ||
|
|
1a924fa403 | ||
|
|
49d2caf57e | ||
|
|
e3bf9a62b4 | ||
|
|
0507647b76 | ||
|
|
ceb0dea179 | ||
|
|
4e4e77d22e | ||
|
|
b80cccad6a | ||
|
|
1fa66525e2 | ||
|
|
6d9d26dcb7 | ||
|
|
7414b84ea5 | ||
|
|
ecbdb1b139 | ||
|
|
57987d0ea5 | ||
|
|
bae55c1eb8 | ||
|
|
994171baf7 | ||
|
|
8ec4ef3725 | ||
|
|
c2e9a494e2 | ||
|
|
0662dbb18b | ||
|
|
7595452a89 | ||
|
|
88e7113ae8 | ||
|
|
6b2c11910a | ||
|
|
606de9a448 | ||
|
|
0dc9ab91fa | ||
|
|
d7554f279f | ||
|
|
45475c7e42 | ||
|
|
cb1893db59 | ||
|
|
88867cc7a7 | ||
|
|
b2d3fc8d85 | ||
|
|
6204c541e2 | ||
|
|
4276646c91 | ||
|
|
893b40ed80 | ||
|
|
da827d51e0 | ||
|
|
bf06be0ea9 | ||
|
|
391e4260d9 | ||
|
|
8597073661 | ||
|
|
d5909f5a37 | ||
|
|
6dd45ff241 | ||
|
|
498ed5134a | ||
|
|
8843036584 | ||
|
|
a886ed5c0a | ||
|
|
2bee4d5f0e | ||
|
|
7f78df069b | ||
|
|
83fc547c8d | ||
|
|
a2747168c3 | ||
|
|
f504036cca | ||
|
|
948dfcab59 | ||
|
|
7ac3b1d564 | ||
|
|
8537b0a332 | ||
|
|
2d3d755fac | ||
|
|
95d0ede446 | ||
|
|
addeefdbb2 | ||
|
|
a8eccebeca | ||
|
|
d94a454cfe | ||
|
|
bd6f94663c | ||
|
|
55d2fa0d37 | ||
|
|
b6b46091f2 | ||
|
|
473eca965f | ||
|
|
25e8e1a1d6 | ||
|
|
1ff198b90c | ||
|
|
760d274d5d | ||
|
|
1f3b88c79f | ||
|
|
edc8b36d42 | ||
|
|
ba147191b9 | ||
|
|
4f8f122caa | ||
|
|
1881c46fa2 | ||
|
|
ea46720de8 | ||
|
|
cea60d0c37 | ||
|
|
4073b7ade5 | ||
|
|
6b0b33cec3 | ||
|
|
3e96c13157 | ||
|
|
8f168807d9 | ||
|
|
850703c75e | ||
|
|
17764b2c82 | ||
|
|
2a8038762e | ||
|
|
e41af3d574 | ||
|
|
5b7334f09d | ||
|
|
0c00458ac3 | ||
|
|
89357e7a47 | ||
|
|
6a84d8330c | ||
|
|
a6b7e3a9bd | ||
|
|
7ab3e5549e | ||
|
|
c2a28bc6fd | ||
|
|
0cc56f8b78 | ||
|
|
0a9e26a27e | ||
|
|
4dd931756f | ||
|
|
8a86bf2875 | ||
|
|
91210a8b1f | ||
|
|
90926725e7 | ||
|
|
11c1cbda16 | ||
|
|
c4b7b5e3ee | ||
|
|
e707ed9853 | ||
|
|
cbf080e19f | ||
|
|
d4264d1019 | ||
|
|
cd3b2d2732 | ||
|
|
519d359b05 | ||
|
|
d602d4878f | ||
|
|
b708b7b687 | ||
|
|
e9727e21b7 | ||
|
|
00b30d4f19 | ||
|
|
e25d526ac4 | ||
|
|
1ff073d78b | ||
|
|
04af8f7f3c | ||
|
|
94b6492a66 | ||
|
|
8f85326cf3 | ||
|
|
c43a183333 | ||
|
|
79a272a078 | ||
|
|
01034d206a | ||
|
|
7bda84f98f | ||
|
|
a0a064e985 | ||
|
|
638ac9f003 | ||
|
|
05456bfe74 | ||
|
|
e2bce6c48a | ||
|
|
071e62d099 | ||
|
|
9563cf3b83 | ||
|
|
b88b10d059 | ||
|
|
7b92cb55aa | ||
|
|
bb7156df5e | ||
|
|
c566639c32 | ||
|
|
a00a881259 | ||
|
|
c1e771b618 | ||
|
|
6995cf8ad6 | ||
|
|
64ac96651b | ||
|
|
8036e3be65 | ||
|
|
402696deec | ||
|
|
da43ce1ecc | ||
|
|
cff91ed11c | ||
|
|
0485f88b2d | ||
|
|
11647dc8ef | ||
|
|
7d78246a7f | ||
|
|
6b2fd62cb1 | ||
|
|
f52f122a6b | ||
|
|
d653744000 | ||
|
|
825fac1f6e | ||
|
|
cda210b8d5 | ||
|
|
b9a3e4330a | ||
|
|
bed4543a6f | ||
|
|
996877f1c2 | ||
|
|
762606a269 | ||
|
|
9d93812f30 | ||
|
|
7cc2246925 | ||
|
|
dc5ca69558 | ||
|
|
f78c40d0d1 | ||
|
|
f1c8e129ac | ||
|
|
d5190e5338 | ||
|
|
823bfecec7 | ||
|
|
b4330b7f47 | ||
|
|
b960545ea2 | ||
|
|
deb50dbe8c | ||
|
|
d7240a52cc | ||
|
|
a937a4aa60 | ||
|
|
4b5df3f800 | ||
|
|
280e32a5ba | ||
|
|
8e38017ae5 | ||
|
|
e74c64d0bd | ||
|
|
dad01ae9d5 | ||
|
|
f6d3929dc4 | ||
|
|
261f6a4435 | ||
|
|
117ad39043 | ||
|
|
9fc5e88186 | ||
|
|
d849ecd168 | ||
|
|
a57058dbda | ||
|
|
2c8edb698c | ||
|
|
e44486c092 | ||
|
|
b08fd9b4b1 | ||
|
|
fdc5f0c932 | ||
|
|
94de61a218 | ||
|
|
fed2eccdfb | ||
|
|
5a9c75975e | ||
|
|
c66577f79f | ||
|
|
2e13f6454e | ||
|
|
934963a9e9 | ||
|
|
4aff4316fe | ||
|
|
f513ab9fdb | ||
|
|
7bfe38b4ca | ||
|
|
05f5a07f05 | ||
|
|
44b3327763 | ||
|
|
ff00c83ea2 | ||
|
|
859f98610b | ||
|
|
2674a0d57a | ||
|
|
a6e8ebab39 | ||
|
|
aea63e7827 | ||
|
|
d647a44e96 | ||
|
|
72ab8741c0 | ||
|
|
8207ef07f3 | ||
|
|
f8c1813c77 | ||
|
|
6afd64a7fe | ||
|
|
9ecddd7eba | ||
|
|
e77f6ff560 | ||
|
|
deb13c3870 | ||
|
|
5dfae75f87 | ||
|
|
cb5a529fb4 | ||
|
|
a479b73cf2 | ||
|
|
da0a2a549d | ||
|
|
8b779c9204 | ||
|
|
99a34cde0d | ||
|
|
46d8a91f7c | ||
|
|
5c4209196d | ||
|
|
6749b7c378 | ||
|
|
77469928ab | ||
|
|
46be594356 | ||
|
|
0b74d6cd22 | ||
|
|
db6bb751d7 | ||
|
|
90b33370f3 | ||
|
|
6b8bffebdf | ||
|
|
0168f9fe6f | ||
|
|
7b577e9a39 | ||
|
|
b8f8c8aefd | ||
|
|
2aeee68d30 | ||
|
|
92898e535b | ||
|
|
9589d11758 | ||
|
|
0336677d9c | ||
|
|
2effa50a76 | ||
|
|
e174564666 | ||
|
|
01b923ee65 | ||
|
|
beca4c609f | ||
|
|
109e412ae7 | ||
|
|
9ee9211ae0 | ||
|
|
30c7b0cec2 | ||
|
|
5e96e2f168 | ||
|
|
143bcd65b6 | ||
|
|
f41b3f021d | ||
|
|
b3b0e1da1a | ||
|
|
d5adbd3b1f | ||
|
|
4646997262 | ||
|
|
b973e2541a | ||
|
|
026a8b53b3 | ||
|
|
9412071926 | ||
|
|
75c7b2849b | ||
|
|
c6ade9a4af | ||
|
|
ca71cf0a3d | ||
|
|
eb13dd1d5d | ||
|
|
c5575bca46 | ||
|
|
59a7ceb702 | ||
|
|
77fe8dc107 | ||
|
|
144e1af79f | ||
|
|
a1b8d0d536 | ||
|
|
4c4ce704ba | ||
|
|
a6d1631ae5 | ||
|
|
14d01c1c86 | ||
|
|
6f72282b22 |
414 changed files with 29958 additions and 61106 deletions
9
.babelrc.json
Normal file
9
.babelrc.json
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"presets": [
|
||||
"@babel/preset-env"
|
||||
],
|
||||
"plugins": [
|
||||
"module:babel-plugin-macros",
|
||||
"@babel/plugin-transform-optional-chaining"
|
||||
]
|
||||
}
|
||||
4
.browserslistrc
Normal file
4
.browserslistrc
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
last 2 Chrome versions
|
||||
last 2 Safari versions
|
||||
Firefox ESR
|
||||
not dead
|
||||
45
.cloudcmd.menu.js
Normal file
45
.cloudcmd.menu.js
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
'use strict';
|
||||
|
||||
module.exports = {
|
||||
'F2 - Rename file': async ({DOM}) => {
|
||||
await DOM.renameCurrent();
|
||||
},
|
||||
'L - Lint': async ({CloudCmd}) => {
|
||||
const {TerminalRun} = CloudCmd;
|
||||
await run(TerminalRun, 'npm run lint');
|
||||
},
|
||||
'F - Fix Lint': async ({CloudCmd}) => {
|
||||
const {TerminalRun} = CloudCmd;
|
||||
await run(TerminalRun, 'npm run fix:lint');
|
||||
},
|
||||
'T - Test': async ({CloudCmd}) => {
|
||||
const {TerminalRun} = CloudCmd;
|
||||
|
||||
await run(TerminalRun, 'npm run test');
|
||||
},
|
||||
'C - Coverage': async ({CloudCmd}) => {
|
||||
const {TerminalRun} = CloudCmd;
|
||||
|
||||
await run(TerminalRun, 'npm run coverage');
|
||||
},
|
||||
'D - Build Dev': async ({CloudCmd}) => {
|
||||
const {TerminalRun} = CloudCmd;
|
||||
|
||||
await run(TerminalRun, 'npm run build:client:dev');
|
||||
CloudCmd.refresh();
|
||||
},
|
||||
'P - Build Prod': async ({CloudCmd}) => {
|
||||
const {TerminalRun} = CloudCmd;
|
||||
|
||||
await run(TerminalRun, 'npm run build:client');
|
||||
CloudCmd.refresh();
|
||||
},
|
||||
};
|
||||
|
||||
async function run(TerminalRun, command) {
|
||||
await TerminalRun.show({
|
||||
command,
|
||||
closeMessage: 'Press any key to close Terminal',
|
||||
autoClose: false,
|
||||
});
|
||||
}
|
||||
23
.dockerignore
Normal file
23
.dockerignore
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
.*
|
||||
*.spec.js
|
||||
node_modules
|
||||
npm-debug.log*
|
||||
coverage
|
||||
test
|
||||
manifest.yml
|
||||
app.json
|
||||
bower.json
|
||||
yarn-error.log
|
||||
yarn.lock
|
||||
now.json
|
||||
|
||||
docker
|
||||
|
||||
webpack.config.js
|
||||
cssnano.config.js
|
||||
|
||||
bin/release.js
|
||||
|
||||
client
|
||||
server_
|
||||
|
||||
17
.editorconfig
Normal file
17
.editorconfig
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# This file is for unifying the coding style for different editors and IDEs
|
||||
# http://editorconfig.org
|
||||
|
||||
# top-most EditorConfig file
|
||||
root = true
|
||||
|
||||
# Unix-style newlines with a newline ending every file
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = false
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
||||
[*.hbs]
|
||||
insert_final_newline = false
|
||||
3
.github/FUNDING.yml
vendored
Normal file
3
.github/FUNDING.yml
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
github: coderaiser
|
||||
open_collective: cloudcmd
|
||||
ko_fi: coderaiser
|
||||
45
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
45
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
---
|
||||
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: ''
|
||||
labels: needs clarification
|
||||
assignees: coderaiser
|
||||
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behavior:
|
||||
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Screenshots**
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
**Desktop (please complete the following information):**
|
||||
|
||||
- **Version** (`cloudcmd -v`):
|
||||
- **Node Version** `node -v`:
|
||||
- **OS** (`uname -a` on Linux):
|
||||
- **Browser name/version**:
|
||||
- **Used Command Line Parameters**:
|
||||
- **Changed Config**:
|
||||
|
||||
```json
|
||||
{}
|
||||
```
|
||||
- [ ] 🎁 **I'm ready to donate on https://opencollective.com/cloudcmd**
|
||||
- [ ] 🎁 **I'm ready to donate on https://ko-fi.com/coderaiser**
|
||||
- [ ] 💪 **I'm willing to work on this issue**
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
||||
5
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
5
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: Stack Overflow
|
||||
url: https://stackoverflow.com/search?q=cloudcmd
|
||||
about: Please ask and answer questions here.
|
||||
21
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
21
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
---
|
||||
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
||||
24
.github/ISSUE_TEMPLATE/issue_template.md
vendored
Normal file
24
.github/ISSUE_TEMPLATE/issue_template.md
vendored
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
***
|
||||
|
||||
name: Tracking issue
|
||||
about: Create an issue with bug report or feature request.
|
||||
title: ""
|
||||
labels: needs triage
|
||||
assignees: coderaiser
|
||||
|
||||
***
|
||||
|
||||
- **Version** (`cloudcmd -v`):
|
||||
- **Node Version** `node -v`:
|
||||
- **OS** (`uname -a` on Linux):
|
||||
- **Browser name/version**:
|
||||
- **Used Command Line Parameters**:
|
||||
- **Changed Config**:
|
||||
|
||||
```json
|
||||
{}
|
||||
```
|
||||
|
||||
- [ ] 🎁 **I'm ready to donate on https://opencollective.com/cloudcmd**
|
||||
- [ ] 🎁 **I'm ready to donate on https://ko-fi.com/coderaiser**
|
||||
- [ ] 💪 **I'm willing to work on this issue**
|
||||
8
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
8
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
<!--
|
||||
Thank you for making pull request. Please fill in the template below. If unsure
|
||||
about something, just do as best as you're able.
|
||||
-->
|
||||
|
||||
- [ ] commit message named according to [Contributing Guide](https://github.com/coderaiser/cloudcmd/blob/master/CONTRIBUTING.md "Contributting Guide")
|
||||
- [ ] `npm run fix:lint` is OK
|
||||
- [ ] `npm test` is OK
|
||||
71
.github/workflows/docker.yml
vendored
Normal file
71
.github/workflows/docker.yml
vendored
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
name: Docker CI
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- "*"
|
||||
jobs:
|
||||
buildx:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
- uses: oven-sh/setup-bun@v2
|
||||
with:
|
||||
bun-version: latest
|
||||
- name: Use Node.js 22.x
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: 22.x
|
||||
- name: Install Redrun
|
||||
run: bun i redrun -g --no-save
|
||||
- name: NPM Install
|
||||
run: bun i --no-save
|
||||
- name: Lint
|
||||
run: redrun lint
|
||||
- name: Build
|
||||
id: build
|
||||
run: |
|
||||
redrun build
|
||||
echo "::set-output name=version::$(grep '"version":' package.json -m1 | cut -d\" -f4)"
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
- name: Login to DockerHub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_TOKEN }}
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Build and push base-image
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
file: docker/Dockerfile
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: |
|
||||
coderaiser/cloudcmd:latest
|
||||
coderaiser/cloudcmd:${{ steps.build.outputs.version }}
|
||||
ghcr.io/${{ github.repository }}:latest
|
||||
ghcr.io/${{ github.repository }}:${{ steps.build.outputs.version }}
|
||||
- name: Build and push alpine-image
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
file: docker/Dockerfile.alpine
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: |
|
||||
coderaiser/cloudcmd:latest-alpine
|
||||
coderaiser/cloudcmd:${{ steps.build.outputs.version }}-alpine
|
||||
ghcr.io/${{ github.repository }}:latest-alpine
|
||||
ghcr.io/${{ github.repository }}:${{ steps.build.outputs.version }}-alpine
|
||||
58
.github/workflows/nodejs.yml
vendored
Normal file
58
.github/workflows/nodejs.yml
vendored
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
name: Node CI
|
||||
on:
|
||||
- push
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
NAME: cloudcmd
|
||||
strategy:
|
||||
matrix:
|
||||
node-version:
|
||||
- 22.x
|
||||
- 24.x
|
||||
- 25.x
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: oven-sh/setup-bun@v2
|
||||
with:
|
||||
bun-version: latest
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
- name: Install Redrun
|
||||
run: bun i redrun -g --no-save
|
||||
- name: Install
|
||||
run: bun i --no-save
|
||||
- name: Lint
|
||||
run: redrun fix:lint
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/.cargo/bin/
|
||||
~/.cargo/registry/index/
|
||||
~/.cargo/registry/cache/
|
||||
~/.cargo/git/db/
|
||||
target/
|
||||
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
|
||||
- name: Typos Install
|
||||
run: cargo install typos-cli || echo 'already installed'
|
||||
- name: Typos
|
||||
run: typos --write-changes
|
||||
- name: Commit fixes
|
||||
uses: EndBug/add-and-commit@v9
|
||||
continue-on-error: true
|
||||
with:
|
||||
message: "chore: ${{ env.NAME }}: actions: lint ☘️"
|
||||
- name: Build
|
||||
run: redrun build
|
||||
- name: Test
|
||||
run: redrun test
|
||||
- name: Coverage
|
||||
run: redrun coverage coverage:report
|
||||
- name: Coveralls
|
||||
uses: coverallsapp/github-action@v2
|
||||
continue-on-error: true
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
31
.gitignore
vendored
31
.gitignore
vendored
|
|
@ -1,20 +1,19 @@
|
|||
#files, the will be ignored by git
|
||||
|
||||
#file with changes
|
||||
json/changes.json
|
||||
|
||||
#c9 files
|
||||
.c9revisions
|
||||
*tmp
|
||||
|
||||
#node modules folder
|
||||
package-lock.json
|
||||
yarn.lock
|
||||
yarn-error.log
|
||||
node_modules
|
||||
npm-debug.log*
|
||||
coverage
|
||||
|
||||
#temporary files folder
|
||||
tmp
|
||||
modules/execon
|
||||
modules/emitify
|
||||
|
||||
#log file
|
||||
log.txt
|
||||
.nyc_output
|
||||
|
||||
#cloudfoundry file
|
||||
manifest.yml
|
||||
*.swp
|
||||
.DS_Store
|
||||
|
||||
dist
|
||||
dist-dev
|
||||
|
||||
.idea
|
||||
|
|
|
|||
63
.madrun.mjs
Normal file
63
.madrun.mjs
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
import process from 'node:process';
|
||||
import {run, cutEnv} from 'madrun';
|
||||
|
||||
const testEnv = {
|
||||
SUPERTAPE_TIMEOUT: 7000,
|
||||
};
|
||||
|
||||
const is17 = /^v1[789]/.test(process.version);
|
||||
const is20 = process.version.startsWith('v2');
|
||||
|
||||
// fix for ERR_OSSL_EVP_UNSUPPORTED on node v17
|
||||
// flag '--openssl-legacy-provider' not supported
|
||||
// on earlier version of node.js
|
||||
//
|
||||
// https://stackoverflow.com/a/69746937/4536327
|
||||
const buildEnv = (is17 || is20) && {
|
||||
NODE_OPTIONS: '--openssl-legacy-provider',
|
||||
NODE_ENV: 'production',
|
||||
};
|
||||
|
||||
export default {
|
||||
'start': () => 'node bin/cloudcmd.mjs',
|
||||
'start:dev': async () => await run('start', null, {
|
||||
NODE_ENV: 'development',
|
||||
}),
|
||||
'build:start': () => run(['build:client', 'start']),
|
||||
'build:start:dev': () => run(['build:client:dev', 'start:dev']),
|
||||
'lint:all': () => run('lint:progress'),
|
||||
'lint': () => 'putout .',
|
||||
'lint:progress': () => run('lint', '-f progress'),
|
||||
'watch:lint': () => 'nodemon -w client -w server -w test -w common -w .webpack -x "putout -s"',
|
||||
'fresh:lint': () => run('lint', '--fresh'),
|
||||
'lint:fresh': () => run('lint', '--fresh'),
|
||||
'fix:lint': () => run('lint', '--fix'),
|
||||
'lint:stream': () => run('lint', '-f stream'),
|
||||
'test': () => [testEnv, `tape 'test/**/*.{js,mjs}' '{client,static,common,server}/**/*.spec.{js,mjs}' -f fail`],
|
||||
'test:client': () => `tape 'test/client/**/*.js'`,
|
||||
'test:server': () => `tape 'test/**/*.js' 'server/**/*.spec.js' 'common/**/*.spec.js'`,
|
||||
'wisdom': () => run(['lint:all', 'build', 'test']),
|
||||
'wisdom:type': () => 'bin/release.mjs',
|
||||
'coverage': async () => [testEnv, `c8 ${await cutEnv('test')}`],
|
||||
'coverage:report': () => 'c8 report --reporter=lcov',
|
||||
'report': () => 'c8 report --reporter=lcov',
|
||||
'6to5': () => [buildEnv, 'webpack --progress'],
|
||||
'6to5:client': () => run('6to5', '--mode production'),
|
||||
'6to5:client:dev': async () => await run('6to5', '--mode development', {
|
||||
NODE_ENV: 'development',
|
||||
}),
|
||||
'pre6to5:client': () => 'rimraf dist',
|
||||
'pre6to5:client:dev': () => 'rimraf dist-dev',
|
||||
'watch:client': () => run('6to5:client', '--watch'),
|
||||
'watch:client:dev': () => run('6to5:client:dev', '--watch'),
|
||||
'watch:server': () => 'nodemon bin/cloudcmd.js',
|
||||
'watch:test': async () => [testEnv, `nodemon -w client -w server -w test -w common -x ${await cutEnv('test')}`],
|
||||
'watch:test:client': async () => `nodemon -w client -w test/client -x ${await run('test:client')}`,
|
||||
'watch:test:server': async () => `nodemon -w client -w test/client -x ${await run('test:server')}`,
|
||||
'watch:coverage': async () => [testEnv, `nodemon -w server -w test -w common -x ${await cutEnv('coverage')}`],
|
||||
'build': async () => run('6to5:*'),
|
||||
'build:dev': async () => run('build:client:dev'),
|
||||
'build:client': () => run('6to5:client'),
|
||||
'build:client:dev': () => run('6to5:client:dev'),
|
||||
'heroku-postbuild': () => run('6to5:client'),
|
||||
};
|
||||
34
.npmignore
Normal file
34
.npmignore
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
.*
|
||||
*.spec.*
|
||||
*.config.*
|
||||
*.fixture.js*
|
||||
manifest.yml
|
||||
docker
|
||||
docker-compose.yml
|
||||
test
|
||||
fixture
|
||||
fixture-*
|
||||
coverage
|
||||
css
|
||||
html
|
||||
yarn-error.log
|
||||
yarn.lock
|
||||
now.json
|
||||
|
||||
app.json
|
||||
bower.json
|
||||
manifest.yml
|
||||
deno.json
|
||||
|
||||
bin/release.mjs
|
||||
|
||||
client
|
||||
img/logo/cloudcmd-hq.png
|
||||
|
||||
webpack.config.js
|
||||
|
||||
*.ai
|
||||
*.cdr
|
||||
*.eps
|
||||
|
||||
*.config.*
|
||||
1
.nvmrc
Normal file
1
.nvmrc
Normal file
|
|
@ -0,0 +1 @@
|
|||
v20.15.1
|
||||
15
.nycrc.json
Normal file
15
.nycrc.json
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"check-coverage": false,
|
||||
"all": false,
|
||||
"exclude": [
|
||||
"**/*.spec.js",
|
||||
"**/fixture",
|
||||
"**/*.*.js",
|
||||
"**/*.config.*",
|
||||
"**/test/**"
|
||||
],
|
||||
"branches": 100,
|
||||
"lines": 100,
|
||||
"functions": 100,
|
||||
"statements": 100
|
||||
}
|
||||
57
.putout.json
Normal file
57
.putout.json
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
{
|
||||
"plugins": ["cloudcmd"],
|
||||
"ignore": [
|
||||
"html",
|
||||
"fixture*",
|
||||
"app.json",
|
||||
"fontello.json",
|
||||
"*.md"
|
||||
],
|
||||
"rules": {
|
||||
"package-json/add-type": "off"
|
||||
},
|
||||
"match": {
|
||||
"base64": {
|
||||
"types/convert-typeof-to-is-type": "off"
|
||||
},
|
||||
"*.md": {
|
||||
"nodejs/convert-commonjs-to-esm": "on"
|
||||
},
|
||||
".webpack": {
|
||||
"webpack": "on"
|
||||
},
|
||||
"server": {
|
||||
"nodejs/remove-process-exit": "on"
|
||||
},
|
||||
"server/{server,exit}.js": {
|
||||
"nodejs/remove-process-exit": "off"
|
||||
},
|
||||
"server/{server,exit,terminal,distribute/log}.{js,mjs}": {
|
||||
"remove-console": "off"
|
||||
},
|
||||
"client/{client,cloudcmd,load-module}.{js,mjs}": {
|
||||
"remove-console": "off"
|
||||
},
|
||||
"client": {
|
||||
"nodejs": "off"
|
||||
},
|
||||
"client/sw": {
|
||||
"remove-console": "off"
|
||||
},
|
||||
"test/common/cloudfunc.js": {
|
||||
"remove-console": "off"
|
||||
},
|
||||
"storage.js": {
|
||||
"promises/remove-useless-async": "off"
|
||||
},
|
||||
"docker.yml": {
|
||||
"github/set-node-versions": "off"
|
||||
},
|
||||
"vim.js": {
|
||||
"merge-duplicate-functions": "off"
|
||||
},
|
||||
"common": {
|
||||
"nodejs/declare": "off"
|
||||
}
|
||||
}
|
||||
}
|
||||
17
.travis.yml
17
.travis.yml
|
|
@ -1,17 +0,0 @@
|
|||
language: node_js
|
||||
node_js:
|
||||
- 0.6
|
||||
- 0.8
|
||||
- 0.10
|
||||
- 0.11
|
||||
|
||||
matrix:
|
||||
allow_failures:
|
||||
- node_js: '0.11'
|
||||
|
||||
notifications:
|
||||
#webhooks:
|
||||
#http://requestb.in/12h5bl71
|
||||
email:
|
||||
on_success: never
|
||||
on_failure: change
|
||||
2
.typos.toml
Normal file
2
.typos.toml
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
[files]
|
||||
extend-exclude= ["ChangeLog", "*.js"]
|
||||
34
.webpack/css.mjs
Normal file
34
.webpack/css.mjs
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
import {env} from 'node:process';
|
||||
import OptimizeCssAssetsPlugin from 'optimize-css-assets-webpack-plugin';
|
||||
import MiniCssExtractPlugin from 'mini-css-extract-plugin';
|
||||
|
||||
const isDev = env.NODE_ENV === 'development';
|
||||
|
||||
const clean = (a) => a.filter(Boolean);
|
||||
|
||||
const plugins = clean([
|
||||
new MiniCssExtractPlugin({
|
||||
filename: '[name].css',
|
||||
}),
|
||||
!isDev && new OptimizeCssAssetsPlugin(),
|
||||
]);
|
||||
|
||||
const rules = [{
|
||||
test: /\.css$/i,
|
||||
use: [MiniCssExtractPlugin.loader, {
|
||||
loader: 'css-loader',
|
||||
options: {
|
||||
url: true,
|
||||
},
|
||||
}],
|
||||
}, {
|
||||
test: /\.(png|gif|svg|woff|woff2|eot|ttf)$/,
|
||||
type: 'asset/inline',
|
||||
}];
|
||||
|
||||
export default {
|
||||
plugins,
|
||||
module: {
|
||||
rules,
|
||||
},
|
||||
};
|
||||
36
.webpack/html.mjs
Normal file
36
.webpack/html.mjs
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
import {env} from 'node:process';
|
||||
import HtmlWebpackPlugin from 'html-webpack-plugin';
|
||||
|
||||
const isDev = env.NODE_ENV === 'development';
|
||||
|
||||
export const plugins = [
|
||||
new HtmlWebpackPlugin({
|
||||
inject: false,
|
||||
template: 'html/index.html',
|
||||
minify: !isDev && getMinifyHtmlOptions(),
|
||||
}),
|
||||
];
|
||||
|
||||
function getMinifyHtmlOptions() {
|
||||
return {
|
||||
removeComments: true,
|
||||
removeCommentsFromCDATA: true,
|
||||
removeCDATASectionsFromCDATA: true,
|
||||
collapseWhitespace: true,
|
||||
collapseBooleanAttributes: true,
|
||||
removeAttributeQuotes: true,
|
||||
removeRedundantAttributes: true,
|
||||
useShortDoctype: true,
|
||||
removeEmptyAttributes: true,
|
||||
/* оставляем, поскольку у нас
|
||||
* в элемент fm генерируеться
|
||||
* таблица файлов
|
||||
*/
|
||||
removeEmptyElements: false,
|
||||
removeOptionalTags: true,
|
||||
removeScriptTypeAttributes: true,
|
||||
removeStyleLinkTypeAttributes: true,
|
||||
|
||||
minifyJS: true,
|
||||
};
|
||||
}
|
||||
160
.webpack/js.mjs
Normal file
160
.webpack/js.mjs
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
import {resolve, sep} from 'node:path';
|
||||
import {env} from 'node:process';
|
||||
import webpack from 'webpack';
|
||||
import WebpackBar from 'webpackbar';
|
||||
|
||||
const {
|
||||
EnvironmentPlugin,
|
||||
NormalModuleReplacementPlugin,
|
||||
} = webpack;
|
||||
|
||||
const modules = './modules';
|
||||
const dirModules = './client/modules';
|
||||
const dirCss = './css';
|
||||
const dirThemes = `${dirCss}/themes`;
|
||||
const dirColumns = `${dirCss}/columns`;
|
||||
const dir = './client';
|
||||
const {NODE_ENV} = env;
|
||||
const isDev = NODE_ENV === 'development';
|
||||
|
||||
const rootDir = new URL('..', import.meta.url).pathname;
|
||||
const dist = resolve(rootDir, 'dist');
|
||||
const distDev = resolve(rootDir, 'dist-dev');
|
||||
const devtool = isDev ? 'eval' : 'source-map';
|
||||
|
||||
const notEmpty = (a) => a;
|
||||
const clean = (array) => array.filter(notEmpty);
|
||||
|
||||
const noParse = (a) => a.endsWith('.spec.js');
|
||||
const options = {
|
||||
babelrc: true,
|
||||
};
|
||||
|
||||
const rules = clean([
|
||||
!isDev && {
|
||||
test: /\.js$/,
|
||||
exclude: /node_modules/,
|
||||
loader: 'babel-loader',
|
||||
},
|
||||
isDev && {
|
||||
test: /\.js$/,
|
||||
exclude: /node_modules/,
|
||||
loader: 'babel-loader',
|
||||
options,
|
||||
},
|
||||
]);
|
||||
|
||||
const plugins = [
|
||||
new NormalModuleReplacementPlugin(/^node:/, (resource) => {
|
||||
resource.request = resource.request.replace(/^node:/, '');
|
||||
}),
|
||||
new NormalModuleReplacementPlugin(/^putout$/, '@putout/bundle'),
|
||||
new EnvironmentPlugin({
|
||||
NODE_ENV,
|
||||
}),
|
||||
new WebpackBar(),
|
||||
];
|
||||
|
||||
const splitChunks = {
|
||||
chunks: 'all',
|
||||
cacheGroups: {
|
||||
abcCommon: {
|
||||
name: 'cloudcmd.common',
|
||||
chunks: (chunk) => {
|
||||
const lazyChunks = [
|
||||
'sw',
|
||||
'nojs',
|
||||
'view',
|
||||
'edit',
|
||||
'terminal',
|
||||
'config',
|
||||
'user-menu',
|
||||
'help',
|
||||
'themes/dark',
|
||||
'themes/light',
|
||||
'columns/name-size',
|
||||
'columns/name-size-date',
|
||||
];
|
||||
|
||||
return !lazyChunks.includes(chunk.name);
|
||||
},
|
||||
minChunks: 1,
|
||||
enforce: true,
|
||||
priority: -1,
|
||||
reuseExistingChunk: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default {
|
||||
resolve: {
|
||||
symlinks: false,
|
||||
alias: {
|
||||
'node:process': 'process',
|
||||
'node:path': 'path',
|
||||
},
|
||||
fallback: {
|
||||
path: import.meta.resolve('path-browserify'),
|
||||
process: import.meta.resolve('process/browser'),
|
||||
},
|
||||
},
|
||||
devtool,
|
||||
optimization: {
|
||||
splitChunks,
|
||||
},
|
||||
entry: {
|
||||
'themes/dark': `${dirThemes}/dark.css`,
|
||||
'themes/light': `${dirThemes}/light.css`,
|
||||
'columns/name-size': `${dirColumns}/name-size.css`,
|
||||
'columns/name-size-date': `${dirColumns}/name-size-date.css`,
|
||||
'nojs': `${dirCss}/nojs.css`,
|
||||
'help': `${dirCss}/help.css`,
|
||||
'view': `${dirCss}/view.css`,
|
||||
'config': `${dirCss}/config.css`,
|
||||
'terminal': `${dirCss}/terminal.css`,
|
||||
'user-menu': `${dirCss}/user-menu.css`,
|
||||
'sw': `${dir}/sw/sw.js`,
|
||||
'cloudcmd': `${dir}/cloudcmd.mjs`,
|
||||
[`${modules}/edit`]: `${dirModules}/edit.js`,
|
||||
[`${modules}/edit-file`]: `${dirModules}/edit-file.js`,
|
||||
[`${modules}/edit-file-vim`]: `${dirModules}/edit-file-vim.js`,
|
||||
[`${modules}/edit-names`]: `${dirModules}/edit-names.js`,
|
||||
[`${modules}/edit-names-vim`]: `${dirModules}/edit-names-vim.js`,
|
||||
[`${modules}/menu`]: `${dirModules}/menu/index.js`,
|
||||
[`${modules}/view`]: `${dirModules}/view/index.js`,
|
||||
[`${modules}/help`]: `${dirModules}/help.js`,
|
||||
[`${modules}/markdown`]: `${dirModules}/markdown.js`,
|
||||
[`${modules}/config`]: `${dirModules}/config/index.js`,
|
||||
[`${modules}/contact`]: `${dirModules}/contact.js`,
|
||||
[`${modules}/upload`]: `${dirModules}/upload.js`,
|
||||
[`${modules}/operation`]: `${dirModules}/operation/index.mjs`,
|
||||
[`${modules}/konsole`]: `${dirModules}/konsole.js`,
|
||||
[`${modules}/terminal`]: `${dirModules}/terminal.js`,
|
||||
[`${modules}/terminal-run`]: `${dirModules}/terminal-run.js`,
|
||||
[`${modules}/cloud`]: `${dirModules}/cloud.js`,
|
||||
[`${modules}/user-menu`]: `${dirModules}/user-menu/index.js`,
|
||||
[`${modules}/polyfill`]: `${dirModules}/polyfill.js`,
|
||||
[`${modules}/command-line`]: `${dirModules}/command-line.js`,
|
||||
},
|
||||
output: {
|
||||
filename: '[name].js',
|
||||
path: isDev ? distDev : dist,
|
||||
pathinfo: isDev,
|
||||
devtoolModuleFilenameTemplate,
|
||||
publicPath: '/dist/',
|
||||
},
|
||||
module: {
|
||||
rules,
|
||||
noParse,
|
||||
},
|
||||
plugins,
|
||||
performance: {
|
||||
maxEntrypointSize: 600_000,
|
||||
maxAssetSize: 600_000,
|
||||
},
|
||||
};
|
||||
|
||||
function devtoolModuleFilenameTemplate(info) {
|
||||
const resource = info.absoluteResourcePath.replace(rootDir + sep, '');
|
||||
return `file://cloudcmd/${resource}`;
|
||||
}
|
||||
72
.yaspellerrc
Normal file
72
.yaspellerrc
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
{
|
||||
"ignoreDigits": true,
|
||||
"excludeFiles": [
|
||||
".git",
|
||||
"modules",
|
||||
"lib",
|
||||
"node_modules"
|
||||
],
|
||||
"fileExtensions": [
|
||||
".md"
|
||||
],
|
||||
"dictionary":[
|
||||
"CloudCmd",
|
||||
"Dev",
|
||||
"Dropbox",
|
||||
"Deepword",
|
||||
"Dword",
|
||||
"FilePicker",
|
||||
"GDrive",
|
||||
"Github",
|
||||
"Heroku",
|
||||
"Iptables",
|
||||
"JitSu",
|
||||
"Node",
|
||||
"IO",
|
||||
"Olena",
|
||||
"TarZak",
|
||||
"Termux",
|
||||
"Zalitok",
|
||||
"WebSocket",
|
||||
"auth",
|
||||
"autostart",
|
||||
"binded",
|
||||
"cd",
|
||||
"cloudcmd",
|
||||
"coderaiser",
|
||||
"com",
|
||||
"deepword",
|
||||
"dev",
|
||||
"destructuring",
|
||||
"dropbox",
|
||||
"dword",
|
||||
"edward",
|
||||
"favicon",
|
||||
"github",
|
||||
"gz",
|
||||
"io",
|
||||
"js",
|
||||
"linux",
|
||||
"maintainers",
|
||||
"markdown",
|
||||
"microservice",
|
||||
"minification",
|
||||
"mouseup",
|
||||
"named",
|
||||
"nginx",
|
||||
"npm",
|
||||
"or io",
|
||||
"patreon",
|
||||
"rc",
|
||||
"refactor",
|
||||
"sexualized",
|
||||
"sslPort",
|
||||
"unselect",
|
||||
"util",
|
||||
"v0",
|
||||
"v1",
|
||||
"v2",
|
||||
"yml",
|
||||
"systemd"
|
||||
]
|
||||
}
|
||||
46
CODE_OF_CONDUCT.md
Normal file
46
CODE_OF_CONDUCT.md
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
# Contributor Covenant Code of Conduct
|
||||
|
||||
## Our Pledge
|
||||
|
||||
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
|
||||
|
||||
## Our Standards
|
||||
|
||||
Examples of behavior that contributes to creating a positive environment include:
|
||||
|
||||
- Using welcoming and inclusive language
|
||||
- Being respectful of differing viewpoints and experiences
|
||||
- Gracefully accepting constructive criticism
|
||||
- Focusing on what is best for the community
|
||||
- Showing empathy towards other community members
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
- The use of sexualized language or imagery and unwelcome sexual attention or advances
|
||||
- Trolling, insulting/derogatory comments, and personal or political attacks
|
||||
- Public or private harassment
|
||||
- Publishing others' private information, such as a physical or electronic address, without explicit permission
|
||||
- Other conduct which could reasonably be considered inappropriate in a professional setting
|
||||
|
||||
## Our Responsibilities
|
||||
|
||||
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
|
||||
|
||||
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
|
||||
|
||||
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
|
||||
|
||||
[homepage]: http://contributor-covenant.org
|
||||
[version]: http://contributor-covenant.org/version/1/4/
|
||||
|
|
@ -1,47 +1,30 @@
|
|||
Brunch
|
||||
---------------
|
||||
If you would like to contribute - send pull request to dev branch.
|
||||
Getting dev version of **Cloud Commander**:
|
||||
## Commit
|
||||
|
||||
git clone git://github.com/coderaiser/cloudcmd.git
|
||||
git checkout dev
|
||||
|
||||
or by [link](https://github.com/coderaiser/cloudcmd/tree/dev "Dev version").
|
||||
|
||||
It is possible thet dev version Cloud Commander will needed dev version of Minify,
|
||||
so to get it you should type a couple more commands:
|
||||
|
||||
cd node_modules
|
||||
rm -rf minify
|
||||
git clone git://github.com/coderaiser/minify
|
||||
cd minify
|
||||
git checkout dev
|
||||
|
||||
Commit
|
||||
---------------
|
||||
Format of the commit message: **type(scope) subject**
|
||||
|
||||
**Type**:
|
||||
- feature
|
||||
- fix (bug fix)
|
||||
- docs (documentation)
|
||||
- style (formatting, missing semi colons, …)
|
||||
- refactor
|
||||
- test (when adding missing tests)
|
||||
- chore (maintain)
|
||||
|
||||
- feature: scope: subject
|
||||
- fix: scope: subject
|
||||
- docs: scope: subject
|
||||
- refactor: scope: subject
|
||||
- test: scope: subject
|
||||
- chore: scope: subject
|
||||
|
||||
**Scope**:
|
||||
Scope could be anything specifying place of the commit change.
|
||||
For example util, console, view, edit, style etc...
|
||||
|
||||
**Subject text**:
|
||||
|
||||
- use imperative, present tense: “change” not “changed” nor “changes”
|
||||
- don't capitalize first letter
|
||||
- no dot (.) at the end
|
||||
**Message body**:
|
||||
**Message body**:
|
||||
- just as in <subject> use imperative, present tense: “change” not “changed” nor “changes”
|
||||
- includes motivation for the change and contrasts with previous behavior
|
||||
|
||||
**Examples**:
|
||||
- [fix(style) .name{width}: 37% -> 35%](https://github.com/coderaiser/cloudcmd/commit/94b0642e3990c17b3a0ee3efeb75f343e1e7c050)
|
||||
- [fix(console) dispatch: focus -> mouseup](https://github.com/coderaiser/cloudcmd/commit/f41ec5058d1411e86a881f8e8077e0572e0409ec)
|
||||
|
||||
- [fix: style: .name{width}: 37% -> 35%](https://github.com/coderaiser/cloudcmd/commit/94b0642e3990c17b3a0ee3efeb75f343e1e7c050)
|
||||
- [fix: console: dispatch: focus -> mouseup](https://github.com/coderaiser/cloudcmd/commit/f41ec5058d1411e86a881f8e8077e0572e0409ec)
|
||||
|
|
|
|||
228
ChangeLog.rus.md
228
ChangeLog.rus.md
|
|
@ -1,228 +0,0 @@
|
|||
2012.07.01, v0.3.0
|
||||
===============
|
||||
Уже прошла середина лета и, благодаря легкому похолоданию, мы, кажется, начали больше ценить эту волшебную пору года. Через месяц детишки пойдут в школу, в город нахлынут толпы жаждущих новых знаний студентов, и город плавно войдет в привычный ритм.
|
||||
С момента прошлого релиза прошло уже больше трёх месяцев, а это значит пора выкатывать новый релиз. В нём будет очень много нового и интересного. У командира наконецто появилась новая иконка, терминал и редактор были полностью заменены и привязаны к вьеру. Код значительно упрощен и оптимизирован. Далее подробнее.
|
||||
|
||||
**Добавлена внешняя возможность:**
|
||||
- Назначено f3 - просмотр.
|
||||
- FilePicker получает ключ из modules.json.
|
||||
- Добавлена возможность показывать помощь по F1.
|
||||
- Jquery-terminal заменён на JQ-Console.
|
||||
- Добавлена лицензия.
|
||||
- Добавлено соглашение по именованию коммитов.
|
||||
- Добавлен favicon.
|
||||
- CodeMirror заменён на Ace.
|
||||
- Обновление теперь возможно, при запуске с любого каталога.
|
||||
- Добавлен исполняемый файл для npm -g.
|
||||
- Файл сохраняется только если он был изменён в Editor.
|
||||
- Для определения разделов на Windows, утилита diskpart заменена на wmic.
|
||||
- Добавлена кнопка "~ - console" для вызова Консоли.
|
||||
- Добавлена кнопка "f9 - menu" для вызова Меню.
|
||||
|
||||
**Исправленные ошибки:**
|
||||
- Функция загрузки в Filepicker.
|
||||
- this.promptNewFile -> Cmd.promptNewFile.
|
||||
- Стили: .name{width}: 37% -> 35%.
|
||||
- socket: log level: debug -> info.
|
||||
- help: удален стиль "pre".
|
||||
- Стили: .mode width: 25% -> 23%.
|
||||
- DOM: убрана возможность принимать массив в jsload.
|
||||
- Стили: .cmd-button: "outline:0".
|
||||
- Сохранение и создание нового файла.
|
||||
|
||||
**Обновлены:**
|
||||
- socket.io до v0.9.16.
|
||||
- jquery до v2.0.3.
|
||||
- minify до v0.2.1.
|
||||
|
||||
**Внутренние изминения:**
|
||||
- Изменена jquery cdn в пользу той, что поддерживает https (jquery.com -> google cdn).
|
||||
- Добавлен заголовок Access-Control-Allow-Origin для под возможности ajax запросов с других адресов.
|
||||
- Добавлены функции в DOM: createEvent(createKeyEvent, createClickEvent, createDblClickEvent), dispatch(dispatchKeyEvent, dispatchClickEvent, dispatchDblClickEvent).
|
||||
- Переименован обьект CloudCommander -> CloudCmd.
|
||||
- Функции загрузки перемещены в обьект Loader модуля DOM.
|
||||
- Добавлен скрипт addtables.sh, добавляющий правила в фаервол.
|
||||
- Исправлены повторяющиеся правила, связанные с фоном, в css.
|
||||
- Переименована функция DOM.addListener - DOM.Events.add.
|
||||
- Добавлена возможность повесить несколько обработчиков через Events.add.
|
||||
- jqeuryLoader и socketLoader перемещены в обьект CMD в модуле DOM.
|
||||
- Исправлена ошибка с удалением файла в Menu.
|
||||
- Удалена функция _editFileName из Client.
|
||||
- Удалена функция linuxWatch из Main.
|
||||
- Добавлен tryCatch в fs.watch в cloudcmd.js.
|
||||
- Переименовано KeyBinding в Key.
|
||||
- Переименовано set - setBinded, unSet -> unsetBinded, get -> isBinded.
|
||||
- Следующие функции теперь приватные: ajaxload, changeLinks, createFileTable, getJSONfromFileTable.
|
||||
- Данные обйъекта CloudCmd.KEY перемещены в прототип CloudCmd.Key.
|
||||
- Упрощены id плагинов.
|
||||
- Переписаны модули _codemirror и View с прототипами.
|
||||
- Добавлен метод hide в модуль View.
|
||||
- Удалено свойство init из модулей View и Edit.
|
||||
- Добавлена возможность передавать колбек во View: show(pData) -> show(pData, pCallBack).
|
||||
- Добавлен модуль Help.
|
||||
- Добавлена возможность устанавливать атрибуты в Loader.anyload.
|
||||
- Добавлен обработчик disconect в Socket.
|
||||
- Добавлена минификация и gzip в Socket.
|
||||
- Если id уже используется происходит повторное соединение в Socket.
|
||||
- Util.log теперь может вызываться с любым количеством параметров.
|
||||
- Добавлена функция logArray в Util.
|
||||
- Добавлена возможность смены каталога по cd в Socket.
|
||||
- Добавлена возможность передавать функции Events.add массив.
|
||||
- Добавлено событие unload.
|
||||
- Добавлена в экспорт функция checkCallBackParams.
|
||||
- Функция dispatch принимает на вход event или его название.
|
||||
- Добавлены media-query для .cmd-button.
|
||||
|
||||
2012.04.22, v0.2.0
|
||||
===============
|
||||
Весна в разгаре, на деревьях появляются почки, наконец-то начинает теплеть.
|
||||
А это значит, что пришло время выпускать на свободу новую версию Командира.
|
||||
|
||||
Много интересных вещей произошло и изменилось со времени прошлого релиза.
|
||||
Сейчас мы рассмотрим поближе, что же именно изменилось. Итак начнём.
|
||||
|
||||
**Добавленна внешняя возможность:**
|
||||
- Всплывающее сообщение об ошибках
|
||||
- Создание папки.
|
||||
- FilePicker.
|
||||
- загружать файлы в облако и скачивать их в файловую систему.
|
||||
- SSL.
|
||||
- Перемещения файлов.
|
||||
- Перехода на http, если https-сервер запустить не удалось.
|
||||
- Если создаётся директория индикатор загрузки будет сверху.
|
||||
- Обновления размера файла после изминения оного в редакторе.
|
||||
- Копирования файлов.
|
||||
- Выделения файлов клавишей Insert.
|
||||
- Получения размера текущей папки при нажатии клавиши Space.
|
||||
- Выделение всех файлов по Ctrl + A.
|
||||
- Удаления файла по F8.
|
||||
- Удаления нескольких файлов.
|
||||
|
||||
**Исправленные ошибки:**
|
||||
- Несколько обработчиков клика по нажатию клавиш F3 и F4.
|
||||
- Множественный вызов Sockets.
|
||||
- Запись json в localStorage: всегда обновлялось содержимое корневой директории.
|
||||
- В функциях Util.time и Util.timeEnd.
|
||||
- Генереация href файла, который переименовывается.
|
||||
- Выделение коревой директории клавишей Space
|
||||
- Обработка выделенной корневой директории.
|
||||
- Создание нового файла.
|
||||
- Стиль выделения в Опере.
|
||||
- Заголовок выдачи REST-фукнции fs метода GET.
|
||||
- Отправка данных в ответ на запрос отличный от ?json в пути /url.
|
||||
- Возвращение в папку, из которой был удален файл.
|
||||
|
||||
**Обновлены:**
|
||||
- jquery до версии v2.0.0.
|
||||
- dropbox до версии v0.9.2.
|
||||
- socket.io до версии v0.9.14.
|
||||
|
||||
**Внутренние изминения:**
|
||||
- Удален массив Listeners из модуля DOM.
|
||||
- Переделан и оптимизирована функция getShortSize в CloudFunc.
|
||||
- Контроль генерации заголовка кеша перенесен в модуль Main.
|
||||
- Установка текущего файла перенесена в Client из CloudFunc.
|
||||
- Изменён способ построения таблицы файлов. Теперь используются шаблоны.
|
||||
- Загрузка SSL-сертификатов теперь асинхронная.
|
||||
- Модуль DropBox перенесён в packege.json из папки Storage.
|
||||
- Удаления выделеного файла из DOM.
|
||||
- Рекурсивного получения размера текущей папки.
|
||||
- Переименована функция promptNewFolder -> promptNewDir.
|
||||
- Добавлена функция getSelectedNames.
|
||||
- Удален модуль Сache.
|
||||
- Оптимизирован модуль CloudFunc.
|
||||
|
||||
2012.03.01, v0.1.9
|
||||
===============
|
||||
Сегодня, в первый день весны, вышла новая версия облачного менеджера файлов: 0.1.9.
|
||||
В связи с этим, есть двойной повод порадоватся: наконец, пришла весна,
|
||||
с полной готовностью согревать серца жителей, после зимних холодов,
|
||||
а так же новая порция положительных изминений и исправленных ошибок в
|
||||
Облачном Командире.
|
||||
|
||||
Теперь Cloud Commander гораздо стабильнее,
|
||||
продуманее, внего гораздо проще вносить изминения и добавлять новые функции.
|
||||
Скоро будет много всего интересного.
|
||||
|
||||
С прошлой версии произошло очень много перемен и для пользователей и
|
||||
для программистов, некоторые части были полностью переписаны, и теперь программа
|
||||
более стабильна, а исходный код более простой и логичный.
|
||||
К примеру раньше был один баг, из-за которого при нескольких одновременных
|
||||
соединениях людям могли не приходить запрошенные файлы. Сейчас подобные просчёты
|
||||
позади. Рассмотрим подробнее, чем нас порадует новая версия Cloud Commaner’а.
|
||||
|
||||
**Добавленна внешняя возможность:**
|
||||
- загрузки файлов на Google Drive и DropBox;
|
||||
- пункт VK в меню;
|
||||
- прятать пункт меню Upload To, если ниодного storage модуля не задано в modules.json.
|
||||
- показывать контекстное меню, правкой кнопкой мыши, даже если оно уже открыто
|
||||
- не менять путь, если у нас нет прав на чтение папки.
|
||||
- времнный редирект для старых no-js урлов.
|
||||
- отключения кеширования файлов браузером в config.json
|
||||
- загрузка файлов;
|
||||
- сохранение файлов по <Ctrl> + <S> в CodeMirror;
|
||||
- удаление файлов;
|
||||
- пункт меню и возможность переименовать;
|
||||
- экран помощи (<F1>, когда Viewer загружен);
|
||||
|
||||
**Убрана внешняя возможность:**
|
||||
- Удалена часть URL, которая говорит о том, что JavaScript отключен. Теперь json-данные о структуре файлов будут получатся в собитии click с флагом ?json. Часть URL /no-js больше не будет поддерживатся;
|
||||
|
||||
**Исправленные ошибки:**
|
||||
- загрузка терминала;
|
||||
- в браузерах, которые поддерживают не все функции: jquery загружался после ie.js, должен загружатся — до;
|
||||
- закрытием терминала и откритием Вьюера, внутри функции, которая возникает во-время возникновения события переменной event не существует (всё хорошо работало на вебките);
|
||||
- высотой терминала;
|
||||
- установка текущего курсора, когда выбрали пункт меню;
|
||||
- ссылки в панели пути и с кликами на файлы.;
|
||||
- поддержка старых браузеров;
|
||||
- скроллинг в опере и Фаерфоксе;
|
||||
- (ненастоящее) удаление файлов;
|
||||
- установка текущего файла после обновления содержимого директории;
|
||||
- нажатие на файле;
|
||||
- первый и последующие показы меню, а так же выделение даблкликом в Firefox
|
||||
|
||||
**Обновлены:**
|
||||
- jquery до версии v1.9.0.
|
||||
- jquery-terminal до версии v0.4.22.
|
||||
- jQuery-contextMenu до версии v1.6.5.
|
||||
- socket.io до версии 0.9.13.
|
||||
- CodeMirror до версии 2.37.01.
|
||||
- dropbox до версии v.0.8.1.
|
||||
- funcyBox до версии v2.1.4.
|
||||
|
||||
**Внутренние изминения:**
|
||||
- Изменен способ получения github id (теперь это делается через config.json, rest api были удалены).
|
||||
- Добавлены функции DOM.getCurrentFileContent(pCallBack [, pCurrentFile]) для получения содержимого файла в ФС, а так же обёртка Util.setTimeout(pFunction [, pCallBack, pTime]).
|
||||
- Добавлена функция в win.js для парсинга вывода команды diskpart (которая используется для опредиления локальных дисков).
|
||||
- Добавлена функция DOM.getCurrentDir().
|
||||
- API url на клиенте читается с файла config.json.
|
||||
- Если выбрана загрузка на Gist (GitHub) и у файла в формате json нет расширения — оно добавляется.
|
||||
- Добавлена возможность авторизовыватся на Гитхабе через новое окно. Изминен редирект на /auth и добавлена фнукция rout в cloudcmd.js.
|
||||
- DropBox, GDrive и GitHub модули теперь выглядят одинаково.
|
||||
- Рефакторинг в модуле Viewer.
|
||||
- Улучшена оптимизация файла menu.js с 2539 до 2444 байт.
|
||||
- Добавлена возможность читать GDrive key из конфига.
|
||||
- Добавлена возможность авторизовыватся на дропбоксе через popup.
|
||||
- Добавлена возможность авторизовыватся на vk.com.
|
||||
- Улучшен формат и парсинг файла modules.json.
|
||||
- Добавлена возможность читать информацию о модулях сохранения из модуля меню.
|
||||
- Добавлена простая система рендеринга шаблонов Util.render.
|
||||
- Добавлены функции DOM.parseJSON и DOM.stringifyJSON, как обёртки над системными функциями.
|
||||
- Добавлен плагин для миграции к новой версии jquery.
|
||||
- Убрано получения данных из кеша Minify.
|
||||
- JSON-файлы перемещены в папки json.
|
||||
- Изминен шрифт с Octicons на Fonteollo.
|
||||
- Полностью удален шрифт Octicons.
|
||||
- Удалено свойство allowed из свойства cache в конфиге.
|
||||
- С этого момента оптимизироватся будут лишь те файлы, дата последнего изминения которых была изменена.
|
||||
- Убрана возможность кешировать файлы в памяти.
|
||||
- Перемещены расширения из main.js в json/ext.json.
|
||||
- Основная функциональность CloudCmd перемещена в commander.js из server.js.
|
||||
- Добавлена возможность удалять приставку к URL /fs когда мы в корневом каталоге.
|
||||
- Убраны перересовки создаваемые js.
|
||||
- Добавлена возможность добавлять флаг ?json только если мы работаем с папкой.
|
||||
- Изминен принцип работы функции clickProcessing в меню, теперь он гораздо проще.
|
||||
- Произведен тотальный рефакторинг в файле commander.js, теперь там только генерация.
|
||||
структуры каталогов в формате json.
|
||||
- добавлен обьект RESTfull в DOM модуль для упрощения работы с CloudCmd REST API.
|
||||
2
LICENSE
2
LICENSE
|
|
@ -1,6 +1,6 @@
|
|||
(The MIT License)
|
||||
|
||||
Copyright (c) 2013 Coderaiser <mnemonic.enemy@gmail.com>
|
||||
Copyright (c) 2012-2025 Coderaiser <mnemonic.enemy@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
|
|
|
|||
460
README.md
460
README.md
|
|
@ -1,339 +1,177 @@
|
|||
Cloud Commander v0.4.0 [![NPM version][NPMIMGURL]][NPMURL] [![Dependency Status][DependencyStatusIMGURL]][DependencyStatusURL] [![Build Status][BuildStatusIMGURL]][BuildStatusURL]
|
||||
===============
|
||||
###[Main][MainURL] [Blog][BlogURL] [Demo][DemoURL]
|
||||
[![Flattr][FlattrIMGURL]][FlattrURL]
|
||||
[NPMIMGURL]: https://badge.fury.io/js/cloudcmd.png
|
||||
[BuildStatusIMGURL]: https://secure.travis-ci.org/coderaiser/cloudcmd.png?branch=master
|
||||
[DependencyStatusIMGURL]: https://gemnasium.com/coderaiser/cloudcmd.png
|
||||
[FlattrIMGURL]: http://api.flattr.com/button/flattr-badge-large.png
|
||||
[NPM_INFO_IMG]: https://nodei.co/npm/cloudcmd.png?downloads=true&&stars
|
||||
[NPMURL]: http://badge.fury.io/js/cloudcmd
|
||||
[BuildStatusURL]: http://travis-ci.org/coderaiser/cloudcmd "Build Status"
|
||||
[DependencyStatusURL]: https://gemnasium.com/coderaiser/cloudcmd "Dependency Status"
|
||||
[FlattrURL]: https://flattr.com/submit/auto?user_id=coderaiser&url=github.com/coderaiser/cloudcmd&title=cloudcmd&language=&tags=github&category=software "flattr"
|
||||
[NPM_INFO_URL]: https://npmjs.org/package/cloudcmd "npm"
|
||||
[MainURL]: http://cloudcmd.io "Main"
|
||||
[BlogURL]: http://blog.cloudcmd.io "Blog"
|
||||
[DemoURL]: http://io.cloudcmd.io "Demo"
|
||||
# Cloud Commander v19.1.9 [![Build Status][BuildStatusIMGURL]][BuildStatusURL] [![Codacy][CodacyIMG]][CodacyURL] [![Gitter][GitterIMGURL]][GitterURL]
|
||||
|
||||
**Cloud Commander** - cloud file manager with console and editor.
|
||||
### [Main][MainURL] [Blog][BlogURL] [Support][SupportURL] [Demo][DemoURL]
|
||||
|
||||

|
||||
[MainURL]: https://cloudcmd.io "Main"
|
||||
[BlogURL]: https://blog.cloudcmd.io "Blog"
|
||||
[SupportURL]: https://patreon.com/coderaiser "Patreon"
|
||||
[DemoURL]: https://cloudcmd-zdp6.onrender.com
|
||||
[NPM_INFO_IMG]: https://nodei.co/npm/cloudcmd.png
|
||||
[BuildStatusURL]: https://github.com/coderaiser/cloudcmd/actions/workflows/nodejs.yml "Build Status"
|
||||
[BuildStatusIMGURL]: https://github.com/coderaiser/cloudcmd/actions/workflows/nodejs.yml/badge.svg
|
||||
[CodacyURL]: https://www.codacy.com/app/coderaiser/cloudcmd
|
||||
[CodacyIMG]: https://api.codacy.com/project/badge/Grade/ddda78be780549ce8754f8d47a8c0e36
|
||||
[GitterURL]: https://gitter.im/cloudcmd/hello
|
||||
[GitterIMGURL]: https://img.shields.io/gitter/room/coderaiser/cloudcmd.js.svg
|
||||
[DeployURL]: https://heroku.com/deploy?template=https://github.com/coderaiser/cloudcmd "Deploy"
|
||||
[DeployIMG]: https://www.herokucdn.com/deploy/button.png
|
||||
|
||||
Benefits
|
||||
---------------
|
||||
- full browser compatibility *(ie6+,chrome,safari,opera,firefox)*;
|
||||
- responsible design
|
||||
- one full page loading, *and then just one-time json-dir-listings loading
|
||||
(with refresh opportunity).*
|
||||
- caching read directories *to localStorage (for now)
|
||||
(so if network will disconnected or something happens with a signal, we
|
||||
definitely will can work with cached copy of directory listings)*;
|
||||
- key binding
|
||||
- disabled js support *(working in limited mode)*.
|
||||
- automated minification *client js-files and onstart-reading Cloud manager files on server starting.*
|
||||
**Cloud Commander** a file manager for the web with console and editor.
|
||||
|
||||
**Cloud Commander** uses all benefits of js, so if js is disabled,
|
||||
we go to *limited mode*.
|
||||

|
||||
|
||||
Limited-mode features
|
||||
---------------
|
||||
- no keybinding
|
||||
- no local caching
|
||||
- full loading of all web page(with styles, js-scripts, html-page etc).
|
||||
|
||||
Hot keys
|
||||
---------------
|
||||
In all modern web browsers (but not in IE, becouse he special) hot keys works.
|
||||
There is a short list:
|
||||
- **F1** - help
|
||||
- **F2** - rename current file
|
||||
- **F3** - view
|
||||
- **F4** - edit
|
||||
- **F5** - copy
|
||||
- **F6** - rename/move
|
||||
- **F7** - new dir
|
||||
- **F8, Delete** - remove current file
|
||||
- **F9** - menu
|
||||
- **Ctrl + r** - reload dir content
|
||||
- **Ctrl + d** - clear local cache (wich contains dir contents)
|
||||
- **Alt + q** - disable key bindings
|
||||
- **Alt + s** - get all key bindings back
|
||||
- **Ctrl + a** - select all files in a panel
|
||||
- **up, down, enter** - filesystem navigation
|
||||
- **Tab** - move via panels
|
||||
- **Page Up** - up on one page
|
||||
- **Page Down** - down on one page
|
||||
- **Home** - to begin of list
|
||||
- **End** - to end of list
|
||||
- **Shift + Delete** - remove without prompt
|
||||
- **Insert** - select current file
|
||||
- **Shift + F10** - context menu
|
||||
- **~** - console
|
||||
|
||||
Edit
|
||||
---------------
|
||||
[Demo](http://io.cloudcmd.io/fs/etc#/edit/passwd "Edit")
|
||||

|
||||
|
||||
###Hot keys
|
||||
- **F4** - open
|
||||
- **Ctrl + s** - save
|
||||
- **Esc** - close
|
||||
|
||||
Console
|
||||
---------------
|
||||
[Demo](http://io.cloudcmd.io#/console "Console")
|
||||

|
||||
|
||||
###Hot keys
|
||||
- **~** - open
|
||||
- **Esc** - close
|
||||
|
||||
Menu
|
||||
---------------
|
||||
[Demo](http://io.cloudcmd.io#/menu "Menu")
|
||||

|
||||
Right mouse click button shows context menu with items:
|
||||
- View
|
||||
- Edit
|
||||
- Rename
|
||||
- Delete
|
||||
- Zip file
|
||||
- Upload to (Dropbox, Github, GDrive)
|
||||
- Download
|
||||
- New (File, Dir, from cloud)
|
||||
|
||||
###Hot keys
|
||||
- **F9** - open
|
||||
- **Esc** - close
|
||||
|
||||
Menu
|
||||
---------------
|
||||
Right mouse click button shows context menu with items:
|
||||
- View
|
||||
- Edit
|
||||
- Rename
|
||||
- Delete
|
||||
- Upload to (Dropbox, Github, GDrive)
|
||||
- Download
|
||||
- New (File, Dir, from cloud)
|
||||
|
||||
Install
|
||||
---------------
|
||||
[![NPM_INFO][NPM_INFO_IMG]][NPM_INFO_URL]
|
||||
|
||||
Installing **Cloud Commander** is very simple.
|
||||
All you need is
|
||||
- install [node.js](http://nodejs.org/ "node.js")
|
||||
- [download](https://github.com/coderaiser/cloudcmd/archive/master.zip)
|
||||
and unpack or just clone repository from github:
|
||||
## Install
|
||||
|
||||
```
|
||||
git clone git://github.com/coderaiser/cloudcmd.git
|
||||
cd cloudcmd
|
||||
node cloudcmd
|
||||
```
|
||||
or install in npm:
|
||||
```
|
||||
npm i cloudcmd -g
|
||||
cloudcmd
|
||||
npm i cloudcmd -g
|
||||
```
|
||||
|
||||
Configuration
|
||||
---------------
|
||||
All main configuration could be done via config.json.
|
||||
## Start
|
||||
|
||||
For starting just type in console:
|
||||
|
||||
```sh
|
||||
cloudcmd
|
||||
```
|
||||
|
||||
## How to use?
|
||||
|
||||
Open url `http://localhost:8000` in browser.
|
||||
|
||||
### View
|
||||
|
||||
You will see something similar to this.
|
||||

|
||||
|
||||
## Deploy
|
||||
|
||||
`Cloud Commander` could be easily deployed to [Heroku][DeployURL].
|
||||
|
||||
[![Deploy][DeployIMG]][DeployURL]
|
||||
|
||||
## Using as Middleware
|
||||
|
||||
Cloud Commander could be used as middleware for `node.js` applications based on [socket.io](http://socket.io "Socket.IO") and [express](http://expressjs.com "Express"):
|
||||
|
||||
Init `package.json`:
|
||||
|
||||
```
|
||||
npm init -y
|
||||
```
|
||||
|
||||
Install dependencies:
|
||||
|
||||
```
|
||||
npm i cloudcmd express socket.io -S
|
||||
```
|
||||
|
||||
And create `index.js`:
|
||||
|
||||
```js
|
||||
{
|
||||
"api_url" :"/api/v1",
|
||||
"appcache" : false, /* cache files for offline use */
|
||||
"analytics" : true, /* google analytics suport */
|
||||
"localStorage" : true, /* cache directory data */
|
||||
"minification" : { /* minification of js,css,html and img */
|
||||
"js" : false, /* minify module needed */
|
||||
"css" : false, /* npm i minify */
|
||||
"html" : true,
|
||||
"img" : false
|
||||
import http from 'node:http';
|
||||
import cloudcmd from 'cloudcmd';
|
||||
import {Server} from 'socket.io';
|
||||
import express from 'express';
|
||||
|
||||
const app = express();
|
||||
|
||||
const port = 1337;
|
||||
const prefix = '/';
|
||||
|
||||
const server = http.createServer(app);
|
||||
const socket = new Server(server, {
|
||||
path: `${prefix}socket.io`,
|
||||
});
|
||||
|
||||
const config = {
|
||||
name: 'cloudcmd :)',
|
||||
};
|
||||
|
||||
const filePicker = {
|
||||
data: {
|
||||
FilePicker: {
|
||||
key: 'key',
|
||||
},
|
||||
},
|
||||
"cache" : true,
|
||||
"logs" : false, /* logs or console ouput */
|
||||
"show_keys_panel" : true, /* show classic panel with buttons of keys */
|
||||
"server" : true, /* server mode or testing mode */
|
||||
"socket" : true /* enable web sockets */
|
||||
"port" : 8000, /* http port or null(default) */
|
||||
"sslPort" : 443, /* https port or null(default) */
|
||||
"ip" : null, /* ip or null(default) */
|
||||
"ssl" : false /* should use https? */
|
||||
"rest" : true /* enable rest interface */
|
||||
}
|
||||
};
|
||||
|
||||
// override option from json/modules.json
|
||||
const modules = {
|
||||
filePicker,
|
||||
};
|
||||
|
||||
const {
|
||||
createConfigManager,
|
||||
configPath,
|
||||
} = cloudcmd;
|
||||
|
||||
const configManager = createConfigManager({
|
||||
configPath,
|
||||
});
|
||||
|
||||
app.use(prefix, cloudcmd({
|
||||
socket, // used by Config, Edit (optional) and Console (required)
|
||||
config, // config data (optional)
|
||||
modules, // optional
|
||||
configManager, // optional
|
||||
}));
|
||||
|
||||
server.listen(port);
|
||||
```
|
||||
|
||||
Server
|
||||
---------------
|
||||
Standard practices say no non-root process gets to talk to
|
||||
the Internet on a port less than 1024. Anyway I suggest you
|
||||
to start Cloud Commander as non-root. How it could be solved?
|
||||
There is a couple easy and fast ways. One of them is port forwarding.
|
||||
###Iptables
|
||||
Just run [shell/addtables.sh](shell/addtables.sh) for default options.
|
||||
```sh
|
||||
@:/tmp/cloudcmd (dev) $ sudo iptables -t nat -L # look rules before
|
||||
@:/tmp/cloudcmd (dev) $ sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 8000
|
||||
@:/tmp/cloudcmd (dev) $ sudo iptables -t nat -A PREROUTING -p tcp --dport 443 -j REDIRECT --to-ports 4430
|
||||
@:/tmp/cloudcmd (dev) $ sudo iptables -t nat -L # look rules after
|
||||
```
|
||||
You should see something like this ( **8000** and **4430** should be in config as **port** and **sslPort** )
|
||||
## Docker
|
||||
|
||||
target prot opt source destination
|
||||
REDIRECT tcp -- anywhere anywhere tcp dpt:http redir ports 8000
|
||||
REDIRECT tcp -- anywhere anywhere tcp dpt:https redir ports 4430
|
||||
The docker images are provided for multiple architectures and types. The following list shows all existing images:
|
||||
|
||||
If you would want to get things back just clear rules ( **1** and **2** it's rule numbers,
|
||||
in your list they could differ).
|
||||
| Architecture | Type |
|
||||
|----------------|--------------|
|
||||
| amd64 | linux |
|
||||
| arm64 (arm/v8) | linux |
|
||||
| amd64 | linux-alpine |
|
||||
| arm64 (arm/v8) | linux-alpine |
|
||||
|
||||
`Cloud Commander` could be used as a [docker container](https://hub.docker.com/r/coderaiser/cloudcmd/ "Docker container") this way:
|
||||
|
||||
```sh
|
||||
@:/tmp/cloudcmd (dev) $ sudo iptables -t nat -D PREROUTING 2
|
||||
@:/tmp/cloudcmd (dev) $ sudo iptables -t nat -D PREROUTING 1
|
||||
docker run -it --rm -v ~:/root -v /:/mnt/fs -w=/root -p 8000:8000 coderaiser/cloudcmd
|
||||
```
|
||||
|
||||
###nginx
|
||||
Get [nginx](http://nginx.org/ "nginx"). On linux it could be done like that
|
||||
Config would be read from home directory, hosts root file system would be mount to `/mnt/fs`,
|
||||
`8000` port would be exposed to hosts port.
|
||||
|
||||
Also you could use [docker compose](https://docs.docker.com/compose/ "Docker Compose") with `docker-compose.yml`:
|
||||
|
||||
```yml
|
||||
version: '2'
|
||||
services:
|
||||
web:
|
||||
ports:
|
||||
- 8000:8000
|
||||
volumes:
|
||||
- ~:/root
|
||||
- /:/mnt/fs
|
||||
image: coderaiser/cloudcmd
|
||||
```
|
||||
|
||||
When you create this file run:
|
||||
|
||||
```sh
|
||||
sudo apt-get install nginx #for ubuntu and debian
|
||||
```
|
||||
Than make host file **/etc/nginx/sites-enabled/io.cloudcmd.io**
|
||||
( *io.cloudcmd.io* is your domain name) with content:
|
||||
```sh
|
||||
server {
|
||||
listen 80;
|
||||
server_name io.cloudcmd.io;
|
||||
access_log /var/log/nginx/io.cloudcmd.io.access.log;
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:8000/;
|
||||
}
|
||||
}
|
||||
```
|
||||
```sh
|
||||
# create symlink of this file
|
||||
ln -s ./sites-enabled/io.cloudcmd.io ./sites-available
|
||||
# restart nginx
|
||||
/etc/init.d/nginx restart
|
||||
docker-compose up
|
||||
```
|
||||
|
||||
To run Cloud Commander as daemon in linux you could set **log** to true in config and
|
||||
do something like this:
|
||||
|
||||
nohup node cloudcmd
|
||||
## Documentation
|
||||
|
||||
Authorization
|
||||
---------------
|
||||
Cloud Commander could authorize clients on GitHub via openID.
|
||||
All things that should be done is must be added **id** and **secret** of application
|
||||
from github settings page and added to [modules.json](json/modules.json) (id just) and env variable (secret)
|
||||
with names: *github_id*, *github_secret*, *dropbox_key*, *dropbox_secret* etc in
|
||||
[secret.bat](shell/secret.bat) *(on win32)* or [secret.sh](shell/secret.sh) *(on nix)*.
|
||||
More documentation you can find on https://cloudcmd.io/.
|
||||
|
||||
## Get involved
|
||||
|
||||
Start
|
||||
---------------
|
||||
To start **Cloud Commander** only one command needed:
|
||||
|
||||
node cloudcmd
|
||||
or on win platform just
|
||||
There is a lot ways to be involved in `Cloud Commander` development:
|
||||
|
||||
cloudcmd
|
||||
After that Cloud Commander reads port information from config file [config.json](json/config.json#L17) and start server
|
||||
on this port ( **8000** by default ), if none of port varibles ( *cloud9*, *cloudfoundry* and *nodester* ) isn't exist.
|
||||
Then type in browser
|
||||
- support project on patreon: https://patreon.com/coderaiser;
|
||||
- if you find a bug or got idea to share [create an issue](https://github.com/coderaiser/cloudcmd/issues/new "Create issue");
|
||||
- if you fixed a bug, typo or implemented new feature [create pull request](https://github.com/coderaiser/cloudcmd/compare "Create pull request");
|
||||
- if you know languages you can help with [site translations](https://github.com/coderaiser/cloudcmd/wiki "Cloud Commander community wiki");
|
||||
|
||||
http://127.0.0.1:8000
|
||||
or
|
||||
## License
|
||||
|
||||
http://localhost:8000
|
||||
Update
|
||||
---------------
|
||||
**Cloud Commander** is very often updates.
|
||||
Update is doing automagically but it could be done also manualy
|
||||
by typing a few commands in cloudcmd directory:
|
||||
|
||||
git pull
|
||||
or check new version on npm
|
||||
|
||||
npm info cloudcmd
|
||||
|
||||
and then, if there is new version
|
||||
|
||||
npm r cloudcmd
|
||||
npm i cloudcmd
|
||||
|
||||
Additional modules
|
||||
---------------
|
||||
**Cloud Commander's Server Side** not using additional modules for main functionality.
|
||||
But for minification and optimization tricks optional can be
|
||||
assingned (and installed) modules: [Minify] (https://github.com/coderaiser/minify "Minify")
|
||||
and [socket.io] (https://github.com/LearnBoost/socket.io "Socket.IO").
|
||||
|
||||
Install addtitional modules (type in **Cloud Commander** directory):
|
||||
|
||||
npm i
|
||||
|
||||
Extensions
|
||||
---------------
|
||||
**Cloud Commander** desinged to easily porting extensions.
|
||||
For extend main functionality Cloud Commander use next modules:
|
||||
- [Ace] [AceURL]
|
||||
- [FancyBox] [FancyBoxURL]
|
||||
- [jQuery-contextMenu] [jQuery-contextMenuURL]
|
||||
- [jq-console] [jq-consoleURL]
|
||||
- [github] [githubURL]
|
||||
- [dropbox-js] [dropbox-jsURL]
|
||||
- [jquery] [jqueryURL]
|
||||
|
||||
[AceURL]: //ace.ajax.org/ "Ace"
|
||||
[FancyBoxURL]: //github.com/fancyapps/fancyBox "FancyBox"
|
||||
[jQuery-contextMenuURL]: //github.com/medialize/jQuery-contextMenu "jQuery-contextMenu"
|
||||
[jq-consoleURL]: //github.com/replit/jq-console "jq-console"
|
||||
[githubURL]: //github.com/michael/github "github"
|
||||
[dropbox-jsURL]: //github.com/dropbox/dropbox-js "dropbox-js"
|
||||
[jqueryURL]: //jquery.com
|
||||
|
||||
Contributing
|
||||
---------------
|
||||
If you would like to contribute - send pull request to dev branch.
|
||||
Getting dev version of **Cloud Commander**:
|
||||
|
||||
git clone git://github.com/coderaiser/cloudcmd.git
|
||||
git checkout dev
|
||||
|
||||
It is possible that dev version of Cloud Commander will needed dev version of Minify,
|
||||
so to get it you should type a couple more commands:
|
||||
|
||||
cd node_modules
|
||||
rm -rf minify
|
||||
git clone git://github.com/coderaiser/minify
|
||||
git checkout dev
|
||||
|
||||
Version history
|
||||
---------------
|
||||
- *2013.09.27*, **[v0.4.0](//github.com/coderaiser/cloudcmd-archive/raw/master/cloudcmd-v0.4.0.zip)**
|
||||
- *2013.07.01*, **[v0.3.0](//github.com/coderaiser/cloudcmd-archive/raw/master/cloudcmd-v0.3.0.zip)**
|
||||
- *2013.04.22*, **[v0.2.0](//github.com/coderaiser/cloudcmd-archive/raw/master/cloudcmd-v0.2.0.zip)**
|
||||
- *2013.03.01*, **[v0.1.9](//github.com/coderaiser/cloudcmd-archive/raw/master/cloudcmd-v0.1.9.zip)**
|
||||
- *2012.12.12*, **[v0.1.8](//github.com/coderaiser/cloudcmd-archive/raw/master/cloudcmd-v0.1.8.zip)**
|
||||
- *2012.10.01*, **[v0.1.7](//github.com/coderaiser/cloudcmd-archive/raw/master/cloudcmd-v0.1.7.zip)**
|
||||
- *2012.08.24*, **[v0.1.6](//github.com/coderaiser/cloudcmd-archive/raw/master/cloudcmd-v0.1.6.zip)**
|
||||
- *2012.08.06*, **[v0.1.5](//github.com/coderaiser/cloudcmd-archive/raw/master/cloudcmd-v0.1.5.zip)**
|
||||
- *2012.07.27*, **[v0.1.4](//github.com/coderaiser/cloudcmd-archive/raw/master/cloudcmd-v0.1.4.zip)**
|
||||
- *2012.07.19*, **[v0.1.3](//github.com/coderaiser/cloudcmd-archive/raw/master/cloudcmd-v0.1.3.zip)**
|
||||
- *2012.07.14*, **[v0.1.2](//github.com/coderaiser/cloudcmd-archive/raw/master/cloudcmd-v0.1.2.zip)**
|
||||
- *2012.07.11*, **[v0.1.1](//github.com/coderaiser/cloudcmd-archive/raw/master/cloudcmd-v0.1.1.zip)**
|
||||
- *2012.00.00*, **[v0.1.0](//github.com/coderaiser/cloudcmd-archive/raw/master/cloudcmd-v0.1.0.zip)**
|
||||
|
||||
License
|
||||
---------------
|
||||
MIT [license](LICENSE "license").
|
||||
|
||||
Special Thanks
|
||||
---------------
|
||||
- [Polietilena](http://polietilena.github.io/ "Polietilena") for [logo](img/logo/cloudcmd.png "logo") and [favicon](img/favicon/favicon.png "favicon").
|
||||
- [Elec-ua](https://github.com/elec-ua) for [ru](http://ru.cloudcmd.io "Cloud Commander in Russian") and [ua](http://ua.cloudcmd.io "Cloud Commander in Ukrainian") translations.
|
||||
MIT
|
||||
|
|
|
|||
162
app.json
Normal file
162
app.json
Normal file
|
|
@ -0,0 +1,162 @@
|
|||
{
|
||||
"name": "cloudcmd",
|
||||
"description": "Cloud Commander orthodox web file manager with console and editor",
|
||||
"repository": "https://github.com/coderaiser/cloudcmd",
|
||||
"logo": "http://cloudcmd.io/img/logo/cloudcmd.png",
|
||||
"keywords": [
|
||||
"console",
|
||||
"editor",
|
||||
"file",
|
||||
"file manager",
|
||||
"folder",
|
||||
"orthodox"
|
||||
],
|
||||
"stack": "heroku-18",
|
||||
"env": {
|
||||
"NPM_CONFIG_PRODUCTION": {
|
||||
"description": "Keep false to install devDependencies and build frontend",
|
||||
"value": "false",
|
||||
"required": false
|
||||
},
|
||||
"CLOUDCMD_EDITOR": {
|
||||
"description": "set editor",
|
||||
"value": "edward",
|
||||
"required": false
|
||||
},
|
||||
"CLOUDCMD_CONTACT": {
|
||||
"description": "enable contact",
|
||||
"value": "true",
|
||||
"required": false
|
||||
},
|
||||
"CLOUDCMD_CONFIG_DIALOG": {
|
||||
"description": "show config dialog",
|
||||
"value": "false",
|
||||
"required": false
|
||||
},
|
||||
"CLOUDCMD_CONFIG_AUTH": {
|
||||
"description": "disable auth change in config dialog",
|
||||
"value": "false",
|
||||
"required": false
|
||||
},
|
||||
"CLOUDCMD_CONSOLE": {
|
||||
"description": "enable console",
|
||||
"value": "true",
|
||||
"required": false
|
||||
},
|
||||
"CLOUDCMD_SYNC_CONSOLE_PATH": {
|
||||
"description": "sync console path",
|
||||
"value": "false",
|
||||
"required": false
|
||||
},
|
||||
"CLOUDCMD_TERMINAL": {
|
||||
"description": "enable terminal",
|
||||
"value": "true",
|
||||
"required": false
|
||||
},
|
||||
"CLOUDCMD_TERMINAL_PATH": {
|
||||
"description": "set terminal path",
|
||||
"value": "gritty",
|
||||
"required": false
|
||||
},
|
||||
"CLOUDCMD_TERMINAL_COMMAND": {
|
||||
"description": "set command to run in terminal (shell by default)",
|
||||
"value": "",
|
||||
"required": false
|
||||
},
|
||||
"CLOUDCMD_ONE_FILE_PANEL": {
|
||||
"description": "show one file panel",
|
||||
"value": "false",
|
||||
"required": false
|
||||
},
|
||||
"CLOUDCMD_KEYS_PANEL": {
|
||||
"description": "show keys panel",
|
||||
"value": "true",
|
||||
"required": false
|
||||
},
|
||||
"CLOUDCMD_NAME": {
|
||||
"description": "set tab name in web browser",
|
||||
"value": "",
|
||||
"required": false
|
||||
},
|
||||
"CLOUDCMD_AUTH": {
|
||||
"description": "enable authorization",
|
||||
"value": "false",
|
||||
"required": false
|
||||
},
|
||||
"CLOUDCMD_USERNAME": {
|
||||
"description": "set username",
|
||||
"value": "root",
|
||||
"required": false
|
||||
},
|
||||
"CLOUDCMD_PASSWORD": {
|
||||
"description": "set password",
|
||||
"value": "toor",
|
||||
"required": false
|
||||
},
|
||||
"CLOUDCMD_ROOT": {
|
||||
"description": "set root dir",
|
||||
"value": "",
|
||||
"required": false
|
||||
},
|
||||
"CLOUDCMD_VIM": {
|
||||
"description": "enable vim hot keys",
|
||||
"value": "false",
|
||||
"required": false
|
||||
},
|
||||
"CLOUDCMD_COLUMNS": {
|
||||
"description": "set visible columns",
|
||||
"value": "name-size-date-owner-mode",
|
||||
"required": false
|
||||
},
|
||||
"CLOUDCMD_OPEN": {
|
||||
"description": "open web browser when server started",
|
||||
"value": "false",
|
||||
"required": false
|
||||
},
|
||||
"CLOUDCMD_CONFIRM_COPY": {
|
||||
"description": "confirm copy",
|
||||
"value": "true",
|
||||
"required": false
|
||||
},
|
||||
"CLOUDCMD_CONFIRM_MOVE": {
|
||||
"description": "confirm move",
|
||||
"value": "true",
|
||||
"required": false
|
||||
},
|
||||
"CLOUDCMD_SHOW_FILE_NAME": {
|
||||
"description": "show file name in view and edit",
|
||||
"value": "false",
|
||||
"required": false
|
||||
},
|
||||
"CLOUDCMD_EXPORT": {
|
||||
"description": "enable export of config through a server",
|
||||
"value": "false",
|
||||
"required": false
|
||||
},
|
||||
"CLOUDCMD_EXPORT_TOKEN": {
|
||||
"description": "authorization token used by export server",
|
||||
"value": "root",
|
||||
"required": false
|
||||
},
|
||||
"CLOUDCMD_IMPORT": {
|
||||
"description": "enable import of config",
|
||||
"value": "false",
|
||||
"required": false
|
||||
},
|
||||
"CLOUDCMD_IMPORT_TOKEN": {
|
||||
"description": "authorization token used to connect to export server",
|
||||
"value": "root",
|
||||
"required": false
|
||||
},
|
||||
"CLOUDCMD_IMPORT_URL": {
|
||||
"description": "url of an import server",
|
||||
"value": "http://localhost:8000",
|
||||
"required": false
|
||||
},
|
||||
"CLOUDCMD_IMPORT_LISTEN": {
|
||||
"description": "enable listen on config updates from import server",
|
||||
"value": "false",
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
}
|
||||
12
bin/cloudcmd
12
bin/cloudcmd
|
|
@ -1,12 +0,0 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
/* cloudcmd binary
|
||||
* usage: node cloudcmd
|
||||
*/
|
||||
(function(){
|
||||
'use strict';
|
||||
|
||||
require('../cloudcmd');
|
||||
|
||||
})();
|
||||
|
||||
365
bin/cloudcmd.mjs
Executable file
365
bin/cloudcmd.mjs
Executable file
|
|
@ -0,0 +1,365 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
import process from 'node:process';
|
||||
import {createRequire} from 'node:module';
|
||||
import {promisify} from 'node:util';
|
||||
import {tryToCatch} from 'try-to-catch';
|
||||
import {createSimport} from 'simport';
|
||||
import parse from 'yargs-parser';
|
||||
import exit from '../server/exit.js';
|
||||
import {createConfig, configPath} from '../server/config.mjs';
|
||||
import * as env from '../server/env.mjs';
|
||||
import prefixer from '../server/prefixer.js';
|
||||
import * as validate from '../server/validate.mjs';
|
||||
|
||||
process.on('unhandledRejection', exit);
|
||||
|
||||
const require = createRequire(import.meta.url);
|
||||
|
||||
const Info = require('../package.json');
|
||||
const isUndefined = (a) => typeof a === 'undefined';
|
||||
const simport = createSimport(import.meta.url);
|
||||
|
||||
const choose = (a, b) => {
|
||||
if (isUndefined(a))
|
||||
return b;
|
||||
|
||||
return a;
|
||||
};
|
||||
|
||||
const config = createConfig({
|
||||
configPath,
|
||||
});
|
||||
|
||||
const DIR_SERVER = '../server/';
|
||||
|
||||
const maybeRoot = (a) => {
|
||||
if (a === '.')
|
||||
return process.cwd();
|
||||
|
||||
return a;
|
||||
};
|
||||
|
||||
const yargsOptions = {
|
||||
configuration: {
|
||||
'strip-aliased': true,
|
||||
'strip-dashed': true,
|
||||
},
|
||||
coerce: {
|
||||
root: maybeRoot,
|
||||
},
|
||||
string: [
|
||||
'name',
|
||||
'port',
|
||||
'password',
|
||||
'username',
|
||||
'config',
|
||||
'editor',
|
||||
'packer',
|
||||
'root',
|
||||
'prefix',
|
||||
'prefix-socket',
|
||||
'terminal-path',
|
||||
'terminal-command',
|
||||
'columns',
|
||||
'menu',
|
||||
'theme',
|
||||
'import-url',
|
||||
'import-token',
|
||||
'export-token',
|
||||
'dropbox-token',
|
||||
],
|
||||
boolean: [
|
||||
'auth',
|
||||
'repl',
|
||||
'save',
|
||||
'server',
|
||||
'online',
|
||||
'open',
|
||||
'config-dialog',
|
||||
'config-auth',
|
||||
'console',
|
||||
'sync-console-path',
|
||||
'contact',
|
||||
'terminal',
|
||||
'terminal-auto-restart',
|
||||
'one-file-panel',
|
||||
'confirm-copy',
|
||||
'confirm-move',
|
||||
'show-config',
|
||||
'show-dot-files',
|
||||
'show-file-name',
|
||||
'vim',
|
||||
'keys-panel',
|
||||
'color',
|
||||
'export',
|
||||
'import',
|
||||
'import-listen',
|
||||
'log',
|
||||
'zip',
|
||||
'dropbox',
|
||||
],
|
||||
default: {
|
||||
'server': true,
|
||||
'name': choose(env.parse('name'), config('name')),
|
||||
'auth': choose(env.bool('auth'), config('auth')),
|
||||
'port': config('port'),
|
||||
'online': config('online'),
|
||||
'open': choose(env.bool('open'), config('open')),
|
||||
'editor': env.parse('editor') || config('editor'),
|
||||
'menu': env.parse('menu') || config('menu'),
|
||||
'packer': config('packer') || 'tar',
|
||||
'zip': config('zip'),
|
||||
'username': env.parse('username') || config('username'),
|
||||
'root': choose(env.parse('root'), config('root')),
|
||||
'prefix': choose(env.parse('prefix'), config('prefix')),
|
||||
'console': choose(env.bool('console'), config('console')),
|
||||
'contact': choose(env.bool('contact'), config('contact')),
|
||||
'terminal': choose(env.bool('terminal'), config('terminal')),
|
||||
'columns': env.parse('columns') || config('columns') || '',
|
||||
'theme': env.parse('theme') || config('theme') || '',
|
||||
'vim': choose(env.bool('vim'), config('vim')),
|
||||
'log': config('log'),
|
||||
|
||||
'import-url': env.parse('import_url') || config('importUrl'),
|
||||
'import-listen': choose(env.bool('import_listen'), config('importListen')),
|
||||
'import': choose(env.bool('import'), config('import')),
|
||||
'export': choose(env.bool('export'), config('export')),
|
||||
|
||||
'prefix-socket': config('prefixSocket'),
|
||||
'show-dot-files': choose(env.bool('show_dot_files'), config('showDotFiles')),
|
||||
'show-file-name': choose(env.bool('show_file_name'), config('showFileName')),
|
||||
'sync-console-path': choose(env.bool('sync_console_path'), config('syncConsolePath')),
|
||||
'config-dialog': choose(env.bool('config_dialog'), config('configDialog')),
|
||||
'config-auth': choose(env.bool('config_auth'), config('configAuth')),
|
||||
'terminal-path': env.parse('terminal_path') || config('terminalPath'),
|
||||
'terminal-command': env.parse('terminal_command') || config('terminalCommand'),
|
||||
'terminal-auto-restart': choose(env.bool('terminal_auto_restart'), config('terminalAutoRestart')),
|
||||
'one-file-panel': choose(env.bool('one_file_panel'), config('oneFilePanel')),
|
||||
'confirm-copy': choose(env.bool('confirm_copy'), config('confirmCopy')),
|
||||
'confirm-move': choose(env.bool('confirm_move'), config('confirmMove')),
|
||||
'keys-panel': env.bool('keys_panel') || config('keysPanel'),
|
||||
'import-token': env.parse('import_token') || config('importToken'),
|
||||
'export-token': env.parse('export_token') || config('exportToken'),
|
||||
|
||||
'dropbox': config('dropbox'),
|
||||
'dropbox-token': config('dropboxToken') || '',
|
||||
},
|
||||
alias: {
|
||||
version: 'v',
|
||||
help: 'h',
|
||||
password: 'p',
|
||||
online: 'o',
|
||||
username: 'u',
|
||||
save: 's',
|
||||
auth: 'a',
|
||||
config: 'c',
|
||||
},
|
||||
};
|
||||
|
||||
const {argv} = process;
|
||||
const args = parse(argv.slice(2), yargsOptions);
|
||||
|
||||
if (args.version)
|
||||
version();
|
||||
else if (args.help)
|
||||
help();
|
||||
else
|
||||
main();
|
||||
|
||||
async function main() {
|
||||
const {validateArgs} = await simport('@putout/cli-validate-args');
|
||||
|
||||
const error = await validateArgs(args, [
|
||||
...yargsOptions.boolean,
|
||||
...yargsOptions.string,
|
||||
]);
|
||||
|
||||
if (error)
|
||||
return exit(error);
|
||||
|
||||
if (args.repl)
|
||||
repl();
|
||||
|
||||
validate.columns(args.columns);
|
||||
validate.theme(args.theme);
|
||||
|
||||
port(args.port);
|
||||
|
||||
config('name', args.name);
|
||||
config('auth', args.auth);
|
||||
config('online', args.online);
|
||||
config('open', args.open);
|
||||
config('username', args.username);
|
||||
config('console', args.console);
|
||||
config('syncConsolePath', args.syncConsolePath);
|
||||
config('showDotFiles', args.showDotFiles);
|
||||
config('showFileName', args.showFileName);
|
||||
config('contact', args.contact);
|
||||
config('terminal', args.terminal);
|
||||
config('terminalPath', args.terminalPath);
|
||||
config('terminalCommand', args.terminalCommand);
|
||||
config('terminalAutoRestart', args.terminalAutoRestart);
|
||||
config('editor', args.editor);
|
||||
config('menu', args.menu);
|
||||
config('prefix', prefixer(args.prefix));
|
||||
config('prefixSocket', prefixer(args.prefixSocket));
|
||||
config('root', args.root || '/');
|
||||
config('vim', args.vim);
|
||||
config('theme', args.theme);
|
||||
config('columns', args.columns);
|
||||
config('log', args.log);
|
||||
config('confirmCopy', args.confirmCopy);
|
||||
config('confirmMove', args.confirmMove);
|
||||
config('oneFilePanel', args.oneFilePanel);
|
||||
config('configDialog', args.configDialog);
|
||||
config('configAuth', args.configAuth);
|
||||
config('keysPanel', args.keysPanel);
|
||||
config('export', args.export);
|
||||
config('exportToken', args.exportToken);
|
||||
config('import', args.import);
|
||||
config('importToken', args.importToken);
|
||||
config('importListen', args.importListen);
|
||||
config('importUrl', args.importUrl);
|
||||
|
||||
config('dropbox', args.dropbox);
|
||||
config('dropboxToken', args.dropboxToken);
|
||||
|
||||
await readConfig(args.config);
|
||||
|
||||
const options = {
|
||||
root: config('root'),
|
||||
editor: config('editor'),
|
||||
packer: config('packer'),
|
||||
prefix: config('prefix'),
|
||||
prefixSocket: config('prefixSocket'),
|
||||
columns: config('columns'),
|
||||
theme: config('theme'),
|
||||
menu: config('menu'),
|
||||
};
|
||||
|
||||
const password = env.parse('password') || args.password;
|
||||
|
||||
if (password)
|
||||
config('password', await getPassword(password));
|
||||
|
||||
validateRoot(options.root, config);
|
||||
|
||||
if (args.showConfig)
|
||||
await showConfig();
|
||||
|
||||
const {distributeImport} = await simport('../server/distribute/import.mjs');
|
||||
const importConfig = promisify(distributeImport);
|
||||
|
||||
await start(options, config);
|
||||
|
||||
if (args.save)
|
||||
config.write();
|
||||
|
||||
await tryToCatch(checkUpdate);
|
||||
await importConfig(config);
|
||||
}
|
||||
|
||||
function validateRoot(root, config) {
|
||||
validate.root(root, config);
|
||||
|
||||
if (root === '/')
|
||||
return;
|
||||
|
||||
console.log(`root: ${root}`);
|
||||
}
|
||||
|
||||
async function getPassword(password) {
|
||||
const criton = await simport('criton');
|
||||
return criton(password, config('algo'));
|
||||
}
|
||||
|
||||
function version() {
|
||||
console.log('v' + Info.version);
|
||||
}
|
||||
|
||||
async function start(options, config) {
|
||||
const SERVER = `${DIR_SERVER}server.mjs`;
|
||||
|
||||
if (!args.server)
|
||||
return;
|
||||
|
||||
const server = await simport(SERVER);
|
||||
server(options, config);
|
||||
}
|
||||
|
||||
function port(arg) {
|
||||
const number = parseInt(arg, 10);
|
||||
|
||||
if (!isNaN(number))
|
||||
return config('port', number);
|
||||
|
||||
exit('cloudcmd --port: should be a number');
|
||||
}
|
||||
|
||||
async function showConfig() {
|
||||
const show = await simport('../server/show-config');
|
||||
const data = show(config('*'));
|
||||
|
||||
console.log(data);
|
||||
}
|
||||
|
||||
async function readConfig(name) {
|
||||
if (!name)
|
||||
return;
|
||||
|
||||
const tryToCatch = await simport('try-to-catch');
|
||||
const forEachKey = await simport('for-each-key');
|
||||
|
||||
const [error, data] = await tryToCatch(simport, name);
|
||||
|
||||
if (error)
|
||||
return exit(error.message);
|
||||
|
||||
forEachKey(config, data);
|
||||
}
|
||||
|
||||
async function help() {
|
||||
const {default: bin} = await import('../json/help.json', {
|
||||
with: {
|
||||
type: 'json',
|
||||
},
|
||||
});
|
||||
|
||||
const forEachKey = await simport('for-each-key');
|
||||
const currify = await simport('currify');
|
||||
|
||||
const usage = 'Usage: cloudcmd [options]';
|
||||
const url = Info.homepage;
|
||||
const log = currify((a, b, c) => console.log(a, b, c));
|
||||
|
||||
console.log(usage);
|
||||
console.log('Options:');
|
||||
forEachKey(log(' %s %s'), bin);
|
||||
console.log('\nGeneral help using Cloud Commander: <%s>', url);
|
||||
}
|
||||
|
||||
function repl() {
|
||||
console.log('REPL mode enabled (telnet localhost 1337)');
|
||||
require(`${DIR_SERVER}repl`);
|
||||
}
|
||||
|
||||
async function checkUpdate() {
|
||||
const load = await simport('package-json');
|
||||
|
||||
const {version} = await load(Info.name, 'latest');
|
||||
await showUpdateInfo(version);
|
||||
}
|
||||
|
||||
async function showUpdateInfo(version) {
|
||||
if (version === Info.version)
|
||||
return;
|
||||
|
||||
const chalk = await simport('chalk');
|
||||
|
||||
const latestVersion = chalk.green.bold(`v${version}`);
|
||||
const latest = `update available: ${latestVersion}`;
|
||||
const current = chalk.dim(`(current: v${Info.version})`);
|
||||
|
||||
console.log('%s %s', latest, current);
|
||||
}
|
||||
75
bin/release.mjs
Executable file
75
bin/release.mjs
Executable file
|
|
@ -0,0 +1,75 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
import {promisify} from 'node:util';
|
||||
import process from 'node:process';
|
||||
import {tryToCatch} from 'try-to-catch';
|
||||
import {createSimport} from 'simport';
|
||||
import minor from 'minor';
|
||||
import _place from 'place';
|
||||
import rendy from 'rendy';
|
||||
import shortdate from 'shortdate';
|
||||
|
||||
const simport = createSimport(import.meta.url);
|
||||
const place = promisify(_place);
|
||||
|
||||
const Info = await simport('../package.json');
|
||||
|
||||
await main();
|
||||
|
||||
async function main() {
|
||||
const history = '## Version history\n\n';
|
||||
const link = '//github.com/coderaiser/cloudcmd/releases/tag/';
|
||||
const template = '- ' +
|
||||
'*{{ date }}*, ' +
|
||||
'**[v{{ version }}]' +
|
||||
'(' + link +
|
||||
'v{{ version }})**\n';
|
||||
|
||||
const {version} = Info;
|
||||
|
||||
const [error, versionNew] = await tryToCatch(cl);
|
||||
|
||||
if (error)
|
||||
return console.error(error);
|
||||
|
||||
await replaceVersion('README.md', version, versionNew);
|
||||
await replaceVersion('HELP.md', version, versionNew);
|
||||
|
||||
const historyNew = history + rendy(template, {
|
||||
date: shortdate(),
|
||||
version: versionNew,
|
||||
});
|
||||
|
||||
await replaceVersion('HELP.md', history, historyNew);
|
||||
}
|
||||
|
||||
async function replaceVersion(name, version, versionNew) {
|
||||
const [error] = await tryToCatch(place, name, version, versionNew);
|
||||
|
||||
if (error)
|
||||
return console.error(error);
|
||||
|
||||
console.log(`done: ${name}`);
|
||||
}
|
||||
|
||||
async function cl() {
|
||||
const {argv} = process;
|
||||
const length = argv.length - 1;
|
||||
const last = process.argv[length];
|
||||
const regExp = /^--(major|minor|patch)$/;
|
||||
const [, match] = last.match(regExp) || [];
|
||||
|
||||
console.log(last);
|
||||
|
||||
if (!regExp.test(last))
|
||||
throw Error('ERROR: version is missing. release --patch|--minor|--major');
|
||||
|
||||
return getVersionNew(last, match);
|
||||
}
|
||||
|
||||
function getVersionNew(last, match) {
|
||||
if (match)
|
||||
return minor(match, Info.version);
|
||||
|
||||
return last.substr(3);
|
||||
}
|
||||
425
client/client.mjs
Normal file
425
client/client.mjs
Normal file
|
|
@ -0,0 +1,425 @@
|
|||
import process from 'node:process';
|
||||
|
||||
/* global DOM */
|
||||
import Emitify from 'emitify';
|
||||
import inherits from 'inherits';
|
||||
import rendy from 'rendy';
|
||||
import load from 'load.js';
|
||||
import {tryToCatch} from 'try-to-catch';
|
||||
import {addSlashToEnd} from 'format-io';
|
||||
import pascalCase from 'just-pascal-case';
|
||||
import currify from 'currify';
|
||||
import * as Images from './dom/images.mjs';
|
||||
import {unregisterSW} from './sw/register.js';
|
||||
import {getJsonFromFileTable} from './get-json-from-file-table.mjs';
|
||||
import {Key} from './key/index.mjs';
|
||||
import {
|
||||
apiURL,
|
||||
formatMsg,
|
||||
buildFromJSON,
|
||||
} from '../common/cloudfunc.mjs';
|
||||
import {loadModule} from './load-module.mjs';
|
||||
|
||||
const noJS = (a) => a.replace(/.js$/, '');
|
||||
|
||||
const isDev = process.env.NODE_ENV === 'development';
|
||||
|
||||
inherits(CloudCmdProto, Emitify);
|
||||
|
||||
export const createCloudCmd = ({DOM, Listeners}) => {
|
||||
return new CloudCmdProto({
|
||||
DOM,
|
||||
Listeners,
|
||||
});
|
||||
};
|
||||
|
||||
load.addErrorListener((e, src) => {
|
||||
const msg = `file ${src} could not be loaded`;
|
||||
Images.show.error(msg);
|
||||
});
|
||||
|
||||
function CloudCmdProto({DOM, Listeners}) {
|
||||
Emitify.call(this);
|
||||
|
||||
const CloudCmd = this;
|
||||
const Info = DOM.CurrentInfo;
|
||||
|
||||
const {Storage, Files} = DOM;
|
||||
|
||||
this.log = () => {
|
||||
if (!isDev)
|
||||
return;
|
||||
};
|
||||
this.prefix = '';
|
||||
this.prefixSocket = '';
|
||||
this.prefixURL = '';
|
||||
|
||||
this.MIN_ONE_PANEL_WIDTH = DOM.getCSSVar('min-one-panel-width');
|
||||
this.HOST = location.origin || location.protocol + '//' + location.host;
|
||||
this.sort = {
|
||||
left: 'name',
|
||||
right: 'name',
|
||||
};
|
||||
|
||||
this.order = {
|
||||
left: 'asc',
|
||||
right: 'asc',
|
||||
};
|
||||
|
||||
this.changeDir = async (path, overrides = {}) => {
|
||||
const {
|
||||
isRefresh,
|
||||
panel,
|
||||
history = true,
|
||||
noCurrent,
|
||||
currentName,
|
||||
} = overrides;
|
||||
|
||||
const refresh = isRefresh;
|
||||
let panelChanged;
|
||||
|
||||
if (!noCurrent && panel && panel !== Info.panel) {
|
||||
DOM.changePanel();
|
||||
panelChanged = true;
|
||||
}
|
||||
|
||||
let imgPosition;
|
||||
|
||||
if (panelChanged || refresh || !history)
|
||||
imgPosition = 'top';
|
||||
|
||||
Images.show.load(imgPosition, panel);
|
||||
|
||||
/* загружаем содержимое каталога */
|
||||
await ajaxLoad(addSlashToEnd(path), {
|
||||
refresh,
|
||||
history,
|
||||
noCurrent,
|
||||
currentName,
|
||||
showDotFiles: CloudCmd.config('showDotFiles'),
|
||||
}, panel);
|
||||
};
|
||||
|
||||
/**
|
||||
* Конструктор CloudClient, который
|
||||
* выполняет весь функционал по
|
||||
* инициализации
|
||||
*/
|
||||
this.init = async (prefix, config) => {
|
||||
CloudCmd.prefix = prefix;
|
||||
CloudCmd.prefixURL = `${prefix}${apiURL}`;
|
||||
CloudCmd.prefixSocket = config.prefixSocket;
|
||||
CloudCmd.DIR_DIST = `${prefix}/dist`;
|
||||
CloudCmd.DIR_MODULES = `${this.DIR_DIST}/modules`;
|
||||
|
||||
CloudCmd.config = (key) => config[key];
|
||||
CloudCmd.config.if = currify((key, fn, a) => config[key] && fn(a));
|
||||
CloudCmd._config = (key, value) => {
|
||||
/*
|
||||
* should be called from config.js only
|
||||
* after successful update on server
|
||||
*/
|
||||
if (key === 'password')
|
||||
return;
|
||||
|
||||
config[key] = value;
|
||||
};
|
||||
|
||||
if (config.oneFilePanel)
|
||||
CloudCmd.MIN_ONE_PANEL_WIDTH = Infinity;
|
||||
|
||||
if (!document.body.scrollIntoViewIfNeeded)
|
||||
await load.js(`${CloudCmd.DIR_MODULES}/polyfill.js`);
|
||||
|
||||
await initModules();
|
||||
await baseInit();
|
||||
|
||||
CloudCmd.route(location.hash);
|
||||
};
|
||||
|
||||
this.route = (path) => {
|
||||
const query = path.split('/');
|
||||
|
||||
if (!path)
|
||||
return;
|
||||
|
||||
const [kebabModule] = query;
|
||||
const module = noJS(pascalCase(kebabModule.slice(1)));
|
||||
|
||||
const [, file] = query;
|
||||
const current = DOM.getCurrentByName(file);
|
||||
|
||||
if (file && !current) {
|
||||
const msg = formatMsg('set current file', file, 'error');
|
||||
CloudCmd.log(msg);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
DOM.setCurrentFile(current);
|
||||
CloudCmd.execFromModule(module, 'show');
|
||||
};
|
||||
|
||||
this.logOut = async () => {
|
||||
const url = CloudCmd.prefix + '/logout';
|
||||
const error = () => document.location.reload();
|
||||
const {prefix} = CloudCmd;
|
||||
|
||||
await DOM.Storage.clear();
|
||||
unregisterSW(prefix);
|
||||
DOM.load.ajax({
|
||||
url,
|
||||
error,
|
||||
});
|
||||
};
|
||||
|
||||
const initModules = async () => {
|
||||
CloudCmd.Key = Key;
|
||||
CloudCmd.Key.bind();
|
||||
|
||||
const [, modules] = await tryToCatch(Files.get, 'modules');
|
||||
const showLoad = Images.show.load;
|
||||
|
||||
const doBefore = {
|
||||
edit: showLoad,
|
||||
menu: showLoad,
|
||||
};
|
||||
|
||||
const load = (name, path, dobefore) => {
|
||||
loadModule({
|
||||
name,
|
||||
path,
|
||||
dobefore,
|
||||
});
|
||||
};
|
||||
|
||||
if (!modules)
|
||||
return;
|
||||
|
||||
for (const module of modules.local) {
|
||||
load(null, module, doBefore[module]);
|
||||
}
|
||||
};
|
||||
|
||||
async function saveCurrentName(currentName) {
|
||||
await Storage.set('current-name', currentName);
|
||||
}
|
||||
|
||||
async function baseInit() {
|
||||
const files = DOM.getFiles();
|
||||
|
||||
CloudCmd.on('current-file', DOM.updateCurrentInfo);
|
||||
CloudCmd.on('current-name', saveCurrentName);
|
||||
|
||||
const name = await Storage.get('current-name');
|
||||
const currentFile = name && DOM.getCurrentByName(name) || files[0];
|
||||
|
||||
/* выделяем строку с первым файлом */
|
||||
if (files)
|
||||
DOM.setCurrentFile(currentFile, {
|
||||
// when hash is present
|
||||
// it should be handled with this.route
|
||||
// overwre otherwise
|
||||
history: !location.hash,
|
||||
});
|
||||
|
||||
const dirPath = DOM.getCurrentDirPath();
|
||||
|
||||
Listeners.init();
|
||||
|
||||
const panels = getPanels();
|
||||
panels.forEach(Listeners.setOnPanel);
|
||||
|
||||
Listeners.initKeysPanel();
|
||||
|
||||
if (!CloudCmd.config('dirStorage'))
|
||||
return;
|
||||
|
||||
const data = await Storage.get(dirPath);
|
||||
|
||||
if (!data)
|
||||
await Storage.setJson(dirPath, getJsonFromFileTable());
|
||||
}
|
||||
|
||||
function getPanels() {
|
||||
const panels = ['left'];
|
||||
|
||||
if (CloudCmd.config('oneFilePanel'))
|
||||
return panels;
|
||||
|
||||
return [
|
||||
...panels,
|
||||
'right',
|
||||
];
|
||||
}
|
||||
|
||||
this.execFromModule = async (moduleName, funcName, ...args) => {
|
||||
await CloudCmd[moduleName]();
|
||||
|
||||
const func = CloudCmd[moduleName][funcName];
|
||||
func(...args);
|
||||
};
|
||||
|
||||
this.refresh = async (options = {}) => {
|
||||
const {panel = Info.panel, currentName} = options;
|
||||
|
||||
const path = DOM.getCurrentDirPath(panel);
|
||||
|
||||
const isRefresh = true;
|
||||
const history = false;
|
||||
const noCurrent = options?.noCurrent;
|
||||
|
||||
await CloudCmd.changeDir(path, {
|
||||
isRefresh,
|
||||
history,
|
||||
panel,
|
||||
noCurrent,
|
||||
currentName,
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Функция загружает json-данные о Файловой Системе
|
||||
* через ajax-запрос.
|
||||
* @param path - каталог для чтения
|
||||
* @param options
|
||||
* { refresh, history } - необходимость обновить данные о каталоге
|
||||
* @param panel
|
||||
*
|
||||
*/
|
||||
async function ajaxLoad(path, options = {}, panel) {
|
||||
const {RESTful} = DOM;
|
||||
|
||||
CloudCmd.log(`reading dir: "${path}";`);
|
||||
|
||||
const dirStorage = CloudCmd.config('dirStorage');
|
||||
const json = dirStorage && await Storage.getJson(path);
|
||||
|
||||
const name = options.currentName || Info.name;
|
||||
const {noCurrent, refresh} = options;
|
||||
|
||||
if (!refresh && json)
|
||||
return await createFileTable(json, panel, options);
|
||||
|
||||
const position = DOM.getPanelPosition(panel);
|
||||
const sort = CloudCmd.sort[position];
|
||||
const order = CloudCmd.order[position];
|
||||
|
||||
const query = rendy('?sort={{ sort }}&order={{ order }}', {
|
||||
sort,
|
||||
order,
|
||||
});
|
||||
|
||||
const [, newObj] = await RESTful.read(path + query, 'json');
|
||||
|
||||
if (!newObj)
|
||||
// that's OK, error handled by RESTful
|
||||
return;
|
||||
|
||||
options.sort = sort;
|
||||
options.order = order;
|
||||
|
||||
await createFileTable(newObj, panel, options);
|
||||
|
||||
if (refresh && !noCurrent)
|
||||
DOM.setCurrentByName(name);
|
||||
|
||||
if (!CloudCmd.config('dirStorage'))
|
||||
return;
|
||||
|
||||
Storage.setJson(path, newObj);
|
||||
}
|
||||
|
||||
/**
|
||||
* Функция строит файловую таблицу
|
||||
* @param data - данные о файлах
|
||||
* @param panelParam
|
||||
* @param options - history, noCurrent, showDotFiles
|
||||
*/
|
||||
async function createFileTable(data, panelParam, options) {
|
||||
const {
|
||||
history,
|
||||
noCurrent,
|
||||
showDotFiles,
|
||||
} = options;
|
||||
|
||||
const names = [
|
||||
'file',
|
||||
'path',
|
||||
'link',
|
||||
'pathLink',
|
||||
];
|
||||
|
||||
const [error, [file, path, link, pathLink]] = await tryToCatch(Files.get, names);
|
||||
|
||||
if (error)
|
||||
return DOM.Dialog.alert(error.responseText);
|
||||
|
||||
const panel = panelParam || DOM.getPanel();
|
||||
const {prefix} = CloudCmd;
|
||||
|
||||
const {dir, name} = Info;
|
||||
|
||||
const {childNodes} = panel;
|
||||
let i = childNodes.length;
|
||||
|
||||
while (i--)
|
||||
panel.removeChild(panel.lastChild);
|
||||
|
||||
panel.innerHTML = buildFromJSON({
|
||||
sort: options.sort,
|
||||
order: options.order,
|
||||
data,
|
||||
id: panel.id,
|
||||
prefix,
|
||||
showDotFiles,
|
||||
template: {
|
||||
file,
|
||||
path,
|
||||
pathLink,
|
||||
link,
|
||||
},
|
||||
});
|
||||
|
||||
Listeners.setOnPanel(panel);
|
||||
|
||||
if (!noCurrent) {
|
||||
let current;
|
||||
|
||||
if (name === '..' && dir !== '/')
|
||||
current = DOM.getCurrentByName(dir);
|
||||
|
||||
if (!current)
|
||||
[current] = DOM.getFiles(panel);
|
||||
|
||||
DOM.setCurrentFile(current, {
|
||||
history,
|
||||
});
|
||||
|
||||
CloudCmd.emit('active-dir', Info.dirPath);
|
||||
}
|
||||
}
|
||||
|
||||
this.goToParentDir = async () => {
|
||||
const {
|
||||
dir,
|
||||
dirPath,
|
||||
parentDirPath,
|
||||
panel,
|
||||
} = Info;
|
||||
|
||||
if (dirPath === parentDirPath)
|
||||
return;
|
||||
|
||||
const path = parentDirPath;
|
||||
|
||||
await CloudCmd.changeDir(path);
|
||||
|
||||
const current = DOM.getCurrentByName(dir);
|
||||
const [first] = DOM.getFiles(panel);
|
||||
|
||||
DOM.setCurrentFile(current || first, {
|
||||
history,
|
||||
});
|
||||
};
|
||||
}
|
||||
74
client/cloudcmd.mjs
Normal file
74
client/cloudcmd.mjs
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
import process from 'node:process';
|
||||
import wraptile from 'wraptile';
|
||||
import load from 'load.js';
|
||||
import '../css/main.css';
|
||||
import {registerSW, listenSW} from './sw/register.js';
|
||||
import {initSortPanel, sortPanel} from './sort.mjs';
|
||||
import Util from '../common/util.js';
|
||||
import * as CloudFunc from '../common/cloudfunc.mjs';
|
||||
import DOM from './dom/index.js';
|
||||
import {createCloudCmd} from './client.mjs';
|
||||
import * as Listeners from './listeners/index.js';
|
||||
|
||||
const isDev = process.env.NODE_ENV === 'development';
|
||||
|
||||
export default init;
|
||||
|
||||
globalThis.CloudCmd = init;
|
||||
|
||||
async function init(config) {
|
||||
globalThis.CloudCmd = createCloudCmd({
|
||||
DOM,
|
||||
Listeners,
|
||||
});
|
||||
globalThis.DOM = DOM;
|
||||
globalThis.Util = Util;
|
||||
globalThis.CloudFunc = CloudFunc;
|
||||
|
||||
await register(config);
|
||||
|
||||
initSortPanel();
|
||||
globalThis.CloudCmd.sortPanel = sortPanel;
|
||||
const prefix = getPrefix(config.prefix);
|
||||
|
||||
globalThis.CloudCmd.init(prefix, config);
|
||||
|
||||
if (globalThis.CloudCmd.config('menu') === 'aleman')
|
||||
setTimeout(() => {
|
||||
import('https://esm.sh/@putout/processor-html');
|
||||
import('https://esm.sh/@putout/bundle');
|
||||
}, 100);
|
||||
}
|
||||
|
||||
function getPrefix(prefix) {
|
||||
if (!prefix)
|
||||
return '';
|
||||
|
||||
if (!prefix.indexOf('/'))
|
||||
return prefix;
|
||||
|
||||
return `/${prefix}`;
|
||||
}
|
||||
|
||||
const onUpdateFound = wraptile(async (config) => {
|
||||
if (isDev)
|
||||
return;
|
||||
|
||||
const {DOM} = globalThis;
|
||||
const prefix = getPrefix(config.prefix);
|
||||
|
||||
await load.js(`${prefix}/dist/cloudcmd.common.js`);
|
||||
await load.js(`${prefix}/dist/cloudcmd.js`);
|
||||
|
||||
console.log('cloudcmd: sw: updated');
|
||||
|
||||
DOM.Events.removeAll();
|
||||
globalThis.CloudCmd(config);
|
||||
});
|
||||
|
||||
async function register(config) {
|
||||
const {prefix} = config;
|
||||
const sw = await registerSW(prefix);
|
||||
|
||||
listenSW(sw, 'updatefound', onUpdateFound(config));
|
||||
}
|
||||
124
client/dom/buffer.mjs
Normal file
124
client/dom/buffer.mjs
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
/* global CloudCmd*/
|
||||
import tryToPromiseAll from '../../common/try-to-promise-all.js';
|
||||
import Storage from './storage.js';
|
||||
|
||||
const CLASS = 'cut-file';
|
||||
const COPY = 'copy';
|
||||
const CUT = 'cut';
|
||||
|
||||
function showMessage(msg) {
|
||||
globalThis.DOM.Dialog.alert(msg);
|
||||
}
|
||||
|
||||
function getNames() {
|
||||
const {DOM} = globalThis;
|
||||
const files = DOM.getActiveFiles();
|
||||
|
||||
return DOM.getFilenames(files);
|
||||
}
|
||||
|
||||
function addCutClass() {
|
||||
const {DOM} = globalThis;
|
||||
const files = DOM.getActiveFiles();
|
||||
|
||||
for (const element of files) {
|
||||
element.classList.add(CLASS);
|
||||
}
|
||||
}
|
||||
|
||||
function rmCutClass() {
|
||||
const {DOM} = globalThis;
|
||||
const files = DOM.getByClassAll(CLASS);
|
||||
|
||||
for (const element of files) {
|
||||
element.classList.remove(CLASS);
|
||||
}
|
||||
}
|
||||
|
||||
const checkEnabled = (fn) => () => {
|
||||
const is = CloudCmd.config('buffer');
|
||||
|
||||
if (is)
|
||||
return fn();
|
||||
|
||||
showMessage('Buffer disabled in config!');
|
||||
};
|
||||
|
||||
async function readBuffer() {
|
||||
const [e, cp, ct] = await tryToPromiseAll([
|
||||
Storage.getJson(COPY),
|
||||
Storage.getJson(CUT),
|
||||
]);
|
||||
|
||||
return [
|
||||
e,
|
||||
cp,
|
||||
ct,
|
||||
];
|
||||
}
|
||||
|
||||
export const copy = checkEnabled(async () => {
|
||||
const Info = globalThis.DOM.CurrentInfo;
|
||||
const names = getNames();
|
||||
const from = Info.dirPath;
|
||||
|
||||
await clear();
|
||||
|
||||
if (!names.length)
|
||||
return;
|
||||
|
||||
await Storage.remove(CUT);
|
||||
await Storage.setJson(COPY, {
|
||||
from,
|
||||
names,
|
||||
});
|
||||
});
|
||||
|
||||
export const cut = checkEnabled(async () => {
|
||||
const Info = globalThis.DOM.CurrentInfo;
|
||||
const names = getNames();
|
||||
const from = Info.dirPath;
|
||||
|
||||
await clear();
|
||||
|
||||
if (!names.length)
|
||||
return;
|
||||
|
||||
addCutClass();
|
||||
|
||||
await Storage.setJson(CUT, {
|
||||
from,
|
||||
names,
|
||||
});
|
||||
});
|
||||
|
||||
export const clear = checkEnabled(async () => {
|
||||
await Storage.remove(COPY);
|
||||
await Storage.remove(CUT);
|
||||
|
||||
rmCutClass();
|
||||
});
|
||||
|
||||
export const paste = checkEnabled(async () => {
|
||||
const Info = globalThis.DOM.CurrentInfo;
|
||||
const [error, cp, ct] = await readBuffer();
|
||||
|
||||
if (error || !cp && !ct)
|
||||
return showMessage(error || 'Buffer is empty!');
|
||||
|
||||
const opStr = cp ? 'copy' : 'move';
|
||||
const data = cp || ct;
|
||||
const {Operation} = CloudCmd;
|
||||
const msg = 'Path is same!';
|
||||
const to = Info.dirPath;
|
||||
|
||||
if (data.from === to)
|
||||
return showMessage(msg);
|
||||
|
||||
Operation.show(opStr, {
|
||||
...data,
|
||||
to,
|
||||
});
|
||||
|
||||
await clear();
|
||||
});
|
||||
310
client/dom/current-file.mjs
Normal file
310
client/dom/current-file.mjs
Normal file
|
|
@ -0,0 +1,310 @@
|
|||
/* global DOM */
|
||||
/* global CloudCmd */
|
||||
import createElement from '@cloudcmd/create-element';
|
||||
import {encode, decode} from '../../common/entity.js';
|
||||
import {getTitle, FS} from '../../common/cloudfunc.mjs';
|
||||
|
||||
let Title;
|
||||
|
||||
const CURRENT_FILE = 'current-file';
|
||||
const encodeNBSP = (a) => a?.replace('\xa0', ' ');
|
||||
const decodeNBSP = (a) => a?.replace(' ', '\xa0');
|
||||
|
||||
export const _CURRENT_FILE = CURRENT_FILE;
|
||||
|
||||
/**
|
||||
* set name from current (or param) file
|
||||
*
|
||||
* @param name
|
||||
* @param current
|
||||
*/
|
||||
export const setCurrentName = (name, current) => {
|
||||
const Info = DOM.CurrentInfo;
|
||||
const {link} = Info;
|
||||
const {prefix} = CloudCmd;
|
||||
const dir = prefix + FS + Info.dirPath;
|
||||
const encoded = encode(name);
|
||||
|
||||
link.title = encoded;
|
||||
link.href = dir + encoded;
|
||||
link.innerHTML = encoded;
|
||||
|
||||
current.setAttribute('data-name', createNameAttribute(name));
|
||||
CloudCmd.emit('current-file', current);
|
||||
|
||||
return link;
|
||||
};
|
||||
|
||||
/**
|
||||
* get name from current (or param) file
|
||||
*
|
||||
* @param currentFile
|
||||
*/
|
||||
export const getCurrentName = (currentFile) => {
|
||||
const current = currentFile || DOM.getCurrentFile();
|
||||
|
||||
if (!current)
|
||||
return '';
|
||||
|
||||
return parseNameAttribute(current.getAttribute('data-name'));
|
||||
};
|
||||
|
||||
/**
|
||||
* Generate a `data-name` attribute for the given filename
|
||||
* @param name The string name to encode
|
||||
*/
|
||||
const createNameAttribute = (name) => {
|
||||
const encoded = btoa(encodeURI(name));
|
||||
return `js-file-${encoded}`;
|
||||
};
|
||||
|
||||
/**
|
||||
* Parse a `data-name` attribute string back into the original filename
|
||||
* @param attribute The string we wish to decode
|
||||
*/
|
||||
const parseNameAttribute = (attribute) => {
|
||||
attribute = attribute.replace('js-file-', '');
|
||||
return decodeNBSP(decodeURI(atob(attribute)));
|
||||
};
|
||||
|
||||
export const _parseNameAttribute = parseNameAttribute;
|
||||
|
||||
const parseHrefAttribute = (prefix, attribute) => {
|
||||
attribute = attribute.replace(RegExp('^' + prefix + FS), '');
|
||||
return decode(decodeNBSP(attribute));
|
||||
};
|
||||
|
||||
export const _parseHrefAttribute = parseHrefAttribute;
|
||||
|
||||
/**
|
||||
* get current direcotory path
|
||||
*/
|
||||
export const getCurrentDirPath = (panel = DOM.getPanel()) => {
|
||||
const path = DOM.getByDataName('js-path', panel);
|
||||
return path.textContent;
|
||||
};
|
||||
|
||||
/**
|
||||
* get link from current (or param) file
|
||||
*
|
||||
* @param currentFile - current file by default
|
||||
*/
|
||||
export const getCurrentPath = (currentFile) => {
|
||||
const current = currentFile || DOM.getCurrentFile();
|
||||
const [element] = DOM.getByTag('a', current);
|
||||
const {prefix} = CloudCmd;
|
||||
|
||||
return parseHrefAttribute(prefix, element.getAttribute('href'));
|
||||
};
|
||||
|
||||
/**
|
||||
* get current direcotory name
|
||||
*/
|
||||
export const getCurrentDirName = () => {
|
||||
const href = DOM
|
||||
.getCurrentDirPath()
|
||||
.replace(/\/$/, '');
|
||||
|
||||
const substr = href.substr(href, href.lastIndexOf('/'));
|
||||
|
||||
return href.replace(`${substr}/`, '') || '/';
|
||||
};
|
||||
|
||||
/**
|
||||
* get current direcotory path
|
||||
*/
|
||||
export const getParentDirPath = (panel) => {
|
||||
const path = DOM.getCurrentDirPath(panel);
|
||||
const dirName = DOM.getCurrentDirName() + '/';
|
||||
const index = path.lastIndexOf(dirName);
|
||||
|
||||
if (path === '/')
|
||||
return path;
|
||||
|
||||
return path.slice(0, index);
|
||||
};
|
||||
|
||||
/**
|
||||
* get not current direcotory path
|
||||
*/
|
||||
export const getNotCurrentDirPath = () => {
|
||||
const panel = DOM.getPanel({
|
||||
active: false,
|
||||
});
|
||||
|
||||
return DOM.getCurrentDirPath(panel);
|
||||
};
|
||||
|
||||
/**
|
||||
* unified way to get current file
|
||||
*
|
||||
* @currentFile
|
||||
*/
|
||||
export const getCurrentFile = () => {
|
||||
return DOM.getByClass(CURRENT_FILE);
|
||||
};
|
||||
|
||||
/**
|
||||
* get current file by name
|
||||
*/
|
||||
export const getCurrentByName = (name, panel = DOM.CurrentInfo.panel) => {
|
||||
const dataName = 'js-file-' + btoa(encodeURI(encodeNBSP(name)));
|
||||
return DOM.getByDataName(dataName, panel);
|
||||
};
|
||||
|
||||
/**
|
||||
* private function thet unset currentfile
|
||||
*
|
||||
* @currentFile
|
||||
*/
|
||||
function unsetCurrentFile(currentFile) {
|
||||
const is = DOM.isCurrentFile(currentFile);
|
||||
|
||||
if (!is)
|
||||
return;
|
||||
|
||||
currentFile.classList.remove(CURRENT_FILE);
|
||||
}
|
||||
|
||||
/**
|
||||
* unified way to set current file
|
||||
*/
|
||||
export const setCurrentFile = (currentFile, options) => {
|
||||
const o = options;
|
||||
const currentFileWas = DOM.getCurrentFile();
|
||||
|
||||
if (!currentFile)
|
||||
return DOM;
|
||||
|
||||
let pathWas = '';
|
||||
|
||||
if (currentFileWas) {
|
||||
pathWas = DOM.getCurrentDirPath();
|
||||
unsetCurrentFile(currentFileWas);
|
||||
}
|
||||
|
||||
currentFile.classList.add(CURRENT_FILE);
|
||||
|
||||
const path = DOM.getCurrentDirPath();
|
||||
const name = CloudCmd.config('name');
|
||||
|
||||
if (path !== pathWas) {
|
||||
DOM.setTitle(getTitle({
|
||||
name,
|
||||
path,
|
||||
}));
|
||||
|
||||
/* history could be present
|
||||
* but it should be false
|
||||
* to prevent default behavior
|
||||
*/
|
||||
if (!o || o.history) {
|
||||
const historyPath = path === '/' ? path : FS + path;
|
||||
DOM.setHistory(historyPath, null, historyPath);
|
||||
}
|
||||
}
|
||||
|
||||
/* scrolling to current file */
|
||||
const CENTER = true;
|
||||
|
||||
DOM.scrollIntoViewIfNeeded(currentFile, CENTER);
|
||||
|
||||
CloudCmd.emit('current-file', currentFile);
|
||||
CloudCmd.emit('current-path', path);
|
||||
CloudCmd.emit('current-name', DOM.getCurrentName(currentFile));
|
||||
|
||||
return DOM;
|
||||
};
|
||||
|
||||
export const setCurrentByName = (name) => {
|
||||
const current = DOM.getCurrentByName(name);
|
||||
return DOM.setCurrentFile(current);
|
||||
};
|
||||
|
||||
/*
|
||||
* set current file by position
|
||||
*
|
||||
* @param layer - element
|
||||
* @param - position {x, y}
|
||||
*/
|
||||
export const getCurrentByPosition = ({x, y}) => {
|
||||
const element = document.elementFromPoint(x, y);
|
||||
|
||||
const getEl = (el) => {
|
||||
const {tagName} = el;
|
||||
const isChild = /A|SPAN|LI/.test(tagName);
|
||||
|
||||
if (!isChild)
|
||||
return null;
|
||||
|
||||
if (tagName === 'A')
|
||||
return el.parentElement.parentElement;
|
||||
|
||||
if (tagName === 'SPAN')
|
||||
return el.parentElement;
|
||||
|
||||
return el;
|
||||
};
|
||||
|
||||
const el = getEl(element);
|
||||
|
||||
if (el && el.tagName !== 'LI')
|
||||
return null;
|
||||
|
||||
return el;
|
||||
};
|
||||
|
||||
/**
|
||||
* current file check
|
||||
*
|
||||
* @param currentFile
|
||||
*/
|
||||
export const isCurrentFile = (currentFile) => {
|
||||
if (!currentFile)
|
||||
return false;
|
||||
|
||||
return DOM.isContainClass(currentFile, CURRENT_FILE);
|
||||
};
|
||||
|
||||
/**
|
||||
* set title or create title element
|
||||
*
|
||||
* @param name
|
||||
*/
|
||||
export const setTitle = (name) => {
|
||||
if (!Title)
|
||||
Title = DOM.getByTag('title')[0] || createElement('title', {
|
||||
innerHTML: name,
|
||||
parent: document.head,
|
||||
});
|
||||
|
||||
Title.textContent = name;
|
||||
|
||||
return DOM;
|
||||
};
|
||||
|
||||
/**
|
||||
* check is current file is a directory
|
||||
*
|
||||
* @param currentFile
|
||||
*/
|
||||
export const isCurrentIsDir = (currentFile) => {
|
||||
const current = currentFile || DOM.getCurrentFile();
|
||||
const path = DOM.getCurrentPath(current);
|
||||
const fileType = DOM.getCurrentType(current);
|
||||
|
||||
const isZip = path.endsWith('.zip');
|
||||
const isDir = /^directory(-link)?/.test(fileType);
|
||||
|
||||
return isDir || isZip;
|
||||
};
|
||||
|
||||
export const getCurrentType = (currentFile) => {
|
||||
const current = currentFile || DOM.getCurrentFile();
|
||||
const el = DOM.getByDataName('js-type', current);
|
||||
const type = el.className
|
||||
.split(' ')
|
||||
.pop();
|
||||
|
||||
return type;
|
||||
};
|
||||
307
client/dom/current-file.spec.mjs
Normal file
307
client/dom/current-file.spec.mjs
Normal file
|
|
@ -0,0 +1,307 @@
|
|||
import {test, stub} from 'supertape';
|
||||
import {create} from 'auto-globals';
|
||||
import wraptile from 'wraptile';
|
||||
import * as currentFile from './current-file.mjs';
|
||||
|
||||
const id = (a) => a;
|
||||
|
||||
const returns = wraptile(id);
|
||||
const {_CURRENT_FILE} = currentFile;
|
||||
|
||||
test('current-file: setCurrentName: setAttribute', (t) => {
|
||||
const {DOM, CloudCmd} = globalThis;
|
||||
|
||||
globalThis.DOM = getDOM();
|
||||
globalThis.CloudCmd = getCloudCmd();
|
||||
|
||||
const current = create();
|
||||
const {setAttribute} = current;
|
||||
|
||||
currentFile.setCurrentName('hello', current);
|
||||
|
||||
t.calledWith(setAttribute, ['data-name', 'js-file-aGVsbG8='], 'should call setAttribute');
|
||||
|
||||
globalThis.DOM = DOM;
|
||||
globalThis.CloudCmd = CloudCmd;
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('current-file: setCurrentName: setAttribute: cyrillic', (t) => {
|
||||
const {DOM, CloudCmd} = globalThis;
|
||||
|
||||
globalThis.DOM = getDOM();
|
||||
globalThis.CloudCmd = getCloudCmd();
|
||||
|
||||
const current = create();
|
||||
const {setAttribute} = current;
|
||||
|
||||
currentFile.setCurrentName('ай', current);
|
||||
|
||||
t.calledWith(setAttribute, ['data-name', 'js-file-JUQwJUIwJUQwJUI5'], 'should call setAttribute');
|
||||
|
||||
globalThis.DOM = DOM;
|
||||
globalThis.CloudCmd = CloudCmd;
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('current-file: getCurrentName', (t) => {
|
||||
const current = create();
|
||||
current.getAttribute.returns('js-file-Ymlu');
|
||||
|
||||
const result = currentFile.getCurrentName(current);
|
||||
|
||||
t.equal(result, 'bin');
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('current-file: emit', (t) => {
|
||||
const {DOM, CloudCmd} = globalThis;
|
||||
|
||||
const emit = stub();
|
||||
|
||||
globalThis.DOM = getDOM();
|
||||
globalThis.CloudCmd = getCloudCmd({
|
||||
emit,
|
||||
});
|
||||
|
||||
const current = create();
|
||||
|
||||
currentFile.setCurrentName('hello', current);
|
||||
|
||||
t.calledWith(emit, ['current-file', current], 'should call emit');
|
||||
|
||||
globalThis.DOM = DOM;
|
||||
globalThis.CloudCmd = CloudCmd;
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('current-file: setCurrentName: return', (t) => {
|
||||
const {DOM, CloudCmd} = globalThis;
|
||||
|
||||
const link = {};
|
||||
|
||||
globalThis.DOM = getDOM({
|
||||
link,
|
||||
});
|
||||
|
||||
globalThis.CloudCmd = getCloudCmd();
|
||||
|
||||
const current = create();
|
||||
|
||||
const result = currentFile.setCurrentName('hello', current);
|
||||
|
||||
t.equal(result, link, 'should return link');
|
||||
|
||||
globalThis.DOM = DOM;
|
||||
globalThis.CloudCmd = CloudCmd;
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('current-file: getParentDirPath: result', (t) => {
|
||||
const {DOM} = globalThis;
|
||||
|
||||
const getCurrentDirPath = returns('/D/Films/+++favorite films/');
|
||||
const getCurrentDirName = returns('+++favorite films');
|
||||
|
||||
globalThis.DOM = getDOM({
|
||||
getCurrentDirPath,
|
||||
getCurrentDirName,
|
||||
});
|
||||
|
||||
const result = currentFile.getParentDirPath();
|
||||
const expected = '/D/Films/';
|
||||
|
||||
globalThis.DOM = DOM;
|
||||
|
||||
t.equal(result, expected, 'should return parent dir path');
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('current-file: isCurrentFile: no', (t) => {
|
||||
const {DOM, CloudCmd} = globalThis;
|
||||
|
||||
globalThis.DOM = getDOM();
|
||||
globalThis.CloudCmd = getCloudCmd();
|
||||
|
||||
const result = currentFile.isCurrentFile();
|
||||
|
||||
globalThis.DOM = DOM;
|
||||
globalThis.CloudCmd = CloudCmd;
|
||||
|
||||
t.notOk(result);
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('current-file: isCurrentFile', (t) => {
|
||||
const {DOM, CloudCmd} = globalThis;
|
||||
|
||||
const isContainClass = stub();
|
||||
|
||||
globalThis.DOM = getDOM({
|
||||
isContainClass,
|
||||
});
|
||||
|
||||
globalThis.CloudCmd = getCloudCmd();
|
||||
|
||||
const current = {};
|
||||
currentFile.isCurrentFile(current);
|
||||
|
||||
globalThis.DOM = DOM;
|
||||
globalThis.CloudCmd = CloudCmd;
|
||||
|
||||
t.calledWith(isContainClass, [current, _CURRENT_FILE], 'should call isContainClass');
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('current-file: getCurrentType', (t) => {
|
||||
const {DOM, CloudCmd} = globalThis;
|
||||
|
||||
globalThis.DOM = getDOM();
|
||||
globalThis.CloudCmd = getCloudCmd();
|
||||
|
||||
const {getByDataName} = globalThis.DOM;
|
||||
|
||||
getByDataName.returns({
|
||||
className: 'mini-icon directory',
|
||||
});
|
||||
|
||||
const current = create();
|
||||
|
||||
currentFile.getCurrentType(current);
|
||||
|
||||
globalThis.DOM = DOM;
|
||||
globalThis.CloudCmd = CloudCmd;
|
||||
|
||||
t.calledWith(getByDataName, ['js-type', current]);
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('current-file: isCurrentIsDir: getCurrentType', (t) => {
|
||||
const {DOM, CloudCmd} = globalThis;
|
||||
|
||||
globalThis.DOM = getDOM();
|
||||
globalThis.CloudCmd = getCloudCmd();
|
||||
|
||||
const {getCurrentType} = globalThis.DOM;
|
||||
|
||||
const current = create();
|
||||
|
||||
currentFile.isCurrentIsDir(current);
|
||||
|
||||
globalThis.DOM = DOM;
|
||||
globalThis.CloudCmd = CloudCmd;
|
||||
|
||||
t.calledWith(getCurrentType, [current]);
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('current-file: isCurrentIsDir: directory', (t) => {
|
||||
const {DOM, CloudCmd} = globalThis;
|
||||
|
||||
globalThis.DOM = getDOM({
|
||||
getCurrentType: stub().returns('directory'),
|
||||
});
|
||||
|
||||
globalThis.CloudCmd = getCloudCmd();
|
||||
|
||||
const current = create();
|
||||
|
||||
const result = currentFile.isCurrentIsDir(current);
|
||||
|
||||
globalThis.DOM = DOM;
|
||||
globalThis.CloudCmd = CloudCmd;
|
||||
|
||||
t.ok(result);
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('current-file: isCurrentIsDir: directory-link', (t) => {
|
||||
const {DOM, CloudCmd} = globalThis;
|
||||
|
||||
globalThis.DOM = getDOM({
|
||||
getCurrentType: stub().returns('directory-link'),
|
||||
});
|
||||
|
||||
globalThis.CloudCmd = getCloudCmd();
|
||||
|
||||
const current = create();
|
||||
|
||||
const result = currentFile.isCurrentIsDir(current);
|
||||
|
||||
globalThis.DOM = DOM;
|
||||
globalThis.CloudCmd = CloudCmd;
|
||||
|
||||
t.ok(result);
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('current-file: isCurrentIsDir: file', (t) => {
|
||||
const {DOM, CloudCmd} = globalThis;
|
||||
|
||||
globalThis.DOM = getDOM({
|
||||
getCurrentType: stub().returns('file'),
|
||||
});
|
||||
|
||||
globalThis.CloudCmd = getCloudCmd();
|
||||
|
||||
const current = create();
|
||||
|
||||
const result = currentFile.isCurrentIsDir(current);
|
||||
|
||||
globalThis.DOM = DOM;
|
||||
globalThis.CloudCmd = CloudCmd;
|
||||
|
||||
t.notOk(result);
|
||||
t.end();
|
||||
});
|
||||
|
||||
const getCloudCmd = ({emit} = {}) => ({
|
||||
prefix: '',
|
||||
emit: emit || stub(),
|
||||
});
|
||||
|
||||
test('current-file: parseNameAttribute', (t) => {
|
||||
const result = currentFile._parseNameAttribute('js-file-aGVsbG8mbmJzcDt3b3JsZA==');
|
||||
const expected = 'hello\xa0world';
|
||||
|
||||
t.equal(result, expected);
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('current-file: parseHrefAttribute', (t) => {
|
||||
const prefix = '/api/v1';
|
||||
const result = currentFile._parseHrefAttribute(prefix, '/api/v1/fs/hello world');
|
||||
const expected = '/hello\xa0world';
|
||||
|
||||
t.equal(result, expected);
|
||||
t.end();
|
||||
});
|
||||
|
||||
function getDOM(overrides = {}) {
|
||||
const {
|
||||
link = {},
|
||||
getCurrentDirPath = stub(),
|
||||
getCurrentDirName = stub(),
|
||||
getByDataName = stub(),
|
||||
isContainClass = stub(),
|
||||
getCurrentType = stub(),
|
||||
getCurrentPath = stub().returns(''),
|
||||
} = overrides;
|
||||
|
||||
return {
|
||||
getCurrentDirPath,
|
||||
getCurrentDirName,
|
||||
getCurrentPath,
|
||||
getByDataName,
|
||||
isContainClass,
|
||||
getCurrentType,
|
||||
CurrentInfo: {
|
||||
link,
|
||||
dirPath: '/',
|
||||
},
|
||||
};
|
||||
}
|
||||
26
client/dom/dialog.js
Normal file
26
client/dom/dialog.js
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
'use strict';
|
||||
|
||||
const {tryToCatch} = require('try-to-catch');
|
||||
|
||||
const {
|
||||
alert,
|
||||
prompt,
|
||||
confirm,
|
||||
progress,
|
||||
} = require('smalltalk');
|
||||
|
||||
const title = 'Cloud Commander';
|
||||
|
||||
module.exports.alert = (...a) => alert(title, ...a, {
|
||||
cancel: false,
|
||||
});
|
||||
|
||||
module.exports.prompt = (...a) => tryToCatch(prompt, title, ...a);
|
||||
module.exports.confirm = (...a) => tryToCatch(confirm, title, ...a);
|
||||
module.exports.progress = (...a) => progress(title, ...a);
|
||||
|
||||
module.exports.alert.noFiles = () => {
|
||||
return alert(title, 'No files selected!', {
|
||||
cancel: false,
|
||||
});
|
||||
};
|
||||
70
client/dom/directory.js
Normal file
70
client/dom/directory.js
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
'use strict';
|
||||
|
||||
/* global CloudCmd */
|
||||
const philip = require('philip');
|
||||
|
||||
const Images = require('./images.mjs');
|
||||
const {FS} = require('../../common/cloudfunc.mjs');
|
||||
const DOM = require('.');
|
||||
const Dialog = require('./dialog');
|
||||
|
||||
const {getCurrentDirPath: getPathWhenRootEmpty} = DOM;
|
||||
|
||||
module.exports = (items) => {
|
||||
if (items.length)
|
||||
Images.show('top');
|
||||
|
||||
const entries = Array
|
||||
.from(items)
|
||||
.map((item) => item.webkitGetAsEntry());
|
||||
|
||||
const dirPath = getPathWhenRootEmpty();
|
||||
const path = dirPath.replace(/\/$/, '');
|
||||
|
||||
const progress = Dialog.progress('Uploading...');
|
||||
|
||||
progress.catch(() => {
|
||||
Dialog.alert('Upload aborted');
|
||||
uploader.abort();
|
||||
});
|
||||
|
||||
const uploader = philip(entries, (type, name, data, i, n, callback) => {
|
||||
const {prefixURL} = CloudCmd;
|
||||
const full = prefixURL + FS + path + name;
|
||||
|
||||
let upload;
|
||||
switch(type) {
|
||||
case 'file':
|
||||
upload = uploadFile(full, data);
|
||||
break;
|
||||
|
||||
case 'directory':
|
||||
upload = uploadDir(full);
|
||||
break;
|
||||
}
|
||||
|
||||
upload.on('end', callback);
|
||||
|
||||
upload.on('progress', (count) => {
|
||||
const current = percent(i, n);
|
||||
const next = percent(i + 1, n);
|
||||
const max = next - current;
|
||||
const value = current + percent(count, 100, max);
|
||||
|
||||
progress.setProgress(value);
|
||||
});
|
||||
});
|
||||
|
||||
uploader.on('error', (error) => {
|
||||
Dialog.alert(error);
|
||||
uploader.abort();
|
||||
});
|
||||
|
||||
uploader.on('end', CloudCmd.refresh);
|
||||
};
|
||||
|
||||
const percent = (i, n, per = 100) => Math.round(i * per / n);
|
||||
|
||||
const uploadFile = (url, data) => DOM.load.put(url, data);
|
||||
|
||||
const uploadDir = (url) => DOM.load.put(`${url}?dir`);
|
||||
83
client/dom/dom-tree.js
Normal file
83
client/dom/dom-tree.js
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
'use strict';
|
||||
|
||||
const currify = require('currify');
|
||||
|
||||
const DOM = module.exports;
|
||||
|
||||
/**
|
||||
* check class of element
|
||||
*
|
||||
* @param element
|
||||
* @param className
|
||||
*/
|
||||
const isContainClass = (element, className) => {
|
||||
if (!element)
|
||||
throw Error('element could not be empty!');
|
||||
|
||||
if (!className)
|
||||
throw Error('className could not be empty!');
|
||||
|
||||
if (Array.isArray(className))
|
||||
return className.some(currify(
|
||||
isContainClass,
|
||||
element,
|
||||
));
|
||||
|
||||
const {classList} = element;
|
||||
|
||||
return classList.contains(className);
|
||||
};
|
||||
|
||||
module.exports.isContainClass = isContainClass;
|
||||
/**
|
||||
* Function search element by tag
|
||||
* @param tag - className
|
||||
* @param element - element
|
||||
*/
|
||||
module.exports.getByTag = (tag, element = document) => {
|
||||
return element.getElementsByTagName(tag);
|
||||
};
|
||||
|
||||
/**
|
||||
* Function search element by id
|
||||
* @param Id - id
|
||||
*/
|
||||
module.exports.getById = (id, element = document) => {
|
||||
return element.querySelector(`#${id}`);
|
||||
};
|
||||
|
||||
/**
|
||||
* Function search first element by class name
|
||||
* @param className - className
|
||||
* @param element - element
|
||||
*/
|
||||
module.exports.getByClass = (className, element = document) => DOM.getByClassAll(className, element)[0];
|
||||
|
||||
module.exports.getByDataName = (attribute, element = document) => {
|
||||
const selector = '[' + 'data-name="' + attribute + '"]';
|
||||
return element.querySelector(selector);
|
||||
};
|
||||
|
||||
/**
|
||||
* Function search element by class name
|
||||
* @param pClass - className
|
||||
* @param element - element
|
||||
*/
|
||||
module.exports.getByClassAll = (className, element) => {
|
||||
return (element || document).getElementsByClassName(className);
|
||||
};
|
||||
|
||||
/**
|
||||
* add class=hidden to element
|
||||
*
|
||||
* @param element
|
||||
*/
|
||||
module.exports.hide = (element) => {
|
||||
element.classList.add('hidden');
|
||||
return DOM;
|
||||
};
|
||||
|
||||
module.exports.show = (element) => {
|
||||
element.classList.remove('hidden');
|
||||
return DOM;
|
||||
};
|
||||
43
client/dom/dom-tree.spec.js
Normal file
43
client/dom/dom-tree.spec.js
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
'use strict';
|
||||
|
||||
const test = require('supertape');
|
||||
const {create} = require('auto-globals');
|
||||
const {tryCatch} = require('try-catch');
|
||||
|
||||
const {isContainClass} = require('./dom-tree');
|
||||
|
||||
test('dom: isContainClass: no element', (t) => {
|
||||
const [e] = tryCatch(isContainClass);
|
||||
|
||||
t.equal(e.message, 'element could not be empty!', 'should throw when no element');
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('dom: isContainClass: no className', (t) => {
|
||||
const [e] = tryCatch(isContainClass, {});
|
||||
|
||||
t.equal(e.message, 'className could not be empty!', 'should throw when no element');
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('dom: isContainClass: contains', (t) => {
|
||||
const el = create();
|
||||
const {contains} = el.classList;
|
||||
|
||||
const className = 'hello';
|
||||
isContainClass(el, className);
|
||||
|
||||
t.calledWith(contains, [className], 'should call contains');
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('dom: isContainClass: contains: array', (t) => {
|
||||
const el = create();
|
||||
const {contains} = el.classList;
|
||||
|
||||
const className = 'hello';
|
||||
isContainClass(el, ['world', className, 'hello']);
|
||||
|
||||
t.calledWith(contains, [className], 'should call contains');
|
||||
t.end();
|
||||
});
|
||||
17
client/dom/events/event-store.js
Normal file
17
client/dom/events/event-store.js
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
'use strict';
|
||||
|
||||
let list = [];
|
||||
|
||||
module.exports.add = (el, name, fn) => {
|
||||
list.push([
|
||||
el,
|
||||
name,
|
||||
fn,
|
||||
]);
|
||||
};
|
||||
|
||||
module.exports.clear = () => {
|
||||
list = [];
|
||||
};
|
||||
|
||||
module.exports.get = () => list;
|
||||
39
client/dom/events/event-store.spec.js
Normal file
39
client/dom/events/event-store.spec.js
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
'use strict';
|
||||
|
||||
const test = require('supertape');
|
||||
const eventStore = require('./event-store');
|
||||
|
||||
test('event-store: get', (t) => {
|
||||
const el = {};
|
||||
const name = 'click';
|
||||
const fn = () => {};
|
||||
|
||||
eventStore.add(el, name, fn);
|
||||
const result = eventStore.get();
|
||||
|
||||
const expected = [
|
||||
[
|
||||
el,
|
||||
name,
|
||||
fn,
|
||||
],
|
||||
];
|
||||
|
||||
t.deepEqual(result, expected);
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('event-store: clear', (t) => {
|
||||
const el = {};
|
||||
const name = 'click';
|
||||
const fn = () => {};
|
||||
|
||||
eventStore.add(el, name, fn);
|
||||
eventStore.clear();
|
||||
|
||||
const result = eventStore.get();
|
||||
const expected = [];
|
||||
|
||||
t.deepEqual(result, expected);
|
||||
t.end();
|
||||
});
|
||||
203
client/dom/events/index.mjs
Normal file
203
client/dom/events/index.mjs
Normal file
|
|
@ -0,0 +1,203 @@
|
|||
import itype from 'itype';
|
||||
import EventStore from './event-store.js';
|
||||
|
||||
/**
|
||||
* safe add event listener
|
||||
*
|
||||
* @param type
|
||||
* @param element - document by default
|
||||
* @param listener
|
||||
*/
|
||||
export const add = (type, element, listener) => {
|
||||
checkType(type);
|
||||
|
||||
parseArgs(type, element, listener, (element, args) => {
|
||||
const [name, fn, options] = args;
|
||||
|
||||
element.addEventListener(name, fn, options);
|
||||
EventStore.add(element, name, fn);
|
||||
});
|
||||
|
||||
return Events;
|
||||
};
|
||||
|
||||
/**
|
||||
* safe add event listener
|
||||
*
|
||||
* @param type
|
||||
* @param listener
|
||||
* @param element - document by default
|
||||
*/
|
||||
export const addOnce = (type, element, listener) => {
|
||||
const once = (event) => {
|
||||
Events.remove(type, element, once);
|
||||
listener(event);
|
||||
};
|
||||
|
||||
if (!listener) {
|
||||
listener = element;
|
||||
element = null;
|
||||
}
|
||||
|
||||
add(type, element, once);
|
||||
|
||||
return Events;
|
||||
};
|
||||
|
||||
/**
|
||||
* safe remove event listener
|
||||
*
|
||||
* @param type
|
||||
* @param listener
|
||||
* @param element - document by default
|
||||
*/
|
||||
export const remove = (type, element, listener) => {
|
||||
checkType(type);
|
||||
|
||||
parseArgs(type, element, listener, (element, args) => {
|
||||
element.removeEventListener(...args);
|
||||
});
|
||||
|
||||
return Events;
|
||||
};
|
||||
|
||||
/**
|
||||
* remove all added event listeners
|
||||
*/
|
||||
export const removeAll = () => {
|
||||
const events = EventStore.get();
|
||||
|
||||
for (const [el, name, fn] of events)
|
||||
el.removeEventListener(name, fn);
|
||||
|
||||
EventStore.clear();
|
||||
};
|
||||
|
||||
/**
|
||||
* safe add event keydown listener
|
||||
*
|
||||
* @param args
|
||||
*/
|
||||
export const addKey = function(...args) {
|
||||
return add('keydown', ...args);
|
||||
};
|
||||
|
||||
/**
|
||||
* safe remove event click listener
|
||||
*
|
||||
* @param args
|
||||
*/
|
||||
export const rmKey = function(...args) {
|
||||
return Events.remove('keydown', ...args);
|
||||
};
|
||||
|
||||
/**
|
||||
* safe add event click listener
|
||||
*/
|
||||
export const addClick = function(...args) {
|
||||
return Events.add('click', ...args);
|
||||
};
|
||||
|
||||
/**
|
||||
* safe remove event click listener
|
||||
*/
|
||||
export const rmClick = function(...args) {
|
||||
return remove('click', ...args);
|
||||
};
|
||||
|
||||
export const addContextMenu = function(...args) {
|
||||
return add('contextmenu', ...args);
|
||||
};
|
||||
|
||||
/**
|
||||
* safe add load listener
|
||||
*/
|
||||
export const addLoad = function(...args) {
|
||||
return add('load', ...args);
|
||||
};
|
||||
|
||||
function checkType(type) {
|
||||
if (!type)
|
||||
throw Error('type could not be empty!');
|
||||
}
|
||||
|
||||
const getEventOptions = (eventName) => {
|
||||
if (eventName !== 'touchstart')
|
||||
return false;
|
||||
|
||||
return {
|
||||
passive: true,
|
||||
};
|
||||
};
|
||||
|
||||
function parseArgs(eventName, element, listener, callback) {
|
||||
let isFunc;
|
||||
const args = [
|
||||
eventName,
|
||||
element,
|
||||
listener,
|
||||
callback,
|
||||
];
|
||||
|
||||
const EVENT_NAME = 1;
|
||||
const ELEMENT = 0;
|
||||
const type = itype(eventName);
|
||||
|
||||
switch(type) {
|
||||
default:
|
||||
if (!type.endsWith('element'))
|
||||
throw Error(`unknown eventName: ${type}`);
|
||||
|
||||
parseArgs(args[EVENT_NAME], args[ELEMENT], listener, callback);
|
||||
break;
|
||||
|
||||
case 'string':
|
||||
isFunc = itype.function(element);
|
||||
|
||||
if (isFunc) {
|
||||
listener = element;
|
||||
element = null;
|
||||
}
|
||||
|
||||
if (!element)
|
||||
element = window;
|
||||
|
||||
callback(element, [
|
||||
eventName,
|
||||
listener,
|
||||
getEventOptions(eventName),
|
||||
]);
|
||||
break;
|
||||
|
||||
case 'array':
|
||||
|
||||
for (const name of eventName) {
|
||||
parseArgs(name, element, listener, callback);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'object':
|
||||
|
||||
for (const name of Object.keys(eventName)) {
|
||||
const eventListener = eventName[name];
|
||||
|
||||
parseArgs(name, element, eventListener, callback);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const Events = {
|
||||
add,
|
||||
addClick,
|
||||
addContextMenu,
|
||||
addKey,
|
||||
addLoad,
|
||||
addOnce,
|
||||
remove,
|
||||
removeAll,
|
||||
rmClick,
|
||||
rmKey,
|
||||
};
|
||||
139
client/dom/files.js
Normal file
139
client/dom/files.js
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
'use strict';
|
||||
|
||||
/* global CloudCmd */
|
||||
const itype = require('itype');
|
||||
const {promisify} = require('es6-promisify');
|
||||
|
||||
const load = require('./load');
|
||||
const RESTful = require('./rest');
|
||||
|
||||
const Promises = {};
|
||||
const FILES_JSON = 'config|modules';
|
||||
const FILES_HTML = 'file|path|link|pathLink|media';
|
||||
const FILES_HTML_ROOT = 'view/media-tmpl|config-tmpl|upload';
|
||||
const DIR_HTML = '/tmpl/';
|
||||
const DIR_HTML_FS = `${DIR_HTML}fs/`;
|
||||
const DIR_JSON = '/json/';
|
||||
const timeout = getTimeoutOnce(2000);
|
||||
|
||||
module.exports.get = getFile;
|
||||
|
||||
function getFile(name) {
|
||||
const type = itype(name);
|
||||
check(name);
|
||||
|
||||
if (type === 'string')
|
||||
return getModule(name);
|
||||
|
||||
if (type === 'array')
|
||||
return Promise.all(name.map(getFile));
|
||||
}
|
||||
|
||||
function check(name) {
|
||||
if (!name)
|
||||
throw Error('name could not be empty!');
|
||||
}
|
||||
|
||||
function getModule(name) {
|
||||
const regExpHTML = RegExp(FILES_HTML + '|' + FILES_HTML_ROOT);
|
||||
const regExpJSON = RegExp(FILES_JSON);
|
||||
|
||||
const isHTML = regExpHTML.test(name);
|
||||
const isJSON = regExpJSON.test(name);
|
||||
|
||||
if (!isHTML && !isJSON)
|
||||
return showError(name);
|
||||
|
||||
if (name === 'config')
|
||||
return getConfig();
|
||||
|
||||
const path = getPath(name, isHTML, isJSON);
|
||||
|
||||
return getSystemFile(path);
|
||||
}
|
||||
|
||||
function getPath(name, isHTML, isJSON) {
|
||||
let path;
|
||||
const regExp = RegExp(FILES_HTML_ROOT);
|
||||
const isRoot = regExp.test(name);
|
||||
|
||||
if (isHTML) {
|
||||
if (isRoot)
|
||||
path = DIR_HTML + name.replace('-tmpl', '');
|
||||
else
|
||||
path = DIR_HTML_FS + name;
|
||||
|
||||
path += '.hbs';
|
||||
} else if (isJSON) {
|
||||
path = DIR_JSON + name + '.json';
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
function showError(name) {
|
||||
const str = `Wrong file name: ${name}`;
|
||||
const error = Error(str);
|
||||
|
||||
throw error;
|
||||
}
|
||||
|
||||
const getSystemFile = promisify((file, callback) => {
|
||||
const {prefix} = CloudCmd;
|
||||
|
||||
if (!Promises[file])
|
||||
Promises[file] = new Promise((success, error) => {
|
||||
const url = prefix + file;
|
||||
|
||||
load.ajax({
|
||||
url,
|
||||
success,
|
||||
error,
|
||||
});
|
||||
});
|
||||
|
||||
Promises[file].then((data) => {
|
||||
callback(null, data);
|
||||
}, (error) => {
|
||||
Promises[file] = null;
|
||||
callback(error);
|
||||
});
|
||||
});
|
||||
|
||||
const getConfig = async () => {
|
||||
let is;
|
||||
|
||||
if (!Promises.config)
|
||||
Promises.config = () => {
|
||||
is = true;
|
||||
return RESTful.Config.read();
|
||||
};
|
||||
|
||||
const [, data] = await Promises.config();
|
||||
|
||||
if (data)
|
||||
is = false;
|
||||
|
||||
timeout(() => {
|
||||
if (!is)
|
||||
Promises.config = null;
|
||||
});
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
function getTimeoutOnce(time) {
|
||||
let is;
|
||||
|
||||
return (callback) => {
|
||||
if (is)
|
||||
return;
|
||||
|
||||
is = true;
|
||||
|
||||
setTimeout(() => {
|
||||
is = false;
|
||||
callback();
|
||||
}, time);
|
||||
};
|
||||
}
|
||||
149
client/dom/images.mjs
Normal file
149
client/dom/images.mjs
Normal file
|
|
@ -0,0 +1,149 @@
|
|||
/* global DOM */
|
||||
import createElement from '@cloudcmd/create-element';
|
||||
|
||||
const LOADING = 'loading';
|
||||
const HIDDEN = 'hidden';
|
||||
const ERROR = 'error';
|
||||
|
||||
const getLoadingType = () => isSVG() ? '-svg' : '-gif';
|
||||
|
||||
export const get = getElement;
|
||||
|
||||
/**
|
||||
* check SVG SMIL animation support
|
||||
*/
|
||||
function isSVG() {
|
||||
const createNS = document.createElementNS;
|
||||
const SVG_URL = 'http://www.w3.org/2000/svg';
|
||||
|
||||
if (!createNS)
|
||||
return false;
|
||||
|
||||
const create = createNS.bind(document);
|
||||
const svgNode = create(SVG_URL, 'animate');
|
||||
const name = svgNode.toString();
|
||||
|
||||
return /SVGAnimate/.test(name);
|
||||
}
|
||||
|
||||
function getElement() {
|
||||
return createElement('span', {
|
||||
id: 'js-status-image',
|
||||
className: 'icon',
|
||||
dataName: 'progress',
|
||||
notAppend: true,
|
||||
});
|
||||
}
|
||||
|
||||
/* Функция создаёт картинку загрузки */
|
||||
export const loading = () => {
|
||||
const element = getElement();
|
||||
const {classList} = element;
|
||||
const loadingImage = LOADING + getLoadingType();
|
||||
|
||||
classList.add(LOADING, loadingImage);
|
||||
classList.remove(ERROR, HIDDEN);
|
||||
|
||||
return element;
|
||||
};
|
||||
|
||||
/* Функция создаёт картинку ошибки загрузки */
|
||||
export const error = () => {
|
||||
const element = getElement();
|
||||
const {classList} = element;
|
||||
const loadingImage = LOADING + getLoadingType();
|
||||
|
||||
classList.add(ERROR);
|
||||
classList.remove(HIDDEN, LOADING, loadingImage);
|
||||
|
||||
return element;
|
||||
};
|
||||
|
||||
show.load = show;
|
||||
show.error = (text) => {
|
||||
const image = Images.error();
|
||||
|
||||
DOM.show(image);
|
||||
image.title = text;
|
||||
|
||||
return image;
|
||||
};
|
||||
|
||||
/**
|
||||
* Function shows loading spinner
|
||||
* position = {top: true};
|
||||
*/
|
||||
export function show(position, panel) {
|
||||
const image = Images.loading();
|
||||
const parent = image.parentElement;
|
||||
const refreshButton = DOM.getRefreshButton(panel);
|
||||
|
||||
let current;
|
||||
|
||||
if (position === 'top') {
|
||||
current = refreshButton.parentElement;
|
||||
} else {
|
||||
current = DOM.getCurrentFile();
|
||||
|
||||
if (current)
|
||||
current = DOM.getByDataName('js-name', current);
|
||||
else
|
||||
current = refreshButton.parentElement;
|
||||
}
|
||||
|
||||
if (!parent || parent && parent !== current)
|
||||
current.appendChild(image);
|
||||
|
||||
DOM.show(image);
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
/**
|
||||
* hide load image
|
||||
*/
|
||||
export const hide = () => {
|
||||
const element = Images.get();
|
||||
|
||||
DOM.hide(element);
|
||||
|
||||
return Images;
|
||||
};
|
||||
|
||||
export const setProgress = (value, title) => {
|
||||
const DATA = 'data-progress';
|
||||
const element = Images.get();
|
||||
|
||||
if (!element)
|
||||
return Images;
|
||||
|
||||
element.setAttribute(DATA, `${value}%`);
|
||||
|
||||
if (title)
|
||||
element.title = title;
|
||||
|
||||
return Images;
|
||||
};
|
||||
|
||||
export const clearProgress = () => {
|
||||
const DATA = 'data-progress';
|
||||
const element = Images.get();
|
||||
|
||||
if (!element)
|
||||
return Images;
|
||||
|
||||
element.setAttribute(DATA, '');
|
||||
element.title = '';
|
||||
|
||||
return Images;
|
||||
};
|
||||
|
||||
const Images = {
|
||||
clearProgress,
|
||||
setProgress,
|
||||
show,
|
||||
hide,
|
||||
get,
|
||||
error,
|
||||
loading,
|
||||
};
|
||||
840
client/dom/index.js
Normal file
840
client/dom/index.js
Normal file
|
|
@ -0,0 +1,840 @@
|
|||
'use strict';
|
||||
|
||||
/* global CloudCmd */
|
||||
const Util = require('../../common/util');
|
||||
|
||||
const Images = require('./images.mjs');
|
||||
const RESTful = require('./rest');
|
||||
const Storage = require('./storage');
|
||||
const renameCurrent = require('./operations/rename-current');
|
||||
|
||||
const CurrentFile = require('./current-file.mjs');
|
||||
const DOMTree = require('./dom-tree');
|
||||
|
||||
const Cmd = module.exports;
|
||||
const DOM = {
|
||||
...DOMTree,
|
||||
...CurrentFile,
|
||||
...Cmd,
|
||||
};
|
||||
|
||||
const CurrentInfo = {};
|
||||
|
||||
DOM.Images = Images;
|
||||
DOM.load = require('./load');
|
||||
DOM.Files = require('./files');
|
||||
DOM.RESTful = RESTful;
|
||||
DOM.IO = require('./io');
|
||||
DOM.Storage = Storage;
|
||||
DOM.Dialog = require('./dialog');
|
||||
DOM.CurrentInfo = CurrentInfo;
|
||||
|
||||
module.exports = DOM;
|
||||
|
||||
DOM.uploadDirectory = require('./directory');
|
||||
DOM.Buffer = require('./buffer.mjs');
|
||||
DOM.Events = require('#dom/events');
|
||||
|
||||
const loadRemote = require('./load-remote');
|
||||
const selectByPattern = require('./select-by-pattern');
|
||||
const isString = (a) => typeof a === 'string';
|
||||
const SELECTED_FILE = 'selected-file';
|
||||
|
||||
const TabPanel = {
|
||||
'js-left': null,
|
||||
'js-right': null,
|
||||
};
|
||||
|
||||
module.exports.loadRemote = (name, options, callback) => {
|
||||
loadRemote(name, options, callback);
|
||||
return DOM;
|
||||
};
|
||||
|
||||
module.exports.loadSocket = (callback) => {
|
||||
DOM.loadRemote('socket', {
|
||||
name: 'io',
|
||||
}, callback);
|
||||
|
||||
return DOM;
|
||||
};
|
||||
|
||||
/**
|
||||
* create new folder
|
||||
*
|
||||
*/
|
||||
module.exports.promptNewDir = async function() {
|
||||
await promptNew('directory');
|
||||
};
|
||||
|
||||
/**
|
||||
* create new file
|
||||
*
|
||||
* @typeName
|
||||
* @type
|
||||
*/
|
||||
module.exports.promptNewFile = async () => {
|
||||
await promptNew('file');
|
||||
};
|
||||
|
||||
async function promptNew(typeName) {
|
||||
const {Dialog} = DOM;
|
||||
const dir = DOM.getCurrentDirPath();
|
||||
const msg = `New ${typeName}` || 'File';
|
||||
|
||||
const getName = () => {
|
||||
const name = DOM.getCurrentName();
|
||||
|
||||
if (name === '..')
|
||||
return '';
|
||||
|
||||
return name;
|
||||
};
|
||||
|
||||
const name = getName();
|
||||
const [cancel, currentName] = await Dialog.prompt(msg, name);
|
||||
|
||||
if (cancel)
|
||||
return;
|
||||
|
||||
const path = `${dir}${currentName}`;
|
||||
|
||||
if (typeName === 'directory')
|
||||
await RESTful.createDirectory(path);
|
||||
else
|
||||
await RESTful.write(path);
|
||||
|
||||
await CloudCmd.refresh({
|
||||
currentName,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* get current direcotory name
|
||||
*/
|
||||
module.exports.getCurrentDirName = () => {
|
||||
const href = DOM
|
||||
.getCurrentDirPath()
|
||||
.replace(/\/$/, '');
|
||||
|
||||
const substr = href.substr(href, href.lastIndexOf('/'));
|
||||
|
||||
return href.replace(`${substr}/`, '') || '/';
|
||||
};
|
||||
|
||||
/**
|
||||
* get current direcotory path
|
||||
*/
|
||||
module.exports.getParentDirPath = (panel) => {
|
||||
const path = DOM.getCurrentDirPath(panel);
|
||||
const dirName = DOM.getCurrentDirName() + '/';
|
||||
const index = path.lastIndexOf(dirName);
|
||||
|
||||
if (path !== '/')
|
||||
return path.slice(0, index);
|
||||
|
||||
return path;
|
||||
};
|
||||
|
||||
/**
|
||||
* get not current direcotory path
|
||||
*/
|
||||
module.exports.getNotCurrentDirPath = () => {
|
||||
const panel = DOM.getPanel({
|
||||
active: false,
|
||||
});
|
||||
|
||||
return DOM.getCurrentDirPath(panel);
|
||||
};
|
||||
|
||||
/**
|
||||
* unified way to get selected files
|
||||
*
|
||||
* @currentFile
|
||||
*/
|
||||
module.exports.getSelectedFiles = () => {
|
||||
const panel = DOM.getPanel();
|
||||
const selected = DOM.getByClassAll(SELECTED_FILE, panel);
|
||||
|
||||
return Array.from(selected);
|
||||
};
|
||||
|
||||
/*
|
||||
* unselect all files
|
||||
*/
|
||||
module.exports.unselectFiles = (files) => {
|
||||
files = files || DOM.getSelectedFiles();
|
||||
|
||||
Array
|
||||
.from(files)
|
||||
.forEach(DOM.toggleSelectedFile);
|
||||
};
|
||||
|
||||
/**
|
||||
* get all selected files or current when none selected
|
||||
*
|
||||
* @currentFile
|
||||
*/
|
||||
module.exports.getActiveFiles = () => {
|
||||
const current = DOM.getCurrentFile();
|
||||
const files = DOM.getSelectedFiles();
|
||||
const name = DOM.getCurrentName(current);
|
||||
|
||||
if (!files.length && name !== '..')
|
||||
return [current];
|
||||
|
||||
return files;
|
||||
};
|
||||
|
||||
module.exports.getCurrentDate = (currentFile) => {
|
||||
const current = currentFile || DOM.getCurrentFile();
|
||||
|
||||
return DOM.getByDataName('js-date', current).textContent;
|
||||
};
|
||||
|
||||
/**
|
||||
* get size
|
||||
* @currentFile
|
||||
*/
|
||||
module.exports.getCurrentSize = (currentFile) => {
|
||||
const current = currentFile || DOM.getCurrentFile();
|
||||
|
||||
/* если это папка - возвращаем слово dir вместо размера*/
|
||||
const size = DOM
|
||||
.getByDataName('js-size', current)
|
||||
.textContent
|
||||
.replace(/^<|>$/g, '');
|
||||
|
||||
return size;
|
||||
};
|
||||
|
||||
/**
|
||||
* get size
|
||||
* @currentFile
|
||||
*/
|
||||
module.exports.loadCurrentSize = async (currentFile) => {
|
||||
const current = currentFile || DOM.getCurrentFile();
|
||||
const query = '?size';
|
||||
const link = DOM.getCurrentPath(current);
|
||||
|
||||
Images.show.load();
|
||||
|
||||
if (name === '..')
|
||||
return;
|
||||
|
||||
const [, size] = await RESTful.read(link + query);
|
||||
|
||||
DOM.setCurrentSize(size, current);
|
||||
Images.hide();
|
||||
|
||||
return current;
|
||||
};
|
||||
|
||||
/**
|
||||
* load hash
|
||||
* @callback
|
||||
* @currentFile
|
||||
*/
|
||||
module.exports.loadCurrentHash = async (currentFile) => {
|
||||
const current = currentFile || DOM.getCurrentFile();
|
||||
const query = '?hash';
|
||||
const link = DOM.getCurrentPath(current);
|
||||
|
||||
const [, data] = await RESTful.read(link + query);
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
/**
|
||||
* set size
|
||||
* @currentFile
|
||||
*/
|
||||
module.exports.setCurrentSize = (size, currentFile) => {
|
||||
const current = currentFile || DOM.getCurrentFile();
|
||||
const sizeElement = DOM.getByDataName('js-size', current);
|
||||
|
||||
sizeElement.textContent = size;
|
||||
};
|
||||
|
||||
/**
|
||||
* @currentFile
|
||||
*/
|
||||
module.exports.getCurrentMode = (currentFile) => {
|
||||
const current = currentFile || DOM.getCurrentFile();
|
||||
const mode = DOM.getByDataName('js-mode', current);
|
||||
|
||||
return mode.textContent;
|
||||
};
|
||||
|
||||
/**
|
||||
* @currentFile
|
||||
*/
|
||||
module.exports.getCurrentOwner = (currentFile) => {
|
||||
const current = currentFile || DOM.getCurrentFile();
|
||||
const owner = DOM.getByDataName('js-owner', current);
|
||||
|
||||
return owner.textContent;
|
||||
};
|
||||
|
||||
/**
|
||||
* unified way to get current file content
|
||||
*
|
||||
* @param currentFile
|
||||
*/
|
||||
module.exports.getCurrentData = async (currentFile) => {
|
||||
const {Dialog} = DOM;
|
||||
const Info = DOM.CurrentInfo;
|
||||
const current = currentFile || DOM.getCurrentFile();
|
||||
const path = DOM.getCurrentPath(current);
|
||||
const isDir = DOM.isCurrentIsDir(current);
|
||||
|
||||
if (Info.name === '..') {
|
||||
Dialog.alert.noFiles();
|
||||
return [
|
||||
Error('No Files'),
|
||||
];
|
||||
}
|
||||
|
||||
if (isDir)
|
||||
return await RESTful.read(path);
|
||||
|
||||
const [hashNew, hash] = await DOM.checkStorageHash(path);
|
||||
|
||||
if (!hashNew)
|
||||
return [
|
||||
Error(`Can't get hash of a file`),
|
||||
];
|
||||
|
||||
if (hash === hashNew)
|
||||
return [null, await Storage.get(`${path}-data`)];
|
||||
|
||||
const [e, data] = await RESTful.read(path);
|
||||
|
||||
if (e)
|
||||
return [
|
||||
e,
|
||||
null,
|
||||
];
|
||||
|
||||
const ONE_MEGABYTE = 1024 ** 2 * 1024;
|
||||
const {length} = data;
|
||||
|
||||
if (hash && length < ONE_MEGABYTE)
|
||||
await DOM.saveDataToStorage(path, data, hashNew);
|
||||
|
||||
return [null, data];
|
||||
};
|
||||
|
||||
/**
|
||||
* unified way to get RefreshButton
|
||||
*/
|
||||
module.exports.getRefreshButton = (panel = DOM.getPanel()) => {
|
||||
return DOM.getByDataName('js-refresh', panel);
|
||||
};
|
||||
|
||||
/**
|
||||
* select current file
|
||||
* @param currentFile
|
||||
*/
|
||||
module.exports.selectFile = (currentFile) => {
|
||||
const current = currentFile || DOM.getCurrentFile();
|
||||
|
||||
current.classList.add(SELECTED_FILE);
|
||||
|
||||
return Cmd;
|
||||
};
|
||||
|
||||
module.exports.unselectFile = (currentFile) => {
|
||||
const current = currentFile || DOM.getCurrentFile();
|
||||
|
||||
current.classList.remove(SELECTED_FILE);
|
||||
|
||||
return Cmd;
|
||||
};
|
||||
|
||||
module.exports.toggleSelectedFile = (currentFile) => {
|
||||
const current = currentFile || DOM.getCurrentFile();
|
||||
const name = DOM.getCurrentName(current);
|
||||
|
||||
if (name === '..')
|
||||
return Cmd;
|
||||
|
||||
current.classList.toggle(SELECTED_FILE);
|
||||
|
||||
return Cmd;
|
||||
};
|
||||
|
||||
module.exports.toggleAllSelectedFiles = () => {
|
||||
DOM
|
||||
.getAllFiles()
|
||||
.map(DOM.toggleSelectedFile);
|
||||
|
||||
return Cmd;
|
||||
};
|
||||
|
||||
module.exports.selectAllFiles = () => {
|
||||
DOM
|
||||
.getAllFiles()
|
||||
.map(DOM.selectFile);
|
||||
|
||||
return Cmd;
|
||||
};
|
||||
|
||||
module.exports.getAllFiles = () => {
|
||||
const panel = DOM.getPanel();
|
||||
const files = DOM.getFiles(panel);
|
||||
const name = DOM.getCurrentName(files[0]);
|
||||
|
||||
const from = (a) => a === '..' ? 1 : 0;
|
||||
const i = from(name);
|
||||
|
||||
return Array
|
||||
.from(files)
|
||||
.slice(i);
|
||||
};
|
||||
|
||||
/**
|
||||
* open dialog with expand selection
|
||||
*/
|
||||
module.exports.expandSelection = () => {
|
||||
const msg = 'expand';
|
||||
const {files} = CurrentInfo;
|
||||
|
||||
selectByPattern(msg, files);
|
||||
};
|
||||
|
||||
/**
|
||||
* open dialog with shrink selection
|
||||
*/
|
||||
module.exports.shrinkSelection = () => {
|
||||
const msg = 'shrink';
|
||||
const {files} = CurrentInfo;
|
||||
|
||||
selectByPattern(msg, files);
|
||||
};
|
||||
|
||||
/**
|
||||
* setting history wrapper
|
||||
*/
|
||||
module.exports.setHistory = (data, title, url) => {
|
||||
const ret = globalThis.history;
|
||||
const {prefix} = CloudCmd;
|
||||
|
||||
url = prefix + url;
|
||||
|
||||
if (ret)
|
||||
history.pushState(data, title, url);
|
||||
|
||||
return ret;
|
||||
};
|
||||
|
||||
/**
|
||||
* selected file check
|
||||
*
|
||||
* @param currentFile
|
||||
*/
|
||||
module.exports.isSelected = (selected) => {
|
||||
if (!selected)
|
||||
return false;
|
||||
|
||||
return DOM.isContainClass(selected, SELECTED_FILE);
|
||||
};
|
||||
|
||||
/**
|
||||
* get link from current (or param) file
|
||||
*
|
||||
* @param currentFile - current file by default
|
||||
*/
|
||||
module.exports.getCurrentLink = (currentFile) => {
|
||||
const current = currentFile || DOM.getCurrentFile();
|
||||
const link = DOM.getByTag('a', current);
|
||||
|
||||
return link[0];
|
||||
};
|
||||
|
||||
module.exports.getFilenames = (files) => {
|
||||
if (!files)
|
||||
throw Error('AllFiles could not be empty');
|
||||
|
||||
const first = files[0] || DOM.getCurrentFile();
|
||||
const name = DOM.getCurrentName(first);
|
||||
|
||||
const allFiles = Array.from(files);
|
||||
|
||||
if (name === '..')
|
||||
allFiles.shift();
|
||||
|
||||
const names = allFiles.map((current) => {
|
||||
return DOM.getCurrentName(current);
|
||||
});
|
||||
|
||||
return names;
|
||||
};
|
||||
|
||||
/**
|
||||
* check storage hash
|
||||
*/
|
||||
module.exports.checkStorageHash = async (name) => {
|
||||
const nameHash = `${name}-hash`;
|
||||
|
||||
if (!isString(name))
|
||||
throw Error('name should be a string!');
|
||||
|
||||
const [loadHash, storeHash] = await Promise.all([
|
||||
DOM.loadCurrentHash(),
|
||||
Storage.get(nameHash),
|
||||
]);
|
||||
|
||||
return [loadHash, storeHash];
|
||||
};
|
||||
|
||||
/**
|
||||
* save data to storage
|
||||
*
|
||||
* @param name
|
||||
* @param data
|
||||
* @param hash
|
||||
* @param callback
|
||||
*/
|
||||
module.exports.saveDataToStorage = async (name, data, hash) => {
|
||||
const isDir = DOM.isCurrentIsDir();
|
||||
|
||||
if (isDir)
|
||||
return;
|
||||
|
||||
hash = hash || await DOM.loadCurrentHash();
|
||||
|
||||
const nameHash = `${name}-hash`;
|
||||
const nameData = `${name}-data`;
|
||||
|
||||
await Storage.set(nameHash, hash);
|
||||
await Storage.set(nameData, data);
|
||||
|
||||
return hash;
|
||||
};
|
||||
|
||||
module.exports.getFM = () => DOM.getPanel().parentElement;
|
||||
|
||||
module.exports.getPanelPosition = (panel) => {
|
||||
panel = panel || DOM.getPanel();
|
||||
|
||||
return panel.dataset.name.replace('js-', '');
|
||||
};
|
||||
|
||||
module.exports.getCSSVar = (name, {body = document.body} = {}) => {
|
||||
const bodyStyle = getComputedStyle(body);
|
||||
return bodyStyle.getPropertyValue(`--${name}`);
|
||||
};
|
||||
|
||||
/** function getting panel active, or passive
|
||||
* @param options = {active: true}
|
||||
*/
|
||||
module.exports.getPanel = (options) => {
|
||||
let files;
|
||||
let panel;
|
||||
let isLeft;
|
||||
let dataName = 'js-';
|
||||
|
||||
const current = DOM.getCurrentFile();
|
||||
|
||||
if (!current) {
|
||||
panel = DOM.getByDataName('js-left');
|
||||
} else {
|
||||
files = current.parentElement;
|
||||
panel = files.parentElement;
|
||||
isLeft = panel.getAttribute('data-name') === 'js-left';
|
||||
}
|
||||
|
||||
/* if {active : false} getting passive panel */
|
||||
if (options && !options.active) {
|
||||
dataName += isLeft ? 'right' : 'left';
|
||||
panel = DOM.getByDataName(dataName);
|
||||
}
|
||||
|
||||
/* if two panels showed
|
||||
* then always work with passive
|
||||
* panel
|
||||
*/
|
||||
if (globalThis.innerWidth < CloudCmd.MIN_ONE_PANEL_WIDTH)
|
||||
panel = DOM.getByDataName('js-left');
|
||||
|
||||
if (!panel)
|
||||
throw Error('can not find Active Panel!');
|
||||
|
||||
return panel;
|
||||
};
|
||||
|
||||
module.exports.getFiles = (element) => {
|
||||
const files = DOM.getByDataName('js-files', element);
|
||||
return files.children || [];
|
||||
};
|
||||
|
||||
/**
|
||||
* shows panel right or left (or active)
|
||||
*/
|
||||
module.exports.showPanel = (active) => {
|
||||
const panel = DOM.getPanel({
|
||||
active,
|
||||
});
|
||||
|
||||
if (!panel)
|
||||
return false;
|
||||
|
||||
DOM.show(panel);
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* hides panel right or left (or active)
|
||||
*/
|
||||
module.exports.hidePanel = (active) => {
|
||||
const panel = DOM.getPanel({
|
||||
active,
|
||||
});
|
||||
|
||||
if (!panel)
|
||||
return false;
|
||||
|
||||
return DOM.hide(panel);
|
||||
};
|
||||
|
||||
/**
|
||||
* remove child of element
|
||||
* @param pChild
|
||||
* @param element
|
||||
*/
|
||||
module.exports.remove = (child, element) => {
|
||||
const parent = element || document.body;
|
||||
|
||||
parent.removeChild(child);
|
||||
|
||||
return DOM;
|
||||
};
|
||||
|
||||
/**
|
||||
* remove current file from file table
|
||||
* @param current
|
||||
*
|
||||
*/
|
||||
module.exports.deleteCurrent = (current) => {
|
||||
if (!current)
|
||||
DOM.getCurrentFile();
|
||||
|
||||
const parent = current?.parentElement;
|
||||
const name = DOM.getCurrentName(current);
|
||||
|
||||
if (current && name !== '..') {
|
||||
const next = current.nextSibling;
|
||||
const prev = current.previousSibling;
|
||||
|
||||
DOM.setCurrentFile(next || prev);
|
||||
parent.removeChild(current);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* remove selected files from file table
|
||||
* @Selected
|
||||
*/
|
||||
module.exports.deleteSelected = (selected) => {
|
||||
selected = selected || DOM.getSelectedFiles();
|
||||
|
||||
if (!selected)
|
||||
return;
|
||||
|
||||
selected.map(DOM.deleteCurrent);
|
||||
};
|
||||
|
||||
/**
|
||||
* rename current file
|
||||
*
|
||||
* @currentFile
|
||||
*/
|
||||
module.exports.renameCurrent = renameCurrent;
|
||||
/**
|
||||
* unified way to scrollIntoViewIfNeeded
|
||||
* (native suporte by webkit only)
|
||||
* @param element
|
||||
* @param center - to scroll as small as possible param should be false
|
||||
*/
|
||||
module.exports.scrollIntoViewIfNeeded = (element, center = false) => {
|
||||
if (!element || !element.scrollIntoViewIfNeeded)
|
||||
return;
|
||||
|
||||
element.scrollIntoViewIfNeeded(center);
|
||||
};
|
||||
|
||||
/* scroll on one page */
|
||||
module.exports.scrollByPages = (element, pPages) => {
|
||||
const ret = element?.scrollByPages && pPages;
|
||||
|
||||
if (ret)
|
||||
element.scrollByPages(pPages);
|
||||
|
||||
return ret;
|
||||
};
|
||||
|
||||
module.exports.changePanel = () => {
|
||||
const Info = CurrentInfo;
|
||||
let panel = DOM.getPanel();
|
||||
|
||||
CloudCmd.emit('passive-dir', Info.dirPath);
|
||||
|
||||
const panelPassive = DOM.getPanel({
|
||||
active: false,
|
||||
});
|
||||
|
||||
let name = DOM.getCurrentName();
|
||||
const filesPassive = DOM.getFiles(panelPassive);
|
||||
|
||||
let dataName = panel.getAttribute('data-name');
|
||||
|
||||
TabPanel[dataName] = name;
|
||||
|
||||
panel = panelPassive;
|
||||
dataName = panel.getAttribute('data-name');
|
||||
|
||||
name = TabPanel[dataName];
|
||||
|
||||
let files;
|
||||
let current;
|
||||
|
||||
if (name) {
|
||||
current = DOM.getCurrentByName(name, panel);
|
||||
|
||||
if (current)
|
||||
files = current.parentElement;
|
||||
}
|
||||
|
||||
if (!files || !files.parentElement) {
|
||||
current = DOM.getCurrentByName(name, panel);
|
||||
|
||||
if (!current)
|
||||
[current] = filesPassive;
|
||||
}
|
||||
|
||||
DOM.setCurrentFile(current, {
|
||||
history: true,
|
||||
});
|
||||
|
||||
CloudCmd.emit('active-dir', Info.dirPath);
|
||||
|
||||
return DOM;
|
||||
};
|
||||
|
||||
module.exports.getPackerExt = (type) => {
|
||||
if (type === 'zip')
|
||||
return '.zip';
|
||||
|
||||
return '.tar.gz';
|
||||
};
|
||||
|
||||
module.exports.goToDirectory = async (overrides = {}) => {
|
||||
const {Dialog} = DOM;
|
||||
const {prompt = Dialog.prompt, changeDir = CloudCmd.changeDir} = overrides;
|
||||
|
||||
const msg = 'Go to directory:';
|
||||
const {dirPath} = CurrentInfo;
|
||||
|
||||
const [cancel, path = dirPath] = await prompt(msg, dirPath);
|
||||
|
||||
if (cancel)
|
||||
return;
|
||||
|
||||
await changeDir(path);
|
||||
};
|
||||
|
||||
module.exports.duplicatePanel = async () => {
|
||||
const Info = CurrentInfo;
|
||||
const {isDir} = Info;
|
||||
const panel = Info.panelPassive;
|
||||
const noCurrent = !Info.isOnePanel;
|
||||
|
||||
const getPath = (isDir) => {
|
||||
if (isDir)
|
||||
return Info.path;
|
||||
|
||||
return Info.dirPath;
|
||||
};
|
||||
|
||||
const path = getPath(isDir);
|
||||
|
||||
await CloudCmd.changeDir(path, {
|
||||
panel,
|
||||
noCurrent,
|
||||
});
|
||||
};
|
||||
|
||||
module.exports.swapPanels = async () => {
|
||||
const Info = CurrentInfo;
|
||||
const {
|
||||
panel,
|
||||
files,
|
||||
element,
|
||||
panelPassive,
|
||||
} = Info;
|
||||
|
||||
const path = DOM.getCurrentDirPath();
|
||||
const dirPathPassive = DOM.getNotCurrentDirPath();
|
||||
|
||||
let currentIndex = files.indexOf(element);
|
||||
|
||||
await CloudCmd.changeDir(path, {
|
||||
panel: panelPassive,
|
||||
noCurrent: true,
|
||||
});
|
||||
|
||||
await CloudCmd.changeDir(dirPathPassive, {
|
||||
panel,
|
||||
});
|
||||
|
||||
const length = Info.files.length - 1;
|
||||
|
||||
if (currentIndex > length)
|
||||
currentIndex = length;
|
||||
|
||||
const el = Info.files[currentIndex];
|
||||
|
||||
DOM.setCurrentFile(el);
|
||||
};
|
||||
|
||||
module.exports.CurrentInfo = CurrentInfo;
|
||||
|
||||
module.exports.updateCurrentInfo = (currentFile) => {
|
||||
const info = DOM.CurrentInfo;
|
||||
const current = currentFile || DOM.getCurrentFile();
|
||||
const files = current.parentElement;
|
||||
|
||||
const panelPassive = DOM.getPanel({
|
||||
active: false,
|
||||
});
|
||||
|
||||
const filesPassive = DOM.getFiles(panelPassive);
|
||||
const name = DOM.getCurrentName(current);
|
||||
|
||||
info.dir = DOM.getCurrentDirName();
|
||||
info.dirPath = DOM.getCurrentDirPath();
|
||||
info.parentDirPath = DOM.getParentDirPath();
|
||||
info.element = current;
|
||||
info.ext = Util.getExt(name);
|
||||
info.files = Array.from(files.children);
|
||||
info.filesPassive = Array.from(filesPassive);
|
||||
info.first = files.firstChild;
|
||||
info.getData = DOM.getCurrentData;
|
||||
info.last = files.lastChild;
|
||||
info.link = DOM.getCurrentLink(current);
|
||||
info.mode = DOM.getCurrentMode(current);
|
||||
info.name = name;
|
||||
info.path = DOM.getCurrentPath(current);
|
||||
info.panel = files.parentElement || DOM.getPanel();
|
||||
info.panelPassive = panelPassive;
|
||||
info.size = DOM.getCurrentSize(current);
|
||||
info.isDir = DOM.isCurrentIsDir();
|
||||
info.isSelected = DOM.isSelected(current);
|
||||
info.panelPosition = DOM
|
||||
.getPanel()
|
||||
.dataset
|
||||
.name
|
||||
.replace('js-', '');
|
||||
info.isOnePanel = info.panel.getAttribute('data-name') === info.panelPassive.getAttribute('data-name');
|
||||
};
|
||||
56
client/dom/index.spec.js
Normal file
56
client/dom/index.spec.js
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
'use strict';
|
||||
|
||||
require('css-modules-require-hook/preset');
|
||||
|
||||
const {test, stub} = require('supertape');
|
||||
const {getCSSVar, goToDirectory} = require('./index');
|
||||
|
||||
globalThis.CloudCmd = {};
|
||||
|
||||
test('cloudcmd: client: dom: goToDirectory', async (t) => {
|
||||
const path = '';
|
||||
const changeDir = stub();
|
||||
const prompt = stub().returns([null, path]);
|
||||
|
||||
await goToDirectory({
|
||||
prompt,
|
||||
changeDir,
|
||||
});
|
||||
|
||||
t.calledWith(changeDir, [path]);
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('cloudcmd: client: dom: getCSSVar', (t) => {
|
||||
const body = {};
|
||||
const getPropertyValue = stub().returns(0);
|
||||
|
||||
globalThis.getComputedStyle = stub().returns({
|
||||
getPropertyValue,
|
||||
});
|
||||
const result = getCSSVar('hello', {
|
||||
body,
|
||||
});
|
||||
|
||||
delete globalThis.getComputedStyle;
|
||||
|
||||
t.notOk(result);
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('cloudcmd: client: dom: getCSSVar: 1', (t) => {
|
||||
const body = {};
|
||||
const getPropertyValue = stub().returns(1);
|
||||
|
||||
globalThis.getComputedStyle = stub().returns({
|
||||
getPropertyValue,
|
||||
});
|
||||
const result = getCSSVar('hello', {
|
||||
body,
|
||||
});
|
||||
|
||||
delete globalThis.getComputedStyle;
|
||||
|
||||
t.ok(result);
|
||||
t.end();
|
||||
});
|
||||
155
client/dom/io/index.js
Normal file
155
client/dom/io/index.js
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
'use strict';
|
||||
|
||||
const {FS} = require('../../../common/cloudfunc.mjs');
|
||||
const _sendRequest = require('./send-request');
|
||||
|
||||
const imgPosition = {
|
||||
top: true,
|
||||
};
|
||||
|
||||
module.exports.delete = async (url, data) => {
|
||||
return await _sendRequest({
|
||||
method: 'DELETE',
|
||||
url: FS + url,
|
||||
data,
|
||||
imgPosition: {
|
||||
top: Boolean(data),
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
module.exports.patch = async (url, data) => {
|
||||
return await _sendRequest({
|
||||
method: 'PATCH',
|
||||
url: FS + url,
|
||||
data,
|
||||
imgPosition,
|
||||
});
|
||||
};
|
||||
|
||||
module.exports.write = async (url, data) => {
|
||||
return await _sendRequest({
|
||||
method: 'PUT',
|
||||
url: FS + url,
|
||||
data,
|
||||
imgPosition,
|
||||
});
|
||||
};
|
||||
|
||||
module.exports.createDirectory = async (url, overrides = {}) => {
|
||||
const {
|
||||
sendRequest = _sendRequest,
|
||||
} = overrides;
|
||||
|
||||
return await sendRequest({
|
||||
method: 'PUT',
|
||||
url: `${FS}${url}?dir`,
|
||||
imgPosition,
|
||||
});
|
||||
};
|
||||
|
||||
module.exports.read = async (url, dataType = 'text') => {
|
||||
const notLog = !url.includes('?');
|
||||
|
||||
return await _sendRequest({
|
||||
method: 'GET',
|
||||
url: FS + url,
|
||||
notLog,
|
||||
dataType,
|
||||
});
|
||||
};
|
||||
|
||||
module.exports.copy = async (from, to, names) => {
|
||||
return await _sendRequest({
|
||||
method: 'PUT',
|
||||
url: '/copy',
|
||||
data: {
|
||||
from,
|
||||
to,
|
||||
names,
|
||||
},
|
||||
imgPosition,
|
||||
});
|
||||
};
|
||||
|
||||
module.exports.pack = async (data) => {
|
||||
return await _sendRequest({
|
||||
method: 'PUT',
|
||||
url: '/pack',
|
||||
data,
|
||||
});
|
||||
};
|
||||
|
||||
module.exports.extract = async (data) => {
|
||||
return await _sendRequest({
|
||||
method: 'PUT',
|
||||
url: '/extract',
|
||||
data,
|
||||
});
|
||||
};
|
||||
|
||||
module.exports.move = async (from, to, names) => {
|
||||
return await _sendRequest({
|
||||
method: 'PUT',
|
||||
url: '/move',
|
||||
data: {
|
||||
from,
|
||||
to,
|
||||
names,
|
||||
},
|
||||
imgPosition,
|
||||
});
|
||||
};
|
||||
|
||||
module.exports.rename = async (from, to) => {
|
||||
return await _sendRequest({
|
||||
method: 'PUT',
|
||||
url: '/rename',
|
||||
data: {
|
||||
from,
|
||||
to,
|
||||
},
|
||||
imgPosition,
|
||||
});
|
||||
};
|
||||
|
||||
module.exports.Config = {
|
||||
read: async () => {
|
||||
return await _sendRequest({
|
||||
method: 'GET',
|
||||
url: '/config',
|
||||
imgPosition,
|
||||
notLog: true,
|
||||
});
|
||||
},
|
||||
|
||||
write: async (data) => {
|
||||
return await _sendRequest({
|
||||
method: 'PATCH',
|
||||
url: '/config',
|
||||
data,
|
||||
imgPosition,
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
module.exports.Markdown = {
|
||||
read: async (url) => {
|
||||
return await _sendRequest({
|
||||
method: 'GET',
|
||||
url: `/markdown${url}`,
|
||||
imgPosition,
|
||||
notLog: true,
|
||||
});
|
||||
},
|
||||
|
||||
render: async (data) => {
|
||||
return await _sendRequest({
|
||||
method: 'PUT',
|
||||
url: '/markdown',
|
||||
data,
|
||||
imgPosition,
|
||||
notLog: true,
|
||||
});
|
||||
},
|
||||
};
|
||||
23
client/dom/io/index.spec.js
Normal file
23
client/dom/io/index.spec.js
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
'use strict';
|
||||
|
||||
const {test, stub} = require('supertape');
|
||||
const io = require('.');
|
||||
|
||||
test('client: dom: io', (t) => {
|
||||
const sendRequest = stub();
|
||||
|
||||
io.createDirectory('/hello', {
|
||||
sendRequest,
|
||||
});
|
||||
|
||||
const expected = {
|
||||
imgPosition: {
|
||||
top: true,
|
||||
},
|
||||
method: 'PUT',
|
||||
url: '/fs/hello?dir',
|
||||
};
|
||||
|
||||
t.calledWith(sendRequest, [expected]);
|
||||
t.end();
|
||||
});
|
||||
50
client/dom/io/send-request.js
Normal file
50
client/dom/io/send-request.js
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
'use strict';
|
||||
|
||||
/* global CloudCmd */
|
||||
const {promisify} = require('es6-promisify');
|
||||
|
||||
const Images = require('../images.mjs');
|
||||
const load = require('../load');
|
||||
|
||||
module.exports = promisify((params, callback) => {
|
||||
const p = params;
|
||||
const {prefixURL} = CloudCmd;
|
||||
|
||||
p.url = prefixURL + p.url;
|
||||
p.url = encodeURI(p.url);
|
||||
|
||||
p.url = replaceHash(p.url);
|
||||
|
||||
load.ajax({
|
||||
method: p.method,
|
||||
url: p.url,
|
||||
data: p.data,
|
||||
dataType: p.dataType,
|
||||
error: (jqXHR) => {
|
||||
const response = jqXHR.responseText;
|
||||
|
||||
const {statusText, status} = jqXHR;
|
||||
|
||||
const text = status === 404 ? response : statusText;
|
||||
|
||||
callback(Error(text));
|
||||
},
|
||||
success: (data) => {
|
||||
Images.hide();
|
||||
|
||||
if (!p.notLog)
|
||||
CloudCmd.log(data);
|
||||
|
||||
callback(null, data);
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
module.exports._replaceHash = replaceHash;
|
||||
function replaceHash(url) {
|
||||
/*
|
||||
* if we send ajax request -
|
||||
* no need in hash so we escape #
|
||||
*/
|
||||
return url.replace(/#/g, '%23');
|
||||
}
|
||||
13
client/dom/io/send-request.spec.js
Normal file
13
client/dom/io/send-request.spec.js
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
'use strict';
|
||||
|
||||
const test = require('supertape');
|
||||
const {_replaceHash} = require('./send-request');
|
||||
|
||||
test('cloudcmd: client: io: replaceHash', (t) => {
|
||||
const url = '/hello/####world';
|
||||
const result = _replaceHash(url);
|
||||
const expected = '/hello/%23%23%23%23world';
|
||||
|
||||
t.equal(result, expected);
|
||||
t.end();
|
||||
});
|
||||
56
client/dom/load-remote.js
Normal file
56
client/dom/load-remote.js
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
'use strict';
|
||||
|
||||
/* global CloudCmd */
|
||||
const rendy = require('rendy');
|
||||
const itype = require('itype');
|
||||
const load = require('load.js');
|
||||
const {tryToCatch} = require('try-to-catch');
|
||||
|
||||
const {findObjByNameInArr} = require('../../common/util');
|
||||
|
||||
const Files = require('./files');
|
||||
|
||||
module.exports = (name, options, callback = options) => {
|
||||
const {prefix, config} = CloudCmd;
|
||||
const o = options;
|
||||
|
||||
if (o.name && window[o.name])
|
||||
return callback();
|
||||
|
||||
Files.get('modules').then(async (modules) => {
|
||||
const online = config('online') && navigator.onLine;
|
||||
const module = findObjByNameInArr(modules.remote, name);
|
||||
|
||||
const isArray = itype.array(module.local);
|
||||
const {version} = module;
|
||||
|
||||
let remoteTmpls;
|
||||
let local;
|
||||
|
||||
if (isArray) {
|
||||
remoteTmpls = module.remote;
|
||||
({local} = module);
|
||||
} else {
|
||||
remoteTmpls = [module.remote];
|
||||
local = [module.local];
|
||||
}
|
||||
|
||||
const localURL = local.map((url) => prefix + url);
|
||||
|
||||
const remoteURL = remoteTmpls.map((tmpl) => {
|
||||
return rendy(tmpl, {
|
||||
version,
|
||||
});
|
||||
});
|
||||
|
||||
if (online) {
|
||||
const [e] = await tryToCatch(load.parallel, remoteURL);
|
||||
|
||||
if (!e)
|
||||
return callback();
|
||||
}
|
||||
|
||||
const [e] = await tryToCatch(load.parallel, localURL);
|
||||
callback(e);
|
||||
});
|
||||
};
|
||||
134
client/dom/load.js
Normal file
134
client/dom/load.js
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
'use strict';
|
||||
|
||||
const itype = require('itype');
|
||||
const jonny = require('jonny');
|
||||
const Emitify = require('emitify');
|
||||
const exec = require('execon');
|
||||
const Images = require('./images.mjs');
|
||||
|
||||
module.exports.getIdBySrc = getIdBySrc;
|
||||
/**
|
||||
* Function gets id by src
|
||||
* @param src
|
||||
*
|
||||
* Example: http://domain.com/1.js -> 1_js
|
||||
*/
|
||||
function getIdBySrc(src) {
|
||||
const isStr = itype.string(src);
|
||||
|
||||
if (!isStr)
|
||||
return;
|
||||
|
||||
if (src.includes(':'))
|
||||
src += '-join';
|
||||
|
||||
const num = src.lastIndexOf('/') + 1;
|
||||
const sub = src.substr(src, num);
|
||||
|
||||
const id = src
|
||||
.replace(sub, '')
|
||||
.replace(/\./g, '-');
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* load file countent via ajax
|
||||
*
|
||||
* @param params
|
||||
*/
|
||||
module.exports.ajax = (params) => {
|
||||
const p = params;
|
||||
const isObject = itype.object(p.data);
|
||||
const isArray = itype.array(p.data);
|
||||
const isArrayBuf = itype(p.data) === 'arraybuffer';
|
||||
const type = p.type || p.method || 'GET';
|
||||
|
||||
const {headers = {}} = p;
|
||||
|
||||
const xhr = new XMLHttpRequest();
|
||||
|
||||
xhr.open(type, p.url, true);
|
||||
|
||||
for (const name of Object.keys(headers)) {
|
||||
const value = headers[name];
|
||||
xhr.setRequestHeader(name, value);
|
||||
}
|
||||
|
||||
if (p.responseType)
|
||||
xhr.responseType = p.responseType;
|
||||
|
||||
let data;
|
||||
|
||||
if (!isArrayBuf && isObject || isArray)
|
||||
data = jonny.stringify(p.data);
|
||||
else
|
||||
({data} = p);
|
||||
|
||||
xhr.onreadystatechange = (event) => {
|
||||
const xhr = event.target;
|
||||
const OK = 200;
|
||||
|
||||
if (xhr.readyState !== xhr.DONE)
|
||||
return;
|
||||
|
||||
Images.clearProgress();
|
||||
|
||||
const TYPE_JSON = 'application/json';
|
||||
const type = xhr.getResponseHeader('content-type');
|
||||
|
||||
if (xhr.status !== OK)
|
||||
return exec(p.error, xhr);
|
||||
|
||||
const notText = p.dataType !== 'text';
|
||||
const isContain = type.includes(TYPE_JSON);
|
||||
|
||||
let data = xhr.response;
|
||||
|
||||
if (type && isContain && notText)
|
||||
data = jonny.parse(xhr.response) || xhr.response;
|
||||
|
||||
exec(p.success, data, xhr.statusText, xhr);
|
||||
};
|
||||
|
||||
xhr.send(data);
|
||||
};
|
||||
|
||||
module.exports.put = (url, body) => {
|
||||
const emitter = Emitify();
|
||||
const xhr = new XMLHttpRequest();
|
||||
|
||||
url = encodeURI(url).replace(/#/g, '%23');
|
||||
|
||||
xhr.open('put', url, true);
|
||||
|
||||
xhr.upload.onprogress = (event) => {
|
||||
if (!event.lengthComputable)
|
||||
return;
|
||||
|
||||
const percent = event.loaded / event.total * 100;
|
||||
const count = Math.round(percent);
|
||||
|
||||
emitter.emit('progress', count);
|
||||
};
|
||||
|
||||
xhr.onreadystatechange = () => {
|
||||
const over = xhr.readyState === xhr.DONE;
|
||||
const OK = 200;
|
||||
|
||||
if (!over)
|
||||
return;
|
||||
|
||||
if (xhr.status === OK) {
|
||||
emitter.emit('progress', 100);
|
||||
return emitter.emit('end');
|
||||
}
|
||||
|
||||
const error = Error(xhr.responseText);
|
||||
emitter.emit('error', error);
|
||||
};
|
||||
|
||||
xhr.send(body);
|
||||
|
||||
return emitter;
|
||||
};
|
||||
70
client/dom/operations/rename-current.js
Normal file
70
client/dom/operations/rename-current.js
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
'use strict';
|
||||
|
||||
/* global CloudCmd */
|
||||
const capitalize = require('just-capitalize');
|
||||
|
||||
const _Dialog = require('../dialog');
|
||||
const Storage = require('../storage');
|
||||
const RESTful = require('../rest');
|
||||
|
||||
const _currentFile = require('../current-file.mjs');
|
||||
|
||||
module.exports = async (current, overrides = {}) => {
|
||||
const {
|
||||
refresh = CloudCmd.refresh,
|
||||
Dialog = _Dialog,
|
||||
currentFile = _currentFile,
|
||||
} = overrides;
|
||||
|
||||
const {
|
||||
isCurrentFile,
|
||||
getCurrentName,
|
||||
getCurrentFile,
|
||||
getCurrentByName,
|
||||
getCurrentType,
|
||||
getCurrentDirPath,
|
||||
setCurrentName,
|
||||
} = currentFile;
|
||||
|
||||
if (!isCurrentFile(current))
|
||||
current = getCurrentFile();
|
||||
|
||||
const from = getCurrentName(current);
|
||||
|
||||
if (from === '..')
|
||||
return Dialog.alert.noFiles();
|
||||
|
||||
const [cancel, to] = await Dialog.prompt('Rename', from);
|
||||
|
||||
if (cancel)
|
||||
return;
|
||||
|
||||
const nextFile = getCurrentByName(to);
|
||||
|
||||
if (nextFile) {
|
||||
const type = getCurrentType(nextFile);
|
||||
const msg = `${capitalize(type)} "${to}" already exists. Proceed?`;
|
||||
const [cancel] = await Dialog.confirm(msg);
|
||||
|
||||
if (cancel)
|
||||
return;
|
||||
}
|
||||
|
||||
if (from === to)
|
||||
return;
|
||||
|
||||
const dirPath = getCurrentDirPath();
|
||||
|
||||
const fromFull = `${dirPath}${from}`;
|
||||
const toFull = `${dirPath}${to}`;
|
||||
|
||||
const [e] = await RESTful.rename(fromFull, toFull);
|
||||
|
||||
if (e)
|
||||
return;
|
||||
|
||||
setCurrentName(to, current);
|
||||
|
||||
Storage.remove(dirPath);
|
||||
refresh();
|
||||
};
|
||||
89
client/dom/operations/rename-current.spec.js
Normal file
89
client/dom/operations/rename-current.spec.js
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
'use strict';
|
||||
|
||||
const {test, stub} = require('supertape');
|
||||
|
||||
const renameCurrent = require('./rename-current');
|
||||
|
||||
test('cloudcmd: client: dom: renameCurrent: isCurrentFile', async (t) => {
|
||||
const current = {};
|
||||
const isCurrentFile = stub();
|
||||
|
||||
const currentFile = stubCurrentFile({
|
||||
isCurrentFile,
|
||||
});
|
||||
|
||||
await renameCurrent(current, {
|
||||
Dialog: stubDialog(),
|
||||
currentFile,
|
||||
});
|
||||
|
||||
t.calledWith(isCurrentFile, [current], 'should call isCurrentFile');
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('cloudcmd: client: dom: renameCurrent: file exist', async (t) => {
|
||||
const current = {};
|
||||
const name = 'hello';
|
||||
|
||||
const prompt = stub().returns([null, name]);
|
||||
const confirm = stub().returns([true]);
|
||||
|
||||
const getCurrentByName = stub().returns(current);
|
||||
const getCurrentType = stub().returns('directory');
|
||||
|
||||
const Dialog = stubDialog({
|
||||
confirm,
|
||||
prompt,
|
||||
});
|
||||
|
||||
const currentFile = stubCurrentFile({
|
||||
getCurrentByName,
|
||||
getCurrentType,
|
||||
});
|
||||
|
||||
await renameCurrent(null, {
|
||||
Dialog,
|
||||
currentFile,
|
||||
});
|
||||
|
||||
const expected = 'Directory "hello" already exists. Proceed?';
|
||||
|
||||
t.calledWith(confirm, [expected], 'should call confirm');
|
||||
t.end();
|
||||
});
|
||||
|
||||
const stubDialog = (fns = {}) => {
|
||||
const {
|
||||
alert = stub().returns([]),
|
||||
confirm = stub().returns([]),
|
||||
prompt = stub().returns([]),
|
||||
} = fns;
|
||||
|
||||
return {
|
||||
alert,
|
||||
confirm,
|
||||
prompt,
|
||||
};
|
||||
};
|
||||
|
||||
const stubCurrentFile = (fns = {}) => {
|
||||
const {
|
||||
isCurrentFile = stub(),
|
||||
getCurrentName = stub(),
|
||||
getCurrentFile = stub(),
|
||||
getCurrentByName = stub(),
|
||||
getCurrentType = stub(),
|
||||
getCurrentDirPath = stub(),
|
||||
setCurrentName = stub(),
|
||||
} = fns;
|
||||
|
||||
return {
|
||||
isCurrentFile,
|
||||
getCurrentName,
|
||||
getCurrentFile,
|
||||
getCurrentByName,
|
||||
getCurrentType,
|
||||
getCurrentDirPath,
|
||||
setCurrentName,
|
||||
};
|
||||
};
|
||||
44
client/dom/rest.js
Normal file
44
client/dom/rest.js
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
'use strict';
|
||||
|
||||
const {tryToCatch} = require('try-to-catch');
|
||||
|
||||
const {encode} = require('../../common/entity');
|
||||
|
||||
const Images = require('./images.mjs');
|
||||
const IO = require('./io');
|
||||
const Dialog = require('./dialog');
|
||||
|
||||
const handleError = (promise) => async (...args) => {
|
||||
const [e, data] = await tryToCatch(promise, ...args);
|
||||
|
||||
if (!e)
|
||||
return [e, data];
|
||||
|
||||
const encoded = encode(e.message);
|
||||
|
||||
Images.show.error(encoded);
|
||||
Dialog.alert(encoded);
|
||||
|
||||
return [e, data];
|
||||
};
|
||||
|
||||
module.exports.delete = handleError(IO.delete);
|
||||
module.exports.patch = handleError(IO.patch);
|
||||
module.exports.write = handleError(IO.write);
|
||||
module.exports.createDirectory = handleError(IO.createDirectory);
|
||||
module.exports.read = handleError(IO.read);
|
||||
module.exports.copy = handleError(IO.copy);
|
||||
module.exports.pack = handleError(IO.pack);
|
||||
module.exports.extract = handleError(IO.extract);
|
||||
module.exports.move = handleError(IO.move);
|
||||
module.exports.rename = handleError(IO.rename);
|
||||
|
||||
module.exports.Config = {
|
||||
read: handleError(IO.Config.read),
|
||||
write: handleError(IO.Config.write),
|
||||
};
|
||||
|
||||
module.exports.Markdown = {
|
||||
read: handleError(IO.Markdown.read),
|
||||
render: handleError(IO.Markdown.render),
|
||||
};
|
||||
45
client/dom/select-by-pattern.js
Normal file
45
client/dom/select-by-pattern.js
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
'use strict';
|
||||
|
||||
let SelectType = '*.*';
|
||||
|
||||
const {getRegExp} = require('../../common/util');
|
||||
const {alert, prompt} = require('./dialog');
|
||||
|
||||
const DOM = require('.');
|
||||
|
||||
module.exports = async (msg, files) => {
|
||||
if (!files)
|
||||
return;
|
||||
|
||||
const allMsg = `Specify file type for ${msg} selection`;
|
||||
const [cancel, type] = await prompt(allMsg, SelectType);
|
||||
|
||||
if (cancel)
|
||||
return;
|
||||
|
||||
SelectType = type;
|
||||
|
||||
const regExp = getRegExp(type);
|
||||
let matches = 0;
|
||||
|
||||
for (const current of files) {
|
||||
const name = DOM.getCurrentName(current);
|
||||
|
||||
if (name === '..' || !regExp.test(name))
|
||||
continue;
|
||||
|
||||
++matches;
|
||||
|
||||
let isSelected = DOM.isSelected(current);
|
||||
const shouldSel = msg === 'expand';
|
||||
|
||||
if (shouldSel)
|
||||
isSelected = !isSelected;
|
||||
|
||||
if (isSelected)
|
||||
DOM.toggleSelectedFile(current);
|
||||
}
|
||||
|
||||
if (!matches)
|
||||
alert('No matches found!');
|
||||
};
|
||||
28
client/dom/storage.js
Normal file
28
client/dom/storage.js
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
'use strict';
|
||||
|
||||
const {parse, stringify} = JSON;
|
||||
|
||||
module.exports.set = async (name, data) => {
|
||||
localStorage.setItem(name, data);
|
||||
};
|
||||
|
||||
module.exports.setJson = async (name, data) => {
|
||||
localStorage.setItem(name, stringify(data));
|
||||
};
|
||||
|
||||
module.exports.get = async (name) => {
|
||||
return localStorage.getItem(name);
|
||||
};
|
||||
|
||||
module.exports.getJson = async (name) => {
|
||||
const data = localStorage.getItem(name);
|
||||
return parse(data);
|
||||
};
|
||||
|
||||
module.exports.clear = () => {
|
||||
localStorage.clear();
|
||||
};
|
||||
|
||||
module.exports.remove = (item) => {
|
||||
localStorage.removeItem(item);
|
||||
};
|
||||
108
client/dom/storage.spec.js
Normal file
108
client/dom/storage.spec.js
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
'use strict';
|
||||
|
||||
const {test, stub} = require('supertape');
|
||||
|
||||
const storage = require('./storage');
|
||||
|
||||
const {stringify} = JSON;
|
||||
|
||||
test('cloudcmd: client: storage: set', async (t) => {
|
||||
const {localStorage} = globalThis;
|
||||
const setItem = stub();
|
||||
|
||||
globalThis.localStorage = {
|
||||
setItem,
|
||||
};
|
||||
|
||||
await storage.set('hello', 'world');
|
||||
globalThis.localStorage = localStorage;
|
||||
|
||||
t.calledWith(setItem, ['hello', 'world'], 'should call setItem');
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('cloudcmd: client: storage: get', async (t) => {
|
||||
const {localStorage} = globalThis;
|
||||
const getItem = stub().returns('world');
|
||||
|
||||
globalThis.localStorage = {
|
||||
getItem,
|
||||
};
|
||||
|
||||
const result = await storage.get('hello');
|
||||
|
||||
globalThis.localStorage = localStorage;
|
||||
|
||||
t.equal(result, 'world');
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('cloudcmd: client: storage: getJson', async (t) => {
|
||||
const {localStorage} = globalThis;
|
||||
const expected = {
|
||||
hello: 'world',
|
||||
};
|
||||
|
||||
const getItem = stub().returns(stringify(expected));
|
||||
|
||||
globalThis.localStorage = {
|
||||
getItem,
|
||||
};
|
||||
|
||||
const result = await storage.getJson('hello');
|
||||
|
||||
globalThis.localStorage = localStorage;
|
||||
|
||||
t.deepEqual(result, expected);
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('cloudcmd: client: storage: setJson', async (t) => {
|
||||
const {localStorage} = globalThis;
|
||||
const data = {
|
||||
hello: 'world',
|
||||
};
|
||||
|
||||
const expected = stringify(data);
|
||||
const setItem = stub();
|
||||
|
||||
globalThis.localStorage = {
|
||||
setItem,
|
||||
};
|
||||
|
||||
await storage.setJson('hello', data);
|
||||
globalThis.localStorage = localStorage;
|
||||
|
||||
t.calledWith(setItem, ['hello', expected]);
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('cloudcmd: client: storage: remove', async (t) => {
|
||||
const {localStorage} = globalThis;
|
||||
const removeItem = stub();
|
||||
|
||||
globalThis.localStorage = {
|
||||
removeItem,
|
||||
};
|
||||
|
||||
await storage.remove('hello');
|
||||
globalThis.localStorage = localStorage;
|
||||
|
||||
t.calledWith(removeItem, ['hello'], 'should call removeItem');
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('cloudcmd: client: storage: clear', async (t) => {
|
||||
const {localStorage} = globalThis;
|
||||
const clear = stub();
|
||||
|
||||
globalThis.localStorage = {
|
||||
clear,
|
||||
};
|
||||
|
||||
await storage.clear();
|
||||
globalThis.localStorage = localStorage;
|
||||
|
||||
t.calledWithNoArgs(clear, 'should call clear');
|
||||
t.end();
|
||||
});
|
||||
72
client/dom/upload-files.js
Normal file
72
client/dom/upload-files.js
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
'use strict';
|
||||
|
||||
/* global CloudCmd */
|
||||
const {eachSeries} = require('execon');
|
||||
const wraptile = require('wraptile');
|
||||
|
||||
const load = require('./load');
|
||||
const Images = require('./images.mjs');
|
||||
const {alert} = require('./dialog');
|
||||
|
||||
const {FS} = require('../../common/cloudfunc.mjs');
|
||||
|
||||
const {getCurrentDirPath: getPathWhenRootEmpty} = require('.');
|
||||
const loadFile = wraptile(_loadFile);
|
||||
|
||||
const onEnd = wraptile(_onEnd);
|
||||
|
||||
module.exports = (dir, files) => {
|
||||
if (!files) {
|
||||
files = dir;
|
||||
dir = getPathWhenRootEmpty();
|
||||
}
|
||||
|
||||
const n = files.length;
|
||||
|
||||
if (!n)
|
||||
return;
|
||||
|
||||
const array = Array.from(files);
|
||||
const {name} = files[0];
|
||||
|
||||
eachSeries(array, loadFile(dir, n), onEnd(name));
|
||||
};
|
||||
|
||||
function _onEnd(currentName) {
|
||||
CloudCmd.refresh({
|
||||
currentName,
|
||||
});
|
||||
}
|
||||
|
||||
function _loadFile(dir, n, file, callback) {
|
||||
let i = 0;
|
||||
|
||||
const {name} = file;
|
||||
const path = dir + name;
|
||||
const {prefixURL} = CloudCmd;
|
||||
const api = prefixURL + FS;
|
||||
|
||||
const percent = (i, n, per = 100) => {
|
||||
return Math.round(i * per / n);
|
||||
};
|
||||
|
||||
const step = (n) => 100 / n;
|
||||
|
||||
++i;
|
||||
|
||||
load
|
||||
.put(api + path, file)
|
||||
.on('error', showError)
|
||||
.on('end', callback)
|
||||
.on('progress', (count) => {
|
||||
const max = step(n);
|
||||
const value = (i - 1) * max + percent(count, 100, max);
|
||||
|
||||
Images.show.load('top');
|
||||
Images.setProgress(Math.round(value));
|
||||
});
|
||||
}
|
||||
|
||||
function showError({message}) {
|
||||
alert(message);
|
||||
}
|
||||
44
client/get-json-from-file-table.mjs
Normal file
44
client/get-json-from-file-table.mjs
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
/* global DOM */
|
||||
/**
|
||||
* Функция генерирует JSON из html-таблицы файлов и
|
||||
* используеться при первом заходе в корень
|
||||
*/
|
||||
export const getJsonFromFileTable = () => {
|
||||
const Info = DOM.CurrentInfo;
|
||||
const path = DOM.getCurrentDirPath();
|
||||
const infoFiles = Info.files || [];
|
||||
|
||||
const files = infoFiles
|
||||
.filter(notParent)
|
||||
.map(parse);
|
||||
|
||||
const fileTable = {
|
||||
path,
|
||||
files,
|
||||
};
|
||||
|
||||
return fileTable;
|
||||
};
|
||||
|
||||
const notParent = (current) => {
|
||||
const name = DOM.getCurrentName(current);
|
||||
return name !== '..';
|
||||
};
|
||||
|
||||
const parse = (current) => {
|
||||
const name = DOM.getCurrentName(current);
|
||||
const size = DOM.getCurrentSize(current);
|
||||
const owner = DOM.getCurrentOwner(current);
|
||||
const mode = DOM.getCurrentMode(current);
|
||||
const date = DOM.getCurrentDate(current);
|
||||
const type = DOM.getCurrentType(current);
|
||||
|
||||
return {
|
||||
name,
|
||||
size,
|
||||
mode,
|
||||
owner,
|
||||
date,
|
||||
type,
|
||||
};
|
||||
};
|
||||
17
client/key/binder.js
Normal file
17
client/key/binder.js
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
'use strict';
|
||||
|
||||
module.exports.createBinder = () => {
|
||||
let binded = false;
|
||||
|
||||
return {
|
||||
isBind() {
|
||||
return binded;
|
||||
},
|
||||
setBind() {
|
||||
binded = true;
|
||||
},
|
||||
unsetBind() {
|
||||
binded = false;
|
||||
},
|
||||
};
|
||||
};
|
||||
536
client/key/index.mjs
Normal file
536
client/key/index.mjs
Normal file
|
|
@ -0,0 +1,536 @@
|
|||
/* global CloudCmd, DOM */
|
||||
import clipboard from '@cloudcmd/clipboard';
|
||||
import {fullstore} from 'fullstore';
|
||||
import * as Events from '#dom/events';
|
||||
import * as Buffer from '../dom/buffer.mjs';
|
||||
import KEY from './key.js';
|
||||
import _vim from './vim/index.js';
|
||||
import setCurrentByChar from './set-current-by-char.js';
|
||||
import {createBinder} from './binder.js';
|
||||
|
||||
const Chars = fullstore();
|
||||
|
||||
const toggleVim = (keyCode, overrides = {}) => {
|
||||
const {_config, config} = overrides;
|
||||
|
||||
if (keyCode === KEY.ESC)
|
||||
_config('vim', !config('vim'));
|
||||
};
|
||||
|
||||
const isUndefined = (a) => typeof a === 'undefined';
|
||||
|
||||
Chars([]);
|
||||
|
||||
const {assign} = Object;
|
||||
const binder = createBinder();
|
||||
|
||||
const bind = () => {
|
||||
Events.addKey(listener, true);
|
||||
binder.setBind();
|
||||
};
|
||||
|
||||
export const Key = assign(binder, KEY, {
|
||||
bind,
|
||||
});
|
||||
|
||||
export const _listener = listener;
|
||||
|
||||
function getChar(event) {
|
||||
/*
|
||||
* event.keyIdentifier deprecated in chrome v51
|
||||
* but event.key is absent in chrome <= v51
|
||||
*/
|
||||
const {
|
||||
key,
|
||||
shift,
|
||||
keyCode,
|
||||
keyIdentifier,
|
||||
} = event;
|
||||
|
||||
const char = key || fromCharCode(keyIdentifier);
|
||||
const symbol = getSymbol(shift, keyCode);
|
||||
|
||||
return [symbol, char];
|
||||
}
|
||||
|
||||
async function listener(event, overrides = {}) {
|
||||
const {
|
||||
config = CloudCmd.config,
|
||||
_config = CloudCmd._config,
|
||||
switchKey = _switchKey,
|
||||
vim = _vim,
|
||||
} = overrides;
|
||||
|
||||
const {keyCode} = event;
|
||||
|
||||
// strange chrome bug calles listener twice
|
||||
// in second time event misses a lot fields
|
||||
if (isUndefined(event.altKey))
|
||||
return;
|
||||
|
||||
const alt = event.altKey;
|
||||
const ctrl = event.ctrlKey;
|
||||
const meta = event.metaKey;
|
||||
const isBetween = keyCode >= KEY.ZERO && keyCode <= KEY.Z;
|
||||
const isNumpad = /Numpad/.test(event.code);
|
||||
|
||||
const [symbol, char] = getChar(event);
|
||||
|
||||
if (!binder.isBind())
|
||||
return;
|
||||
|
||||
toggleVim(keyCode, {
|
||||
config,
|
||||
_config,
|
||||
});
|
||||
|
||||
const isVim = config('vim');
|
||||
|
||||
if (!isVim && !isNumpad && !alt && !ctrl && !meta && (isBetween || symbol))
|
||||
return setCurrentByChar(char, Chars);
|
||||
|
||||
Chars([]);
|
||||
await switchKey(event);
|
||||
|
||||
if (keyCode >= KEY.F1 && keyCode <= KEY.F10)
|
||||
return;
|
||||
|
||||
if (isVim)
|
||||
vim(char, event);
|
||||
}
|
||||
|
||||
function getSymbol(shift, keyCode) {
|
||||
switch(keyCode) {
|
||||
case KEY.DOT:
|
||||
return '.';
|
||||
|
||||
case KEY.HYPHEN:
|
||||
return shift ? '_' : '-';
|
||||
|
||||
case KEY.EQUAL:
|
||||
return shift ? '+' : '=';
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
function fromCharCode(keyIdentifier) {
|
||||
const code = keyIdentifier.substring(2);
|
||||
const hex = parseInt(code, 16);
|
||||
|
||||
return String.fromCharCode(hex);
|
||||
}
|
||||
|
||||
async function _switchKey(event) {
|
||||
const Info = DOM.CurrentInfo;
|
||||
let i;
|
||||
let isSelected;
|
||||
let prev;
|
||||
let next;
|
||||
let current = Info.element;
|
||||
let dataName;
|
||||
|
||||
const {
|
||||
name,
|
||||
panel,
|
||||
path,
|
||||
isDir,
|
||||
} = Info;
|
||||
|
||||
const {
|
||||
Operation,
|
||||
changeDir,
|
||||
config,
|
||||
} = CloudCmd;
|
||||
|
||||
const {keyCode} = event;
|
||||
|
||||
const alt = event.altKey;
|
||||
const shift = event.shiftKey;
|
||||
const ctrl = event.ctrlKey;
|
||||
const meta = event.metaKey;
|
||||
const ctrlMeta = ctrl || meta;
|
||||
|
||||
if (current) {
|
||||
prev = current.previousSibling;
|
||||
next = current.nextSibling;
|
||||
}
|
||||
|
||||
switch(keyCode) {
|
||||
case KEY.TAB:
|
||||
DOM.changePanel();
|
||||
event.preventDefault();
|
||||
break;
|
||||
|
||||
case KEY.INSERT:
|
||||
DOM
|
||||
.toggleSelectedFile(current)
|
||||
.setCurrentFile(next);
|
||||
break;
|
||||
|
||||
case KEY.INSERT_MAC:
|
||||
DOM
|
||||
.toggleSelectedFile(current)
|
||||
.setCurrentFile(next);
|
||||
break;
|
||||
|
||||
case KEY.DELETE:
|
||||
if (shift)
|
||||
Operation.show('delete:silent');
|
||||
else
|
||||
Operation.show('delete');
|
||||
|
||||
break;
|
||||
|
||||
case KEY.ASTERISK:
|
||||
DOM.toggleAllSelectedFiles(current);
|
||||
break;
|
||||
|
||||
case KEY.PLUS:
|
||||
DOM.expandSelection();
|
||||
event.preventDefault();
|
||||
break;
|
||||
|
||||
case KEY.MINUS:
|
||||
DOM.shrinkSelection();
|
||||
event.preventDefault();
|
||||
break;
|
||||
|
||||
case KEY.F1:
|
||||
CloudCmd.Help.show();
|
||||
event.preventDefault();
|
||||
break;
|
||||
|
||||
case KEY.F2:
|
||||
CloudCmd.UserMenu.show();
|
||||
break;
|
||||
|
||||
case KEY.F3:
|
||||
event.preventDefault();
|
||||
|
||||
if (Info.isDir)
|
||||
await changeDir(path);
|
||||
else if (shift)
|
||||
CloudCmd.View.show(null, {
|
||||
raw: true,
|
||||
});
|
||||
else if (ctrlMeta)
|
||||
CloudCmd.sortPanel('name');
|
||||
else
|
||||
CloudCmd.View.show();
|
||||
|
||||
break;
|
||||
|
||||
case KEY.F4:
|
||||
if (config('vim'))
|
||||
CloudCmd.EditFileVim.show();
|
||||
else
|
||||
CloudCmd.EditFile.show();
|
||||
|
||||
event.preventDefault();
|
||||
break;
|
||||
|
||||
case KEY.F5:
|
||||
if (ctrlMeta)
|
||||
CloudCmd.sortPanel('date');
|
||||
else if (alt)
|
||||
Operation.show('pack');
|
||||
else
|
||||
Operation.show('copy');
|
||||
|
||||
event.preventDefault();
|
||||
break;
|
||||
|
||||
case KEY.F6:
|
||||
if (ctrlMeta)
|
||||
CloudCmd.sortPanel('size');
|
||||
else if (shift)
|
||||
DOM.renameCurrent(current);
|
||||
else
|
||||
Operation.show('move');
|
||||
|
||||
event.preventDefault();
|
||||
break;
|
||||
|
||||
case KEY.F7:
|
||||
if (shift)
|
||||
DOM.promptNewFile();
|
||||
else
|
||||
DOM.promptNewDir();
|
||||
|
||||
event.preventDefault();
|
||||
break;
|
||||
|
||||
case KEY.F8:
|
||||
Operation.show('delete');
|
||||
event.preventDefault();
|
||||
break;
|
||||
|
||||
case KEY.F9:
|
||||
if (alt)
|
||||
Operation.show('extract');
|
||||
else
|
||||
CloudCmd.Menu.show();
|
||||
|
||||
event.preventDefault();
|
||||
break;
|
||||
|
||||
case KEY.F10:
|
||||
CloudCmd.Config.show();
|
||||
event.preventDefault();
|
||||
break;
|
||||
|
||||
case KEY.TRA:
|
||||
event.preventDefault();
|
||||
|
||||
if (shift)
|
||||
return CloudCmd.Terminal.show();
|
||||
|
||||
CloudCmd.Konsole.show();
|
||||
break;
|
||||
|
||||
case KEY.BRACKET_CLOSE:
|
||||
CloudCmd.Konsole.show();
|
||||
event.preventDefault();
|
||||
break;
|
||||
|
||||
case KEY.SPACE:
|
||||
event.preventDefault();
|
||||
|
||||
if (!isDir || name === '..')
|
||||
isSelected = true;
|
||||
else
|
||||
isSelected = DOM.isSelected(current);
|
||||
|
||||
if (!isSelected)
|
||||
await DOM.loadCurrentSize(current);
|
||||
|
||||
DOM.toggleSelectedFile(current);
|
||||
|
||||
break;
|
||||
|
||||
case KEY.U:
|
||||
if (ctrlMeta) {
|
||||
DOM.swapPanels();
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
/* navigation on file table: *
|
||||
* in case of pressing button 'up', *
|
||||
* select previous row */
|
||||
case KEY.UP:
|
||||
if (shift)
|
||||
DOM.toggleSelectedFile(current);
|
||||
|
||||
DOM.setCurrentFile(prev);
|
||||
event.preventDefault();
|
||||
break;
|
||||
|
||||
/* in case of pressing button 'down', *
|
||||
* select next row */
|
||||
case KEY.DOWN:
|
||||
if (shift)
|
||||
DOM.toggleSelectedFile(current);
|
||||
|
||||
DOM.setCurrentFile(next);
|
||||
event.preventDefault();
|
||||
break;
|
||||
|
||||
case KEY.LEFT:
|
||||
if (!alt)
|
||||
return;
|
||||
|
||||
event.preventDefault();
|
||||
|
||||
dataName = Info.panel.getAttribute('data-name');
|
||||
|
||||
if (dataName === 'js-right')
|
||||
DOM.duplicatePanel();
|
||||
|
||||
break;
|
||||
|
||||
case KEY.RIGHT:
|
||||
if (!alt)
|
||||
return;
|
||||
|
||||
event.preventDefault();
|
||||
|
||||
dataName = Info.panel.getAttribute('data-name');
|
||||
|
||||
if (dataName === 'js-left')
|
||||
DOM.duplicatePanel();
|
||||
|
||||
break;
|
||||
|
||||
/* in case of pressing button 'Home', *
|
||||
* go to top element */
|
||||
case KEY.HOME:
|
||||
DOM.setCurrentFile(Info.first);
|
||||
event.preventDefault();
|
||||
break;
|
||||
|
||||
/* in case of pressing button 'End', select last element */
|
||||
case KEY.END:
|
||||
DOM.setCurrentFile(Info.last);
|
||||
event.preventDefault();
|
||||
break;
|
||||
|
||||
/* если нажали клавишу page down проматываем экран */
|
||||
case KEY.PAGE_DOWN:
|
||||
DOM.scrollByPages(panel, 1);
|
||||
|
||||
for (i = 0; i < 30; i++) {
|
||||
if (!current.nextSibling)
|
||||
break;
|
||||
|
||||
current = current.nextSibling;
|
||||
}
|
||||
|
||||
DOM.setCurrentFile(current);
|
||||
event.preventDefault();
|
||||
break;
|
||||
|
||||
/* если нажали клавишу page up проматываем экран */
|
||||
case KEY.PAGE_UP:
|
||||
DOM.scrollByPages(panel, -1);
|
||||
|
||||
for (i = 0; i < 30; i++) {
|
||||
if (!current.previousSibling)
|
||||
break;
|
||||
|
||||
current = current.previousSibling;
|
||||
}
|
||||
|
||||
DOM.setCurrentFile(current);
|
||||
event.preventDefault();
|
||||
break;
|
||||
|
||||
case KEY.ENTER:
|
||||
if (Info.isDir)
|
||||
await changeDir(path);
|
||||
else
|
||||
CloudCmd.View.show();
|
||||
|
||||
break;
|
||||
|
||||
case KEY.BACKSPACE:
|
||||
CloudCmd.goToParentDir();
|
||||
event.preventDefault();
|
||||
break;
|
||||
|
||||
case KEY.BACKSLASH:
|
||||
if (ctrlMeta)
|
||||
await changeDir('/');
|
||||
|
||||
break;
|
||||
|
||||
case KEY.A:
|
||||
if (ctrlMeta) {
|
||||
DOM.selectAllFiles();
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case KEY.G:
|
||||
if (alt) {
|
||||
DOM.goToDirectory();
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case KEY.M:
|
||||
if (ctrlMeta) {
|
||||
if (config('vim'))
|
||||
CloudCmd.EditNamesVim.show();
|
||||
else
|
||||
CloudCmd.EditNames.show();
|
||||
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case KEY.P:
|
||||
if (!ctrlMeta)
|
||||
return;
|
||||
|
||||
event.preventDefault();
|
||||
clipboard
|
||||
.writeText(Info.dirPath)
|
||||
.catch(CloudCmd.log);
|
||||
|
||||
break;
|
||||
|
||||
/**
|
||||
* обновляем страницу,
|
||||
* загружаем содержимое каталога
|
||||
* при этом данные берём всегда с
|
||||
* сервера, а не из кэша
|
||||
* (обновляем кэш)
|
||||
*/
|
||||
case KEY.R:
|
||||
if (ctrlMeta) {
|
||||
CloudCmd.log('reloading page...\n');
|
||||
CloudCmd.refresh();
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case KEY.C:
|
||||
if (ctrlMeta)
|
||||
Buffer.copy();
|
||||
|
||||
break;
|
||||
|
||||
case KEY.X:
|
||||
if (ctrlMeta)
|
||||
Buffer.cut();
|
||||
|
||||
break;
|
||||
|
||||
case KEY.V:
|
||||
if (ctrlMeta)
|
||||
Buffer.paste();
|
||||
|
||||
break;
|
||||
|
||||
case KEY.Z:
|
||||
if (ctrlMeta)
|
||||
Buffer.clear();
|
||||
|
||||
break;
|
||||
|
||||
case KEY.COLON:
|
||||
CloudCmd.CommandLine.show();
|
||||
event.preventDefault();
|
||||
break;
|
||||
|
||||
/* чистим хранилище */
|
||||
case KEY.D:
|
||||
if (ctrlMeta) {
|
||||
CloudCmd.log('clearing storage...');
|
||||
await DOM.Storage.clear();
|
||||
CloudCmd.log('storage cleared');
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case KEY.DOT:
|
||||
if (meta && shift) {
|
||||
const showDotFiles = !CloudCmd.config('showDotFiles');
|
||||
CloudCmd._config('showDotFiles', showDotFiles);
|
||||
CloudCmd.refresh();
|
||||
await DOM.RESTful.Config.write({
|
||||
showDotFiles,
|
||||
});
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
61
client/key/index.spec.js
Normal file
61
client/key/index.spec.js
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
'use strict';
|
||||
|
||||
require('css-modules-require-hook/preset');
|
||||
|
||||
const autoGlobals = require('auto-globals');
|
||||
const supertape = require('supertape');
|
||||
|
||||
const {ESC} = require('./key');
|
||||
|
||||
const {Key, _listener} = require('./index.mjs');
|
||||
|
||||
const {getDOM, getCloudCmd} = require('./vim/globals.fixture');
|
||||
const test = autoGlobals(supertape);
|
||||
const {stub} = supertape;
|
||||
|
||||
globalThis.DOM = getDOM();
|
||||
globalThis.CloudCmd = getCloudCmd();
|
||||
|
||||
test('cloudcmd: client: key: enable vim', async (t) => {
|
||||
const vim = stub();
|
||||
const config = stub().returns(true);
|
||||
const _config = stub();
|
||||
|
||||
const event = {
|
||||
keyCode: ESC,
|
||||
key: 'Escape',
|
||||
altKey: false,
|
||||
};
|
||||
|
||||
Key.setBind();
|
||||
|
||||
await _listener(event, {
|
||||
vim,
|
||||
config,
|
||||
_config,
|
||||
switchKey: stub(),
|
||||
});
|
||||
|
||||
t.calledWith(vim, ['Escape', event]);
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('cloudcmd: client: key: disable vim', async (t) => {
|
||||
const _config = stub();
|
||||
const config = stub();
|
||||
const event = {
|
||||
keyCode: ESC,
|
||||
key: 'Escape',
|
||||
altKey: false,
|
||||
};
|
||||
|
||||
Key.setBind();
|
||||
await _listener(event, {
|
||||
config,
|
||||
_config,
|
||||
switchKey: stub(),
|
||||
});
|
||||
|
||||
t.calledWith(_config, ['vim', true]);
|
||||
t.end();
|
||||
});
|
||||
81
client/key/key.js
Normal file
81
client/key/key.js
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
'use strict';
|
||||
|
||||
module.exports = {
|
||||
BACKSPACE: 8,
|
||||
TAB: 9,
|
||||
ENTER: 13,
|
||||
CAPSLOCK: 20,
|
||||
ESC: 27,
|
||||
|
||||
SPACE: 32,
|
||||
PAGE_UP: 33,
|
||||
PAGE_DOWN: 34,
|
||||
END: 35,
|
||||
HOME: 36,
|
||||
|
||||
LEFT: 37,
|
||||
UP: 38,
|
||||
RIGHT: 39,
|
||||
DOWN: 40,
|
||||
|
||||
INSERT: 45,
|
||||
DELETE: 46,
|
||||
|
||||
ZERO: 48,
|
||||
|
||||
SEMICOLON: 52,
|
||||
|
||||
A: 65,
|
||||
|
||||
C: 67,
|
||||
D: 68,
|
||||
|
||||
G: 71,
|
||||
|
||||
J: 74,
|
||||
K: 75,
|
||||
|
||||
M: 77,
|
||||
|
||||
O: 79,
|
||||
P: 80,
|
||||
Q: 81,
|
||||
R: 82,
|
||||
S: 83,
|
||||
T: 84,
|
||||
U: 85,
|
||||
|
||||
V: 86,
|
||||
|
||||
X: 88,
|
||||
|
||||
Z: 90,
|
||||
|
||||
INSERT_MAC: 96,
|
||||
|
||||
ASTERISK: 106,
|
||||
PLUS: 107,
|
||||
MINUS: 109,
|
||||
|
||||
F1: 112,
|
||||
F2: 113,
|
||||
F3: 114,
|
||||
F4: 115,
|
||||
F5: 116,
|
||||
F6: 117,
|
||||
F7: 118,
|
||||
F8: 119,
|
||||
F9: 120,
|
||||
F10: 121,
|
||||
|
||||
COLON: 186,
|
||||
EQUAL: 187,
|
||||
HYPHEN: 189,
|
||||
DOT: 190,
|
||||
SLASH: 191,
|
||||
/* Typewritten Reverse Apostrophe (`) */
|
||||
TRA: 192,
|
||||
BACKSLASH: 220,
|
||||
|
||||
BRACKET_CLOSE: 221,
|
||||
};
|
||||
60
client/key/set-current-by-char.js
Normal file
60
client/key/set-current-by-char.js
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
/* global DOM */
|
||||
|
||||
'use strict';
|
||||
|
||||
const {escapeRegExp} = require('../../common/util');
|
||||
|
||||
module.exports = function setCurrentByChar(char, charStore) {
|
||||
const Info = DOM.CurrentInfo;
|
||||
let firstByName;
|
||||
let skipCount = 0;
|
||||
let setted = false;
|
||||
let i = 0;
|
||||
|
||||
const escapeChar = escapeRegExp(char);
|
||||
const regExp = new RegExp(`^${escapeChar}.*$`, 'i');
|
||||
const {files} = Info;
|
||||
const chars = charStore();
|
||||
const n = chars.length;
|
||||
|
||||
while (i < n && char === chars[i])
|
||||
i++;
|
||||
|
||||
if (!i)
|
||||
charStore([]);
|
||||
|
||||
const skipN = skipCount = i;
|
||||
|
||||
charStore(charStore().concat(char));
|
||||
|
||||
const names = DOM.getFilenames(files);
|
||||
const isTest = (a) => regExp.test(a);
|
||||
const isRoot = (a) => a === '..';
|
||||
const not = (f) => (a) => !f(a);
|
||||
|
||||
const setCurrent = (name) => {
|
||||
const byName = DOM.getCurrentByName(name);
|
||||
|
||||
if (!skipCount) {
|
||||
setted = true;
|
||||
DOM.setCurrentFile(byName);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (skipN === skipCount)
|
||||
firstByName = byName;
|
||||
|
||||
--skipCount;
|
||||
};
|
||||
|
||||
names
|
||||
.filter(isTest)
|
||||
.filter(not(isRoot))
|
||||
.some(setCurrent);
|
||||
|
||||
if (!setted) {
|
||||
DOM.setCurrentFile(firstByName);
|
||||
charStore([char]);
|
||||
}
|
||||
};
|
||||
49
client/key/vim/find.js
Normal file
49
client/key/vim/find.js
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
'use strict';
|
||||
|
||||
const {fullstore} = require('fullstore');
|
||||
const limier = require('limier');
|
||||
|
||||
const searchStore = fullstore([]);
|
||||
const searchIndex = fullstore(0);
|
||||
|
||||
module.exports.find = (value, names) => {
|
||||
const result = limier(value, names);
|
||||
|
||||
searchStore(result);
|
||||
searchIndex(0);
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
module.exports.findNext = () => {
|
||||
const names = searchStore();
|
||||
const index = next(searchIndex(), names.length);
|
||||
|
||||
searchIndex(index);
|
||||
return names[searchIndex()];
|
||||
};
|
||||
|
||||
module.exports.findPrevious = () => {
|
||||
const names = searchStore();
|
||||
const index = previous(searchIndex(), names.length);
|
||||
|
||||
searchIndex(index);
|
||||
return names[index];
|
||||
};
|
||||
|
||||
module.exports._next = next;
|
||||
module.exports._previous = previous;
|
||||
|
||||
function next(index, length) {
|
||||
if (index === length - 1)
|
||||
return 0;
|
||||
|
||||
return ++index;
|
||||
}
|
||||
|
||||
function previous(index, length) {
|
||||
if (!index)
|
||||
return length - 1;
|
||||
|
||||
return --index;
|
||||
}
|
||||
24
client/key/vim/find.spec.js
Normal file
24
client/key/vim/find.spec.js
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
'use strict';
|
||||
|
||||
const test = require('supertape');
|
||||
const dir = './';
|
||||
|
||||
const {getDOM} = require('./globals.fixture');
|
||||
|
||||
globalThis.DOM = getDOM();
|
||||
|
||||
const {_next, _previous} = require(`${dir}find`);
|
||||
|
||||
test('cloudcmd: client: vim: _next', (t) => {
|
||||
const result = _next(1, 2);
|
||||
|
||||
t.notOk(result, 'should return 0');
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('cloudcmd: client: vim: _previous', (t) => {
|
||||
const result = _previous(0, 2);
|
||||
|
||||
t.equal(result, 1, 'should return 1');
|
||||
t.end();
|
||||
});
|
||||
48
client/key/vim/globals.fixture.js
Normal file
48
client/key/vim/globals.fixture.js
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
'use strict';
|
||||
|
||||
const noop = () => {};
|
||||
|
||||
module.exports.getDOM = () => {
|
||||
const prompt = Promise.resolve.bind(Promise);
|
||||
const CurrentInfo = {
|
||||
element: {},
|
||||
files: [],
|
||||
};
|
||||
|
||||
const Buffer = {
|
||||
copy: noop,
|
||||
paste: noop,
|
||||
};
|
||||
|
||||
const Dialog = {
|
||||
prompt,
|
||||
};
|
||||
|
||||
return {
|
||||
Buffer,
|
||||
CurrentInfo,
|
||||
Dialog,
|
||||
selectFile: noop,
|
||||
unselectFile: noop,
|
||||
unselectFiles: noop,
|
||||
setCurrentFile: noop,
|
||||
getCurrentName: noop,
|
||||
setCurrentByName: noop,
|
||||
toggleSelectedFile: noop,
|
||||
prompNewDirectory: noop,
|
||||
promptNewFile: noop,
|
||||
};
|
||||
};
|
||||
|
||||
module.exports.getCloudCmd = () => {
|
||||
const show = () => {};
|
||||
|
||||
return {
|
||||
Operation: {
|
||||
show,
|
||||
},
|
||||
|
||||
config: noop,
|
||||
_config: noop,
|
||||
};
|
||||
};
|
||||
140
client/key/vim/index.js
Normal file
140
client/key/vim/index.js
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
'use strict';
|
||||
|
||||
/* global CloudCmd */
|
||||
/* global DOM */
|
||||
const vim = require('./vim');
|
||||
const finder = require('./find');
|
||||
const {
|
||||
setCurrent,
|
||||
selectFileNotParent,
|
||||
} = require('./set-current');
|
||||
|
||||
module.exports = (key, event, overrides = {}) => {
|
||||
const defaults = {
|
||||
...globalThis.DOM,
|
||||
...globalThis.CloudCmd,
|
||||
};
|
||||
|
||||
const deps = {
|
||||
...defaults,
|
||||
...overrides,
|
||||
};
|
||||
|
||||
const operations = getOperations(event, deps);
|
||||
|
||||
vim(key, operations, deps);
|
||||
};
|
||||
|
||||
const getOperations = (event, deps) => {
|
||||
const {
|
||||
Info = globalThis.DOM.CurrentInfo,
|
||||
CloudCmd = globalThis.CloudCmd,
|
||||
Operation,
|
||||
unselectFiles,
|
||||
setCurrentFile,
|
||||
setCurrentByName,
|
||||
getCurrentName,
|
||||
prompt = globalThis.DOM.Dialog.prompt,
|
||||
preventDefault = event?.preventDefault?.bind(event),
|
||||
|
||||
toggleSelectedFile,
|
||||
Buffer = {},
|
||||
createFindNext = _createFindNext,
|
||||
} = deps;
|
||||
|
||||
return {
|
||||
findNext: createFindNext({
|
||||
setCurrentByName,
|
||||
}),
|
||||
escape: unselectFiles,
|
||||
|
||||
remove: () => {
|
||||
Operation.show('delete');
|
||||
},
|
||||
|
||||
makeDirectory: () => {
|
||||
event.stopImmediatePropagation();
|
||||
event.preventDefault();
|
||||
DOM.promptNewDir();
|
||||
},
|
||||
|
||||
makeFile: () => {
|
||||
event.stopImmediatePropagation();
|
||||
event.preventDefault();
|
||||
DOM.promptNewFile();
|
||||
},
|
||||
|
||||
terminal: () => {
|
||||
CloudCmd.Terminal.show();
|
||||
},
|
||||
|
||||
edit: () => {
|
||||
CloudCmd.EditFileVim.show();
|
||||
},
|
||||
|
||||
copy: () => {
|
||||
Buffer.copy();
|
||||
unselectFiles();
|
||||
},
|
||||
|
||||
select: () => {
|
||||
const current = Info.element;
|
||||
toggleSelectedFile(current);
|
||||
},
|
||||
|
||||
paste: Buffer.paste,
|
||||
|
||||
moveNext: ({count, isVisual, isDelete}) => {
|
||||
setCurrent('next', {
|
||||
count,
|
||||
isVisual,
|
||||
isDelete,
|
||||
}, {
|
||||
Info,
|
||||
setCurrentFile,
|
||||
unselectFiles,
|
||||
Operation,
|
||||
});
|
||||
},
|
||||
|
||||
movePrevious: ({count, isVisual, isDelete}) => {
|
||||
setCurrent('previous', {
|
||||
count,
|
||||
isVisual,
|
||||
isDelete,
|
||||
}, {
|
||||
Info,
|
||||
setCurrentFile,
|
||||
unselectFiles,
|
||||
Operation,
|
||||
});
|
||||
},
|
||||
|
||||
find: async () => {
|
||||
preventDefault();
|
||||
const [, value] = await prompt('Find', '');
|
||||
|
||||
if (!value)
|
||||
return;
|
||||
|
||||
const names = Info.files.map(getCurrentName);
|
||||
const [result] = finder.find(value, names);
|
||||
|
||||
setCurrentByName(result);
|
||||
},
|
||||
|
||||
findPrevious: () => {
|
||||
const name = finder.findPrevious();
|
||||
setCurrentByName(name);
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
module.exports.selectFile = selectFileNotParent;
|
||||
|
||||
const _createFindNext = (overrides = {}) => () => {
|
||||
const {setCurrentByName} = overrides;
|
||||
const name = finder.findNext();
|
||||
|
||||
setCurrentByName(name);
|
||||
};
|
||||
681
client/key/vim/index.spec.js
Normal file
681
client/key/vim/index.spec.js
Normal file
|
|
@ -0,0 +1,681 @@
|
|||
'use strict';
|
||||
|
||||
const {join} = require('node:path');
|
||||
const {test, stub} = require('supertape');
|
||||
const mockRequire = require('mock-require');
|
||||
|
||||
const dir = '../';
|
||||
|
||||
const pathVim = join(dir, 'vim');
|
||||
|
||||
const {getDOM, getCloudCmd} = require('./globals.fixture');
|
||||
|
||||
globalThis.DOM = getDOM();
|
||||
globalThis.CloudCmd = getCloudCmd();
|
||||
|
||||
const vim = require('./index.js');
|
||||
|
||||
const {assign} = Object;
|
||||
const {DOM} = globalThis;
|
||||
const {Buffer} = DOM;
|
||||
const pathFind = join(dir, 'vim', 'find');
|
||||
const {reRequire, stopAll} = mockRequire;
|
||||
|
||||
test('cloudcmd: client: key: set next file: no', (t) => {
|
||||
const element = {};
|
||||
const setCurrentFile = stub();
|
||||
const unselectFiles = stub();
|
||||
|
||||
const Info = {
|
||||
element,
|
||||
};
|
||||
|
||||
vim('j', {}, {
|
||||
Info,
|
||||
setCurrentFile,
|
||||
unselectFiles,
|
||||
});
|
||||
|
||||
t.calledWith(setCurrentFile, [element], 'should set next file');
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('cloudcmd: client: key: set next file current: j', async (t) => {
|
||||
const nextSibling = 'hello';
|
||||
const element = {
|
||||
nextSibling,
|
||||
};
|
||||
|
||||
const setCurrentFile = stub();
|
||||
|
||||
const Info = {
|
||||
element,
|
||||
};
|
||||
|
||||
await vim('j', {}, {
|
||||
Info,
|
||||
setCurrentFile,
|
||||
unselectFiles: stub(),
|
||||
});
|
||||
|
||||
t.calledWith(setCurrentFile, [nextSibling], 'should set next file');
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('cloudcmd: client: key: set next file current: mjj', (t) => {
|
||||
const nextSibling = 'hello';
|
||||
const element = {
|
||||
nextSibling,
|
||||
};
|
||||
|
||||
const setCurrentFile = stub();
|
||||
|
||||
const Info = {
|
||||
element,
|
||||
};
|
||||
|
||||
const deps = {
|
||||
Info,
|
||||
setCurrentFile,
|
||||
unselectFiles: stub(),
|
||||
};
|
||||
|
||||
vim('m', {}, deps);
|
||||
vim('j', {}, deps);
|
||||
vim('j', {}, deps);
|
||||
|
||||
t.calledWith(setCurrentFile, [nextSibling], 'should set next file');
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('cloudcmd: client: key: set next file current: g', (t) => {
|
||||
const nextSibling = 'hello';
|
||||
const element = {
|
||||
nextSibling,
|
||||
};
|
||||
|
||||
const setCurrentFile = stub();
|
||||
|
||||
const Info = {
|
||||
element,
|
||||
};
|
||||
|
||||
const deps = {
|
||||
Info,
|
||||
setCurrentFile,
|
||||
unselectFiles: stub(),
|
||||
};
|
||||
|
||||
vim('g', {}, deps);
|
||||
vim('j', {}, deps);
|
||||
|
||||
t.calledWith(setCurrentFile, [nextSibling], 'should ignore g');
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('cloudcmd: client: key: set +2 file current', (t) => {
|
||||
const last = {};
|
||||
const setCurrentFile = stub();
|
||||
const element = {};
|
||||
|
||||
const Info = {
|
||||
element,
|
||||
};
|
||||
|
||||
const deps = {
|
||||
setCurrentFile,
|
||||
Info,
|
||||
unselectFiles: stub(),
|
||||
};
|
||||
|
||||
const event = {};
|
||||
|
||||
vim('2', event, deps);
|
||||
vim('j', event, deps);
|
||||
|
||||
t.calledWith(setCurrentFile, [last], 'should set next file');
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('cloudcmd: client: key: select +2 files from current before delete', (t) => {
|
||||
const last = {};
|
||||
const nextSibling = {
|
||||
nextSibling: last,
|
||||
};
|
||||
|
||||
const element = {
|
||||
nextSibling,
|
||||
};
|
||||
|
||||
const setCurrentFile = stub();
|
||||
|
||||
const Info = {
|
||||
element,
|
||||
};
|
||||
|
||||
const Operation = {
|
||||
show: stub(),
|
||||
};
|
||||
|
||||
const selectFile = stub();
|
||||
const getCurrentName = stub().returns('x');
|
||||
|
||||
const event = {};
|
||||
|
||||
const deps = {
|
||||
Info,
|
||||
setCurrentFile,
|
||||
selectFile,
|
||||
getCurrentName,
|
||||
Operation,
|
||||
};
|
||||
|
||||
vim('d', event, deps);
|
||||
vim('2', event, deps);
|
||||
vim('j', event, deps);
|
||||
|
||||
t.calledWith(setCurrentFile, [last], 'should set next file');
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('cloudcmd: client: key: delete +2 files from current', (t) => {
|
||||
const last = {};
|
||||
const nextSibling = {
|
||||
nextSibling: last,
|
||||
};
|
||||
|
||||
const element = {
|
||||
nextSibling,
|
||||
};
|
||||
|
||||
const setCurrentFile = stub();
|
||||
const show = stub();
|
||||
|
||||
const deps = {
|
||||
Info: {
|
||||
element,
|
||||
},
|
||||
Operation: {
|
||||
show,
|
||||
},
|
||||
setCurrentFile,
|
||||
selectFile: stub(),
|
||||
getCurrentName: stub().returns('x'),
|
||||
unselectFiles: stub(),
|
||||
};
|
||||
|
||||
const event = {};
|
||||
|
||||
vim('d', event, deps);
|
||||
vim('2', event, deps);
|
||||
vim('j', event, deps);
|
||||
|
||||
t.calledWith(show, ['delete'], 'should call delete');
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('cloudcmd: client: key: set previous file current', (t) => {
|
||||
const previousSibling = 'hello';
|
||||
const element = {
|
||||
previousSibling,
|
||||
};
|
||||
|
||||
const setCurrentFile = stub();
|
||||
const unselectFiles = stub();
|
||||
|
||||
const Info = {
|
||||
element,
|
||||
};
|
||||
|
||||
const deps = {
|
||||
Info,
|
||||
setCurrentFile,
|
||||
unselectFiles,
|
||||
};
|
||||
|
||||
vim('k', {}, deps);
|
||||
|
||||
t.calledWith(setCurrentFile, [previousSibling], 'should set previous file');
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('cloudcmd: client: key: copy: no', (t) => {
|
||||
const copy = stub();
|
||||
|
||||
vim('y', {}, {
|
||||
unselectFiles: stub(),
|
||||
Buffer: {
|
||||
copy,
|
||||
},
|
||||
});
|
||||
|
||||
t.notCalled(copy, 'should not copy files');
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('cloudcmd: client: key: copy', (t) => {
|
||||
const copy = stub();
|
||||
const Info = {
|
||||
element: {},
|
||||
};
|
||||
|
||||
const toggleSelectedFile = stub();
|
||||
const unselectFiles = stub();
|
||||
|
||||
const deps = {
|
||||
Info,
|
||||
unselectFiles,
|
||||
toggleSelectedFile,
|
||||
Buffer: {
|
||||
copy,
|
||||
},
|
||||
};
|
||||
|
||||
vim('v', {}, deps);
|
||||
vim('y', {}, deps);
|
||||
|
||||
t.calledWithNoArgs(copy, 'should copy files');
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('cloudcmd: client: key: copy: unselectFiles', (t) => {
|
||||
const unselectFiles = stub();
|
||||
const Info = {
|
||||
element: {},
|
||||
};
|
||||
|
||||
const toggleSelectedFile = stub();
|
||||
|
||||
const deps = {
|
||||
Info,
|
||||
unselectFiles,
|
||||
toggleSelectedFile,
|
||||
Buffer: {
|
||||
copy: stub(),
|
||||
},
|
||||
};
|
||||
|
||||
vim('v', {}, deps);
|
||||
vim('y', {}, deps);
|
||||
|
||||
t.calledWithNoArgs(unselectFiles, 'should unselect files');
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('cloudcmd: client: key: paste', (t) => {
|
||||
const paste = stub();
|
||||
|
||||
Buffer.paste = paste;
|
||||
|
||||
vim('p', {}, {
|
||||
Buffer,
|
||||
});
|
||||
|
||||
t.calledWithNoArgs(paste, 'should paste files');
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('cloudcmd: client: key: selectFile: ..', (t) => {
|
||||
const getCurrentName = stub().returns('..');
|
||||
const selectFile = stub();
|
||||
const current = {};
|
||||
|
||||
vim.selectFile(current, {
|
||||
selectFile,
|
||||
getCurrentName,
|
||||
});
|
||||
|
||||
t.notCalled(selectFile, 'should not call selectFile');
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('cloudcmd: client: key: selectFile', (t) => {
|
||||
const selectFile = stub();
|
||||
const getCurrentName = stub().returns('x');
|
||||
const current = {};
|
||||
|
||||
vim.selectFile(current, {
|
||||
selectFile,
|
||||
getCurrentName,
|
||||
});
|
||||
|
||||
t.calledWith(selectFile, [current], 'should call selectFile');
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('cloudcmd: client: key: set last file current: shift + g', async (t) => {
|
||||
const last = 'last';
|
||||
const nextSibling = {
|
||||
nextSibling: last,
|
||||
};
|
||||
|
||||
const element = {
|
||||
nextSibling,
|
||||
};
|
||||
|
||||
const setCurrentFile = stub();
|
||||
|
||||
await vim('G', {}, {
|
||||
Info: {
|
||||
element,
|
||||
},
|
||||
setCurrentFile,
|
||||
unselectFiles: stub(),
|
||||
});
|
||||
|
||||
t.calledWith(setCurrentFile, [last], 'should set last file');
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('cloudcmd: client: key: set last file current: $', (t) => {
|
||||
const last = 'last';
|
||||
const nextSibling = {
|
||||
nextSibling: last,
|
||||
};
|
||||
|
||||
const element = {
|
||||
nextSibling,
|
||||
};
|
||||
|
||||
const setCurrentFile = stub();
|
||||
|
||||
vim('$', {}, {
|
||||
Info: {
|
||||
element,
|
||||
},
|
||||
setCurrentFile,
|
||||
unselectFiles: stub(),
|
||||
});
|
||||
|
||||
t.calledWith(setCurrentFile, [last], 'should set last file');
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('cloudcmd: client: key: set first file current: gg', (t) => {
|
||||
const first = 'first';
|
||||
const previousSibling = {
|
||||
previousSibling: first,
|
||||
};
|
||||
|
||||
const element = {
|
||||
previousSibling,
|
||||
};
|
||||
|
||||
const Operation = {
|
||||
show: stub(),
|
||||
};
|
||||
|
||||
const unselectFiles = stub();
|
||||
const setCurrentFile = stub();
|
||||
|
||||
const deps = {
|
||||
Operation,
|
||||
unselectFiles,
|
||||
setCurrentFile,
|
||||
Info: {
|
||||
element,
|
||||
},
|
||||
};
|
||||
|
||||
vim('g', {}, deps);
|
||||
vim('g', {}, deps);
|
||||
|
||||
t.calledWith(setCurrentFile, [first], 'should set first file');
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('cloudcmd: client: key: set first file current: ^', async (t) => {
|
||||
const first = 'first';
|
||||
const previousSibling = {
|
||||
previousSibling: first,
|
||||
};
|
||||
|
||||
const element = {
|
||||
previousSibling,
|
||||
};
|
||||
|
||||
const Operation = {
|
||||
show: stub(),
|
||||
};
|
||||
|
||||
const unselectFiles = stub();
|
||||
const setCurrentFile = stub();
|
||||
|
||||
const deps = {
|
||||
setCurrentFile,
|
||||
Info: {
|
||||
element,
|
||||
},
|
||||
unselectFiles,
|
||||
Operation,
|
||||
};
|
||||
|
||||
await vim('^', {}, deps);
|
||||
|
||||
t.calledWith(setCurrentFile, [first], 'should set first file');
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('cloudcmd: client: key: visual', (t) => {
|
||||
const element = {};
|
||||
const toggleSelectedFile = stub();
|
||||
const Info = {
|
||||
element,
|
||||
};
|
||||
|
||||
vim('v', {}, {
|
||||
Info,
|
||||
toggleSelectedFile,
|
||||
});
|
||||
|
||||
t.calledWith(toggleSelectedFile, [element], 'should toggle selection');
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('cloudcmd: client: key: ESC', (t) => {
|
||||
const element = {};
|
||||
const unselectFiles = stub();
|
||||
const Info = {
|
||||
element,
|
||||
};
|
||||
|
||||
vim('Escape', null, {
|
||||
Info,
|
||||
unselectFiles,
|
||||
});
|
||||
|
||||
t.calledWithNoArgs(unselectFiles, 'should toggle selection');
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('cloudcmd: client: key: Enter', async (t) => {
|
||||
const nextSibling = 'hello';
|
||||
const element = {
|
||||
nextSibling,
|
||||
};
|
||||
|
||||
const unselectFiles = stub();
|
||||
const setCurrentFile = stub();
|
||||
|
||||
const Info = {
|
||||
element,
|
||||
};
|
||||
|
||||
await vim('Enter', null, {
|
||||
Info,
|
||||
setCurrentFile,
|
||||
unselectFiles,
|
||||
});
|
||||
|
||||
await vim('j', null, {
|
||||
Info,
|
||||
setCurrentFile,
|
||||
unselectFiles,
|
||||
});
|
||||
|
||||
t.calledWith(setCurrentFile, [nextSibling], 'should set next file');
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('cloudcmd: client: key: /', (t) => {
|
||||
const preventDefault = stub();
|
||||
const element = {};
|
||||
const Info = {
|
||||
element,
|
||||
files: [],
|
||||
};
|
||||
|
||||
const getCurrentName = stub().returns('');
|
||||
|
||||
const event = {
|
||||
preventDefault,
|
||||
};
|
||||
|
||||
const prompt = stub().returns([]);
|
||||
|
||||
vim('/', event, {
|
||||
getCurrentName,
|
||||
Info,
|
||||
prompt,
|
||||
});
|
||||
|
||||
t.calledWithNoArgs(preventDefault);
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('cloudcmd: client: find', (t) => {
|
||||
assign(DOM.Dialog, {
|
||||
prompt: stub().returns([]),
|
||||
});
|
||||
|
||||
const setCurrentByName = stub();
|
||||
|
||||
assign(DOM, {
|
||||
setCurrentByName,
|
||||
});
|
||||
|
||||
const vim = reRequire(pathVim);
|
||||
|
||||
const event = {
|
||||
preventDefault: stub(),
|
||||
};
|
||||
|
||||
vim('/', event);
|
||||
|
||||
stopAll();
|
||||
|
||||
t.notCalled(setCurrentByName);
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('cloudcmd: client: key: n', (t) => {
|
||||
const findNext = stub();
|
||||
const createFindNext = stub().returns(findNext);
|
||||
|
||||
const event = {};
|
||||
|
||||
vim('n', event, {
|
||||
createFindNext,
|
||||
});
|
||||
|
||||
t.calledWithNoArgs(findNext, 'should call findNext');
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('cloudcmd: client: key: N', (t) => {
|
||||
const findPrevious = stub();
|
||||
|
||||
mockRequire(pathFind, {
|
||||
findPrevious,
|
||||
});
|
||||
|
||||
const vim = reRequire(`${dir}vim`);
|
||||
const event = {};
|
||||
|
||||
vim('N', event);
|
||||
|
||||
stopAll();
|
||||
|
||||
t.calledWithNoArgs(findPrevious, 'should call findPrevious');
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('cloudcmd: client: key: make directory', async (t) => {
|
||||
const vim = reRequire(pathVim);
|
||||
const {DOM} = globalThis;
|
||||
|
||||
assign(DOM, {
|
||||
promptNewDir: stub(),
|
||||
});
|
||||
|
||||
const event = {
|
||||
stopImmediatePropagation: stub(),
|
||||
preventDefault: stub(),
|
||||
};
|
||||
|
||||
await vim('m', event);
|
||||
await vim('d', event);
|
||||
|
||||
t.calledWithNoArgs(DOM.promptNewDir);
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('cloudcmd: client: key: make file', (t) => {
|
||||
const vim = reRequire(pathVim);
|
||||
const {DOM} = globalThis;
|
||||
|
||||
assign(DOM, {
|
||||
promptNewFile: stub(),
|
||||
});
|
||||
|
||||
const event = {
|
||||
stopImmediatePropagation: stub(),
|
||||
preventDefault: stub(),
|
||||
};
|
||||
|
||||
vim('m', event);
|
||||
vim('f', event);
|
||||
|
||||
t.calledWithNoArgs(DOM.promptNewDir);
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('cloudcmd: client: vim: terminal', (t) => {
|
||||
const CloudCmd = {
|
||||
Terminal: {
|
||||
show: stub(),
|
||||
},
|
||||
};
|
||||
|
||||
const event = {};
|
||||
|
||||
vim('t', event, {
|
||||
CloudCmd,
|
||||
});
|
||||
vim('t', event, {
|
||||
CloudCmd,
|
||||
});
|
||||
|
||||
t.calledWithNoArgs(CloudCmd.Terminal.show);
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('cloudcmd: client: vim: edit', async (t) => {
|
||||
globalThis.DOM = getDOM();
|
||||
globalThis.CloudCmd = getCloudCmd();
|
||||
|
||||
const {CloudCmd} = globalThis;
|
||||
|
||||
assign(CloudCmd, {
|
||||
EditFileVim: {
|
||||
show: stub(),
|
||||
},
|
||||
});
|
||||
|
||||
const event = {};
|
||||
|
||||
await vim('e', event);
|
||||
|
||||
t.calledWithNoArgs(CloudCmd.EditFileVim.show);
|
||||
t.end();
|
||||
});
|
||||
36
client/key/vim/set-current.js
Normal file
36
client/key/vim/set-current.js
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
'use strict';
|
||||
|
||||
/* global DOM */
|
||||
module.exports.selectFileNotParent = selectFileNotParent;
|
||||
function selectFileNotParent(current, {getCurrentName, selectFile} = DOM) {
|
||||
const name = getCurrentName(current);
|
||||
|
||||
if (name === '..')
|
||||
return;
|
||||
|
||||
selectFile(current);
|
||||
}
|
||||
|
||||
module.exports.setCurrent = (sibling, {count, isVisual, isDelete}, {Info, setCurrentFile, unselectFiles, Operation}) => {
|
||||
let current = Info.element;
|
||||
const select = isVisual ? selectFileNotParent : unselectFiles;
|
||||
|
||||
select(current);
|
||||
|
||||
const position = `${sibling}Sibling`;
|
||||
|
||||
for (let i = 0; i < count; i++) {
|
||||
const next = current[position];
|
||||
|
||||
if (!next)
|
||||
break;
|
||||
|
||||
current = next;
|
||||
select(current);
|
||||
}
|
||||
|
||||
setCurrentFile(current);
|
||||
|
||||
if (isDelete)
|
||||
Operation.show('delete');
|
||||
};
|
||||
203
client/key/vim/vim.js
Normal file
203
client/key/vim/vim.js
Normal file
|
|
@ -0,0 +1,203 @@
|
|||
'use strict';
|
||||
|
||||
const {fullstore} = require('fullstore');
|
||||
const store = fullstore('');
|
||||
const visual = fullstore(false);
|
||||
|
||||
const stopVisual = () => {
|
||||
visual(false);
|
||||
};
|
||||
|
||||
const end = () => {
|
||||
store('');
|
||||
};
|
||||
|
||||
const rmFirst = (a) => {
|
||||
return a
|
||||
.split('')
|
||||
.slice(1)
|
||||
.join('');
|
||||
};
|
||||
|
||||
const noop = () => {};
|
||||
|
||||
module.exports = (key, operations = {}) => {
|
||||
const prevStore = store();
|
||||
const isVisual = visual();
|
||||
const value = store(prevStore.concat(key));
|
||||
|
||||
const {
|
||||
escape = noop,
|
||||
moveNext = noop,
|
||||
movePrevious = noop,
|
||||
remove = noop,
|
||||
copy = noop,
|
||||
paste = noop,
|
||||
select = noop,
|
||||
find = noop,
|
||||
findNext = noop,
|
||||
findPrevious = noop,
|
||||
makeFile = noop,
|
||||
makeDirectory = noop,
|
||||
terminal = noop,
|
||||
edit = noop,
|
||||
} = operations;
|
||||
|
||||
if (key === 'Enter')
|
||||
return end();
|
||||
|
||||
if (key === 'Escape') {
|
||||
visual(false);
|
||||
escape();
|
||||
|
||||
return end();
|
||||
}
|
||||
|
||||
if (key === 'j' || key === 'w') {
|
||||
const {
|
||||
count,
|
||||
isDelete,
|
||||
isVisual,
|
||||
} = handleDelete(prevStore);
|
||||
|
||||
!isNaN(count) && moveNext({
|
||||
count,
|
||||
isVisual,
|
||||
isDelete,
|
||||
});
|
||||
|
||||
return end();
|
||||
}
|
||||
|
||||
if (key === 'k' || key === 'b') {
|
||||
const {
|
||||
count,
|
||||
isDelete,
|
||||
isVisual,
|
||||
} = handleDelete(prevStore);
|
||||
|
||||
!isNaN(count) && movePrevious({
|
||||
count,
|
||||
isVisual,
|
||||
isDelete,
|
||||
});
|
||||
|
||||
return end();
|
||||
}
|
||||
|
||||
if (value === 'gg' || key === '^') {
|
||||
const {isDelete, isVisual} = handleDelete(prevStore);
|
||||
|
||||
movePrevious({
|
||||
count: Infinity,
|
||||
isVisual,
|
||||
isDelete,
|
||||
});
|
||||
|
||||
return end();
|
||||
}
|
||||
|
||||
if (value === 'md') {
|
||||
makeDirectory();
|
||||
return end();
|
||||
}
|
||||
|
||||
if (value === 'tt') {
|
||||
terminal();
|
||||
return end();
|
||||
}
|
||||
|
||||
if (value === 'e') {
|
||||
edit();
|
||||
return end();
|
||||
}
|
||||
|
||||
if (value === 'mf') {
|
||||
makeFile();
|
||||
return end();
|
||||
}
|
||||
|
||||
if (key === 'd' && (visual() || prevStore === 'd')) {
|
||||
stopVisual();
|
||||
remove();
|
||||
|
||||
return end();
|
||||
}
|
||||
|
||||
if (key === 'G' || key === '$') {
|
||||
moveNext({
|
||||
count: Infinity,
|
||||
isVisual,
|
||||
});
|
||||
|
||||
return end();
|
||||
}
|
||||
|
||||
if (key === 'y') {
|
||||
if (!visual())
|
||||
return end();
|
||||
|
||||
stopVisual();
|
||||
copy();
|
||||
|
||||
return end();
|
||||
}
|
||||
|
||||
if (/^p$/i.test(key)) {
|
||||
paste();
|
||||
return end();
|
||||
}
|
||||
|
||||
if (/^v$/i.test(key)) {
|
||||
visual(!visual());
|
||||
select();
|
||||
|
||||
return end();
|
||||
}
|
||||
|
||||
if (key === '/') {
|
||||
find();
|
||||
return end();
|
||||
}
|
||||
|
||||
if (key === 'n') {
|
||||
findNext();
|
||||
return end();
|
||||
}
|
||||
|
||||
if (key === 'N') {
|
||||
findPrevious();
|
||||
return end();
|
||||
}
|
||||
|
||||
if (key === ' ')
|
||||
return end();
|
||||
};
|
||||
|
||||
function handleDelete(prevStore) {
|
||||
const isDelete = prevStore[0] === 'd';
|
||||
|
||||
if (isDelete) {
|
||||
visual(true);
|
||||
prevStore = rmFirst(prevStore);
|
||||
}
|
||||
|
||||
const count = getNumber(prevStore);
|
||||
const isVisual = visual();
|
||||
|
||||
return {
|
||||
count,
|
||||
isDelete,
|
||||
isVisual,
|
||||
};
|
||||
}
|
||||
|
||||
function getNumber(value) {
|
||||
if (!value)
|
||||
return 1;
|
||||
|
||||
if (value === 'g')
|
||||
return 1;
|
||||
|
||||
return parseInt(value);
|
||||
}
|
||||
81
client/key/vim/vim.spec.js
Normal file
81
client/key/vim/vim.spec.js
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
'use strict';
|
||||
|
||||
const {test, stub} = require('supertape');
|
||||
|
||||
const vim = require('./vim');
|
||||
|
||||
test('vim: no operations', (t) => {
|
||||
const result = vim('hello', {});
|
||||
|
||||
t.notOk(result);
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('vim: space', (t) => {
|
||||
const moveNext = stub();
|
||||
|
||||
vim(' ');
|
||||
vim('j', {
|
||||
moveNext,
|
||||
});
|
||||
|
||||
const args = [{
|
||||
count: 1,
|
||||
isDelete: false,
|
||||
isVisual: false,
|
||||
}];
|
||||
|
||||
t.calledWith(moveNext, args);
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('vim: ^', (t) => {
|
||||
const movePrevious = stub();
|
||||
|
||||
vim('^', {
|
||||
movePrevious,
|
||||
});
|
||||
|
||||
const expected = {
|
||||
count: Infinity,
|
||||
isVisual: false,
|
||||
isDelete: false,
|
||||
};
|
||||
|
||||
t.calledWith(movePrevious, [expected], 'should call movePrevious');
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('vim: w', (t) => {
|
||||
const moveNext = stub();
|
||||
|
||||
vim('w', {
|
||||
moveNext,
|
||||
});
|
||||
|
||||
const expected = {
|
||||
count: 1,
|
||||
isVisual: false,
|
||||
isDelete: false,
|
||||
};
|
||||
|
||||
t.calledWith(moveNext, [expected], 'should call moveNext');
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('vim: b', (t) => {
|
||||
const movePrevious = stub();
|
||||
|
||||
vim('b', {
|
||||
movePrevious,
|
||||
});
|
||||
|
||||
const expected = {
|
||||
count: 1,
|
||||
isVisual: false,
|
||||
isDelete: false,
|
||||
};
|
||||
|
||||
t.calledWith(movePrevious, [expected], 'should call movePrevious');
|
||||
t.end();
|
||||
});
|
||||
10
client/listeners/get-index.js
Normal file
10
client/listeners/get-index.js
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
'use strict';
|
||||
|
||||
module.exports = (array, item) => {
|
||||
const index = array.indexOf(item);
|
||||
|
||||
if (!~index)
|
||||
return 0;
|
||||
|
||||
return index;
|
||||
};
|
||||
11
client/listeners/get-range.js
Normal file
11
client/listeners/get-range.js
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
'use strict';
|
||||
|
||||
module.exports = (indexFrom, indexTo, files) => {
|
||||
if (indexFrom < indexTo)
|
||||
return files.slice(indexFrom, indexTo + 1);
|
||||
|
||||
if (indexFrom > indexTo)
|
||||
return files.slice(indexTo, indexFrom + 1);
|
||||
|
||||
return [files[indexFrom]];
|
||||
};
|
||||
504
client/listeners/index.js
Normal file
504
client/listeners/index.js
Normal file
|
|
@ -0,0 +1,504 @@
|
|||
/* global DOM, CloudCmd */
|
||||
|
||||
'use strict';
|
||||
|
||||
const exec = require('execon');
|
||||
const itype = require('itype');
|
||||
const currify = require('currify');
|
||||
const {tryToCatch} = require('try-to-catch');
|
||||
const clipboard = require('@cloudcmd/clipboard');
|
||||
|
||||
const getRange = require('./get-range');
|
||||
const uploadFiles = require('../dom/upload-files');
|
||||
const {FS} = require('../../common/cloudfunc.mjs');
|
||||
const Events = require('#dom/events');
|
||||
|
||||
const getIndex = currify(require('./get-index'));
|
||||
|
||||
const NBSP_REG = RegExp(String.fromCharCode(160), 'g');
|
||||
const SPACE = ' ';
|
||||
|
||||
module.exports.init = async () => {
|
||||
await Promise.all([
|
||||
contextMenu(),
|
||||
dragndrop(),
|
||||
unload(),
|
||||
pop(),
|
||||
resize(),
|
||||
header(),
|
||||
config(),
|
||||
]);
|
||||
};
|
||||
|
||||
const unselect = (event) => {
|
||||
const isMac = /Mac/.test(globalThis.navigator.platform);
|
||||
const {
|
||||
shiftKey,
|
||||
metaKey,
|
||||
ctrlKey,
|
||||
} = event;
|
||||
|
||||
if (shiftKey || isMac && metaKey || ctrlKey)
|
||||
return;
|
||||
|
||||
DOM.unselectFiles();
|
||||
};
|
||||
|
||||
const execAll = currify((funcs, event) => {
|
||||
for (const fn of funcs)
|
||||
fn(event);
|
||||
});
|
||||
|
||||
const EventsFiles = {
|
||||
mousedown: exec.with(execIfNotUL, setCurrentFileByEvent),
|
||||
click: execAll([onClick, exec.with(execIfNotMobile, unselect)]),
|
||||
dragstart: exec.with(execIfNotUL, onDragStart),
|
||||
dblclick: exec.with(execIfNotUL, onDblClick),
|
||||
touchstart: exec.with(execIfNotUL, onTouch),
|
||||
};
|
||||
|
||||
let EXT;
|
||||
|
||||
function header() {
|
||||
const fm = DOM.getFM();
|
||||
const isDataset = (el) => el.dataset;
|
||||
const isPanel = (el) => {
|
||||
return /^js-(left|right)$/.test(el.dataset.name);
|
||||
};
|
||||
|
||||
Events.addClick(fm, (event) => {
|
||||
const el = event.target;
|
||||
const parent = el.parentElement;
|
||||
|
||||
if (parent.dataset.name !== 'js-fm-header')
|
||||
return;
|
||||
|
||||
const name = (el.dataset.name || '').replace('js-', '');
|
||||
|
||||
if (!/^(name|size|date)$/.test(name))
|
||||
return;
|
||||
|
||||
const panel = getPath(el)
|
||||
.filter(isDataset)
|
||||
.filter(isPanel)
|
||||
.pop();
|
||||
|
||||
CloudCmd.sortPanel(name, panel);
|
||||
});
|
||||
}
|
||||
|
||||
function getPath(el, path = []) {
|
||||
if (!el)
|
||||
return path;
|
||||
|
||||
return getPath(el.parentElement, path.concat(el));
|
||||
}
|
||||
|
||||
async function config() {
|
||||
const [, config] = await tryToCatch(DOM.Files.get, 'config');
|
||||
const type = config?.packer;
|
||||
|
||||
EXT = DOM.getPackerExt(type);
|
||||
}
|
||||
|
||||
module.exports.initKeysPanel = () => {
|
||||
const keysElement = DOM.getById('js-keyspanel');
|
||||
|
||||
if (!keysElement)
|
||||
return;
|
||||
|
||||
Events.addClick(keysElement, (event) => {
|
||||
const {target} = event;
|
||||
const {id} = target;
|
||||
|
||||
const operation = (name) => {
|
||||
const {Operation} = CloudCmd;
|
||||
|
||||
return Operation.show.bind(null, name);
|
||||
};
|
||||
|
||||
const clickFuncs = {
|
||||
'f1': CloudCmd.Help.show,
|
||||
'f2': CloudCmd.UserMenu.show,
|
||||
'f3': CloudCmd.View.show,
|
||||
'f4': CloudCmd.EditFile.show,
|
||||
'f5': operation('copy'),
|
||||
'f6': operation('move'),
|
||||
'f7': DOM.promptNewDir,
|
||||
'f8': operation('delete'),
|
||||
'f9': () => {
|
||||
event.stopPropagation();
|
||||
CloudCmd.Menu.show();
|
||||
},
|
||||
'f10': CloudCmd.Config.show,
|
||||
'~': CloudCmd.Konsole.show,
|
||||
'shift~': CloudCmd.Terminal.show,
|
||||
'contact': CloudCmd.Contact.show,
|
||||
};
|
||||
|
||||
exec(clickFuncs[id]);
|
||||
});
|
||||
};
|
||||
|
||||
const getPanel = (side) => {
|
||||
if (!itype.string(side))
|
||||
return side;
|
||||
|
||||
return DOM.getByDataName(`js-${side}`);
|
||||
};
|
||||
|
||||
module.exports.setOnPanel = (side) => {
|
||||
const panel = getPanel(side);
|
||||
|
||||
const filesElement = DOM.getByDataName('js-files', panel);
|
||||
const pathElement = DOM.getByDataName('js-path', panel);
|
||||
|
||||
/* ставим загрузку гифа на клик*/
|
||||
Events.addClick(pathElement, getPathListener(panel));
|
||||
Events.add(filesElement, EventsFiles);
|
||||
};
|
||||
|
||||
function getPathListener(panel) {
|
||||
return onPathElementClick.bind(null, panel);
|
||||
}
|
||||
|
||||
function isNoCurrent(panel) {
|
||||
const Info = DOM.CurrentInfo;
|
||||
const infoPanel = Info.panel;
|
||||
|
||||
if (!infoPanel)
|
||||
return true;
|
||||
|
||||
const namePanel = panel.getAttribute('data-name');
|
||||
const nameInfoPanel = infoPanel.getAttribute('data-name');
|
||||
|
||||
return namePanel !== nameInfoPanel;
|
||||
}
|
||||
|
||||
function decodePath(path) {
|
||||
const url = CloudCmd.HOST;
|
||||
const {prefix} = CloudCmd;
|
||||
const prefixReg = RegExp('^' + prefix + FS);
|
||||
|
||||
return decodeURI(path)
|
||||
.replace(url, '')
|
||||
.replace(prefixReg, '') // browser doesn't replace % -> %25% do it for him
|
||||
.replace('%%', '%25%')
|
||||
.replace(NBSP_REG, SPACE) || '/';
|
||||
}
|
||||
|
||||
async function onPathElementClick(panel, event) {
|
||||
const Info = DOM.CurrentInfo;
|
||||
event.preventDefault();
|
||||
|
||||
const element = event.target;
|
||||
const attr = element.getAttribute('data-name');
|
||||
const noCurrent = isNoCurrent(panel);
|
||||
|
||||
if (attr === 'js-copy-path')
|
||||
return copyPath(element);
|
||||
|
||||
if (attr === 'js-refresh')
|
||||
return CloudCmd.refresh({
|
||||
panel,
|
||||
noCurrent,
|
||||
});
|
||||
|
||||
if (attr !== 'js-path-link')
|
||||
return;
|
||||
|
||||
const {href} = element;
|
||||
const path = decodePath(href);
|
||||
|
||||
await CloudCmd.changeDir(path, {
|
||||
isRefresh: false,
|
||||
panel: noCurrent ? panel : Info.panel,
|
||||
});
|
||||
}
|
||||
|
||||
function copyPath(el) {
|
||||
clipboard
|
||||
.writeText(el.parentElement.title)
|
||||
.then(CloudCmd.log)
|
||||
.catch(CloudCmd.log);
|
||||
}
|
||||
|
||||
function execIfNotMobile(callback, event) {
|
||||
const isMobile = DOM.getCSSVar('is-mobile');
|
||||
|
||||
if (!isMobile)
|
||||
callback(event);
|
||||
}
|
||||
|
||||
function execIfNotUL(callback, event) {
|
||||
const {target} = event;
|
||||
const {tagName} = target;
|
||||
|
||||
if (tagName !== 'UL')
|
||||
callback(event);
|
||||
}
|
||||
|
||||
function onClick(event) {
|
||||
event.preventDefault();
|
||||
changePanel(event.target);
|
||||
}
|
||||
|
||||
function toggleSelect(key, files) {
|
||||
const isMac = /Mac/.test(globalThis.navigator.platform);
|
||||
|
||||
if (!key)
|
||||
throw Error('key should not be undefined!');
|
||||
|
||||
const [file] = files;
|
||||
|
||||
if (isMac && key.meta)
|
||||
return DOM.toggleSelectedFile(file);
|
||||
|
||||
if (key.shift)
|
||||
return files.map(DOM.selectFile);
|
||||
}
|
||||
|
||||
function changePanel(element) {
|
||||
const Info = DOM.CurrentInfo;
|
||||
const {panel} = Info;
|
||||
const files = DOM.getByDataName('js-files', panel);
|
||||
const ul = getULElement(element);
|
||||
|
||||
if (ul !== files)
|
||||
DOM.changePanel();
|
||||
}
|
||||
|
||||
async function onDblClick(event) {
|
||||
event.preventDefault();
|
||||
|
||||
const current = getLIElement(event.target);
|
||||
const isDir = DOM.isCurrentIsDir(current);
|
||||
const path = DOM.getCurrentPath(current);
|
||||
|
||||
if (!isDir)
|
||||
return CloudCmd.View.show();
|
||||
|
||||
await CloudCmd.changeDir(path);
|
||||
}
|
||||
|
||||
async function onTouch(event) {
|
||||
const current = getLIElement(event.target);
|
||||
const isDir = DOM.isCurrentIsDir(current);
|
||||
|
||||
if (!isDir)
|
||||
return;
|
||||
|
||||
const isCurrent = DOM.isCurrentFile(current);
|
||||
|
||||
if (!isCurrent)
|
||||
return;
|
||||
|
||||
await CloudCmd.changeDir(DOM.getCurrentPath(current));
|
||||
}
|
||||
|
||||
/*
|
||||
* download file from browser to desktop
|
||||
* in Chrome (HTML5)
|
||||
*/
|
||||
function onDragStart(event) {
|
||||
const Info = DOM.CurrentInfo;
|
||||
const {prefixURL} = CloudCmd;
|
||||
const element = getLIElement(event.target);
|
||||
const {isDir} = Info;
|
||||
let link = DOM.getCurrentLink(element);
|
||||
let name = DOM.getCurrentName(element);
|
||||
|
||||
/* if it's directory - adding json extension */
|
||||
if (isDir) {
|
||||
name += EXT;
|
||||
link = document.createElement('a');
|
||||
link.textContent = name;
|
||||
link.href = prefixURL + '/pack' + Info.path + EXT;
|
||||
}
|
||||
|
||||
event.dataTransfer.setData('DownloadURL', 'application/octet-stream' + ':' + name +
|
||||
':' + link);
|
||||
}
|
||||
|
||||
function getLIElement(element) {
|
||||
if (!element)
|
||||
return element;
|
||||
|
||||
while (element.tagName !== 'LI')
|
||||
element = element.parentElement;
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
function getULElement(element) {
|
||||
while (element.tagName !== 'UL')
|
||||
element = element.parentElement;
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
function setCurrentFileByEvent(event) {
|
||||
const Info = DOM.CurrentInfo;
|
||||
const BUTTON_LEFT = 0;
|
||||
|
||||
const key = {
|
||||
alt: event.altKey,
|
||||
ctrl: event.ctrlKey,
|
||||
meta: event.metaKey,
|
||||
shift: event.shiftKey,
|
||||
};
|
||||
|
||||
const element = getLIElement(event.target);
|
||||
|
||||
const fromName = Info.name;
|
||||
DOM.setCurrentFile(element);
|
||||
const toName = Info.name;
|
||||
|
||||
let files = [];
|
||||
|
||||
if (key.shift)
|
||||
files = getFilesRange(fromName, toName);
|
||||
else
|
||||
files.push(Info.element);
|
||||
|
||||
if (event.button === BUTTON_LEFT)
|
||||
toggleSelect(key, files);
|
||||
}
|
||||
|
||||
function getFilesRange(from, to) {
|
||||
const files = DOM.getAllFiles();
|
||||
const names = DOM.getFilenames(files);
|
||||
const getNameIndex = getIndex(names);
|
||||
|
||||
const indexFrom = getNameIndex(from);
|
||||
const indexTo = getNameIndex(to);
|
||||
|
||||
return getRange(indexFrom, indexTo, files);
|
||||
}
|
||||
|
||||
function contextMenu() {
|
||||
const fm = DOM.getFM();
|
||||
|
||||
Events.addOnce('contextmenu', fm, (event) => {
|
||||
CloudCmd.Menu.show({
|
||||
x: event.clientX,
|
||||
y: event.clientY,
|
||||
});
|
||||
});
|
||||
|
||||
Events.addContextMenu(fm, (event) => {
|
||||
CloudCmd.Menu.ENABLED || event.preventDefault();
|
||||
});
|
||||
}
|
||||
|
||||
function dragndrop() {
|
||||
const panels = DOM.getByClassAll('panel');
|
||||
const select = ({target}) => {
|
||||
target.classList.add('selected-panel');
|
||||
};
|
||||
|
||||
const unselect = ({target}) => {
|
||||
target.classList.remove('selected-panel');
|
||||
};
|
||||
|
||||
const onDrop = (event) => {
|
||||
const {files, items} = event.dataTransfer;
|
||||
|
||||
const {length: filesCount} = files;
|
||||
|
||||
event.preventDefault();
|
||||
|
||||
if (filesCount && (!items || !items.length || !items[0].webkitGetAsEntry))
|
||||
return uploadFiles(files);
|
||||
|
||||
const isFile = (item) => item.kind === 'file';
|
||||
|
||||
const dirFiles = Array
|
||||
.from(items)
|
||||
.filter(isFile);
|
||||
|
||||
if (dirFiles.length)
|
||||
return DOM.uploadDirectory(dirFiles);
|
||||
|
||||
const {Operation} = CloudCmd;
|
||||
const operation = event.shiftKey ? 'move' : 'copy';
|
||||
|
||||
return Operation.show(operation);
|
||||
};
|
||||
|
||||
/**
|
||||
* In macOS Chrome dropEffect = 'none'
|
||||
* so drop do not firing up when try
|
||||
* to upload file from download bar
|
||||
*/
|
||||
const onDragOver = (event) => {
|
||||
const {dataTransfer} = event;
|
||||
const {effectAllowed} = dataTransfer;
|
||||
|
||||
if (/move|linkMove/.test(effectAllowed))
|
||||
dataTransfer.dropEffect = 'move';
|
||||
else
|
||||
dataTransfer.dropEffect = 'copy';
|
||||
|
||||
event.preventDefault();
|
||||
};
|
||||
|
||||
for (const panel of panels)
|
||||
Events
|
||||
.add('dragover', panel, onDragOver)
|
||||
.add('drop', panel, onDrop)
|
||||
.add('dragenter', select)
|
||||
.add(['dragleave', 'drop'], unselect);
|
||||
}
|
||||
|
||||
function unload() {
|
||||
Events.add(['unload', 'beforeunload'], (event) => {
|
||||
const {Key} = CloudCmd;
|
||||
const isBind = Key?.isBind();
|
||||
|
||||
if (isBind)
|
||||
return;
|
||||
|
||||
event.preventDefault();
|
||||
return 'Please make sure that you saved all work.';
|
||||
});
|
||||
}
|
||||
|
||||
function pop() {
|
||||
Events.add('popstate', async ({state}) => {
|
||||
const path = (state || '').replace(FS, '');
|
||||
|
||||
if (!path)
|
||||
return CloudCmd.route(location.hash);
|
||||
|
||||
const history = false;
|
||||
|
||||
await CloudCmd.changeDir(path, {
|
||||
history,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function resize() {
|
||||
Events.add('resize', () => {
|
||||
const Info = DOM.CurrentInfo;
|
||||
const is = globalThis.innerWidth < CloudCmd.MIN_ONE_PANEL_WIDTH;
|
||||
|
||||
if (!is)
|
||||
return;
|
||||
|
||||
const {panel} = Info;
|
||||
const isEmptyRoot = !panel;
|
||||
|
||||
if (isEmptyRoot)
|
||||
return;
|
||||
|
||||
const name = panel.getAttribute('data-name');
|
||||
const isLeft = name === 'js-left';
|
||||
|
||||
if (isLeft)
|
||||
return;
|
||||
|
||||
DOM.changePanel();
|
||||
});
|
||||
}
|
||||
56
client/load-module.mjs
Normal file
56
client/load-module.mjs
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
/* global CloudCmd */
|
||||
import exec from 'execon';
|
||||
import {tryToCatch} from 'try-to-catch';
|
||||
import {js as loadJS} from 'load.js';
|
||||
import pascalCase from 'just-pascal-case';
|
||||
|
||||
const noJS = (a) => a.replace(/.js$/, '');
|
||||
|
||||
/**
|
||||
* function load modules
|
||||
* @params = {name, path, func, dobefore, arg}
|
||||
*/
|
||||
export const loadModule = (params) => {
|
||||
if (!params)
|
||||
return;
|
||||
|
||||
const {path} = params;
|
||||
|
||||
const name = path && noJS(pascalCase(path));
|
||||
const doBefore = params.dobefore;
|
||||
|
||||
if (CloudCmd[name])
|
||||
return;
|
||||
|
||||
CloudCmd[name] = async () => {
|
||||
exec(doBefore);
|
||||
|
||||
const {DIR_MODULES} = CloudCmd;
|
||||
const pathFull = `${DIR_MODULES}/${path}.js`;
|
||||
|
||||
await loadJS(pathFull);
|
||||
const newModule = async (f) => f && f();
|
||||
const module = CloudCmd[name];
|
||||
|
||||
Object.assign(newModule, module);
|
||||
|
||||
CloudCmd[name] = newModule;
|
||||
CloudCmd.log('init', name);
|
||||
|
||||
await module.init();
|
||||
|
||||
return newModule;
|
||||
};
|
||||
|
||||
CloudCmd[name].show = async (...args) => {
|
||||
CloudCmd.log('show', name, args);
|
||||
const m = CloudCmd[name];
|
||||
|
||||
const [e, a] = await tryToCatch(m);
|
||||
|
||||
if (e)
|
||||
return;
|
||||
|
||||
return await a.show(...args);
|
||||
};
|
||||
};
|
||||
64
client/modules/cloud.js
Normal file
64
client/modules/cloud.js
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
/* global CloudCmd, filepicker */
|
||||
|
||||
'use strict';
|
||||
|
||||
const exec = require('execon');
|
||||
const currify = require('currify');
|
||||
const load = require('load.js');
|
||||
|
||||
const {ajax} = require('../dom/load');
|
||||
|
||||
const Files = require('../dom/files');
|
||||
const Images = require('../dom/images.mjs');
|
||||
const {log} = CloudCmd;
|
||||
|
||||
const upload = currify(_upload);
|
||||
|
||||
const Name = 'Cloud';
|
||||
|
||||
CloudCmd[Name] = module.exports;
|
||||
|
||||
module.exports.init = async () => {
|
||||
const [modules] = await loadFiles();
|
||||
const {key} = modules.data.FilePicker;
|
||||
|
||||
filepicker.setKey(key);
|
||||
Images.hide();
|
||||
};
|
||||
|
||||
module.exports.uploadFile = (filename, data) => {
|
||||
const mimetype = '';
|
||||
|
||||
filepicker.store(data, {
|
||||
mimetype,
|
||||
filename,
|
||||
}, (fpFile) => {
|
||||
filepicker.exportFile(fpFile, log, log);
|
||||
});
|
||||
};
|
||||
|
||||
module.exports.saveFile = (callback) => {
|
||||
filepicker.pick(upload(callback));
|
||||
};
|
||||
|
||||
function _upload(callback, file) {
|
||||
const {url, filename} = file;
|
||||
|
||||
const responseType = 'arraybuffer';
|
||||
const success = exec.with(callback, filename);
|
||||
|
||||
ajax({
|
||||
url,
|
||||
responseType,
|
||||
success,
|
||||
});
|
||||
}
|
||||
|
||||
function loadFiles() {
|
||||
const js = '//api.filepicker.io/v2/filepicker.js';
|
||||
|
||||
return Promise.all([
|
||||
Files.get('modules'),
|
||||
load.js(js),
|
||||
]);
|
||||
}
|
||||
35
client/modules/command-line.js
Normal file
35
client/modules/command-line.js
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
'use strict';
|
||||
|
||||
/* global CloudCmd */
|
||||
CloudCmd.CommandLine = exports;
|
||||
|
||||
const Dialog = require('../dom/dialog');
|
||||
|
||||
const noop = () => {};
|
||||
|
||||
module.exports.init = noop;
|
||||
|
||||
module.exports.show = show;
|
||||
module.exports.hide = hide;
|
||||
|
||||
async function show() {
|
||||
const [, cmd] = await Dialog.prompt('Command Line', '');
|
||||
const TERMINAL = '^(t|terminal)';
|
||||
|
||||
if (RegExp(`${TERMINAL}$`).test(cmd))
|
||||
return await CloudCmd.Terminal.show();
|
||||
|
||||
if (RegExp(TERMINAL).test(cmd)) {
|
||||
const command = cmd.replace(RegExp(`${TERMINAL} `), '');
|
||||
const exitCode = await CloudCmd.TerminalRun.show({
|
||||
command: `bash -c '${command}'`,
|
||||
});
|
||||
|
||||
if (exitCode === -1)
|
||||
await Dialog.alert(`☝️ Looks like Terminal is disabled, start Cloud Coammnder with '--terminal' flag.`);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
function hide() {}
|
||||
248
client/modules/config/index.js
Normal file
248
client/modules/config/index.js
Normal file
|
|
@ -0,0 +1,248 @@
|
|||
'use strict';
|
||||
|
||||
/* global CloudCmd, DOM, io */
|
||||
require('../../../css/config.css');
|
||||
|
||||
const rendy = require('rendy');
|
||||
const currify = require('currify');
|
||||
const wraptile = require('wraptile');
|
||||
const squad = require('squad');
|
||||
const {promisify} = require('es6-promisify');
|
||||
const {tryToCatch} = require('try-to-catch');
|
||||
const load = require('load.js');
|
||||
const createElement = require('@cloudcmd/create-element');
|
||||
|
||||
const input = require('./input');
|
||||
const Images = require('../../dom/images.mjs');
|
||||
const Events = require('#dom/events');
|
||||
const Files = require('../../dom/files');
|
||||
|
||||
const {getTitle} = require('../../../common/cloudfunc.mjs');
|
||||
const {Dialog, setTitle} = DOM;
|
||||
|
||||
const Name = 'Config';
|
||||
|
||||
CloudCmd[Name] = module.exports;
|
||||
|
||||
const loadSocket = promisify(DOM.loadSocket);
|
||||
|
||||
const showLoad = () => {
|
||||
Images.show.load('top');
|
||||
};
|
||||
|
||||
const addKey = currify((fn, input) => {
|
||||
Events.addKey(input, fn);
|
||||
return input;
|
||||
});
|
||||
|
||||
const addChange = currify((fn, input) => {
|
||||
Events.add('change', input, fn);
|
||||
return input;
|
||||
});
|
||||
|
||||
const Config = {};
|
||||
|
||||
let Template;
|
||||
|
||||
const loadCSS = load.css;
|
||||
|
||||
module.exports.init = async () => {
|
||||
if (!CloudCmd.config('configDialog'))
|
||||
return;
|
||||
|
||||
showLoad();
|
||||
|
||||
const {DIR_DIST} = CloudCmd;
|
||||
|
||||
[Template] = await Promise.all([
|
||||
Files.get('config-tmpl'),
|
||||
loadSocket(),
|
||||
loadCSS(`${DIR_DIST}/config.css`),
|
||||
CloudCmd.View(),
|
||||
]);
|
||||
|
||||
initSocket();
|
||||
};
|
||||
|
||||
const {config, Key} = CloudCmd;
|
||||
|
||||
let Element;
|
||||
|
||||
function getHost() {
|
||||
const {
|
||||
host,
|
||||
origin,
|
||||
protocol,
|
||||
} = location;
|
||||
|
||||
return origin || `${protocol}//${host}`;
|
||||
}
|
||||
|
||||
function initSocket() {
|
||||
const href = getHost();
|
||||
const {prefixSocket, prefix} = CloudCmd;
|
||||
|
||||
const ONE_MINUTE = 60 * 1000;
|
||||
|
||||
const socket = io.connect(href + prefixSocket + '/config', {
|
||||
reconnectionAttempts: Infinity,
|
||||
reconnectionDelay: ONE_MINUTE,
|
||||
path: `${prefix}/socket.io`,
|
||||
});
|
||||
|
||||
const save = (data) => {
|
||||
onSave(data);
|
||||
socket.send(data);
|
||||
};
|
||||
|
||||
authCheck(socket);
|
||||
|
||||
socket.on('connect', () => {
|
||||
Config.save = save;
|
||||
});
|
||||
|
||||
socket.on('message', onSave);
|
||||
socket.on('log', CloudCmd.log);
|
||||
|
||||
socket.on('disconnect', () => {
|
||||
Config.save = saveHttp;
|
||||
});
|
||||
|
||||
socket.on('err', Dialog.alert);
|
||||
}
|
||||
|
||||
function authCheck(socket) {
|
||||
socket.emit('auth', config('username'), config('password'));
|
||||
socket.on('reject', wraptile(Dialog.alert, 'Wrong credentials!'));
|
||||
}
|
||||
|
||||
Config.save = saveHttp;
|
||||
|
||||
module.exports.show = show;
|
||||
|
||||
async function show() {
|
||||
if (!CloudCmd.config('configDialog'))
|
||||
return;
|
||||
|
||||
await fillTemplate();
|
||||
}
|
||||
|
||||
async function fillTemplate() {
|
||||
const [error, config] = await tryToCatch(Files.get, 'config');
|
||||
|
||||
if (error)
|
||||
return Dialog.alert('Could not load config!');
|
||||
|
||||
const {
|
||||
editor,
|
||||
menu,
|
||||
packer,
|
||||
columns,
|
||||
theme,
|
||||
configAuth,
|
||||
...obj
|
||||
} = input.convert(config);
|
||||
|
||||
obj[`${menu}-selected`] = 'selected';
|
||||
obj[`${editor}-selected`] = 'selected';
|
||||
obj[`${packer}-selected`] = 'selected';
|
||||
obj[`${columns}-selected`] = 'selected';
|
||||
obj[`${theme}-selected`] = 'selected';
|
||||
obj.configAuth = configAuth ? '' : 'hidden';
|
||||
|
||||
const innerHTML = rendy(Template, obj);
|
||||
|
||||
Element = createElement('form', {
|
||||
className: 'config',
|
||||
innerHTML,
|
||||
});
|
||||
|
||||
const inputs = document.querySelectorAll('input, select', Element);
|
||||
const [inputFirst] = inputs;
|
||||
|
||||
let afterShow;
|
||||
|
||||
if (inputFirst) {
|
||||
onAuthChange(inputFirst.checked);
|
||||
afterShow = inputFirst.focus.bind(inputFirst);
|
||||
}
|
||||
|
||||
const getTarget = ({target}) => target;
|
||||
const handleChange = squad(onChange, getTarget);
|
||||
|
||||
Array
|
||||
.from(inputs)
|
||||
.map(addKey(onKey))
|
||||
.map(addChange(handleChange));
|
||||
|
||||
const autoSize = true;
|
||||
|
||||
CloudCmd.View.show(Element, {
|
||||
autoSize,
|
||||
afterShow,
|
||||
});
|
||||
}
|
||||
|
||||
module.exports.hide = hide;
|
||||
|
||||
function hide() {
|
||||
CloudCmd.View.hide();
|
||||
}
|
||||
|
||||
async function onChange(el) {
|
||||
const obj = {};
|
||||
const name = input.getName(el);
|
||||
const data = input.getValue(name, Element);
|
||||
|
||||
if (name === 'name')
|
||||
onNameChange(data);
|
||||
else if (name === 'auth')
|
||||
onAuthChange(data);
|
||||
|
||||
obj[name] = data;
|
||||
|
||||
await Config.save(obj);
|
||||
}
|
||||
|
||||
function onSave(obj) {
|
||||
for (const name of Object.keys(obj)) {
|
||||
const data = obj[name];
|
||||
|
||||
CloudCmd._config(name, data);
|
||||
input.setValue(name, data, Element);
|
||||
}
|
||||
}
|
||||
|
||||
async function saveHttp(obj) {
|
||||
const {RESTful} = DOM;
|
||||
const [e] = await RESTful.Config.write(obj);
|
||||
|
||||
if (e)
|
||||
return;
|
||||
|
||||
onSave(obj);
|
||||
}
|
||||
|
||||
function onAuthChange(checked) {
|
||||
const elUsername = input.getElementByName('username', Element);
|
||||
const elPassword = input.getElementByName('password', Element);
|
||||
|
||||
elUsername.disabled = !checked;
|
||||
elPassword.disabled = !checked;
|
||||
}
|
||||
|
||||
function onNameChange(name) {
|
||||
setTitle(getTitle({
|
||||
name,
|
||||
}));
|
||||
}
|
||||
|
||||
async function onKey({keyCode, target}) {
|
||||
switch(keyCode) {
|
||||
case Key.ESC:
|
||||
return hide();
|
||||
|
||||
case Key.ENTER:
|
||||
return await onChange(target);
|
||||
}
|
||||
}
|
||||
75
client/modules/config/input.js
Normal file
75
client/modules/config/input.js
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
'use strict';
|
||||
|
||||
const currify = require('currify');
|
||||
|
||||
const isType = currify((type, object, name) => type === typeof object[name]);
|
||||
|
||||
const isBool = isType('boolean');
|
||||
|
||||
module.exports.getElementByName = getElementByName;
|
||||
|
||||
function getElementByName(selector, element) {
|
||||
const str = `[data-name="js-${selector}"]`;
|
||||
|
||||
return element.querySelector(str);
|
||||
}
|
||||
|
||||
module.exports.getName = (element) => {
|
||||
const name = element
|
||||
.getAttribute('data-name')
|
||||
.replace(/^js-/, '');
|
||||
|
||||
return name;
|
||||
};
|
||||
|
||||
module.exports.convert = (config) => {
|
||||
const result = config;
|
||||
const array = Object.keys(config);
|
||||
|
||||
const filtered = array.filter(isBool(config));
|
||||
|
||||
for (const name of filtered) {
|
||||
const item = config[name];
|
||||
result[name] = setState(item);
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
function setState(state) {
|
||||
if (state)
|
||||
return ' checked';
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
module.exports.getValue = (name, element) => {
|
||||
const el = getElementByName(name, element);
|
||||
const {type} = el;
|
||||
|
||||
switch(type) {
|
||||
case 'checkbox':
|
||||
return el.checked;
|
||||
|
||||
case 'number':
|
||||
return Number(el.value);
|
||||
|
||||
default:
|
||||
return el.value;
|
||||
}
|
||||
};
|
||||
|
||||
module.exports.setValue = (name, value, element) => {
|
||||
const el = getElementByName(name, element);
|
||||
const {type} = el;
|
||||
|
||||
switch(type) {
|
||||
case 'checkbox':
|
||||
el.checked = value;
|
||||
break;
|
||||
|
||||
default:
|
||||
el.value = value;
|
||||
break;
|
||||
}
|
||||
};
|
||||
41
client/modules/contact.js
Normal file
41
client/modules/contact.js
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
/* global CloudCmd */
|
||||
/* global DOM */
|
||||
|
||||
'use strict';
|
||||
|
||||
CloudCmd.Contact = exports;
|
||||
|
||||
const olark = require('@cloudcmd/olark');
|
||||
const Images = require('../dom/images.mjs');
|
||||
|
||||
const {Events} = DOM;
|
||||
const {Key} = CloudCmd;
|
||||
|
||||
module.exports.show = show;
|
||||
module.exports.hide = hide;
|
||||
|
||||
module.exports.init = () => {
|
||||
Events.addKey(onKey);
|
||||
|
||||
olark.identify('6216-545-10-4223');
|
||||
olark('api.box.onExpand', show);
|
||||
olark('api.box.onShow', show);
|
||||
olark('api.box.onShrink', hide);
|
||||
};
|
||||
|
||||
function show() {
|
||||
Key.unsetBind();
|
||||
Images.hide();
|
||||
|
||||
olark('api.box.expand');
|
||||
}
|
||||
|
||||
function hide() {
|
||||
Key.setBind();
|
||||
olark('api.box.hide');
|
||||
}
|
||||
|
||||
function onKey({keyCode}) {
|
||||
if (keyCode === Key.ESC)
|
||||
hide();
|
||||
}
|
||||
45
client/modules/edit-file-vim.js
Normal file
45
client/modules/edit-file-vim.js
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
'use strict';
|
||||
|
||||
/* global CloudCmd */
|
||||
CloudCmd.EditFileVim = exports;
|
||||
|
||||
const Events = require('#dom/events');
|
||||
|
||||
const {Key} = CloudCmd;
|
||||
|
||||
const ConfigView = {
|
||||
bindKeys: false,
|
||||
beforeClose: () => {
|
||||
Events.rmKey(listener);
|
||||
CloudCmd.EditFile.isChanged();
|
||||
},
|
||||
};
|
||||
|
||||
module.exports.init = async () => {
|
||||
await CloudCmd.EditFile();
|
||||
};
|
||||
|
||||
module.exports.show = async () => {
|
||||
Events.addKey(listener);
|
||||
|
||||
const editFile = await CloudCmd.EditFile.show(ConfigView);
|
||||
|
||||
editFile
|
||||
.getEditor()
|
||||
.setKeyMap('vim');
|
||||
};
|
||||
|
||||
module.exports.hide = hide;
|
||||
|
||||
function hide() {
|
||||
CloudCmd.Edit.hide();
|
||||
}
|
||||
|
||||
function listener(event) {
|
||||
const {keyCode, shiftKey} = event;
|
||||
|
||||
if (shiftKey && keyCode === Key.ESC) {
|
||||
event.preventDefault();
|
||||
hide();
|
||||
}
|
||||
}
|
||||
194
client/modules/edit-file.js
Normal file
194
client/modules/edit-file.js
Normal file
|
|
@ -0,0 +1,194 @@
|
|||
'use strict';
|
||||
|
||||
/* global CloudCmd, DOM*/
|
||||
CloudCmd.EditFile = exports;
|
||||
|
||||
const Format = require('format-io');
|
||||
const {fullstore} = require('fullstore');
|
||||
const exec = require('execon');
|
||||
const supermenu = require('supermenu');
|
||||
|
||||
const Info = DOM.CurrentInfo;
|
||||
|
||||
const {Dialog, Images} = DOM;
|
||||
|
||||
const {config} = CloudCmd;
|
||||
|
||||
let Menu;
|
||||
let MSG_CHANGED;
|
||||
|
||||
const isLoading = fullstore();
|
||||
|
||||
const ConfigView = {
|
||||
beforeClose: async () => {
|
||||
exec.ifExist(Menu, 'hide');
|
||||
await isChanged();
|
||||
},
|
||||
};
|
||||
|
||||
module.exports.init = async () => {
|
||||
isLoading(true);
|
||||
|
||||
await CloudCmd.Edit();
|
||||
|
||||
const editor = CloudCmd.Edit.getEditor();
|
||||
authCheck(editor);
|
||||
setListeners(editor);
|
||||
|
||||
isLoading(false);
|
||||
};
|
||||
|
||||
function getName() {
|
||||
const {name, isDir} = Info;
|
||||
|
||||
if (isDir)
|
||||
return `${name}.json`;
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
module.exports.show = async (options) => {
|
||||
if (isLoading())
|
||||
return;
|
||||
|
||||
const optionsEdit = {
|
||||
...ConfigView,
|
||||
...options,
|
||||
};
|
||||
|
||||
if (CloudCmd.config('showFileName'))
|
||||
optionsEdit.title = Info.name;
|
||||
|
||||
Images.show.load();
|
||||
|
||||
CloudCmd.Edit
|
||||
.getEditor()
|
||||
.setOption('keyMap', 'default');
|
||||
|
||||
const [error, data] = await Info.getData();
|
||||
|
||||
if (error) {
|
||||
Images.hide();
|
||||
return CloudCmd.Edit;
|
||||
}
|
||||
|
||||
const {path} = Info;
|
||||
const name = getName();
|
||||
|
||||
setMsgChanged(name);
|
||||
|
||||
CloudCmd.Edit
|
||||
.getEditor()
|
||||
.setValueFirst(path, data)
|
||||
.setModeForPath(name)
|
||||
.enableKey();
|
||||
|
||||
CloudCmd.Edit.show(optionsEdit);
|
||||
|
||||
return CloudCmd.Edit;
|
||||
};
|
||||
|
||||
module.exports.hide = hide;
|
||||
|
||||
function hide() {
|
||||
CloudCmd.Edit.hide();
|
||||
}
|
||||
|
||||
function setListeners(editor) {
|
||||
const element = CloudCmd.Edit.getElement();
|
||||
|
||||
DOM.Events.addOnce('contextmenu', element, setMenu);
|
||||
|
||||
editor.on('save', (value) => {
|
||||
DOM.setCurrentSize(Format.size(value));
|
||||
});
|
||||
}
|
||||
|
||||
function authCheck(spawn) {
|
||||
spawn.emit('auth', config('username'), config('password'));
|
||||
spawn.on('reject', () => {
|
||||
Dialog.alert('Wrong credentials!');
|
||||
});
|
||||
}
|
||||
|
||||
function setMenu(event) {
|
||||
const position = {
|
||||
x: event.clientX,
|
||||
y: event.clientY,
|
||||
};
|
||||
|
||||
event.preventDefault();
|
||||
|
||||
if (Menu)
|
||||
return;
|
||||
|
||||
const options = {
|
||||
beforeShow: (params) => {
|
||||
params.x -= 18;
|
||||
params.y -= 27;
|
||||
},
|
||||
|
||||
afterClick: () => {
|
||||
CloudCmd.Edit
|
||||
.getEditor()
|
||||
.focus();
|
||||
},
|
||||
};
|
||||
|
||||
const element = CloudCmd.Edit.getElement();
|
||||
|
||||
Menu = supermenu(element, options, getMenuData());
|
||||
|
||||
Menu.addContextMenuListener();
|
||||
Menu.show(position.x, position.y);
|
||||
}
|
||||
|
||||
function getMenuData() {
|
||||
const editor = CloudCmd.Edit.getEditor();
|
||||
|
||||
return {
|
||||
'Save Ctrl+S': () => {
|
||||
editor.save();
|
||||
},
|
||||
'Go To Line Ctrl+G': () => {
|
||||
editor.goToLine();
|
||||
},
|
||||
'Cut Ctrl+X': () => {
|
||||
editor.cutToClipboard();
|
||||
},
|
||||
'Copy Ctrl+C': () => {
|
||||
editor.copyToClipboard();
|
||||
},
|
||||
'Paste Ctrl+V': () => {
|
||||
editor.pasteFromClipboard();
|
||||
},
|
||||
'Delete Del': () => {
|
||||
editor.remove('right');
|
||||
},
|
||||
'Select All Ctrl+A': () => {
|
||||
editor.selectAll();
|
||||
},
|
||||
'Close Esc': hide,
|
||||
};
|
||||
}
|
||||
|
||||
function setMsgChanged(name) {
|
||||
MSG_CHANGED = `Do you want to save changes to ${name}?`;
|
||||
}
|
||||
|
||||
module.exports.isChanged = isChanged;
|
||||
|
||||
async function isChanged() {
|
||||
const editor = CloudCmd.Edit.getEditor();
|
||||
const is = editor.isChanged();
|
||||
|
||||
if (!is)
|
||||
return;
|
||||
|
||||
const [cancel] = await Dialog.confirm(MSG_CHANGED);
|
||||
|
||||
if (cancel)
|
||||
return;
|
||||
|
||||
editor.save();
|
||||
}
|
||||
43
client/modules/edit-names-vim.js
Normal file
43
client/modules/edit-names-vim.js
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
'use strict';
|
||||
|
||||
/* global CloudCmd */
|
||||
CloudCmd.EditNamesVim = exports;
|
||||
|
||||
const Events = require('#dom/events');
|
||||
const {Key} = CloudCmd;
|
||||
|
||||
const ConfigView = {
|
||||
bindKeys: false,
|
||||
beforeClose: () => {
|
||||
Events.rmKey(listener);
|
||||
CloudCmd.EditNames.isChanged();
|
||||
},
|
||||
};
|
||||
|
||||
module.exports.init = async () => {
|
||||
await CloudCmd.EditNames();
|
||||
};
|
||||
|
||||
module.exports.show = () => {
|
||||
Events.addKey(listener);
|
||||
|
||||
CloudCmd.EditNames
|
||||
.show(ConfigView)
|
||||
.getEditor()
|
||||
.setKeyMap('vim');
|
||||
};
|
||||
|
||||
module.exports.hide = hide;
|
||||
|
||||
function hide() {
|
||||
CloudCmd.Edit.hide();
|
||||
}
|
||||
|
||||
function listener(event) {
|
||||
const {keyCode, shiftKey} = event;
|
||||
|
||||
if (shiftKey && keyCode === Key.ESC) {
|
||||
event.preventDefault();
|
||||
hide();
|
||||
}
|
||||
}
|
||||
216
client/modules/edit-names.js
Normal file
216
client/modules/edit-names.js
Normal file
|
|
@ -0,0 +1,216 @@
|
|||
'use strict';
|
||||
|
||||
const {tryToCatch} = require('try-to-catch');
|
||||
|
||||
/* global CloudCmd, DOM */
|
||||
CloudCmd.EditNames = exports;
|
||||
|
||||
const exec = require('execon');
|
||||
const supermenu = require('supermenu');
|
||||
const {multiRename} = require('multi-rename');
|
||||
|
||||
const Info = DOM.CurrentInfo;
|
||||
const {Dialog} = DOM;
|
||||
|
||||
let Menu;
|
||||
|
||||
const ConfigView = {
|
||||
beforeClose: async () => {
|
||||
exec.ifExist(Menu, 'hide');
|
||||
DOM.Events.remove('keydown', keyListener);
|
||||
await isChanged();
|
||||
},
|
||||
};
|
||||
|
||||
module.exports.init = async () => {
|
||||
await CloudCmd.Edit();
|
||||
|
||||
setListeners();
|
||||
};
|
||||
|
||||
module.exports.show = (options) => {
|
||||
const names = getActiveNames().join('\n');
|
||||
const config = {
|
||||
...ConfigView,
|
||||
...options,
|
||||
};
|
||||
|
||||
if (Info.name === '..' && names.length === 1)
|
||||
return Dialog.alert.noFiles();
|
||||
|
||||
DOM.Events.addKey(keyListener);
|
||||
|
||||
CloudCmd.Edit
|
||||
.getEditor()
|
||||
.setValueFirst('edit-names', names)
|
||||
.setMode()
|
||||
.setOption('keyMap', 'default')
|
||||
.disableKey();
|
||||
|
||||
CloudCmd.Edit.show(config);
|
||||
|
||||
return CloudCmd.Edit;
|
||||
};
|
||||
|
||||
async function keyListener(event) {
|
||||
const ctrl = event.ctrlKey;
|
||||
const meta = event.metaKey;
|
||||
const ctrlMeta = ctrl || meta;
|
||||
const {Key} = CloudCmd;
|
||||
|
||||
if (ctrlMeta && event.keyCode === Key.S) {
|
||||
hide();
|
||||
} else if (ctrlMeta && event.keyCode === Key.P) {
|
||||
const [, pattern] = await Dialog.prompt('Apply pattern:', '[n][e]');
|
||||
pattern && applyPattern(pattern);
|
||||
}
|
||||
}
|
||||
|
||||
function applyPattern(pattern) {
|
||||
const newNames = multiRename(pattern, getActiveNames());
|
||||
const editor = CloudCmd.Edit.getEditor();
|
||||
|
||||
editor.setValue(newNames.join('\n'));
|
||||
}
|
||||
|
||||
function getActiveNames() {
|
||||
return DOM.getFilenames(DOM.getActiveFiles());
|
||||
}
|
||||
|
||||
module.exports.hide = hide;
|
||||
|
||||
function hide() {
|
||||
CloudCmd.Edit.hide();
|
||||
}
|
||||
|
||||
function setListeners() {
|
||||
const element = CloudCmd.Edit.getElement();
|
||||
|
||||
DOM.Events.addOnce('contextmenu', element, setMenu);
|
||||
}
|
||||
|
||||
async function applyNames() {
|
||||
const dir = Info.dirPath;
|
||||
const from = getActiveNames();
|
||||
const nameIndex = from.indexOf(Info.name);
|
||||
|
||||
const editor = CloudCmd.Edit.getEditor();
|
||||
const to = editor
|
||||
.getValue()
|
||||
.split('\n');
|
||||
|
||||
const root = CloudCmd.config('root');
|
||||
|
||||
const response = rename(dir, from, to, root);
|
||||
const [error] = await tryToCatch(refresh, to, nameIndex, response);
|
||||
|
||||
if (error)
|
||||
alert(error);
|
||||
}
|
||||
|
||||
function refresh(to, nameIndex, res) {
|
||||
if (res.status === 404) {
|
||||
const error = res.text();
|
||||
throw error;
|
||||
}
|
||||
|
||||
const currentName = to[nameIndex];
|
||||
|
||||
CloudCmd.refresh({
|
||||
currentName,
|
||||
});
|
||||
}
|
||||
|
||||
function getDir(root, dir) {
|
||||
if (root === '/')
|
||||
return dir;
|
||||
|
||||
return root + dir;
|
||||
}
|
||||
|
||||
function rename(path, from, to, root) {
|
||||
const dir = getDir(root, path);
|
||||
const {prefix} = CloudCmd;
|
||||
|
||||
return fetch(`${prefix}/rename`, {
|
||||
method: 'put',
|
||||
credentials: 'include',
|
||||
body: JSON.stringify({
|
||||
from,
|
||||
to,
|
||||
dir,
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
function setMenu(event) {
|
||||
const position = {
|
||||
x: event.clientX,
|
||||
y: event.clientY,
|
||||
};
|
||||
|
||||
event.preventDefault();
|
||||
|
||||
if (Menu)
|
||||
return;
|
||||
|
||||
const editor = CloudCmd.Edit.getEditor();
|
||||
|
||||
const options = {
|
||||
beforeShow: (params) => {
|
||||
params.x -= 18;
|
||||
params.y -= 27;
|
||||
},
|
||||
|
||||
afterClick: () => {
|
||||
editor.focus();
|
||||
},
|
||||
};
|
||||
|
||||
const menuData = {
|
||||
'Save Ctrl+S': async () => {
|
||||
await applyNames();
|
||||
hide();
|
||||
},
|
||||
'Go To Line Ctrl+G': () => {
|
||||
editor.goToLine();
|
||||
},
|
||||
'Cut Ctrl+X': () => {
|
||||
editor.cutToClipboard();
|
||||
},
|
||||
'Copy Ctrl+C': () => {
|
||||
editor.copyToClipboard();
|
||||
},
|
||||
'Paste Ctrl+V': () => {
|
||||
editor.pasteFromClipboard();
|
||||
},
|
||||
'Delete Del': () => {
|
||||
editor.remove('right');
|
||||
},
|
||||
'Select All Ctrl+A': () => {
|
||||
editor.selectAll();
|
||||
},
|
||||
'Close Esc': hide,
|
||||
};
|
||||
|
||||
const element = CloudCmd.Edit.getElement();
|
||||
|
||||
Menu = supermenu(element, options, menuData);
|
||||
|
||||
Menu.addContextMenuListener();
|
||||
Menu.show(position.x, position.y);
|
||||
}
|
||||
|
||||
module.exports.isChanged = isChanged;
|
||||
|
||||
async function isChanged() {
|
||||
const editor = CloudCmd.Edit.getEditor();
|
||||
const msg = 'Apply new names?';
|
||||
|
||||
if (!editor.isChanged())
|
||||
return;
|
||||
|
||||
const [cancel] = await Dialog.confirm(msg);
|
||||
|
||||
!cancel && await applyNames();
|
||||
}
|
||||
122
client/modules/edit.js
Normal file
122
client/modules/edit.js
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
/* global CloudCmd */
|
||||
|
||||
'use strict';
|
||||
|
||||
const montag = require('montag');
|
||||
|
||||
const {promisify} = require('es6-promisify');
|
||||
const {tryToCatch} = require('try-to-catch');
|
||||
const createElement = require('@cloudcmd/create-element');
|
||||
const load = require('load.js');
|
||||
const {MAX_FILE_SIZE: maxSize} = require('../../common/cloudfunc.mjs');
|
||||
|
||||
const {time, timeEnd} = require('../../common/util');
|
||||
const getEditor = () => editor;
|
||||
const isFn = (a) => typeof a === 'function';
|
||||
const loadJS = load.js;
|
||||
|
||||
const Name = 'Edit';
|
||||
|
||||
CloudCmd[Name] = exports;
|
||||
|
||||
const EditorName = CloudCmd.config('editor');
|
||||
|
||||
let Loading = true;
|
||||
let Element;
|
||||
let editor;
|
||||
|
||||
const ConfigView = {
|
||||
afterShow: () => {
|
||||
editor
|
||||
.moveCursorTo(0, 0)
|
||||
.focus();
|
||||
},
|
||||
};
|
||||
|
||||
module.exports.init = async () => {
|
||||
const element = create();
|
||||
|
||||
await CloudCmd.View();
|
||||
await loadFiles(element);
|
||||
};
|
||||
|
||||
function create() {
|
||||
const element = createElement('div', {
|
||||
style: montag`
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
font-family: "Droid Sans Mono";
|
||||
`,
|
||||
notAppend: true,
|
||||
});
|
||||
|
||||
Element = element;
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
function checkFn(name, fn) {
|
||||
if (!isFn(fn))
|
||||
throw Error(`${name} should be a function!`);
|
||||
}
|
||||
|
||||
function initConfig(options = {}) {
|
||||
const config = {
|
||||
...options,
|
||||
...ConfigView,
|
||||
};
|
||||
|
||||
if (!options.afterShow)
|
||||
return config;
|
||||
|
||||
checkFn('options.afterShow', options.afterShow);
|
||||
|
||||
config.afterShow = () => {
|
||||
ConfigView.afterShow();
|
||||
options.afterShow();
|
||||
};
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
module.exports.show = (options) => {
|
||||
if (Loading)
|
||||
return;
|
||||
|
||||
CloudCmd.View.show(Element, initConfig(options));
|
||||
|
||||
getEditor().setOptions({
|
||||
fontSize: 16,
|
||||
});
|
||||
};
|
||||
|
||||
module.exports.getEditor = getEditor;
|
||||
|
||||
module.exports.getElement = () => Element;
|
||||
|
||||
module.exports.hide = () => {
|
||||
CloudCmd.View.hide();
|
||||
};
|
||||
|
||||
const loadFiles = async (element) => {
|
||||
const prefix = `${CloudCmd.prefix}/${EditorName}`;
|
||||
const socketPath = CloudCmd.prefix;
|
||||
const prefixSocket = `${CloudCmd.prefixSocket}/${EditorName}`;
|
||||
const url = `${prefix}/${EditorName}.js`;
|
||||
|
||||
time(`${Name} load`);
|
||||
|
||||
await loadJS(url);
|
||||
|
||||
const word = promisify(window[EditorName]);
|
||||
const [ed] = await tryToCatch(word, element, {
|
||||
maxSize,
|
||||
prefix,
|
||||
prefixSocket,
|
||||
socketPath,
|
||||
});
|
||||
|
||||
timeEnd(`${Name} load`);
|
||||
editor = ed;
|
||||
Loading = false;
|
||||
};
|
||||
27
client/modules/help.js
Normal file
27
client/modules/help.js
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
'use strict';
|
||||
|
||||
/* global CloudCmd */
|
||||
CloudCmd.Help = exports;
|
||||
|
||||
const Images = require('../dom/images.mjs');
|
||||
|
||||
module.exports.init = () => {
|
||||
Images.show.load('top');
|
||||
};
|
||||
|
||||
module.exports.show = show;
|
||||
module.exports.hide = hide;
|
||||
|
||||
function show() {
|
||||
const positionLoad = 'top';
|
||||
const relative = true;
|
||||
|
||||
CloudCmd.Markdown.show('/HELP.md', {
|
||||
positionLoad,
|
||||
relative,
|
||||
});
|
||||
}
|
||||
|
||||
function hide() {
|
||||
CloudCmd.View.hide();
|
||||
}
|
||||
141
client/modules/konsole.js
Normal file
141
client/modules/konsole.js
Normal file
|
|
@ -0,0 +1,141 @@
|
|||
'use strict';
|
||||
|
||||
/* global CloudCmd */
|
||||
/* global Util */
|
||||
/* global DOM */
|
||||
/* global Console */
|
||||
CloudCmd.Konsole = exports;
|
||||
|
||||
const exec = require('execon');
|
||||
const currify = require('currify');
|
||||
const {tryToCatch} = require('try-to-catch');
|
||||
const loadJS = require('load.js').js;
|
||||
const createElement = require('@cloudcmd/create-element');
|
||||
|
||||
const Images = require('../dom/images.mjs');
|
||||
const {Dialog, CurrentInfo: Info} = DOM;
|
||||
|
||||
const rmLastSlash = (a) => a.replace(/\/$/, '') || '/';
|
||||
|
||||
let konsole;
|
||||
const {config} = CloudCmd;
|
||||
|
||||
const cd = currify((fn, dir) => fn(`cd ${rmLastSlash(dir)}`));
|
||||
|
||||
const Name = 'Konsole';
|
||||
|
||||
let Element;
|
||||
let Loaded;
|
||||
|
||||
module.exports.init = async () => {
|
||||
if (!config('console'))
|
||||
return;
|
||||
|
||||
Images.show.load('top');
|
||||
|
||||
await CloudCmd.View();
|
||||
await load();
|
||||
await create();
|
||||
};
|
||||
|
||||
module.exports.hide = () => {
|
||||
CloudCmd.View.hide();
|
||||
};
|
||||
|
||||
module.exports.clear = () => {
|
||||
konsole.clear();
|
||||
};
|
||||
|
||||
const getPrefix = () => CloudCmd.prefix + '/console';
|
||||
|
||||
function getPrefixSocket() {
|
||||
return CloudCmd.prefixSocket + '/console';
|
||||
}
|
||||
|
||||
const getEnv = () => ({
|
||||
ACTIVE_DIR: DOM.getCurrentDirPath.bind(DOM),
|
||||
PASSIVE_DIR: DOM.getNotCurrentDirPath.bind(DOM),
|
||||
CURRENT_NAME: DOM.getCurrentName.bind(DOM),
|
||||
CURRENT_PATH: () => Info.path,
|
||||
});
|
||||
|
||||
async function onPath(path) {
|
||||
if (Info.dirPath === path)
|
||||
return;
|
||||
|
||||
await CloudCmd.changeDir(path);
|
||||
}
|
||||
|
||||
const getDirPath = () => {
|
||||
if (config('syncConsolePath'))
|
||||
return Info.dirPath;
|
||||
};
|
||||
|
||||
const create = async () => {
|
||||
const options = {
|
||||
cwd: getDirPath(),
|
||||
env: getEnv(),
|
||||
prefix: getPrefix(),
|
||||
prefixSocket: getPrefixSocket(),
|
||||
socketPath: CloudCmd.prefix,
|
||||
};
|
||||
|
||||
Element = createElement('div', {
|
||||
className: 'console',
|
||||
});
|
||||
|
||||
konsole = await Console(Element, options);
|
||||
|
||||
konsole.on('connect', exec.with(authCheck, konsole));
|
||||
konsole.on('path', config.if('syncConsolePath', onPath));
|
||||
|
||||
CloudCmd.on('active-dir', config.if('syncConsolePath', cd(konsole.handler)));
|
||||
|
||||
konsole.addShortCuts({
|
||||
P: () => {
|
||||
const command = konsole.getPromptText();
|
||||
const path = DOM.getCurrentDirPath();
|
||||
|
||||
konsole.setPromptText(command + path);
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
function authCheck(konsole) {
|
||||
konsole.emit('auth', config('username'), config('password'));
|
||||
|
||||
konsole.on('reject', () => {
|
||||
Dialog.alert('Wrong credentials!');
|
||||
});
|
||||
}
|
||||
|
||||
module.exports.show = (callback) => {
|
||||
if (!Loaded)
|
||||
return;
|
||||
|
||||
if (!config('console'))
|
||||
return;
|
||||
|
||||
CloudCmd.View.show(Element, {
|
||||
afterShow: () => {
|
||||
konsole.focus();
|
||||
exec(callback);
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const load = async () => {
|
||||
Util.time(`${Name} load`);
|
||||
|
||||
const prefix = getPrefix();
|
||||
const url = `${prefix}/console.js`;
|
||||
const [error] = await tryToCatch(loadJS, url);
|
||||
|
||||
Loaded = true;
|
||||
Util.timeEnd(`${Name} load`);
|
||||
|
||||
if (error)
|
||||
return Dialog.alert(error.message, {
|
||||
cancel: false,
|
||||
});
|
||||
};
|
||||
47
client/modules/markdown.js
Normal file
47
client/modules/markdown.js
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
'use strict';
|
||||
|
||||
/* global CloudCmd */
|
||||
CloudCmd.Markdown = exports;
|
||||
|
||||
const createElement = require('@cloudcmd/create-element');
|
||||
|
||||
const Images = require('../dom/images.mjs');
|
||||
const {Markdown} = require('../dom/rest');
|
||||
const {alert} = require('../dom/dialog');
|
||||
|
||||
module.exports.init = async () => {
|
||||
Images.show.load('top');
|
||||
await CloudCmd.View();
|
||||
};
|
||||
|
||||
module.exports.show = show;
|
||||
|
||||
module.exports.hide = () => {
|
||||
CloudCmd.View.hide();
|
||||
};
|
||||
|
||||
async function show(name, options = {}) {
|
||||
const {positionLoad, relative} = options;
|
||||
|
||||
Images.show.load(positionLoad);
|
||||
|
||||
if (relative)
|
||||
name += '?relative';
|
||||
|
||||
const [error, innerHTML] = await Markdown.read(name);
|
||||
Images.hide();
|
||||
|
||||
if (error)
|
||||
return alert(error.message, {
|
||||
cancel: false,
|
||||
});
|
||||
|
||||
const className = 'help';
|
||||
|
||||
const div = createElement('div', {
|
||||
className,
|
||||
innerHTML,
|
||||
});
|
||||
|
||||
CloudCmd.View.show(div);
|
||||
}
|
||||
30
client/modules/menu/cloudmenu.mjs
Normal file
30
client/modules/menu/cloudmenu.mjs
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
import supermenu from 'supermenu';
|
||||
|
||||
const noop = () => {};
|
||||
const {CloudCmd} = globalThis;
|
||||
|
||||
export const createCloudMenu = async (fm, options, menuData) => {
|
||||
const createMenu = await loadMenu();
|
||||
const menu = await createMenu(fm, options, menuData);
|
||||
|
||||
menu.addContextMenuListener = menu.addContextMenuListener || noop;
|
||||
|
||||
return menu;
|
||||
};
|
||||
|
||||
async function loadMenu() {
|
||||
if (CloudCmd.config('menu') === 'aleman') {
|
||||
const {host, protocol} = globalThis.location;
|
||||
const url = `${protocol}//${host}/node_modules/aleman/menu/menu.js`;
|
||||
const {createMenu} = await import(/* webpackIgnore: true */url);
|
||||
|
||||
return createMenu;
|
||||
}
|
||||
|
||||
return createSupermenu;
|
||||
}
|
||||
|
||||
function createSupermenu(name, options, menuData) {
|
||||
const element = document.querySelector('[data-name="js-fm"]');
|
||||
return supermenu(element, options, menuData);
|
||||
}
|
||||
357
client/modules/menu/index.js
Normal file
357
client/modules/menu/index.js
Normal file
|
|
@ -0,0 +1,357 @@
|
|||
/* global CloudCmd, DOM */
|
||||
|
||||
'use strict';
|
||||
|
||||
const exec = require('execon');
|
||||
const wrap = require('wraptile');
|
||||
const createElement = require('@cloudcmd/create-element');
|
||||
|
||||
const {FS} = require('../../../common/cloudfunc.mjs');
|
||||
const {getIdBySrc} = require('../../dom/load');
|
||||
const RESTful = require('../../dom/rest');
|
||||
|
||||
const {config, Key} = CloudCmd;
|
||||
|
||||
const {
|
||||
Buffer,
|
||||
Events,
|
||||
Dialog,
|
||||
Images,
|
||||
} = DOM;
|
||||
|
||||
const Info = DOM.CurrentInfo;
|
||||
const alertNoFiles = Dialog.alert.noFiles;
|
||||
const uploadTo = wrap(_uploadTo);
|
||||
|
||||
let MenuShowedName;
|
||||
let MenuContext;
|
||||
let MenuContextFile;
|
||||
|
||||
module.exports.ENABLED = false;
|
||||
|
||||
CloudCmd.Menu = exports;
|
||||
|
||||
module.exports.init = async () => {
|
||||
const {isAuth, menuDataFile} = getFileMenuData();
|
||||
|
||||
const fm = DOM.getFM();
|
||||
const menuData = getMenuData(isAuth);
|
||||
|
||||
const options = getOptions({
|
||||
type: 'context',
|
||||
});
|
||||
|
||||
const optionsFile = getOptions({
|
||||
type: 'file',
|
||||
});
|
||||
|
||||
const {createCloudMenu} = await import('./cloudmenu.mjs');
|
||||
|
||||
const {name} = fm.dataset;
|
||||
|
||||
MenuContext = await createCloudMenu(name, options, menuData);
|
||||
MenuContextFile = await createCloudMenu(name, optionsFile, menuDataFile);
|
||||
|
||||
MenuContext.addContextMenuListener();
|
||||
MenuContextFile.addContextMenuListener();
|
||||
|
||||
Events.addKey(listener);
|
||||
};
|
||||
|
||||
module.exports.hide = hide;
|
||||
|
||||
function hide() {
|
||||
MenuContext.hide();
|
||||
MenuContextFile.hide();
|
||||
}
|
||||
|
||||
module.exports.show = (position) => {
|
||||
const {x, y} = getPosition(position);
|
||||
|
||||
MenuContext.show(x, y);
|
||||
MenuContextFile.show(x, y);
|
||||
|
||||
Images.hide();
|
||||
};
|
||||
|
||||
function getPosition(position) {
|
||||
if (position)
|
||||
return {
|
||||
x: position.x,
|
||||
y: position.y,
|
||||
};
|
||||
|
||||
return getCurrentPosition();
|
||||
}
|
||||
|
||||
function getMenuNameByEl(el) {
|
||||
if (!el)
|
||||
return 'context';
|
||||
|
||||
const name = DOM.getCurrentName(el);
|
||||
|
||||
if (name === '..')
|
||||
return 'context';
|
||||
|
||||
return 'contextFile';
|
||||
}
|
||||
|
||||
function getOptions({type}) {
|
||||
let name;
|
||||
let func;
|
||||
|
||||
if (type === 'context') {
|
||||
name = 'context';
|
||||
func = Key.unsetBind;
|
||||
} else if (type === 'file') {
|
||||
name = 'contextFile';
|
||||
}
|
||||
|
||||
const options = {
|
||||
icon: true,
|
||||
infiniteScroll: false,
|
||||
beforeClose: Key.setBind,
|
||||
beforeHide: Key.setBind,
|
||||
beforeShow: exec.with(beforeShow, func),
|
||||
beforeClick,
|
||||
name,
|
||||
};
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
function getMenuData(isAuth) {
|
||||
const menu = {
|
||||
'Paste': Buffer.paste,
|
||||
'New': {
|
||||
File: DOM.promptNewFile,
|
||||
Directory: DOM.promptNewDir,
|
||||
},
|
||||
'Upload': () => {
|
||||
CloudCmd.Upload.show();
|
||||
},
|
||||
'Upload From Cloud': uploadFromCloud,
|
||||
'Toggle File Selection': DOM.toggleSelectedFile,
|
||||
'(Un)Select All': DOM.toggleAllSelectedFiles,
|
||||
};
|
||||
|
||||
if (isAuth)
|
||||
menu['Log Out'] = CloudCmd.logOut;
|
||||
|
||||
return menu;
|
||||
}
|
||||
|
||||
function getFileMenuData() {
|
||||
const isAuth = CloudCmd.config('auth');
|
||||
|
||||
const menuBottom = getMenuData(isAuth);
|
||||
const menuTop = {
|
||||
'View': () => {
|
||||
CloudCmd.View.show();
|
||||
},
|
||||
'Edit': () => {
|
||||
const name = config('vim') ? 'EditFileVim' : 'EditFile';
|
||||
CloudCmd[name].show();
|
||||
},
|
||||
'Rename': () => {
|
||||
setTimeout(DOM.renameCurrent, 100);
|
||||
},
|
||||
'Delete': () => {
|
||||
CloudCmd.Operation.show('delete');
|
||||
},
|
||||
'Pack': () => {
|
||||
CloudCmd.Operation.show('pack');
|
||||
},
|
||||
'Extract': () => {
|
||||
CloudCmd.Operation.show('extract');
|
||||
},
|
||||
'Download': preDownload,
|
||||
'Upload To Cloud': uploadTo('Cloud'),
|
||||
'Cut': () => {
|
||||
isCurrent(Buffer.cut, alertNoFiles);
|
||||
},
|
||||
'Copy': () => {
|
||||
isCurrent(Buffer.copy, alertNoFiles);
|
||||
},
|
||||
};
|
||||
|
||||
const menuDataFile = {
|
||||
...menuTop,
|
||||
...menuBottom,
|
||||
};
|
||||
|
||||
return {
|
||||
isAuth,
|
||||
menuDataFile,
|
||||
};
|
||||
}
|
||||
|
||||
function isCurrent(yesFn, noFn) {
|
||||
if (Info.name !== '..')
|
||||
return yesFn();
|
||||
|
||||
noFn();
|
||||
}
|
||||
|
||||
function isPath(x, y) {
|
||||
const {panel} = Info;
|
||||
const isEmptyRoot = !panel;
|
||||
|
||||
if (isEmptyRoot)
|
||||
return false;
|
||||
|
||||
const el = document.elementFromPoint(x, y);
|
||||
const elements = panel.querySelectorAll('[data-name="js-path"] *');
|
||||
|
||||
return !~[].indexOf.call(elements, el);
|
||||
}
|
||||
|
||||
function beforeShow(callback, params) {
|
||||
Key.unsetBind();
|
||||
|
||||
const {
|
||||
name,
|
||||
position = {
|
||||
x: params.x,
|
||||
y: params.y,
|
||||
},
|
||||
} = params;
|
||||
|
||||
const {x, y} = position;
|
||||
|
||||
const el = DOM.getCurrentByPosition({
|
||||
x,
|
||||
y,
|
||||
});
|
||||
|
||||
const menuName = getMenuNameByEl(el);
|
||||
|
||||
let isShow = menuName !== 'contextFile';
|
||||
|
||||
if (params.name === 'contextFile')
|
||||
isShow = !isShow;
|
||||
|
||||
if (isShow)
|
||||
MenuShowedName = name;
|
||||
|
||||
exec(callback);
|
||||
|
||||
if (isShow)
|
||||
isShow = isPath(x, y);
|
||||
|
||||
return isShow;
|
||||
}
|
||||
|
||||
const beforeClick = (name) => MenuShowedName !== name;
|
||||
|
||||
async function _uploadTo(nameModule) {
|
||||
const [error, data] = await Info.getData();
|
||||
|
||||
if (error)
|
||||
return;
|
||||
|
||||
const {name} = Info;
|
||||
|
||||
CloudCmd.execFromModule(nameModule, 'uploadFile', name, data);
|
||||
CloudCmd.log(`Uploading to ${name}...`);
|
||||
}
|
||||
|
||||
function uploadFromCloud() {
|
||||
Images.show.load('top');
|
||||
|
||||
CloudCmd.execFromModule('Cloud', 'saveFile', async (currentName, data) => {
|
||||
const path = DOM.getCurrentDirPath() + currentName;
|
||||
const [e] = await RESTful.write(path, data);
|
||||
|
||||
if (e)
|
||||
return;
|
||||
|
||||
await CloudCmd.refresh({
|
||||
currentName,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function preDownload() {
|
||||
download(config('packer'));
|
||||
}
|
||||
|
||||
function download(type) {
|
||||
const TIME = 30 * 1000;
|
||||
const {prefixURL} = CloudCmd;
|
||||
const PACK = '/pack';
|
||||
const date = Date.now();
|
||||
const files = DOM.getActiveFiles();
|
||||
|
||||
if (!files.length)
|
||||
return alertNoFiles();
|
||||
|
||||
for (const file of files) {
|
||||
const selected = DOM.isSelected(file);
|
||||
const isDir = DOM.isCurrentIsDir(file);
|
||||
const path = DOM.getCurrentPath(file);
|
||||
|
||||
CloudCmd.log(`downloading file ${path}...`);
|
||||
|
||||
/*
|
||||
* if we send ajax request -
|
||||
* no need in hash so we escape #
|
||||
* and all other characters, like "%"
|
||||
*/
|
||||
const encodedPath = encodeURI(path).replace(/#/g, '%23');
|
||||
const id = getIdBySrc(path);
|
||||
|
||||
let src;
|
||||
|
||||
if (isDir)
|
||||
src = prefixURL + PACK + encodedPath + DOM.getPackerExt(type);
|
||||
else
|
||||
src = prefixURL + FS + encodedPath + '?download';
|
||||
|
||||
const element = createElement('iframe', {
|
||||
id: id + '-' + date,
|
||||
async: false,
|
||||
className: 'hidden',
|
||||
src,
|
||||
});
|
||||
|
||||
const {body} = document;
|
||||
const removeChild = body.removeChild.bind(body, element);
|
||||
|
||||
setTimeout(removeChild, TIME);
|
||||
|
||||
if (selected)
|
||||
DOM.toggleSelectedFile(file);
|
||||
}
|
||||
}
|
||||
|
||||
function getCurrentPosition() {
|
||||
const current = Info.element;
|
||||
const rect = current.getBoundingClientRect();
|
||||
|
||||
const position = {
|
||||
x: Math.round(rect.left + rect.width / 3),
|
||||
y: Math.round(rect.top),
|
||||
};
|
||||
|
||||
return position;
|
||||
}
|
||||
|
||||
function listener(event) {
|
||||
const {F9, ESC} = Key;
|
||||
|
||||
const key = event.keyCode;
|
||||
const isBind = Key.isBind();
|
||||
|
||||
if (key === ESC) {
|
||||
Key.setBind();
|
||||
return hide();
|
||||
}
|
||||
|
||||
if (isBind && key === F9) {
|
||||
const position = getCurrentPosition();
|
||||
MenuContext.show(position.x, position.y);
|
||||
|
||||
event.preventDefault();
|
||||
}
|
||||
}
|
||||
8
client/modules/operation/format.js
Normal file
8
client/modules/operation/format.js
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
'use strict';
|
||||
|
||||
module.exports = (operation, from, to) => {
|
||||
if (!to)
|
||||
return `${operation} ${from}`;
|
||||
|
||||
return `${operation} ${from} -> ${to}`;
|
||||
};
|
||||
18
client/modules/operation/get-next-current-name.js
Normal file
18
client/modules/operation/get-next-current-name.js
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
'use strict';
|
||||
|
||||
const currify = require('currify');
|
||||
|
||||
const not = currify((array, value) => !array.includes(value));
|
||||
const notOneOf = currify((a, b) => a.filter(not(b)));
|
||||
|
||||
module.exports = (currentName, names, removedNames) => {
|
||||
const i = names.indexOf(currentName);
|
||||
|
||||
const nextNames = notOneOf(names, removedNames);
|
||||
const {length} = nextNames;
|
||||
|
||||
if (nextNames[i])
|
||||
return nextNames[i];
|
||||
|
||||
return nextNames[length - 1];
|
||||
};
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue