mirror of
https://github.com/home-assistant/frontend.git
synced 2025-08-22 15:49:26 +00:00
Compare commits
1990 Commits
20240424.0
...
websocket_
Author | SHA1 | Date | |
---|---|---|---|
![]() |
dd00b51f21 | ||
![]() |
64b886eea0 | ||
![]() |
b95e87845f | ||
![]() |
bc49ebc489 | ||
![]() |
c97d0ce68a | ||
![]() |
a0e7d6f1c6 | ||
![]() |
25d2a5ddac | ||
![]() |
a2f2d64f5c | ||
![]() |
fcdcbbda05 | ||
![]() |
4b5c7fc2de | ||
![]() |
dd64d88afe | ||
![]() |
5feffd08ff | ||
![]() |
543c7df3e0 | ||
![]() |
167f859f2a | ||
![]() |
c7d9699a24 | ||
![]() |
a638cf443d | ||
![]() |
438d1c13ef | ||
![]() |
cc8869b9f9 | ||
![]() |
cbdb7406ad | ||
![]() |
f8d2560104 | ||
![]() |
cc48ae82d6 | ||
![]() |
e1bda9b57d | ||
![]() |
89e9316a40 | ||
![]() |
85e4975206 | ||
![]() |
142faba04d | ||
![]() |
c1c6d71ccf | ||
![]() |
5204a565cf | ||
![]() |
05b8a48ba8 | ||
![]() |
41770a89b4 | ||
![]() |
b7d14d7950 | ||
![]() |
4ccef6f28b | ||
![]() |
d1be441455 | ||
![]() |
b3391b34e4 | ||
![]() |
9359e9d475 | ||
![]() |
5453da75ea | ||
![]() |
bc21877008 | ||
![]() |
c9956c65e9 | ||
![]() |
74814cc305 | ||
![]() |
8f231d7b3e | ||
![]() |
5b6818d72d | ||
![]() |
8c75865a02 | ||
![]() |
99d832ac77 | ||
![]() |
240e48f5c1 | ||
![]() |
77fc11cda6 | ||
![]() |
f8f152f118 | ||
![]() |
20a67cf73c | ||
![]() |
dd11b3092e | ||
![]() |
7f3363621e | ||
![]() |
edce1901d7 | ||
![]() |
546087066a | ||
![]() |
a95c589a06 | ||
![]() |
5f6da9d959 | ||
![]() |
bc94ca0a0a | ||
![]() |
dc8d483e8b | ||
![]() |
a329553ce1 | ||
![]() |
1f8cfdd0de | ||
![]() |
fd1f966216 | ||
![]() |
243a2ce0e2 | ||
![]() |
77c1786171 | ||
![]() |
7a7c204d74 | ||
![]() |
dcb74ad2ee | ||
![]() |
fd4c62a852 | ||
![]() |
bf1b0ac949 | ||
![]() |
c6f0c62fd6 | ||
![]() |
ac98672cb7 | ||
![]() |
6b471ba6e7 | ||
![]() |
b28e7d2f06 | ||
![]() |
bf471eb8c3 | ||
![]() |
8c52bc3ffb | ||
![]() |
54b328648a | ||
![]() |
62a9da2de2 | ||
![]() |
25ff96b9bf | ||
![]() |
caeb616dc6 | ||
![]() |
fb79e2cfb2 | ||
![]() |
666316e44a | ||
![]() |
1532093426 | ||
![]() |
2effb0935c | ||
![]() |
06a08bb4f2 | ||
![]() |
09102d34d6 | ||
![]() |
27d683f6e8 | ||
![]() |
b89bd0be3b | ||
![]() |
51e6e6d230 | ||
![]() |
9005f8faa9 | ||
![]() |
7aa2abc9c2 | ||
![]() |
898fd51c7d | ||
![]() |
b3141a0653 | ||
![]() |
1025f73c36 | ||
![]() |
1cd44728df | ||
![]() |
eaab19fb8c | ||
![]() |
c4b2896fac | ||
![]() |
ca2a9f9171 | ||
![]() |
9e868e144d | ||
![]() |
fcb6da55d8 | ||
![]() |
87907b98bd | ||
![]() |
7535d66373 | ||
![]() |
e994e3565d | ||
![]() |
562589a6cb | ||
![]() |
e87f6d6d5e | ||
![]() |
3feedb792a | ||
![]() |
fc290028c6 | ||
![]() |
2f5fd6f0c7 | ||
![]() |
9a3ca59d77 | ||
![]() |
f76c22cb5b | ||
![]() |
aad94624e2 | ||
![]() |
076ab91199 | ||
![]() |
d121b33263 | ||
![]() |
dbfcf310c3 | ||
![]() |
25ea6c2c55 | ||
![]() |
b2b2c21477 | ||
![]() |
09777db549 | ||
![]() |
f108f65e39 | ||
![]() |
2ee9824bcc | ||
![]() |
812461ea00 | ||
![]() |
c430c28c2a | ||
![]() |
d67c463b98 | ||
![]() |
8efaf2b031 | ||
![]() |
5b038a4fef | ||
![]() |
2105793355 | ||
![]() |
21c2351137 | ||
![]() |
ebd1bdd686 | ||
![]() |
05bd70dd64 | ||
![]() |
e5d2f2d94b | ||
![]() |
57edb86c5c | ||
![]() |
173d60b913 | ||
![]() |
c17c1e4217 | ||
![]() |
d112872eb2 | ||
![]() |
e54f178b02 | ||
![]() |
7960da1872 | ||
![]() |
6288154c53 | ||
![]() |
52d8e98cdb | ||
![]() |
1043db29be | ||
![]() |
e6cc920781 | ||
![]() |
8bc78ba793 | ||
![]() |
e703750136 | ||
![]() |
69a93ddb6e | ||
![]() |
630b48218b | ||
![]() |
54c78ecc4d | ||
![]() |
57a17b8663 | ||
![]() |
d3e832c09b | ||
![]() |
abe8899f9b | ||
![]() |
922cd72be4 | ||
![]() |
3f4ee97ede | ||
![]() |
6f9a385619 | ||
![]() |
eda0ea077c | ||
![]() |
9934ea4b4f | ||
![]() |
cc42d958ce | ||
![]() |
2e1efecdf7 | ||
![]() |
5fead1b03a | ||
![]() |
730da177ef | ||
![]() |
bd53d1076f | ||
![]() |
e012a9e929 | ||
![]() |
95ac8eb5ab | ||
![]() |
6dbc04455f | ||
![]() |
2b8fc04fdc | ||
![]() |
3baeb22423 | ||
![]() |
aae4ba7341 | ||
![]() |
46d62d55a3 | ||
![]() |
de027b6d93 | ||
![]() |
f1cc02b40f | ||
![]() |
23c6155f9b | ||
![]() |
b0e6c5dbaf | ||
![]() |
8cb4452126 | ||
![]() |
0cd0f65d51 | ||
![]() |
3479879bd0 | ||
![]() |
60b9fbced7 | ||
![]() |
7496998a69 | ||
![]() |
c9db02ba2e | ||
![]() |
08737366fc | ||
![]() |
707192feac | ||
![]() |
4b03caa01a | ||
![]() |
3ffbd435e0 | ||
![]() |
2e2f39adbd | ||
![]() |
5e7f356707 | ||
![]() |
b02d0e58b1 | ||
![]() |
c01d3aee41 | ||
![]() |
6dde7d6945 | ||
![]() |
14c71f436e | ||
![]() |
9acdd9f903 | ||
![]() |
12b2edaa65 | ||
![]() |
d55d388046 | ||
![]() |
ec1dedcb6b | ||
![]() |
d0fbba5063 | ||
![]() |
344e083ac6 | ||
![]() |
0ee6548650 | ||
![]() |
166633cfa8 | ||
![]() |
853059ac73 | ||
![]() |
31ed0f7bea | ||
![]() |
57388ae429 | ||
![]() |
20203a3cef | ||
![]() |
9ec9c7e56b | ||
![]() |
788441499a | ||
![]() |
712817df65 | ||
![]() |
f8264e4500 | ||
![]() |
50fa8dd269 | ||
![]() |
fc20716ff2 | ||
![]() |
c6aec2db7d | ||
![]() |
f75f4b9733 | ||
![]() |
b1acf9a057 | ||
![]() |
221b3932ed | ||
![]() |
c50f701160 | ||
![]() |
85bebfc309 | ||
![]() |
6e90afc5bd | ||
![]() |
e137e695ec | ||
![]() |
7133dc5688 | ||
![]() |
617480472e | ||
![]() |
6ef799be60 | ||
![]() |
9ff1ce3c96 | ||
![]() |
f53ac94e76 | ||
![]() |
6d084813d5 | ||
![]() |
926f5e3cd8 | ||
![]() |
befc650f81 | ||
![]() |
2019b8992e | ||
![]() |
4d2e9f203f | ||
![]() |
760d898de7 | ||
![]() |
a755af96a6 | ||
![]() |
046b90ae25 | ||
![]() |
a3e8bcf848 | ||
![]() |
2cf1b7b6e6 | ||
![]() |
4b13dde92e | ||
![]() |
ebcee7680a | ||
![]() |
ffff7970f5 | ||
![]() |
2a2b6d33b8 | ||
![]() |
61ed889370 | ||
![]() |
4cc95938c8 | ||
![]() |
63c658e5b9 | ||
![]() |
3d1817a6b9 | ||
![]() |
8be2ca5392 | ||
![]() |
f043886273 | ||
![]() |
ff75c89ed4 | ||
![]() |
a8803de6e3 | ||
![]() |
e9f3f71be1 | ||
![]() |
334c87b194 | ||
![]() |
8db4a76bb9 | ||
![]() |
7aa2136c21 | ||
![]() |
47308e7b46 | ||
![]() |
87884ac747 | ||
![]() |
ec1fc09140 | ||
![]() |
e2ad94469a | ||
![]() |
70541ec966 | ||
![]() |
0bf64ee7f4 | ||
![]() |
4ea0c83fbe | ||
![]() |
d126e02747 | ||
![]() |
102a9eeb61 | ||
![]() |
fc3e99e794 | ||
![]() |
70953788cc | ||
![]() |
4ffec51a5e | ||
![]() |
71e10d5d8e | ||
![]() |
cfbcb74ac2 | ||
![]() |
3ff5b832bc | ||
![]() |
1faf024c5b | ||
![]() |
6d48e725c7 | ||
![]() |
052744e3d1 | ||
![]() |
2945a7b701 | ||
![]() |
6c9df587e7 | ||
![]() |
8f58681d83 | ||
![]() |
4a16d9bd44 | ||
![]() |
fcc9da6d85 | ||
![]() |
e03dc2c382 | ||
![]() |
be967940a2 | ||
![]() |
64ad37ed6a | ||
![]() |
01bc45c78b | ||
![]() |
2206644c47 | ||
![]() |
486038c426 | ||
![]() |
711f721007 | ||
![]() |
3b8bc242fe | ||
![]() |
7e80eed003 | ||
![]() |
a7ef498d75 | ||
![]() |
caf8fdf4c7 | ||
![]() |
f19ca78b89 | ||
![]() |
0fba0e2850 | ||
![]() |
15606a5a90 | ||
![]() |
c7df147908 | ||
![]() |
031658eef4 | ||
![]() |
fa672ffbba | ||
![]() |
34bcd5e71c | ||
![]() |
73854efa57 | ||
![]() |
a371b842da | ||
![]() |
b439c5d213 | ||
![]() |
04a9c67112 | ||
![]() |
012bd0714c | ||
![]() |
4e10d140d9 | ||
![]() |
8df67b8eb1 | ||
![]() |
fb09eba831 | ||
![]() |
a5de6ff3af | ||
![]() |
806cc2c608 | ||
![]() |
48a160f057 | ||
![]() |
c697843c34 | ||
![]() |
317a2f5b21 | ||
![]() |
220011f15f | ||
![]() |
35faeb651b | ||
![]() |
8daea5b565 | ||
![]() |
cd69c4c361 | ||
![]() |
eaab47a667 | ||
![]() |
d08a28ab9e | ||
![]() |
e8af454705 | ||
![]() |
713b5c7cf7 | ||
![]() |
8b17286fb6 | ||
![]() |
f3705a7e1d | ||
![]() |
d0123b2cce | ||
![]() |
884c22f92b | ||
![]() |
700690474c | ||
![]() |
4686808e53 | ||
![]() |
cf1df712e4 | ||
![]() |
c338e9cb30 | ||
![]() |
8e8fd89d56 | ||
![]() |
f1c360c550 | ||
![]() |
b429ecc376 | ||
![]() |
6d8422513a | ||
![]() |
cb0a48265a | ||
![]() |
c9082724a8 | ||
![]() |
455cd0485e | ||
![]() |
f5ec2dcbe2 | ||
![]() |
6b039a1073 | ||
![]() |
94c03be7ae | ||
![]() |
4bf0a23513 | ||
![]() |
f01388473a | ||
![]() |
1d0c3da294 | ||
![]() |
be849887a1 | ||
![]() |
e1a6f6f0e3 | ||
![]() |
d0327915db | ||
![]() |
351d318c89 | ||
![]() |
7d1ca2acf0 | ||
![]() |
fea83c0873 | ||
![]() |
d3b4014182 | ||
![]() |
5c7fe04562 | ||
![]() |
44e26c925b | ||
![]() |
205dd3f968 | ||
![]() |
86133a0696 | ||
![]() |
2105db9104 | ||
![]() |
49c377b1c4 | ||
![]() |
3fd3c8003a | ||
![]() |
ccbb2704d1 | ||
![]() |
34218f08ef | ||
![]() |
cf91e6a2a3 | ||
![]() |
ab9759c6dd | ||
![]() |
95adbfcc12 | ||
![]() |
1b9cbe434d | ||
![]() |
918aa562c5 | ||
![]() |
2ff0cb58bc | ||
![]() |
a94460a0c7 | ||
![]() |
60e57748f7 | ||
![]() |
0ecb8a6866 | ||
![]() |
d9dfea938e | ||
![]() |
6fe4f94d55 | ||
![]() |
01bec32fd6 | ||
![]() |
5453d6f7f5 | ||
![]() |
a0799a409b | ||
![]() |
704e7f279f | ||
![]() |
1daaf50773 | ||
![]() |
54eb7d169c | ||
![]() |
33b410dea0 | ||
![]() |
c05054e4ff | ||
![]() |
f416b1b5da | ||
![]() |
6a345d86a6 | ||
![]() |
a04e9b68bd | ||
![]() |
f7dbd38c2e | ||
![]() |
7150016375 | ||
![]() |
c3507abd9c | ||
![]() |
fc8a8b28c2 | ||
![]() |
637fe37ef4 | ||
![]() |
657bfc82ca | ||
![]() |
44423812f4 | ||
![]() |
a6a76155e5 | ||
![]() |
8c18d816b6 | ||
![]() |
361caafab9 | ||
![]() |
94f679e387 | ||
![]() |
85bd6432a9 | ||
![]() |
00c1dfa1d2 | ||
![]() |
fb72e1fb9c | ||
![]() |
152d2d0bdf | ||
![]() |
e06aa52a21 | ||
![]() |
49aa935490 | ||
![]() |
cead1e355d | ||
![]() |
edc99b5d6c | ||
![]() |
b38963b214 | ||
![]() |
0d99531855 | ||
![]() |
9cde7637ca | ||
![]() |
edc08994b3 | ||
![]() |
fc0907ef72 | ||
![]() |
bdb28246fc | ||
![]() |
0582798cde | ||
![]() |
e7d9032cc4 | ||
![]() |
331385794c | ||
![]() |
8e71bd7e82 | ||
![]() |
664cc9b33d | ||
![]() |
6757cda7f0 | ||
![]() |
97e6313890 | ||
![]() |
3cfba7b960 | ||
![]() |
5fb384ad31 | ||
![]() |
76cb9ce807 | ||
![]() |
0e61596f5c | ||
![]() |
061b6af812 | ||
![]() |
fd95ab5518 | ||
![]() |
a7cacbbbe6 | ||
![]() |
5a0225b86a | ||
![]() |
8b79fc5848 | ||
![]() |
5513da51a8 | ||
![]() |
56f9165323 | ||
![]() |
6afcd4d770 | ||
![]() |
52e1f9315e | ||
![]() |
a00f645921 | ||
![]() |
faf3bb2644 | ||
![]() |
31d98ec935 | ||
![]() |
7d0a269f1b | ||
![]() |
147098f0fd | ||
![]() |
d4cbfd9583 | ||
![]() |
a35ba38a2d | ||
![]() |
8fa36c8226 | ||
![]() |
5ccc3365fe | ||
![]() |
dcf97d4667 | ||
![]() |
4b7acbb766 | ||
![]() |
7900eb4054 | ||
![]() |
53caef8f92 | ||
![]() |
14bebc76b0 | ||
![]() |
8b6382448f | ||
![]() |
5cd6f22e99 | ||
![]() |
523c38a83e | ||
![]() |
0a28bbdd72 | ||
![]() |
e58bef7795 | ||
![]() |
d403532fc1 | ||
![]() |
4de8b562bd | ||
![]() |
31e85836f0 | ||
![]() |
e1359781a5 | ||
![]() |
379bc3a4e3 | ||
![]() |
b3b0006ba3 | ||
![]() |
cd44b33201 | ||
![]() |
33df805168 | ||
![]() |
fad435ea10 | ||
![]() |
b35f9944ea | ||
![]() |
dc799bf691 | ||
![]() |
1f7929bb3d | ||
![]() |
fb228dc918 | ||
![]() |
c66f5e2d8a | ||
![]() |
d71b29d089 | ||
![]() |
6b230b6142 | ||
![]() |
c532a9023a | ||
![]() |
ecc704e6ac | ||
![]() |
5470c8f250 | ||
![]() |
d21f249aac | ||
![]() |
907299b139 | ||
![]() |
37aa2bd869 | ||
![]() |
f1f53b9f24 | ||
![]() |
49d9c7f392 | ||
![]() |
65860a3142 | ||
![]() |
3b52d3d302 | ||
![]() |
2fe6203eae | ||
![]() |
92b02e39c9 | ||
![]() |
b693fd1edc | ||
![]() |
b84e00b312 | ||
![]() |
973fd51639 | ||
![]() |
e0494ccb57 | ||
![]() |
95559cbc2a | ||
![]() |
3da13b823a | ||
![]() |
c022871ead | ||
![]() |
c4fcbf0613 | ||
![]() |
79921745a8 | ||
![]() |
40a4255045 | ||
![]() |
2d902a0688 | ||
![]() |
8a46ef6168 | ||
![]() |
ba3d37b550 | ||
![]() |
88d0247217 | ||
![]() |
1c076d22a6 | ||
![]() |
0ecdae2551 | ||
![]() |
6f8ba6afac | ||
![]() |
ad1c32a880 | ||
![]() |
48819a59e7 | ||
![]() |
2718801c69 | ||
![]() |
2b43f5f8c8 | ||
![]() |
0ef23cd712 | ||
![]() |
7370d1e0dd | ||
![]() |
da7d3e118c | ||
![]() |
d4188d9aee | ||
![]() |
8722157623 | ||
![]() |
6e2f0d8c9b | ||
![]() |
08459394a6 | ||
![]() |
ee292f900f | ||
![]() |
3aaf08ac03 | ||
![]() |
d31f4a5f1d | ||
![]() |
875ab0cb97 | ||
![]() |
678af025ac | ||
![]() |
1fd38d085f | ||
![]() |
ec324ab09f | ||
![]() |
efcd57934a | ||
![]() |
1efe61445f | ||
![]() |
6db9bf800a | ||
![]() |
65458538a7 | ||
![]() |
9ddeb3734f | ||
![]() |
c89fc188a5 | ||
![]() |
d366471058 | ||
![]() |
9951c162a1 | ||
![]() |
0c7d689b5a | ||
![]() |
655ce05efe | ||
![]() |
2a6e562d37 | ||
![]() |
98d1954812 | ||
![]() |
72a2f54598 | ||
![]() |
9364ea060a | ||
![]() |
f8dfdcb090 | ||
![]() |
3d78a7821a | ||
![]() |
e923d610ce | ||
![]() |
8b25fe88a4 | ||
![]() |
3768be55ff | ||
![]() |
47cf17ab50 | ||
![]() |
d2ec24f32a | ||
![]() |
69ed736080 | ||
![]() |
7d3c77008d | ||
![]() |
27dbabc6bf | ||
![]() |
27ce395d68 | ||
![]() |
145a536156 | ||
![]() |
e9b2a83411 | ||
![]() |
784b7e4d04 | ||
![]() |
f4bf999ae2 | ||
![]() |
9c04f57e35 | ||
![]() |
f0ddc408e8 | ||
![]() |
df4d5a4567 | ||
![]() |
0a413cba03 | ||
![]() |
7e2217b542 | ||
![]() |
93947d76a2 | ||
![]() |
18cce45b88 | ||
![]() |
86f1af6682 | ||
![]() |
c8f58c7bc9 | ||
![]() |
e5e168803a | ||
![]() |
3436a023f6 | ||
![]() |
84322a21fe | ||
![]() |
ec20f7e2c4 | ||
![]() |
3579d82e8e | ||
![]() |
70532ac3bf | ||
![]() |
96b9d25bc5 | ||
![]() |
91777d45b0 | ||
![]() |
0582b8430d | ||
![]() |
63d97398c1 | ||
![]() |
3552417b39 | ||
![]() |
a6cbbfe1a4 | ||
![]() |
48f5d17060 | ||
![]() |
c713106948 | ||
![]() |
142e674020 | ||
![]() |
e4fc21c991 | ||
![]() |
f688780677 | ||
![]() |
0ce98a86e6 | ||
![]() |
bf624f5ca7 | ||
![]() |
ce5ce37de7 | ||
![]() |
da727d3a3a | ||
![]() |
9d83cc6988 | ||
![]() |
ed625d4e0b | ||
![]() |
84157c8ea5 | ||
![]() |
8f19c0abb0 | ||
![]() |
008647aa7a | ||
![]() |
b86d6021da | ||
![]() |
98af479fd3 | ||
![]() |
d1c981bc19 | ||
![]() |
1b0e53d3d9 | ||
![]() |
0d49927541 | ||
![]() |
9e8d452438 | ||
![]() |
ddd646007e | ||
![]() |
f9844e8e58 | ||
![]() |
86f9909ac9 | ||
![]() |
629ae3fbf3 | ||
![]() |
ddd2c177b5 | ||
![]() |
829de4a073 | ||
![]() |
0df8b96133 | ||
![]() |
443921a97c | ||
![]() |
787fba82bd | ||
![]() |
1393a3ade8 | ||
![]() |
bf24d67066 | ||
![]() |
9774deef6d | ||
![]() |
8390c6e29b | ||
![]() |
c78d371a9c | ||
![]() |
7750299a66 | ||
![]() |
43f31dd455 | ||
![]() |
df21900341 | ||
![]() |
6934f0626c | ||
![]() |
54bc0525f7 | ||
![]() |
72f8f020fc | ||
![]() |
7f31acf764 | ||
![]() |
ea5bf17780 | ||
![]() |
0b7af715a8 | ||
![]() |
8579bee053 | ||
![]() |
400ddbf625 | ||
![]() |
5fdefc0c20 | ||
![]() |
c72c74828e | ||
![]() |
e0b157d280 | ||
![]() |
8c5862e4ce | ||
![]() |
f3e0df93b5 | ||
![]() |
c6c5ea34d3 | ||
![]() |
287a068ada | ||
![]() |
8ca52820b1 | ||
![]() |
cd8900dd26 | ||
![]() |
6d2e7f9fbd | ||
![]() |
e02736b4e2 | ||
![]() |
af049274d9 | ||
![]() |
7a12fd2853 | ||
![]() |
f724d8e7a9 | ||
![]() |
0d7e0df194 | ||
![]() |
7d567bc386 | ||
![]() |
ad52386ae0 | ||
![]() |
512fee47b6 | ||
![]() |
4092f56ea5 | ||
![]() |
926972cce6 | ||
![]() |
d51eea7bb6 | ||
![]() |
a3ca889ca3 | ||
![]() |
a7406b3201 | ||
![]() |
b54057cc4b | ||
![]() |
d77dd5300e | ||
![]() |
9396d5cf8c | ||
![]() |
a78ddb50fd | ||
![]() |
1016c87c60 | ||
![]() |
dbda1d75f9 | ||
![]() |
a9c25b49b9 | ||
![]() |
fbff95345c | ||
![]() |
8f4e65d392 | ||
![]() |
3a2cb51f8d | ||
![]() |
6c9cfed49f | ||
![]() |
257cab1061 | ||
![]() |
5f6577a24c | ||
![]() |
f8d6f0fae4 | ||
![]() |
5b7eeb6ac1 | ||
![]() |
64e8b636b9 | ||
![]() |
2c604ff946 | ||
![]() |
f8ce7c2ce1 | ||
![]() |
af1622e306 | ||
![]() |
3c03dfb322 | ||
![]() |
697a99f913 | ||
![]() |
06925f0716 | ||
![]() |
afcfdb5140 | ||
![]() |
6126280f2d | ||
![]() |
8e6f4886e8 | ||
![]() |
480de9ef03 | ||
![]() |
191feed920 | ||
![]() |
13c1763277 | ||
![]() |
ac9085c7a4 | ||
![]() |
8beb93b695 | ||
![]() |
4f76e66cc0 | ||
![]() |
614c4ec404 | ||
![]() |
d43291ae52 | ||
![]() |
7c486ec969 | ||
![]() |
19f54b6ba2 | ||
![]() |
97cc9f9ab9 | ||
![]() |
a104d38fc9 | ||
![]() |
2582023ab2 | ||
![]() |
e731f060f1 | ||
![]() |
1ebd13027c | ||
![]() |
04beef5e36 | ||
![]() |
0a578c5847 | ||
![]() |
41924d8ec6 | ||
![]() |
6ff1a6fecc | ||
![]() |
05eb6e15a5 | ||
![]() |
6d01728d54 | ||
![]() |
2550bff4e9 | ||
![]() |
c3942d244d | ||
![]() |
f4ef4c628a | ||
![]() |
a0f3e4f785 | ||
![]() |
2c13c5a18c | ||
![]() |
22cfd40ccc | ||
![]() |
5c7d9b3fa3 | ||
![]() |
55b6aa09d9 | ||
![]() |
96395dd5e1 | ||
![]() |
7191edd3c6 | ||
![]() |
6169379f4c | ||
![]() |
5500dd1332 | ||
![]() |
5c681896f3 | ||
![]() |
d826113319 | ||
![]() |
f72b298f97 | ||
![]() |
90b7cad7ac | ||
![]() |
e0239486bc | ||
![]() |
e10fb3c168 | ||
![]() |
5ee8bee6dc | ||
![]() |
4b678ffb41 | ||
![]() |
82c23026b3 | ||
![]() |
94b7b60fe0 | ||
![]() |
e1553a7ccf | ||
![]() |
fb0ca49742 | ||
![]() |
97015788a2 | ||
![]() |
0cf05ea2cc | ||
![]() |
acbe77c0d6 | ||
![]() |
6e003907fb | ||
![]() |
f6c15dc990 | ||
![]() |
1061769144 | ||
![]() |
1edfec08e1 | ||
![]() |
239cad9b47 | ||
![]() |
8d7c175d70 | ||
![]() |
795bbefba6 | ||
![]() |
e1b34eaa33 | ||
![]() |
bede8c66c5 | ||
![]() |
de87aee15b | ||
![]() |
36312cc273 | ||
![]() |
3120184d63 | ||
![]() |
a1be9d923e | ||
![]() |
7dee34ca75 | ||
![]() |
f7c8c6e3e8 | ||
![]() |
3411967fd9 | ||
![]() |
125805d6d1 | ||
![]() |
91d5d2f1eb | ||
![]() |
e0e158b64c | ||
![]() |
078095db3f | ||
![]() |
8c7fcc725c | ||
![]() |
988fa3e4e4 | ||
![]() |
f9118a4b87 | ||
![]() |
164944ceff | ||
![]() |
bc195c61cc | ||
![]() |
f54bb20fef | ||
![]() |
71214351ca | ||
![]() |
0a954cf1c7 | ||
![]() |
2782b2fb1b | ||
![]() |
a532b4461d | ||
![]() |
dd7987e199 | ||
![]() |
81cc73ece3 | ||
![]() |
f9701b2363 | ||
![]() |
adb22abd7d | ||
![]() |
4df90ebbc3 | ||
![]() |
4655929fed | ||
![]() |
39b00f1063 | ||
![]() |
bd0bfc1fbe | ||
![]() |
09c5dab69f | ||
![]() |
25a7f6ebf7 | ||
![]() |
a5e12cb558 | ||
![]() |
a2927f281d | ||
![]() |
3c23c18faf | ||
![]() |
616bd065e0 | ||
![]() |
a525c44794 | ||
![]() |
2d3579c08a | ||
![]() |
6ef36dce3e | ||
![]() |
74bf1d2a82 | ||
![]() |
8ea2e3f471 | ||
![]() |
1b74e94f14 | ||
![]() |
536d2e0ab0 | ||
![]() |
c610778b0f | ||
![]() |
0791b1bc71 | ||
![]() |
c93f6f683a | ||
![]() |
999969b78d | ||
![]() |
10b8627f51 | ||
![]() |
528fcecd16 | ||
![]() |
f8fb5d7bf2 | ||
![]() |
3e02d95e01 | ||
![]() |
4ef6661532 | ||
![]() |
6cc6d9fb45 | ||
![]() |
43911ef3be | ||
![]() |
6b0afe6ebb | ||
![]() |
811977b366 | ||
![]() |
fc2e3b7bcf | ||
![]() |
6b8068a22a | ||
![]() |
2899388395 | ||
![]() |
4e63eacb79 | ||
![]() |
881ff13832 | ||
![]() |
79c7cf59ee | ||
![]() |
b82d880bfd | ||
![]() |
64374a4fcb | ||
![]() |
0e0be279ea | ||
![]() |
08a8e053d3 | ||
![]() |
7d9752abdf | ||
![]() |
0c382f1967 | ||
![]() |
7833a31eea | ||
![]() |
8e796e013a | ||
![]() |
757ed2e80c | ||
![]() |
d2665f1349 | ||
![]() |
84f7c62ee2 | ||
![]() |
a9d7082218 | ||
![]() |
766de17ea3 | ||
![]() |
8988bd519f | ||
![]() |
6ccd4fa431 | ||
![]() |
5b8e63a213 | ||
![]() |
6a337cc486 | ||
![]() |
f7f936cb54 | ||
![]() |
7252169325 | ||
![]() |
b7ef633a3e | ||
![]() |
995155696f | ||
![]() |
7996f4e0b2 | ||
![]() |
ac6e61b9b8 | ||
![]() |
b7f3e40340 | ||
![]() |
39b4e85dcd | ||
![]() |
37d2c6844a | ||
![]() |
b8e2298cdd | ||
![]() |
a3ff065c7a | ||
![]() |
a224d6c61b | ||
![]() |
cd0980d13e | ||
![]() |
13cb32a83f | ||
![]() |
12a9cf4b32 | ||
![]() |
8cce13163f | ||
![]() |
46a55630fa | ||
![]() |
c92bee4f1d | ||
![]() |
940cbd42c3 | ||
![]() |
39bf7c9ad4 | ||
![]() |
64c260c1c4 | ||
![]() |
36f3ef9e86 | ||
![]() |
42622fe21e | ||
![]() |
64f7afd60f | ||
![]() |
3282785cf2 | ||
![]() |
2c1931adb1 | ||
![]() |
c9cad254d2 | ||
![]() |
f4f2cce57e | ||
![]() |
556315b360 | ||
![]() |
bed470f79d | ||
![]() |
9acf946097 | ||
![]() |
231ef4b5b4 | ||
![]() |
f8bcc6dde4 | ||
![]() |
11ed4600fd | ||
![]() |
c0e2d6fa23 | ||
![]() |
942562161a | ||
![]() |
d35c40b585 | ||
![]() |
8cd0ddceb8 | ||
![]() |
c3ee49298a | ||
![]() |
89dc1a7ebc | ||
![]() |
ced70fd9a1 | ||
![]() |
253c8f358b | ||
![]() |
23b55484c3 | ||
![]() |
1990b8fa84 | ||
![]() |
03ea08f98c | ||
![]() |
1f5f6c5f8a | ||
![]() |
fa821b1c4f | ||
![]() |
f51bc40203 | ||
![]() |
c7dae49c42 | ||
![]() |
b056b71557 | ||
![]() |
0db2b45cc3 | ||
![]() |
1be1003549 | ||
![]() |
b8a13dd6eb | ||
![]() |
cae5540c44 | ||
![]() |
d47966cdf7 | ||
![]() |
991cf83ff3 | ||
![]() |
b83be38514 | ||
![]() |
17982e0bdc | ||
![]() |
b918862bb1 | ||
![]() |
6bdc7af09f | ||
![]() |
7cbebfd603 | ||
![]() |
42b1f938d6 | ||
![]() |
311f221387 | ||
![]() |
3c6be8cf99 | ||
![]() |
28703b39da | ||
![]() |
db03e271f5 | ||
![]() |
7c851d4542 | ||
![]() |
4d107f978c | ||
![]() |
de57b025e6 | ||
![]() |
3f4351476f | ||
![]() |
d763a014ad | ||
![]() |
52a91d8403 | ||
![]() |
f6cc435f86 | ||
![]() |
349b1ccaad | ||
![]() |
ca921be9d2 | ||
![]() |
919932e414 | ||
![]() |
97a8b6da34 | ||
![]() |
1eceaa0d1b | ||
![]() |
ba3fae2577 | ||
![]() |
93ed1cae5e | ||
![]() |
d8618b4a25 | ||
![]() |
1f6b0360de | ||
![]() |
e1830470b6 | ||
![]() |
9e002f7940 | ||
![]() |
a1380e93ea | ||
![]() |
c511672b0d | ||
![]() |
d6d6d1d0b5 | ||
![]() |
bee629f7ed | ||
![]() |
188fe44c2e | ||
![]() |
25c02b1219 | ||
![]() |
e5e84acd07 | ||
![]() |
722ccc017f | ||
![]() |
d8df380edc | ||
![]() |
cbfcad71d5 | ||
![]() |
327a9ff836 | ||
![]() |
ae2c389273 | ||
![]() |
5ce75cea0d | ||
![]() |
ee79c3a983 | ||
![]() |
f396be2ed7 | ||
![]() |
8a4b96f1ff | ||
![]() |
17b6bf0673 | ||
![]() |
387392713c | ||
![]() |
125ad9c794 | ||
![]() |
ae33b10cb2 | ||
![]() |
1181ddcbbf | ||
![]() |
f7103febdf | ||
![]() |
6e8c1f1a63 | ||
![]() |
9f55ef811d | ||
![]() |
4c898a2a5a | ||
![]() |
a56e22790d | ||
![]() |
2d8fbc652f | ||
![]() |
46f0e0212d | ||
![]() |
786b9ee8d6 | ||
![]() |
1e73cebda6 | ||
![]() |
9b9adf3c7a | ||
![]() |
a08c7a319f | ||
![]() |
5e8868e4b1 | ||
![]() |
64285d5155 | ||
![]() |
ce39b1a2c8 | ||
![]() |
5247b74fd4 | ||
![]() |
26e914290d | ||
![]() |
ed3096157c | ||
![]() |
04a45a4361 | ||
![]() |
5430040b96 | ||
![]() |
4bd70167ad | ||
![]() |
e908fbb48e | ||
![]() |
38da01abfa | ||
![]() |
c3b7ce8dc4 | ||
![]() |
0488d199ac | ||
![]() |
df3e4576db | ||
![]() |
6bd7788815 | ||
![]() |
a6971d61d1 | ||
![]() |
9cdae4fea7 | ||
![]() |
7adf9f8526 | ||
![]() |
35dcb46703 | ||
![]() |
17db85ebad | ||
![]() |
fa39595c37 | ||
![]() |
4db908171f | ||
![]() |
7306b8c102 | ||
![]() |
452cfee2cd | ||
![]() |
928bf3465e | ||
![]() |
0b38143765 | ||
![]() |
2f974078e0 | ||
![]() |
efe90fcc55 | ||
![]() |
01e33f5412 | ||
![]() |
51fdc484c3 | ||
![]() |
3d9fa462a6 | ||
![]() |
32b5d67806 | ||
![]() |
20d3681da3 | ||
![]() |
9b97274bf6 | ||
![]() |
ede0dff030 | ||
![]() |
4cd4635fa5 | ||
![]() |
7832219749 | ||
![]() |
a8d4726caf | ||
![]() |
4b3e20c6ca | ||
![]() |
f9a53743ce | ||
![]() |
89250c0c01 | ||
![]() |
4ef944ea08 | ||
![]() |
5f58c183f4 | ||
![]() |
f71feff916 | ||
![]() |
50fb3b314b | ||
![]() |
06298562cd | ||
![]() |
89e74f3f07 | ||
![]() |
da96c27893 | ||
![]() |
3321dd4ca7 | ||
![]() |
7106d56b33 | ||
![]() |
25cd8a9d9f | ||
![]() |
deb077b5e9 | ||
![]() |
a4bb0e04ab | ||
![]() |
1df60056b2 | ||
![]() |
c4bc1f627f | ||
![]() |
f4df5852fb | ||
![]() |
152b665f2e | ||
![]() |
f1d49aaeb1 | ||
![]() |
5db293ce01 | ||
![]() |
744cda3974 | ||
![]() |
79e223cf8e | ||
![]() |
eb8d23320a | ||
![]() |
7bfa72e7ac | ||
![]() |
031548c155 | ||
![]() |
a7d3ab9d17 | ||
![]() |
d2e00a0f0a | ||
![]() |
eea9e660ac | ||
![]() |
5644c78664 | ||
![]() |
7677471dcc | ||
![]() |
c0ca7e425e | ||
![]() |
29d9b61319 | ||
![]() |
3c8da03d66 | ||
![]() |
9a9b2e3900 | ||
![]() |
830d8d2410 | ||
![]() |
cda34a6ffd | ||
![]() |
76ee9ce202 | ||
![]() |
00bd32acba | ||
![]() |
bc11c0b3ac | ||
![]() |
51f89b00c1 | ||
![]() |
67852125e5 | ||
![]() |
7a36cf67e3 | ||
![]() |
d175e84623 | ||
![]() |
9fff3adbfb | ||
![]() |
5f6396b187 | ||
![]() |
42f2341e06 | ||
![]() |
48dfa1163b | ||
![]() |
28e12f7fd1 | ||
![]() |
5f58ac4fb6 | ||
![]() |
25e7c4f1b2 | ||
![]() |
00934f2183 | ||
![]() |
d302eaffe6 | ||
![]() |
901f736d5f | ||
![]() |
e55f32ae91 | ||
![]() |
3e0c998e74 | ||
![]() |
597866ff4e | ||
![]() |
64e21e185c | ||
![]() |
7a1838ee1a | ||
![]() |
4debac60ae | ||
![]() |
4af231e62b | ||
![]() |
432cf4a7ed | ||
![]() |
df064967ca | ||
![]() |
dc0cab9307 | ||
![]() |
3180747a0a | ||
![]() |
1542095138 | ||
![]() |
6c1937f247 | ||
![]() |
9db1e52a55 | ||
![]() |
f92c63135c | ||
![]() |
a3bf1a014b | ||
![]() |
31fba48ad5 | ||
![]() |
05dfa1bb1a | ||
![]() |
f0f47aac3b | ||
![]() |
9b42494667 | ||
![]() |
42df951f89 | ||
![]() |
f4996424a2 | ||
![]() |
fd01302d9a | ||
![]() |
2daaa1cb9c | ||
![]() |
9fde175c6b | ||
![]() |
f1b24e847e | ||
![]() |
7a587de54e | ||
![]() |
eb69f95f83 | ||
![]() |
359a3a4af9 | ||
![]() |
a8b75e7814 | ||
![]() |
2b898822d1 | ||
![]() |
fc9a0958d4 | ||
![]() |
5843877cc8 | ||
![]() |
913837f064 | ||
![]() |
386ac5d779 | ||
![]() |
3a1a4ade68 | ||
![]() |
dd35112a04 | ||
![]() |
afcb4c56fa | ||
![]() |
58f210f45b | ||
![]() |
f4d9d55ecd | ||
![]() |
995955491f | ||
![]() |
2ab9aed5b4 | ||
![]() |
1693f5b5c9 | ||
![]() |
f096e1698c | ||
![]() |
2f46caa806 | ||
![]() |
5c9b53ffb7 | ||
![]() |
f6e00e7262 | ||
![]() |
5d49f4007e | ||
![]() |
ca20c2d292 | ||
![]() |
f1ab24da99 | ||
![]() |
e16e851952 | ||
![]() |
0b562a4b16 | ||
![]() |
7734922059 | ||
![]() |
54320c3dbf | ||
![]() |
849cfed669 | ||
![]() |
8932dfd504 | ||
![]() |
b9922b2f8e | ||
![]() |
11fc5bc755 | ||
![]() |
67ac4882f2 | ||
![]() |
413171bb3c | ||
![]() |
b111eb2316 | ||
![]() |
9bafabe3e9 | ||
![]() |
202bc6440b | ||
![]() |
e2a89a55b7 | ||
![]() |
1e05730ec7 | ||
![]() |
885a63d3f6 | ||
![]() |
206fbac618 | ||
![]() |
4509661652 | ||
![]() |
4669decfd0 | ||
![]() |
f05c204da3 | ||
![]() |
338692d2c3 | ||
![]() |
5415690585 | ||
![]() |
418315d20b | ||
![]() |
9bbffb6919 | ||
![]() |
e338d63ec5 | ||
![]() |
264aedbff3 | ||
![]() |
4103ef362c | ||
![]() |
a04a449eb9 | ||
![]() |
08633c197b | ||
![]() |
f8b3a429c6 | ||
![]() |
946c8a59b4 | ||
![]() |
f93c7e1b6e | ||
![]() |
6298534b9c | ||
![]() |
5175b42069 | ||
![]() |
e01e31341b | ||
![]() |
203d900d16 | ||
![]() |
4d9e9aaead | ||
![]() |
82ec308be0 | ||
![]() |
dcafbcb06c | ||
![]() |
aa5f8dc082 | ||
![]() |
4dcae9c69c | ||
![]() |
13a1af97da | ||
![]() |
e3c435fd78 | ||
![]() |
a32dee7071 | ||
![]() |
c098858b73 | ||
![]() |
9e509e3bc9 | ||
![]() |
79ac2a72fa | ||
![]() |
b063840f46 | ||
![]() |
4366308b2b | ||
![]() |
126826e52c | ||
![]() |
e31af5d31b | ||
![]() |
fca97cd734 | ||
![]() |
ca94267c44 | ||
![]() |
df1f26cee7 | ||
![]() |
24a4e075e6 | ||
![]() |
43fcc6238e | ||
![]() |
b40b96248b | ||
![]() |
c7ac4c7490 | ||
![]() |
6cd8471b91 | ||
![]() |
940eaa26e0 | ||
![]() |
79e68ce125 | ||
![]() |
e581d35432 | ||
![]() |
d3d578e0f4 | ||
![]() |
79c71cbe48 | ||
![]() |
82b50a1c5d | ||
![]() |
6cfda78aa1 | ||
![]() |
f9ff938775 | ||
![]() |
778fcab90d | ||
![]() |
07e5aa30c6 | ||
![]() |
3f0ec03a14 | ||
![]() |
1bb871b9ac | ||
![]() |
0e8783fb01 | ||
![]() |
1d88c4465b | ||
![]() |
1f0cfb5fd6 | ||
![]() |
a21e17fb23 | ||
![]() |
5de888c91a | ||
![]() |
2dd4090db3 | ||
![]() |
35aafd45dc | ||
![]() |
c778b881ab | ||
![]() |
04acecc832 | ||
![]() |
a10a9916be | ||
![]() |
3604ffa64a | ||
![]() |
a0724749d3 | ||
![]() |
45a75c3a7c | ||
![]() |
f0dcfa4aa3 | ||
![]() |
1c4b66cb1e | ||
![]() |
af2d575bf0 | ||
![]() |
92165d776a | ||
![]() |
a8bbd8ab90 | ||
![]() |
43ac9dbea7 | ||
![]() |
bba9eca4e9 | ||
![]() |
40f65b1980 | ||
![]() |
23a33b10a1 | ||
![]() |
67a93013c7 | ||
![]() |
1f838d7529 | ||
![]() |
ffc0435144 | ||
![]() |
5877d69c87 | ||
![]() |
99035cea8f | ||
![]() |
1b441a7eec | ||
![]() |
ad49e9f7b0 | ||
![]() |
e32b15ede2 | ||
![]() |
a35b4376ea | ||
![]() |
619f9f76ee | ||
![]() |
f771bc10db | ||
![]() |
b8889a1183 | ||
![]() |
eb6b45eaed | ||
![]() |
31a748ed93 | ||
![]() |
0110bdd24a | ||
![]() |
365b712976 | ||
![]() |
7d97dbe15b | ||
![]() |
8bc0ea5a0b | ||
![]() |
44948a3474 | ||
![]() |
bc51b53b4a | ||
![]() |
693dbfd050 | ||
![]() |
67217b9dd0 | ||
![]() |
487795b7c4 | ||
![]() |
a30e0d33f9 | ||
![]() |
0c1b8abe03 | ||
![]() |
ce9c5149d5 | ||
![]() |
adbcdc62eb | ||
![]() |
faf872bfb8 | ||
![]() |
fe0fb2382a | ||
![]() |
e84c3a85db | ||
![]() |
cdd29295e5 | ||
![]() |
f7532f3476 | ||
![]() |
fdf9fab709 | ||
![]() |
c8930cec87 | ||
![]() |
f9c336890d | ||
![]() |
c721de109f | ||
![]() |
1c95e8d6ec | ||
![]() |
57cf2c1341 | ||
![]() |
f7d5c5f850 | ||
![]() |
470f5127f4 | ||
![]() |
34e361601a | ||
![]() |
70d6cce8f8 | ||
![]() |
f9814f35d1 | ||
![]() |
f30603753e | ||
![]() |
ce9993fd36 | ||
![]() |
268eb4317c | ||
![]() |
4c2044e70a | ||
![]() |
7f96c1fbe1 | ||
![]() |
75e24780c1 | ||
![]() |
95580bc4c0 | ||
![]() |
175f68e0cf | ||
![]() |
b6efedfc8d | ||
![]() |
23c21a35d8 | ||
![]() |
9c7324298b | ||
![]() |
e92be566a0 | ||
![]() |
4e96ad5f28 | ||
![]() |
f64a1500af | ||
![]() |
c9e8619c04 | ||
![]() |
7ab1133b45 | ||
![]() |
77abfd3e61 | ||
![]() |
d7aaa41aa4 | ||
![]() |
8223f6b155 | ||
![]() |
435eae77fa | ||
![]() |
394d8ddd6c | ||
![]() |
ead54e445f | ||
![]() |
7ee5db2be5 | ||
![]() |
fef6f0ac94 | ||
![]() |
7a60763786 | ||
![]() |
94e321a364 | ||
![]() |
1c12c2b714 | ||
![]() |
442a8f11a7 | ||
![]() |
4e8b58cd6c | ||
![]() |
a92dab46c2 | ||
![]() |
468660d235 | ||
![]() |
c721afa137 | ||
![]() |
ac9654c1de | ||
![]() |
570ad38bac | ||
![]() |
e778a9aa1d | ||
![]() |
49576189af | ||
![]() |
d4a5115a65 | ||
![]() |
5d71d4c0a1 | ||
![]() |
d334b1ca7b | ||
![]() |
5551e98388 | ||
![]() |
59945cb2f8 | ||
![]() |
500bc959f0 | ||
![]() |
deece20206 | ||
![]() |
fc8945be60 | ||
![]() |
3fbd5f07a9 | ||
![]() |
ff9af2f980 | ||
![]() |
62cba99491 | ||
![]() |
5a5005c09c | ||
![]() |
dd179e1f4e | ||
![]() |
27bdf80168 | ||
![]() |
f70ce7491a | ||
![]() |
9f17f6a8cf | ||
![]() |
8890c7da17 | ||
![]() |
4e51c7cf96 | ||
![]() |
291c026da0 | ||
![]() |
dd88d8633f | ||
![]() |
254ee8568b | ||
![]() |
cd631e8693 | ||
![]() |
765812331b | ||
![]() |
7462f8fbe3 | ||
![]() |
dc940f248c | ||
![]() |
2793ca65cd | ||
![]() |
e687ddab21 | ||
![]() |
4bd27e5055 | ||
![]() |
c6e2e07286 | ||
![]() |
e77508b8a8 | ||
![]() |
a5db44a167 | ||
![]() |
265bbfc95d | ||
![]() |
305cecb213 | ||
![]() |
813feff12e | ||
![]() |
cbce6f633f | ||
![]() |
1bbf45d35e | ||
![]() |
76e53e9738 | ||
![]() |
c30e4a6935 | ||
![]() |
c4a700a55c | ||
![]() |
a759767d79 | ||
![]() |
7f868c8140 | ||
![]() |
f7f37c24e2 | ||
![]() |
be02a8869f | ||
![]() |
3a9f09cb47 | ||
![]() |
0c2a9d85e0 | ||
![]() |
e72356033c | ||
![]() |
3c48559df6 | ||
![]() |
f36d68c677 | ||
![]() |
af46b8221e | ||
![]() |
d25f72524b | ||
![]() |
0840d8a10e | ||
![]() |
597bf5def0 | ||
![]() |
3478bd309b | ||
![]() |
64b8b7658d | ||
![]() |
a1af8718a0 | ||
![]() |
fd9e2b647d | ||
![]() |
caee4ba7bc | ||
![]() |
915036006d | ||
![]() |
48887f2066 | ||
![]() |
68d9ce7923 | ||
![]() |
a36f3c8fb1 | ||
![]() |
4dfadea9e9 | ||
![]() |
71dc26edab | ||
![]() |
f260c95add | ||
![]() |
dc6f1efffb | ||
![]() |
b7763882f4 | ||
![]() |
7de5c46f14 | ||
![]() |
5920efa2b2 | ||
![]() |
d2194d55f9 | ||
![]() |
c0043af4c9 | ||
![]() |
dcf763438b | ||
![]() |
858a00e28c | ||
![]() |
ab407e8274 | ||
![]() |
14f96a6262 | ||
![]() |
2b33c70e04 | ||
![]() |
717443e2d6 | ||
![]() |
2aba9099a0 | ||
![]() |
3079f126a8 | ||
![]() |
1cdfb746bf | ||
![]() |
39a1844991 | ||
![]() |
9e4dc0d39e | ||
![]() |
ab91a4b814 | ||
![]() |
ca66c02fb3 | ||
![]() |
97bb052d71 | ||
![]() |
137bb473c0 | ||
![]() |
326b57f91b | ||
![]() |
32feab6a70 | ||
![]() |
68a0d04f04 | ||
![]() |
9078ab4026 | ||
![]() |
8605684906 | ||
![]() |
9f17d17d6e | ||
![]() |
ba5f176d52 | ||
![]() |
7115d14699 | ||
![]() |
23e37daff3 | ||
![]() |
ed6c2dfe39 | ||
![]() |
b48a28f2a6 | ||
![]() |
3166fec7db | ||
![]() |
1a67bd0414 | ||
![]() |
d34c43e292 | ||
![]() |
c7cfbb5b6c | ||
![]() |
05ad3137f1 | ||
![]() |
bde2fd8202 | ||
![]() |
e5327c0903 | ||
![]() |
1a0ca1b78f | ||
![]() |
ed141b1d12 | ||
![]() |
5a7a71c551 | ||
![]() |
f09e0d187b | ||
![]() |
7f6325fa5e | ||
![]() |
de292a8143 | ||
![]() |
84b2005844 | ||
![]() |
0d93432a2c | ||
![]() |
8bc9927ee2 | ||
![]() |
484bed4dab | ||
![]() |
3d7e243707 | ||
![]() |
f8a432c89e | ||
![]() |
d484b2f63d | ||
![]() |
ba770f8e50 | ||
![]() |
30d9186031 | ||
![]() |
cd74367acc | ||
![]() |
618cd9d9e5 | ||
![]() |
0ff2f1bf75 | ||
![]() |
d28f1f07e7 | ||
![]() |
b457d27c4c | ||
![]() |
6aa5bc2d8b | ||
![]() |
76fc0c7ab1 | ||
![]() |
7aa7019386 | ||
![]() |
b69f0964c9 | ||
![]() |
2f9b6d000b | ||
![]() |
9c12ab9c6d | ||
![]() |
94f186c436 | ||
![]() |
449f858ac8 | ||
![]() |
91a2f2cf24 | ||
![]() |
2c975d4f41 | ||
![]() |
ab534933fc | ||
![]() |
e353aaa339 | ||
![]() |
020904f8f6 | ||
![]() |
fa8b3f006d | ||
![]() |
d9ce20992c | ||
![]() |
a09f44dcd2 | ||
![]() |
c709059c00 | ||
![]() |
5613df1d01 | ||
![]() |
d8013a4db9 | ||
![]() |
216dbc4d41 | ||
![]() |
c40751dadd | ||
![]() |
f58d3ad670 | ||
![]() |
682f5345cc | ||
![]() |
a69771c1f8 | ||
![]() |
22de449dda | ||
![]() |
05a27b9399 | ||
![]() |
32083ea13d | ||
![]() |
18210f35b5 | ||
![]() |
362a6f46fe | ||
![]() |
1c9d411d3a | ||
![]() |
6d84523456 | ||
![]() |
2a18706a13 | ||
![]() |
87b58b0bbd | ||
![]() |
3ebb268b57 | ||
![]() |
2df097cd1b | ||
![]() |
8349e47c17 | ||
![]() |
4913932c97 | ||
![]() |
19f057a51b | ||
![]() |
c556742ff4 | ||
![]() |
8b5f731d0c | ||
![]() |
9568677926 | ||
![]() |
93ee5de1b4 | ||
![]() |
2f68ee0efc | ||
![]() |
5a229e3c88 | ||
![]() |
7c5f947865 | ||
![]() |
e9cbd54979 | ||
![]() |
cf55824899 | ||
![]() |
395586ddeb | ||
![]() |
9c48dbf232 | ||
![]() |
00eb820e36 | ||
![]() |
6b99cda982 | ||
![]() |
9bde0e876d | ||
![]() |
9482fcb04b | ||
![]() |
883ad58f52 | ||
![]() |
11ace6002a | ||
![]() |
c416daeb92 | ||
![]() |
061521a979 | ||
![]() |
d3f73baa36 | ||
![]() |
3037bf494c | ||
![]() |
b4dd953128 | ||
![]() |
430a28f350 | ||
![]() |
0eacf3fdac | ||
![]() |
7f9bf69a08 | ||
![]() |
32cca9e30c | ||
![]() |
d7d62307b8 | ||
![]() |
12bfa5dab2 | ||
![]() |
c0a728bc66 | ||
![]() |
19e8667349 | ||
![]() |
f3688b95d4 | ||
![]() |
01f692f05c | ||
![]() |
d652f6382d | ||
![]() |
c0f96d9473 | ||
![]() |
f1a2af24b3 | ||
![]() |
8501098bd1 | ||
![]() |
a235f76985 | ||
![]() |
968c0de141 | ||
![]() |
77d8aff1f4 | ||
![]() |
5e486d9cf0 | ||
![]() |
f730761b3f | ||
![]() |
46fc9c1a33 | ||
![]() |
8ed68bf295 | ||
![]() |
5622180d42 | ||
![]() |
ef1f9b371d | ||
![]() |
0b79684cf1 | ||
![]() |
bc68d8df11 | ||
![]() |
ebbade2fb7 | ||
![]() |
2b5f778f2e | ||
![]() |
91fc2383cb | ||
![]() |
1080a8c961 | ||
![]() |
6144049f8c | ||
![]() |
4ad3ad6e93 | ||
![]() |
16e84296da | ||
![]() |
3e1ea8d236 | ||
![]() |
8c9996fc81 | ||
![]() |
336b5fb547 | ||
![]() |
3f0f3affb6 | ||
![]() |
6754b8893b | ||
![]() |
6ec4323c76 | ||
![]() |
20408392d2 | ||
![]() |
b030a5d1f0 | ||
![]() |
a9f8eb5ab1 | ||
![]() |
e26e6d7c2d | ||
![]() |
e0c98e4524 | ||
![]() |
2832f501d1 | ||
![]() |
d2f2d682a9 | ||
![]() |
54b2121273 | ||
![]() |
c5ca731e05 | ||
![]() |
fd9c6c5449 | ||
![]() |
39f4355c1a | ||
![]() |
35fed0b0e2 | ||
![]() |
f0f0aefca1 | ||
![]() |
b60864086f | ||
![]() |
6629f372fc | ||
![]() |
ec9a95dde0 | ||
![]() |
3cd0c49c78 | ||
![]() |
e1ae95dd9f | ||
![]() |
ab38dad156 | ||
![]() |
1ddeca3eeb | ||
![]() |
9c6aef033d | ||
![]() |
b23aacef84 | ||
![]() |
7d218c89ae | ||
![]() |
ffa96d789f | ||
![]() |
f08f455698 | ||
![]() |
5eae163796 | ||
![]() |
9e7f01a009 | ||
![]() |
eeffa3561c | ||
![]() |
f096eb2031 | ||
![]() |
3aad7431da | ||
![]() |
a4f167559c | ||
![]() |
44a0582e83 | ||
![]() |
735560c552 | ||
![]() |
94c28ea534 | ||
![]() |
5b7c20af33 | ||
![]() |
4719775926 | ||
![]() |
5c30c1647c | ||
![]() |
3ba572ee37 | ||
![]() |
0adee7d189 | ||
![]() |
b5c2b555bc | ||
![]() |
51b6d7758d | ||
![]() |
0f21dfadf1 | ||
![]() |
54e8a34f21 | ||
![]() |
dfbf4abd5d | ||
![]() |
62d8434596 | ||
![]() |
d6df228e17 | ||
![]() |
00faa16349 | ||
![]() |
3c92fe4170 | ||
![]() |
02a9d67c7d | ||
![]() |
b368f886f9 | ||
![]() |
88718bca23 | ||
![]() |
33931b29a1 | ||
![]() |
a9310fdde0 | ||
![]() |
d634317438 | ||
![]() |
a41978f647 | ||
![]() |
7e799bf639 | ||
![]() |
73617711ff | ||
![]() |
edbfc22bf8 | ||
![]() |
5e75f6a6c2 | ||
![]() |
6dc80306e8 | ||
![]() |
acd1b04b0a | ||
![]() |
7e9d09e11c | ||
![]() |
038f7ec000 | ||
![]() |
08959cbabf | ||
![]() |
b611674ebd | ||
![]() |
da75eecfa5 | ||
![]() |
2f696bd511 | ||
![]() |
9e3284a7db | ||
![]() |
0c3471e0b7 | ||
![]() |
1ca0b58aca | ||
![]() |
adceed689b | ||
![]() |
fdf829bc81 | ||
![]() |
574fc99889 | ||
![]() |
3a83cb36a1 | ||
![]() |
a458ccf995 | ||
![]() |
560e2c9438 | ||
![]() |
78becb5440 | ||
![]() |
da2e530601 | ||
![]() |
a88a7c5236 | ||
![]() |
0a095c6f21 | ||
![]() |
e8dd835eeb | ||
![]() |
e05c66444a | ||
![]() |
d0e61ca31a | ||
![]() |
1f90a0c2e5 | ||
![]() |
dbd84901f8 | ||
![]() |
0aa25dbed9 | ||
![]() |
dd74a35d3f | ||
![]() |
b1d8ec0fe4 | ||
![]() |
cd4af674a3 | ||
![]() |
7a6491a901 | ||
![]() |
8d20303d54 | ||
![]() |
a5786b4761 | ||
![]() |
4ade39543d | ||
![]() |
a85dda3365 | ||
![]() |
e578904ff7 | ||
![]() |
09f0da1ead | ||
![]() |
2faa8fec17 | ||
![]() |
945c4a66b1 | ||
![]() |
5d794e7e88 | ||
![]() |
88a33bee14 | ||
![]() |
35ec9af23f | ||
![]() |
dd331173ad | ||
![]() |
885ccb84cb | ||
![]() |
0358fe5614 | ||
![]() |
89d842c2a8 | ||
![]() |
8911b55316 | ||
![]() |
6791e85625 | ||
![]() |
79618ce114 | ||
![]() |
87ba0e73dd | ||
![]() |
567a2ea019 | ||
![]() |
811c34b489 | ||
![]() |
dd22ae446a | ||
![]() |
d96ddf968c | ||
![]() |
bbb64870a1 | ||
![]() |
f05ddd3fcd | ||
![]() |
0612e25d9f | ||
![]() |
559ecf3eae | ||
![]() |
ddb31a8342 | ||
![]() |
1c978b7cce | ||
![]() |
9d9624c960 | ||
![]() |
179245e1aa | ||
![]() |
345000a0e9 | ||
![]() |
d94d5f96c3 | ||
![]() |
0fa3538db5 | ||
![]() |
1749725229 | ||
![]() |
83e94d32e3 | ||
![]() |
7fed4e6b37 | ||
![]() |
677cffd650 | ||
![]() |
1faa1480e4 | ||
![]() |
8cb63ac36d | ||
![]() |
6e29b77e94 | ||
![]() |
38e7b8c467 | ||
![]() |
d078807255 | ||
![]() |
82d84de426 | ||
![]() |
729a12af0c | ||
![]() |
ce43774b5f | ||
![]() |
e63d82d291 | ||
![]() |
d997cfcef0 | ||
![]() |
219f548261 | ||
![]() |
ee2b10912c | ||
![]() |
e3b0630797 | ||
![]() |
30d0293a4b | ||
![]() |
7468ab985a | ||
![]() |
ef3758da55 | ||
![]() |
2a970b8416 | ||
![]() |
f70126eb62 | ||
![]() |
f87296d978 | ||
![]() |
2890d5c8cf | ||
![]() |
15a7ace278 | ||
![]() |
71a2c40dd7 | ||
![]() |
a08bbcd1b4 | ||
![]() |
5ec257fa18 | ||
![]() |
9b01c0b2f0 | ||
![]() |
7dd860c539 | ||
![]() |
dbc2db2591 | ||
![]() |
29aa57229c | ||
![]() |
8d74174be1 | ||
![]() |
a60242f042 | ||
![]() |
db314522d7 | ||
![]() |
7b66ee06eb | ||
![]() |
3f34dacec9 | ||
![]() |
277650e1c1 | ||
![]() |
e59c04c685 | ||
![]() |
d9583582e6 | ||
![]() |
5ead5ed058 | ||
![]() |
f2993602f9 | ||
![]() |
11b490d145 | ||
![]() |
cd4937b539 | ||
![]() |
daa36788e0 | ||
![]() |
0447247add | ||
![]() |
7edc4efc95 | ||
![]() |
144d278e4a | ||
![]() |
541453c245 | ||
![]() |
ca53af5c41 | ||
![]() |
bd54eb40a7 | ||
![]() |
8ff2396a53 | ||
![]() |
c85e29f2bb | ||
![]() |
e7a749ef7d | ||
![]() |
bef53aef57 | ||
![]() |
877d0db1bb | ||
![]() |
aa49d6ef6b | ||
![]() |
d646ce4995 | ||
![]() |
d6e6844f23 | ||
![]() |
66e26e1a27 | ||
![]() |
b7473b58fb | ||
![]() |
895333aa05 | ||
![]() |
42b5fbec9b | ||
![]() |
f7072c247e | ||
![]() |
f995f19f06 | ||
![]() |
7f50504908 | ||
![]() |
dc93a0ce54 | ||
![]() |
3e4d06fca3 | ||
![]() |
050bef0564 | ||
![]() |
1abebdae21 | ||
![]() |
b411ae0286 | ||
![]() |
202bd148ef | ||
![]() |
15589927c8 | ||
![]() |
df7b5b08cf | ||
![]() |
8b9fa9bc39 | ||
![]() |
c07e1122e1 | ||
![]() |
1ceef7c3d3 | ||
![]() |
e332364ec0 | ||
![]() |
97c4cf9391 | ||
![]() |
522f66423b | ||
![]() |
58ba9f628a | ||
![]() |
57e48e2561 | ||
![]() |
37af77dabe | ||
![]() |
2b5fba4a30 | ||
![]() |
d833910796 | ||
![]() |
81c796beb4 | ||
![]() |
19ee150395 | ||
![]() |
82329833f5 | ||
![]() |
28ced4bfd3 | ||
![]() |
ab3b8593f4 | ||
![]() |
094203f0b4 | ||
![]() |
9a2051a679 | ||
![]() |
09accb3071 | ||
![]() |
7d432cd11a | ||
![]() |
7258e31348 | ||
![]() |
5707ca0016 | ||
![]() |
76abfea6ed | ||
![]() |
d01377da3c | ||
![]() |
e97be57e3b | ||
![]() |
c71a051b6d | ||
![]() |
f41fab6968 | ||
![]() |
bda61da666 | ||
![]() |
93445ced74 | ||
![]() |
fd6a192db1 | ||
![]() |
b81314fc1f | ||
![]() |
9beb4c39ff | ||
![]() |
18a6f8d64d | ||
![]() |
beec720b9b | ||
![]() |
85865af0c3 | ||
![]() |
d33cf4f199 | ||
![]() |
4a1087c969 | ||
![]() |
cbc95a5e2d | ||
![]() |
dcd4c39978 | ||
![]() |
11d832c2ea | ||
![]() |
3b15d26500 | ||
![]() |
df65038341 | ||
![]() |
d72e8c35d8 | ||
![]() |
da2865d8bf | ||
![]() |
fd64d17d88 | ||
![]() |
5273293cd6 | ||
![]() |
49c42fc757 | ||
![]() |
7603fa3aa8 | ||
![]() |
7aa005e0ce | ||
![]() |
b2a55dd737 | ||
![]() |
5bc3ad4c63 | ||
![]() |
ccad1afcf0 | ||
![]() |
530745d20d | ||
![]() |
a16cae0671 | ||
![]() |
231c923776 | ||
![]() |
b08b67179e | ||
![]() |
d9f1b06199 | ||
![]() |
8d0c4e4a52 | ||
![]() |
4b7526c8a3 | ||
![]() |
6267ab5ed3 | ||
![]() |
ae94231800 | ||
![]() |
7d28f3f585 | ||
![]() |
adea384f40 | ||
![]() |
55b66250f4 | ||
![]() |
182111912c | ||
![]() |
8a0924bf1f | ||
![]() |
94dc9308ea | ||
![]() |
f42a9ac070 | ||
![]() |
1acada625f | ||
![]() |
128dbbcfef | ||
![]() |
57d8544dbf | ||
![]() |
76daa2bb7f | ||
![]() |
9cbb51549b | ||
![]() |
bd1ede4145 | ||
![]() |
321a085c0e | ||
![]() |
6a3041988a | ||
![]() |
23fcdf876c | ||
![]() |
00f325e961 | ||
![]() |
d00b3cfc61 | ||
![]() |
4cc9e74ea8 | ||
![]() |
a56b9a96ce | ||
![]() |
d4b5f4bc14 | ||
![]() |
cf1523ee73 | ||
![]() |
f5d571ca84 | ||
![]() |
362e92f313 | ||
![]() |
5ddf72b973 | ||
![]() |
6e78c28f51 | ||
![]() |
772f0bb669 | ||
![]() |
846c2a848f | ||
![]() |
8495757005 | ||
![]() |
9960d38b91 | ||
![]() |
d3222f8bb0 | ||
![]() |
2e5cce5409 | ||
![]() |
f78946447f | ||
![]() |
eb0579ddc5 | ||
![]() |
686424fc70 | ||
![]() |
039e9b40bd | ||
![]() |
8272bef890 | ||
![]() |
62528b2413 | ||
![]() |
fa24f529e0 | ||
![]() |
43a54f6cda | ||
![]() |
9c153bbd58 | ||
![]() |
27afe9ecb7 | ||
![]() |
72f989e2bd | ||
![]() |
a6ef46565f | ||
![]() |
a35ac09688 | ||
![]() |
27024135ea | ||
![]() |
8759ed740a | ||
![]() |
bb3e8ae33d | ||
![]() |
b5b60c9bf0 | ||
![]() |
3b6a2cf7d8 | ||
![]() |
7e10e14102 | ||
![]() |
a580abab4a | ||
![]() |
11523c08c4 | ||
![]() |
7a8988528b | ||
![]() |
2a6380f083 | ||
![]() |
f43319a3ae | ||
![]() |
e8eefaf1d3 | ||
![]() |
06d82a4925 | ||
![]() |
4991d52fcc | ||
![]() |
0b391eafcf | ||
![]() |
0bb34830f8 | ||
![]() |
29881c8bb4 | ||
![]() |
56254ddf03 | ||
![]() |
007ba70641 | ||
![]() |
3e1227b064 | ||
![]() |
067e179f26 | ||
![]() |
9a3f7df25e | ||
![]() |
c7b4e8f37c | ||
![]() |
bfa8b886ab | ||
![]() |
433c00b73a | ||
![]() |
a497f42f73 | ||
![]() |
165723cb5b | ||
![]() |
42b5fa696a | ||
![]() |
59062d96a8 | ||
![]() |
d36bbfe07d | ||
![]() |
4a8bb5034d | ||
![]() |
0d489213a4 | ||
![]() |
c54acc9369 | ||
![]() |
562bc084f0 | ||
![]() |
6fce2f35a5 | ||
![]() |
f4e24bed2e | ||
![]() |
09969c0e2d | ||
![]() |
4b0181774b | ||
![]() |
272db5e9e8 | ||
![]() |
9ae3a824d9 | ||
![]() |
9db55c9391 | ||
![]() |
59697127c0 | ||
![]() |
565600e945 | ||
![]() |
721eebf367 | ||
![]() |
f5ae842167 | ||
![]() |
3575734ed0 | ||
![]() |
4e8de1f64d | ||
![]() |
a8366c6416 | ||
![]() |
cd73b8ac29 | ||
![]() |
74eca6b1f5 | ||
![]() |
9ef0bd6e46 | ||
![]() |
53eb7f771f | ||
![]() |
8ff8c01bba | ||
![]() |
cd62f064cb | ||
![]() |
db82b856e0 | ||
![]() |
ab340e13e9 | ||
![]() |
22c54b3fea | ||
![]() |
2dd7e598d5 | ||
![]() |
d1ce06e368 | ||
![]() |
52f3ff3306 | ||
![]() |
9717304b68 | ||
![]() |
c646f3c39a | ||
![]() |
0297ec5a7b | ||
![]() |
e48286c2a0 | ||
![]() |
f2b2da9877 | ||
![]() |
250f87cfd8 | ||
![]() |
9f6afb162a | ||
![]() |
0add65feff | ||
![]() |
c08d9a9166 | ||
![]() |
d9a9038cec | ||
![]() |
6bee3ef45c | ||
![]() |
3a855f95ad | ||
![]() |
e7f3393ec6 | ||
![]() |
d7cb4cb537 | ||
![]() |
c55720c933 | ||
![]() |
f78e757485 | ||
![]() |
fa03c58a93 | ||
![]() |
49f1ad633f | ||
![]() |
d449e10120 | ||
![]() |
474c8c243e | ||
![]() |
e9e53e9451 | ||
![]() |
cfa84f30be | ||
![]() |
7416ae7dfd | ||
![]() |
10a5c4dfb4 | ||
![]() |
6f1fa139e7 | ||
![]() |
b38a348957 | ||
![]() |
f97971faf6 | ||
![]() |
c5ae9e8497 | ||
![]() |
c00287c401 | ||
![]() |
1a2daf8a7a | ||
![]() |
c0e048023d | ||
![]() |
431f4937c1 | ||
![]() |
0a55220837 | ||
![]() |
13f01492b4 | ||
![]() |
ce5bcf61f9 | ||
![]() |
d31a777135 | ||
![]() |
5cc08cfe0b | ||
![]() |
3eea7dc6cd | ||
![]() |
a629f01300 | ||
![]() |
f1345af526 | ||
![]() |
064c51f487 | ||
![]() |
d88670034a | ||
![]() |
5fab1969a8 | ||
![]() |
b3e14d449e | ||
![]() |
97206ee8fe | ||
![]() |
7748315fc3 | ||
![]() |
e059ca146b | ||
![]() |
56cabeb497 | ||
![]() |
7a7bd87f50 | ||
![]() |
ff9c794659 | ||
![]() |
2921161336 | ||
![]() |
91e5fcacd5 | ||
![]() |
febbf34de6 | ||
![]() |
5a2977f4d4 | ||
![]() |
7a7a355765 | ||
![]() |
ccebae84a7 | ||
![]() |
f96f38ee82 | ||
![]() |
d4056e6a32 | ||
![]() |
389a7a6ed9 | ||
![]() |
05aecaaaf1 | ||
![]() |
085131d546 | ||
![]() |
c2737d5cec | ||
![]() |
29ae46d775 | ||
![]() |
dfee3ba089 | ||
![]() |
1dbb70b964 | ||
![]() |
1eecc5c0e2 | ||
![]() |
81c0bcff0b | ||
![]() |
6ccbeb8a75 | ||
![]() |
f59ed0a72b | ||
![]() |
a9f00ded0f | ||
![]() |
74730ba201 | ||
![]() |
95b2f7d821 | ||
![]() |
661b14da54 | ||
![]() |
41e34c0d61 | ||
![]() |
5d044a06eb | ||
![]() |
f617426808 | ||
![]() |
3c3d54243c | ||
![]() |
afc624bf4b | ||
![]() |
0991628843 | ||
![]() |
34b9c7b9d1 | ||
![]() |
d52641b495 | ||
![]() |
80c7fd2bf2 | ||
![]() |
e0062cf190 | ||
![]() |
7d2cee650d | ||
![]() |
66560b1f1c | ||
![]() |
a500b582e3 | ||
![]() |
19f94ff8cc | ||
![]() |
0b6994d402 | ||
![]() |
9fe8f507ec | ||
![]() |
2113cf5280 | ||
![]() |
ae9e1b724f | ||
![]() |
9b28c7cf69 | ||
![]() |
d9bac06806 | ||
![]() |
b1e37cb1e1 | ||
![]() |
a2a89502d8 | ||
![]() |
4cc5d2d04b | ||
![]() |
79abcca3b3 | ||
![]() |
043f383a35 | ||
![]() |
d4dd767941 | ||
![]() |
174f1991b1 | ||
![]() |
e15495a626 | ||
![]() |
a8a9a797cb | ||
![]() |
914dbc1e28 | ||
![]() |
111816f08a | ||
![]() |
1b4534890c | ||
![]() |
ed6542469d | ||
![]() |
3774a3d6ba | ||
![]() |
bfa293ae3a | ||
![]() |
9264adb799 | ||
![]() |
829ea4a9e4 | ||
![]() |
be26f8bc24 | ||
![]() |
c864b34a9a | ||
![]() |
099ea61a94 | ||
![]() |
3ebe6027be | ||
![]() |
f5f2a5ad5b | ||
![]() |
d046700d06 | ||
![]() |
2ad84b2832 | ||
![]() |
f9ccb9fc72 | ||
![]() |
6d3940db1e | ||
![]() |
20d174431d | ||
![]() |
1900710e06 | ||
![]() |
ed86a48e1c | ||
![]() |
d2bdb52926 | ||
![]() |
9c57c9f151 | ||
![]() |
9e9cb15a42 | ||
![]() |
6421a9443d | ||
![]() |
f2b43ddad8 | ||
![]() |
e55b59d9b7 | ||
![]() |
4a77359a06 | ||
![]() |
505d7b6ddb | ||
![]() |
79cdc43699 | ||
![]() |
8ff9823cd7 | ||
![]() |
3488c60818 | ||
![]() |
b2af21ba5c | ||
![]() |
12a61a0021 | ||
![]() |
649917cdde | ||
![]() |
3ed27ee853 | ||
![]() |
c1d3a76917 | ||
![]() |
571ed6b9e9 | ||
![]() |
a347315fa7 | ||
![]() |
57d1405115 | ||
![]() |
e5ff6bd2f5 | ||
![]() |
43a422cdca | ||
![]() |
11f2bef05c | ||
![]() |
ff9f331287 | ||
![]() |
cdf64ccdaa | ||
![]() |
8b220acca2 | ||
![]() |
8fdb7fa1d5 | ||
![]() |
008c842431 | ||
![]() |
bc41de0d9c | ||
![]() |
7310c9cf6d | ||
![]() |
84b436c08e | ||
![]() |
1925a47bdc | ||
![]() |
438a426458 | ||
![]() |
f923deb71d | ||
![]() |
e79bc71ab7 | ||
![]() |
11b0990d2b | ||
![]() |
870cb0c65f | ||
![]() |
deda2009f8 | ||
![]() |
b2797ab8da | ||
![]() |
644dcb0381 | ||
![]() |
c65f4f7a6e | ||
![]() |
e2266aa671 | ||
![]() |
68a79490dc | ||
![]() |
6febe8552e | ||
![]() |
f611f23f6f | ||
![]() |
ef4f11fdf8 | ||
![]() |
627e06663b | ||
![]() |
ab01633069 | ||
![]() |
17dcc90638 | ||
![]() |
d0df029ff1 | ||
![]() |
86a7e69812 | ||
![]() |
af9417f2a6 | ||
![]() |
7120ad99b9 | ||
![]() |
334c245b65 | ||
![]() |
bcb72d83b8 | ||
![]() |
c99e0e846b | ||
![]() |
ec3f63e8a3 | ||
![]() |
1bc33a30ec | ||
![]() |
8cca233b7c | ||
![]() |
a78608bfb4 | ||
![]() |
e7c1ac94af | ||
![]() |
1a797b3415 | ||
![]() |
2b27a4da2b | ||
![]() |
1df92fa863 | ||
![]() |
cdde85315a | ||
![]() |
dc67f9faf4 | ||
![]() |
3ad1be50a2 | ||
![]() |
8aadfe7d28 | ||
![]() |
cff54b73a4 | ||
![]() |
b54cfeb0c0 | ||
![]() |
cefe612b11 | ||
![]() |
4bc874b497 | ||
![]() |
f3abaa8e02 | ||
![]() |
21a563fe98 | ||
![]() |
1acbcccd62 | ||
![]() |
35d6c638ab | ||
![]() |
68f8239708 | ||
![]() |
0db64cca0b | ||
![]() |
accfda5f4b | ||
![]() |
c97c20f57d | ||
![]() |
2725d0191d | ||
![]() |
852cc62398 | ||
![]() |
654e3ce437 | ||
![]() |
20a3a00aec | ||
![]() |
22b927d666 | ||
![]() |
709d6be2e3 | ||
![]() |
64f54d9aaa | ||
![]() |
fbda9ca418 | ||
![]() |
4e97e3763e | ||
![]() |
4c9c52d27d | ||
![]() |
87bcd3e471 | ||
![]() |
7e9b01b56d | ||
![]() |
713763fc21 | ||
![]() |
5b7ab1bfcb |
@@ -1,39 +1,36 @@
|
|||||||
[modern]
|
[modern]
|
||||||
# Support for dynamic import is the main litmus test for serving modern builds.
|
# Modern builds target recent browsers supporting the latest features to minimize transpilation, polyfills, etc.
|
||||||
# Although officially a ES2020 feature, browsers implemented it early, so this
|
# It is served to browsers meeting the following requirements:
|
||||||
# enables all of ES2017 and some features in ES2018.
|
# - released in the last year + current alpha/beta versions
|
||||||
supports es6-module-dynamic-import
|
# - Firefox extended support release (ESR)
|
||||||
|
# - with global utilization at or above 0.5%
|
||||||
# Exclude Safari 11-12 because of a bug in tagged template literals
|
# - exclude dead browsers (no security maintenance for 2+ years)
|
||||||
# https://bugs.webkit.org/show_bug.cgi?id=190756
|
# - exclude KaiOS, QQ, and UC browsers due to lack of sufficient feature support data
|
||||||
# Note: Dropping version 11 also enables several more ES2018 features
|
unreleased versions
|
||||||
not Safari < 13
|
last 1 year
|
||||||
not iOS < 13
|
Firefox ESR
|
||||||
|
>= 0.5%
|
||||||
# Exclude KaiOS, QQ, and UC browsers due to lack of sufficient feature support data
|
not dead
|
||||||
# Babel ignores these automatically, but we need here for Webpack to output ESM with dynamic imports
|
|
||||||
not KaiOS > 0
|
not KaiOS > 0
|
||||||
not QQAndroid > 0
|
not QQAndroid > 0
|
||||||
not UCAndroid > 0
|
not UCAndroid > 0
|
||||||
|
|
||||||
# Exclude unsupported browsers
|
|
||||||
not dead
|
|
||||||
|
|
||||||
[legacy]
|
[legacy]
|
||||||
# Legacy builds are served when modern requirements are not met and support browsers:
|
# Legacy builds are served when modern requirements are not met and support browsers:
|
||||||
# - released in the last 7 years + current alpha/beta versionss
|
# - released in the last 7 years + current alpha/beta versionss
|
||||||
# - with global utilization above 0.05%
|
# - with global utilization at or above 0.05%
|
||||||
# The lattermost query ensures that support for popular old browsers is not dropped too early
|
# - exclude dead browsers (no security maintenance for 2+ years)
|
||||||
# (e.g. IE 11, Android 4.4, or Samsung 4).
|
# - exclude Opera Mini which does not support web sockets
|
||||||
#
|
|
||||||
# In addition, legacy browsers must support some minimum features that cannot be polyfilled:
|
|
||||||
# - ES5 (strict mode)
|
|
||||||
# - web sockets to communicate with backend
|
|
||||||
# - inline SVG used widely in buttons, widgets, etc.
|
|
||||||
# - custom events used for most user interactions
|
|
||||||
# - CSS flexbox used in the majority of the layout
|
|
||||||
# Nearly all of these are redundant with the above rules.
|
|
||||||
# As of May 2023, only web sockets must be added to the query.
|
|
||||||
unreleased versions
|
unreleased versions
|
||||||
last 7 years
|
last 7 years
|
||||||
> 0.05% and supports websockets
|
>= 0.05%
|
||||||
|
not dead
|
||||||
|
not op_mini all
|
||||||
|
|
||||||
|
[legacy-sw]
|
||||||
|
# Same as legacy plus supports service workers
|
||||||
|
unreleased versions
|
||||||
|
last 7 years
|
||||||
|
>= 0.05% and supports serviceworkers
|
||||||
|
not dead
|
||||||
|
not op_mini all
|
||||||
|
@@ -1,5 +1,4 @@
|
|||||||
# See here for image contents: https://github.com/microsoft/vscode-dev-containers/tree/v0.148.1/containers/python-3/.devcontainer/base.Dockerfile
|
FROM mcr.microsoft.com/devcontainers/python:1-3.13
|
||||||
FROM mcr.microsoft.com/devcontainers/python:3.12
|
|
||||||
|
|
||||||
ENV \
|
ENV \
|
||||||
DEBIAN_FRONTEND=noninteractive \
|
DEBIAN_FRONTEND=noninteractive \
|
||||||
|
@@ -8,6 +8,7 @@
|
|||||||
"postCreateCommand": "sudo apt update && sudo apt upgrade -y && sudo apt install -y libpcap-dev",
|
"postCreateCommand": "sudo apt update && sudo apt upgrade -y && sudo apt install -y libpcap-dev",
|
||||||
"postStartCommand": "script/bootstrap",
|
"postStartCommand": "script/bootstrap",
|
||||||
"containerEnv": {
|
"containerEnv": {
|
||||||
|
"DEV_CONTAINER": "1",
|
||||||
"WORKSPACE_DIRECTORY": "${containerWorkspaceFolder}"
|
"WORKSPACE_DIRECTORY": "${containerWorkspaceFolder}"
|
||||||
},
|
},
|
||||||
"customizations": {
|
"customizations": {
|
||||||
|
130
.eslintrc.json
130
.eslintrc.json
@@ -1,130 +0,0 @@
|
|||||||
{
|
|
||||||
"extends": [
|
|
||||||
"airbnb-base",
|
|
||||||
"airbnb-typescript/base",
|
|
||||||
"plugin:@typescript-eslint/recommended",
|
|
||||||
"plugin:wc/recommended",
|
|
||||||
"plugin:lit/all",
|
|
||||||
"plugin:lit-a11y/recommended",
|
|
||||||
"prettier"
|
|
||||||
],
|
|
||||||
"parser": "@typescript-eslint/parser",
|
|
||||||
"parserOptions": {
|
|
||||||
"ecmaVersion": 2020,
|
|
||||||
"ecmaFeatures": {
|
|
||||||
"modules": true
|
|
||||||
},
|
|
||||||
"sourceType": "module",
|
|
||||||
"project": "./tsconfig.json"
|
|
||||||
},
|
|
||||||
"settings": {
|
|
||||||
"import/resolver": {
|
|
||||||
"webpack": {
|
|
||||||
"config": "./webpack.config.cjs"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"globals": {
|
|
||||||
"__DEV__": false,
|
|
||||||
"__DEMO__": false,
|
|
||||||
"__BUILD__": false,
|
|
||||||
"__VERSION__": false,
|
|
||||||
"__STATIC_PATH__": false,
|
|
||||||
"__SUPERVISOR__": false,
|
|
||||||
"Polymer": true
|
|
||||||
},
|
|
||||||
"env": {
|
|
||||||
"browser": true,
|
|
||||||
"es6": true
|
|
||||||
},
|
|
||||||
"rules": {
|
|
||||||
"class-methods-use-this": "off",
|
|
||||||
"new-cap": "off",
|
|
||||||
"prefer-template": "off",
|
|
||||||
"object-shorthand": "off",
|
|
||||||
"func-names": "off",
|
|
||||||
"no-underscore-dangle": "off",
|
|
||||||
"strict": "off",
|
|
||||||
"no-plusplus": "off",
|
|
||||||
"no-bitwise": "error",
|
|
||||||
"comma-dangle": "off",
|
|
||||||
"vars-on-top": "off",
|
|
||||||
"no-continue": "off",
|
|
||||||
"no-param-reassign": "off",
|
|
||||||
"no-multi-assign": "off",
|
|
||||||
"no-console": "error",
|
|
||||||
"radix": "off",
|
|
||||||
"no-alert": "off",
|
|
||||||
"no-nested-ternary": "off",
|
|
||||||
"prefer-destructuring": "off",
|
|
||||||
"no-restricted-globals": [2, "event"],
|
|
||||||
"prefer-promise-reject-errors": "off",
|
|
||||||
"import/prefer-default-export": "off",
|
|
||||||
"import/no-default-export": "off",
|
|
||||||
"import/no-unresolved": "off",
|
|
||||||
"import/no-cycle": "off",
|
|
||||||
"import/extensions": [
|
|
||||||
"error",
|
|
||||||
"ignorePackages",
|
|
||||||
{
|
|
||||||
"ts": "never",
|
|
||||||
"js": "never"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"no-restricted-syntax": ["error", "LabeledStatement", "WithStatement"],
|
|
||||||
"object-curly-newline": "off",
|
|
||||||
"default-case": "off",
|
|
||||||
"wc/no-self-class": "off",
|
|
||||||
"no-shadow": "off",
|
|
||||||
"@typescript-eslint/camelcase": "off",
|
|
||||||
"@typescript-eslint/ban-ts-comment": "off",
|
|
||||||
"@typescript-eslint/no-use-before-define": "off",
|
|
||||||
"@typescript-eslint/no-non-null-assertion": "off",
|
|
||||||
"@typescript-eslint/no-explicit-any": "off",
|
|
||||||
"@typescript-eslint/explicit-function-return-type": "off",
|
|
||||||
"@typescript-eslint/explicit-module-boundary-types": "off",
|
|
||||||
"@typescript-eslint/no-shadow": ["error"],
|
|
||||||
"@typescript-eslint/naming-convention": [
|
|
||||||
"off",
|
|
||||||
{
|
|
||||||
"selector": "default",
|
|
||||||
"format": ["camelCase", "snake_case"],
|
|
||||||
"leadingUnderscore": "allow",
|
|
||||||
"trailingUnderscore": "allow"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"selector": ["variable"],
|
|
||||||
"format": ["camelCase", "snake_case", "UPPER_CASE"],
|
|
||||||
"leadingUnderscore": "allow",
|
|
||||||
"trailingUnderscore": "allow"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"selector": "typeLike",
|
|
||||||
"format": ["PascalCase"]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"@typescript-eslint/no-unused-vars": "off",
|
|
||||||
"unused-imports/no-unused-vars": [
|
|
||||||
"error",
|
|
||||||
{
|
|
||||||
"vars": "all",
|
|
||||||
"varsIgnorePattern": "^_",
|
|
||||||
"args": "after-used",
|
|
||||||
"argsIgnorePattern": "^_",
|
|
||||||
"ignoreRestSiblings": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"unused-imports/no-unused-imports": "error",
|
|
||||||
"lit/attribute-value-entities": "off",
|
|
||||||
"lit/no-template-map": "off",
|
|
||||||
"lit/no-native-attributes": "warn",
|
|
||||||
"lit/no-this-assign-in-render": "warn",
|
|
||||||
"lit-a11y/click-events-have-key-events": ["off"],
|
|
||||||
"lit-a11y/no-autofocus": "off",
|
|
||||||
"lit-a11y/alt-text": "warn",
|
|
||||||
"lit-a11y/anchor-is-valid": "warn",
|
|
||||||
"lit-a11y/role-has-required-aria-attrs": "warn"
|
|
||||||
},
|
|
||||||
"plugins": ["disable", "unused-imports"],
|
|
||||||
"processor": "disable/disable"
|
|
||||||
}
|
|
4
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
4
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@@ -7,7 +7,7 @@ body:
|
|||||||
value: |
|
value: |
|
||||||
Make sure you are running the [latest version of Home Assistant][releases] before reporting an issue.
|
Make sure you are running the [latest version of Home Assistant][releases] before reporting an issue.
|
||||||
|
|
||||||
If you have a feature or enhancement request for the frontend, please [start an discussion][fr] instead of creating an issue.
|
If you have a feature or enhancement request for the frontend, please [start a discussion][fr] instead of creating an issue.
|
||||||
|
|
||||||
**Please do not report issues for custom cards.**
|
**Please do not report issues for custom cards.**
|
||||||
|
|
||||||
@@ -74,7 +74,7 @@ body:
|
|||||||
If known, otherwise leave blank.
|
If known, otherwise leave blank.
|
||||||
- type: input
|
- type: input
|
||||||
attributes:
|
attributes:
|
||||||
label: In which browser are you experiencing the issue with?
|
label: In which browser are you experiencing the issue?
|
||||||
placeholder: Google Chrome 88.0.4324.150
|
placeholder: Google Chrome 88.0.4324.150
|
||||||
description: >
|
description: >
|
||||||
Provide the full name and don't forget to add the version!
|
Provide the full name and don't forget to add the version!
|
||||||
|
2
.github/ISSUE_TEMPLATE/config.yml
vendored
2
.github/ISSUE_TEMPLATE/config.yml
vendored
@@ -2,7 +2,7 @@ blank_issues_enabled: false
|
|||||||
contact_links:
|
contact_links:
|
||||||
- name: Request a feature for the UI / Dashboards
|
- name: Request a feature for the UI / Dashboards
|
||||||
url: https://github.com/home-assistant/frontend/discussions/category_choices
|
url: https://github.com/home-assistant/frontend/discussions/category_choices
|
||||||
about: Request an new feature for the Home Assistant frontend.
|
about: Request a new feature for the Home Assistant frontend.
|
||||||
- name: Report a bug that is NOT related to the UI / Dashboards
|
- name: Report a bug that is NOT related to the UI / Dashboards
|
||||||
url: https://github.com/home-assistant/core/issues
|
url: https://github.com/home-assistant/core/issues
|
||||||
about: This is the issue tracker for our frontend. Please report other issues in the backend ("core") repository.
|
about: This is the issue tracker for our frontend. Please report other issues in the backend ("core") repository.
|
||||||
|
8
.github/workflows/cast_deployment.yaml
vendored
8
.github/workflows/cast_deployment.yaml
vendored
@@ -21,12 +21,12 @@ jobs:
|
|||||||
url: ${{ steps.deploy.outputs.NETLIFY_LIVE_URL || steps.deploy.outputs.NETLIFY_URL }}
|
url: ${{ steps.deploy.outputs.NETLIFY_LIVE_URL || steps.deploy.outputs.NETLIFY_URL }}
|
||||||
steps:
|
steps:
|
||||||
- name: Check out files from GitHub
|
- name: Check out files from GitHub
|
||||||
uses: actions/checkout@v4.1.3
|
uses: actions/checkout@v4.2.2
|
||||||
with:
|
with:
|
||||||
ref: dev
|
ref: dev
|
||||||
|
|
||||||
- name: Setup Node
|
- name: Setup Node
|
||||||
uses: actions/setup-node@v4.0.2
|
uses: actions/setup-node@v4.2.0
|
||||||
with:
|
with:
|
||||||
node-version-file: ".nvmrc"
|
node-version-file: ".nvmrc"
|
||||||
cache: yarn
|
cache: yarn
|
||||||
@@ -57,12 +57,12 @@ jobs:
|
|||||||
url: ${{ steps.deploy.outputs.NETLIFY_LIVE_URL || steps.deploy.outputs.NETLIFY_URL }}
|
url: ${{ steps.deploy.outputs.NETLIFY_LIVE_URL || steps.deploy.outputs.NETLIFY_URL }}
|
||||||
steps:
|
steps:
|
||||||
- name: Check out files from GitHub
|
- name: Check out files from GitHub
|
||||||
uses: actions/checkout@v4.1.3
|
uses: actions/checkout@v4.2.2
|
||||||
with:
|
with:
|
||||||
ref: master
|
ref: master
|
||||||
|
|
||||||
- name: Setup Node
|
- name: Setup Node
|
||||||
uses: actions/setup-node@v4.0.2
|
uses: actions/setup-node@v4.2.0
|
||||||
with:
|
with:
|
||||||
node-version-file: ".nvmrc"
|
node-version-file: ".nvmrc"
|
||||||
cache: yarn
|
cache: yarn
|
||||||
|
22
.github/workflows/ci.yaml
vendored
22
.github/workflows/ci.yaml
vendored
@@ -24,9 +24,9 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Check out files from GitHub
|
- name: Check out files from GitHub
|
||||||
uses: actions/checkout@v4.1.3
|
uses: actions/checkout@v4.2.2
|
||||||
- name: Setup Node
|
- name: Setup Node
|
||||||
uses: actions/setup-node@v4.0.2
|
uses: actions/setup-node@v4.2.0
|
||||||
with:
|
with:
|
||||||
node-version-file: ".nvmrc"
|
node-version-file: ".nvmrc"
|
||||||
cache: yarn
|
cache: yarn
|
||||||
@@ -37,7 +37,7 @@ jobs:
|
|||||||
- name: Build resources
|
- name: Build resources
|
||||||
run: ./node_modules/.bin/gulp gen-icons-json build-translations build-locale-data gather-gallery-pages
|
run: ./node_modules/.bin/gulp gen-icons-json build-translations build-locale-data gather-gallery-pages
|
||||||
- name: Setup lint cache
|
- name: Setup lint cache
|
||||||
uses: actions/cache@v4.0.2
|
uses: actions/cache@v4.2.0
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
node_modules/.cache/prettier
|
node_modules/.cache/prettier
|
||||||
@@ -58,9 +58,9 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Check out files from GitHub
|
- name: Check out files from GitHub
|
||||||
uses: actions/checkout@v4.1.3
|
uses: actions/checkout@v4.2.2
|
||||||
- name: Setup Node
|
- name: Setup Node
|
||||||
uses: actions/setup-node@v4.0.2
|
uses: actions/setup-node@v4.2.0
|
||||||
with:
|
with:
|
||||||
node-version-file: ".nvmrc"
|
node-version-file: ".nvmrc"
|
||||||
cache: yarn
|
cache: yarn
|
||||||
@@ -76,9 +76,9 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Check out files from GitHub
|
- name: Check out files from GitHub
|
||||||
uses: actions/checkout@v4.1.3
|
uses: actions/checkout@v4.2.2
|
||||||
- name: Setup Node
|
- name: Setup Node
|
||||||
uses: actions/setup-node@v4.0.2
|
uses: actions/setup-node@v4.2.0
|
||||||
with:
|
with:
|
||||||
node-version-file: ".nvmrc"
|
node-version-file: ".nvmrc"
|
||||||
cache: yarn
|
cache: yarn
|
||||||
@@ -89,7 +89,7 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
IS_TEST: "true"
|
IS_TEST: "true"
|
||||||
- name: Upload bundle stats
|
- name: Upload bundle stats
|
||||||
uses: actions/upload-artifact@v4.3.2
|
uses: actions/upload-artifact@v4.6.0
|
||||||
with:
|
with:
|
||||||
name: frontend-bundle-stats
|
name: frontend-bundle-stats
|
||||||
path: build/stats/*.json
|
path: build/stats/*.json
|
||||||
@@ -100,9 +100,9 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Check out files from GitHub
|
- name: Check out files from GitHub
|
||||||
uses: actions/checkout@v4.1.3
|
uses: actions/checkout@v4.2.2
|
||||||
- name: Setup Node
|
- name: Setup Node
|
||||||
uses: actions/setup-node@v4.0.2
|
uses: actions/setup-node@v4.2.0
|
||||||
with:
|
with:
|
||||||
node-version-file: ".nvmrc"
|
node-version-file: ".nvmrc"
|
||||||
cache: yarn
|
cache: yarn
|
||||||
@@ -113,7 +113,7 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
IS_TEST: "true"
|
IS_TEST: "true"
|
||||||
- name: Upload bundle stats
|
- name: Upload bundle stats
|
||||||
uses: actions/upload-artifact@v4.3.2
|
uses: actions/upload-artifact@v4.6.0
|
||||||
with:
|
with:
|
||||||
name: supervisor-bundle-stats
|
name: supervisor-bundle-stats
|
||||||
path: build/stats/*.json
|
path: build/stats/*.json
|
||||||
|
2
.github/workflows/codeql-analysis.yml
vendored
2
.github/workflows/codeql-analysis.yml
vendored
@@ -23,7 +23,7 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v4.1.3
|
uses: actions/checkout@v4.2.2
|
||||||
with:
|
with:
|
||||||
# We must fetch at least the immediate parents so that if this is
|
# We must fetch at least the immediate parents so that if this is
|
||||||
# a pull request then we can checkout the head.
|
# a pull request then we can checkout the head.
|
||||||
|
8
.github/workflows/demo_deployment.yaml
vendored
8
.github/workflows/demo_deployment.yaml
vendored
@@ -22,12 +22,12 @@ jobs:
|
|||||||
url: ${{ steps.deploy.outputs.NETLIFY_LIVE_URL || steps.deploy.outputs.NETLIFY_URL }}
|
url: ${{ steps.deploy.outputs.NETLIFY_LIVE_URL || steps.deploy.outputs.NETLIFY_URL }}
|
||||||
steps:
|
steps:
|
||||||
- name: Check out files from GitHub
|
- name: Check out files from GitHub
|
||||||
uses: actions/checkout@v4.1.3
|
uses: actions/checkout@v4.2.2
|
||||||
with:
|
with:
|
||||||
ref: dev
|
ref: dev
|
||||||
|
|
||||||
- name: Setup Node
|
- name: Setup Node
|
||||||
uses: actions/setup-node@v4.0.2
|
uses: actions/setup-node@v4.2.0
|
||||||
with:
|
with:
|
||||||
node-version-file: ".nvmrc"
|
node-version-file: ".nvmrc"
|
||||||
cache: yarn
|
cache: yarn
|
||||||
@@ -58,12 +58,12 @@ jobs:
|
|||||||
url: ${{ steps.deploy.outputs.NETLIFY_LIVE_URL || steps.deploy.outputs.NETLIFY_URL }}
|
url: ${{ steps.deploy.outputs.NETLIFY_LIVE_URL || steps.deploy.outputs.NETLIFY_URL }}
|
||||||
steps:
|
steps:
|
||||||
- name: Check out files from GitHub
|
- name: Check out files from GitHub
|
||||||
uses: actions/checkout@v4.1.3
|
uses: actions/checkout@v4.2.2
|
||||||
with:
|
with:
|
||||||
ref: master
|
ref: master
|
||||||
|
|
||||||
- name: Setup Node
|
- name: Setup Node
|
||||||
uses: actions/setup-node@v4.0.2
|
uses: actions/setup-node@v4.2.0
|
||||||
with:
|
with:
|
||||||
node-version-file: ".nvmrc"
|
node-version-file: ".nvmrc"
|
||||||
cache: yarn
|
cache: yarn
|
||||||
|
4
.github/workflows/design_deployment.yaml
vendored
4
.github/workflows/design_deployment.yaml
vendored
@@ -16,10 +16,10 @@ jobs:
|
|||||||
url: ${{ steps.deploy.outputs.NETLIFY_LIVE_URL || steps.deploy.outputs.NETLIFY_URL }}
|
url: ${{ steps.deploy.outputs.NETLIFY_LIVE_URL || steps.deploy.outputs.NETLIFY_URL }}
|
||||||
steps:
|
steps:
|
||||||
- name: Check out files from GitHub
|
- name: Check out files from GitHub
|
||||||
uses: actions/checkout@v4.1.3
|
uses: actions/checkout@v4.2.2
|
||||||
|
|
||||||
- name: Setup Node
|
- name: Setup Node
|
||||||
uses: actions/setup-node@v4.0.2
|
uses: actions/setup-node@v4.2.0
|
||||||
with:
|
with:
|
||||||
node-version-file: ".nvmrc"
|
node-version-file: ".nvmrc"
|
||||||
cache: yarn
|
cache: yarn
|
||||||
|
4
.github/workflows/design_preview.yaml
vendored
4
.github/workflows/design_preview.yaml
vendored
@@ -21,10 +21,10 @@ jobs:
|
|||||||
if: github.repository == 'home-assistant/frontend' && contains(github.event.pull_request.labels.*.name, 'needs design preview')
|
if: github.repository == 'home-assistant/frontend' && contains(github.event.pull_request.labels.*.name, 'needs design preview')
|
||||||
steps:
|
steps:
|
||||||
- name: Check out files from GitHub
|
- name: Check out files from GitHub
|
||||||
uses: actions/checkout@v4.1.3
|
uses: actions/checkout@v4.2.2
|
||||||
|
|
||||||
- name: Setup Node
|
- name: Setup Node
|
||||||
uses: actions/setup-node@v4.0.2
|
uses: actions/setup-node@v4.2.0
|
||||||
with:
|
with:
|
||||||
node-version-file: ".nvmrc"
|
node-version-file: ".nvmrc"
|
||||||
cache: yarn
|
cache: yarn
|
||||||
|
10
.github/workflows/nightly.yaml
vendored
10
.github/workflows/nightly.yaml
vendored
@@ -6,7 +6,7 @@ on:
|
|||||||
- cron: "0 1 * * *"
|
- cron: "0 1 * * *"
|
||||||
|
|
||||||
env:
|
env:
|
||||||
PYTHON_VERSION: "3.12"
|
PYTHON_VERSION: "3.13"
|
||||||
NODE_OPTIONS: --max_old_space_size=6144
|
NODE_OPTIONS: --max_old_space_size=6144
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
@@ -20,7 +20,7 @@ jobs:
|
|||||||
contents: write
|
contents: write
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout the repository
|
- name: Checkout the repository
|
||||||
uses: actions/checkout@v4.1.3
|
uses: actions/checkout@v4.2.2
|
||||||
|
|
||||||
- name: Set up Python ${{ env.PYTHON_VERSION }}
|
- name: Set up Python ${{ env.PYTHON_VERSION }}
|
||||||
uses: actions/setup-python@v5
|
uses: actions/setup-python@v5
|
||||||
@@ -28,7 +28,7 @@ jobs:
|
|||||||
python-version: ${{ env.PYTHON_VERSION }}
|
python-version: ${{ env.PYTHON_VERSION }}
|
||||||
|
|
||||||
- name: Setup Node
|
- name: Setup Node
|
||||||
uses: actions/setup-node@v4.0.2
|
uses: actions/setup-node@v4.2.0
|
||||||
with:
|
with:
|
||||||
node-version-file: ".nvmrc"
|
node-version-file: ".nvmrc"
|
||||||
cache: yarn
|
cache: yarn
|
||||||
@@ -57,14 +57,14 @@ jobs:
|
|||||||
run: tar -czvf translations.tar.gz translations
|
run: tar -czvf translations.tar.gz translations
|
||||||
|
|
||||||
- name: Upload build artifacts
|
- name: Upload build artifacts
|
||||||
uses: actions/upload-artifact@v4.3.2
|
uses: actions/upload-artifact@v4.6.0
|
||||||
with:
|
with:
|
||||||
name: wheels
|
name: wheels
|
||||||
path: dist/home_assistant_frontend*.whl
|
path: dist/home_assistant_frontend*.whl
|
||||||
if-no-files-found: error
|
if-no-files-found: error
|
||||||
|
|
||||||
- name: Upload translations
|
- name: Upload translations
|
||||||
uses: actions/upload-artifact@v4.3.2
|
uses: actions/upload-artifact@v4.6.0
|
||||||
with:
|
with:
|
||||||
name: translations
|
name: translations
|
||||||
path: translations.tar.gz
|
path: translations.tar.gz
|
||||||
|
2
.github/workflows/relative-ci.yaml
vendored
2
.github/workflows/relative-ci.yaml
vendored
@@ -17,7 +17,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Send bundle stats and build information to RelativeCI
|
- name: Send bundle stats and build information to RelativeCI
|
||||||
uses: relative-ci/agent-action@v2.1.10
|
uses: relative-ci/agent-action@v2.1.14
|
||||||
with:
|
with:
|
||||||
key: ${{ secrets[format('RELATIVE_CI_KEY_{0}_{1}', matrix.bundle, matrix.build)] }}
|
key: ${{ secrets[format('RELATIVE_CI_KEY_{0}_{1}', matrix.bundle, matrix.build)] }}
|
||||||
token: ${{ github.token }}
|
token: ${{ github.token }}
|
||||||
|
2
.github/workflows/release-drafter.yaml
vendored
2
.github/workflows/release-drafter.yaml
vendored
@@ -18,6 +18,6 @@ jobs:
|
|||||||
pull-requests: read
|
pull-requests: read
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: release-drafter/release-drafter@v6.0.0
|
- uses: release-drafter/release-drafter@v6.1.0
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
76
.github/workflows/release.yaml
vendored
76
.github/workflows/release.yaml
vendored
@@ -6,7 +6,7 @@ on:
|
|||||||
- published
|
- published
|
||||||
|
|
||||||
env:
|
env:
|
||||||
PYTHON_VERSION: "3.12"
|
PYTHON_VERSION: "3.13"
|
||||||
NODE_OPTIONS: --max_old_space_size=6144
|
NODE_OPTIONS: --max_old_space_size=6144
|
||||||
|
|
||||||
# Set default workflow permissions
|
# Set default workflow permissions
|
||||||
@@ -23,18 +23,18 @@ jobs:
|
|||||||
contents: write # Required to upload release assets
|
contents: write # Required to upload release assets
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout the repository
|
- name: Checkout the repository
|
||||||
uses: actions/checkout@v4.1.3
|
uses: actions/checkout@v4.2.2
|
||||||
|
|
||||||
- name: Verify version
|
|
||||||
uses: home-assistant/actions/helpers/verify-version@master
|
|
||||||
|
|
||||||
- name: Set up Python ${{ env.PYTHON_VERSION }}
|
- name: Set up Python ${{ env.PYTHON_VERSION }}
|
||||||
uses: actions/setup-python@v5
|
uses: actions/setup-python@v5
|
||||||
with:
|
with:
|
||||||
python-version: ${{ env.PYTHON_VERSION }}
|
python-version: ${{ env.PYTHON_VERSION }}
|
||||||
|
|
||||||
|
- name: Verify version
|
||||||
|
uses: home-assistant/actions/helpers/verify-version@master
|
||||||
|
|
||||||
- name: Setup Node
|
- name: Setup Node
|
||||||
uses: actions/setup-node@v4.0.2
|
uses: actions/setup-node@v4.2.0
|
||||||
with:
|
with:
|
||||||
node-version-file: ".nvmrc"
|
node-version-file: ".nvmrc"
|
||||||
cache: yarn
|
cache: yarn
|
||||||
@@ -55,7 +55,7 @@ jobs:
|
|||||||
script/release
|
script/release
|
||||||
|
|
||||||
- name: Upload release assets
|
- name: Upload release assets
|
||||||
uses: softprops/action-gh-release@v2.0.4
|
uses: softprops/action-gh-release@v2.2.1
|
||||||
with:
|
with:
|
||||||
files: |
|
files: |
|
||||||
dist/*.whl
|
dist/*.whl
|
||||||
@@ -74,10 +74,68 @@ jobs:
|
|||||||
echo "home-assistant-frontend==$version" > ./requirements.txt
|
echo "home-assistant-frontend==$version" > ./requirements.txt
|
||||||
|
|
||||||
- name: Build wheels
|
- name: Build wheels
|
||||||
uses: home-assistant/wheels@2024.01.0
|
uses: home-assistant/wheels@2024.11.0
|
||||||
with:
|
with:
|
||||||
abi: cp311
|
abi: cp313
|
||||||
tag: musllinux_1_2
|
tag: musllinux_1_2
|
||||||
arch: amd64
|
arch: amd64
|
||||||
wheels-key: ${{ secrets.WHEELS_KEY }}
|
wheels-key: ${{ secrets.WHEELS_KEY }}
|
||||||
requirements: "requirements.txt"
|
requirements: "requirements.txt"
|
||||||
|
|
||||||
|
release-landing-page:
|
||||||
|
name: Release landing-page frontend
|
||||||
|
if: github.event.release.prerelease == false
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: write # Required to upload release assets
|
||||||
|
steps:
|
||||||
|
- name: Checkout the repository
|
||||||
|
uses: actions/checkout@v4.2.2
|
||||||
|
- name: Setup Node
|
||||||
|
uses: actions/setup-node@v4.2.0
|
||||||
|
with:
|
||||||
|
node-version-file: ".nvmrc"
|
||||||
|
cache: yarn
|
||||||
|
- name: Install dependencies
|
||||||
|
run: yarn install
|
||||||
|
- name: Download Translations
|
||||||
|
run: ./script/translations_download
|
||||||
|
env:
|
||||||
|
LOKALISE_TOKEN: ${{ secrets.LOKALISE_TOKEN }}
|
||||||
|
- name: Build landing-page
|
||||||
|
run: landing-page/script/build_landing_page
|
||||||
|
- name: Tar folder
|
||||||
|
run: tar -czf landing-page/home_assistant_frontend_landingpage-${{ github.event.release.tag_name }}.tar.gz -C landing-page/dist .
|
||||||
|
- name: Upload release asset
|
||||||
|
uses: softprops/action-gh-release@v2.2.1
|
||||||
|
with:
|
||||||
|
files: landing-page/home_assistant_frontend_landingpage-${{ github.event.release.tag_name }}.tar.gz
|
||||||
|
|
||||||
|
release-supervisor:
|
||||||
|
name: Release supervisor frontend
|
||||||
|
if: github.event.release.prerelease == false
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: write # Required to upload release assets
|
||||||
|
steps:
|
||||||
|
- name: Checkout the repository
|
||||||
|
uses: actions/checkout@v4.2.2
|
||||||
|
- name: Setup Node
|
||||||
|
uses: actions/setup-node@v4.2.0
|
||||||
|
with:
|
||||||
|
node-version-file: ".nvmrc"
|
||||||
|
cache: yarn
|
||||||
|
- name: Install dependencies
|
||||||
|
run: yarn install
|
||||||
|
- name: Download Translations
|
||||||
|
run: ./script/translations_download
|
||||||
|
env:
|
||||||
|
LOKALISE_TOKEN: ${{ secrets.LOKALISE_TOKEN }}
|
||||||
|
- name: Build supervisor
|
||||||
|
run: hassio/script/build_hassio
|
||||||
|
- name: Tar folder
|
||||||
|
run: tar -czf hassio/home_assistant_frontend_supervisor-${{ github.event.release.tag_name }}.tar.gz -C hassio/build .
|
||||||
|
- name: Upload release asset
|
||||||
|
uses: softprops/action-gh-release@v2.2.1
|
||||||
|
with:
|
||||||
|
files: hassio/home_assistant_frontend_supervisor-${{ github.event.release.tag_name }}.tar.gz
|
||||||
|
2
.github/workflows/stale.yml
vendored
2
.github/workflows/stale.yml
vendored
@@ -10,7 +10,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: 90 days stale policy
|
- name: 90 days stale policy
|
||||||
uses: actions/stale@v9.0.0
|
uses: actions/stale@v9.1.0
|
||||||
with:
|
with:
|
||||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
days-before-stale: 90
|
days-before-stale: 90
|
||||||
|
2
.github/workflows/translations.yaml
vendored
2
.github/workflows/translations.yaml
vendored
@@ -13,7 +13,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout the repository
|
- name: Checkout the repository
|
||||||
uses: actions/checkout@v4.1.3
|
uses: actions/checkout@v4.2.2
|
||||||
|
|
||||||
- name: Upload Translations
|
- name: Upload Translations
|
||||||
run: |
|
run: |
|
||||||
|
3
.gitignore
vendored
3
.gitignore
vendored
@@ -50,3 +50,6 @@ src/cast/dev_const.ts
|
|||||||
|
|
||||||
# Jetbrains
|
# Jetbrains
|
||||||
/.idea/
|
/.idea/
|
||||||
|
|
||||||
|
# test coverage
|
||||||
|
test/coverage/
|
||||||
|
@@ -1,4 +1 @@
|
|||||||
#!/usr/bin/env sh
|
|
||||||
. "$(dirname -- "$0")/_/husky.sh"
|
|
||||||
|
|
||||||
yarn run lint-staged --relative --shell "/bin/bash"
|
yarn run lint-staged --relative --shell "/bin/bash"
|
||||||
|
3
.vscode/extensions.json
vendored
3
.vscode/extensions.json
vendored
@@ -4,6 +4,7 @@
|
|||||||
"esbenp.prettier-vscode",
|
"esbenp.prettier-vscode",
|
||||||
"runem.lit-plugin",
|
"runem.lit-plugin",
|
||||||
"github.vscode-pull-request-github",
|
"github.vscode-pull-request-github",
|
||||||
"eamodio.gitlens"
|
"eamodio.gitlens",
|
||||||
|
"vitest.explorer"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
32
.vscode/tasks.json
vendored
32
.vscode/tasks.json
vendored
@@ -100,6 +100,38 @@
|
|||||||
"instanceLimit": 1
|
"instanceLimit": 1
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"label": "Develop Landing Page",
|
||||||
|
"type": "gulp",
|
||||||
|
"task": "develop-landing-page",
|
||||||
|
"problemMatcher": {
|
||||||
|
"owner": "ha-build",
|
||||||
|
"source": "ha-build",
|
||||||
|
"fileLocation": "absolute",
|
||||||
|
"severity": "error",
|
||||||
|
"pattern": [
|
||||||
|
{
|
||||||
|
"regexp": "(SyntaxError): (.+): (.+) \\((\\d+):(\\d+)\\)",
|
||||||
|
"severity": 1,
|
||||||
|
"file": 2,
|
||||||
|
"message": 3,
|
||||||
|
"line": 4,
|
||||||
|
"column": 5
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"background": {
|
||||||
|
"activeOnStart": true,
|
||||||
|
"beginsPattern": "Changes detected. Starting compilation",
|
||||||
|
"endsPattern": "Build done @"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"isBackground": true,
|
||||||
|
"group": "build",
|
||||||
|
"runOptions": {
|
||||||
|
"instanceLimit": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"label": "Develop Demo",
|
"label": "Develop Demo",
|
||||||
"type": "gulp",
|
"type": "gulp",
|
||||||
|
@@ -1,16 +1,7 @@
|
|||||||
diff --git a/modular/sortable.core.esm.js b/modular/sortable.core.esm.js
|
diff --git a/modular/sortable.core.esm.js b/modular/sortable.core.esm.js
|
||||||
index 93ba17509e2e8583ab241fea6845fbe714c584a2..de0651ddb5dced30d36f7d764da0dd0b441f523f 100644
|
index 8b5e49b011713c8859c669069fbe85ce53974e1d..6a0afc92787157b8a31c38cc5f67dfa526090a00 100644
|
||||||
--- a/modular/sortable.core.esm.js
|
--- a/modular/sortable.core.esm.js
|
||||||
+++ b/modular/sortable.core.esm.js
|
+++ b/modular/sortable.core.esm.js
|
||||||
@@ -1461,7 +1461,7 @@ Sortable.prototype = /** @lends Sortable.prototype */{
|
|
||||||
}
|
|
||||||
target = parent; // store last element
|
|
||||||
}
|
|
||||||
- /* jshint boss:true */ while (parent = parent.parentNode);
|
|
||||||
+ /* jshint boss:true */ while (parent = parent.parentNode || parent.getRootNode().host);
|
|
||||||
}
|
|
||||||
_unhideGhostForTarget();
|
|
||||||
}
|
|
||||||
@@ -1781,11 +1781,16 @@ Sortable.prototype = /** @lends Sortable.prototype */{
|
@@ -1781,11 +1781,16 @@ Sortable.prototype = /** @lends Sortable.prototype */{
|
||||||
}
|
}
|
||||||
if (_onMove(rootEl, el, dragEl, dragRect, target, targetRect, evt, !!target) !== false) {
|
if (_onMove(rootEl, el, dragEl, dragRect, target, targetRect, evt, !!target) !== false) {
|
||||||
@@ -33,7 +24,7 @@ index 93ba17509e2e8583ab241fea6845fbe714c584a2..de0651ddb5dced30d36f7d764da0dd0b
|
|||||||
}
|
}
|
||||||
parentEl = el; // actualization
|
parentEl = el; // actualization
|
||||||
|
|
||||||
@@ -1802,7 +1807,13 @@ Sortable.prototype = /** @lends Sortable.prototype */{
|
@@ -1802,7 +1807,12 @@ Sortable.prototype = /** @lends Sortable.prototype */{
|
||||||
targetRect = getRect(target);
|
targetRect = getRect(target);
|
||||||
if (_onMove(rootEl, el, dragEl, dragRect, target, targetRect, evt, false) !== false) {
|
if (_onMove(rootEl, el, dragEl, dragRect, target, targetRect, evt, false) !== false) {
|
||||||
capture();
|
capture();
|
||||||
@@ -44,11 +35,10 @@ index 93ba17509e2e8583ab241fea6845fbe714c584a2..de0651ddb5dced30d36f7d764da0dd0b
|
|||||||
+ catch(err) {
|
+ catch(err) {
|
||||||
+ return completed(false);
|
+ return completed(false);
|
||||||
+ }
|
+ }
|
||||||
+
|
|
||||||
parentEl = el; // actualization
|
parentEl = el; // actualization
|
||||||
|
|
||||||
changed();
|
changed();
|
||||||
@@ -1849,12 +1860,17 @@ Sortable.prototype = /** @lends Sortable.prototype */{
|
@@ -1849,10 +1859,15 @@ Sortable.prototype = /** @lends Sortable.prototype */{
|
||||||
_silent = true;
|
_silent = true;
|
||||||
setTimeout(_unsilent, 30);
|
setTimeout(_unsilent, 30);
|
||||||
capture();
|
capture();
|
||||||
@@ -56,8 +46,6 @@ index 93ba17509e2e8583ab241fea6845fbe714c584a2..de0651ddb5dced30d36f7d764da0dd0b
|
|||||||
- el.appendChild(dragEl);
|
- el.appendChild(dragEl);
|
||||||
- } else {
|
- } else {
|
||||||
- target.parentNode.insertBefore(dragEl, after ? nextSibling : target);
|
- target.parentNode.insertBefore(dragEl, after ? nextSibling : target);
|
||||||
- }
|
|
||||||
|
|
||||||
+ try {
|
+ try {
|
||||||
+ if (after && !nextSibling) {
|
+ if (after && !nextSibling) {
|
||||||
+ el.appendChild(dragEl);
|
+ el.appendChild(dragEl);
|
||||||
@@ -67,7 +55,6 @@ index 93ba17509e2e8583ab241fea6845fbe714c584a2..de0651ddb5dced30d36f7d764da0dd0b
|
|||||||
+ }
|
+ }
|
||||||
+ catch(err) {
|
+ catch(err) {
|
||||||
+ return completed(false);
|
+ return completed(false);
|
||||||
+ }
|
}
|
||||||
|
|
||||||
// Undo chrome's scroll adjustment (has no effect on other browsers)
|
// Undo chrome's scroll adjustment (has no effect on other browsers)
|
||||||
if (scrolledPastTop) {
|
|
||||||
scrollBy(scrolledPastTop, 0, scrollBefore - scrolledPastTop.scrollTop);
|
|
55
.yarn/patches/workbox-build-npm-7.1.1-a854f3faae.patch
Normal file
55
.yarn/patches/workbox-build-npm-7.1.1-a854f3faae.patch
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
diff --git a/build/inject-manifest.js b/build/inject-manifest.js
|
||||||
|
index 60e3d2bb51c11a19fbbedbad65e101082ec41c36..fed6026630f43f86e25446383982cf6fb694313b 100644
|
||||||
|
--- a/build/inject-manifest.js
|
||||||
|
+++ b/build/inject-manifest.js
|
||||||
|
@@ -104,7 +104,7 @@ async function injectManifest(config) {
|
||||||
|
replaceString: manifestString,
|
||||||
|
searchString: options.injectionPoint,
|
||||||
|
});
|
||||||
|
- filesToWrite[options.swDest] = source;
|
||||||
|
+ filesToWrite[options.swDest] = source.replace(url, encodeURI(upath_1.default.basename(destPath)));
|
||||||
|
filesToWrite[destPath] = map;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
diff --git a/build/lib/translate-url-to-sourcemap-paths.js b/build/lib/translate-url-to-sourcemap-paths.js
|
||||||
|
index 3220c5474eeac6e8a56ca9b2ac2bd9be48529e43..5f003879a904d4840529a42dd056d288fd213771 100644
|
||||||
|
--- a/build/lib/translate-url-to-sourcemap-paths.js
|
||||||
|
+++ b/build/lib/translate-url-to-sourcemap-paths.js
|
||||||
|
@@ -22,7 +22,7 @@ function translateURLToSourcemapPaths(url, swSrc, swDest) {
|
||||||
|
const possibleSrcPath = upath_1.default.resolve(upath_1.default.dirname(swSrc), url);
|
||||||
|
if (fs_extra_1.default.existsSync(possibleSrcPath)) {
|
||||||
|
srcPath = possibleSrcPath;
|
||||||
|
- destPath = upath_1.default.resolve(upath_1.default.dirname(swDest), url);
|
||||||
|
+ destPath = `${swDest}.map`;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
warning = `${errors_1.errors['cant-find-sourcemap']} ${possibleSrcPath}`;
|
||||||
|
diff --git a/src/inject-manifest.ts b/src/inject-manifest.ts
|
||||||
|
index 8795ddcaa77aea7b0356417e4bc4b19e2b3f860c..fcdc68342d9ac53936c9ed40a9ccfc2f5070cad3 100644
|
||||||
|
--- a/src/inject-manifest.ts
|
||||||
|
+++ b/src/inject-manifest.ts
|
||||||
|
@@ -129,7 +129,10 @@ export async function injectManifest(
|
||||||
|
searchString: options.injectionPoint!,
|
||||||
|
});
|
||||||
|
|
||||||
|
- filesToWrite[options.swDest] = source;
|
||||||
|
+ filesToWrite[options.swDest] = source.replace(
|
||||||
|
+ url!,
|
||||||
|
+ encodeURI(upath.basename(destPath)),
|
||||||
|
+ );
|
||||||
|
filesToWrite[destPath] = map;
|
||||||
|
} else {
|
||||||
|
// If there's no sourcemap associated with swSrc, a simple string
|
||||||
|
diff --git a/src/lib/translate-url-to-sourcemap-paths.ts b/src/lib/translate-url-to-sourcemap-paths.ts
|
||||||
|
index 072eac40d4ef5d095a01cb7f7e392a9e034853bd..f0bbe69e88ef3a415de18a7e9cb264daea273d71 100644
|
||||||
|
--- a/src/lib/translate-url-to-sourcemap-paths.ts
|
||||||
|
+++ b/src/lib/translate-url-to-sourcemap-paths.ts
|
||||||
|
@@ -28,7 +28,7 @@ export function translateURLToSourcemapPaths(
|
||||||
|
const possibleSrcPath = upath.resolve(upath.dirname(swSrc), url);
|
||||||
|
if (fse.existsSync(possibleSrcPath)) {
|
||||||
|
srcPath = possibleSrcPath;
|
||||||
|
- destPath = upath.resolve(upath.dirname(swDest), url);
|
||||||
|
+ destPath = `${swDest}.map`;
|
||||||
|
} else {
|
||||||
|
warning = `${errors['cant-find-sourcemap']} ${possibleSrcPath}`;
|
||||||
|
}
|
893
.yarn/releases/yarn-4.1.1.cjs
vendored
893
.yarn/releases/yarn-4.1.1.cjs
vendored
File diff suppressed because one or more lines are too long
934
.yarn/releases/yarn-4.6.0.cjs
vendored
Executable file
934
.yarn/releases/yarn-4.6.0.cjs
vendored
Executable file
File diff suppressed because one or more lines are too long
@@ -6,4 +6,4 @@ enableGlobalCache: false
|
|||||||
|
|
||||||
nodeLinker: node-modules
|
nodeLinker: node-modules
|
||||||
|
|
||||||
yarnPath: .yarn/releases/yarn-4.1.1.cjs
|
yarnPath: .yarn/releases/yarn-4.6.0.cjs
|
||||||
|
@@ -27,3 +27,5 @@ A complete guide can be found at the following [link](https://www.home-assistant
|
|||||||
Home Assistant is open-source and Apache 2 licensed. Feel free to browse the repository, learn and reuse parts in your own projects.
|
Home Assistant is open-source and Apache 2 licensed. Feel free to browse the repository, learn and reuse parts in your own projects.
|
||||||
|
|
||||||
We use [BrowserStack](https://www.browserstack.com) to test Home Assistant on a large variety of devices.
|
We use [BrowserStack](https://www.browserstack.com) to test Home Assistant on a large variety of devices.
|
||||||
|
|
||||||
|
[](https://www.openhomefoundation.org/)
|
||||||
|
@@ -1,12 +0,0 @@
|
|||||||
{
|
|
||||||
"extends": "../.eslintrc.json",
|
|
||||||
"rules": {
|
|
||||||
"no-console": "off",
|
|
||||||
"import/no-extraneous-dependencies": "off",
|
|
||||||
"import/extensions": "off",
|
|
||||||
"import/no-dynamic-require": "off",
|
|
||||||
"global-require": "off",
|
|
||||||
"@typescript-eslint/no-var-requires": "off",
|
|
||||||
"prefer-arrow-callback": "off"
|
|
||||||
}
|
|
||||||
}
|
|
@@ -15,7 +15,7 @@ The Home Assistant build pipeline contains various steps to prepare a build.
|
|||||||
|
|
||||||
Currently in Home Assistant we use a bundler to convert TypeScript, CSS and JSON files to JavaScript files that the browser understands.
|
Currently in Home Assistant we use a bundler to convert TypeScript, CSS and JSON files to JavaScript files that the browser understands.
|
||||||
|
|
||||||
We currently rely on Webpack but also have experimental Rollup support. Both of these programs bundle the converted files in both production and development.
|
We currently rely on Webpack. Both of these programs bundle the converted files in both production and development.
|
||||||
|
|
||||||
For development, bundling is optional. We just want to get the right files in the browser.
|
For development, bundling is optional. We just want to get the right files in the browser.
|
||||||
|
|
||||||
|
@@ -1,28 +1,82 @@
|
|||||||
import defineProvider from "@babel/helper-define-polyfill-provider";
|
import defineProvider from "@babel/helper-define-polyfill-provider";
|
||||||
|
import { join } from "node:path";
|
||||||
|
import paths from "../paths.cjs";
|
||||||
|
|
||||||
|
const POLYFILL_DIR = join(paths.polymer_dir, "src/resources/polyfills");
|
||||||
|
|
||||||
// List of polyfill keys with supported browser targets for the functionality
|
// List of polyfill keys with supported browser targets for the functionality
|
||||||
const PolyfillSupport = {
|
const polyfillSupport = {
|
||||||
fetch: {
|
// Note states and shadowRoot properties should be supported.
|
||||||
android: 42,
|
"element-internals": {
|
||||||
chrome: 42,
|
android: 90,
|
||||||
edge: 14,
|
chrome: 90,
|
||||||
firefox: 39,
|
edge: 90,
|
||||||
ios: 10.3,
|
firefox: 126,
|
||||||
opera: 29,
|
ios: 17.4,
|
||||||
opera_mobile: 29,
|
opera: 76,
|
||||||
safari: 10.1,
|
opera_mobile: 64,
|
||||||
samsung: 4.0,
|
safari: 17.4,
|
||||||
|
samsung: 15.0,
|
||||||
},
|
},
|
||||||
proxy: {
|
"element-getattributenames": {
|
||||||
android: 49,
|
android: 61,
|
||||||
chrome: 49,
|
chrome: 61,
|
||||||
edge: 12,
|
edge: 18,
|
||||||
firefox: 18,
|
firefox: 45,
|
||||||
ios: 10.0,
|
ios: 10.3,
|
||||||
opera: 36,
|
opera: 48,
|
||||||
opera_mobile: 36,
|
opera_mobile: 45,
|
||||||
safari: 10.0,
|
safari: 10.1,
|
||||||
samsung: 5.0,
|
samsung: 8.0,
|
||||||
|
},
|
||||||
|
"element-toggleattribute": {
|
||||||
|
android: 69,
|
||||||
|
chrome: 69,
|
||||||
|
edge: 18,
|
||||||
|
firefox: 63,
|
||||||
|
ios: 12.0,
|
||||||
|
opera: 56,
|
||||||
|
opera_mobile: 48,
|
||||||
|
safari: 12.0,
|
||||||
|
samsung: 10.0,
|
||||||
|
},
|
||||||
|
// FormatJS polyfill detects fix for https://bugs.chromium.org/p/v8/issues/detail?id=10682,
|
||||||
|
// so adjusted to several months after that was marked fixed
|
||||||
|
"intl-getcanonicallocales": {
|
||||||
|
android: 90,
|
||||||
|
chrome: 90,
|
||||||
|
edge: 90,
|
||||||
|
firefox: 48,
|
||||||
|
ios: 10.3,
|
||||||
|
opera: 76,
|
||||||
|
opera_mobile: 64,
|
||||||
|
safari: 10.1,
|
||||||
|
samsung: 15.0,
|
||||||
|
},
|
||||||
|
"intl-locale": {
|
||||||
|
android: 74,
|
||||||
|
chrome: 74,
|
||||||
|
edge: 79,
|
||||||
|
firefox: 75,
|
||||||
|
ios: 14.0,
|
||||||
|
opera: 62,
|
||||||
|
opera_mobile: 53,
|
||||||
|
safari: 14.0,
|
||||||
|
samsung: 11.0,
|
||||||
|
},
|
||||||
|
"intl-other": {
|
||||||
|
// Not specified (i.e. always try polyfill) since compatibility depends on supported locales
|
||||||
|
},
|
||||||
|
"resize-observer": {
|
||||||
|
android: 64,
|
||||||
|
chrome: 64,
|
||||||
|
edge: 79,
|
||||||
|
firefox: 69,
|
||||||
|
ios: 13.4,
|
||||||
|
opera: 51,
|
||||||
|
opera_mobile: 47,
|
||||||
|
safari: 13.1,
|
||||||
|
samsung: 9.0,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -30,11 +84,49 @@ const PolyfillSupport = {
|
|||||||
// corresponding polyfill key and actual module to import
|
// corresponding polyfill key and actual module to import
|
||||||
const polyfillMap = {
|
const polyfillMap = {
|
||||||
global: {
|
global: {
|
||||||
Proxy: { key: "proxy", module: "proxy-polyfill" },
|
ResizeObserver: {
|
||||||
fetch: { key: "fetch", module: "unfetch/polyfill" },
|
key: "resize-observer",
|
||||||
|
module: join(POLYFILL_DIR, "resize-observer.ts"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
instance: {
|
||||||
|
attachInternals: {
|
||||||
|
key: "element-internals",
|
||||||
|
module: "element-internals-polyfill",
|
||||||
|
},
|
||||||
|
...Object.fromEntries(
|
||||||
|
["getAttributeNames", "toggleAttribute"].map((prop) => {
|
||||||
|
const key = `element-${prop.toLowerCase()}`;
|
||||||
|
return [prop, { key, module: join(POLYFILL_DIR, `${key}.ts`) }];
|
||||||
|
})
|
||||||
|
),
|
||||||
|
},
|
||||||
|
static: {
|
||||||
|
Intl: {
|
||||||
|
getCanonicalLocales: {
|
||||||
|
key: "intl-getcanonicallocales",
|
||||||
|
module: join(POLYFILL_DIR, "intl-polyfill.ts"),
|
||||||
|
},
|
||||||
|
Locale: {
|
||||||
|
key: "intl-locale",
|
||||||
|
module: join(POLYFILL_DIR, "intl-polyfill.ts"),
|
||||||
|
},
|
||||||
|
...Object.fromEntries(
|
||||||
|
[
|
||||||
|
"DateTimeFormat",
|
||||||
|
"DurationFormat",
|
||||||
|
"DisplayNames",
|
||||||
|
"ListFormat",
|
||||||
|
"NumberFormat",
|
||||||
|
"PluralRules",
|
||||||
|
"RelativeTimeFormat",
|
||||||
|
].map((obj) => [
|
||||||
|
obj,
|
||||||
|
{ key: "intl-other", module: join(POLYFILL_DIR, "intl-polyfill.ts") },
|
||||||
|
])
|
||||||
|
),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
instance: {},
|
|
||||||
static: {},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Create plugin using the same factory as for CoreJS
|
// Create plugin using the same factory as for CoreJS
|
||||||
@@ -42,14 +134,16 @@ export default defineProvider(
|
|||||||
({ createMetaResolver, debug, shouldInjectPolyfill }) => {
|
({ createMetaResolver, debug, shouldInjectPolyfill }) => {
|
||||||
const resolvePolyfill = createMetaResolver(polyfillMap);
|
const resolvePolyfill = createMetaResolver(polyfillMap);
|
||||||
return {
|
return {
|
||||||
name: "HA Custom",
|
name: "custom-polyfill",
|
||||||
polyfills: PolyfillSupport,
|
polyfills: polyfillSupport,
|
||||||
usageGlobal(meta, utils) {
|
usageGlobal(meta, utils) {
|
||||||
const polyfill = resolvePolyfill(meta);
|
const polyfill = resolvePolyfill(meta);
|
||||||
if (polyfill && shouldInjectPolyfill(polyfill.desc.key)) {
|
if (polyfill && shouldInjectPolyfill(polyfill.desc.key)) {
|
||||||
debug(polyfill.desc.key);
|
debug(polyfill.desc.key);
|
||||||
utils.injectGlobalImport(polyfill.desc.module);
|
utils.injectGlobalImport(polyfill.desc.module);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@@ -3,6 +3,8 @@ const env = require("./env.cjs");
|
|||||||
const paths = require("./paths.cjs");
|
const paths = require("./paths.cjs");
|
||||||
const { dependencies } = require("../package.json");
|
const { dependencies } = require("../package.json");
|
||||||
|
|
||||||
|
const BABEL_PLUGINS = path.join(__dirname, "babel-plugins");
|
||||||
|
|
||||||
// GitHub base URL to use for production source maps
|
// GitHub base URL to use for production source maps
|
||||||
// Nightly builds use the commit SHA, otherwise assumes there is a tag that matches the version
|
// Nightly builds use the commit SHA, otherwise assumes there is a tag that matches the version
|
||||||
module.exports.sourceMapURL = () => {
|
module.exports.sourceMapURL = () => {
|
||||||
@@ -45,12 +47,17 @@ module.exports.emptyPackages = ({ latestBuild, isHassioBuild }) =>
|
|||||||
|
|
||||||
module.exports.definedVars = ({ isProdBuild, latestBuild, defineOverlay }) => ({
|
module.exports.definedVars = ({ isProdBuild, latestBuild, defineOverlay }) => ({
|
||||||
__DEV__: !isProdBuild,
|
__DEV__: !isProdBuild,
|
||||||
__BUILD__: JSON.stringify(latestBuild ? "latest" : "es5"),
|
__BUILD__: JSON.stringify(latestBuild ? "modern" : "legacy"),
|
||||||
__VERSION__: JSON.stringify(env.version()),
|
__VERSION__: JSON.stringify(env.version()),
|
||||||
__DEMO__: false,
|
__DEMO__: false,
|
||||||
__SUPERVISOR__: false,
|
__SUPERVISOR__: false,
|
||||||
__BACKWARDS_COMPAT__: false,
|
__BACKWARDS_COMPAT__: false,
|
||||||
__STATIC_PATH__: "/static/",
|
__STATIC_PATH__: "/static/",
|
||||||
|
__HASS_URL__: `\`${
|
||||||
|
"HASS_URL" in process.env
|
||||||
|
? process.env["HASS_URL"]
|
||||||
|
: "${location.protocol}//${location.host}"
|
||||||
|
}\``,
|
||||||
"process.env.NODE_ENV": JSON.stringify(
|
"process.env.NODE_ENV": JSON.stringify(
|
||||||
isProdBuild ? "production" : "development"
|
isProdBuild ? "production" : "development"
|
||||||
),
|
),
|
||||||
@@ -77,7 +84,12 @@ module.exports.terserOptions = ({ latestBuild, isTestBuild }) => ({
|
|||||||
sourceMap: !isTestBuild,
|
sourceMap: !isTestBuild,
|
||||||
});
|
});
|
||||||
|
|
||||||
module.exports.babelOptions = ({ latestBuild, isProdBuild, isTestBuild }) => ({
|
module.exports.babelOptions = ({
|
||||||
|
latestBuild,
|
||||||
|
isProdBuild,
|
||||||
|
isTestBuild,
|
||||||
|
sw,
|
||||||
|
}) => ({
|
||||||
babelrc: false,
|
babelrc: false,
|
||||||
compact: false,
|
compact: false,
|
||||||
assumptions: {
|
assumptions: {
|
||||||
@@ -85,13 +97,13 @@ module.exports.babelOptions = ({ latestBuild, isProdBuild, isTestBuild }) => ({
|
|||||||
setPublicClassFields: true,
|
setPublicClassFields: true,
|
||||||
setSpreadProperties: true,
|
setSpreadProperties: true,
|
||||||
},
|
},
|
||||||
browserslistEnv: latestBuild ? "modern" : "legacy",
|
browserslistEnv: latestBuild ? "modern" : `legacy${sw ? "-sw" : ""}`,
|
||||||
presets: [
|
presets: [
|
||||||
[
|
[
|
||||||
"@babel/preset-env",
|
"@babel/preset-env",
|
||||||
{
|
{
|
||||||
useBuiltIns: latestBuild ? false : "usage",
|
useBuiltIns: "usage",
|
||||||
corejs: latestBuild ? false : dependencies["core-js"],
|
corejs: dependencies["core-js"],
|
||||||
bugfixes: true,
|
bugfixes: true,
|
||||||
shippedProposals: true,
|
shippedProposals: true,
|
||||||
},
|
},
|
||||||
@@ -100,22 +112,12 @@ module.exports.babelOptions = ({ latestBuild, isProdBuild, isTestBuild }) => ({
|
|||||||
],
|
],
|
||||||
plugins: [
|
plugins: [
|
||||||
[
|
[
|
||||||
path.resolve(
|
path.join(BABEL_PLUGINS, "inline-constants-plugin.cjs"),
|
||||||
paths.polymer_dir,
|
|
||||||
"build-scripts/babel-plugins/inline-constants-plugin.cjs"
|
|
||||||
),
|
|
||||||
{
|
{
|
||||||
modules: ["@mdi/js"],
|
modules: ["@mdi/js"],
|
||||||
ignoreModuleNotFound: true,
|
ignoreModuleNotFound: true,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
[
|
|
||||||
path.resolve(
|
|
||||||
paths.polymer_dir,
|
|
||||||
"build-scripts/babel-plugins/custom-polyfill-plugin.js"
|
|
||||||
),
|
|
||||||
{ method: "usage-global" },
|
|
||||||
],
|
|
||||||
// Minify template literals for production
|
// Minify template literals for production
|
||||||
isProdBuild && [
|
isProdBuild && [
|
||||||
"template-html-minifier",
|
"template-html-minifier",
|
||||||
@@ -143,16 +145,42 @@ module.exports.babelOptions = ({ latestBuild, isProdBuild, isTestBuild }) => ({
|
|||||||
"@babel/plugin-transform-runtime",
|
"@babel/plugin-transform-runtime",
|
||||||
{ version: dependencies["@babel/runtime"] },
|
{ version: dependencies["@babel/runtime"] },
|
||||||
],
|
],
|
||||||
// Support some proposals still in TC39 process
|
// Transpile decorators (still in TC39 process)
|
||||||
["@babel/plugin-proposal-decorators", { decoratorsBeforeExport: true }],
|
// Modern browsers support class fields and private methods, but transform is required with the older decorator version dictated by Lit
|
||||||
|
[
|
||||||
|
"@babel/plugin-proposal-decorators",
|
||||||
|
{ version: "2018-09", decoratorsBeforeExport: true },
|
||||||
|
],
|
||||||
|
"@babel/plugin-transform-class-properties",
|
||||||
|
"@babel/plugin-transform-private-methods",
|
||||||
].filter(Boolean),
|
].filter(Boolean),
|
||||||
exclude: [
|
exclude: [
|
||||||
// \\ for Windows, / for Mac OS and Linux
|
// \\ for Windows, / for Mac OS and Linux
|
||||||
/node_modules[\\/]core-js/,
|
/node_modules[\\/]core-js/,
|
||||||
/node_modules[\\/]webpack[\\/]buildin/,
|
|
||||||
],
|
],
|
||||||
sourceMaps: !isTestBuild,
|
sourceMaps: !isTestBuild,
|
||||||
overrides: [
|
overrides: [
|
||||||
|
{
|
||||||
|
// Add plugin to inject various polyfills, excluding the polyfills
|
||||||
|
// themselves to prevent self-injection.
|
||||||
|
plugins: [
|
||||||
|
[
|
||||||
|
path.join(BABEL_PLUGINS, "custom-polyfill-plugin.js"),
|
||||||
|
{ method: "usage-global" },
|
||||||
|
],
|
||||||
|
],
|
||||||
|
exclude: [
|
||||||
|
path.join(paths.polymer_dir, "src/resources/polyfills"),
|
||||||
|
...[
|
||||||
|
"@formatjs/(?:ecma402-abstract|intl-\\w+)",
|
||||||
|
"@lit-labs/virtualizer/polyfills",
|
||||||
|
"@webcomponents/scoped-custom-element-registry",
|
||||||
|
"element-internals-polyfill",
|
||||||
|
"proxy-polyfill",
|
||||||
|
"unfetch",
|
||||||
|
].map((p) => new RegExp(`/node_modules/${p}/`)),
|
||||||
|
],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
// Use unambiguous for dependencies so that require() is correctly injected into CommonJS files
|
// Use unambiguous for dependencies so that require() is correctly injected into CommonJS files
|
||||||
// Exclusions are needed in some cases where ES modules have no static imports or exports, such as polyfills
|
// Exclusions are needed in some cases where ES modules have no static imports or exports, such as polyfills
|
||||||
@@ -202,7 +230,12 @@ module.exports.config = {
|
|||||||
return {
|
return {
|
||||||
name: "frontend" + nameSuffix(latestBuild),
|
name: "frontend" + nameSuffix(latestBuild),
|
||||||
entry: {
|
entry: {
|
||||||
service_worker: "./src/entrypoints/service_worker.ts",
|
"service-worker": !latestBuild
|
||||||
|
? {
|
||||||
|
import: "./src/entrypoints/service-worker.ts",
|
||||||
|
layer: "sw",
|
||||||
|
}
|
||||||
|
: "./src/entrypoints/service-worker.ts",
|
||||||
app: "./src/entrypoints/app.ts",
|
app: "./src/entrypoints/app.ts",
|
||||||
authorize: "./src/entrypoints/authorize.ts",
|
authorize: "./src/entrypoints/authorize.ts",
|
||||||
onboarding: "./src/entrypoints/onboarding.ts",
|
onboarding: "./src/entrypoints/onboarding.ts",
|
||||||
@@ -298,4 +331,17 @@ module.exports.config = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
landingPage({ isProdBuild, latestBuild }) {
|
||||||
|
return {
|
||||||
|
name: "landing-page" + nameSuffix(latestBuild),
|
||||||
|
entry: {
|
||||||
|
entrypoint: path.resolve(paths.landingPage_dir, "src/entrypoint.js"),
|
||||||
|
},
|
||||||
|
outputPath: outputPath(paths.landingPage_output_root, latestBuild),
|
||||||
|
publicPath: publicPath(latestBuild),
|
||||||
|
isProdBuild,
|
||||||
|
latestBuild,
|
||||||
|
};
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
@@ -2,26 +2,22 @@ const fs = require("fs");
|
|||||||
const path = require("path");
|
const path = require("path");
|
||||||
const paths = require("./paths.cjs");
|
const paths = require("./paths.cjs");
|
||||||
|
|
||||||
|
const isTrue = (value) => value === "1" || value?.toLowerCase() === "true";
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
useRollup() {
|
|
||||||
return process.env.ROLLUP === "1";
|
|
||||||
},
|
|
||||||
useWDS() {
|
|
||||||
return process.env.WDS === "1";
|
|
||||||
},
|
|
||||||
isProdBuild() {
|
isProdBuild() {
|
||||||
return (
|
return (
|
||||||
process.env.NODE_ENV === "production" || module.exports.isStatsBuild()
|
process.env.NODE_ENV === "production" || module.exports.isStatsBuild()
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
isStatsBuild() {
|
isStatsBuild() {
|
||||||
return process.env.STATS === "1";
|
return isTrue(process.env.STATS);
|
||||||
},
|
},
|
||||||
isTestBuild() {
|
isTestBuild() {
|
||||||
return process.env.IS_TEST === "true";
|
return isTrue(process.env.IS_TEST);
|
||||||
},
|
},
|
||||||
isNetlify() {
|
isNetlify() {
|
||||||
return process.env.NETLIFY === "true";
|
return isTrue(process.env.NETLIFY);
|
||||||
},
|
},
|
||||||
version() {
|
version() {
|
||||||
const version = fs
|
const version = fs
|
||||||
@@ -32,4 +28,7 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
return version[1];
|
return version[1];
|
||||||
},
|
},
|
||||||
|
isDevContainer() {
|
||||||
|
return isTrue(process.env.DEV_CONTAINER);
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
16
build-scripts/eslint.config.mjs
Normal file
16
build-scripts/eslint.config.mjs
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import rootConfig from "../eslint.config.mjs";
|
||||||
|
|
||||||
|
export default [
|
||||||
|
...rootConfig,
|
||||||
|
{
|
||||||
|
rules: {
|
||||||
|
"no-console": "off",
|
||||||
|
"import/no-extraneous-dependencies": "off",
|
||||||
|
"import/extensions": "off",
|
||||||
|
"import/no-dynamic-require": "off",
|
||||||
|
"global-require": "off",
|
||||||
|
"@typescript-eslint/no-require-imports": "off",
|
||||||
|
"prefer-arrow-callback": "off",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
@@ -6,11 +6,9 @@ import "./entry-html.js";
|
|||||||
import "./gather-static.js";
|
import "./gather-static.js";
|
||||||
import "./gen-icons-json.js";
|
import "./gen-icons-json.js";
|
||||||
import "./locale-data.js";
|
import "./locale-data.js";
|
||||||
import "./rollup.js";
|
|
||||||
import "./service-worker.js";
|
import "./service-worker.js";
|
||||||
import "./translations.js";
|
import "./translations.js";
|
||||||
import "./wds.js";
|
import "./rspack.js";
|
||||||
import "./webpack.js";
|
|
||||||
|
|
||||||
gulp.task(
|
gulp.task(
|
||||||
"develop-app",
|
"develop-app",
|
||||||
@@ -27,11 +25,7 @@ gulp.task(
|
|||||||
"build-locale-data"
|
"build-locale-data"
|
||||||
),
|
),
|
||||||
"copy-static-app",
|
"copy-static-app",
|
||||||
env.useWDS()
|
"rspack-watch-app"
|
||||||
? "wds-watch-app"
|
|
||||||
: env.useRollup()
|
|
||||||
? "rollup-watch-app"
|
|
||||||
: "webpack-watch-app"
|
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -44,9 +38,20 @@ gulp.task(
|
|||||||
"clean",
|
"clean",
|
||||||
gulp.parallel("gen-icons-json", "build-translations", "build-locale-data"),
|
gulp.parallel("gen-icons-json", "build-translations", "build-locale-data"),
|
||||||
"copy-static-app",
|
"copy-static-app",
|
||||||
env.useRollup() ? "rollup-prod-app" : "webpack-prod-app",
|
"rspack-prod-app",
|
||||||
gulp.parallel("gen-pages-app-prod", "gen-service-worker-app-prod"),
|
gulp.parallel("gen-pages-app-prod", "gen-service-worker-app-prod"),
|
||||||
// Don't compress running tests
|
// Don't compress running tests
|
||||||
...(env.isTestBuild() ? [] : ["compress-app"])
|
...(env.isTestBuild() || env.isStatsBuild() ? [] : ["compress-app"])
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
gulp.task(
|
||||||
|
"analyze-app",
|
||||||
|
gulp.series(
|
||||||
|
async function setEnv() {
|
||||||
|
process.env.STATS = "1";
|
||||||
|
},
|
||||||
|
"clean",
|
||||||
|
"rspack-prod-app"
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
@@ -1,12 +1,10 @@
|
|||||||
import gulp from "gulp";
|
import gulp from "gulp";
|
||||||
import env from "../env.cjs";
|
|
||||||
import "./clean.js";
|
import "./clean.js";
|
||||||
import "./entry-html.js";
|
import "./entry-html.js";
|
||||||
import "./gather-static.js";
|
import "./gather-static.js";
|
||||||
import "./rollup.js";
|
|
||||||
import "./service-worker.js";
|
import "./service-worker.js";
|
||||||
import "./translations.js";
|
import "./translations.js";
|
||||||
import "./webpack.js";
|
import "./rspack.js";
|
||||||
|
|
||||||
gulp.task(
|
gulp.task(
|
||||||
"develop-cast",
|
"develop-cast",
|
||||||
@@ -19,7 +17,7 @@ gulp.task(
|
|||||||
gulp.parallel("gen-icons-json", "build-translations", "build-locale-data"),
|
gulp.parallel("gen-icons-json", "build-translations", "build-locale-data"),
|
||||||
"copy-static-cast",
|
"copy-static-cast",
|
||||||
"gen-pages-cast-dev",
|
"gen-pages-cast-dev",
|
||||||
env.useRollup() ? "rollup-dev-server-cast" : "webpack-dev-server-cast"
|
"rspack-dev-server-cast"
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -33,7 +31,7 @@ gulp.task(
|
|||||||
"translations-enable-merge-backend",
|
"translations-enable-merge-backend",
|
||||||
gulp.parallel("gen-icons-json", "build-translations", "build-locale-data"),
|
gulp.parallel("gen-icons-json", "build-translations", "build-locale-data"),
|
||||||
"copy-static-cast",
|
"copy-static-cast",
|
||||||
env.useRollup() ? "rollup-prod-cast" : "webpack-prod-cast",
|
"rspack-prod-cast",
|
||||||
"gen-pages-cast-prod"
|
"gen-pages-cast-prod"
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
@@ -38,3 +38,14 @@ gulp.task(
|
|||||||
])
|
])
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
gulp.task(
|
||||||
|
"clean-landing-page",
|
||||||
|
gulp.parallel("clean-translations", async () =>
|
||||||
|
deleteSync([
|
||||||
|
paths.landingPage_output_root,
|
||||||
|
paths.landingPage_build,
|
||||||
|
paths.build_dir,
|
||||||
|
])
|
||||||
|
)
|
||||||
|
);
|
||||||
|
@@ -1,19 +1,86 @@
|
|||||||
// Tasks to compress
|
// Tasks to compress
|
||||||
|
|
||||||
|
import { constants } from "node:zlib";
|
||||||
import gulp from "gulp";
|
import gulp from "gulp";
|
||||||
|
import brotli from "gulp-brotli";
|
||||||
import zopfli from "gulp-zopfli-green";
|
import zopfli from "gulp-zopfli-green";
|
||||||
import paths from "../paths.cjs";
|
import paths from "../paths.cjs";
|
||||||
|
|
||||||
|
const filesGlob = "*.{js,json,css,svg,xml}";
|
||||||
|
const brotliOptions = {
|
||||||
|
skipLarger: true,
|
||||||
|
params: {
|
||||||
|
[constants.BROTLI_PARAM_QUALITY]: constants.BROTLI_MAX_QUALITY,
|
||||||
|
},
|
||||||
|
};
|
||||||
const zopfliOptions = { threshold: 150 };
|
const zopfliOptions = { threshold: 150 };
|
||||||
|
|
||||||
const compressDist = (rootDir) =>
|
const compressModern = (rootDir, modernDir, compress) =>
|
||||||
gulp
|
gulp
|
||||||
.src([
|
.src([`${modernDir}/**/${filesGlob}`, `${rootDir}/sw-modern.js`], {
|
||||||
`${rootDir}/**/*.{js,json,css,svg,xml}`,
|
base: rootDir,
|
||||||
`${rootDir}/{authorize,onboarding}.html`,
|
allowEmpty: true,
|
||||||
])
|
})
|
||||||
.pipe(zopfli(zopfliOptions))
|
.pipe(compress === "zopfli" ? zopfli(zopfliOptions) : brotli(brotliOptions))
|
||||||
.pipe(gulp.dest(rootDir));
|
.pipe(gulp.dest(rootDir));
|
||||||
|
|
||||||
gulp.task("compress-app", () => compressDist(paths.app_output_root));
|
const compressOther = (rootDir, modernDir, compress) =>
|
||||||
gulp.task("compress-hassio", () => compressDist(paths.hassio_output_root));
|
gulp
|
||||||
|
.src(
|
||||||
|
[
|
||||||
|
`${rootDir}/**/${filesGlob}`,
|
||||||
|
`!${modernDir}/**/${filesGlob}`,
|
||||||
|
`!${rootDir}/{sw-modern,service_worker}.js`,
|
||||||
|
`${rootDir}/{authorize,onboarding}.html`,
|
||||||
|
],
|
||||||
|
{ base: rootDir, allowEmpty: true }
|
||||||
|
)
|
||||||
|
.pipe(compress === "zopfli" ? zopfli(zopfliOptions) : brotli(brotliOptions))
|
||||||
|
.pipe(gulp.dest(rootDir));
|
||||||
|
|
||||||
|
const compressAppModernBrotli = () =>
|
||||||
|
compressModern(paths.app_output_root, paths.app_output_latest, "brotli");
|
||||||
|
const compressAppModernZopfli = () =>
|
||||||
|
compressModern(paths.app_output_root, paths.app_output_latest, "zopfli");
|
||||||
|
|
||||||
|
const compressHassioModernBrotli = () =>
|
||||||
|
compressModern(
|
||||||
|
paths.hassio_output_root,
|
||||||
|
paths.hassio_output_latest,
|
||||||
|
"brotli"
|
||||||
|
);
|
||||||
|
const compressHassioModernZopfli = () =>
|
||||||
|
compressModern(
|
||||||
|
paths.hassio_output_root,
|
||||||
|
paths.hassio_output_latest,
|
||||||
|
"zopfli"
|
||||||
|
);
|
||||||
|
|
||||||
|
const compressAppOtherBrotli = () =>
|
||||||
|
compressOther(paths.app_output_root, paths.app_output_latest, "brotli");
|
||||||
|
const compressAppOtherZopfli = () =>
|
||||||
|
compressOther(paths.app_output_root, paths.app_output_latest, "zopfli");
|
||||||
|
|
||||||
|
const compressHassioOtherBrotli = () =>
|
||||||
|
compressOther(paths.hassio_output_root, paths.hassio_output_latest, "brotli");
|
||||||
|
const compressHassioOtherZopfli = () =>
|
||||||
|
compressOther(paths.hassio_output_root, paths.hassio_output_latest, "zopfli");
|
||||||
|
|
||||||
|
gulp.task(
|
||||||
|
"compress-app",
|
||||||
|
gulp.parallel(
|
||||||
|
compressAppModernBrotli,
|
||||||
|
compressAppOtherBrotli,
|
||||||
|
compressAppModernZopfli,
|
||||||
|
compressAppOtherZopfli
|
||||||
|
)
|
||||||
|
);
|
||||||
|
gulp.task(
|
||||||
|
"compress-hassio",
|
||||||
|
gulp.parallel(
|
||||||
|
compressHassioModernBrotli,
|
||||||
|
compressHassioOtherBrotli,
|
||||||
|
compressHassioModernZopfli,
|
||||||
|
compressHassioOtherZopfli
|
||||||
|
)
|
||||||
|
);
|
||||||
|
@@ -1,13 +1,11 @@
|
|||||||
import gulp from "gulp";
|
import gulp from "gulp";
|
||||||
import env from "../env.cjs";
|
|
||||||
import "./clean.js";
|
import "./clean.js";
|
||||||
import "./entry-html.js";
|
import "./entry-html.js";
|
||||||
import "./gather-static.js";
|
import "./gather-static.js";
|
||||||
import "./gen-icons-json.js";
|
import "./gen-icons-json.js";
|
||||||
import "./rollup.js";
|
|
||||||
import "./service-worker.js";
|
import "./service-worker.js";
|
||||||
import "./translations.js";
|
import "./translations.js";
|
||||||
import "./webpack.js";
|
import "./rspack.js";
|
||||||
|
|
||||||
gulp.task(
|
gulp.task(
|
||||||
"develop-demo",
|
"develop-demo",
|
||||||
@@ -24,7 +22,7 @@ gulp.task(
|
|||||||
"build-locale-data"
|
"build-locale-data"
|
||||||
),
|
),
|
||||||
"copy-static-demo",
|
"copy-static-demo",
|
||||||
env.useRollup() ? "rollup-dev-server-demo" : "webpack-dev-server-demo"
|
"rspack-dev-server-demo"
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -39,7 +37,18 @@ gulp.task(
|
|||||||
"translations-enable-merge-backend",
|
"translations-enable-merge-backend",
|
||||||
gulp.parallel("gen-icons-json", "build-translations", "build-locale-data"),
|
gulp.parallel("gen-icons-json", "build-translations", "build-locale-data"),
|
||||||
"copy-static-demo",
|
"copy-static-demo",
|
||||||
env.useRollup() ? "rollup-prod-demo" : "webpack-prod-demo",
|
"rspack-prod-demo",
|
||||||
"gen-pages-demo-prod"
|
"gen-pages-demo-prod"
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
gulp.task(
|
||||||
|
"analyze-demo",
|
||||||
|
gulp.series(
|
||||||
|
async function setEnv() {
|
||||||
|
process.env.STATS = "1";
|
||||||
|
},
|
||||||
|
"clean",
|
||||||
|
"rspack-prod-demo"
|
||||||
|
)
|
||||||
|
);
|
||||||
|
@@ -13,7 +13,7 @@ const srcMeta = "src/translations/translationMetadata.json";
|
|||||||
const encoding = "utf8";
|
const encoding = "utf8";
|
||||||
|
|
||||||
function hasHtml(data) {
|
function hasHtml(data) {
|
||||||
return /<[a-z][\s\S]*>/i.test(data);
|
return /<\S*>/i.test(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
function recursiveCheckHasHtml(file, data, errors, recKey) {
|
function recursiveCheckHasHtml(file, data, errors, recKey) {
|
||||||
@@ -127,6 +127,7 @@ gulp.task("fetch-lokalise", async function () {
|
|||||||
replace_breaks: false,
|
replace_breaks: false,
|
||||||
json_unescaped_slashes: true,
|
json_unescaped_slashes: true,
|
||||||
export_empty_as: "skip",
|
export_empty_as: "skip",
|
||||||
|
filter_data: ["verified"],
|
||||||
})
|
})
|
||||||
.then((download) => fetch(download.bundle_url))
|
.then((download) => fetch(download.bundle_url))
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
|
@@ -1,28 +1,73 @@
|
|||||||
// Tasks to generate entry HTML
|
// Tasks to generate entry HTML
|
||||||
|
|
||||||
|
import {
|
||||||
|
applyVersionsToRegexes,
|
||||||
|
compileRegex,
|
||||||
|
getPreUserAgentRegexes,
|
||||||
|
} from "browserslist-useragent-regexp";
|
||||||
import fs from "fs-extra";
|
import fs from "fs-extra";
|
||||||
import gulp from "gulp";
|
import gulp from "gulp";
|
||||||
import { minify } from "html-minifier-terser";
|
import { minify } from "html-minifier-terser";
|
||||||
import template from "lodash.template";
|
import template from "lodash.template";
|
||||||
import path from "path";
|
import { dirname, extname, resolve } from "node:path";
|
||||||
import { htmlMinifierOptions, terserOptions } from "../bundle.cjs";
|
import { htmlMinifierOptions, terserOptions } from "../bundle.cjs";
|
||||||
import env from "../env.cjs";
|
|
||||||
import paths from "../paths.cjs";
|
import paths from "../paths.cjs";
|
||||||
|
|
||||||
|
// macOS companion app has no way to obtain the Safari version used by WKWebView,
|
||||||
|
// and it is not in the default user agent string. So we add an additional regex
|
||||||
|
// to serve modern based on a minimum macOS version. We take the minimum Safari
|
||||||
|
// major version from browserslist and manually map that to a supported macOS
|
||||||
|
// version. Note this assumes the user has kept Safari updated.
|
||||||
|
const HA_MACOS_REGEX =
|
||||||
|
/Home Assistant\/[\d.]+ \(.+; macOS (\d+)\.(\d+)(?:\.(\d+))?\)/;
|
||||||
|
const SAFARI_TO_MACOS = {
|
||||||
|
15: [10, 15, 0],
|
||||||
|
16: [11, 0, 0],
|
||||||
|
17: [12, 0, 0],
|
||||||
|
18: [13, 0, 0],
|
||||||
|
};
|
||||||
|
|
||||||
|
const getCommonTemplateVars = () => {
|
||||||
|
const browserRegexes = getPreUserAgentRegexes({
|
||||||
|
env: "modern",
|
||||||
|
allowHigherVersions: true,
|
||||||
|
mobileToDesktop: true,
|
||||||
|
throwOnMissing: true,
|
||||||
|
});
|
||||||
|
const minSafariVersion = browserRegexes.find(
|
||||||
|
(regex) => regex.family === "safari"
|
||||||
|
)?.matchedVersions[0][0];
|
||||||
|
const minMacOSVersion = SAFARI_TO_MACOS[minSafariVersion];
|
||||||
|
if (!minMacOSVersion) {
|
||||||
|
throw Error(
|
||||||
|
`Could not find minimum MacOS version for Safari ${minSafariVersion}.`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
const haMacOSRegex = applyVersionsToRegexes(
|
||||||
|
[
|
||||||
|
{
|
||||||
|
family: "ha_macos",
|
||||||
|
regex: HA_MACOS_REGEX,
|
||||||
|
matchedVersions: [minMacOSVersion],
|
||||||
|
requestVersions: [minMacOSVersion],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
{ ignorePatch: true, allowHigherVersions: true }
|
||||||
|
);
|
||||||
|
return {
|
||||||
|
modernRegex: compileRegex(browserRegexes.concat(haMacOSRegex)).toString(),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
const renderTemplate = (templateFile, data = {}) => {
|
const renderTemplate = (templateFile, data = {}) => {
|
||||||
const compiled = template(
|
const compiled = template(
|
||||||
fs.readFileSync(templateFile, { encoding: "utf-8" })
|
fs.readFileSync(templateFile, { encoding: "utf-8" })
|
||||||
);
|
);
|
||||||
return compiled({
|
return compiled({
|
||||||
...data,
|
...data,
|
||||||
useRollup: env.useRollup(),
|
|
||||||
useWDS: env.useWDS(),
|
|
||||||
// Resolve any child/nested templates relative to the parent and pass the same data
|
// Resolve any child/nested templates relative to the parent and pass the same data
|
||||||
renderTemplate: (childTemplate) =>
|
renderTemplate: (childTemplate) =>
|
||||||
renderTemplate(
|
renderTemplate(resolve(dirname(templateFile), childTemplate), data),
|
||||||
path.resolve(path.dirname(templateFile), childTemplate),
|
|
||||||
data
|
|
||||||
),
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -45,36 +90,32 @@ const minifyHtml = (content, ext) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Function to generate a dev task for each project's configuration
|
// Function to generate a dev task for each project's configuration
|
||||||
// Note Currently WDS paths are hard-coded to only work for app
|
|
||||||
const genPagesDevTask =
|
const genPagesDevTask =
|
||||||
(
|
(
|
||||||
pageEntries,
|
pageEntries,
|
||||||
inputRoot,
|
inputRoot,
|
||||||
outputRoot,
|
outputRoot,
|
||||||
useWDS = false,
|
|
||||||
inputSub = "src/html",
|
inputSub = "src/html",
|
||||||
publicRoot = ""
|
publicRoot = ""
|
||||||
) =>
|
) =>
|
||||||
async () => {
|
async () => {
|
||||||
|
const commonVars = getCommonTemplateVars();
|
||||||
for (const [page, entries] of Object.entries(pageEntries)) {
|
for (const [page, entries] of Object.entries(pageEntries)) {
|
||||||
const content = renderTemplate(
|
const content = renderTemplate(
|
||||||
path.resolve(inputRoot, inputSub, `${page}.template`),
|
resolve(inputRoot, inputSub, `${page}.template`),
|
||||||
{
|
{
|
||||||
latestEntryJS: entries.map((entry) =>
|
...commonVars,
|
||||||
useWDS
|
latestEntryJS: entries.map(
|
||||||
? `http://localhost:8000/src/entrypoints/${entry}.ts`
|
(entry) => `${publicRoot}/frontend_latest/${entry}.js`
|
||||||
: `${publicRoot}/frontend_latest/${entry}.js`
|
|
||||||
),
|
),
|
||||||
es5EntryJS: entries.map(
|
es5EntryJS: entries.map(
|
||||||
(entry) => `${publicRoot}/frontend_es5/${entry}.js`
|
(entry) => `${publicRoot}/frontend_es5/${entry}.js`
|
||||||
),
|
),
|
||||||
latestCustomPanelJS: useWDS
|
latestCustomPanelJS: `${publicRoot}/frontend_latest/custom-panel.js`,
|
||||||
? "http://localhost:8000/src/entrypoints/custom-panel.ts"
|
|
||||||
: `${publicRoot}/frontend_latest/custom-panel.js`,
|
|
||||||
es5CustomPanelJS: `${publicRoot}/frontend_es5/custom-panel.js`,
|
es5CustomPanelJS: `${publicRoot}/frontend_es5/custom-panel.js`,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
fs.outputFileSync(path.resolve(outputRoot, page), content);
|
fs.outputFileSync(resolve(outputRoot, page), content);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -91,16 +132,18 @@ const genPagesProdTask =
|
|||||||
) =>
|
) =>
|
||||||
async () => {
|
async () => {
|
||||||
const latestManifest = fs.readJsonSync(
|
const latestManifest = fs.readJsonSync(
|
||||||
path.resolve(outputLatest, "manifest.json")
|
resolve(outputLatest, "manifest.json")
|
||||||
);
|
);
|
||||||
const es5Manifest = outputES5
|
const es5Manifest = outputES5
|
||||||
? fs.readJsonSync(path.resolve(outputES5, "manifest.json"))
|
? fs.readJsonSync(resolve(outputES5, "manifest.json"))
|
||||||
: {};
|
: {};
|
||||||
|
const commonVars = getCommonTemplateVars();
|
||||||
const minifiedHTML = [];
|
const minifiedHTML = [];
|
||||||
for (const [page, entries] of Object.entries(pageEntries)) {
|
for (const [page, entries] of Object.entries(pageEntries)) {
|
||||||
const content = renderTemplate(
|
const content = renderTemplate(
|
||||||
path.resolve(inputRoot, inputSub, `${page}.template`),
|
resolve(inputRoot, inputSub, `${page}.template`),
|
||||||
{
|
{
|
||||||
|
...commonVars,
|
||||||
latestEntryJS: entries.map((entry) => latestManifest[`${entry}.js`]),
|
latestEntryJS: entries.map((entry) => latestManifest[`${entry}.js`]),
|
||||||
es5EntryJS: entries.map((entry) => es5Manifest[`${entry}.js`]),
|
es5EntryJS: entries.map((entry) => es5Manifest[`${entry}.js`]),
|
||||||
latestCustomPanelJS: latestManifest["custom-panel.js"],
|
latestCustomPanelJS: latestManifest["custom-panel.js"],
|
||||||
@@ -108,8 +151,8 @@ const genPagesProdTask =
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
minifiedHTML.push(
|
minifiedHTML.push(
|
||||||
minifyHtml(content, path.extname(page)).then((minified) =>
|
minifyHtml(content, extname(page)).then((minified) =>
|
||||||
fs.outputFileSync(path.resolve(outputRoot, page), minified)
|
fs.outputFileSync(resolve(outputRoot, page), minified)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -125,12 +168,7 @@ const APP_PAGE_ENTRIES = {
|
|||||||
|
|
||||||
gulp.task(
|
gulp.task(
|
||||||
"gen-pages-app-dev",
|
"gen-pages-app-dev",
|
||||||
genPagesDevTask(
|
genPagesDevTask(APP_PAGE_ENTRIES, paths.polymer_dir, paths.app_output_root)
|
||||||
APP_PAGE_ENTRIES,
|
|
||||||
paths.polymer_dir,
|
|
||||||
paths.app_output_root,
|
|
||||||
env.useWDS()
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
gulp.task(
|
gulp.task(
|
||||||
@@ -206,6 +244,28 @@ gulp.task(
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const LANDING_PAGE_PAGE_ENTRIES = { "index.html": ["entrypoint"] };
|
||||||
|
|
||||||
|
gulp.task(
|
||||||
|
"gen-pages-landing-page-dev",
|
||||||
|
genPagesDevTask(
|
||||||
|
LANDING_PAGE_PAGE_ENTRIES,
|
||||||
|
paths.landingPage_dir,
|
||||||
|
paths.landingPage_output_root
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
gulp.task(
|
||||||
|
"gen-pages-landing-page-prod",
|
||||||
|
genPagesProdTask(
|
||||||
|
LANDING_PAGE_PAGE_ENTRIES,
|
||||||
|
paths.landingPage_dir,
|
||||||
|
paths.landingPage_output_root,
|
||||||
|
paths.landingPage_output_latest,
|
||||||
|
paths.landingPage_output_es5
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
const HASSIO_PAGE_ENTRIES = { "entrypoint.js": ["entrypoint"] };
|
const HASSIO_PAGE_ENTRIES = { "entrypoint.js": ["entrypoint"] };
|
||||||
|
|
||||||
gulp.task(
|
gulp.task(
|
||||||
@@ -214,7 +274,6 @@ gulp.task(
|
|||||||
HASSIO_PAGE_ENTRIES,
|
HASSIO_PAGE_ENTRIES,
|
||||||
paths.hassio_dir,
|
paths.hassio_dir,
|
||||||
paths.hassio_output_root,
|
paths.hassio_output_root,
|
||||||
undefined,
|
|
||||||
"src",
|
"src",
|
||||||
paths.hassio_publicPath
|
paths.hassio_publicPath
|
||||||
)
|
)
|
||||||
|
@@ -66,7 +66,7 @@ gulp.task("fetch-nightly-translations", async function () {
|
|||||||
tokenAuth = JSON.parse(await readFile(TOKEN_FILE, "utf-8"));
|
tokenAuth = JSON.parse(await readFile(TOKEN_FILE, "utf-8"));
|
||||||
} catch {
|
} catch {
|
||||||
if (!allowTokenSetup) {
|
if (!allowTokenSetup) {
|
||||||
console.log("No token found so build wil continue with English only");
|
console.log("No token found so build will continue with English only");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const auth = createOAuthDeviceAuth({
|
const auth = createOAuthDeviceAuth({
|
||||||
|
@@ -4,16 +4,14 @@ import gulp from "gulp";
|
|||||||
import yaml from "js-yaml";
|
import yaml from "js-yaml";
|
||||||
import { marked } from "marked";
|
import { marked } from "marked";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
import env from "../env.cjs";
|
|
||||||
import paths from "../paths.cjs";
|
import paths from "../paths.cjs";
|
||||||
import "./clean.js";
|
import "./clean.js";
|
||||||
import "./entry-html.js";
|
import "./entry-html.js";
|
||||||
import "./gather-static.js";
|
import "./gather-static.js";
|
||||||
import "./gen-icons-json.js";
|
import "./gen-icons-json.js";
|
||||||
import "./rollup.js";
|
|
||||||
import "./service-worker.js";
|
import "./service-worker.js";
|
||||||
import "./translations.js";
|
import "./translations.js";
|
||||||
import "./webpack.js";
|
import "./rspack.js";
|
||||||
|
|
||||||
gulp.task("gather-gallery-pages", async function gatherPages() {
|
gulp.task("gather-gallery-pages", async function gatherPages() {
|
||||||
const pageDir = path.resolve(paths.gallery_dir, "src/pages");
|
const pageDir = path.resolve(paths.gallery_dir, "src/pages");
|
||||||
@@ -158,9 +156,7 @@ gulp.task(
|
|||||||
"copy-static-gallery",
|
"copy-static-gallery",
|
||||||
"gen-pages-gallery-dev",
|
"gen-pages-gallery-dev",
|
||||||
gulp.parallel(
|
gulp.parallel(
|
||||||
env.useRollup()
|
"rspack-dev-server-gallery",
|
||||||
? "rollup-dev-server-gallery"
|
|
||||||
: "webpack-dev-server-gallery",
|
|
||||||
async function watchMarkdownFiles() {
|
async function watchMarkdownFiles() {
|
||||||
gulp.watch(
|
gulp.watch(
|
||||||
[
|
[
|
||||||
@@ -189,7 +185,7 @@ gulp.task(
|
|||||||
"gather-gallery-pages"
|
"gather-gallery-pages"
|
||||||
),
|
),
|
||||||
"copy-static-gallery",
|
"copy-static-gallery",
|
||||||
env.useRollup() ? "rollup-prod-gallery" : "webpack-prod-gallery",
|
"rspack-prod-gallery",
|
||||||
"gen-pages-gallery-prod"
|
"gen-pages-gallery-prod"
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
@@ -4,7 +4,6 @@ import fs from "fs-extra";
|
|||||||
import gulp from "gulp";
|
import gulp from "gulp";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
import paths from "../paths.cjs";
|
import paths from "../paths.cjs";
|
||||||
import env from "../env.cjs";
|
|
||||||
|
|
||||||
const npmPath = (...parts) =>
|
const npmPath = (...parts) =>
|
||||||
path.resolve(paths.polymer_dir, "node_modules", ...parts);
|
path.resolve(paths.polymer_dir, "node_modules", ...parts);
|
||||||
@@ -60,15 +59,12 @@ function copyPolyfills(staticDir) {
|
|||||||
npmPath("@webcomponents/webcomponentsjs/webcomponents-bundle.js.map"),
|
npmPath("@webcomponents/webcomponentsjs/webcomponents-bundle.js.map"),
|
||||||
staticPath("polyfills/")
|
staticPath("polyfills/")
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
|
||||||
function copyLoaderJS(staticDir) {
|
// dialog-polyfill css
|
||||||
if (!env.useRollup()) {
|
copyFileDir(
|
||||||
return;
|
npmPath("dialog-polyfill/dialog-polyfill.css"),
|
||||||
}
|
staticPath("polyfills/")
|
||||||
const staticPath = genStaticPath(staticDir);
|
);
|
||||||
copyFileDir(npmPath("systemjs/dist/s.min.js"), staticPath("js"));
|
|
||||||
copyFileDir(npmPath("systemjs/dist/s.min.js.map"), staticPath("js"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function copyFonts(staticDir) {
|
function copyFonts(staticDir) {
|
||||||
@@ -100,6 +96,14 @@ function copyMapPanel(staticDir) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function copyZXingWasm(staticDir) {
|
||||||
|
const staticPath = genStaticPath(staticDir);
|
||||||
|
copyFileDir(
|
||||||
|
npmPath("zxing-wasm/dist/reader/zxing_reader.wasm"),
|
||||||
|
staticPath("js")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
gulp.task("copy-locale-data", async () => {
|
gulp.task("copy-locale-data", async () => {
|
||||||
const staticDir = paths.app_output_static;
|
const staticDir = paths.app_output_static;
|
||||||
copyLocaleData(staticDir);
|
copyLocaleData(staticDir);
|
||||||
@@ -115,6 +119,11 @@ gulp.task("copy-translations-supervisor", async () => {
|
|||||||
copyTranslations(staticDir);
|
copyTranslations(staticDir);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
gulp.task("copy-translations-landing-page", async () => {
|
||||||
|
const staticDir = paths.landingPage_output_static;
|
||||||
|
copyTranslations(staticDir);
|
||||||
|
});
|
||||||
|
|
||||||
gulp.task("copy-static-supervisor", async () => {
|
gulp.task("copy-static-supervisor", async () => {
|
||||||
const staticDir = paths.hassio_output_static;
|
const staticDir = paths.hassio_output_static;
|
||||||
copyLocaleData(staticDir);
|
copyLocaleData(staticDir);
|
||||||
@@ -125,8 +134,6 @@ gulp.task("copy-static-app", async () => {
|
|||||||
const staticDir = paths.app_output_static;
|
const staticDir = paths.app_output_static;
|
||||||
// Basic static files
|
// Basic static files
|
||||||
fs.copySync(polyPath("public"), paths.app_output_root);
|
fs.copySync(polyPath("public"), paths.app_output_root);
|
||||||
|
|
||||||
copyLoaderJS(staticDir);
|
|
||||||
copyPolyfills(staticDir);
|
copyPolyfills(staticDir);
|
||||||
copyFonts(staticDir);
|
copyFonts(staticDir);
|
||||||
copyTranslations(staticDir);
|
copyTranslations(staticDir);
|
||||||
@@ -137,6 +144,7 @@ gulp.task("copy-static-app", async () => {
|
|||||||
copyMapPanel(staticDir);
|
copyMapPanel(staticDir);
|
||||||
|
|
||||||
// Qr Scanner assets
|
// Qr Scanner assets
|
||||||
|
copyZXingWasm(staticDir);
|
||||||
copyQrScannerWorker(staticDir);
|
copyQrScannerWorker(staticDir);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -148,8 +156,6 @@ gulp.task("copy-static-demo", async () => {
|
|||||||
);
|
);
|
||||||
// Copy demo static files
|
// Copy demo static files
|
||||||
fs.copySync(path.resolve(paths.demo_dir, "public"), paths.demo_output_root);
|
fs.copySync(path.resolve(paths.demo_dir, "public"), paths.demo_output_root);
|
||||||
|
|
||||||
copyLoaderJS(paths.demo_output_static);
|
|
||||||
copyPolyfills(paths.demo_output_static);
|
copyPolyfills(paths.demo_output_static);
|
||||||
copyMapPanel(paths.demo_output_static);
|
copyMapPanel(paths.demo_output_static);
|
||||||
copyFonts(paths.demo_output_static);
|
copyFonts(paths.demo_output_static);
|
||||||
@@ -163,8 +169,6 @@ gulp.task("copy-static-cast", async () => {
|
|||||||
fs.copySync(polyPath("public/static"), paths.cast_output_static);
|
fs.copySync(polyPath("public/static"), paths.cast_output_static);
|
||||||
// Copy cast static files
|
// Copy cast static files
|
||||||
fs.copySync(path.resolve(paths.cast_dir, "public"), paths.cast_output_root);
|
fs.copySync(path.resolve(paths.cast_dir, "public"), paths.cast_output_root);
|
||||||
|
|
||||||
copyLoaderJS(paths.cast_output_static);
|
|
||||||
copyPolyfills(paths.cast_output_static);
|
copyPolyfills(paths.cast_output_static);
|
||||||
copyMapPanel(paths.cast_output_static);
|
copyMapPanel(paths.cast_output_static);
|
||||||
copyFonts(paths.cast_output_static);
|
copyFonts(paths.cast_output_static);
|
||||||
@@ -188,3 +192,14 @@ gulp.task("copy-static-gallery", async () => {
|
|||||||
copyLocaleData(paths.gallery_output_static);
|
copyLocaleData(paths.gallery_output_static);
|
||||||
copyMdiIcons(paths.gallery_output_static);
|
copyMdiIcons(paths.gallery_output_static);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
gulp.task("copy-static-landing-page", async () => {
|
||||||
|
// Copy landing-page static files
|
||||||
|
fs.copySync(
|
||||||
|
path.resolve(paths.landingPage_dir, "public"),
|
||||||
|
paths.landingPage_output_root
|
||||||
|
);
|
||||||
|
|
||||||
|
copyFonts(paths.landingPage_output_static);
|
||||||
|
copyTranslations(paths.landingPage_output_static);
|
||||||
|
});
|
||||||
|
@@ -5,9 +5,8 @@ import "./compress.js";
|
|||||||
import "./entry-html.js";
|
import "./entry-html.js";
|
||||||
import "./gather-static.js";
|
import "./gather-static.js";
|
||||||
import "./gen-icons-json.js";
|
import "./gen-icons-json.js";
|
||||||
import "./rollup.js";
|
|
||||||
import "./translations.js";
|
import "./translations.js";
|
||||||
import "./webpack.js";
|
import "./rspack.js";
|
||||||
|
|
||||||
gulp.task(
|
gulp.task(
|
||||||
"develop-hassio",
|
"develop-hassio",
|
||||||
@@ -22,7 +21,7 @@ gulp.task(
|
|||||||
"copy-translations-supervisor",
|
"copy-translations-supervisor",
|
||||||
"build-locale-data",
|
"build-locale-data",
|
||||||
"copy-static-supervisor",
|
"copy-static-supervisor",
|
||||||
env.useRollup() ? "rollup-watch-hassio" : "webpack-watch-hassio"
|
"rspack-watch-hassio"
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -38,7 +37,7 @@ gulp.task(
|
|||||||
"copy-translations-supervisor",
|
"copy-translations-supervisor",
|
||||||
"build-locale-data",
|
"build-locale-data",
|
||||||
"copy-static-supervisor",
|
"copy-static-supervisor",
|
||||||
env.useRollup() ? "rollup-prod-hassio" : "webpack-prod-hassio",
|
"rspack-prod-hassio",
|
||||||
"gen-pages-hassio-prod",
|
"gen-pages-hassio-prod",
|
||||||
...// Don't compress running tests
|
...// Don't compress running tests
|
||||||
(env.isTestBuild() ? [] : ["compress-hassio"])
|
(env.isTestBuild() ? [] : ["compress-hassio"])
|
||||||
|
17
build-scripts/gulp/index.mjs
Normal file
17
build-scripts/gulp/index.mjs
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import "./app.js";
|
||||||
|
import "./cast.js";
|
||||||
|
import "./clean.js";
|
||||||
|
import "./compress.js";
|
||||||
|
import "./demo.js";
|
||||||
|
import "./download-translations.js";
|
||||||
|
import "./entry-html.js";
|
||||||
|
import "./fetch-nightly-translations.js";
|
||||||
|
import "./gallery.js";
|
||||||
|
import "./gather-static.js";
|
||||||
|
import "./gen-icons-json.js";
|
||||||
|
import "./hassio.js";
|
||||||
|
import "./landing-page.js";
|
||||||
|
import "./locale-data.js";
|
||||||
|
import "./rspack.js";
|
||||||
|
import "./service-worker.js";
|
||||||
|
import "./translations.js";
|
41
build-scripts/gulp/landing-page.js
Normal file
41
build-scripts/gulp/landing-page.js
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
import gulp from "gulp";
|
||||||
|
import "./clean.js";
|
||||||
|
import "./compress.js";
|
||||||
|
import "./entry-html.js";
|
||||||
|
import "./gather-static.js";
|
||||||
|
import "./gen-icons-json.js";
|
||||||
|
import "./translations.js";
|
||||||
|
import "./rspack.js";
|
||||||
|
|
||||||
|
gulp.task(
|
||||||
|
"develop-landing-page",
|
||||||
|
gulp.series(
|
||||||
|
async function setEnv() {
|
||||||
|
process.env.NODE_ENV = "development";
|
||||||
|
},
|
||||||
|
"clean-landing-page",
|
||||||
|
"translations-enable-merge-backend",
|
||||||
|
"build-landing-page-translations",
|
||||||
|
"copy-translations-landing-page",
|
||||||
|
"build-locale-data",
|
||||||
|
"copy-static-landing-page",
|
||||||
|
"gen-pages-landing-page-dev",
|
||||||
|
"rspack-watch-landing-page"
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
gulp.task(
|
||||||
|
"build-landing-page",
|
||||||
|
gulp.series(
|
||||||
|
async function setEnv() {
|
||||||
|
process.env.NODE_ENV = "production";
|
||||||
|
},
|
||||||
|
"clean-landing-page",
|
||||||
|
"build-landing-page-translations",
|
||||||
|
"copy-translations-landing-page",
|
||||||
|
"build-locale-data",
|
||||||
|
"copy-static-landing-page",
|
||||||
|
"rspack-prod-landing-page",
|
||||||
|
"gen-pages-landing-page-prod"
|
||||||
|
)
|
||||||
|
);
|
@@ -24,8 +24,11 @@ const convertToJSON = async (
|
|||||||
) => {
|
) => {
|
||||||
let localeData;
|
let localeData;
|
||||||
try {
|
try {
|
||||||
|
// use "pt" for "pt-BR", because "pt-BR" is unsupported by @formatjs
|
||||||
|
const language = lang === "pt-BR" ? "pt" : lang;
|
||||||
|
|
||||||
localeData = await readFile(
|
localeData = await readFile(
|
||||||
join(formatjsDir, pkg, subDir, `${lang}.js`),
|
join(formatjsDir, pkg, subDir, `${language}.js`),
|
||||||
"utf-8"
|
"utf-8"
|
||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@@ -1,147 +0,0 @@
|
|||||||
// Tasks to run Rollup
|
|
||||||
|
|
||||||
import log from "fancy-log";
|
|
||||||
import gulp from "gulp";
|
|
||||||
import http from "http";
|
|
||||||
import open from "open";
|
|
||||||
import path from "path";
|
|
||||||
import { rollup } from "rollup";
|
|
||||||
import handler from "serve-handler";
|
|
||||||
import paths from "../paths.cjs";
|
|
||||||
import rollupConfig from "../rollup.cjs";
|
|
||||||
|
|
||||||
const bothBuilds = (createConfigFunc, params) =>
|
|
||||||
gulp.series(
|
|
||||||
async function buildLatest() {
|
|
||||||
await buildRollup(
|
|
||||||
createConfigFunc({
|
|
||||||
...params,
|
|
||||||
latestBuild: true,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
},
|
|
||||||
async function buildES5() {
|
|
||||||
await buildRollup(
|
|
||||||
createConfigFunc({
|
|
||||||
...params,
|
|
||||||
latestBuild: false,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
function createServer(serveOptions) {
|
|
||||||
const server = http.createServer((request, response) =>
|
|
||||||
handler(request, response, {
|
|
||||||
public: serveOptions.root,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
server.listen(
|
|
||||||
serveOptions.port,
|
|
||||||
serveOptions.networkAccess ? "0.0.0.0" : undefined,
|
|
||||||
() => {
|
|
||||||
log.info(`Available at http://localhost:${serveOptions.port}`);
|
|
||||||
open(`http://localhost:${serveOptions.port}`);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function watchRollup(createConfig, extraWatchSrc = [], serveOptions = null) {
|
|
||||||
const { inputOptions, outputOptions } = createConfig({
|
|
||||||
isProdBuild: false,
|
|
||||||
latestBuild: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
const watcher = rollup.watch({
|
|
||||||
...inputOptions,
|
|
||||||
output: [outputOptions],
|
|
||||||
watch: {
|
|
||||||
include: ["src/**"] + extraWatchSrc,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
let startedHttp = false;
|
|
||||||
|
|
||||||
watcher.on("event", (event) => {
|
|
||||||
if (event.code === "BUNDLE_END") {
|
|
||||||
log(`Build done @ ${new Date().toLocaleTimeString()}`);
|
|
||||||
} else if (event.code === "ERROR") {
|
|
||||||
log.error(event.error);
|
|
||||||
} else if (event.code === "END") {
|
|
||||||
if (startedHttp || !serveOptions) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
startedHttp = true;
|
|
||||||
createServer(serveOptions);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
gulp.watch(
|
|
||||||
path.join(paths.translations_src, "en.json"),
|
|
||||||
gulp.series("build-translations", "copy-translations-app")
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function buildRollup(config) {
|
|
||||||
const bundle = await rollup.rollup(config.inputOptions);
|
|
||||||
await bundle.write(config.outputOptions);
|
|
||||||
}
|
|
||||||
|
|
||||||
gulp.task("rollup-watch-app", () => {
|
|
||||||
watchRollup(rollupConfig.createAppConfig);
|
|
||||||
});
|
|
||||||
|
|
||||||
gulp.task("rollup-watch-hassio", () => {
|
|
||||||
watchRollup(rollupConfig.createHassioConfig, ["hassio/src/**"]);
|
|
||||||
});
|
|
||||||
|
|
||||||
gulp.task("rollup-dev-server-demo", () => {
|
|
||||||
watchRollup(rollupConfig.createDemoConfig, ["demo/src/**"], {
|
|
||||||
root: paths.demo_output_root,
|
|
||||||
port: 8090,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
gulp.task("rollup-dev-server-cast", () => {
|
|
||||||
watchRollup(rollupConfig.createCastConfig, ["cast/src/**"], {
|
|
||||||
root: paths.cast_output_root,
|
|
||||||
port: 8080,
|
|
||||||
networkAccess: true,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
gulp.task("rollup-dev-server-gallery", () => {
|
|
||||||
watchRollup(rollupConfig.createGalleryConfig, ["gallery/src/**"], {
|
|
||||||
root: paths.gallery_output_root,
|
|
||||||
port: 8100,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
gulp.task(
|
|
||||||
"rollup-prod-app",
|
|
||||||
bothBuilds(rollupConfig.createAppConfig, { isProdBuild: true })
|
|
||||||
);
|
|
||||||
|
|
||||||
gulp.task(
|
|
||||||
"rollup-prod-demo",
|
|
||||||
bothBuilds(rollupConfig.createDemoConfig, { isProdBuild: true })
|
|
||||||
);
|
|
||||||
|
|
||||||
gulp.task(
|
|
||||||
"rollup-prod-cast",
|
|
||||||
bothBuilds(rollupConfig.createCastConfig, { isProdBuild: true })
|
|
||||||
);
|
|
||||||
|
|
||||||
gulp.task("rollup-prod-hassio", () =>
|
|
||||||
bothBuilds(rollupConfig.createHassioConfig, { isProdBuild: true })
|
|
||||||
);
|
|
||||||
|
|
||||||
gulp.task("rollup-prod-gallery", () =>
|
|
||||||
buildRollup(
|
|
||||||
rollupConfig.createGalleryConfig({
|
|
||||||
isProdBuild: true,
|
|
||||||
latestBuild: true,
|
|
||||||
})
|
|
||||||
)
|
|
||||||
);
|
|
@@ -1,11 +1,11 @@
|
|||||||
// Tasks to run webpack.
|
// Tasks to run rspack.
|
||||||
|
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
import log from "fancy-log";
|
import log from "fancy-log";
|
||||||
import gulp from "gulp";
|
import gulp from "gulp";
|
||||||
import webpack from "webpack";
|
import rspack from "@rspack/core";
|
||||||
import WebpackDevServer from "webpack-dev-server";
|
import { RspackDevServer } from "@rspack/dev-server";
|
||||||
import env from "../env.cjs";
|
import env from "../env.cjs";
|
||||||
import paths from "../paths.cjs";
|
import paths from "../paths.cjs";
|
||||||
import {
|
import {
|
||||||
@@ -14,7 +14,8 @@ import {
|
|||||||
createDemoConfig,
|
createDemoConfig,
|
||||||
createGalleryConfig,
|
createGalleryConfig,
|
||||||
createHassioConfig,
|
createHassioConfig,
|
||||||
} from "../webpack.cjs";
|
createLandingPageConfig,
|
||||||
|
} from "../rspack.cjs";
|
||||||
|
|
||||||
const bothBuilds = (createConfigFunc, params) => [
|
const bothBuilds = (createConfigFunc, params) => [
|
||||||
createConfigFunc({ ...params, latestBuild: true }),
|
createConfigFunc({ ...params, latestBuild: true }),
|
||||||
@@ -30,7 +31,7 @@ const isWsl =
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {{
|
* @param {{
|
||||||
* compiler: import("webpack").Compiler,
|
* compiler: import("@rspack/core").Compiler,
|
||||||
* contentBase: string,
|
* contentBase: string,
|
||||||
* port: number,
|
* port: number,
|
||||||
* listenHost?: string
|
* listenHost?: string
|
||||||
@@ -40,9 +41,14 @@ const runDevServer = async ({
|
|||||||
compiler,
|
compiler,
|
||||||
contentBase,
|
contentBase,
|
||||||
port,
|
port,
|
||||||
listenHost = "localhost",
|
listenHost = undefined,
|
||||||
|
proxy = undefined,
|
||||||
}) => {
|
}) => {
|
||||||
const server = new WebpackDevServer(
|
if (listenHost === undefined) {
|
||||||
|
// For dev container, we need to listen on all hosts
|
||||||
|
listenHost = env.isDevContainer() ? "0.0.0.0" : "localhost";
|
||||||
|
}
|
||||||
|
const server = new RspackDevServer(
|
||||||
{
|
{
|
||||||
hot: false,
|
hot: false,
|
||||||
open: true,
|
open: true,
|
||||||
@@ -52,13 +58,14 @@ const runDevServer = async ({
|
|||||||
directory: contentBase,
|
directory: contentBase,
|
||||||
watch: true,
|
watch: true,
|
||||||
},
|
},
|
||||||
|
proxy,
|
||||||
},
|
},
|
||||||
compiler
|
compiler
|
||||||
);
|
);
|
||||||
|
|
||||||
await server.start();
|
await server.start();
|
||||||
// Server listening
|
// Server listening
|
||||||
log("[webpack-dev-server]", `Project is running at http://localhost:${port}`);
|
log("[rspack-dev-server]", `Project is running at http://localhost:${port}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
const doneHandler = (done) => (err, stats) => {
|
const doneHandler = (done) => (err, stats) => {
|
||||||
@@ -83,16 +90,16 @@ const doneHandler = (done) => (err, stats) => {
|
|||||||
|
|
||||||
const prodBuild = (conf) =>
|
const prodBuild = (conf) =>
|
||||||
new Promise((resolve) => {
|
new Promise((resolve) => {
|
||||||
webpack(
|
rspack(
|
||||||
conf,
|
conf,
|
||||||
// Resolve promise when done. Because we pass a callback, webpack closes itself
|
// Resolve promise when done. Because we pass a callback, rspack closes itself
|
||||||
doneHandler(resolve)
|
doneHandler(resolve)
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task("webpack-watch-app", () => {
|
gulp.task("rspack-watch-app", () => {
|
||||||
// This command will run forever because we don't close compiler
|
// This command will run forever because we don't close compiler
|
||||||
webpack(
|
rspack(
|
||||||
process.env.ES5
|
process.env.ES5
|
||||||
? bothBuilds(createAppConfig, { isProdBuild: false })
|
? bothBuilds(createAppConfig, { isProdBuild: false })
|
||||||
: createAppConfig({ isProdBuild: false, latestBuild: true })
|
: createAppConfig({ isProdBuild: false, latestBuild: true })
|
||||||
@@ -103,7 +110,7 @@ gulp.task("webpack-watch-app", () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task("webpack-prod-app", () =>
|
gulp.task("rspack-prod-app", () =>
|
||||||
prodBuild(
|
prodBuild(
|
||||||
bothBuilds(createAppConfig, {
|
bothBuilds(createAppConfig, {
|
||||||
isProdBuild: true,
|
isProdBuild: true,
|
||||||
@@ -113,9 +120,9 @@ gulp.task("webpack-prod-app", () =>
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
gulp.task("webpack-dev-server-demo", () =>
|
gulp.task("rspack-dev-server-demo", () =>
|
||||||
runDevServer({
|
runDevServer({
|
||||||
compiler: webpack(
|
compiler: rspack(
|
||||||
createDemoConfig({ isProdBuild: false, latestBuild: true })
|
createDemoConfig({ isProdBuild: false, latestBuild: true })
|
||||||
),
|
),
|
||||||
contentBase: paths.demo_output_root,
|
contentBase: paths.demo_output_root,
|
||||||
@@ -123,17 +130,18 @@ gulp.task("webpack-dev-server-demo", () =>
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
gulp.task("webpack-prod-demo", () =>
|
gulp.task("rspack-prod-demo", () =>
|
||||||
prodBuild(
|
prodBuild(
|
||||||
bothBuilds(createDemoConfig, {
|
bothBuilds(createDemoConfig, {
|
||||||
isProdBuild: true,
|
isProdBuild: true,
|
||||||
|
isStatsBuild: env.isStatsBuild(),
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
gulp.task("webpack-dev-server-cast", () =>
|
gulp.task("rspack-dev-server-cast", () =>
|
||||||
runDevServer({
|
runDevServer({
|
||||||
compiler: webpack(
|
compiler: rspack(
|
||||||
createCastConfig({ isProdBuild: false, latestBuild: true })
|
createCastConfig({ isProdBuild: false, latestBuild: true })
|
||||||
),
|
),
|
||||||
contentBase: paths.cast_output_root,
|
contentBase: paths.cast_output_root,
|
||||||
@@ -143,7 +151,7 @@ gulp.task("webpack-dev-server-cast", () =>
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
gulp.task("webpack-prod-cast", () =>
|
gulp.task("rspack-prod-cast", () =>
|
||||||
prodBuild(
|
prodBuild(
|
||||||
bothBuilds(createCastConfig, {
|
bothBuilds(createCastConfig, {
|
||||||
isProdBuild: true,
|
isProdBuild: true,
|
||||||
@@ -151,9 +159,9 @@ gulp.task("webpack-prod-cast", () =>
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
gulp.task("webpack-watch-hassio", () => {
|
gulp.task("rspack-watch-hassio", () => {
|
||||||
// This command will run forever because we don't close compiler
|
// This command will run forever because we don't close compiler
|
||||||
webpack(
|
rspack(
|
||||||
createHassioConfig({
|
createHassioConfig({
|
||||||
isProdBuild: false,
|
isProdBuild: false,
|
||||||
latestBuild: true,
|
latestBuild: true,
|
||||||
@@ -166,7 +174,7 @@ gulp.task("webpack-watch-hassio", () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task("webpack-prod-hassio", () =>
|
gulp.task("rspack-prod-hassio", () =>
|
||||||
prodBuild(
|
prodBuild(
|
||||||
bothBuilds(createHassioConfig, {
|
bothBuilds(createHassioConfig, {
|
||||||
isProdBuild: true,
|
isProdBuild: true,
|
||||||
@@ -176,9 +184,9 @@ gulp.task("webpack-prod-hassio", () =>
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
gulp.task("webpack-dev-server-gallery", () =>
|
gulp.task("rspack-dev-server-gallery", () =>
|
||||||
runDevServer({
|
runDevServer({
|
||||||
compiler: webpack(
|
compiler: rspack(
|
||||||
createGalleryConfig({ isProdBuild: false, latestBuild: true })
|
createGalleryConfig({ isProdBuild: false, latestBuild: true })
|
||||||
),
|
),
|
||||||
contentBase: paths.gallery_output_root,
|
contentBase: paths.gallery_output_root,
|
||||||
@@ -187,7 +195,7 @@ gulp.task("webpack-dev-server-gallery", () =>
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
gulp.task("webpack-prod-gallery", () =>
|
gulp.task("rspack-prod-gallery", () =>
|
||||||
prodBuild(
|
prodBuild(
|
||||||
createGalleryConfig({
|
createGalleryConfig({
|
||||||
isProdBuild: true,
|
isProdBuild: true,
|
||||||
@@ -195,3 +203,30 @@ gulp.task("webpack-prod-gallery", () =>
|
|||||||
})
|
})
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
gulp.task("rspack-watch-landing-page", () => {
|
||||||
|
// This command will run forever because we don't close compiler
|
||||||
|
rspack(
|
||||||
|
process.env.ES5
|
||||||
|
? bothBuilds(createLandingPageConfig, { isProdBuild: false })
|
||||||
|
: createLandingPageConfig({ isProdBuild: false, latestBuild: true })
|
||||||
|
).watch({ poll: isWsl }, doneHandler());
|
||||||
|
|
||||||
|
gulp.watch(
|
||||||
|
path.join(paths.translations_src, "en.json"),
|
||||||
|
gulp.series(
|
||||||
|
"build-landing-page-translations",
|
||||||
|
"copy-translations-landing-page"
|
||||||
|
)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
gulp.task("rspack-prod-landing-page", () =>
|
||||||
|
prodBuild(
|
||||||
|
bothBuilds(createLandingPageConfig, {
|
||||||
|
isProdBuild: true,
|
||||||
|
isStatsBuild: env.isStatsBuild(),
|
||||||
|
isTestBuild: env.isTestBuild(),
|
||||||
|
})
|
||||||
|
)
|
||||||
|
);
|
@@ -1,20 +1,19 @@
|
|||||||
// Generate service worker.
|
// Generate service workers
|
||||||
// Based on manifest, create a file with the content as service_worker.js
|
|
||||||
|
|
||||||
import fs from "fs-extra";
|
import { deleteAsync } from "del";
|
||||||
import gulp from "gulp";
|
import gulp from "gulp";
|
||||||
import path from "path";
|
import { mkdir, readFile, symlink, writeFile } from "node:fs/promises";
|
||||||
import sourceMapUrl from "source-map-url";
|
import { basename, join, relative } from "node:path";
|
||||||
import workboxBuild from "workbox-build";
|
import { injectManifest } from "workbox-build";
|
||||||
import paths from "../paths.cjs";
|
import paths from "../paths.cjs";
|
||||||
|
|
||||||
const swDest = path.resolve(paths.app_output_root, "service_worker.js");
|
const SW_MAP = {
|
||||||
|
[paths.app_output_latest]: "modern",
|
||||||
|
[paths.app_output_es5]: "legacy",
|
||||||
|
};
|
||||||
|
|
||||||
const writeSW = (content) => fs.outputFileSync(swDest, content.trim() + "\n");
|
const SW_DEV =
|
||||||
|
`
|
||||||
gulp.task("gen-service-worker-app-dev", (done) => {
|
|
||||||
writeSW(
|
|
||||||
`
|
|
||||||
console.debug('Service worker disabled in development');
|
console.debug('Service worker disabled in development');
|
||||||
|
|
||||||
self.addEventListener('install', (event) => {
|
self.addEventListener('install', (event) => {
|
||||||
@@ -22,72 +21,67 @@ self.addEventListener('install', (event) => {
|
|||||||
// removing any prod service worker the dev might have running
|
// removing any prod service worker the dev might have running
|
||||||
self.skipWaiting();
|
self.skipWaiting();
|
||||||
});
|
});
|
||||||
`
|
`.trim() + "\n";
|
||||||
|
|
||||||
|
gulp.task("gen-service-worker-app-dev", async () => {
|
||||||
|
await mkdir(paths.app_output_root, { recursive: true });
|
||||||
|
await Promise.all(
|
||||||
|
Object.values(SW_MAP).map((build) =>
|
||||||
|
writeFile(join(paths.app_output_root, `sw-${build}.js`), SW_DEV, {
|
||||||
|
encoding: "utf-8",
|
||||||
|
})
|
||||||
|
)
|
||||||
);
|
);
|
||||||
done();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task("gen-service-worker-app-prod", async () => {
|
gulp.task("gen-service-worker-app-prod", () =>
|
||||||
// Read bundled source file
|
Promise.all(
|
||||||
const bundleManifestLatest = fs.readJsonSync(
|
Object.entries(SW_MAP).map(async ([outPath, build]) => {
|
||||||
path.resolve(paths.app_output_latest, "manifest.json")
|
const manifest = JSON.parse(
|
||||||
);
|
await readFile(join(outPath, "manifest.json"), "utf-8")
|
||||||
let serviceWorkerContent = fs.readFileSync(
|
);
|
||||||
paths.app_output_root + bundleManifestLatest["service_worker.js"],
|
const swSrc = join(paths.app_output_root, manifest["service-worker.js"]);
|
||||||
"utf-8"
|
const swDest = join(paths.app_output_root, `sw-${build}.js`);
|
||||||
);
|
const buildDir = relative(paths.app_output_root, outPath);
|
||||||
|
const { warnings } = await injectManifest({
|
||||||
// Delete old file from frontend_latest so manifest won't pick it up
|
swSrc,
|
||||||
fs.removeSync(
|
swDest,
|
||||||
paths.app_output_root + bundleManifestLatest["service_worker.js"]
|
injectionPoint: "__WB_MANIFEST__",
|
||||||
);
|
// Files that mach this pattern will be considered unique and skip revision check
|
||||||
fs.removeSync(
|
// ignore JS files + translation files
|
||||||
paths.app_output_root + bundleManifestLatest["service_worker.js.map"]
|
dontCacheBustURLsMatching: new RegExp(
|
||||||
);
|
`(?:${buildDir}/.+|static/translations/.+)`
|
||||||
|
),
|
||||||
// Remove ES5
|
globDirectory: paths.app_output_root,
|
||||||
const bundleManifestES5 = fs.readJsonSync(
|
globPatterns: [
|
||||||
path.resolve(paths.app_output_es5, "manifest.json")
|
`${buildDir}/*.js`,
|
||||||
);
|
// Cache all English translations because we catch them as fallback
|
||||||
fs.removeSync(paths.app_output_root + bundleManifestES5["service_worker.js"]);
|
// Using pattern to match hash instead of * to avoid caching en-GB
|
||||||
fs.removeSync(
|
// 'v' added as valid hash letter because in dev we hash with 'dev'
|
||||||
paths.app_output_root + bundleManifestES5["service_worker.js.map"]
|
"static/translations/**/en-+([a-fv0-9]).json",
|
||||||
);
|
// Icon shown on splash screen
|
||||||
|
"static/icons/favicon-192x192.png",
|
||||||
const workboxManifest = await workboxBuild.getManifest({
|
"static/icons/favicon.ico",
|
||||||
// Files that mach this pattern will be considered unique and skip revision check
|
// Common fonts
|
||||||
// ignore JS files + translation files
|
"static/fonts/roboto/Roboto-Light.woff2",
|
||||||
dontCacheBustURLsMatching: /(frontend_latest\/.+|static\/translations\/.+)/,
|
"static/fonts/roboto/Roboto-Medium.woff2",
|
||||||
|
"static/fonts/roboto/Roboto-Regular.woff2",
|
||||||
globDirectory: paths.app_output_root,
|
"static/fonts/roboto/Roboto-Bold.woff2",
|
||||||
globPatterns: [
|
],
|
||||||
"frontend_latest/*.js",
|
globIgnores: [`${buildDir}/service-worker*`],
|
||||||
// Cache all English translations because we catch them as fallback
|
});
|
||||||
// Using pattern to match hash instead of * to avoid caching en-GB
|
if (warnings.length > 0) {
|
||||||
// 'v' added as valid hash letter because in dev we hash with 'dev'
|
console.warn(
|
||||||
"static/translations/**/en-+([a-fv0-9]).json",
|
`Problems while injecting ${build} service worker:\n`,
|
||||||
// Icon shown on splash screen
|
warnings.join("\n")
|
||||||
"static/icons/favicon-192x192.png",
|
);
|
||||||
"static/icons/favicon.ico",
|
}
|
||||||
// Common fonts
|
await deleteAsync(`${swSrc}?(.map)`);
|
||||||
"static/fonts/roboto/Roboto-Light.woff2",
|
// Needed to install new SW from a cached HTML
|
||||||
"static/fonts/roboto/Roboto-Medium.woff2",
|
if (build === "modern") {
|
||||||
"static/fonts/roboto/Roboto-Regular.woff2",
|
const swOld = join(paths.app_output_root, "service_worker.js");
|
||||||
"static/fonts/roboto/Roboto-Bold.woff2",
|
await symlink(basename(swDest), swOld);
|
||||||
],
|
}
|
||||||
});
|
})
|
||||||
|
)
|
||||||
for (const warning of workboxManifest.warnings) {
|
);
|
||||||
console.warn(warning);
|
|
||||||
}
|
|
||||||
|
|
||||||
// remove source map and add WB manifest
|
|
||||||
serviceWorkerContent = sourceMapUrl.removeFrom(serviceWorkerContent);
|
|
||||||
serviceWorkerContent = serviceWorkerContent.replace(
|
|
||||||
"WB_MANIFEST",
|
|
||||||
JSON.stringify(workboxManifest.manifestEntries)
|
|
||||||
);
|
|
||||||
|
|
||||||
// Write new file to root
|
|
||||||
fs.writeFileSync(swDest, serviceWorkerContent);
|
|
||||||
});
|
|
||||||
|
@@ -1,12 +1,14 @@
|
|||||||
|
/* eslint-disable max-classes-per-file */
|
||||||
|
|
||||||
import { deleteAsync } from "del";
|
import { deleteAsync } from "del";
|
||||||
import { glob } from "glob";
|
import { glob } from "glob";
|
||||||
import gulp from "gulp";
|
import gulp from "gulp";
|
||||||
import merge from "gulp-merge-json";
|
|
||||||
import rename from "gulp-rename";
|
import rename from "gulp-rename";
|
||||||
|
import merge from "lodash.merge";
|
||||||
import { createHash } from "node:crypto";
|
import { createHash } from "node:crypto";
|
||||||
import { mkdir, readFile } from "node:fs/promises";
|
import { mkdir, readFile } from "node:fs/promises";
|
||||||
import { basename, join } from "node:path";
|
import { basename, join } from "node:path";
|
||||||
import { Transform } from "node:stream";
|
import { PassThrough, Transform } from "node:stream";
|
||||||
import { finished } from "node:stream/promises";
|
import { finished } from "node:stream/promises";
|
||||||
import env from "../env.cjs";
|
import env from "../env.cjs";
|
||||||
import paths from "../paths.cjs";
|
import paths from "../paths.cjs";
|
||||||
@@ -17,6 +19,7 @@ const inBackendDir = "translations/backend";
|
|||||||
const workDir = "build/translations";
|
const workDir = "build/translations";
|
||||||
const outDir = join(workDir, "output");
|
const outDir = join(workDir, "output");
|
||||||
const EN_SRC = join(paths.translations_src, "en.json");
|
const EN_SRC = join(paths.translations_src, "en.json");
|
||||||
|
const TEST_LOCALE = "en-x-test";
|
||||||
|
|
||||||
let mergeBackend = false;
|
let mergeBackend = false;
|
||||||
|
|
||||||
@@ -54,6 +57,39 @@ class CustomJSON extends Transform {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Transform stream to merge Vinyl JSON files (buffer mode only).
|
||||||
|
class MergeJSON extends Transform {
|
||||||
|
_objects = [];
|
||||||
|
|
||||||
|
constructor(stem, startObj = {}, reviver = null) {
|
||||||
|
super({ objectMode: true, allowHalfOpen: false });
|
||||||
|
this._stem = stem;
|
||||||
|
this._startObj = structuredClone(startObj);
|
||||||
|
this._reviver = reviver;
|
||||||
|
}
|
||||||
|
|
||||||
|
async _transform(file, _, callback) {
|
||||||
|
try {
|
||||||
|
this._objects.push(JSON.parse(file.contents.toString(), this._reviver));
|
||||||
|
if (!this._outFile) this._outFile = file.clone({ contents: false });
|
||||||
|
callback(null);
|
||||||
|
} catch (err) {
|
||||||
|
callback(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async _flush(callback) {
|
||||||
|
try {
|
||||||
|
const mergedObj = merge(this._startObj, ...this._objects);
|
||||||
|
this._outFile.contents = Buffer.from(JSON.stringify(mergedObj));
|
||||||
|
this._outFile.stem = this._stem;
|
||||||
|
callback(null, this._outFile);
|
||||||
|
} catch (err) {
|
||||||
|
callback(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Utility to flatten object keys to single level using separator
|
// Utility to flatten object keys to single level using separator
|
||||||
const flatten = (data, prefix = "", sep = ".") => {
|
const flatten = (data, prefix = "", sep = ".") => {
|
||||||
const output = {};
|
const output = {};
|
||||||
@@ -115,7 +151,7 @@ const createTestTranslation = () =>
|
|||||||
: gulp
|
: gulp
|
||||||
.src(EN_SRC)
|
.src(EN_SRC)
|
||||||
.pipe(new CustomJSON(null, testReviver))
|
.pipe(new CustomJSON(null, testReviver))
|
||||||
.pipe(rename("test.json"))
|
.pipe(rename(`${TEST_LOCALE}.json`))
|
||||||
.pipe(gulp.dest(workDir));
|
.pipe(gulp.dest(workDir));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -131,22 +167,19 @@ const createMasterTranslation = () =>
|
|||||||
gulp
|
gulp
|
||||||
.src([EN_SRC, ...(mergeBackend ? [`${inBackendDir}/en.json`] : [])])
|
.src([EN_SRC, ...(mergeBackend ? [`${inBackendDir}/en.json`] : [])])
|
||||||
.pipe(new CustomJSON(lokaliseTransform))
|
.pipe(new CustomJSON(lokaliseTransform))
|
||||||
.pipe(
|
.pipe(new MergeJSON("en"))
|
||||||
merge({
|
|
||||||
fileName: "en.json",
|
|
||||||
jsonSpace: undefined,
|
|
||||||
})
|
|
||||||
)
|
|
||||||
.pipe(gulp.dest(workDir));
|
.pipe(gulp.dest(workDir));
|
||||||
|
|
||||||
const FRAGMENTS = ["base"];
|
const FRAGMENTS = ["base"];
|
||||||
|
|
||||||
const toggleSupervisorFragment = async () => {
|
const setFragment = (fragment) => async () => {
|
||||||
FRAGMENTS[0] = "supervisor";
|
FRAGMENTS[0] = fragment;
|
||||||
};
|
};
|
||||||
|
|
||||||
const panelFragment = (fragment) =>
|
const panelFragment = (fragment) =>
|
||||||
fragment !== "base" && fragment !== "supervisor";
|
fragment !== "base" &&
|
||||||
|
fragment !== "supervisor" &&
|
||||||
|
fragment !== "landing-page";
|
||||||
|
|
||||||
const HASHES = new Map();
|
const HASHES = new Map();
|
||||||
|
|
||||||
@@ -162,7 +195,7 @@ const createTranslations = async () => {
|
|||||||
// each locale, then fragmentizes and flattens the data for final output.
|
// each locale, then fragmentizes and flattens the data for final output.
|
||||||
const translationFiles = await glob([
|
const translationFiles = await glob([
|
||||||
`${inFrontendDir}/!(en).json`,
|
`${inFrontendDir}/!(en).json`,
|
||||||
...(env.isProdBuild() ? [] : [`${workDir}/test.json`]),
|
...(env.isProdBuild() ? [] : [`${workDir}/${TEST_LOCALE}.json`]),
|
||||||
]);
|
]);
|
||||||
const hashStream = new Transform({
|
const hashStream = new Transform({
|
||||||
objectMode: true,
|
objectMode: true,
|
||||||
@@ -193,6 +226,9 @@ const createTranslations = async () => {
|
|||||||
case "supervisor":
|
case "supervisor":
|
||||||
// Supervisor key is at the top level
|
// Supervisor key is at the top level
|
||||||
return [flatten(data.supervisor), ""];
|
return [flatten(data.supervisor), ""];
|
||||||
|
case "landing-page":
|
||||||
|
// landing-page key is at the top level
|
||||||
|
return [flatten(data["landing-page"]), ""];
|
||||||
default:
|
default:
|
||||||
// Create a fragment with only the given panel
|
// Create a fragment with only the given panel
|
||||||
return [
|
return [
|
||||||
@@ -213,16 +249,19 @@ const createTranslations = async () => {
|
|||||||
// TODO: This is a naive interpretation of BCP47 that should be improved.
|
// TODO: This is a naive interpretation of BCP47 that should be improved.
|
||||||
// Will be OK for now as long as we don't have anything more complicated
|
// Will be OK for now as long as we don't have anything more complicated
|
||||||
// than a base translation + region.
|
// than a base translation + region.
|
||||||
gulp.src(`${workDir}/en.json`).pipe(hashStream, { end: false });
|
const masterStream = gulp
|
||||||
const mergesFinished = [];
|
.src(`${workDir}/en.json`)
|
||||||
|
.pipe(new PassThrough({ objectMode: true }));
|
||||||
|
masterStream.pipe(hashStream, { end: false });
|
||||||
|
const mergesFinished = [finished(masterStream)];
|
||||||
for (const translationFile of translationFiles) {
|
for (const translationFile of translationFiles) {
|
||||||
const locale = basename(translationFile, ".json");
|
const locale = basename(translationFile, ".json");
|
||||||
const subtags = locale.split("-");
|
const subtags = locale.split("-");
|
||||||
const mergeFiles = [];
|
const mergeFiles = [];
|
||||||
for (let i = 1; i <= subtags.length; i++) {
|
for (let i = 1; i <= subtags.length; i++) {
|
||||||
const lang = subtags.slice(0, i).join("-");
|
const lang = subtags.slice(0, i).join("-");
|
||||||
if (lang === "test") {
|
if (lang === TEST_LOCALE) {
|
||||||
mergeFiles.push(`${workDir}/test.json`);
|
mergeFiles.push(`${workDir}/${TEST_LOCALE}.json`);
|
||||||
} else if (lang !== "en") {
|
} else if (lang !== "en") {
|
||||||
mergeFiles.push(`${inFrontendDir}/${lang}.json`);
|
mergeFiles.push(`${inFrontendDir}/${lang}.json`);
|
||||||
if (mergeBackend) {
|
if (mergeBackend) {
|
||||||
@@ -230,14 +269,9 @@ const createTranslations = async () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const mergeStream = gulp.src(mergeFiles, { allowEmpty: true }).pipe(
|
const mergeStream = gulp
|
||||||
merge({
|
.src(mergeFiles, { allowEmpty: true })
|
||||||
fileName: `${locale}.json`,
|
.pipe(new MergeJSON(locale, enMaster, emptyReviver));
|
||||||
startObj: enMaster,
|
|
||||||
jsonReviver: emptyReviver,
|
|
||||||
jsonSpace: undefined,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
mergesFinished.push(finished(mergeStream));
|
mergesFinished.push(finished(mergeStream));
|
||||||
mergeStream.pipe(hashStream, { end: false });
|
mergeStream.pipe(hashStream, { end: false });
|
||||||
}
|
}
|
||||||
@@ -256,7 +290,7 @@ const writeTranslationMetaData = () =>
|
|||||||
new CustomJSON((meta) => {
|
new CustomJSON((meta) => {
|
||||||
// Add the test translation in development.
|
// Add the test translation in development.
|
||||||
if (!env.isProdBuild()) {
|
if (!env.isProdBuild()) {
|
||||||
meta.test = { nativeName: "Test" };
|
meta[TEST_LOCALE] = { nativeName: "Translation Test" };
|
||||||
}
|
}
|
||||||
// Filter out locales without a native name, and add the hashes.
|
// Filter out locales without a native name, and add the hashes.
|
||||||
for (const locale of Object.keys(meta)) {
|
for (const locale of Object.keys(meta)) {
|
||||||
@@ -293,5 +327,10 @@ gulp.task(
|
|||||||
|
|
||||||
gulp.task(
|
gulp.task(
|
||||||
"build-supervisor-translations",
|
"build-supervisor-translations",
|
||||||
gulp.series(toggleSupervisorFragment, "build-translations")
|
gulp.series(setFragment("supervisor"), "build-translations")
|
||||||
|
);
|
||||||
|
|
||||||
|
gulp.task(
|
||||||
|
"build-landing-page-translations",
|
||||||
|
gulp.series(setFragment("landing-page"), "build-translations")
|
||||||
);
|
);
|
||||||
|
@@ -1,10 +0,0 @@
|
|||||||
import gulp from "gulp";
|
|
||||||
import { startDevServer } from "@web/dev-server";
|
|
||||||
|
|
||||||
gulp.task("wds-watch-app", async () => {
|
|
||||||
startDevServer({
|
|
||||||
config: {
|
|
||||||
watch: true,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
@@ -33,6 +33,22 @@ module.exports = {
|
|||||||
),
|
),
|
||||||
gallery_output_static: path.resolve(__dirname, "../gallery/dist/static"),
|
gallery_output_static: path.resolve(__dirname, "../gallery/dist/static"),
|
||||||
|
|
||||||
|
landingPage_dir: path.resolve(__dirname, "../landing-page"),
|
||||||
|
landingPage_build: path.resolve(__dirname, "../landing-page/build"),
|
||||||
|
landingPage_output_root: path.resolve(__dirname, "../landing-page/dist"),
|
||||||
|
landingPage_output_latest: path.resolve(
|
||||||
|
__dirname,
|
||||||
|
"../landing-page/dist/frontend_latest"
|
||||||
|
),
|
||||||
|
landingPage_output_es5: path.resolve(
|
||||||
|
__dirname,
|
||||||
|
"../landing-page/dist/frontend_es5"
|
||||||
|
),
|
||||||
|
landingPage_output_static: path.resolve(
|
||||||
|
__dirname,
|
||||||
|
"../landing-page/dist/static"
|
||||||
|
),
|
||||||
|
|
||||||
hassio_dir: path.resolve(__dirname, "../hassio"),
|
hassio_dir: path.resolve(__dirname, "../hassio"),
|
||||||
hassio_output_root: path.resolve(__dirname, "../hassio/build"),
|
hassio_output_root: path.resolve(__dirname, "../hassio/build"),
|
||||||
hassio_output_static: path.resolve(__dirname, "../hassio/build/static"),
|
hassio_output_static: path.resolve(__dirname, "../hassio/build/static"),
|
||||||
|
@@ -1,14 +0,0 @@
|
|||||||
module.exports = function (opts = {}) {
|
|
||||||
const dontHash = opts.dontHash || new Set();
|
|
||||||
|
|
||||||
return {
|
|
||||||
name: "dont-hash",
|
|
||||||
renderChunk(_code, chunk, _options) {
|
|
||||||
if (!chunk.isEntry || !dontHash.has(chunk.name)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
chunk.fileName = `${chunk.name}.js`;
|
|
||||||
return null;
|
|
||||||
},
|
|
||||||
};
|
|
||||||
};
|
|
@@ -1,24 +0,0 @@
|
|||||||
module.exports = function (userOptions = {}) {
|
|
||||||
// Files need to be absolute paths.
|
|
||||||
// This only works if the file has no exports
|
|
||||||
// and only is imported for its side effects
|
|
||||||
const files = userOptions.files || [];
|
|
||||||
|
|
||||||
if (files.length === 0) {
|
|
||||||
return {
|
|
||||||
name: "ignore",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
name: "ignore",
|
|
||||||
|
|
||||||
load(id) {
|
|
||||||
return files.some((toIgnorePath) => id.startsWith(toIgnorePath))
|
|
||||||
? {
|
|
||||||
code: "",
|
|
||||||
}
|
|
||||||
: null;
|
|
||||||
},
|
|
||||||
};
|
|
||||||
};
|
|
@@ -1,34 +0,0 @@
|
|||||||
const url = require("url");
|
|
||||||
|
|
||||||
const defaultOptions = {
|
|
||||||
publicPath: "",
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = function (userOptions = {}) {
|
|
||||||
const options = { ...defaultOptions, ...userOptions };
|
|
||||||
|
|
||||||
return {
|
|
||||||
name: "manifest",
|
|
||||||
generateBundle(outputOptions, bundle) {
|
|
||||||
const manifest = {};
|
|
||||||
|
|
||||||
for (const chunk of Object.values(bundle)) {
|
|
||||||
if (!chunk.isEntry) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// Add js extension to mimic Webpack manifest.
|
|
||||||
manifest[`${chunk.name}.js`] = url.resolve(
|
|
||||||
options.publicPath,
|
|
||||||
chunk.fileName
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.emitFile({
|
|
||||||
type: "asset",
|
|
||||||
source: JSON.stringify(manifest, undefined, 2),
|
|
||||||
name: "manifest.json",
|
|
||||||
fileName: "manifest.json",
|
|
||||||
});
|
|
||||||
},
|
|
||||||
};
|
|
||||||
};
|
|
@@ -1,152 +0,0 @@
|
|||||||
// Worker plugin
|
|
||||||
// Each worker will include all of its dependencies
|
|
||||||
// instead of relying on an importer.
|
|
||||||
|
|
||||||
// Forked from v.1.4.1
|
|
||||||
// https://github.com/surma/rollup-plugin-off-main-thread
|
|
||||||
/**
|
|
||||||
* Copyright 2018 Google Inc. All Rights Reserved.
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
const rollup = require("rollup");
|
|
||||||
const path = require("path");
|
|
||||||
const MagicString = require("magic-string");
|
|
||||||
|
|
||||||
const defaultOpts = {
|
|
||||||
// A RegExp to find `new Workers()` calls. The second capture group _must_
|
|
||||||
// capture the provided file name without the quotes.
|
|
||||||
workerRegexp: /new Worker\((["'])(.+?)\1(,[^)]+)?\)/g,
|
|
||||||
plugins: ["node-resolve", "commonjs", "babel", "terser", "ignore"],
|
|
||||||
};
|
|
||||||
|
|
||||||
async function getBundledWorker(workerPath, rollupOptions) {
|
|
||||||
const bundle = await rollup.rollup({
|
|
||||||
...rollupOptions,
|
|
||||||
input: {
|
|
||||||
worker: workerPath,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
const { output } = await bundle.generate({
|
|
||||||
// Generates cleanest output, we shouldn't have any imports/exports
|
|
||||||
// that would be incompatible with ES5.
|
|
||||||
format: "es",
|
|
||||||
// We should not export anything. This will fail build if we are.
|
|
||||||
exports: "none",
|
|
||||||
});
|
|
||||||
|
|
||||||
let code;
|
|
||||||
|
|
||||||
for (const chunkOrAsset of output) {
|
|
||||||
if (chunkOrAsset.name === "worker") {
|
|
||||||
code = chunkOrAsset.code;
|
|
||||||
} else if (chunkOrAsset.type !== "asset") {
|
|
||||||
throw new Error("Unexpected extra output");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return code;
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = function (opts = {}) {
|
|
||||||
opts = { ...defaultOpts, ...opts };
|
|
||||||
|
|
||||||
let rollupOptions;
|
|
||||||
let refIds;
|
|
||||||
|
|
||||||
return {
|
|
||||||
name: "hass-worker",
|
|
||||||
|
|
||||||
async buildStart(options) {
|
|
||||||
refIds = {};
|
|
||||||
rollupOptions = {
|
|
||||||
plugins: options.plugins.filter((plugin) =>
|
|
||||||
opts.plugins.includes(plugin.name)
|
|
||||||
),
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
async transform(code, id) {
|
|
||||||
// Copy the regexp as they are stateful and this hook is async.
|
|
||||||
const workerRegexp = new RegExp(
|
|
||||||
opts.workerRegexp.source,
|
|
||||||
opts.workerRegexp.flags
|
|
||||||
);
|
|
||||||
if (!workerRegexp.test(code)) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
const ms = new MagicString(code);
|
|
||||||
// Reset the regexp
|
|
||||||
workerRegexp.lastIndex = 0;
|
|
||||||
for (;;) {
|
|
||||||
const match = workerRegexp.exec(code);
|
|
||||||
if (!match) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
const workerFile = match[2];
|
|
||||||
let optionsObject = {};
|
|
||||||
// Parse the optional options object
|
|
||||||
if (match[3] && match[3].length > 0) {
|
|
||||||
// FIXME: ooooof!
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-implied-eval
|
|
||||||
optionsObject = new Function(`return ${match[3].slice(1)};`)();
|
|
||||||
}
|
|
||||||
delete optionsObject.type;
|
|
||||||
|
|
||||||
if (!/^.*\//.test(workerFile)) {
|
|
||||||
this.warn(
|
|
||||||
`Paths passed to the Worker constructor must be relative or absolute, i.e. start with /, ./ or ../ (just like dynamic import!). Ignoring "${workerFile}".`
|
|
||||||
);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find worker file and store it as a chunk with ID prefixed for our loader
|
|
||||||
// eslint-disable-next-line no-await-in-loop
|
|
||||||
const resolvedWorkerFile = (await this.resolve(workerFile, id)).id;
|
|
||||||
let chunkRefId;
|
|
||||||
if (resolvedWorkerFile in refIds) {
|
|
||||||
chunkRefId = refIds[resolvedWorkerFile];
|
|
||||||
} else {
|
|
||||||
this.addWatchFile(resolvedWorkerFile);
|
|
||||||
// eslint-disable-next-line no-await-in-loop
|
|
||||||
const source = await getBundledWorker(
|
|
||||||
resolvedWorkerFile,
|
|
||||||
rollupOptions
|
|
||||||
);
|
|
||||||
chunkRefId = refIds[resolvedWorkerFile] = this.emitFile({
|
|
||||||
name: path.basename(resolvedWorkerFile),
|
|
||||||
source,
|
|
||||||
type: "asset",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const workerParametersStartIndex = match.index + "new Worker(".length;
|
|
||||||
const workerParametersEndIndex =
|
|
||||||
match.index + match[0].length - ")".length;
|
|
||||||
|
|
||||||
ms.overwrite(
|
|
||||||
workerParametersStartIndex,
|
|
||||||
workerParametersEndIndex,
|
|
||||||
`import.meta.ROLLUP_FILE_URL_${chunkRefId}, ${JSON.stringify(
|
|
||||||
optionsObject
|
|
||||||
)}`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
code: ms.toString(),
|
|
||||||
map: ms.generateMap({ hires: true }),
|
|
||||||
};
|
|
||||||
},
|
|
||||||
};
|
|
||||||
};
|
|
@@ -1,146 +0,0 @@
|
|||||||
const path = require("path");
|
|
||||||
|
|
||||||
const commonjs = require("@rollup/plugin-commonjs");
|
|
||||||
const resolve = require("@rollup/plugin-node-resolve");
|
|
||||||
const json = require("@rollup/plugin-json");
|
|
||||||
const { babel } = require("@rollup/plugin-babel");
|
|
||||||
const replace = require("@rollup/plugin-replace");
|
|
||||||
const visualizer = require("rollup-plugin-visualizer");
|
|
||||||
const { string } = require("rollup-plugin-string");
|
|
||||||
const { terser } = require("rollup-plugin-terser");
|
|
||||||
const manifest = require("./rollup-plugins/manifest-plugin.cjs");
|
|
||||||
const worker = require("./rollup-plugins/worker-plugin.cjs");
|
|
||||||
const dontHashPlugin = require("./rollup-plugins/dont-hash-plugin.cjs");
|
|
||||||
const ignore = require("./rollup-plugins/ignore-plugin.cjs");
|
|
||||||
|
|
||||||
const bundle = require("./bundle.cjs");
|
|
||||||
const paths = require("./paths.cjs");
|
|
||||||
|
|
||||||
const extensions = [".js", ".ts"];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {Object} arg
|
|
||||||
* @param { import("rollup").InputOption } arg.input
|
|
||||||
*/
|
|
||||||
const createRollupConfig = ({
|
|
||||||
entry,
|
|
||||||
outputPath,
|
|
||||||
defineOverlay,
|
|
||||||
isProdBuild,
|
|
||||||
latestBuild,
|
|
||||||
isStatsBuild,
|
|
||||||
publicPath,
|
|
||||||
dontHash,
|
|
||||||
isWDS,
|
|
||||||
}) => ({
|
|
||||||
/**
|
|
||||||
* @type { import("rollup").InputOptions }
|
|
||||||
*/
|
|
||||||
inputOptions: {
|
|
||||||
input: entry,
|
|
||||||
// Some entry points contain no JavaScript. This setting silences a warning about that.
|
|
||||||
// https://rollupjs.org/configuration-options/#preserveentrysignatures
|
|
||||||
preserveEntrySignatures: false,
|
|
||||||
plugins: [
|
|
||||||
ignore({
|
|
||||||
files: bundle
|
|
||||||
.emptyPackages({ latestBuild })
|
|
||||||
// TEMP HACK: Makes Rollup build work again
|
|
||||||
.concat(
|
|
||||||
require.resolve(
|
|
||||||
"@webcomponents/scoped-custom-element-registry/scoped-custom-element-registry.min"
|
|
||||||
)
|
|
||||||
),
|
|
||||||
}),
|
|
||||||
resolve({
|
|
||||||
extensions,
|
|
||||||
preferBuiltins: false,
|
|
||||||
browser: true,
|
|
||||||
rootDir: paths.polymer_dir,
|
|
||||||
}),
|
|
||||||
commonjs(),
|
|
||||||
json(),
|
|
||||||
babel({
|
|
||||||
...bundle.babelOptions({ latestBuild, isProdBuild }),
|
|
||||||
extensions,
|
|
||||||
babelHelpers: isWDS ? "inline" : "bundled",
|
|
||||||
}),
|
|
||||||
string({
|
|
||||||
// Import certain extensions as strings
|
|
||||||
include: [path.join(paths.polymer_dir, "node_modules/**/*.css")],
|
|
||||||
}),
|
|
||||||
replace(bundle.definedVars({ isProdBuild, latestBuild, defineOverlay })),
|
|
||||||
!isWDS &&
|
|
||||||
manifest({
|
|
||||||
publicPath,
|
|
||||||
}),
|
|
||||||
!isWDS && worker(),
|
|
||||||
!isWDS && dontHashPlugin({ dontHash }),
|
|
||||||
!isWDS && isProdBuild && terser(bundle.terserOptions({ latestBuild })),
|
|
||||||
!isWDS &&
|
|
||||||
isStatsBuild &&
|
|
||||||
visualizer({
|
|
||||||
// https://github.com/btd/rollup-plugin-visualizer#options
|
|
||||||
open: true,
|
|
||||||
sourcemap: true,
|
|
||||||
}),
|
|
||||||
].filter(Boolean),
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* @type { import("rollup").OutputOptions }
|
|
||||||
*/
|
|
||||||
outputOptions: {
|
|
||||||
// https://rollupjs.org/configuration-options/#output-dir
|
|
||||||
dir: outputPath,
|
|
||||||
// https://rollupjs.org/configuration-options/#output-format
|
|
||||||
format: latestBuild ? "es" : "systemjs",
|
|
||||||
// https://rollupjs.org/configuration-options/#output-externallivebindings
|
|
||||||
externalLiveBindings: false,
|
|
||||||
// https://rollupjs.org/configuration-options/#output-entryfilenames
|
|
||||||
// https://rollupjs.org/configuration-options/#output-chunkfilenames
|
|
||||||
// https://rollupjs.org/configuration-options/#output-assetfilenames
|
|
||||||
entryFileNames:
|
|
||||||
isProdBuild && !isStatsBuild ? "[name]-[hash].js" : "[name].js",
|
|
||||||
chunkFileNames: isProdBuild && !isStatsBuild ? "c.[hash].js" : "[name].js",
|
|
||||||
assetFileNames: isProdBuild && !isStatsBuild ? "a.[hash].js" : "[name].js",
|
|
||||||
// https://rollupjs.org/configuration-options/#output-sourcemap
|
|
||||||
sourcemap: isProdBuild ? true : "inline",
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const createAppConfig = ({ isProdBuild, latestBuild, isStatsBuild, isWDS }) =>
|
|
||||||
createRollupConfig(
|
|
||||||
bundle.config.app({
|
|
||||||
isProdBuild,
|
|
||||||
latestBuild,
|
|
||||||
isStatsBuild,
|
|
||||||
isWDS,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
const createDemoConfig = ({ isProdBuild, latestBuild, isStatsBuild }) =>
|
|
||||||
createRollupConfig(
|
|
||||||
bundle.config.demo({
|
|
||||||
isProdBuild,
|
|
||||||
latestBuild,
|
|
||||||
isStatsBuild,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
const createCastConfig = ({ isProdBuild, latestBuild }) =>
|
|
||||||
createRollupConfig(bundle.config.cast({ isProdBuild, latestBuild }));
|
|
||||||
|
|
||||||
const createHassioConfig = ({ isProdBuild, latestBuild }) =>
|
|
||||||
createRollupConfig(bundle.config.hassio({ isProdBuild, latestBuild }));
|
|
||||||
|
|
||||||
const createGalleryConfig = ({ isProdBuild, latestBuild }) =>
|
|
||||||
createRollupConfig(bundle.config.gallery({ isProdBuild, latestBuild }));
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
createAppConfig,
|
|
||||||
createDemoConfig,
|
|
||||||
createCastConfig,
|
|
||||||
createHassioConfig,
|
|
||||||
createGalleryConfig,
|
|
||||||
createRollupConfig,
|
|
||||||
};
|
|
@@ -1,16 +1,13 @@
|
|||||||
const { existsSync } = require("fs");
|
const { existsSync } = require("fs");
|
||||||
const path = require("path");
|
const path = require("path");
|
||||||
const webpack = require("webpack");
|
const rspack = require("@rspack/core");
|
||||||
|
const { RsdoctorRspackPlugin } = require("@rsdoctor/rspack-plugin");
|
||||||
const { StatsWriterPlugin } = require("webpack-stats-plugin");
|
const { StatsWriterPlugin } = require("webpack-stats-plugin");
|
||||||
const filterStats = require("@bundle-stats/plugin-webpack-filter").default;
|
const filterStats = require("@bundle-stats/plugin-webpack-filter").default;
|
||||||
const TerserPlugin = require("terser-webpack-plugin");
|
const TerserPlugin = require("terser-webpack-plugin");
|
||||||
const { WebpackManifestPlugin } = require("webpack-manifest-plugin");
|
const { WebpackManifestPlugin } = require("rspack-manifest-plugin");
|
||||||
const log = require("fancy-log");
|
const log = require("fancy-log");
|
||||||
const WebpackBar = require("webpackbar");
|
const WebpackBar = require("webpackbar/rspack");
|
||||||
const {
|
|
||||||
TransformAsyncModulesPlugin,
|
|
||||||
} = require("transform-async-modules-webpack-plugin");
|
|
||||||
const { dependencies } = require("../package.json");
|
|
||||||
const paths = require("./paths.cjs");
|
const paths = require("./paths.cjs");
|
||||||
const bundle = require("./bundle.cjs");
|
const bundle = require("./bundle.cjs");
|
||||||
|
|
||||||
@@ -28,7 +25,7 @@ class LogStartCompilePlugin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const createWebpackConfig = ({
|
const createRspackConfig = ({
|
||||||
name,
|
name,
|
||||||
entry,
|
entry,
|
||||||
outputPath,
|
outputPath,
|
||||||
@@ -63,17 +60,25 @@ const createWebpackConfig = ({
|
|||||||
rules: [
|
rules: [
|
||||||
{
|
{
|
||||||
test: /\.m?js$|\.ts$/,
|
test: /\.m?js$|\.ts$/,
|
||||||
use: {
|
use: (info) => ({
|
||||||
loader: "babel-loader",
|
loader: "babel-loader",
|
||||||
options: {
|
options: {
|
||||||
...bundle.babelOptions({ latestBuild, isProdBuild, isTestBuild }),
|
...bundle.babelOptions({
|
||||||
|
latestBuild,
|
||||||
|
isProdBuild,
|
||||||
|
isTestBuild,
|
||||||
|
sw: info.issuerLayer === "sw",
|
||||||
|
}),
|
||||||
cacheDirectory: !isProdBuild,
|
cacheDirectory: !isProdBuild,
|
||||||
cacheCompression: false,
|
cacheCompression: false,
|
||||||
},
|
},
|
||||||
},
|
}),
|
||||||
resolve: {
|
resolve: {
|
||||||
fullySpecified: false,
|
fullySpecified: false,
|
||||||
},
|
},
|
||||||
|
parser: {
|
||||||
|
worker: ["*context.audioWorklet.addModule()", "..."],
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
test: /\.css$/,
|
test: /\.css$/,
|
||||||
@@ -92,11 +97,20 @@ const createWebpackConfig = ({
|
|||||||
moduleIds: isProdBuild && !isStatsBuild ? "deterministic" : "named",
|
moduleIds: isProdBuild && !isStatsBuild ? "deterministic" : "named",
|
||||||
chunkIds: isProdBuild && !isStatsBuild ? "deterministic" : "named",
|
chunkIds: isProdBuild && !isStatsBuild ? "deterministic" : "named",
|
||||||
splitChunks: {
|
splitChunks: {
|
||||||
// Disable splitting for web workers with ESM output
|
// Disable splitting for web workers and worklets because imports of
|
||||||
// Imports of external chunks are broken
|
// external chunks are broken for:
|
||||||
chunks: latestBuild
|
chunks: !isProdBuild
|
||||||
? (chunk) => !chunk.canBeInitial() && !/^.+-worker$/.test(chunk.name)
|
? // improve incremental build speed, but blows up bundle size
|
||||||
: undefined,
|
new RegExp(
|
||||||
|
`^(?!(${Object.keys(entry).join("|")}|.*work(?:er|let))$)`
|
||||||
|
)
|
||||||
|
: // - ESM output: https://github.com/webpack/webpack/issues/17014
|
||||||
|
// - Worklets use `importScripts`: https://github.com/webpack/webpack/issues/11543
|
||||||
|
(chunk) =>
|
||||||
|
!chunk.canBeInitial() &&
|
||||||
|
!new RegExp(
|
||||||
|
`^.+-work${latestBuild ? "(?:let|er)" : "let"}$`
|
||||||
|
).test(chunk.name),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
@@ -105,10 +119,10 @@ const createWebpackConfig = ({
|
|||||||
// Only include the JS of entrypoints
|
// Only include the JS of entrypoints
|
||||||
filter: (file) => file.isInitial && !file.name.endsWith(".map"),
|
filter: (file) => file.isInitial && !file.name.endsWith(".map"),
|
||||||
}),
|
}),
|
||||||
new webpack.DefinePlugin(
|
new rspack.DefinePlugin(
|
||||||
bundle.definedVars({ isProdBuild, latestBuild, defineOverlay })
|
bundle.definedVars({ isProdBuild, latestBuild, defineOverlay })
|
||||||
),
|
),
|
||||||
new webpack.IgnorePlugin({
|
new rspack.IgnorePlugin({
|
||||||
checkResource(resource, context) {
|
checkResource(resource, context) {
|
||||||
// Only use ignore to intercept imports that we don't control
|
// Only use ignore to intercept imports that we don't control
|
||||||
// inside node_module dependencies.
|
// inside node_module dependencies.
|
||||||
@@ -140,7 +154,7 @@ const createWebpackConfig = ({
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
new webpack.NormalModuleReplacementPlugin(
|
new rspack.NormalModuleReplacementPlugin(
|
||||||
new RegExp(
|
new RegExp(
|
||||||
bundle.emptyPackages({ latestBuild, isHassioBuild }).join("|")
|
bundle.emptyPackages({ latestBuild, isHassioBuild }).join("|")
|
||||||
),
|
),
|
||||||
@@ -156,10 +170,14 @@ const createWebpackConfig = ({
|
|||||||
stats: { assets: true, chunks: true, modules: true },
|
stats: { assets: true, chunks: true, modules: true },
|
||||||
transform: (stats) => JSON.stringify(filterStats(stats)),
|
transform: (stats) => JSON.stringify(filterStats(stats)),
|
||||||
}),
|
}),
|
||||||
!latestBuild &&
|
isProdBuild &&
|
||||||
new TransformAsyncModulesPlugin({
|
isStatsBuild &&
|
||||||
browserslistEnv: "legacy",
|
new RsdoctorRspackPlugin({
|
||||||
runtime: { version: dependencies["@babel/runtime"] },
|
reportDir: path.join(paths.build_dir, "rsdoctor"),
|
||||||
|
features: ["plugins", "bundle"],
|
||||||
|
supports: {
|
||||||
|
generateTileGraph: true,
|
||||||
|
},
|
||||||
}),
|
}),
|
||||||
].filter(Boolean),
|
].filter(Boolean),
|
||||||
resolve: {
|
resolve: {
|
||||||
@@ -176,6 +194,7 @@ const createWebpackConfig = ({
|
|||||||
"lit/directives/cache$": "lit/directives/cache.js",
|
"lit/directives/cache$": "lit/directives/cache.js",
|
||||||
"lit/directives/repeat$": "lit/directives/repeat.js",
|
"lit/directives/repeat$": "lit/directives/repeat.js",
|
||||||
"lit/directives/live$": "lit/directives/live.js",
|
"lit/directives/live$": "lit/directives/live.js",
|
||||||
|
"lit/directives/keyed$": "lit/directives/keyed.js",
|
||||||
"lit/polyfill-support$": "lit/polyfill-support.js",
|
"lit/polyfill-support$": "lit/polyfill-support.js",
|
||||||
"@lit-labs/virtualizer/layouts/grid":
|
"@lit-labs/virtualizer/layouts/grid":
|
||||||
"@lit-labs/virtualizer/layouts/grid.js",
|
"@lit-labs/virtualizer/layouts/grid.js",
|
||||||
@@ -197,8 +216,6 @@ const createWebpackConfig = ({
|
|||||||
isProdBuild && !isStatsBuild ? "[id].[contenthash][ext]" : "[id][ext]",
|
isProdBuild && !isStatsBuild ? "[id].[contenthash][ext]" : "[id][ext]",
|
||||||
crossOriginLoading: "use-credentials",
|
crossOriginLoading: "use-credentials",
|
||||||
hashFunction: "xxhash64",
|
hashFunction: "xxhash64",
|
||||||
hashDigest: "base64url",
|
|
||||||
hashDigestLength: 11, // full length of 64 bit base64url
|
|
||||||
path: outputPath,
|
path: outputPath,
|
||||||
publicPath,
|
publicPath,
|
||||||
// To silence warning in worker plugin
|
// To silence warning in worker plugin
|
||||||
@@ -228,6 +245,7 @@ const createWebpackConfig = ({
|
|||||||
),
|
),
|
||||||
},
|
},
|
||||||
experiments: {
|
experiments: {
|
||||||
|
layers: true,
|
||||||
outputModule: true,
|
outputModule: true,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -239,17 +257,17 @@ const createAppConfig = ({
|
|||||||
isStatsBuild,
|
isStatsBuild,
|
||||||
isTestBuild,
|
isTestBuild,
|
||||||
}) =>
|
}) =>
|
||||||
createWebpackConfig(
|
createRspackConfig(
|
||||||
bundle.config.app({ isProdBuild, latestBuild, isStatsBuild, isTestBuild })
|
bundle.config.app({ isProdBuild, latestBuild, isStatsBuild, isTestBuild })
|
||||||
);
|
);
|
||||||
|
|
||||||
const createDemoConfig = ({ isProdBuild, latestBuild, isStatsBuild }) =>
|
const createDemoConfig = ({ isProdBuild, latestBuild, isStatsBuild }) =>
|
||||||
createWebpackConfig(
|
createRspackConfig(
|
||||||
bundle.config.demo({ isProdBuild, latestBuild, isStatsBuild })
|
bundle.config.demo({ isProdBuild, latestBuild, isStatsBuild })
|
||||||
);
|
);
|
||||||
|
|
||||||
const createCastConfig = ({ isProdBuild, latestBuild }) =>
|
const createCastConfig = ({ isProdBuild, latestBuild }) =>
|
||||||
createWebpackConfig(bundle.config.cast({ isProdBuild, latestBuild }));
|
createRspackConfig(bundle.config.cast({ isProdBuild, latestBuild }));
|
||||||
|
|
||||||
const createHassioConfig = ({
|
const createHassioConfig = ({
|
||||||
isProdBuild,
|
isProdBuild,
|
||||||
@@ -257,7 +275,7 @@ const createHassioConfig = ({
|
|||||||
isStatsBuild,
|
isStatsBuild,
|
||||||
isTestBuild,
|
isTestBuild,
|
||||||
}) =>
|
}) =>
|
||||||
createWebpackConfig(
|
createRspackConfig(
|
||||||
bundle.config.hassio({
|
bundle.config.hassio({
|
||||||
isProdBuild,
|
isProdBuild,
|
||||||
latestBuild,
|
latestBuild,
|
||||||
@@ -267,7 +285,10 @@ const createHassioConfig = ({
|
|||||||
);
|
);
|
||||||
|
|
||||||
const createGalleryConfig = ({ isProdBuild, latestBuild }) =>
|
const createGalleryConfig = ({ isProdBuild, latestBuild }) =>
|
||||||
createWebpackConfig(bundle.config.gallery({ isProdBuild, latestBuild }));
|
createRspackConfig(bundle.config.gallery({ isProdBuild, latestBuild }));
|
||||||
|
|
||||||
|
const createLandingPageConfig = ({ isProdBuild, latestBuild }) =>
|
||||||
|
createRspackConfig(bundle.config.landingPage({ isProdBuild, latestBuild }));
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
createAppConfig,
|
createAppConfig,
|
||||||
@@ -275,5 +296,6 @@ module.exports = {
|
|||||||
createCastConfig,
|
createCastConfig,
|
||||||
createHassioConfig,
|
createHassioConfig,
|
||||||
createGalleryConfig,
|
createGalleryConfig,
|
||||||
createWebpackConfig,
|
createRspackConfig,
|
||||||
|
createLandingPageConfig,
|
||||||
};
|
};
|
@@ -25,7 +25,7 @@ Home Assistant Cast is made up of two separate applications:
|
|||||||
|
|
||||||
### Setting dev variables
|
### Setting dev variables
|
||||||
|
|
||||||
Open `src/cast/dev_const.ts` and change `CAST_DEV_APP_ID` to the ID of the app you just created. And set the `CAST_DEV_HASS_URL` to the url of you development machine.
|
Open `src/cast/dev_const.ts` and change `CAST_DEV_APP_ID` to the ID of the app you just created. And set the `CAST_DEV_HASS_URL` to the url of your development machine.
|
||||||
|
|
||||||
### Changing configuration
|
### Changing configuration
|
||||||
|
|
||||||
|
5
cast/public/sw-legacy.js
Normal file
5
cast/public/sw-legacy.js
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
self.addEventListener("fetch", (event) => {
|
||||||
|
event.respondWith(fetch(event.request));
|
||||||
|
});
|
@@ -1,10 +0,0 @@
|
|||||||
import rollup from "../build-scripts/rollup.cjs";
|
|
||||||
import env from "../build-scripts/env.cjs";
|
|
||||||
|
|
||||||
const config = rollup.createCastConfig({
|
|
||||||
isProdBuild: env.isProdBuild(),
|
|
||||||
latestBuild: true,
|
|
||||||
isStatsBuild: env.isStatsBuild(),
|
|
||||||
});
|
|
||||||
|
|
||||||
export default { ...config.inputOptions, output: config.outputOptions };
|
|
@@ -36,13 +36,7 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<%= renderTemplate("../../../src/html/_js_base.html.template") %>
|
<%= renderTemplate("../../../src/html/_js_base.html.template") %>
|
||||||
<script>
|
<%= renderTemplate("../../../src/html/_script_loader.html.template") %>
|
||||||
<% for (const entry of latestEntryJS) { %>
|
|
||||||
import("<%= entry %>");
|
|
||||||
<% } %>
|
|
||||||
window.latestJS = true;
|
|
||||||
</script>
|
|
||||||
<%= renderTemplate("../../../src/html/_script_load_es5.html.template") %>
|
|
||||||
<hc-layout subtitle="FAQ">
|
<hc-layout subtitle="FAQ">
|
||||||
<style>
|
<style>
|
||||||
a {
|
a {
|
||||||
@@ -145,7 +139,7 @@
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="section-header">Wat does Home Assistant Cast do?</div>
|
<div class="section-header">What does Home Assistant Cast do?</div>
|
||||||
<div class="card-content">
|
<div class="card-content">
|
||||||
<p>
|
<p>
|
||||||
Home Assistant Cast is a receiver application for the Chromecast. When
|
Home Assistant Cast is a receiver application for the Chromecast. When
|
||||||
@@ -232,17 +226,5 @@ http:
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</hc-layout>
|
</hc-layout>
|
||||||
|
|
||||||
<script>
|
|
||||||
var _gaq = [["_setAccount", "UA-57927901-9"], ["_trackPageview"]];
|
|
||||||
(function (d, t) {
|
|
||||||
var g = d.createElement(t),
|
|
||||||
s = d.getElementsByTagName(t)[0];
|
|
||||||
g.src =
|
|
||||||
("https:" == location.protocol ? "//ssl" : "//www") +
|
|
||||||
".google-analytics.com/ga.js";
|
|
||||||
s.parentNode.insertBefore(g, s);
|
|
||||||
})(document, "script");
|
|
||||||
</script>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@@ -13,15 +13,9 @@
|
|||||||
<%= renderTemplate("_social_meta.html.template") %>
|
<%= renderTemplate("_social_meta.html.template") %>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<%= renderTemplate("../../../src/html/_js_base.html.template") %>
|
|
||||||
<hc-connect></hc-connect>
|
<hc-connect></hc-connect>
|
||||||
<script>
|
<%= renderTemplate("../../../src/html/_js_base.html.template") %>
|
||||||
<% for (const entry of latestEntryJS) { %>
|
<%= renderTemplate("../../../src/html/_script_loader.html.template") %>
|
||||||
import("<%= entry %>");
|
|
||||||
<% } %>
|
|
||||||
window.latestJS = true;
|
|
||||||
</script>
|
|
||||||
<%= renderTemplate("../../../src/html/_script_load_es5.html.template") %>
|
|
||||||
<script>
|
<script>
|
||||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
||||||
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
||||||
|
@@ -14,22 +14,10 @@
|
|||||||
--background-color: #41bdf5;
|
--background-color: #41bdf5;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<script>
|
|
||||||
var _gaq=[['_setAccount','UA-57927901-10'],['_trackPageview']];
|
|
||||||
(function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
|
|
||||||
g.src=('https:'==location.protocol?'//ssl':'//www')+'.google-analytics.com/ga.js';
|
|
||||||
s.parentNode.insertBefore(g,s)}(document,'script'));
|
|
||||||
</script>
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<%= renderTemplate("../../../src/html/_js_base.html.template") %>
|
|
||||||
<cast-media-player></cast-media-player>
|
<cast-media-player></cast-media-player>
|
||||||
<script>
|
<%= renderTemplate("../../../src/html/_js_base.html.template") %>
|
||||||
<% for (const entry of latestEntryJS) { %>
|
<%= renderTemplate("../../../src/html/_script_loader.html.template") %>
|
||||||
import("<%= entry %>");
|
|
||||||
<% } %>
|
|
||||||
window.latestJS = true;
|
|
||||||
</script>
|
|
||||||
<%= renderTemplate("../../../src/html/_script_load_es5.html.template") %>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@@ -7,14 +7,7 @@
|
|||||||
<%= renderTemplate("../../../src/html/_style_base.html.template") %>
|
<%= renderTemplate("../../../src/html/_style_base.html.template") %>
|
||||||
<style>
|
<style>
|
||||||
body {
|
body {
|
||||||
background-color: white;
|
|
||||||
font-size: initial;
|
font-size: initial;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<script>
|
|
||||||
var _gaq=[['_setAccount','UA-57927901-10'],['_trackPageview']];
|
|
||||||
(function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
|
|
||||||
g.src=('https:'==location.protocol?'//ssl':'//www')+'.google-analytics.com/ga.js';
|
|
||||||
s.parentNode.insertBefore(g,s)}(document,'script'));
|
|
||||||
</script>
|
|
||||||
</html>
|
</html>
|
||||||
|
@@ -1,4 +1,3 @@
|
|||||||
import "../../../src/resources/safari-14-attachshadow-patch";
|
|
||||||
import "./layout/hc-connect";
|
import "./layout/hc-connect";
|
||||||
|
|
||||||
import("../../../src/resources/ha-style");
|
import("../../../src/resources/ha-style");
|
||||||
|
@@ -1,11 +1,12 @@
|
|||||||
import "@material/mwc-button/mwc-button";
|
import "@material/mwc-button/mwc-button";
|
||||||
import { mdiCast, mdiCastConnected } from "@mdi/js";
|
import "@material/mwc-list/mwc-list";
|
||||||
import "@polymer/paper-item/paper-icon-item";
|
import type { ActionDetail } from "@material/mwc-list/mwc-list";
|
||||||
import "@polymer/paper-listbox/paper-listbox";
|
import { mdiCast, mdiCastConnected, mdiViewDashboard } from "@mdi/js";
|
||||||
import { Auth, Connection } from "home-assistant-js-websocket";
|
import type { Auth, Connection } from "home-assistant-js-websocket";
|
||||||
import { CSSResultGroup, LitElement, TemplateResult, css, html } from "lit";
|
import type { TemplateResult } from "lit";
|
||||||
|
import { LitElement, css, html } from "lit";
|
||||||
import { customElement, property, state } from "lit/decorators";
|
import { customElement, property, state } from "lit/decorators";
|
||||||
import { CastManager } from "../../../../src/cast/cast_manager";
|
import type { CastManager } from "../../../../src/cast/cast_manager";
|
||||||
import {
|
import {
|
||||||
castSendShowLovelaceView,
|
castSendShowLovelaceView,
|
||||||
ensureConnectedCastSession,
|
ensureConnectedCastSession,
|
||||||
@@ -24,10 +25,11 @@ import {
|
|||||||
getLovelaceCollection,
|
getLovelaceCollection,
|
||||||
} from "../../../../src/data/lovelace";
|
} from "../../../../src/data/lovelace";
|
||||||
import { isStrategyDashboard } from "../../../../src/data/lovelace/config/types";
|
import { isStrategyDashboard } from "../../../../src/data/lovelace/config/types";
|
||||||
import { LovelaceViewConfig } from "../../../../src/data/lovelace/config/view";
|
import type { LovelaceViewConfig } from "../../../../src/data/lovelace/config/view";
|
||||||
import "../../../../src/layouts/hass-loading-screen";
|
import "../../../../src/layouts/hass-loading-screen";
|
||||||
import { generateDefaultViewConfig } from "../../../../src/panels/lovelace/common/generate-lovelace-config";
|
import { generateDefaultViewConfig } from "../../../../src/panels/lovelace/common/generate-lovelace-config";
|
||||||
import "./hc-layout";
|
import "./hc-layout";
|
||||||
|
import "../../../../src/components/ha-list-item";
|
||||||
|
|
||||||
@customElement("hc-cast")
|
@customElement("hc-cast")
|
||||||
class HcCast extends LitElement {
|
class HcCast extends LitElement {
|
||||||
@@ -83,34 +85,38 @@ class HcCast extends LitElement {
|
|||||||
`
|
`
|
||||||
: html`
|
: html`
|
||||||
<div class="section-header">PICK A VIEW</div>
|
<div class="section-header">PICK A VIEW</div>
|
||||||
<paper-listbox
|
<mwc-list @action=${this._handlePickView} activatable>
|
||||||
attr-for-selected="data-path"
|
|
||||||
.selected=${this.castManager.status.lovelacePath || ""}
|
|
||||||
>
|
|
||||||
${(
|
${(
|
||||||
this.lovelaceViews ?? [
|
this.lovelaceViews ?? [
|
||||||
generateDefaultViewConfig({}, {}, {}, {}, () => ""),
|
generateDefaultViewConfig({}, {}, {}, {}, () => ""),
|
||||||
]
|
]
|
||||||
).map(
|
).map(
|
||||||
(view, idx) => html`
|
(view, idx) => html`
|
||||||
<paper-icon-item
|
<ha-list-item
|
||||||
@click=${this._handlePickView}
|
graphic="avatar"
|
||||||
data-path=${view.path || idx}
|
.activated=${this.castManager.status?.lovelacePath ===
|
||||||
|
(view.path ?? idx)}
|
||||||
|
.selected=${this.castManager.status?.lovelacePath ===
|
||||||
|
(view.path ?? idx)}
|
||||||
>
|
>
|
||||||
|
${view.title || view.path || "Unnamed view"}
|
||||||
${view.icon
|
${view.icon
|
||||||
? html`
|
? html`
|
||||||
<ha-icon
|
<ha-icon
|
||||||
.icon=${view.icon}
|
.icon=${view.icon}
|
||||||
slot="item-icon"
|
slot="graphic"
|
||||||
></ha-icon>
|
></ha-icon>
|
||||||
`
|
`
|
||||||
: ""}
|
: html`<ha-svg-icon
|
||||||
${view.title || view.path}
|
slot="item-icon"
|
||||||
</paper-icon-item>
|
.path=${mdiViewDashboard}
|
||||||
|
></ha-svg-icon>`}
|
||||||
|
</ha-list-item>
|
||||||
`
|
`
|
||||||
)}
|
)}</mwc-list
|
||||||
</paper-listbox>
|
>
|
||||||
`}
|
`}
|
||||||
|
|
||||||
<div class="card-actions">
|
<div class="card-actions">
|
||||||
${this.castManager.status
|
${this.castManager.status
|
||||||
? html`
|
? html`
|
||||||
@@ -182,8 +188,8 @@ class HcCast extends LitElement {
|
|||||||
this.castManager.requestSession();
|
this.castManager.requestSession();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _handlePickView(ev: Event) {
|
private async _handlePickView(ev: CustomEvent<ActionDetail>) {
|
||||||
const path = (ev.currentTarget as any).getAttribute("data-path");
|
const path = this.lovelaceViews![ev.detail.index].path ?? ev.detail.index;
|
||||||
await ensureConnectedCastSession(this.castManager!, this.auth!);
|
await ensureConnectedCastSession(this.castManager!, this.auth!);
|
||||||
castSendShowLovelaceView(this.castManager, this.auth.data.hassUrl, path);
|
castSendShowLovelaceView(this.castManager, this.auth.data.hassUrl, path);
|
||||||
}
|
}
|
||||||
@@ -197,85 +203,72 @@ class HcCast extends LitElement {
|
|||||||
}
|
}
|
||||||
this.connection.close();
|
this.connection.close();
|
||||||
location.reload();
|
location.reload();
|
||||||
} catch (err: any) {
|
} catch (_err: any) {
|
||||||
alert("Unable to log out!");
|
alert("Unable to log out!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static get styles(): CSSResultGroup {
|
static styles = css`
|
||||||
return css`
|
.center-item {
|
||||||
.center-item {
|
display: flex;
|
||||||
display: flex;
|
justify-content: space-around;
|
||||||
justify-content: space-around;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.action-item {
|
.action-item {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
}
|
}
|
||||||
|
|
||||||
.question {
|
.question {
|
||||||
position: relative;
|
position: relative;
|
||||||
padding: 8px 16px;
|
padding: 8px 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.question:before {
|
.question:before {
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
content: "";
|
content: "";
|
||||||
background-color: var(--primary-color);
|
background-color: var(--primary-color);
|
||||||
opacity: 0.12;
|
opacity: 0.12;
|
||||||
will-change: opacity;
|
will-change: opacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
.connection,
|
.connection,
|
||||||
.connection a {
|
.connection a {
|
||||||
color: var(--secondary-text-color);
|
color: var(--secondary-text-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
mwc-button ha-svg-icon {
|
mwc-button ha-svg-icon {
|
||||||
margin-right: 8px;
|
margin-right: 8px;
|
||||||
margin-inline-end: 8px;
|
margin-inline-end: 8px;
|
||||||
margin-inline-start: initial;
|
margin-inline-start: initial;
|
||||||
height: 18px;
|
height: 18px;
|
||||||
}
|
}
|
||||||
|
|
||||||
paper-listbox {
|
ha-list-item ha-icon,
|
||||||
padding-top: 0;
|
ha-list-item ha-svg-icon {
|
||||||
}
|
padding: 12px;
|
||||||
|
color: var(--secondary-text-color);
|
||||||
|
}
|
||||||
|
|
||||||
paper-listbox ha-icon {
|
:host([hide-icons]) ha-icon {
|
||||||
padding: 12px;
|
display: none;
|
||||||
color: var(--secondary-text-color);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
paper-icon-item {
|
.spacer {
|
||||||
cursor: pointer;
|
flex: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
paper-icon-item[disabled] {
|
.card-content a {
|
||||||
cursor: initial;
|
color: var(--primary-color);
|
||||||
}
|
}
|
||||||
|
`;
|
||||||
:host([hide-icons]) paper-icon-item {
|
|
||||||
--paper-item-icon-width: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.spacer {
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card-content a {
|
|
||||||
color: var(--primary-color);
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
|
@@ -1,19 +1,23 @@
|
|||||||
import "@material/mwc-button";
|
import "@material/mwc-button";
|
||||||
import { mdiCastConnected, mdiCast } from "@mdi/js";
|
import { mdiCastConnected, mdiCast } from "@mdi/js";
|
||||||
import {
|
import type {
|
||||||
Auth,
|
Auth,
|
||||||
Connection,
|
Connection,
|
||||||
|
getAuthOptions,
|
||||||
|
} from "home-assistant-js-websocket";
|
||||||
|
import {
|
||||||
createConnection,
|
createConnection,
|
||||||
ERR_CANNOT_CONNECT,
|
ERR_CANNOT_CONNECT,
|
||||||
ERR_HASS_HOST_REQUIRED,
|
ERR_HASS_HOST_REQUIRED,
|
||||||
ERR_INVALID_AUTH,
|
ERR_INVALID_AUTH,
|
||||||
ERR_INVALID_HTTPS_TO_HTTP,
|
ERR_INVALID_HTTPS_TO_HTTP,
|
||||||
getAuth,
|
getAuth,
|
||||||
getAuthOptions,
|
|
||||||
} from "home-assistant-js-websocket";
|
} from "home-assistant-js-websocket";
|
||||||
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
|
import type { TemplateResult } from "lit";
|
||||||
|
import { css, html, LitElement } from "lit";
|
||||||
import { customElement, state } from "lit/decorators";
|
import { customElement, state } from "lit/decorators";
|
||||||
import { CastManager, getCastManager } from "../../../../src/cast/cast_manager";
|
import type { CastManager } from "../../../../src/cast/cast_manager";
|
||||||
|
import { getCastManager } from "../../../../src/cast/cast_manager";
|
||||||
import { castSendShowDemo } from "../../../../src/cast/receiver_messages";
|
import { castSendShowDemo } from "../../../../src/cast/receiver_messages";
|
||||||
import {
|
import {
|
||||||
loadTokens,
|
loadTokens,
|
||||||
@@ -211,7 +215,7 @@ export class HcConnect extends LitElement {
|
|||||||
let url: URL;
|
let url: URL;
|
||||||
try {
|
try {
|
||||||
url = new URL(value);
|
url = new URL(value);
|
||||||
} catch (err: any) {
|
} catch (_err: any) {
|
||||||
this.error = "Invalid URL";
|
this.error = "Invalid URL";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -248,7 +252,7 @@ export class HcConnect extends LitElement {
|
|||||||
this.loading = false;
|
this.loading = false;
|
||||||
return;
|
return;
|
||||||
} finally {
|
} finally {
|
||||||
// Clear url if we have a auth callback in url.
|
// Clear url if we have an auth callback in url.
|
||||||
if (location.search.includes("auth_callback=1")) {
|
if (location.search.includes("auth_callback=1")) {
|
||||||
history.replaceState(null, "", location.pathname);
|
history.replaceState(null, "", location.pathname);
|
||||||
}
|
}
|
||||||
@@ -284,41 +288,39 @@ export class HcConnect extends LitElement {
|
|||||||
try {
|
try {
|
||||||
saveTokens(null);
|
saveTokens(null);
|
||||||
location.reload();
|
location.reload();
|
||||||
} catch (err: any) {
|
} catch (_err: any) {
|
||||||
alert("Unable to log out!");
|
alert("Unable to log out!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static get styles(): CSSResultGroup {
|
static styles = css`
|
||||||
return css`
|
.card-content a {
|
||||||
.card-content a {
|
color: var(--primary-color);
|
||||||
color: var(--primary-color);
|
}
|
||||||
}
|
.card-actions a {
|
||||||
.card-actions a {
|
text-decoration: none;
|
||||||
text-decoration: none;
|
}
|
||||||
}
|
.error {
|
||||||
.error {
|
color: red;
|
||||||
color: red;
|
font-weight: bold;
|
||||||
font-weight: bold;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.error a {
|
.error a {
|
||||||
color: darkred;
|
color: darkred;
|
||||||
}
|
}
|
||||||
|
|
||||||
mwc-button ha-svg-icon {
|
mwc-button ha-svg-icon {
|
||||||
margin-left: 8px;
|
margin-left: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.spacer {
|
.spacer {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ha-textfield {
|
ha-textfield {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
|
@@ -1,10 +1,7 @@
|
|||||||
import {
|
import type { Auth, Connection, HassUser } from "home-assistant-js-websocket";
|
||||||
Auth,
|
import { getUser } from "home-assistant-js-websocket";
|
||||||
Connection,
|
import type { TemplateResult } from "lit";
|
||||||
getUser,
|
import { css, html, LitElement } from "lit";
|
||||||
HassUser,
|
|
||||||
} from "home-assistant-js-websocket";
|
|
||||||
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
|
|
||||||
import { customElement, property } from "lit/decorators";
|
import { customElement, property } from "lit/decorators";
|
||||||
import "../../../../src/components/ha-card";
|
import "../../../../src/components/ha-card";
|
||||||
|
|
||||||
@@ -66,96 +63,94 @@ class HcLayout extends LitElement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static get styles(): CSSResultGroup {
|
static styles = css`
|
||||||
return css`
|
:host {
|
||||||
|
display: flex;
|
||||||
|
min-height: 100%;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
ha-card {
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
max-width: 500px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.layout {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-header {
|
||||||
|
color: var(--ha-card-header-color, var(--primary-text-color));
|
||||||
|
font-family: var(--ha-card-header-font-family, inherit);
|
||||||
|
font-size: var(--ha-card-header-font-size, 24px);
|
||||||
|
letter-spacing: -0.012em;
|
||||||
|
line-height: 32px;
|
||||||
|
padding: 24px 16px 16px;
|
||||||
|
display: block;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero {
|
||||||
|
border-radius: 4px 4px 0 0;
|
||||||
|
}
|
||||||
|
.subtitle {
|
||||||
|
font-size: 14px;
|
||||||
|
color: var(--secondary-text-color);
|
||||||
|
line-height: initial;
|
||||||
|
}
|
||||||
|
.subtitle a {
|
||||||
|
color: var(--secondary-text-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
:host ::slotted(.card-content:not(:first-child)),
|
||||||
|
slot:not(:first-child)::slotted(.card-content) {
|
||||||
|
padding-top: 0px;
|
||||||
|
margin-top: -8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:host ::slotted(.section-header) {
|
||||||
|
font-weight: 500;
|
||||||
|
padding: 4px 16px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
:host ::slotted(.card-content) {
|
||||||
|
padding: 16px;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
:host ::slotted(.card-actions) {
|
||||||
|
border-top: 1px solid #e8e8e8;
|
||||||
|
padding: 5px 16px;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer {
|
||||||
|
text-align: center;
|
||||||
|
font-size: 12px;
|
||||||
|
padding: 8px 0 24px;
|
||||||
|
color: var(--secondary-text-color);
|
||||||
|
}
|
||||||
|
.footer a {
|
||||||
|
color: var(--secondary-text-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media all and (max-width: 500px) {
|
||||||
:host {
|
:host {
|
||||||
display: flex;
|
justify-content: flex-start;
|
||||||
min-height: 100%;
|
min-height: 90%;
|
||||||
align-items: center;
|
margin-bottom: 30px;
|
||||||
justify-content: center;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
ha-card {
|
`;
|
||||||
display: flex;
|
|
||||||
width: 100%;
|
|
||||||
max-width: 500px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.layout {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card-header {
|
|
||||||
color: var(--ha-card-header-color, --primary-text-color);
|
|
||||||
font-family: var(--ha-card-header-font-family, inherit);
|
|
||||||
font-size: var(--ha-card-header-font-size, 24px);
|
|
||||||
letter-spacing: -0.012em;
|
|
||||||
line-height: 32px;
|
|
||||||
padding: 24px 16px 16px;
|
|
||||||
display: block;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hero {
|
|
||||||
border-radius: 4px 4px 0 0;
|
|
||||||
}
|
|
||||||
.subtitle {
|
|
||||||
font-size: 14px;
|
|
||||||
color: var(--secondary-text-color);
|
|
||||||
line-height: initial;
|
|
||||||
}
|
|
||||||
.subtitle a {
|
|
||||||
color: var(--secondary-text-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
:host ::slotted(.card-content:not(:first-child)),
|
|
||||||
slot:not(:first-child)::slotted(.card-content) {
|
|
||||||
padding-top: 0px;
|
|
||||||
margin-top: -8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
:host ::slotted(.section-header) {
|
|
||||||
font-weight: 500;
|
|
||||||
padding: 4px 16px;
|
|
||||||
text-transform: uppercase;
|
|
||||||
}
|
|
||||||
|
|
||||||
:host ::slotted(.card-content) {
|
|
||||||
padding: 16px;
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
:host ::slotted(.card-actions) {
|
|
||||||
border-top: 1px solid #e8e8e8;
|
|
||||||
padding: 5px 16px;
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
img {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.footer {
|
|
||||||
text-align: center;
|
|
||||||
font-size: 12px;
|
|
||||||
padding: 8px 0 24px;
|
|
||||||
color: var(--secondary-text-color);
|
|
||||||
}
|
|
||||||
.footer a {
|
|
||||||
color: var(--secondary-text-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
@media all and (max-width: 500px) {
|
|
||||||
:host {
|
|
||||||
justify-content: flex-start;
|
|
||||||
min-height: 90%;
|
|
||||||
margin-bottom: 30px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
import { convertEntities, Entity } from "../../../../src/fake_data/entity";
|
import type { Entity } from "../../../../src/fake_data/entity";
|
||||||
|
import { convertEntities } from "../../../../src/fake_data/entity";
|
||||||
|
|
||||||
export const castDemoEntities: () => Entity[] = () =>
|
export const castDemoEntities: () => Entity[] = () =>
|
||||||
convertEntities({
|
convertEntities({
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import { LovelaceCardConfig } from "../../../../src/data/lovelace/config/card";
|
import type { LovelaceCardConfig } from "../../../../src/data/lovelace/config/card";
|
||||||
import { LovelaceConfig } from "../../../../src/data/lovelace/config/types";
|
import type { LovelaceConfig } from "../../../../src/data/lovelace/config/types";
|
||||||
import { castContext } from "../cast_context";
|
import { castContext } from "../cast_context";
|
||||||
|
|
||||||
export const castDemoLovelace: () => LovelaceConfig = () => {
|
export const castDemoLovelace: () => LovelaceConfig = () => {
|
||||||
|
@@ -1,10 +1,10 @@
|
|||||||
import { framework } from "./cast_framework";
|
import { framework } from "./cast_framework";
|
||||||
import { CAST_NS } from "../../../src/cast/const";
|
import { CAST_NS } from "../../../src/cast/const";
|
||||||
import { HassMessage } from "../../../src/cast/receiver_messages";
|
import type { HassMessage } from "../../../src/cast/receiver_messages";
|
||||||
import "../../../src/resources/custom-card-support";
|
import "../../../src/resources/custom-card-support";
|
||||||
import { castContext } from "./cast_context";
|
import { castContext } from "./cast_context";
|
||||||
import { HcMain } from "./layout/hc-main";
|
import { HcMain } from "./layout/hc-main";
|
||||||
import { ReceivedMessage } from "./types";
|
import type { ReceivedMessage } from "./types";
|
||||||
|
|
||||||
const lovelaceController = new HcMain();
|
const lovelaceController = new HcMain();
|
||||||
document.body.append(lovelaceController);
|
document.body.append(lovelaceController);
|
||||||
|
@@ -1,13 +1,11 @@
|
|||||||
import { html, nothing } from "lit";
|
import { html, nothing } from "lit";
|
||||||
import { customElement, property, state } from "lit/decorators";
|
import { customElement, property, state } from "lit/decorators";
|
||||||
import { mockHistory } from "../../../../demo/src/stubs/history";
|
import { mockHistory } from "../../../../demo/src/stubs/history";
|
||||||
import { LovelaceConfig } from "../../../../src/data/lovelace/config/types";
|
import type { LovelaceConfig } from "../../../../src/data/lovelace/config/types";
|
||||||
import {
|
import type { MockHomeAssistant } from "../../../../src/fake_data/provide_hass";
|
||||||
MockHomeAssistant,
|
import { provideHass } from "../../../../src/fake_data/provide_hass";
|
||||||
provideHass,
|
|
||||||
} from "../../../../src/fake_data/provide_hass";
|
|
||||||
import { HassElement } from "../../../../src/state/hass-element";
|
import { HassElement } from "../../../../src/state/hass-element";
|
||||||
import { HomeAssistant } from "../../../../src/types";
|
import type { HomeAssistant } from "../../../../src/types";
|
||||||
import { castDemoEntities } from "../demo/cast-demo-entities";
|
import { castDemoEntities } from "../demo/cast-demo-entities";
|
||||||
import { castDemoLovelace } from "../demo/cast-demo-lovelace";
|
import { castDemoLovelace } from "../demo/cast-demo-lovelace";
|
||||||
import "./hc-lovelace";
|
import "./hc-lovelace";
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
|
import type { TemplateResult } from "lit";
|
||||||
|
import { css, html, LitElement } from "lit";
|
||||||
import { customElement, property } from "lit/decorators";
|
import { customElement, property } from "lit/decorators";
|
||||||
import { HomeAssistant } from "../../../../src/types";
|
import type { HomeAssistant } from "../../../../src/types";
|
||||||
|
|
||||||
@customElement("hc-launch-screen")
|
@customElement("hc-launch-screen")
|
||||||
class HcLaunchScreen extends LitElement {
|
class HcLaunchScreen extends LitElement {
|
||||||
@@ -23,31 +24,29 @@ class HcLaunchScreen extends LitElement {
|
|||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
static get styles(): CSSResultGroup {
|
static styles = css`
|
||||||
return css`
|
:host {
|
||||||
:host {
|
display: block;
|
||||||
display: block;
|
height: 100vh;
|
||||||
height: 100vh;
|
background-color: #f2f4f9;
|
||||||
background-color: #f2f4f9;
|
font-size: 24px;
|
||||||
font-size: 24px;
|
}
|
||||||
}
|
.container {
|
||||||
.container {
|
display: flex;
|
||||||
display: flex;
|
flex-direction: column;
|
||||||
flex-direction: column;
|
text-align: center;
|
||||||
text-align: center;
|
align-items: center;
|
||||||
align-items: center;
|
height: 100%;
|
||||||
height: 100%;
|
justify-content: space-evenly;
|
||||||
justify-content: space-evenly;
|
}
|
||||||
}
|
img {
|
||||||
img {
|
max-width: 80%;
|
||||||
max-width: 80%;
|
object-fit: cover;
|
||||||
object-fit: cover;
|
}
|
||||||
}
|
.status {
|
||||||
.status {
|
color: #1d2126;
|
||||||
color: #1d2126;
|
}
|
||||||
}
|
`;
|
||||||
`;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
|
@@ -1,11 +1,14 @@
|
|||||||
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
|
import { css, html, LitElement, type TemplateResult } from "lit";
|
||||||
import { customElement, property, query } from "lit/decorators";
|
import { customElement, property } from "lit/decorators";
|
||||||
import { fireEvent } from "../../../../src/common/dom/fire_event";
|
import { fireEvent } from "../../../../src/common/dom/fire_event";
|
||||||
import { LovelaceConfig } from "../../../../src/data/lovelace/config/types";
|
import type { LovelaceConfig } from "../../../../src/data/lovelace/config/types";
|
||||||
import { Lovelace } from "../../../../src/panels/lovelace/types";
|
import { getPanelTitleFromUrlPath } from "../../../../src/data/panel";
|
||||||
|
import type { Lovelace } from "../../../../src/panels/lovelace/types";
|
||||||
import "../../../../src/panels/lovelace/views/hui-view";
|
import "../../../../src/panels/lovelace/views/hui-view";
|
||||||
import { HomeAssistant } from "../../../../src/types";
|
import "../../../../src/panels/lovelace/views/hui-view-container";
|
||||||
|
import type { HomeAssistant } from "../../../../src/types";
|
||||||
import "./hc-launch-screen";
|
import "./hc-launch-screen";
|
||||||
|
import "../../../../src/panels/lovelace/views/hui-view-background";
|
||||||
|
|
||||||
(window as any).loadCardHelpers = () =>
|
(window as any).loadCardHelpers = () =>
|
||||||
import("../../../../src/panels/lovelace/custom-card-helpers");
|
import("../../../../src/panels/lovelace/custom-card-helpers");
|
||||||
@@ -17,11 +20,9 @@ class HcLovelace extends LitElement {
|
|||||||
@property({ attribute: false })
|
@property({ attribute: false })
|
||||||
public lovelaceConfig!: LovelaceConfig;
|
public lovelaceConfig!: LovelaceConfig;
|
||||||
|
|
||||||
@property() public viewPath?: string | number | null;
|
@property({ attribute: false }) public viewPath?: string | number | null;
|
||||||
|
|
||||||
@property() public urlPath: string | null = null;
|
@property({ attribute: false }) public urlPath: string | null = null;
|
||||||
|
|
||||||
@query("hui-view") private _huiView?: HTMLElement;
|
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult {
|
||||||
const index = this._viewIndex;
|
const index = this._viewIndex;
|
||||||
@@ -44,13 +45,22 @@ class HcLovelace extends LitElement {
|
|||||||
saveConfig: async () => undefined,
|
saveConfig: async () => undefined,
|
||||||
deleteConfig: async () => undefined,
|
deleteConfig: async () => undefined,
|
||||||
setEditMode: () => undefined,
|
setEditMode: () => undefined,
|
||||||
|
showToast: () => undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const viewConfig = this.lovelaceConfig.views[index];
|
||||||
|
const background = viewConfig.background || this.lovelaceConfig.background;
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
<hui-view
|
<hui-view-container .hass=${this.hass} .theme=${viewConfig.theme}>
|
||||||
.hass=${this.hass}
|
<hui-view-background .hass=${this.hass} .background=${background}>
|
||||||
.lovelace=${lovelace}
|
</hui-view-background>
|
||||||
.index=${index}
|
<hui-view
|
||||||
></hui-view>
|
.hass=${this.hass}
|
||||||
|
.lovelace=${lovelace}
|
||||||
|
.index=${index}
|
||||||
|
></hui-view>
|
||||||
|
</hui-view-container>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -61,7 +71,12 @@ class HcLovelace extends LitElement {
|
|||||||
const index = this._viewIndex;
|
const index = this._viewIndex;
|
||||||
|
|
||||||
if (index !== undefined) {
|
if (index !== undefined) {
|
||||||
const dashboardTitle = this.lovelaceConfig.title || this.urlPath;
|
const title = getPanelTitleFromUrlPath(
|
||||||
|
this.hass,
|
||||||
|
this.urlPath || "lovelace"
|
||||||
|
);
|
||||||
|
|
||||||
|
const dashboardTitle = title || this.urlPath;
|
||||||
|
|
||||||
const viewTitle =
|
const viewTitle =
|
||||||
this.lovelaceConfig.views[index].title ||
|
this.lovelaceConfig.views[index].title ||
|
||||||
@@ -75,19 +90,6 @@ class HcLovelace extends LitElement {
|
|||||||
}${viewTitle || ""}`
|
}${viewTitle || ""}`
|
||||||
: undefined,
|
: undefined,
|
||||||
});
|
});
|
||||||
|
|
||||||
const configBackground =
|
|
||||||
this.lovelaceConfig.views[index].background ||
|
|
||||||
this.lovelaceConfig.background;
|
|
||||||
|
|
||||||
if (configBackground) {
|
|
||||||
this._huiView!.style.setProperty(
|
|
||||||
"--lovelace-background",
|
|
||||||
configBackground
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
this._huiView!.style.removeProperty("--lovelace-background");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -109,24 +111,18 @@ class HcLovelace extends LitElement {
|
|||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
static get styles(): CSSResultGroup {
|
static styles = css`
|
||||||
return css`
|
hui-view-container {
|
||||||
:host {
|
display: flex;
|
||||||
min-height: 100vh;
|
position: relative;
|
||||||
height: 0;
|
min-height: 100vh;
|
||||||
display: flex;
|
box-sizing: border-box;
|
||||||
flex-direction: column;
|
}
|
||||||
box-sizing: border-box;
|
hui-view-container > * {
|
||||||
background: var(--primary-background-color);
|
flex: 1 1 100%;
|
||||||
}
|
max-width: 100%;
|
||||||
:host > * {
|
}
|
||||||
flex: 1;
|
`;
|
||||||
}
|
|
||||||
hui-view {
|
|
||||||
background: var(--lovelace-background, var(--primary-background-color));
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface CastViewChanged {
|
export interface CastViewChanged {
|
||||||
|
@@ -1,40 +1,40 @@
|
|||||||
import {
|
import type { UnsubscribeFunc } from "home-assistant-js-websocket";
|
||||||
createConnection,
|
import { createConnection, getAuth } from "home-assistant-js-websocket";
|
||||||
getAuth,
|
import type { TemplateResult } from "lit";
|
||||||
UnsubscribeFunc,
|
import { html } from "lit";
|
||||||
} from "home-assistant-js-websocket";
|
|
||||||
import { html, TemplateResult } from "lit";
|
|
||||||
import { customElement, state } from "lit/decorators";
|
import { customElement, state } from "lit/decorators";
|
||||||
import { CAST_NS } from "../../../../src/cast/const";
|
import { CAST_NS } from "../../../../src/cast/const";
|
||||||
import {
|
import type {
|
||||||
ConnectMessage,
|
ConnectMessage,
|
||||||
GetStatusMessage,
|
GetStatusMessage,
|
||||||
HassMessage,
|
HassMessage,
|
||||||
ShowDemoMessage,
|
ShowDemoMessage,
|
||||||
ShowLovelaceViewMessage,
|
ShowLovelaceViewMessage,
|
||||||
} from "../../../../src/cast/receiver_messages";
|
} from "../../../../src/cast/receiver_messages";
|
||||||
import {
|
import type {
|
||||||
ReceiverErrorCode,
|
|
||||||
ReceiverErrorMessage,
|
ReceiverErrorMessage,
|
||||||
ReceiverStatusMessage,
|
ReceiverStatusMessage,
|
||||||
} from "../../../../src/cast/sender_messages";
|
} from "../../../../src/cast/sender_messages";
|
||||||
|
import { ReceiverErrorCode } from "../../../../src/cast/sender_messages";
|
||||||
import { atLeastVersion } from "../../../../src/common/config/version";
|
import { atLeastVersion } from "../../../../src/common/config/version";
|
||||||
import { isNavigationClick } from "../../../../src/common/dom/is-navigation-click";
|
import { isNavigationClick } from "../../../../src/common/dom/is-navigation-click";
|
||||||
import {
|
import {
|
||||||
getLegacyLovelaceCollection,
|
getLegacyLovelaceCollection,
|
||||||
getLovelaceCollection,
|
getLovelaceCollection,
|
||||||
} from "../../../../src/data/lovelace";
|
} from "../../../../src/data/lovelace";
|
||||||
import {
|
import type {
|
||||||
isStrategyDashboard,
|
|
||||||
LegacyLovelaceConfig,
|
LegacyLovelaceConfig,
|
||||||
LovelaceConfig,
|
LovelaceConfig,
|
||||||
LovelaceDashboardStrategyConfig,
|
LovelaceDashboardStrategyConfig,
|
||||||
} from "../../../../src/data/lovelace/config/types";
|
} from "../../../../src/data/lovelace/config/types";
|
||||||
|
import { isStrategyDashboard } from "../../../../src/data/lovelace/config/types";
|
||||||
import { fetchResources } from "../../../../src/data/lovelace/resource";
|
import { fetchResources } from "../../../../src/data/lovelace/resource";
|
||||||
import { loadLovelaceResources } from "../../../../src/panels/lovelace/common/load-resources";
|
import { loadLovelaceResources } from "../../../../src/panels/lovelace/common/load-resources";
|
||||||
import { HassElement } from "../../../../src/state/hass-element";
|
import { HassElement } from "../../../../src/state/hass-element";
|
||||||
import { castContext } from "../cast_context";
|
import { castContext } from "../cast_context";
|
||||||
import "./hc-launch-screen";
|
import "./hc-launch-screen";
|
||||||
|
import { getPanelTitleFromUrlPath } from "../../../../src/data/panel";
|
||||||
|
import { checkLovelaceConfig } from "../../../../src/panels/lovelace/common/check-lovelace-config";
|
||||||
|
|
||||||
const DEFAULT_CONFIG: LovelaceDashboardStrategyConfig = {
|
const DEFAULT_CONFIG: LovelaceDashboardStrategyConfig = {
|
||||||
strategy: {
|
strategy: {
|
||||||
@@ -144,10 +144,10 @@ export class HcMain extends HassElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (senderId) {
|
if (senderId) {
|
||||||
this.sendMessage(senderId, status);
|
this._sendMessage(senderId, status);
|
||||||
} else {
|
} else {
|
||||||
for (const sender of castContext.getSenders()) {
|
for (const sender of castContext.getSenders()) {
|
||||||
this.sendMessage(sender.id, status);
|
this._sendMessage(sender.id, status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -164,10 +164,10 @@ export class HcMain extends HassElement {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (senderId) {
|
if (senderId) {
|
||||||
this.sendMessage(senderId, error);
|
this._sendMessage(senderId, error);
|
||||||
} else {
|
} else {
|
||||||
for (const sender of castContext.getSenders()) {
|
for (const sender of castContext.getSenders()) {
|
||||||
this.sendMessage(sender.id, error);
|
this._sendMessage(sender.id, error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -359,8 +359,14 @@ export class HcMain extends HassElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _handleNewLovelaceConfig(lovelaceConfig: LovelaceConfig) {
|
private _handleNewLovelaceConfig(lovelaceConfig: LovelaceConfig) {
|
||||||
castContext.setApplicationState(lovelaceConfig.title || "");
|
const title = getPanelTitleFromUrlPath(
|
||||||
this._lovelaceConfig = lovelaceConfig;
|
this.hass!,
|
||||||
|
this._urlPath || "lovelace"
|
||||||
|
);
|
||||||
|
castContext.setApplicationState(title || "");
|
||||||
|
this._lovelaceConfig = checkLovelaceConfig(
|
||||||
|
lovelaceConfig
|
||||||
|
) as LovelaceConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _handleShowDemo(_msg: ShowDemoMessage) {
|
private _handleShowDemo(_msg: ShowDemoMessage) {
|
||||||
@@ -388,7 +394,7 @@ export class HcMain extends HassElement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private sendMessage(senderId: string, response: any) {
|
private _sendMessage(senderId: string, response: any) {
|
||||||
castContext.sendCustomMessage(CAST_NS, senderId, response);
|
castContext.sendCustomMessage(CAST_NS, senderId, response);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,8 +0,0 @@
|
|||||||
import webpack from "../build-scripts/webpack.cjs";
|
|
||||||
import env from "../build-scripts/env.cjs";
|
|
||||||
|
|
||||||
export default webpack.createCastConfig({
|
|
||||||
isProdBuild: env.isProdBuild(),
|
|
||||||
isStatsBuild: env.isStatsBuild(),
|
|
||||||
latestBuild: true,
|
|
||||||
});
|
|
BIN
demo/public/assets/sections/images/media_player_family_room.jpg
Normal file
BIN
demo/public/assets/sections/images/media_player_family_room.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 30 KiB |
5
demo/public/sw-legacy.js
Normal file
5
demo/public/sw-legacy.js
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
self.addEventListener("fetch", (event) => {
|
||||||
|
event.respondWith(fetch(event.request));
|
||||||
|
});
|
@@ -1,10 +0,0 @@
|
|||||||
import rollup from "../build-scripts/rollup.cjs";
|
|
||||||
import env from "../build-scripts/env.cjs";
|
|
||||||
|
|
||||||
const config = rollup.createDemoConfig({
|
|
||||||
isProdBuild: env.isProdBuild(),
|
|
||||||
latestBuild: true,
|
|
||||||
isStatsBuild: env.isStatsBuild(),
|
|
||||||
});
|
|
||||||
|
|
||||||
export default { ...config.inputOptions, output: config.outputOptions };
|
|
@@ -4,11 +4,6 @@
|
|||||||
# Stop on errors
|
# Stop on errors
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
cd "$(dirname "$0")/.."
|
cd "$(dirname "$0")/../.."
|
||||||
|
|
||||||
export STATS=1
|
./node_modules/.bin/gulp analyze-demo
|
||||||
statsfile="compilation-stats-demo.json"
|
|
||||||
|
|
||||||
./node_modules/.bin/webpack-cli --profile --node-env=production --json=$statsfile
|
|
||||||
npx webpack-bundle-analyzer $statsfile dist/frontend_latest
|
|
||||||
rm -f $statsfile
|
|
@@ -1,5 +1,5 @@
|
|||||||
import { convertEntities } from "../../../../src/fake_data/entity";
|
import { convertEntities } from "../../../../src/fake_data/entity";
|
||||||
import { DemoConfig } from "../types";
|
import type { DemoConfig } from "../types";
|
||||||
|
|
||||||
export const demoEntitiesArsaboo: DemoConfig["entities"] = (localize) =>
|
export const demoEntitiesArsaboo: DemoConfig["entities"] = (localize) =>
|
||||||
convertEntities({
|
convertEntities({
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import { DemoConfig } from "../types";
|
import type { DemoConfig } from "../types";
|
||||||
import { demoEntitiesArsaboo } from "./entities";
|
import { demoEntitiesArsaboo } from "./entities";
|
||||||
import { demoLovelaceArsaboo } from "./lovelace";
|
import { demoLovelaceArsaboo } from "./lovelace";
|
||||||
import { demoThemeArsaboo } from "./theme";
|
import { demoThemeArsaboo } from "./theme";
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import { DemoConfig } from "../types";
|
import type { DemoConfig } from "../types";
|
||||||
|
|
||||||
export const demoLovelaceArsaboo: DemoConfig["lovelace"] = (localize) => ({
|
export const demoLovelaceArsaboo: DemoConfig["lovelace"] = (localize) => ({
|
||||||
title: "Home Assistant",
|
title: "Home Assistant",
|
||||||
|
@@ -1,9 +1,9 @@
|
|||||||
import { MockHomeAssistant } from "../../../src/fake_data/provide_hass";
|
import type { MockHomeAssistant } from "../../../src/fake_data/provide_hass";
|
||||||
import { Lovelace } from "../../../src/panels/lovelace/types";
|
import type { Lovelace } from "../../../src/panels/lovelace/types";
|
||||||
import { energyEntities } from "../stubs/entities";
|
import { energyEntities } from "../stubs/entities";
|
||||||
import { DemoConfig } from "./types";
|
import type { DemoConfig } from "./types";
|
||||||
|
|
||||||
export const demoConfigs: Array<() => Promise<DemoConfig>> = [
|
export const demoConfigs: (() => Promise<DemoConfig>)[] = [
|
||||||
() => import("./sections").then((mod) => mod.demoSections),
|
() => import("./sections").then((mod) => mod.demoSections),
|
||||||
() => import("./arsaboo").then((mod) => mod.demoArsaboo),
|
() => import("./arsaboo").then((mod) => mod.demoArsaboo),
|
||||||
() => import("./teachingbirds").then((mod) => mod.demoTeachingbirds),
|
() => import("./teachingbirds").then((mod) => mod.demoTeachingbirds),
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import { convertEntities } from "../../../../src/fake_data/entity";
|
import { convertEntities } from "../../../../src/fake_data/entity";
|
||||||
import { DemoConfig } from "../types";
|
import type { DemoConfig } from "../types";
|
||||||
|
|
||||||
export const demoEntitiesJimpower: DemoConfig["entities"] = () =>
|
export const demoEntitiesJimpower: DemoConfig["entities"] = () =>
|
||||||
convertEntities({
|
convertEntities({
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import { DemoConfig } from "../types";
|
import type { DemoConfig } from "../types";
|
||||||
import { demoEntitiesJimpower } from "./entities";
|
import { demoEntitiesJimpower } from "./entities";
|
||||||
import { demoLovelaceJimpower } from "./lovelace";
|
import { demoLovelaceJimpower } from "./lovelace";
|
||||||
import { demoThemeJimpower } from "./theme";
|
import { demoThemeJimpower } from "./theme";
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import "../../custom-cards/card-modder";
|
import "../../custom-cards/card-modder";
|
||||||
import { DemoConfig } from "../types";
|
import type { DemoConfig } from "../types";
|
||||||
|
|
||||||
export const demoLovelaceJimpower: DemoConfig["lovelace"] = () => ({
|
export const demoLovelaceJimpower: DemoConfig["lovelace"] = () => ({
|
||||||
name: "Kingia Castle",
|
name: "Kingia Castle",
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import { convertEntities } from "../../../../src/fake_data/entity";
|
import { convertEntities } from "../../../../src/fake_data/entity";
|
||||||
import { DemoConfig } from "../types";
|
import type { DemoConfig } from "../types";
|
||||||
|
|
||||||
export const demoEntitiesKernehed: DemoConfig["entities"] = () =>
|
export const demoEntitiesKernehed: DemoConfig["entities"] = () =>
|
||||||
convertEntities({
|
convertEntities({
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import { DemoConfig } from "../types";
|
import type { DemoConfig } from "../types";
|
||||||
import { demoEntitiesKernehed } from "./entities";
|
import { demoEntitiesKernehed } from "./entities";
|
||||||
import { demoLovelaceKernehed } from "./lovelace";
|
import { demoLovelaceKernehed } from "./lovelace";
|
||||||
import { demoThemeKernehed } from "./theme";
|
import { demoThemeKernehed } from "./theme";
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import { DemoConfig } from "../types";
|
import type { DemoConfig } from "../types";
|
||||||
|
|
||||||
export const demoLovelaceKernehed: DemoConfig["lovelace"] = () => ({
|
export const demoLovelaceKernehed: DemoConfig["lovelace"] = () => ({
|
||||||
name: "Hem",
|
name: "Hem",
|
||||||
|
@@ -1,16 +0,0 @@
|
|||||||
import { html } from "lit";
|
|
||||||
import { DemoConfig } from "../types";
|
|
||||||
|
|
||||||
export const demoLovelaceDescription: DemoConfig["description"] = (
|
|
||||||
localize
|
|
||||||
) => html`
|
|
||||||
<p>
|
|
||||||
${localize("ui.panel.page-demo.config.sections.description", {
|
|
||||||
blog_post: html`<a
|
|
||||||
href="https://www.home-assistant.io/blog/2024/03/04/dashboard-chapter-1/"
|
|
||||||
target="_blank"
|
|
||||||
>${localize("ui.panel.page-demo.config.sections.description_blog_post")}
|
|
||||||
</a>`,
|
|
||||||
})}
|
|
||||||
</p>
|
|
||||||
`;
|
|
@@ -1,7 +1,7 @@
|
|||||||
import { convertEntities } from "../../../../src/fake_data/entity";
|
import { convertEntities } from "../../../../src/fake_data/entity";
|
||||||
import { DemoConfig } from "../types";
|
import type { DemoConfig } from "../types";
|
||||||
|
|
||||||
export const demoEntitiesSections: DemoConfig["entities"] = () =>
|
export const demoEntitiesSections: DemoConfig["entities"] = (localize) =>
|
||||||
convertEntities({
|
convertEntities({
|
||||||
"cover.living_room_garden_shutter": {
|
"cover.living_room_garden_shutter": {
|
||||||
entity_id: "cover.living_room_garden_shutter",
|
entity_id: "cover.living_room_garden_shutter",
|
||||||
@@ -111,13 +111,70 @@ export const demoEntitiesSections: DemoConfig["entities"] = () =>
|
|||||||
friendly_name: "Living room Temperature",
|
friendly_name: "Living room Temperature",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
"sensor.living_room_humidity": {
|
||||||
|
entity_id: "sensor.living_room_humidity",
|
||||||
|
state: "57",
|
||||||
|
attributes: {
|
||||||
|
state_class: "measurement",
|
||||||
|
unit_of_measurement: "%",
|
||||||
|
device_class: "humidity",
|
||||||
|
friendly_name: "Living room Humidity",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"sensor.outdoor_temperature": {
|
||||||
|
entity_id: "sensor.outdoor_temperature",
|
||||||
|
state: "10.5",
|
||||||
|
attributes: {
|
||||||
|
state_class: "measurement",
|
||||||
|
unit_of_measurement: "°C",
|
||||||
|
device_class: "temperature",
|
||||||
|
friendly_name: "Outdoor temperature",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"sensor.outdoor_humidity": {
|
||||||
|
entity_id: "sensor.outdoor_humidity",
|
||||||
|
state: "70.4",
|
||||||
|
attributes: {
|
||||||
|
state_class: "measurement",
|
||||||
|
unit_of_measurement: "%",
|
||||||
|
device_class: "humidity",
|
||||||
|
friendly_name: "Outdoor humidity",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"device_tracker.car": {
|
||||||
|
entity_id: "sensor.outdoor_humidity",
|
||||||
|
state: "not_home",
|
||||||
|
attributes: {
|
||||||
|
friendly_name: "Car",
|
||||||
|
icon: "mdi:car",
|
||||||
|
},
|
||||||
|
},
|
||||||
"media_player.living_room_nest_mini": {
|
"media_player.living_room_nest_mini": {
|
||||||
entity_id: "media_player.living_room_nest_mini",
|
entity_id: "media_player.living_room_nest_mini",
|
||||||
state: "off",
|
state: "playing",
|
||||||
attributes: {
|
attributes: {
|
||||||
device_class: "speaker",
|
device_class: "speaker",
|
||||||
friendly_name: "Living room Nest Mini",
|
volume_level: 0.18,
|
||||||
supported_features: 152461,
|
is_volume_muted: false,
|
||||||
|
media_content_type: "music",
|
||||||
|
media_duration: 300,
|
||||||
|
media_position: 0,
|
||||||
|
media_position_updated_at: new Date(
|
||||||
|
// 23 seconds in
|
||||||
|
new Date().getTime() - 23000
|
||||||
|
).toISOString(),
|
||||||
|
media_title: "I Wasn't Born To Follow",
|
||||||
|
media_artist: "The Byrds",
|
||||||
|
media_album_name: "The Notorious Byrd Brothers",
|
||||||
|
source_list: ["It's A Party", "Radio HSL", "Retro 70s and 80s"],
|
||||||
|
shuffle: false,
|
||||||
|
night_sound: false,
|
||||||
|
speech_enhance: false,
|
||||||
|
friendly_name: localize(
|
||||||
|
"ui.panel.page-demo.config.sections.entities.media_player.living_room_nest_mini"
|
||||||
|
),
|
||||||
|
entity_picture: "/assets/sections/images/media_player_family_room.jpg",
|
||||||
|
supported_features: 64063,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"cover.kitchen_shutter": {
|
"cover.kitchen_shutter": {
|
||||||
@@ -142,6 +199,14 @@ export const demoEntitiesSections: DemoConfig["entities"] = () =>
|
|||||||
supported_features: 32,
|
supported_features: 32,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
"binary_sensor.kitchen_motion": {
|
||||||
|
entity_id: "light.kitchen_motion",
|
||||||
|
state: "on",
|
||||||
|
attributes: {
|
||||||
|
device_class: "motion",
|
||||||
|
friendly_name: "Kitchen motion",
|
||||||
|
},
|
||||||
|
},
|
||||||
"light.worktop_spotlights": {
|
"light.worktop_spotlights": {
|
||||||
entity_id: "light.worktop_spotlights",
|
entity_id: "light.worktop_spotlights",
|
||||||
state: "off",
|
state: "off",
|
||||||
@@ -168,8 +233,27 @@ export const demoEntitiesSections: DemoConfig["entities"] = () =>
|
|||||||
state: "on",
|
state: "on",
|
||||||
attributes: {
|
attributes: {
|
||||||
device_class: "speaker",
|
device_class: "speaker",
|
||||||
friendly_name: "Kitchen Nest Audio",
|
volume_level: 0.18,
|
||||||
supported_features: 152461,
|
is_volume_muted: false,
|
||||||
|
media_content_type: "music",
|
||||||
|
media_duration: 300,
|
||||||
|
media_position: 0,
|
||||||
|
media_position_updated_at: new Date(
|
||||||
|
// 23 seconds in
|
||||||
|
new Date().getTime() - 23000
|
||||||
|
).toISOString(),
|
||||||
|
media_title: "I Wasn't Born To Follow",
|
||||||
|
media_artist: "The Byrds",
|
||||||
|
media_album_name: "The Notorious Byrd Brothers",
|
||||||
|
source_list: ["It's A Party", "Radio HSL", "Retro 70s and 80s"],
|
||||||
|
shuffle: false,
|
||||||
|
night_sound: false,
|
||||||
|
speech_enhance: false,
|
||||||
|
friendly_name: localize(
|
||||||
|
"ui.panel.page-demo.config.sections.entities.media_player.kitchen_nest_audio"
|
||||||
|
),
|
||||||
|
entity_picture: "/assets/sections/images/media_player_family_room.jpg",
|
||||||
|
supported_features: 64063,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"binary_sensor.tesla_wall_connector_vehicle_connected": {
|
"binary_sensor.tesla_wall_connector_vehicle_connected": {
|
||||||
@@ -333,8 +417,36 @@ export const demoEntitiesSections: DemoConfig["entities"] = () =>
|
|||||||
entity_id: "media_player.study_nest_hub",
|
entity_id: "media_player.study_nest_hub",
|
||||||
state: "off",
|
state: "off",
|
||||||
attributes: {
|
attributes: {
|
||||||
friendly_name: "Study Nest Hub",
|
device_class: "speaker",
|
||||||
supported_features: 152461,
|
volume_level: 0.18,
|
||||||
|
is_volume_muted: false,
|
||||||
|
media_content_type: "music",
|
||||||
|
media_duration: 300,
|
||||||
|
media_position: 0,
|
||||||
|
media_position_updated_at: new Date(
|
||||||
|
// 23 seconds in
|
||||||
|
new Date().getTime() - 23000
|
||||||
|
).toISOString(),
|
||||||
|
media_title: "I Wasn't Born To Follow",
|
||||||
|
media_artist: "The Byrds",
|
||||||
|
media_album_name: "The Notorious Byrd Brothers",
|
||||||
|
source_list: ["It's A Party", "Radio HSL", "Retro 70s and 80s"],
|
||||||
|
shuffle: false,
|
||||||
|
night_sound: false,
|
||||||
|
speech_enhance: false,
|
||||||
|
friendly_name: localize(
|
||||||
|
"ui.panel.page-demo.config.sections.entities.media_player.study_nest_hub"
|
||||||
|
),
|
||||||
|
entity_picture: "/assets/sections/images/media_player_family_room.jpg",
|
||||||
|
supported_features: 64063,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"switch.in_meeting": {
|
||||||
|
entity_id: "switch.in_meeting",
|
||||||
|
state: "on",
|
||||||
|
attributes: {
|
||||||
|
icon: "mdi:laptop-account",
|
||||||
|
friendly_name: "In a meeting",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"sensor.standing_desk_height": {
|
"sensor.standing_desk_height": {
|
||||||
|
@@ -1,5 +1,4 @@
|
|||||||
import { DemoConfig } from "../types";
|
import type { DemoConfig } from "../types";
|
||||||
import { demoLovelaceDescription } from "./description";
|
|
||||||
import { demoEntitiesSections } from "./entities";
|
import { demoEntitiesSections } from "./entities";
|
||||||
import { demoLovelaceSections } from "./lovelace";
|
import { demoLovelaceSections } from "./lovelace";
|
||||||
|
|
||||||
@@ -7,7 +6,6 @@ export const demoSections: DemoConfig = {
|
|||||||
authorName: "Home Assistant",
|
authorName: "Home Assistant",
|
||||||
authorUrl: "https://github.com/home-assistant/frontend/",
|
authorUrl: "https://github.com/home-assistant/frontend/",
|
||||||
name: "Home Demo",
|
name: "Home Demo",
|
||||||
description: demoLovelaceDescription,
|
|
||||||
lovelace: demoLovelaceSections,
|
lovelace: demoLovelaceSections,
|
||||||
entities: demoEntitiesSections,
|
entities: demoEntitiesSections,
|
||||||
theme: () => ({}),
|
theme: () => ({}),
|
||||||
|
@@ -1,39 +1,64 @@
|
|||||||
import { DemoConfig } from "../types";
|
import { isFrontpageEmbed } from "../../util/is_frontpage";
|
||||||
|
import type { DemoConfig } from "../types";
|
||||||
|
|
||||||
export const demoLovelaceSections: DemoConfig["lovelace"] = () => ({
|
export const demoLovelaceSections: DemoConfig["lovelace"] = (localize) => ({
|
||||||
title: "Home Assistant Demo",
|
title: "Home Assistant Demo",
|
||||||
views: [
|
views: [
|
||||||
{
|
{
|
||||||
type: "sections",
|
type: "sections",
|
||||||
title: "Demo",
|
title: isFrontpageEmbed ? "Home Assistant" : "Demo",
|
||||||
path: "home",
|
path: "home",
|
||||||
icon: "mdi:home-assistant",
|
icon: "mdi:home-assistant",
|
||||||
sections: [
|
badges: [
|
||||||
{
|
{
|
||||||
title: "Welcome 👋",
|
type: "entity",
|
||||||
cards: [{ type: "custom:ha-demo-card" }],
|
entity: "sensor.outdoor_temperature",
|
||||||
|
color: "red",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
type: "entity",
|
||||||
|
entity: "sensor.outdoor_humidity",
|
||||||
|
color: "indigo",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "entity",
|
||||||
|
entity: "device_tracker.car",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
sections: [
|
||||||
|
...(isFrontpageEmbed
|
||||||
|
? []
|
||||||
|
: [
|
||||||
|
{
|
||||||
|
cards: [
|
||||||
|
{
|
||||||
|
type: "heading",
|
||||||
|
heading: `${localize("ui.panel.page-demo.config.sections.titles.welcome")} 👋`,
|
||||||
|
},
|
||||||
|
{ type: "custom:ha-demo-card" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]),
|
||||||
{
|
{
|
||||||
cards: [
|
cards: [
|
||||||
{
|
{
|
||||||
type: "tile",
|
type: "heading",
|
||||||
entity: "cover.living_room_garden_shutter",
|
heading: localize(
|
||||||
name: "Garden",
|
"ui.panel.page-demo.config.sections.titles.living_room"
|
||||||
},
|
),
|
||||||
{
|
icon: "mdi:sofa",
|
||||||
type: "tile",
|
badges: [
|
||||||
entity: "cover.living_room_graveyard_shutter",
|
{
|
||||||
name: "Rear",
|
type: "entity",
|
||||||
},
|
entity: "sensor.living_room_temperature",
|
||||||
{
|
color: "red",
|
||||||
type: "tile",
|
},
|
||||||
entity: "cover.living_room_left_shutter",
|
{
|
||||||
name: "Left",
|
type: "entity",
|
||||||
},
|
entity: "sensor.living_room_humidity",
|
||||||
{
|
color: "indigo",
|
||||||
type: "tile",
|
},
|
||||||
entity: "cover.living_room_right_shutter",
|
],
|
||||||
name: "Right",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "tile",
|
type: "tile",
|
||||||
@@ -54,23 +79,34 @@ export const demoLovelaceSections: DemoConfig["lovelace"] = () => ({
|
|||||||
entity: "light.bar_lamp",
|
entity: "light.bar_lamp",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
graph: "line",
|
type: "tile",
|
||||||
type: "sensor",
|
entity: "cover.living_room_garden_shutter",
|
||||||
entity: "sensor.living_room_temperature",
|
name: "Blinds",
|
||||||
detail: 1,
|
|
||||||
name: "Temperature",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "tile",
|
type: "tile",
|
||||||
entity: "media_player.living_room_nest_mini",
|
entity: "media_player.living_room_nest_mini",
|
||||||
name: "Nest Mini",
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
title: "🛋️ Living room ",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "grid",
|
type: "grid",
|
||||||
cards: [
|
cards: [
|
||||||
|
{
|
||||||
|
type: "heading",
|
||||||
|
heading: localize(
|
||||||
|
"ui.panel.page-demo.config.sections.titles.kitchen"
|
||||||
|
),
|
||||||
|
icon: "mdi:fridge",
|
||||||
|
badges: [
|
||||||
|
{
|
||||||
|
type: "entity",
|
||||||
|
entity: "binary_sensor.kitchen_motion",
|
||||||
|
show_state: false,
|
||||||
|
color: "blue",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
type: "tile",
|
type: "tile",
|
||||||
entity: "cover.kitchen_shutter",
|
entity: "cover.kitchen_shutter",
|
||||||
@@ -99,14 +135,19 @@ export const demoLovelaceSections: DemoConfig["lovelace"] = () => ({
|
|||||||
{
|
{
|
||||||
type: "tile",
|
type: "tile",
|
||||||
entity: "media_player.kitchen_nest_audio",
|
entity: "media_player.kitchen_nest_audio",
|
||||||
name: "Nest Audio",
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
title: "👩🍳 Kitchen",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "grid",
|
type: "grid",
|
||||||
cards: [
|
cards: [
|
||||||
|
{
|
||||||
|
type: "heading",
|
||||||
|
heading: localize(
|
||||||
|
"ui.panel.page-demo.config.sections.titles.energy"
|
||||||
|
),
|
||||||
|
icon: "mdi:transmission-tower",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
type: "tile",
|
type: "tile",
|
||||||
entity: "binary_sensor.tesla_wall_connector_vehicle_connected",
|
entity: "binary_sensor.tesla_wall_connector_vehicle_connected",
|
||||||
@@ -144,11 +185,17 @@ export const demoLovelaceSections: DemoConfig["lovelace"] = () => ({
|
|||||||
color: "dark-grey",
|
color: "dark-grey",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
title: "⚡️ Energy",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "grid",
|
type: "grid",
|
||||||
cards: [
|
cards: [
|
||||||
|
{
|
||||||
|
type: "heading",
|
||||||
|
heading: localize(
|
||||||
|
"ui.panel.page-demo.config.sections.titles.climate"
|
||||||
|
),
|
||||||
|
icon: "mdi:thermometer",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
type: "tile",
|
type: "tile",
|
||||||
entity: "sun.sun",
|
entity: "sun.sun",
|
||||||
@@ -181,16 +228,38 @@ export const demoLovelaceSections: DemoConfig["lovelace"] = () => ({
|
|||||||
state_content: ["preset_mode", "current_temperature"],
|
state_content: ["preset_mode", "current_temperature"],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
title: "🌤️ Climate",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "grid",
|
type: "grid",
|
||||||
cards: [
|
cards: [
|
||||||
|
{
|
||||||
|
type: "heading",
|
||||||
|
heading: localize(
|
||||||
|
"ui.panel.page-demo.config.sections.titles.study"
|
||||||
|
),
|
||||||
|
icon: "mdi:desk-lamp",
|
||||||
|
badges: [
|
||||||
|
{
|
||||||
|
type: "entity",
|
||||||
|
entity: "switch.in_meeting",
|
||||||
|
state: "on",
|
||||||
|
state_content: "name",
|
||||||
|
visibility: [
|
||||||
|
{
|
||||||
|
condition: "state",
|
||||||
|
state: "on",
|
||||||
|
entity: "switch.in_meeting",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
type: "tile",
|
type: "tile",
|
||||||
entity: "cover.study_shutter",
|
entity: "cover.study_shutter",
|
||||||
name: "Shutter",
|
name: "Shutter",
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
type: "tile",
|
type: "tile",
|
||||||
entity: "light.study_spotlights",
|
entity: "light.study_spotlights",
|
||||||
@@ -199,7 +268,6 @@ export const demoLovelaceSections: DemoConfig["lovelace"] = () => ({
|
|||||||
{
|
{
|
||||||
type: "tile",
|
type: "tile",
|
||||||
entity: "media_player.study_nest_hub",
|
entity: "media_player.study_nest_hub",
|
||||||
name: "Nest Hub",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "tile",
|
type: "tile",
|
||||||
@@ -208,12 +276,23 @@ export const demoLovelaceSections: DemoConfig["lovelace"] = () => ({
|
|||||||
color: "brown",
|
color: "brown",
|
||||||
icon: "mdi:desk",
|
icon: "mdi:desk",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
type: "tile",
|
||||||
|
entity: "switch.in_meeting",
|
||||||
|
name: "Meeting mode",
|
||||||
|
},
|
||||||
],
|
],
|
||||||
title: "🧑💻 Study",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "grid",
|
type: "grid",
|
||||||
cards: [
|
cards: [
|
||||||
|
{
|
||||||
|
type: "heading",
|
||||||
|
heading: localize(
|
||||||
|
"ui.panel.page-demo.config.sections.titles.outdoor"
|
||||||
|
),
|
||||||
|
icon: "mdi:tree",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
type: "tile",
|
type: "tile",
|
||||||
entity: "light.outdoor_light",
|
entity: "light.outdoor_light",
|
||||||
@@ -243,11 +322,17 @@ export const demoLovelaceSections: DemoConfig["lovelace"] = () => ({
|
|||||||
name: "Illuminance",
|
name: "Illuminance",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
title: "🌳 Outdoor",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "grid",
|
type: "grid",
|
||||||
cards: [
|
cards: [
|
||||||
|
{
|
||||||
|
type: "heading",
|
||||||
|
heading: localize(
|
||||||
|
"ui.panel.page-demo.config.sections.titles.updates"
|
||||||
|
),
|
||||||
|
icon: "mdi:update",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
type: "tile",
|
type: "tile",
|
||||||
entity: "automation.home_assistant_auto_update",
|
entity: "automation.home_assistant_auto_update",
|
||||||
@@ -273,7 +358,6 @@ export const demoLovelaceSections: DemoConfig["lovelace"] = () => ({
|
|||||||
icon: "mdi:home-assistant",
|
icon: "mdi:home-assistant",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
title: "🎉 Updates",
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import { convertEntities } from "../../../../src/fake_data/entity";
|
import { convertEntities } from "../../../../src/fake_data/entity";
|
||||||
import { DemoConfig } from "../types";
|
import type { DemoConfig } from "../types";
|
||||||
|
|
||||||
export const demoEntitiesTeachingbirds: DemoConfig["entities"] = () =>
|
export const demoEntitiesTeachingbirds: DemoConfig["entities"] = () =>
|
||||||
convertEntities({
|
convertEntities({
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user