Compare commits
902 commits
auth-v3.0.
...
main
Author | SHA1 | Date | |
---|---|---|---|
![]() |
ae61fc9c6f | ||
![]() |
c291fa70d3 | ||
![]() |
232acfa211 | ||
![]() |
f25f119ca1 | ||
![]() |
89a61b3bf7 | ||
![]() |
380d37267b | ||
![]() |
9cf5691e42 | ||
![]() |
8f474a4500 | ||
![]() |
c7be2270ff | ||
![]() |
ced1f0bd79 | ||
![]() |
9f58f1eeb3 | ||
![]() |
04be2b6a2c | ||
![]() |
9f361237b1 | ||
![]() |
8cb7cae7b7 | ||
![]() |
a2a209a849 | ||
![]() |
d413c4f4c1 | ||
![]() |
ee8976e92b | ||
![]() |
baa90c42ad | ||
![]() |
30ade541df | ||
![]() |
86fb8ebfaf | ||
![]() |
b2e8c3c0eb | ||
![]() |
e203a8378e | ||
![]() |
b100f1d4bf | ||
![]() |
7b4559f3ca | ||
![]() |
eac142025d | ||
![]() |
c5aa536c3b | ||
![]() |
05406333e4 | ||
![]() |
8ebd50606a | ||
![]() |
cbcfc243fc | ||
![]() |
7d497b5ae1 | ||
![]() |
b28f6c3d8c | ||
![]() |
71a8049a35 | ||
![]() |
e95cba0ace | ||
![]() |
e836ada0d6 | ||
![]() |
19a104374d | ||
![]() |
693ef45e2c | ||
![]() |
55bdb070ce | ||
![]() |
27127ff3d4 | ||
![]() |
345c706814 | ||
![]() |
49133b7b86 | ||
![]() |
3a5311cdcc | ||
![]() |
7182795732 | ||
![]() |
ca00b3b558 | ||
![]() |
4bcb765810 | ||
![]() |
17b49595a0 | ||
![]() |
b99c573d3a | ||
![]() |
d3d3e4dbed | ||
![]() |
ba1af5eaf0 | ||
![]() |
14cf59c1e5 | ||
![]() |
452872156a | ||
![]() |
4f31bd625d | ||
![]() |
6bf6f78147 | ||
![]() |
5576f99548 | ||
![]() |
5bbe768acb | ||
![]() |
babe378301 | ||
![]() |
b2fda16561 | ||
![]() |
6d289d73db | ||
![]() |
17acf4b3ee | ||
![]() |
4d666d4b01 | ||
![]() |
619f8319ed | ||
![]() |
3261da3515 | ||
![]() |
d0d491f7f5 | ||
![]() |
db3764d448 | ||
![]() |
5fe5451f5c | ||
![]() |
6d3d5d03f8 | ||
![]() |
582eb9e1ea | ||
![]() |
51770a11ef | ||
![]() |
1ea7a8f3a7 | ||
![]() |
b4536a7aee | ||
![]() |
9d2be29fad | ||
![]() |
f92a18efca | ||
![]() |
af382d483d | ||
![]() |
99f1ba799d | ||
![]() |
1548bcd378 | ||
![]() |
c2fc0a3d57 | ||
![]() |
39a706ea20 | ||
![]() |
38d6464f55 | ||
![]() |
c5b6297cea | ||
![]() |
390b4b1f81 | ||
![]() |
b19b34b3dc | ||
![]() |
5690d613bb | ||
![]() |
bb713cfc76 | ||
![]() |
4a0c93373d | ||
![]() |
b42759d473 | ||
![]() |
2e93281368 | ||
![]() |
c18be32c09 | ||
![]() |
650163c341 | ||
![]() |
d101208baa | ||
![]() |
76f7215269 | ||
![]() |
621c482529 | ||
![]() |
314c8f69f2 | ||
![]() |
1f45cf00c7 | ||
![]() |
e0e80ee91f | ||
![]() |
225278adb7 | ||
![]() |
8d30bfbefa | ||
![]() |
ad96f679c9 | ||
![]() |
4b896d3aab | ||
![]() |
533e6d06e7 | ||
![]() |
e88b5c99ba | ||
![]() |
1ec7e02695 | ||
![]() |
19e08cf803 | ||
![]() |
08073b927c | ||
![]() |
711a44412d | ||
![]() |
c9f94f062b | ||
![]() |
c8205b8475 | ||
![]() |
b0d3fcfe79 | ||
![]() |
11a354c560 | ||
![]() |
823f739c32 | ||
![]() |
f8876c8154 | ||
![]() |
90db45d845 | ||
![]() |
6a1f5945b9 | ||
![]() |
f7ca838428 | ||
![]() |
2b065dd68d | ||
![]() |
f168ea9e1e | ||
![]() |
58702103f3 | ||
![]() |
dfb3a6f65c | ||
![]() |
491f38b120 | ||
![]() |
79c0880c9c | ||
![]() |
834b8f78b7 | ||
![]() |
cbf0336cd0 | ||
![]() |
431d629641 | ||
![]() |
94c1cc011b | ||
![]() |
b26b0759d6 | ||
![]() |
d51fb99fd3 | ||
![]() |
0379216e05 | ||
![]() |
ccd486f659 | ||
![]() |
ce3ab55069 | ||
![]() |
34effef810 | ||
![]() |
56aceb589d | ||
![]() |
92a2506f8a | ||
![]() |
e23bc2602f | ||
![]() |
69beecb7bb | ||
![]() |
880b13f436 | ||
![]() |
9061caac99 | ||
![]() |
11cc8e46b7 | ||
![]() |
54820689c2 | ||
![]() |
acebb86fec | ||
![]() |
367e09599d | ||
![]() |
b9fe509567 | ||
![]() |
82bffd81de | ||
![]() |
7340443b86 | ||
![]() |
2cd1dfd720 | ||
![]() |
3c8d29bcdc | ||
![]() |
06a698ddbb | ||
![]() |
3b8c48e92d | ||
![]() |
3c0cb20a9b | ||
![]() |
74bb169f0d | ||
![]() |
302890baef | ||
![]() |
54e33d3f42 | ||
![]() |
0adb94f405 | ||
![]() |
7d634aa703 | ||
![]() |
b1e0c83733 | ||
![]() |
d4af7792d4 | ||
![]() |
f301ab57f2 | ||
![]() |
7b0f5909b5 | ||
![]() |
e9064f6904 | ||
![]() |
0d21fc77b5 | ||
![]() |
b26c6e9c0d | ||
![]() |
057d11f39b | ||
![]() |
c9de6d7a82 | ||
![]() |
698ac9f29e | ||
![]() |
a0d26c860c | ||
![]() |
bd2444d353 | ||
![]() |
ca24a86179 | ||
![]() |
fffe96a4c7 | ||
![]() |
0ec75c2435 | ||
![]() |
cb78c848d6 | ||
![]() |
6594db9393 | ||
![]() |
f6c40ee67d | ||
![]() |
36aa33ed5a | ||
![]() |
776dba4fb0 | ||
![]() |
7f49f530c5 | ||
![]() |
ef6fe80944 | ||
![]() |
370b28f9e4 | ||
![]() |
05e737cb11 | ||
![]() |
0fdb58eda1 | ||
![]() |
1ce90839fe | ||
![]() |
697946f415 | ||
![]() |
cc91cb8012 | ||
![]() |
754de7065f | ||
![]() |
5587373b42 | ||
![]() |
f1d1a4a9e1 | ||
![]() |
dc38a8bc9f | ||
![]() |
edf9f743f4 | ||
![]() |
fec040e528 | ||
![]() |
86f96a5713 | ||
![]() |
c3fb472287 | ||
![]() |
eaf8b9cebc | ||
![]() |
2ce9212457 | ||
![]() |
4fa59ce258 | ||
![]() |
59ed89cba1 | ||
![]() |
623b71715d | ||
![]() |
a74943698f | ||
![]() |
bfe8fd83ac | ||
![]() |
0a01cac57b | ||
![]() |
b7f248fa93 | ||
![]() |
d814b6cdf0 | ||
![]() |
1712bf60cb | ||
![]() |
369a5a5233 | ||
![]() |
9bae31d748 | ||
![]() |
11453b327f | ||
![]() |
7780c1c7b7 | ||
![]() |
0f1c98d0d0 | ||
![]() |
48fcbdc98c | ||
![]() |
90d0196d47 | ||
![]() |
30a8691c7f | ||
![]() |
69cea6786d | ||
![]() |
ccac5e73a3 | ||
![]() |
3e79c8cf28 | ||
![]() |
31dee1249d | ||
![]() |
e5a293a6ab | ||
![]() |
ffcb68b32f | ||
![]() |
a8af90dfee | ||
![]() |
6ee38cb291 | ||
![]() |
3810df1b20 | ||
![]() |
cc8e345a17 | ||
![]() |
63653411b8 | ||
![]() |
c4a6011621 | ||
![]() |
1ee52c780f | ||
![]() |
b402662c09 | ||
![]() |
51756d45d9 | ||
![]() |
a3bb7ad85a | ||
![]() |
17058299c1 | ||
![]() |
65de02d8d9 | ||
![]() |
1f9e222d6e | ||
![]() |
3d96be6c27 | ||
![]() |
1bbe495306 | ||
![]() |
a76f3ca1b3 | ||
![]() |
7800b7db32 | ||
![]() |
ea2a355bcc | ||
![]() |
d585b75514 | ||
![]() |
5caa32b1e0 | ||
![]() |
11402d7819 | ||
![]() |
a41f705dad | ||
![]() |
69b808e62c | ||
![]() |
1e1e629891 | ||
![]() |
a7e96d055c | ||
![]() |
5e2261f793 | ||
![]() |
206be5c16f | ||
![]() |
41c87efc5a | ||
![]() |
171af35d85 | ||
![]() |
99f47dc1ae | ||
![]() |
cc7a516eba | ||
![]() |
26436f116f | ||
![]() |
9eab415906 | ||
![]() |
14655e5633 | ||
![]() |
51dc8d1de6 | ||
![]() |
51568e6c56 | ||
![]() |
d2743f4121 | ||
![]() |
05c50e78bc | ||
![]() |
9ac7b29e96 | ||
![]() |
42106a72b3 | ||
![]() |
2504046e26 | ||
![]() |
a104f36561 | ||
![]() |
b26afdcf2e | ||
![]() |
bf707ae02d | ||
![]() |
68648d2f6c | ||
![]() |
371b8bf9cc | ||
![]() |
3b89471b87 | ||
![]() |
8a2117f9d4 | ||
![]() |
132ddd3648 | ||
![]() |
048aaee40d | ||
![]() |
04475110ce | ||
![]() |
02366eb27f | ||
![]() |
6c3953e855 | ||
![]() |
201286f59a | ||
![]() |
b00bffd785 | ||
![]() |
d477b55071 | ||
![]() |
227b7ddba0 | ||
![]() |
d12f570178 | ||
![]() |
70dc660f5a | ||
![]() |
e4c379963f | ||
![]() |
e44be63586 | ||
![]() |
6d5436c885 | ||
![]() |
d75abcf6a7 | ||
![]() |
b3229785a0 | ||
![]() |
bd8757bbb8 | ||
![]() |
92bafa7c38 | ||
![]() |
df756076e8 | ||
![]() |
ffc9eecbd1 | ||
![]() |
678efd1e8b | ||
![]() |
9ab82621b9 | ||
![]() |
59c2c7e343 | ||
![]() |
8c3c0b2128 | ||
![]() |
954581093d | ||
![]() |
78afae4013 | ||
![]() |
7811c58214 | ||
![]() |
85a8f6b7cf | ||
![]() |
f60e750848 | ||
![]() |
a086f36433 | ||
![]() |
4cb49c0b4a | ||
![]() |
334587474f | ||
![]() |
0d52737c49 | ||
![]() |
d4dc080231 | ||
![]() |
f8d35c3dcf | ||
![]() |
c20b9fa5fa | ||
![]() |
6a8fa727a9 | ||
![]() |
7712a8bd10 | ||
![]() |
4feb8fd1f1 | ||
![]() |
994876911a | ||
![]() |
d6398bd8fc | ||
![]() |
43064b617a | ||
![]() |
789783a370 | ||
![]() |
9db1197c19 | ||
![]() |
56a71c2cd8 | ||
![]() |
608c97603b | ||
![]() |
a9721e7744 | ||
![]() |
44e5af0434 | ||
![]() |
dfbdc94e61 | ||
![]() |
71d3427879 | ||
![]() |
d235ff1035 | ||
![]() |
ee5be7f339 | ||
![]() |
9b0e8b265d | ||
![]() |
c0f243cee0 | ||
![]() |
1bd2033a63 | ||
![]() |
982f0d8f77 | ||
![]() |
9e26b81adf | ||
![]() |
94cc26aead | ||
![]() |
d4b4007d96 | ||
![]() |
2daf5c8fde | ||
![]() |
7a5d4cedf6 | ||
![]() |
2abc57f981 | ||
![]() |
2d5894c5d6 | ||
![]() |
0d43c0d326 | ||
![]() |
1b46e159da | ||
![]() |
a4d6fece41 | ||
![]() |
86b24a4ccf | ||
![]() |
8520cdd1bb | ||
![]() |
0655617a9e | ||
![]() |
4dbc8ab31e | ||
![]() |
1a376a1a9b | ||
![]() |
6e82964bf2 | ||
![]() |
fdd5ffd45c | ||
![]() |
ccb5c48c7d | ||
![]() |
074d315c9f | ||
![]() |
b8734fcc6c | ||
![]() |
a8229f325d | ||
![]() |
5768edb3a5 | ||
![]() |
8bc80d2821 | ||
![]() |
825f5ff88d | ||
![]() |
5aee42d59d | ||
![]() |
c8be764f35 | ||
![]() |
4e2f7c95e3 | ||
![]() |
56cd3a9949 | ||
![]() |
12ce21cd08 | ||
![]() |
ae5496f306 | ||
![]() |
d23638c30d | ||
![]() |
5724fad813 | ||
![]() |
ffe54f591c | ||
![]() |
13f9358a4f | ||
![]() |
4289ab2393 | ||
![]() |
4032952168 | ||
![]() |
d104fc6788 | ||
![]() |
85396158aa | ||
![]() |
3d91b548db | ||
![]() |
e500347fc5 | ||
![]() |
9c667efee5 | ||
![]() |
0877d9c788 | ||
![]() |
be9f8b8b1d | ||
![]() |
b1314729b1 | ||
![]() |
0e957cbecb | ||
![]() |
57e9ef10af | ||
![]() |
ee7c1bafc3 | ||
![]() |
93473ebd12 | ||
![]() |
e9be2b46a1 | ||
![]() |
e4bec56ea3 | ||
![]() |
1e3fca2835 | ||
![]() |
58851f2d6e | ||
![]() |
5172ce3126 | ||
![]() |
3e1e26feb0 | ||
![]() |
aa8e128c44 | ||
![]() |
cacb50b040 | ||
![]() |
58dcceca9f | ||
![]() |
84f7d20966 | ||
![]() |
76848c826e | ||
![]() |
09b2732d76 | ||
![]() |
a48c8b481e | ||
![]() |
bd28254021 | ||
![]() |
7263c45300 | ||
![]() |
613dffa03f | ||
![]() |
131108a6db | ||
![]() |
90c0ad08da | ||
![]() |
a222e06634 | ||
![]() |
bcf78fb4b9 | ||
![]() |
b00ee96dde | ||
![]() |
ea587b6ccd | ||
![]() |
af88756b5d | ||
![]() |
df867b5957 | ||
![]() |
4bfb69dcc4 | ||
![]() |
b1ccc39178 | ||
![]() |
b0ef3a070e | ||
![]() |
e331443691 | ||
![]() |
285b1f9527 | ||
![]() |
7a37eca4e6 | ||
![]() |
cd9db4d10f | ||
![]() |
460025ce4a | ||
![]() |
b0fe3946ef | ||
![]() |
8a2e2a8f80 | ||
![]() |
c8efc5fca0 | ||
![]() |
992ca1c4de | ||
![]() |
baf24aca99 | ||
![]() |
76a10fb84c | ||
![]() |
1f78f71d0d | ||
![]() |
88b75c1191 | ||
![]() |
372fdd8a05 | ||
![]() |
63618f00b2 | ||
![]() |
41edee7d04 | ||
![]() |
9e8a127d4a | ||
![]() |
1299e12d92 | ||
![]() |
a8da045a32 | ||
![]() |
d7e7aaa26f | ||
![]() |
1f82599fb6 | ||
![]() |
345eed5209 | ||
![]() |
725e628537 | ||
![]() |
579239ad54 | ||
![]() |
288adb2e7c | ||
![]() |
f441a0b456 | ||
![]() |
d9232c1b83 | ||
![]() |
1932a92cb8 | ||
![]() |
9251fd8196 | ||
![]() |
7f358c4bff | ||
![]() |
e9392d8f33 | ||
![]() |
e414128f18 | ||
![]() |
ccec166fa0 | ||
![]() |
1e5512b36f | ||
![]() |
3d906490a6 | ||
![]() |
9946d08697 | ||
![]() |
83a873672f | ||
![]() |
cdf3d0e037 | ||
![]() |
eef18ca054 | ||
![]() |
c142ed07b8 | ||
![]() |
6ab1371077 | ||
![]() |
b2c274e73b | ||
![]() |
48e78d170d | ||
![]() |
df1ca5d583 | ||
![]() |
17696c6665 | ||
![]() |
4f9fc9fb6a | ||
![]() |
ef33754108 | ||
![]() |
3724ea0af1 | ||
![]() |
cb51e3e5b5 | ||
![]() |
848b9c3b1b | ||
![]() |
71ca8a414c | ||
![]() |
4af9d46111 | ||
![]() |
2dc17dcec8 | ||
![]() |
a7bcd62a9d | ||
![]() |
3b8cae068e | ||
![]() |
f4024d2007 | ||
![]() |
a3eba12ccf | ||
![]() |
2cf193c2d0 | ||
![]() |
ed23286331 | ||
![]() |
36ac637206 | ||
![]() |
2205d21770 | ||
![]() |
5815b57fe3 | ||
![]() |
7c7ee6c432 | ||
![]() |
bb9c0673a8 | ||
![]() |
022d89b4a0 | ||
![]() |
e188382f09 | ||
![]() |
75f0b0481b | ||
![]() |
d7bd735f7b | ||
![]() |
1f2c3f73df | ||
![]() |
6652125804 | ||
![]() |
c28f6c36bb | ||
![]() |
605112eeb9 | ||
![]() |
a05d7d8660 | ||
![]() |
05f5e8a175 | ||
![]() |
8e341310a2 | ||
![]() |
45d46d5ca8 | ||
![]() |
7045dbaeff | ||
![]() |
fc6830bdaf | ||
![]() |
abff589c21 | ||
![]() |
3ab2535193 | ||
![]() |
da5ceea0db | ||
![]() |
c235fb85b4 | ||
![]() |
5ba46a0707 | ||
![]() |
38d622825b | ||
![]() |
eee168837e | ||
![]() |
c906480dee | ||
![]() |
4db3c9fe95 | ||
![]() |
7623e69de3 | ||
![]() |
33a0641c52 | ||
![]() |
5c85fe764a | ||
![]() |
b74a572f1a | ||
![]() |
acf8fd6e63 | ||
![]() |
d08edacb66 | ||
![]() |
b78a65dc51 | ||
![]() |
54e1198088 | ||
![]() |
6eb34937b8 | ||
![]() |
089aa16bc6 | ||
![]() |
8c373857a2 | ||
![]() |
63f22680f4 | ||
![]() |
5e2f689265 | ||
![]() |
bcac9b9ce9 | ||
![]() |
9ff4fc1b81 | ||
![]() |
ee9eaedd99 | ||
![]() |
dd29e55b53 | ||
![]() |
8027579080 | ||
![]() |
cb4fa38004 | ||
![]() |
aff27a2211 | ||
![]() |
dc5a8ebd44 | ||
![]() |
0ecbb73f1e | ||
![]() |
115f1bd42e | ||
![]() |
68be7f69d8 | ||
![]() |
bd495c3860 | ||
![]() |
b4736fb1d6 | ||
![]() |
71b572917e | ||
![]() |
3c24345b68 | ||
![]() |
ea8846ee0c | ||
![]() |
077b46e490 | ||
![]() |
cf6b311c14 | ||
![]() |
ade70f40a9 | ||
![]() |
35aed07bc6 | ||
![]() |
319dc055de | ||
![]() |
662dc1a32b | ||
![]() |
38a40a5ace | ||
![]() |
915a3f646d | ||
![]() |
f275761c4b | ||
![]() |
cfd656b360 | ||
![]() |
95ba8a368b | ||
![]() |
8c27eb59ce | ||
![]() |
267b3669f2 | ||
![]() |
1ab42640d9 | ||
![]() |
cdc6972d53 | ||
![]() |
5c1bc220e9 | ||
![]() |
7e60e8532f | ||
![]() |
4bafdf8922 | ||
![]() |
6ea8b972bd | ||
![]() |
793fc3aa46 | ||
![]() |
6b70c721d4 | ||
![]() |
88bdb06d05 | ||
![]() |
2e17e2b78d | ||
![]() |
c6129c32da | ||
![]() |
d650bac501 | ||
![]() |
745daf39f7 | ||
![]() |
9ecd406e56 | ||
![]() |
74ae4ea74f | ||
![]() |
ca3172c33e | ||
![]() |
689833d8aa | ||
![]() |
09fadecd7a | ||
![]() |
10b04c6ad3 | ||
![]() |
f80f7a03e1 | ||
![]() |
4cff6b1299 | ||
![]() |
7e5561e5cd | ||
![]() |
b1cbf8526b | ||
![]() |
49d5370d47 | ||
![]() |
8d4f9fe966 | ||
![]() |
29b9bee1be | ||
![]() |
a80c9dd589 | ||
![]() |
046a96f586 | ||
![]() |
740ca907f2 | ||
![]() |
c783735e86 | ||
![]() |
cbf2a77d5b | ||
![]() |
9f5c5fde49 | ||
![]() |
1cd31d2cab | ||
![]() |
4b6ecbdd30 | ||
![]() |
7d2633190f | ||
![]() |
52f605831f | ||
![]() |
8b1545239c | ||
![]() |
aad1327705 | ||
![]() |
8058c6b621 | ||
![]() |
d03d8d564d | ||
![]() |
87571159cc | ||
![]() |
97d8c5f83e | ||
![]() |
a2023bd457 | ||
![]() |
a16910a4ee | ||
![]() |
54d3ad9743 | ||
![]() |
6235f7ee78 | ||
![]() |
9eeab36392 | ||
![]() |
f422e30a8e | ||
![]() |
58cd9350c0 | ||
![]() |
ab5985a08b | ||
![]() |
19f2c5f00a | ||
![]() |
707916f677 | ||
![]() |
8b236cde09 | ||
![]() |
968eaaf5f6 | ||
![]() |
caa72ba830 | ||
![]() |
2692d0a34f | ||
![]() |
44898415e7 | ||
![]() |
811ffe0117 | ||
![]() |
43f01c31da | ||
![]() |
a0e9913f43 | ||
![]() |
b256bb2757 | ||
![]() |
3eebfdd037 | ||
![]() |
a577611e65 | ||
![]() |
b2a2078045 | ||
![]() |
7617817798 | ||
![]() |
f173bc4038 | ||
![]() |
3828fa328e | ||
![]() |
f101468a8d | ||
![]() |
52a7f2753e | ||
![]() |
7fd5ffc0e6 | ||
![]() |
43cbfbfa33 | ||
![]() |
7370557b08 | ||
![]() |
f0ebdb211c | ||
![]() |
2f7e0cd1ef | ||
![]() |
d429efaf14 | ||
![]() |
7b8816a4bf | ||
![]() |
7e00a470aa | ||
![]() |
1ae4482fe5 | ||
![]() |
d0420ce477 | ||
![]() |
b022ef6d1e | ||
![]() |
244d562207 | ||
![]() |
3fbfa8c0e6 | ||
![]() |
6f6f976dec | ||
![]() |
07458fb247 | ||
![]() |
72ff6e2cf3 | ||
![]() |
e0fbb2620b | ||
![]() |
462d1d4854 | ||
![]() |
05a4e9f90b | ||
![]() |
3806ee3232 | ||
![]() |
e829f7b62f | ||
![]() |
4b6641d7d8 | ||
![]() |
093f48fb63 | ||
![]() |
759c8aa404 | ||
![]() |
c80208e754 | ||
![]() |
7097ce3cf4 | ||
![]() |
efb1170b44 | ||
![]() |
7312633e02 | ||
![]() |
3786c9def9 | ||
![]() |
6fe8dc7c66 | ||
![]() |
9e87b4a2cc | ||
![]() |
dad427a498 | ||
![]() |
4c25997bb6 | ||
![]() |
6a0a9bad1e | ||
![]() |
731610ed94 | ||
![]() |
e875eb1389 | ||
![]() |
3253a2bf26 | ||
![]() |
8225697e43 | ||
![]() |
f49ede4a74 | ||
![]() |
9cdd4fd713 | ||
![]() |
fa466d715f | ||
![]() |
c1587cc5ea | ||
![]() |
ae046e33b4 | ||
![]() |
37ab467da5 | ||
![]() |
cc682a0a09 | ||
![]() |
864f8444d5 | ||
![]() |
edf99385dc | ||
![]() |
cde17441d6 | ||
![]() |
4ac295e1e2 | ||
![]() |
a0502886b6 | ||
![]() |
7be1b63822 | ||
![]() |
01aecb9742 | ||
![]() |
a0fa90cb50 | ||
![]() |
6d3e1325c4 | ||
![]() |
4095b14589 | ||
![]() |
a92081e703 | ||
![]() |
f3f85e81ca | ||
![]() |
ecc1bc9980 | ||
![]() |
2b88daa15f | ||
![]() |
a9ca8a4a24 | ||
![]() |
ab0a99cf76 | ||
![]() |
e20f13f02b | ||
![]() |
34798c344c | ||
![]() |
e7992674d5 | ||
![]() |
74247c4563 | ||
![]() |
be1b4b359c | ||
![]() |
79e763bf16 | ||
![]() |
afbb1c69c2 | ||
![]() |
417c5eab1c | ||
![]() |
ba58ac1358 | ||
![]() |
7a5e1263e0 | ||
![]() |
45d18b187c | ||
![]() |
e3fd836901 | ||
![]() |
51d15cc441 | ||
![]() |
72e677e9e5 | ||
![]() |
6f26901073 | ||
![]() |
f61a5f91b6 | ||
![]() |
d4d9253f1a | ||
![]() |
b1eb6c11b2 | ||
![]() |
618b152f17 | ||
![]() |
e3b8d8975f | ||
![]() |
624a06c3f8 | ||
![]() |
e3b1cb8014 | ||
![]() |
e09b77770d | ||
![]() |
ef4135f378 | ||
![]() |
38381f6bb0 | ||
![]() |
7d414a7b7d | ||
![]() |
2ce078e173 | ||
![]() |
8801dc1a7a | ||
![]() |
5cf10c9c9b | ||
![]() |
c58a8dc773 | ||
![]() |
c67a1fa52a | ||
![]() |
5a5cdc8b6b | ||
![]() |
da7302b677 | ||
![]() |
d65264e8e8 | ||
![]() |
2cb08569c9 | ||
![]() |
5fec61fc1b | ||
![]() |
107b79eae6 | ||
![]() |
2302b930d3 | ||
![]() |
fbec7db865 | ||
![]() |
96b9019fff | ||
![]() |
21451efa6b | ||
![]() |
259787ff41 | ||
![]() |
481410f183 | ||
![]() |
eb8294ce95 | ||
![]() |
9c09af54b3 | ||
![]() |
642e36b050 | ||
![]() |
38c0c44331 | ||
![]() |
3860d0a230 | ||
![]() |
ba107c2d25 | ||
![]() |
f3647df1e9 | ||
![]() |
01914ed3ce | ||
![]() |
5710cb2d35 | ||
![]() |
6df5559d75 | ||
![]() |
b90aed0b4b | ||
![]() |
0eb876c985 | ||
![]() |
5996981c13 | ||
![]() |
f459b1c2dd | ||
![]() |
3ba6aea827 | ||
![]() |
90db558498 | ||
![]() |
cab649ef77 | ||
![]() |
5b6df99486 | ||
![]() |
c902f24e63 | ||
![]() |
aad0a5a1d4 | ||
![]() |
b18734f63e | ||
![]() |
21adb91c2f | ||
![]() |
d4086357ec | ||
![]() |
efaf869e95 | ||
![]() |
74f8f7aaf3 | ||
![]() |
222716f6f9 | ||
![]() |
af8d919ff2 | ||
![]() |
f3d18edf98 | ||
![]() |
fac087c81b | ||
![]() |
c920aacd1b | ||
![]() |
16da5056ea | ||
![]() |
73007ee541 | ||
![]() |
915da41c86 | ||
![]() |
c224e38ddf | ||
![]() |
e82cda1e82 | ||
![]() |
c8154784f1 | ||
![]() |
52038b8972 | ||
![]() |
d43ed15cdf | ||
![]() |
24f7b191b4 | ||
![]() |
acb3e05fc8 | ||
![]() |
4cb15268e9 | ||
![]() |
250cb33bc9 | ||
![]() |
eeedf8b3c2 | ||
![]() |
b6aec20b22 | ||
![]() |
0b08afdbe2 | ||
![]() |
412e93c9fa | ||
![]() |
67f26a1551 | ||
![]() |
2d58558737 | ||
![]() |
4a2b5fe27d | ||
![]() |
3d452c4e98 | ||
![]() |
b00ab0541e | ||
![]() |
cbc7034d47 | ||
![]() |
d19d7ffe79 | ||
![]() |
6c02b03426 | ||
![]() |
2ae37682e7 | ||
![]() |
f261ee7184 | ||
![]() |
add66569dd | ||
![]() |
bb3a37adf5 | ||
![]() |
7c6001321f | ||
![]() |
1b9c81c50c | ||
![]() |
1996d86835 | ||
![]() |
0c72fd2a69 | ||
![]() |
723253a12c | ||
![]() |
18f202d3e4 | ||
![]() |
0777013b93 | ||
![]() |
04a33e6f65 | ||
![]() |
f1a7256a14 | ||
![]() |
78af84450a | ||
![]() |
2456c02956 | ||
![]() |
199dad3705 | ||
![]() |
ad73496c4d | ||
![]() |
ef03c6f40a | ||
![]() |
bd4c506fdd | ||
![]() |
be06d45e3a | ||
![]() |
7429791a19 | ||
![]() |
49671cbda3 | ||
![]() |
81c94b1e73 | ||
![]() |
3fb323ef29 | ||
![]() |
d8bf0ad2d5 | ||
![]() |
b48cb84100 | ||
![]() |
f1fd74b119 | ||
![]() |
f5a9679c0e | ||
![]() |
19007c38b5 | ||
![]() |
583c09155b | ||
![]() |
5bce9abb5c | ||
![]() |
c6f9bbbbda | ||
![]() |
517b099de8 | ||
![]() |
2163201046 | ||
![]() |
dd3b0be8f2 | ||
![]() |
6a9b670d52 | ||
![]() |
0176b01fea | ||
![]() |
15f9176208 | ||
![]() |
744ded4922 | ||
![]() |
b21466bf13 | ||
![]() |
6a240ee030 | ||
![]() |
922550b1a3 | ||
![]() |
fb3a77bf94 | ||
![]() |
934d0bb3a0 | ||
![]() |
11937a42b4 | ||
![]() |
cb8f66fcaa | ||
![]() |
786ddf438b | ||
![]() |
e10cb5d456 | ||
![]() |
a8b154b46e | ||
![]() |
172678dc42 | ||
![]() |
8fefc22180 | ||
![]() |
8e6617eed5 | ||
![]() |
faa07a0704 | ||
![]() |
57fec06d73 | ||
![]() |
e2ed836b16 | ||
![]() |
bdb7ce2f03 | ||
![]() |
255b566342 | ||
![]() |
c85692360c | ||
![]() |
8e322114b7 | ||
![]() |
226808aadb | ||
![]() |
4cb7334868 | ||
![]() |
814c0ad4b6 | ||
![]() |
51b51ff2b1 | ||
![]() |
323521d496 | ||
![]() |
baec7a2af8 | ||
![]() |
7e9c6a7f81 | ||
![]() |
5b339fc30e | ||
![]() |
f663bbfc53 | ||
![]() |
1af3d2d2db | ||
![]() |
29c58d5554 | ||
![]() |
e7670bfee6 | ||
![]() |
a75c440dc2 | ||
![]() |
768fa3d1ce | ||
![]() |
a3b6a72315 | ||
![]() |
7f66bd2ed0 | ||
![]() |
f5ea834fad | ||
![]() |
aa79c4ee24 | ||
![]() |
8c6bb30578 | ||
![]() |
8aed14ace6 | ||
![]() |
b56b0c47d0 | ||
![]() |
2a04192b3c | ||
![]() |
67134db3a4 | ||
![]() |
44a5b97de1 | ||
![]() |
ab875ea9a9 | ||
![]() |
5f468e6c63 | ||
![]() |
1d527f9e02 | ||
![]() |
afa8a372d2 | ||
![]() |
6c287775d4 | ||
![]() |
9aafe137a1 | ||
![]() |
d6db3de6b1 | ||
![]() |
03e5f06bf2 | ||
![]() |
aa58989299 | ||
![]() |
5b94cbf912 | ||
![]() |
3869802e4c | ||
![]() |
a09b71cc15 | ||
![]() |
b1b3bcc534 | ||
![]() |
85f76497b4 | ||
![]() |
005ab0814f | ||
![]() |
b8813161a1 | ||
![]() |
f94aa400bf | ||
![]() |
b5cff212bb | ||
![]() |
212208ae01 | ||
![]() |
fc8122b18e | ||
![]() |
a2bca84b91 | ||
![]() |
a9fdee96a8 | ||
![]() |
125a4de66a | ||
![]() |
a4582c0e55 | ||
![]() |
1819ea834a | ||
![]() |
a443ac1680 | ||
![]() |
39f16ff517 | ||
![]() |
974b7c7329 | ||
![]() |
af1a6fc9fa | ||
![]() |
2573328c30 | ||
![]() |
eaea4f81b7 | ||
![]() |
17fa64aa5e | ||
![]() |
83d8d7ae7a | ||
![]() |
4d4bdb99df | ||
![]() |
a79b14db78 | ||
![]() |
e83e8cdb6e | ||
![]() |
3e4cf4b4f2 | ||
![]() |
8a4ca15eb8 | ||
![]() |
79acd166b7 | ||
![]() |
f78eb703ef | ||
![]() |
58c85c8c13 | ||
![]() |
0b0a0cec26 | ||
![]() |
470a3da7b0 | ||
![]() |
9285baace2 | ||
![]() |
bcfe05f16a | ||
![]() |
ca16c6f0d6 | ||
![]() |
cdd8929bc6 | ||
![]() |
05f188080b | ||
![]() |
85ed93e374 | ||
![]() |
3007c4c7dd | ||
![]() |
847a99d0e9 | ||
![]() |
52b787f71e | ||
![]() |
9f3fe7b05b | ||
![]() |
8ef673fe58 | ||
![]() |
74d1cbb01f | ||
![]() |
f0ad363895 | ||
![]() |
c643876955 | ||
![]() |
17684a112e | ||
![]() |
aad4bd3b79 | ||
![]() |
614db863bc | ||
![]() |
f239959067 | ||
![]() |
83b9afa5c8 | ||
![]() |
33a0a3511a | ||
![]() |
f9dd509d61 | ||
![]() |
af978e1e36 | ||
![]() |
a00a8bb0a9 | ||
![]() |
3b2fa3ba10 | ||
![]() |
5b3519ea38 | ||
![]() |
ebc69b645e | ||
![]() |
db4b1a8767 | ||
![]() |
350e02f348 | ||
![]() |
d2bf4846a5 |
14
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
|
@ -4,11 +4,12 @@ labels: ["triage"]
|
|||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: >
|
||||
Before opening a new issue, please ensure you are on the latest
|
||||
version (it might've already been fixed), and that you've searched
|
||||
for existing issues (please add you observations as a comment
|
||||
there instead of creating a duplicate).
|
||||
value: |
|
||||
Before opening a new bug report, please ensure
|
||||
1. you are on the latest version (it might've already been fixed),
|
||||
2. you've searched for existing issues (please add your observations as a comment there instead of creating a duplicate).
|
||||
|
||||
If you are self hosting, please create a community [Q&A](https://github.com/ente-io/ente/discussions/categories/q-a) instead.
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Description
|
||||
|
@ -16,7 +17,8 @@ body:
|
|||
Please describe the bug. If possible, also include the steps to
|
||||
reproduce the behaviour, and the expected behaviour (sometimes
|
||||
bugs are just expectation mismatches, in which case this would be
|
||||
a good fit for Discussions).
|
||||
a good fit for [feature
|
||||
requests](https://github.com/ente-io/ente/discussions/categories/feature-requests)).
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
|
|
|
@ -4,7 +4,7 @@ on:
|
|||
workflow_dispatch: # Allow manually running the action
|
||||
|
||||
env:
|
||||
FLUTTER_VERSION: "3.19.3"
|
||||
FLUTTER_VERSION: "3.22.0"
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
|
2
.github/workflows/mobile-lint.yml
vendored
|
@ -9,7 +9,7 @@ on:
|
|||
- ".github/workflows/mobile-lint.yml"
|
||||
|
||||
env:
|
||||
FLUTTER_VERSION: "3.19.5"
|
||||
FLUTTER_VERSION: "3.22.0"
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
<application android:name="${applicationName}"
|
||||
android:label="auth"
|
||||
android:label="Auth"
|
||||
android:icon="@mipmap/launcher_icon"
|
||||
android:usesCleartextTraffic="true"
|
||||
android:requestLegacyExternalStorage="true"
|
||||
|
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 133 KiB |
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 801 KiB |
|
@ -20,7 +20,7 @@
|
|||
<string>es</string>
|
||||
</array>
|
||||
<key>CFBundleName</key>
|
||||
<string>auth</string>
|
||||
<string>Auth</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
|
|
|
@ -189,7 +189,7 @@ class _AppState extends State<App> with WindowListener, TrayListener {
|
|||
windowManager.show();
|
||||
break;
|
||||
case 'exit_app':
|
||||
windowManager.close();
|
||||
windowManager.destroy();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
"codeIssuerHint": "発行者",
|
||||
"codeSecretKeyHint": "秘密鍵",
|
||||
"codeAccountHint": "アカウント (you@domain.com)",
|
||||
"codeTagHint": "タグ",
|
||||
"accountKeyType": "鍵の種類",
|
||||
"sessionExpired": "セッションが失効しました",
|
||||
"@sessionExpired": {
|
||||
"description": "Title of the dialog when the users current session is invalid/expired"
|
||||
|
@ -77,6 +79,7 @@
|
|||
"data": "データ",
|
||||
"importCodes": "コードをインポート",
|
||||
"importTypePlainText": "プレーンテキスト",
|
||||
"importTypeEnteEncrypted": "Ente 暗号化されたエクスポート",
|
||||
"passwordForDecryptingExport": "復号化用パスワード",
|
||||
"passwordEmptyError": "パスワードは空欄にできません",
|
||||
"importFromApp": "{appName} からコードをインポート",
|
||||
|
@ -121,6 +124,7 @@
|
|||
"suggestFeatures": "機能を提案",
|
||||
"faq": "FAQ",
|
||||
"faq_q_1": "Authはどのくらい安全ですか?",
|
||||
"faq_a_1": "Ente Authでバックアップされたコードはすべてエンドツーエンドで暗号化されて保存されます。つまり、コードにアクセスできるのはあなただけです。当社のアプリはオープンソースであり、暗号化技術は外部監査を受けています。",
|
||||
"faq_q_2": "パソコンから私のコードにアクセスできますか?",
|
||||
"faq_a_2": "auth.ente.io で Web からコードにアクセス可能です。",
|
||||
"faq_q_3": "コードを削除するにはどうすればいいですか?",
|
||||
|
@ -154,6 +158,7 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"invalidQRCode": "QRコードが無効です",
|
||||
"noRecoveryKeyTitle": "回復キーがありませんか?",
|
||||
"enterEmailHint": "メールアドレスを入力してください",
|
||||
"invalidEmailTitle": "メールアドレスが無効です",
|
||||
|
@ -347,6 +352,7 @@
|
|||
"deleteCodeAuthMessage": "コードを削除するためには認証が必要です",
|
||||
"showQRAuthMessage": "QR コードを表示するためには認証が必要です",
|
||||
"confirmAccountDeleteTitle": "アカウントの削除に同意",
|
||||
"confirmAccountDeleteMessage": "このアカウントは他のEnteアプリも使用している場合はそれらにも紐づけされています。\nすべてのEnteアプリでアップロードされたデータは削除され、アカウントは完全に削除されます。",
|
||||
"androidBiometricHint": "本人を確認する",
|
||||
"@androidBiometricHint": {
|
||||
"description": "Hint message advising the user how to authenticate with biometrics. It is used on Android side. Maximum 60 characters."
|
||||
|
@ -417,5 +423,18 @@
|
|||
"invalidEndpoint": "無効なエンドポイントです",
|
||||
"invalidEndpointMessage": "入力されたエンドポイントは無効です。有効なエンドポイントを入力して再試行してください。",
|
||||
"endpointUpdatedMessage": "エンドポイントの更新に成功しました",
|
||||
"customEndpoint": "{endpoint} に接続しました"
|
||||
"customEndpoint": "{endpoint} に接続しました",
|
||||
"pinText": "固定",
|
||||
"unpinText": "固定を解除",
|
||||
"pinnedCodeMessage": "{code} を固定しました",
|
||||
"unpinnedCodeMessage": "{code} の固定が解除されました",
|
||||
"tags": "タグ",
|
||||
"createNewTag": "新しいタグの作成",
|
||||
"tag": "タグ",
|
||||
"create": "作成",
|
||||
"editTag": "タグの編集",
|
||||
"deleteTagTitle": "タグを削除しますか?",
|
||||
"deleteTagMessage": "このタグを削除してもよろしいですか?この操作は取り消しできません。",
|
||||
"somethingWentWrongParsingCode": "{x} のコードを解析できませんでした。",
|
||||
"updateNotAvailable": "アップデートは利用できません"
|
||||
}
|
|
@ -20,6 +20,8 @@
|
|||
"codeIssuerHint": "Emissor",
|
||||
"codeSecretKeyHint": "Chave secreta",
|
||||
"codeAccountHint": "Conta (voce@dominio.com)",
|
||||
"codeTagHint": "Etiqueta",
|
||||
"accountKeyType": "Tipo de chave",
|
||||
"sessionExpired": "Sessão expirada",
|
||||
"@sessionExpired": {
|
||||
"description": "Title of the dialog when the users current session is invalid/expired"
|
||||
|
@ -156,6 +158,7 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"invalidQRCode": "QR Code inválido",
|
||||
"noRecoveryKeyTitle": "Sem chave de recuperação?",
|
||||
"enterEmailHint": "Insira o seu endereço de e-mail",
|
||||
"invalidEmailTitle": "Endereço de e-mail inválido",
|
||||
|
@ -420,5 +423,16 @@
|
|||
"invalidEndpoint": "Endpoint inválido",
|
||||
"invalidEndpointMessage": "Desculpe, o endpoint que você inseriu é inválido. Por favor, insira um endpoint válido e tente novamente.",
|
||||
"endpointUpdatedMessage": "Endpoint atualizado com sucesso",
|
||||
"customEndpoint": "Conectado a {endpoint}"
|
||||
"customEndpoint": "Conectado a {endpoint}",
|
||||
"pinText": "Fixar",
|
||||
"pinnedCodeMessage": "{code} foi fixado",
|
||||
"tags": "Etiquetas",
|
||||
"createNewTag": "Criar etiqueta",
|
||||
"tag": "Etiqueta",
|
||||
"create": "Criar",
|
||||
"editTag": "Editar etiqueta",
|
||||
"deleteTagTitle": "Excluir etiqueta?",
|
||||
"deleteTagMessage": "Tem certeza de que deseja excluir esta etiqueta? Essa ação é irreversível.",
|
||||
"somethingWentWrongParsingCode": "Não foi possível analisar os códigos {x}.",
|
||||
"updateNotAvailable": "Atualização não está disponível"
|
||||
}
|
|
@ -20,6 +20,8 @@
|
|||
"codeIssuerHint": "发行人",
|
||||
"codeSecretKeyHint": "私钥",
|
||||
"codeAccountHint": "账户 (you@domain.com)",
|
||||
"codeTagHint": "标签",
|
||||
"accountKeyType": "密钥类型",
|
||||
"sessionExpired": "会话已过期",
|
||||
"@sessionExpired": {
|
||||
"description": "Title of the dialog when the users current session is invalid/expired"
|
||||
|
@ -156,6 +158,7 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"invalidQRCode": "二维码无效",
|
||||
"noRecoveryKeyTitle": "没有恢复密钥吗?",
|
||||
"enterEmailHint": "请输入您的电子邮件地址",
|
||||
"invalidEmailTitle": "无效的电子邮件地址",
|
||||
|
@ -420,5 +423,18 @@
|
|||
"invalidEndpoint": "端点无效",
|
||||
"invalidEndpointMessage": "抱歉,您输入的端点无效。请输入有效的端点,然后重试。",
|
||||
"endpointUpdatedMessage": "端点更新成功",
|
||||
"customEndpoint": "已连接至 {endpoint}"
|
||||
"customEndpoint": "已连接至 {endpoint}",
|
||||
"pinText": "置顶",
|
||||
"unpinText": "取消置顶",
|
||||
"pinnedCodeMessage": "{code} 已被置顶",
|
||||
"unpinnedCodeMessage": "{code} 已被取消置顶",
|
||||
"tags": "标签",
|
||||
"createNewTag": "创建新标签",
|
||||
"tag": "标签",
|
||||
"create": "创建",
|
||||
"editTag": "编辑标签",
|
||||
"deleteTagTitle": "要删除标签吗?",
|
||||
"deleteTagMessage": "您确定要删除此标签吗?此操作是不可逆的。",
|
||||
"somethingWentWrongParsingCode": "我们无法解析 {x} 代码。",
|
||||
"updateNotAvailable": "更新不可用"
|
||||
}
|
|
@ -125,10 +125,10 @@ class Code {
|
|||
final issuer = _getIssuer(uri);
|
||||
|
||||
try {
|
||||
return Code(
|
||||
final code = Code(
|
||||
_getAccount(uri),
|
||||
issuer,
|
||||
_getDigits(uri, issuer),
|
||||
_getDigits(uri),
|
||||
_getPeriod(uri),
|
||||
getSanitizedSecret(uri.queryParameters['secret']!),
|
||||
_getAlgorithm(uri),
|
||||
|
@ -137,6 +137,7 @@ class Code {
|
|||
rawData,
|
||||
display: CodeDisplay.fromUri(uri) ?? CodeDisplay(),
|
||||
);
|
||||
return code;
|
||||
} catch (e) {
|
||||
// if account name contains # without encoding,
|
||||
// rest of the url are treated as url fragment
|
||||
|
@ -174,12 +175,11 @@ class Code {
|
|||
}
|
||||
|
||||
String toOTPAuthUrlFormat() {
|
||||
final uri = Uri.parse(rawData);
|
||||
final uri = Uri.parse(rawData.replaceAll("#", '%23'));
|
||||
final query = {...uri.queryParameters};
|
||||
query["codeDisplay"] = jsonEncode(display.toJson());
|
||||
|
||||
final newUri = uri.replace(queryParameters: query);
|
||||
|
||||
return jsonEncode(newUri.toString());
|
||||
}
|
||||
|
||||
|
@ -201,11 +201,11 @@ class Code {
|
|||
}
|
||||
}
|
||||
|
||||
static int _getDigits(Uri uri, String issuer) {
|
||||
static int _getDigits(Uri uri) {
|
||||
try {
|
||||
return int.parse(uri.queryParameters['digits']!);
|
||||
} catch (e) {
|
||||
if (issuer.toLowerCase() == "steam") {
|
||||
if (uri.host == "steam") {
|
||||
return steamDigits;
|
||||
}
|
||||
return defaultDigits;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
|
||||
/// Used to store the display settings of a code.
|
||||
class CodeDisplay {
|
||||
|
@ -54,13 +55,34 @@ class CodeDisplay {
|
|||
);
|
||||
}
|
||||
|
||||
static CodeDisplay? fromUri(Uri uri) {
|
||||
/// Converts the [CodeDisplay] to a json object.
|
||||
/// When [safeParsing] is true, the json will be parsed safely.
|
||||
/// If we fail to parse the json, we will return an empty [CodeDisplay].
|
||||
static CodeDisplay? fromUri(Uri uri, {bool safeParsing = false}) {
|
||||
if (!uri.queryParameters.containsKey("codeDisplay")) return null;
|
||||
final String codeDisplay =
|
||||
uri.queryParameters['codeDisplay']!.replaceAll('%2C', ',');
|
||||
final decodedDisplay = jsonDecode(codeDisplay);
|
||||
return _parseCodeDisplayJson(codeDisplay, safeParsing);
|
||||
}
|
||||
|
||||
return CodeDisplay.fromJson(decodedDisplay);
|
||||
static CodeDisplay _parseCodeDisplayJson(String json, bool safeParsing) {
|
||||
try {
|
||||
final decodedDisplay = jsonDecode(json);
|
||||
return CodeDisplay.fromJson(decodedDisplay);
|
||||
} catch (e, s) {
|
||||
Logger("CodeDisplay")
|
||||
.severe("Could not parse code display from json", e, s);
|
||||
// (ng/prateek) Handle the case where we have fragment in the rawDataUrl
|
||||
if (!json.endsWith("}") && json.contains("}#")) {
|
||||
Logger("CodeDisplay").warning("ignoring code display as it's invalid");
|
||||
return CodeDisplay();
|
||||
}
|
||||
if (safeParsing) {
|
||||
return CodeDisplay();
|
||||
} else {
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
|
|
|
@ -240,7 +240,7 @@ class _SetupEnterSecretKeyPageState extends State<SetupEnterSecretKeyPage> {
|
|||
final account = _accountController.text.trim();
|
||||
final issuer = _issuerController.text.trim();
|
||||
final secret = _secretController.text.trim().replaceAll(' ', '');
|
||||
final isStreamCode = issuer.toLowerCase() == "steam";
|
||||
final isStreamCode = issuer.toLowerCase() == "steam" || issuer.toLowerCase().contains('steampowered.com');
|
||||
if (widget.code != null && widget.code!.secret != secret) {
|
||||
ButtonResult? result = await showChoiceActionSheet(
|
||||
context,
|
||||
|
|
|
@ -41,9 +41,9 @@ class CodeStore {
|
|||
} else {
|
||||
code = Code.fromExportJson(decodeJson);
|
||||
}
|
||||
} catch (e) {
|
||||
} catch (e, s) {
|
||||
code = Code.withError(e, entity.rawData);
|
||||
_logger.severe("Could not parse code", code.err);
|
||||
_logger.severe("Could not parse code", e, s);
|
||||
}
|
||||
code.generatedID = entity.generatedID;
|
||||
code.hasSynced = entity.hasSynced;
|
||||
|
|
|
@ -48,7 +48,6 @@ class _CodeWidgetState extends State<CodeWidget> {
|
|||
late bool _shouldShowLargeIcon;
|
||||
late bool _hideCode;
|
||||
bool isMaskingEnabled = false;
|
||||
late final colorScheme = getEnteColorScheme(context);
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
|
@ -78,6 +77,7 @@ class _CodeWidgetState extends State<CodeWidget> {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final colorScheme = getEnteColorScheme(context);
|
||||
if (isMaskingEnabled != PreferenceService.instance.shouldHideCodes()) {
|
||||
isMaskingEnabled = PreferenceService.instance.shouldHideCodes();
|
||||
_hideCode = isMaskingEnabled;
|
||||
|
@ -91,6 +91,100 @@ class _CodeWidgetState extends State<CodeWidget> {
|
|||
_isInitialized = true;
|
||||
}
|
||||
final l10n = context.l10n;
|
||||
|
||||
Widget getCardContents(AppLocalizations l10n) {
|
||||
return Stack(
|
||||
children: [
|
||||
if (widget.code.isPinned)
|
||||
Align(
|
||||
alignment: Alignment.topRight,
|
||||
child: CustomPaint(
|
||||
painter: PinBgPainter(
|
||||
color: colorScheme.pinnedBgColor,
|
||||
),
|
||||
size: const Size(39, 39),
|
||||
),
|
||||
),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
if (widget.code.type.isTOTPCompatible)
|
||||
CodeTimerProgress(
|
||||
period: widget.code.period,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Row(
|
||||
children: [
|
||||
_shouldShowLargeIcon ? _getIcon() : const SizedBox.shrink(),
|
||||
Expanded(
|
||||
child: Column(
|
||||
children: [
|
||||
_getTopRow(),
|
||||
const SizedBox(height: 4),
|
||||
_getBottomRow(l10n),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
],
|
||||
),
|
||||
if (widget.code.isPinned) ...[
|
||||
Align(
|
||||
alignment: Alignment.topRight,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(right: 6, top: 6),
|
||||
child: SvgPicture.asset("assets/svg/pin-card.svg"),
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget clippedCard(AppLocalizations l10n) {
|
||||
return Container(
|
||||
height: 132,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
color: Theme.of(context).colorScheme.codeCardBackgroundColor,
|
||||
boxShadow:
|
||||
widget.code.isPinned ? colorScheme.pinnedCardBoxShadow : [],
|
||||
),
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
child: Material(
|
||||
color: Colors.transparent,
|
||||
child: InkWell(
|
||||
customBorder: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
onTap: () {
|
||||
_copyCurrentOTPToClipboard();
|
||||
},
|
||||
onDoubleTap: isMaskingEnabled
|
||||
? () {
|
||||
setState(
|
||||
() {
|
||||
_hideCode = !_hideCode;
|
||||
},
|
||||
);
|
||||
}
|
||||
: null,
|
||||
onLongPress: () {
|
||||
_copyCurrentOTPToClipboard();
|
||||
},
|
||||
child: getCardContents(l10n),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return Container(
|
||||
margin: const EdgeInsets.only(left: 16, right: 16, bottom: 8, top: 8),
|
||||
child: Builder(
|
||||
|
@ -126,7 +220,7 @@ class _CodeWidgetState extends State<CodeWidget> {
|
|||
],
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
),
|
||||
child: _clippedCard(l10n),
|
||||
child: clippedCard(l10n),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -216,7 +310,7 @@ class _CodeWidgetState extends State<CodeWidget> {
|
|||
],
|
||||
),
|
||||
child: Builder(
|
||||
builder: (context) => _clippedCard(l10n),
|
||||
builder: (context) => clippedCard(l10n),
|
||||
),
|
||||
);
|
||||
},
|
||||
|
@ -224,98 +318,6 @@ class _CodeWidgetState extends State<CodeWidget> {
|
|||
);
|
||||
}
|
||||
|
||||
Widget _clippedCard(AppLocalizations l10n) {
|
||||
return Container(
|
||||
height: 132,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
color: Theme.of(context).colorScheme.codeCardBackgroundColor,
|
||||
boxShadow: widget.code.isPinned ? colorScheme.pinnedCardBoxShadow : [],
|
||||
),
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
child: Material(
|
||||
color: Colors.transparent,
|
||||
child: InkWell(
|
||||
customBorder: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
onTap: () {
|
||||
_copyCurrentOTPToClipboard();
|
||||
},
|
||||
onDoubleTap: isMaskingEnabled
|
||||
? () {
|
||||
setState(
|
||||
() {
|
||||
_hideCode = !_hideCode;
|
||||
},
|
||||
);
|
||||
}
|
||||
: null,
|
||||
onLongPress: () {
|
||||
_copyCurrentOTPToClipboard();
|
||||
},
|
||||
child: _getCardContents(l10n),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _getCardContents(AppLocalizations l10n) {
|
||||
return Stack(
|
||||
children: [
|
||||
if (widget.code.isPinned)
|
||||
Align(
|
||||
alignment: Alignment.topRight,
|
||||
child: CustomPaint(
|
||||
painter: PinBgPainter(
|
||||
color: colorScheme.pinnedBgColor,
|
||||
),
|
||||
size: const Size(39, 39),
|
||||
),
|
||||
),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
if (widget.code.type == Type.totp)
|
||||
CodeTimerProgress(
|
||||
period: widget.code.period,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Row(
|
||||
children: [
|
||||
_shouldShowLargeIcon ? _getIcon() : const SizedBox.shrink(),
|
||||
Expanded(
|
||||
child: Column(
|
||||
children: [
|
||||
_getTopRow(),
|
||||
const SizedBox(height: 4),
|
||||
_getBottomRow(l10n),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
],
|
||||
),
|
||||
if (widget.code.isPinned) ...[
|
||||
Align(
|
||||
alignment: Alignment.topRight,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(right: 6, top: 6),
|
||||
child: SvgPicture.asset("assets/svg/pin-card.svg"),
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget _getBottomRow(AppLocalizations l10n) {
|
||||
return Container(
|
||||
padding: const EdgeInsets.only(left: 16, right: 16),
|
||||
|
@ -585,7 +587,7 @@ class _CodeWidgetState extends State<CodeWidget> {
|
|||
String _getFormattedCode(String code) {
|
||||
if (_hideCode) {
|
||||
// replace all digits with •
|
||||
code = code.replaceAll(RegExp(r'\d'), '•');
|
||||
code = code.replaceAll(RegExp(r'\S'), '•');
|
||||
}
|
||||
if (code.length == 6) {
|
||||
return "${code.substring(0, 3)} ${code.substring(3, 6)}";
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
import 'package:ente_auth/models/code.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:otp/otp.dart' as otp;
|
||||
import 'package:steam_totp/steam_totp.dart';
|
||||
|
||||
String getOTP(Code code) {
|
||||
if (code.type == Type.steam) {
|
||||
return _getSteamCode(code);
|
||||
}
|
||||
if (code.type == Type.hotp) {
|
||||
return _getHOTPCode(code);
|
||||
}
|
||||
|
@ -26,7 +30,18 @@ String _getHOTPCode(Code code) {
|
|||
);
|
||||
}
|
||||
|
||||
String _getSteamCode(Code code, [bool isNext = false]) {
|
||||
final SteamTOTP steamtotp = SteamTOTP(secret: code.secret);
|
||||
|
||||
return steamtotp.generate(
|
||||
DateTime.now().millisecondsSinceEpoch ~/ 1000 + (isNext ? code.period : 0),
|
||||
);
|
||||
}
|
||||
|
||||
String getNextTotp(Code code) {
|
||||
if (code.type == Type.steam) {
|
||||
return _getSteamCode(code, true);
|
||||
}
|
||||
return otp.OTP.generateTOTPCodeString(
|
||||
getSanitizedSecret(code.secret),
|
||||
DateTime.now().millisecondsSinceEpoch + code.period * 1000,
|
||||
|
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.9 KiB |
Before Width: | Height: | Size: 240 B After Width: | Height: | Size: 324 B |
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 5.6 KiB |
Before Width: | Height: | Size: 628 B After Width: | Height: | Size: 780 B |
Before Width: | Height: | Size: 7.6 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.5 KiB |
|
@ -745,6 +745,22 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.0"
|
||||
hashlib:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: hashlib
|
||||
sha256: "67e640e19cc33070113acab3125cd48ebe480a0300e15554dec089b8878a729f"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.16.0"
|
||||
hashlib_codecs:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: hashlib_codecs
|
||||
sha256: "49e2a471f74b15f1854263e58c2ac11f2b631b5b12c836f9708a35397d36d626"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.2.0"
|
||||
hex:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -1439,6 +1455,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.11.1"
|
||||
steam_totp:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: steam_totp
|
||||
sha256: "3c09143c983f6bb05bb53e9232f9d40bbcc01c596ba0273c3e6bb246729abfa1"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.0.1"
|
||||
step_progress_indicator:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
name: ente_auth
|
||||
description: ente two-factor authenticator
|
||||
version: 3.0.2+302
|
||||
version: 3.0.4+304
|
||||
publish_to: none
|
||||
|
||||
environment:
|
||||
|
@ -94,6 +94,7 @@ dependencies:
|
|||
sqflite_common_ffi: ^2.3.0+4
|
||||
sqlite3: ^2.1.0
|
||||
sqlite3_flutter_libs: ^0.5.19+1
|
||||
steam_totp: ^0.0.1
|
||||
step_progress_indicator: ^1.0.2
|
||||
styled_text: ^8.1.0
|
||||
tray_manager: ^0.2.1
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
"compare-versions": "^6.1",
|
||||
"electron-log": "^5.1",
|
||||
"electron-store": "^8.2",
|
||||
"electron-updater": "^6.1",
|
||||
"electron-updater": "^6.2",
|
||||
"ffmpeg-static": "^5.2",
|
||||
"html-entities": "^2.5",
|
||||
"jpeg-js": "^0.4",
|
||||
|
|
|
@ -51,14 +51,6 @@ export const openLogDirectory = () => openDirectory(logDirectoryPath());
|
|||
* "userData" directory. This is the **primary** place applications are meant to
|
||||
* store user's data, e.g. various configuration files and saved state.
|
||||
*
|
||||
* During development, our app name is "Electron", so this'd be, for example,
|
||||
* `~/Library/Application Support/Electron` if we run using `yarn dev`. For the
|
||||
* packaged production app, our app name is "ente", so this would be:
|
||||
*
|
||||
* - Windows: `%APPDATA%\ente`, e.g. `C:\Users\<username>\AppData\Local\ente`
|
||||
* - Linux: `~/.config/ente`
|
||||
* - macOS: `~/Library/Application Support/ente`
|
||||
*
|
||||
* Note that Chromium also stores the browser state, e.g. localStorage or disk
|
||||
* caches, in userData.
|
||||
*
|
||||
|
@ -71,7 +63,6 @@ export const openLogDirectory = () => openDirectory(logDirectoryPath());
|
|||
* "ente.log", it can be found at:
|
||||
*
|
||||
* - macOS: ~/Library/Logs/ente/ente.log (production)
|
||||
* - macOS: ~/Library/Logs/Electron/ente.log (dev)
|
||||
* - Linux: ~/.config/ente/logs/ente.log
|
||||
* - Windows: %USERPROFILE%\AppData\Roaming\ente\logs\ente.log
|
||||
*/
|
||||
|
|
|
@ -18,10 +18,7 @@ export const clearStores = () => {
|
|||
* [Note: Safe storage keys]
|
||||
*
|
||||
* On macOS, `safeStorage` stores our data under a Keychain entry named
|
||||
* "<app-name> Safe Storage". Which resolves to:
|
||||
*
|
||||
* - Electron Safe Storage (dev)
|
||||
* - ente Safe Storage (prod)
|
||||
* "<app-name> Safe Storage". In our case, "ente Safe Storage".
|
||||
*/
|
||||
export const saveEncryptionKey = (encryptionKey: string) => {
|
||||
const encryptedKey = safeStorage.encryptString(encryptionKey);
|
||||
|
|
|
@ -106,7 +106,7 @@ const handleRead = async (path: string) => {
|
|||
res.headers.set("Content-Length", `${fileSize}`);
|
||||
|
||||
// Add the file's last modified time (as epoch milliseconds).
|
||||
const mtimeMs = stat.mtimeMs;
|
||||
const mtimeMs = stat.mtime.getTime();
|
||||
res.headers.set("X-Last-Modified-Ms", `${mtimeMs}`);
|
||||
}
|
||||
return res;
|
||||
|
@ -132,6 +132,13 @@ const handleReadZip = async (zipPath: string, entryName: string) => {
|
|||
// Close the zip handle when the underlying stream closes.
|
||||
stream.on("end", () => void zip.close());
|
||||
|
||||
// While it is documented that entry.time is the modification time,
|
||||
// the units are not mentioned. By seeing the source code, we can
|
||||
// verify that it is indeed epoch milliseconds. See `parseZipTime`
|
||||
// in the node-stream-zip source,
|
||||
// https://github.com/antelle/node-stream-zip/blob/master/node_stream_zip.js
|
||||
const modifiedMs = entry.time;
|
||||
|
||||
return new Response(webReadableStream, {
|
||||
headers: {
|
||||
// We don't know the exact type, but it doesn't really matter, just
|
||||
|
@ -139,12 +146,7 @@ const handleReadZip = async (zipPath: string, entryName: string) => {
|
|||
// doesn't tinker with it thinking of it as text.
|
||||
"Content-Type": "application/octet-stream",
|
||||
"Content-Length": `${entry.size}`,
|
||||
// While it is documented that entry.time is the modification time,
|
||||
// the units are not mentioned. By seeing the source code, we can
|
||||
// verify that it is indeed epoch milliseconds. See `parseZipTime`
|
||||
// in the node-stream-zip source,
|
||||
// https://github.com/antelle/node-stream-zip/blob/master/node_stream_zip.js
|
||||
"X-Last-Modified-Ms": `${entry.time}`,
|
||||
"X-Last-Modified-Ms": `${modifiedMs}`,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
|
|
@ -743,10 +743,10 @@ buffer@^5.1.0, buffer@^5.5.0:
|
|||
base64-js "^1.3.1"
|
||||
ieee754 "^1.1.13"
|
||||
|
||||
builder-util-runtime@9.2.3:
|
||||
version "9.2.3"
|
||||
resolved "https://registry.yarnpkg.com/builder-util-runtime/-/builder-util-runtime-9.2.3.tgz#0a82c7aca8eadef46d67b353c638f052c206b83c"
|
||||
integrity sha512-FGhkqXdFFZ5dNC4C+yuQB9ak311rpGAw+/ASz8ZdxwODCv1GGMWgLDeofRkdi0F3VCHQEWy/aXcJQozx2nOPiw==
|
||||
builder-util-runtime@9.2.4:
|
||||
version "9.2.4"
|
||||
resolved "https://registry.yarnpkg.com/builder-util-runtime/-/builder-util-runtime-9.2.4.tgz#13cd1763da621e53458739a1e63f7fcba673c42a"
|
||||
integrity sha512-upp+biKpN/XZMLim7aguUyW8s0FUpDvOtK6sbanMFDAMBzpHDqdhgVYm6zc9HJ6nWo7u2Lxk60i2M6Jd3aiNrA==
|
||||
dependencies:
|
||||
debug "^4.3.4"
|
||||
sax "^1.2.4"
|
||||
|
@ -1251,12 +1251,12 @@ electron-store@^8.2:
|
|||
conf "^10.2.0"
|
||||
type-fest "^2.17.0"
|
||||
|
||||
electron-updater@^6.1:
|
||||
version "6.1.8"
|
||||
resolved "https://registry.yarnpkg.com/electron-updater/-/electron-updater-6.1.8.tgz#17637bca165322f4e526b13c99165f43e6f697d8"
|
||||
integrity sha512-hhOTfaFAd6wRHAfUaBhnAOYc+ymSGCWJLtFkw4xJqOvtpHmIdNHnXDV9m1MHC+A6q08Abx4Ykgyz/R5DGKNAMQ==
|
||||
electron-updater@^6.2:
|
||||
version "6.2.1"
|
||||
resolved "https://registry.yarnpkg.com/electron-updater/-/electron-updater-6.2.1.tgz#1c9adb9ba2a21a5dc50a8c434c45360d5e9fe6c9"
|
||||
integrity sha512-83eKIPW14qwZqUUM6wdsIRwVKZyjmHxQ4/8G+1C6iS5PdDt7b1umYQyj1/qPpH510GmHEQe4q0kCPe3qmb3a0Q==
|
||||
dependencies:
|
||||
builder-util-runtime "9.2.3"
|
||||
builder-util-runtime "9.2.4"
|
||||
fs-extra "^10.1.0"
|
||||
js-yaml "^4.1.0"
|
||||
lazy-val "^1.0.5"
|
||||
|
|
|
@ -163,6 +163,10 @@ export const sidebar = [
|
|||
text: "From Authy",
|
||||
link: "/auth/migration-guides/authy/",
|
||||
},
|
||||
{
|
||||
text: "From Steam",
|
||||
link: "/auth/migration-guides/steam/",
|
||||
},
|
||||
{
|
||||
text: "Exporting your data",
|
||||
link: "/auth/migration-guides/export",
|
||||
|
|
|
@ -7,4 +7,5 @@ description:
|
|||
# Migrating to/from Ente Auth
|
||||
|
||||
- [Migrating from Authy](authy/)
|
||||
- [Importing codes from Steam](steam/)
|
||||
- [Exporting your data out of Ente Auth](export)
|
||||
|
|
79
docs/docs/auth/migration-guides/steam/index.md
Normal file
|
@ -0,0 +1,79 @@
|
|||
---
|
||||
title: Migrating from Steam Authenticator
|
||||
description: Guide for importing from Steam Authenticator to Ente Auth
|
||||
---
|
||||
|
||||
# Migrating from Steam Authenticator
|
||||
|
||||
A guide written by an ente.io lover
|
||||
|
||||
> [!WARNING]
|
||||
>
|
||||
> Steam Authenticator code is only supported after auth-v3.0.3, check the app's
|
||||
> version number before migration.
|
||||
|
||||
One way to migrate is to
|
||||
[use this tool by dyc3](https://github.com/dyc3/steamguard-cli/releases/latest)
|
||||
to simplify the process and skip directly to generating a qr code to Ente
|
||||
Authenticator.
|
||||
|
||||
## Download/Install steamguard-cli
|
||||
|
||||
### Windows
|
||||
|
||||
1. Download `steamguard.exe` from the [releases page][releases].
|
||||
2. Place `steamguard.exe` in a folder of your choice. For this example, we will
|
||||
use `%USERPROFILE%\Desktop`.
|
||||
3. Open Powershell or Command Prompt. The prompt should be at `%USERPROFILE%`
|
||||
(eg. `C:\Users\<username>`).
|
||||
4. Use `cd` to change directory into the folder where you placed
|
||||
`steamguard.exe`. For this example, it would be `cd Desktop`.
|
||||
5. You should now be able to run `steamguard.exe` by typing
|
||||
`.\steamguard.exe --help` and pressing enter.
|
||||
|
||||
### Linux
|
||||
|
||||
#### Ubuntu/Debian
|
||||
|
||||
1. Download the `.deb` from the [releases page][releases].
|
||||
2. Open a terminal and run this to install it:
|
||||
|
||||
```bash
|
||||
sudo dpkg -i ./steamguard-cli_<version>_amd64.deb
|
||||
```
|
||||
|
||||
#### Other Linux
|
||||
|
||||
1. Download `steamguard` from the [releases page][releases]
|
||||
2. Make it executable, and move `steamguard` to `/usr/local/bin` or any other
|
||||
directory in your `$PATH`.
|
||||
|
||||
```bash
|
||||
chmod +x ./steamguard
|
||||
sudo mv ./steamguard /usr/local/bin
|
||||
```
|
||||
|
||||
3. You should now be able to run `steamguard` by typing `steamguard --help` and
|
||||
pressing enter.
|
||||
|
||||
## Login to Steam account
|
||||
|
||||
Set up a new account with steamguard-cli
|
||||
|
||||
```bash
|
||||
steamguard setup # set up a new account with steamguard-cli
|
||||
```
|
||||
|
||||
## Generate & importing QR codes
|
||||
|
||||
steamguard-cli can then generate a QR code for your 2FA secret.
|
||||
|
||||
```bash
|
||||
steamguard qr # print QR code for the first account in your maFiles
|
||||
steamguard -u <account name> qr # print QR code for a specific account
|
||||
```
|
||||
|
||||
Open Ente Auth, press the '+' button, select `Scan a QR code`, and scan the qr
|
||||
code.
|
||||
|
||||
You should now have your steam code inside Ente Auth
|
|
@ -78,3 +78,23 @@ To summarize:
|
|||
Set the S3 bucket `endpoint` in `credentials.yaml` to a `yourserverip:3200` or
|
||||
some such IP/hostname that accessible from both where you are running the Ente
|
||||
clients (e.g. the mobile app) and also from within the Docker compose cluster.
|
||||
|
||||
### 403 Forbidden
|
||||
|
||||
If museum (`2`) is able to make a network connection to your S3 bucket (`3`) but
|
||||
uploads are still failing, it could be a credentials or permissions issue. A
|
||||
telltale sign of this is that in the museum logs you can see `403 Forbidden`
|
||||
errors about it not able to find the size of a file even though the
|
||||
corresponding object exists in the S3 bucket.
|
||||
|
||||
To fix these, you should ensure the following:
|
||||
|
||||
1. The bucket CORS rules do not allow museum to access these objects.
|
||||
|
||||
> For uploading files from the browser, you will need to currently set
|
||||
> allowedOrigins to "\*", and allow the "X-Auth-Token", "X-Client-Package"
|
||||
> headers configuration too.
|
||||
> [Here is an example of a working configuration](https://github.com/ente-io/ente/discussions/1764#discussioncomment-9478204).
|
||||
|
||||
2. The credentials are not being picked up (you might be setting the correct
|
||||
creds, but not in the place where museum picks them from).
|
||||
|
|
|
@ -46,7 +46,7 @@ You can alternatively install the build from PlayStore or F-Droid.
|
|||
|
||||
## 🧑💻 Building from source
|
||||
|
||||
1. [Install Flutter v3.19.3](https://flutter.dev/docs/get-started/install).
|
||||
1. [Install Flutter v3.22.0](https://flutter.dev/docs/get-started/install).
|
||||
|
||||
2. Pull in all submodules with `git submodule update --init --recursive`
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ android {
|
|||
|
||||
defaultConfig {
|
||||
applicationId "io.ente.photos"
|
||||
minSdkVersion 21
|
||||
minSdkVersion 26
|
||||
targetSdkVersion 33
|
||||
versionCode flutterVersionCode.toInteger()
|
||||
versionName flutterVersionName
|
||||
|
@ -70,6 +70,10 @@ android {
|
|||
dimension "default"
|
||||
applicationIdSuffix ".dev"
|
||||
}
|
||||
face {
|
||||
dimension "default"
|
||||
applicationIdSuffix ".face"
|
||||
}
|
||||
playstore {
|
||||
dimension "default"
|
||||
}
|
||||
|
|
10
mobile/android/app/src/face/AndroidManifest.xml
Normal file
|
@ -0,0 +1,10 @@
|
|||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="io.ente.photos">
|
||||
<!-- Flutter needs it to communicate with the running application
|
||||
to allow setting breakpoints, to provide hot reload, etc.
|
||||
-->
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
</manifest>
|
4
mobile/android/app/src/face/res/values/strings.xml
Normal file
|
@ -0,0 +1,4 @@
|
|||
<resources>
|
||||
<string name="app_name">ente face</string>
|
||||
<string name="backup">backup face</string>
|
||||
</resources>
|
|
@ -1,91 +0,0 @@
|
|||
unknown
|
||||
person
|
||||
bicycle
|
||||
car
|
||||
motorcycle
|
||||
airplane
|
||||
bus
|
||||
train
|
||||
truck
|
||||
boat
|
||||
traffic light
|
||||
fire hydrant
|
||||
unknown
|
||||
stop sign
|
||||
parking meter
|
||||
bench
|
||||
bird
|
||||
cat
|
||||
dog
|
||||
horse
|
||||
sheep
|
||||
cow
|
||||
elephant
|
||||
bear
|
||||
zebra
|
||||
giraffe
|
||||
unknown
|
||||
backpack
|
||||
umbrella
|
||||
unknown
|
||||
unknown
|
||||
handbag
|
||||
tie
|
||||
suitcase
|
||||
frisbee
|
||||
skis
|
||||
snowboard
|
||||
sports ball
|
||||
kite
|
||||
baseball bat
|
||||
baseball glove
|
||||
skateboard
|
||||
surfboard
|
||||
tennis racket
|
||||
bottle
|
||||
unknown
|
||||
wine glass
|
||||
cup
|
||||
fork
|
||||
knife
|
||||
spoon
|
||||
bowl
|
||||
banana
|
||||
apple
|
||||
sandwich
|
||||
orange
|
||||
broccoli
|
||||
carrot
|
||||
hot dog
|
||||
pizza
|
||||
donut
|
||||
cake
|
||||
chair
|
||||
couch
|
||||
potted plant
|
||||
bed
|
||||
unknown
|
||||
dining table
|
||||
unknown
|
||||
unknown
|
||||
toilet
|
||||
unknown
|
||||
tv
|
||||
laptop
|
||||
mouse
|
||||
remote
|
||||
keyboard
|
||||
cell phone
|
||||
microwave
|
||||
oven
|
||||
toaster
|
||||
sink
|
||||
refrigerator
|
||||
unknown
|
||||
book
|
||||
clock
|
||||
vase
|
||||
scissors
|
||||
teddy bear
|
||||
hair drier
|
||||
toothbrush
|
|
@ -1,30 +0,0 @@
|
|||
waterfall
|
||||
snow
|
||||
landscape
|
||||
underwater
|
||||
architecture
|
||||
sunset / sunrise
|
||||
blue sky
|
||||
cloudy sky
|
||||
greenery
|
||||
autumn leaves
|
||||
portrait
|
||||
flower
|
||||
night shot
|
||||
stage concert
|
||||
fireworks
|
||||
candle light
|
||||
neon lights
|
||||
indoor
|
||||
backlight
|
||||
text documents
|
||||
qr images
|
||||
group portrait
|
||||
computer screens
|
||||
kids
|
||||
dog
|
||||
cat
|
||||
macro
|
||||
food
|
||||
beach
|
||||
mountain
|
|
@ -6,6 +6,8 @@ PODS:
|
|||
- connectivity_plus (0.0.1):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
- dart_ui_isolate (0.0.1):
|
||||
- Flutter
|
||||
- device_info_plus (0.0.1):
|
||||
- Flutter
|
||||
- file_saver (0.0.1):
|
||||
|
@ -226,6 +228,7 @@ DEPENDENCIES:
|
|||
- background_fetch (from `.symlinks/plugins/background_fetch/ios`)
|
||||
- battery_info (from `.symlinks/plugins/battery_info/ios`)
|
||||
- connectivity_plus (from `.symlinks/plugins/connectivity_plus/darwin`)
|
||||
- dart_ui_isolate (from `.symlinks/plugins/dart_ui_isolate/ios`)
|
||||
- device_info_plus (from `.symlinks/plugins/device_info_plus/ios`)
|
||||
- file_saver (from `.symlinks/plugins/file_saver/ios`)
|
||||
- firebase_core (from `.symlinks/plugins/firebase_core/ios`)
|
||||
|
@ -302,6 +305,8 @@ EXTERNAL SOURCES:
|
|||
:path: ".symlinks/plugins/battery_info/ios"
|
||||
connectivity_plus:
|
||||
:path: ".symlinks/plugins/connectivity_plus/darwin"
|
||||
dart_ui_isolate:
|
||||
:path: ".symlinks/plugins/dart_ui_isolate/ios"
|
||||
device_info_plus:
|
||||
:path: ".symlinks/plugins/device_info_plus/ios"
|
||||
file_saver:
|
||||
|
@ -397,6 +402,7 @@ SPEC CHECKSUMS:
|
|||
background_fetch: 2319bf7e18237b4b269430b7f14d177c0df09c5a
|
||||
battery_info: 09f5c9ee65394f2291c8c6227bedff345b8a730c
|
||||
connectivity_plus: ddd7f30999e1faaef5967c23d5b6d503d10434db
|
||||
dart_ui_isolate: d5bcda83ca4b04f129d70eb90110b7a567aece14
|
||||
device_info_plus: c6fb39579d0f423935b0c9ce7ee2f44b71b9fce6
|
||||
file_saver: 503e386464dbe118f630e17b4c2e1190fa0cf808
|
||||
Firebase: 91fefd38712feb9186ea8996af6cbdef41473442
|
||||
|
@ -421,7 +427,7 @@ SPEC CHECKSUMS:
|
|||
home_widget: 0434835a4c9a75704264feff6be17ea40e0f0d57
|
||||
image_editor_common: d6f6644ae4a6de80481e89fe6d0a8c49e30b4b43
|
||||
in_app_purchase_storekit: 0e4b3c2e43ba1e1281f4f46dd71b0593ce529892
|
||||
integration_test: 13825b8a9334a850581300559b8839134b124670
|
||||
integration_test: ce0a3ffa1de96d1a89ca0ac26fca7ea18a749ef4
|
||||
libwebp: 1786c9f4ff8a279e4dac1e8f385004d5fc253009
|
||||
local_auth_darwin: c7e464000a6a89e952235699e32b329457608d98
|
||||
local_auth_ios: 5046a18c018dd973247a0564496c8898dbb5adf9
|
||||
|
|
|
@ -293,6 +293,7 @@
|
|||
"${BUILT_PRODUCTS_DIR}/background_fetch/background_fetch.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/battery_info/battery_info.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/connectivity_plus/connectivity_plus.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/dart_ui_isolate/dart_ui_isolate.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/device_info_plus/device_info_plus.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/file_saver/file_saver.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/fk_user_agent/fk_user_agent.framework",
|
||||
|
@ -374,6 +375,7 @@
|
|||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/background_fetch.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/battery_info.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/connectivity_plus.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/dart_ui_isolate.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/device_info_plus.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/file_saver.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/fk_user_agent.framework",
|
||||
|
|
|
@ -65,9 +65,9 @@
|
|||
<key>ITSAppUsesNonExemptEncryption</key>
|
||||
<false/>
|
||||
<key>FLTEnableImpeller</key>
|
||||
<false />
|
||||
<true />
|
||||
<key>FLTEnableWideGamut</key>
|
||||
<false/>
|
||||
<true/>
|
||||
<key>NSFaceIDUsageDescription</key>
|
||||
<string>Please allow ente to lock itself with FaceID or TouchID</string>
|
||||
<key>NSCameraUsageDescription</key>
|
||||
|
|
|
@ -19,6 +19,7 @@ import 'package:photos/db/upload_locks_db.dart';
|
|||
import "package:photos/events/endpoint_updated_event.dart";
|
||||
import 'package:photos/events/signed_in_event.dart';
|
||||
import 'package:photos/events/user_logged_out_event.dart';
|
||||
import "package:photos/face/db.dart";
|
||||
import 'package:photos/models/key_attributes.dart';
|
||||
import 'package:photos/models/key_gen_result.dart';
|
||||
import 'package:photos/models/private_key_attributes.dart';
|
||||
|
@ -34,10 +35,10 @@ import 'package:photos/services/sync_service.dart';
|
|||
import 'package:photos/utils/crypto_util.dart';
|
||||
import 'package:photos/utils/file_uploader.dart';
|
||||
import 'package:photos/utils/validator_util.dart';
|
||||
import "package:photos/utils/wakelock_util.dart";
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import "package:tuple/tuple.dart";
|
||||
import 'package:uuid/uuid.dart';
|
||||
import 'package:wakelock_plus/wakelock_plus.dart';
|
||||
|
||||
class Configuration {
|
||||
Configuration._privateConstructor();
|
||||
|
@ -187,6 +188,7 @@ class Configuration {
|
|||
: null;
|
||||
await CollectionsDB.instance.clearTable();
|
||||
await MemoriesDB.instance.clearTable();
|
||||
await FaceMLDataDB.instance.clearTable();
|
||||
|
||||
await UploadLocksDB.instance.clearTable();
|
||||
await IgnoredFilesService.instance.reset();
|
||||
|
@ -583,7 +585,7 @@ class Configuration {
|
|||
|
||||
Future<void> setShouldKeepDeviceAwake(bool value) async {
|
||||
await _preferences.setBool(keyShouldKeepDeviceAwake, value);
|
||||
await WakelockPlus.toggle(enable: value);
|
||||
await EnteWakeLock.toggle(enable: value);
|
||||
}
|
||||
|
||||
Future<void> setShouldBackupVideos(bool value) async {
|
||||
|
|
|
@ -69,6 +69,8 @@ const galleryGridSpacing = 2.0;
|
|||
|
||||
const kSearchSectionLimit = 9;
|
||||
|
||||
const maxPickAssetLimit = 50;
|
||||
|
||||
const iOSGroupID = "group.io.ente.frame.SlideshowWidget";
|
||||
|
||||
const blackThumbnailBase64 = '/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAEBAQEBAQEB'
|
||||
|
@ -99,6 +101,9 @@ const blackThumbnailBase64 = '/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAEBAQEBAQEB'
|
|||
'AKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAo' +
|
||||
'AKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgD/9k=';
|
||||
|
||||
const localFileServer =
|
||||
String.fromEnvironment("localFileServer", defaultValue: "");
|
||||
|
||||
const uploadTempFilePrefix = "upload_file_";
|
||||
final tempDirCleanUpInterval = kDebugMode
|
||||
? const Duration(seconds: 30).inMicroseconds
|
||||
|
|
|
@ -54,7 +54,7 @@ class EmbeddingsDB {
|
|||
|
||||
Future<void> clearTable() async {
|
||||
final db = await _database;
|
||||
await db.execute('DELETE * FROM $tableName');
|
||||
await db.execute('DELETE FROM $tableName');
|
||||
}
|
||||
|
||||
Future<List<Embedding>> getAll(Model model) async {
|
||||
|
|
|
@ -9,7 +9,7 @@ extension EntitiesDB on FilesDB {
|
|||
List<LocalEntityData> data, {
|
||||
ConflictAlgorithm conflictAlgorithm = ConflictAlgorithm.replace,
|
||||
}) async {
|
||||
debugPrint("Inserting missing PathIDToLocalIDMapping");
|
||||
debugPrint("entitiesDB: upsertEntities ${data.length} entities");
|
||||
final db = await database;
|
||||
var batch = db.batch();
|
||||
int batchCounter = 0;
|
||||
|
@ -62,4 +62,17 @@ extension EntitiesDB on FilesDB {
|
|||
return LocalEntityData.fromJson(maps[i]);
|
||||
});
|
||||
}
|
||||
|
||||
Future<LocalEntityData?> getEntity(EntityType type, String id) async {
|
||||
final db = await database;
|
||||
final List<Map<String, dynamic>> maps = await db.query(
|
||||
"entities",
|
||||
where: "type = ? AND id = ?",
|
||||
whereArgs: [type.typeToString(), id],
|
||||
);
|
||||
if (maps.isEmpty) {
|
||||
return null;
|
||||
}
|
||||
return LocalEntityData.fromJson(maps.first);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -491,6 +491,18 @@ class FilesDB {
|
|||
return convertToFiles(results)[0];
|
||||
}
|
||||
|
||||
Future<EnteFile?> getAnyUploadedFile(int uploadedID) async {
|
||||
final db = await instance.sqliteAsyncDB;
|
||||
final results = await db.getAll(
|
||||
'SELECT * FROM $filesTable WHERE $columnUploadedFileID = ?',
|
||||
[uploadedID],
|
||||
);
|
||||
if (results.isEmpty) {
|
||||
return null;
|
||||
}
|
||||
return convertToFiles(results)[0];
|
||||
}
|
||||
|
||||
Future<Set<int>> getUploadedFileIDs(int collectionID) async {
|
||||
final db = await instance.sqliteAsyncDB;
|
||||
final results = await db.getAll(
|
||||
|
@ -683,6 +695,17 @@ class FilesDB {
|
|||
return files;
|
||||
}
|
||||
|
||||
Future<List<EnteFile>> getAllFilesFromCollections(
|
||||
Iterable<int> collectionID,
|
||||
) async {
|
||||
final db = await instance.sqliteAsyncDB;
|
||||
final String sql =
|
||||
'SELECT * FROM $filesTable WHERE $columnCollectionID IN (${collectionID.join(',')})';
|
||||
final results = await db.getAll(sql);
|
||||
final files = convertToFiles(results);
|
||||
return files;
|
||||
}
|
||||
|
||||
Future<List<EnteFile>> getNewFilesInCollection(
|
||||
int collectionID,
|
||||
int addedTime,
|
||||
|
@ -1304,6 +1327,23 @@ class FilesDB {
|
|||
return result;
|
||||
}
|
||||
|
||||
Future<Map<int, int>> getFileIDToCreationTime() async {
|
||||
final db = await instance.sqliteAsyncDB;
|
||||
final rows = await db.getAll(
|
||||
'''
|
||||
SELECT $columnUploadedFileID, $columnCreationTime
|
||||
FROM $filesTable
|
||||
WHERE
|
||||
($columnUploadedFileID IS NOT NULL AND $columnUploadedFileID IS NOT -1);
|
||||
''',
|
||||
);
|
||||
final result = <int, int>{};
|
||||
for (final row in rows) {
|
||||
result[row[columnUploadedFileID] as int] = row[columnCreationTime] as int;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// getCollectionFileFirstOrLast returns the first or last uploaded file in
|
||||
// the collection based on the given collectionID and the order.
|
||||
Future<EnteFile?> getCollectionFileFirstOrLast(
|
||||
|
@ -1643,13 +1683,14 @@ class FilesDB {
|
|||
}
|
||||
|
||||
Future<List<int>> getOwnedFileIDs(int ownerID) async {
|
||||
final db = await instance.database;
|
||||
final results = await db.query(
|
||||
filesTable,
|
||||
columns: [columnUploadedFileID],
|
||||
where:
|
||||
'($columnOwnerID = $ownerID AND $columnUploadedFileID IS NOT NULL AND $columnUploadedFileID IS NOT -1)',
|
||||
distinct: true,
|
||||
final db = await instance.sqliteAsyncDB;
|
||||
final results = await db.getAll(
|
||||
'''
|
||||
SELECT DISTINCT $columnUploadedFileID FROM $filesTable
|
||||
WHERE ($columnOwnerID = ? AND $columnUploadedFileID IS NOT NULL AND
|
||||
$columnUploadedFileID IS NOT -1)
|
||||
''',
|
||||
[ownerID],
|
||||
);
|
||||
final ids = <int>[];
|
||||
for (final result in results) {
|
||||
|
@ -1659,16 +1700,17 @@ class FilesDB {
|
|||
}
|
||||
|
||||
Future<List<EnteFile>> getUploadedFiles(List<int> uploadedIDs) async {
|
||||
final db = await instance.database;
|
||||
final db = await instance.sqliteAsyncDB;
|
||||
String inParam = "";
|
||||
for (final id in uploadedIDs) {
|
||||
inParam += "'" + id.toString() + "',";
|
||||
}
|
||||
inParam = inParam.substring(0, inParam.length - 1);
|
||||
final results = await db.query(
|
||||
filesTable,
|
||||
where: '$columnUploadedFileID IN ($inParam)',
|
||||
groupBy: columnUploadedFileID,
|
||||
final results = await db.getAll(
|
||||
'''
|
||||
SELECT * FROM $filesTable WHERE $columnUploadedFileID IN ($inParam)
|
||||
GROUP BY $columnUploadedFileID
|
||||
''',
|
||||
);
|
||||
if (results.isEmpty) {
|
||||
return <EnteFile>[];
|
||||
|
|
|
@ -26,4 +26,6 @@ enum EventType {
|
|||
hide,
|
||||
unhide,
|
||||
coverChanged,
|
||||
peopleChanged,
|
||||
peopleClusterChanged,
|
||||
}
|
||||
|
|
22
mobile/lib/events/people_changed_event.dart
Normal file
|
@ -0,0 +1,22 @@
|
|||
import "package:photos/events/event.dart";
|
||||
import "package:photos/models/file/file.dart";
|
||||
|
||||
class PeopleChangedEvent extends Event {
|
||||
final List<EnteFile>? relevantFiles;
|
||||
final PeopleEventType type;
|
||||
final String source;
|
||||
|
||||
PeopleChangedEvent({
|
||||
this.relevantFiles,
|
||||
this.type = PeopleEventType.defaultType,
|
||||
this.source = "",
|
||||
});
|
||||
|
||||
@override
|
||||
String get reason => '$runtimeType{type: ${type.name}, "via": $source}';
|
||||
}
|
||||
|
||||
enum PeopleEventType {
|
||||
defaultType,
|
||||
removedFilesFromCluster,
|
||||
}
|
193
mobile/lib/extensions/ml_linalg_extensions.dart
Normal file
|
@ -0,0 +1,193 @@
|
|||
import 'dart:math' as math show sin, cos, atan2, sqrt, pow;
|
||||
import 'package:ml_linalg/linalg.dart';
|
||||
|
||||
extension SetVectorValues on Vector {
|
||||
Vector setValues(int start, int end, Iterable<double> values) {
|
||||
if (values.length > length) {
|
||||
throw Exception('Values cannot be larger than vector');
|
||||
} else if (end - start != values.length) {
|
||||
throw Exception('Values must be same length as range');
|
||||
} else if (start < 0 || end > length) {
|
||||
throw Exception('Range must be within vector');
|
||||
}
|
||||
final tempList = toList();
|
||||
tempList.replaceRange(start, end, values);
|
||||
final newVector = Vector.fromList(tempList);
|
||||
return newVector;
|
||||
}
|
||||
}
|
||||
|
||||
extension SetMatrixValues on Matrix {
|
||||
Matrix setSubMatrix(
|
||||
int startRow,
|
||||
int endRow,
|
||||
int startColumn,
|
||||
int endColumn,
|
||||
Iterable<Iterable<double>> values,
|
||||
) {
|
||||
if (values.length > rowCount) {
|
||||
throw Exception('New values cannot have more rows than original matrix');
|
||||
} else if (values.elementAt(0).length > columnCount) {
|
||||
throw Exception(
|
||||
'New values cannot have more columns than original matrix',
|
||||
);
|
||||
} else if (endRow - startRow != values.length) {
|
||||
throw Exception('Values (number of rows) must be same length as range');
|
||||
} else if (endColumn - startColumn != values.elementAt(0).length) {
|
||||
throw Exception(
|
||||
'Values (number of columns) must be same length as range',
|
||||
);
|
||||
} else if (startRow < 0 ||
|
||||
endRow > rowCount ||
|
||||
startColumn < 0 ||
|
||||
endColumn > columnCount) {
|
||||
throw Exception('Range must be within matrix');
|
||||
}
|
||||
final tempList = asFlattenedList
|
||||
.toList(); // You need `.toList()` here to make sure the list is growable, otherwise `replaceRange` will throw an error
|
||||
for (var i = startRow; i < endRow; i++) {
|
||||
tempList.replaceRange(
|
||||
i * columnCount + startColumn,
|
||||
i * columnCount + endColumn,
|
||||
values.elementAt(i).toList(),
|
||||
);
|
||||
}
|
||||
final newMatrix = Matrix.fromFlattenedList(tempList, rowCount, columnCount);
|
||||
return newMatrix;
|
||||
}
|
||||
|
||||
Matrix setValues(
|
||||
int startRow,
|
||||
int endRow,
|
||||
int startColumn,
|
||||
int endColumn,
|
||||
Iterable<double> values,
|
||||
) {
|
||||
if ((startRow - endRow) * (startColumn - endColumn) != values.length) {
|
||||
throw Exception('Values must be same length as range');
|
||||
} else if (startRow < 0 ||
|
||||
endRow > rowCount ||
|
||||
startColumn < 0 ||
|
||||
endColumn > columnCount) {
|
||||
throw Exception('Range must be within matrix');
|
||||
}
|
||||
|
||||
final tempList = asFlattenedList
|
||||
.toList(); // You need `.toList()` here to make sure the list is growable, otherwise `replaceRange` will throw an error
|
||||
var index = 0;
|
||||
for (var i = startRow; i < endRow; i++) {
|
||||
for (var j = startColumn; j < endColumn; j++) {
|
||||
tempList[i * columnCount + j] = values.elementAt(index);
|
||||
index++;
|
||||
}
|
||||
}
|
||||
final newMatrix = Matrix.fromFlattenedList(tempList, rowCount, columnCount);
|
||||
return newMatrix;
|
||||
}
|
||||
|
||||
Matrix setValue(int row, int column, double value) {
|
||||
if (row < 0 || row > rowCount || column < 0 || column > columnCount) {
|
||||
throw Exception('Index must be within range of matrix');
|
||||
}
|
||||
final tempList = asFlattenedList;
|
||||
tempList[row * columnCount + column] = value;
|
||||
final newMatrix = Matrix.fromFlattenedList(tempList, rowCount, columnCount);
|
||||
return newMatrix;
|
||||
}
|
||||
|
||||
Matrix appendRow(List<double> row) {
|
||||
final oldNumberOfRows = rowCount;
|
||||
final oldNumberOfColumns = columnCount;
|
||||
if (row.length != oldNumberOfColumns) {
|
||||
throw Exception('Row must have same number of columns as matrix');
|
||||
}
|
||||
final flatListMatrix = asFlattenedList;
|
||||
flatListMatrix.addAll(row);
|
||||
return Matrix.fromFlattenedList(
|
||||
flatListMatrix,
|
||||
oldNumberOfRows + 1,
|
||||
oldNumberOfColumns,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
extension MatrixCalculations on Matrix {
|
||||
double determinant() {
|
||||
final int length = rowCount;
|
||||
if (length != columnCount) {
|
||||
throw Exception('Matrix must be square');
|
||||
}
|
||||
if (length == 1) {
|
||||
return this[0][0];
|
||||
} else if (length == 2) {
|
||||
return this[0][0] * this[1][1] - this[0][1] * this[1][0];
|
||||
} else {
|
||||
throw Exception('Determinant for Matrix larger than 2x2 not implemented');
|
||||
}
|
||||
}
|
||||
|
||||
/// Computes the singular value decomposition of a matrix, using https://lucidar.me/en/mathematics/singular-value-decomposition-of-a-2x2-matrix/ as reference, but with slightly different signs for the second columns of U and V
|
||||
Map<String, dynamic> svd() {
|
||||
if (rowCount != 2 || columnCount != 2) {
|
||||
throw Exception('Matrix must be 2x2');
|
||||
}
|
||||
final a = this[0][0];
|
||||
final b = this[0][1];
|
||||
final c = this[1][0];
|
||||
final d = this[1][1];
|
||||
|
||||
// Computation of U matrix
|
||||
final tempCalc = a * a + b * b - c * c - d * d;
|
||||
final theta = 0.5 * math.atan2(2 * a * c + 2 * b * d, tempCalc);
|
||||
final U = Matrix.fromList([
|
||||
[math.cos(theta), math.sin(theta)],
|
||||
[math.sin(theta), -math.cos(theta)],
|
||||
]);
|
||||
|
||||
// Computation of S matrix
|
||||
// ignore: non_constant_identifier_names
|
||||
final S1 = a * a + b * b + c * c + d * d;
|
||||
// ignore: non_constant_identifier_names
|
||||
final S2 =
|
||||
math.sqrt(math.pow(tempCalc, 2) + 4 * math.pow(a * c + b * d, 2));
|
||||
final sigma1 = math.sqrt((S1 + S2) / 2);
|
||||
final sigma2 = math.sqrt((S1 - S2) / 2);
|
||||
final S = Vector.fromList([sigma1, sigma2]);
|
||||
|
||||
// Computation of V matrix
|
||||
final tempCalc2 = a * a - b * b + c * c - d * d;
|
||||
final phi = 0.5 * math.atan2(2 * a * b + 2 * c * d, tempCalc2);
|
||||
final s11 = (a * math.cos(theta) + c * math.sin(theta)) * math.cos(phi) +
|
||||
(b * math.cos(theta) + d * math.sin(theta)) * math.sin(phi);
|
||||
final s22 = (a * math.sin(theta) - c * math.cos(theta)) * math.sin(phi) +
|
||||
(-b * math.sin(theta) + d * math.cos(theta)) * math.cos(phi);
|
||||
final V = Matrix.fromList([
|
||||
[s11.sign * math.cos(phi), s22.sign * math.sin(phi)],
|
||||
[s11.sign * math.sin(phi), -s22.sign * math.cos(phi)],
|
||||
]);
|
||||
|
||||
return {
|
||||
'U': U,
|
||||
'S': S,
|
||||
'V': V,
|
||||
};
|
||||
}
|
||||
|
||||
int matrixRank() {
|
||||
final svdResult = svd();
|
||||
final Vector S = svdResult['S']!;
|
||||
final rank = S.toList().where((element) => element > 1e-10).length;
|
||||
return rank;
|
||||
}
|
||||
}
|
||||
|
||||
extension TransformMatrix on Matrix {
|
||||
List<List<double>> to2DList() {
|
||||
final List<List<double>> outerList = [];
|
||||
for (var i = 0; i < rowCount; i++) {
|
||||
final innerList = this[i].toList();
|
||||
outerList.add(innerList);
|
||||
}
|
||||
return outerList;
|
||||
}
|
||||
}
|
|
@ -23,4 +23,9 @@ class EnteWatch extends Stopwatch {
|
|||
reset();
|
||||
previousElapsed = 0;
|
||||
}
|
||||
|
||||
void stopWithLog(String msg) {
|
||||
log(msg);
|
||||
stop();
|
||||
}
|
||||
}
|
||||
|
|
1083
mobile/lib/face/db.dart
Normal file
97
mobile/lib/face/db_fields.dart
Normal file
|
@ -0,0 +1,97 @@
|
|||
// Faces Table Fields & Schema Queries
|
||||
import 'package:photos/services/machine_learning/face_ml/face_filtering/face_filtering_constants.dart';
|
||||
|
||||
const facesTable = 'faces';
|
||||
const fileIDColumn = 'file_id';
|
||||
const faceIDColumn = 'face_id';
|
||||
const faceDetectionColumn = 'detection';
|
||||
const faceEmbeddingBlob = 'eBlob';
|
||||
const faceScore = 'score';
|
||||
const faceBlur = 'blur';
|
||||
const isSideways = 'is_sideways';
|
||||
const imageWidth = 'width';
|
||||
const imageHeight = 'height';
|
||||
const faceClusterId = 'cluster_id';
|
||||
const mlVersionColumn = 'ml_version';
|
||||
|
||||
const createFacesTable = '''CREATE TABLE IF NOT EXISTS $facesTable (
|
||||
$fileIDColumn INTEGER NOT NULL,
|
||||
$faceIDColumn TEXT NOT NULL UNIQUE,
|
||||
$faceDetectionColumn TEXT NOT NULL,
|
||||
$faceEmbeddingBlob BLOB NOT NULL,
|
||||
$faceScore REAL NOT NULL,
|
||||
$faceBlur REAL NOT NULL DEFAULT $kLapacianDefault,
|
||||
$isSideways INTEGER NOT NULL DEFAULT 0,
|
||||
$imageHeight INTEGER NOT NULL DEFAULT 0,
|
||||
$imageWidth INTEGER NOT NULL DEFAULT 0,
|
||||
$mlVersionColumn INTEGER NOT NULL DEFAULT -1,
|
||||
PRIMARY KEY($fileIDColumn, $faceIDColumn)
|
||||
);
|
||||
''';
|
||||
|
||||
const deleteFacesTable = 'DELETE FROM $facesTable';
|
||||
// End of Faces Table Fields & Schema Queries
|
||||
|
||||
//##region Face Clusters Table Fields & Schema Queries
|
||||
const faceClustersTable = 'face_clusters';
|
||||
const fcClusterID = 'cluster_id';
|
||||
const fcFaceId = 'face_id';
|
||||
|
||||
// fcClusterId & fcFaceId are the primary keys and fcClusterId is a foreign key to faces table
|
||||
const createFaceClustersTable = '''
|
||||
CREATE TABLE IF NOT EXISTS $faceClustersTable (
|
||||
$fcFaceId TEXT NOT NULL,
|
||||
$fcClusterID INTEGER NOT NULL,
|
||||
PRIMARY KEY($fcFaceId)
|
||||
);
|
||||
''';
|
||||
// -- Creating a non-unique index on clusterID for query optimization
|
||||
const fcClusterIDIndex =
|
||||
'''CREATE INDEX IF NOT EXISTS idx_fcClusterID ON $faceClustersTable($fcClusterID);''';
|
||||
const deleteFaceClustersTable = 'DELETE FROM $faceClustersTable';
|
||||
//##endregion
|
||||
|
||||
// Clusters Table Fields & Schema Queries
|
||||
const clusterPersonTable = 'cluster_person';
|
||||
const personIdColumn = 'person_id';
|
||||
const clusterIDColumn = 'cluster_id';
|
||||
|
||||
const createClusterPersonTable = '''
|
||||
CREATE TABLE IF NOT EXISTS $clusterPersonTable (
|
||||
$personIdColumn TEXT NOT NULL,
|
||||
$clusterIDColumn INTEGER NOT NULL,
|
||||
PRIMARY KEY($personIdColumn, $clusterIDColumn)
|
||||
);
|
||||
''';
|
||||
const deleteClusterPersonTable = 'DELETE FROM $clusterPersonTable';
|
||||
// End Clusters Table Fields & Schema Queries
|
||||
|
||||
/// Cluster Summary Table Fields & Schema Queries
|
||||
const clusterSummaryTable = 'cluster_summary';
|
||||
const avgColumn = 'avg';
|
||||
const countColumn = 'count';
|
||||
const createClusterSummaryTable = '''
|
||||
CREATE TABLE IF NOT EXISTS $clusterSummaryTable (
|
||||
$clusterIDColumn INTEGER NOT NULL,
|
||||
$avgColumn BLOB NOT NULL,
|
||||
$countColumn INTEGER NOT NULL,
|
||||
PRIMARY KEY($clusterIDColumn)
|
||||
);
|
||||
''';
|
||||
|
||||
const deleteClusterSummaryTable = 'DELETE FROM $clusterSummaryTable';
|
||||
|
||||
/// End Cluster Summary Table Fields & Schema Queries
|
||||
|
||||
/// notPersonFeedback Table Fields & Schema Queries
|
||||
const notPersonFeedback = 'not_person_feedback';
|
||||
|
||||
const createNotPersonFeedbackTable = '''
|
||||
CREATE TABLE IF NOT EXISTS $notPersonFeedback (
|
||||
$personIdColumn TEXT NOT NULL,
|
||||
$clusterIDColumn INTEGER NOT NULL,
|
||||
PRIMARY KEY($personIdColumn, $clusterIDColumn)
|
||||
);
|
||||
''';
|
||||
const deleteNotPersonFeedbackTable = 'DELETE FROM $notPersonFeedback';
|
||||
// End Clusters Table Fields & Schema Queries
|
57
mobile/lib/face/db_model_mappers.dart
Normal file
|
@ -0,0 +1,57 @@
|
|||
import "dart:convert";
|
||||
|
||||
import 'package:photos/face/db_fields.dart';
|
||||
import "package:photos/face/model/detection.dart";
|
||||
import "package:photos/face/model/face.dart";
|
||||
import "package:photos/generated/protos/ente/common/vector.pb.dart";
|
||||
import "package:photos/models/ml/ml_versions.dart";
|
||||
|
||||
int boolToSQLInt(bool? value, {bool defaultValue = false}) {
|
||||
final bool v = value ?? defaultValue;
|
||||
if (v == false) {
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
bool sqlIntToBool(int? value, {bool defaultValue = false}) {
|
||||
final int v = value ?? (defaultValue ? 1 : 0);
|
||||
if (v == 0) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, dynamic> mapRemoteToFaceDB(Face face) {
|
||||
return {
|
||||
faceIDColumn: face.faceID,
|
||||
fileIDColumn: face.fileID,
|
||||
faceDetectionColumn: json.encode(face.detection.toJson()),
|
||||
faceEmbeddingBlob: EVector(
|
||||
values: face.embedding,
|
||||
).writeToBuffer(),
|
||||
faceScore: face.score,
|
||||
faceBlur: face.blur,
|
||||
isSideways: face.detection.faceIsSideways() ? 1 : 0,
|
||||
mlVersionColumn: faceMlVersion,
|
||||
imageWidth: face.fileInfo?.imageWidth ?? 0,
|
||||
imageHeight: face.fileInfo?.imageHeight ?? 0,
|
||||
};
|
||||
}
|
||||
|
||||
Face mapRowToFace(Map<String, dynamic> row) {
|
||||
return Face(
|
||||
row[faceIDColumn] as String,
|
||||
row[fileIDColumn] as int,
|
||||
EVector.fromBuffer(row[faceEmbeddingBlob] as List<int>).values,
|
||||
row[faceScore] as double,
|
||||
Detection.fromJson(json.decode(row[faceDetectionColumn] as String)),
|
||||
row[faceBlur] as double,
|
||||
fileInfo: FileInfo(
|
||||
imageWidth: row[imageWidth] as int,
|
||||
imageHeight: row[imageHeight] as int,
|
||||
),
|
||||
);
|
||||
}
|
35
mobile/lib/face/model/box.dart
Normal file
|
@ -0,0 +1,35 @@
|
|||
/// Bounding box of a face.
|
||||
///
|
||||
/// [ x] and [y] are the minimum coordinates, so the top left corner of the box.
|
||||
/// [width] and [height] are the width and height of the box.
|
||||
///
|
||||
/// WARNING: All values are relative to the original image size, so in the range [0, 1].
|
||||
class FaceBox {
|
||||
final double x;
|
||||
final double y;
|
||||
final double width;
|
||||
final double height;
|
||||
|
||||
FaceBox({
|
||||
required this.x,
|
||||
required this.y,
|
||||
required this.width,
|
||||
required this.height,
|
||||
});
|
||||
|
||||
factory FaceBox.fromJson(Map<String, dynamic> json) {
|
||||
return FaceBox(
|
||||
x: (json['x'] as double?) ?? (json['xMin'] as double),
|
||||
y: (json['y'] as double?) ?? (json['yMin'] as double),
|
||||
width: json['width'] as double,
|
||||
height: json['height'] as double,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
'x': x,
|
||||
'y': y,
|
||||
'width': width,
|
||||
'height': height,
|
||||
};
|
||||
}
|
120
mobile/lib/face/model/detection.dart
Normal file
|
@ -0,0 +1,120 @@
|
|||
import "dart:math" show min, max;
|
||||
|
||||
import "package:photos/face/model/box.dart";
|
||||
import "package:photos/face/model/landmark.dart";
|
||||
import "package:photos/services/machine_learning/face_ml/face_detection/detection.dart";
|
||||
|
||||
/// Stores the face detection data, notably the bounding box and landmarks.
|
||||
///
|
||||
/// - Bounding box: [FaceBox] with x, y (minimum, so top left corner), width, height
|
||||
/// - Landmarks: list of [Landmark]s, namely leftEye, rightEye, nose, leftMouth, rightMouth
|
||||
///
|
||||
/// WARNING: All coordinates are relative to the image size, so in the range [0, 1]!
|
||||
class Detection {
|
||||
FaceBox box;
|
||||
List<Landmark> landmarks;
|
||||
|
||||
Detection({
|
||||
required this.box,
|
||||
required this.landmarks,
|
||||
});
|
||||
|
||||
bool get isEmpty => box.width == 0 && box.height == 0 && landmarks.isEmpty;
|
||||
|
||||
// empty box
|
||||
Detection.empty()
|
||||
: box = FaceBox(
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 0,
|
||||
height: 0,
|
||||
),
|
||||
landmarks = [];
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
'box': box.toJson(),
|
||||
'landmarks': landmarks.map((x) => x.toJson()).toList(),
|
||||
};
|
||||
|
||||
factory Detection.fromJson(Map<String, dynamic> json) {
|
||||
return Detection(
|
||||
box: FaceBox.fromJson(json['box'] as Map<String, dynamic>),
|
||||
landmarks: List<Landmark>.from(
|
||||
json['landmarks']
|
||||
.map((x) => Landmark.fromJson(x as Map<String, dynamic>)),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
int getFaceArea(int imageWidth, int imageHeight) {
|
||||
return (box.width * imageWidth * box.height * imageHeight).toInt();
|
||||
}
|
||||
|
||||
FaceDirection getFaceDirection() {
|
||||
if (isEmpty) {
|
||||
return FaceDirection.straight;
|
||||
}
|
||||
final leftEye = [landmarks[0].x, landmarks[0].y];
|
||||
final rightEye = [landmarks[1].x, landmarks[1].y];
|
||||
final nose = [landmarks[2].x, landmarks[2].y];
|
||||
final leftMouth = [landmarks[3].x, landmarks[3].y];
|
||||
final rightMouth = [landmarks[4].x, landmarks[4].y];
|
||||
|
||||
final double eyeDistanceX = (rightEye[0] - leftEye[0]).abs();
|
||||
final double eyeDistanceY = (rightEye[1] - leftEye[1]).abs();
|
||||
final double mouthDistanceY = (rightMouth[1] - leftMouth[1]).abs();
|
||||
|
||||
final bool faceIsUpright =
|
||||
(max(leftEye[1], rightEye[1]) + 0.5 * eyeDistanceY < nose[1]) &&
|
||||
(nose[1] + 0.5 * mouthDistanceY < min(leftMouth[1], rightMouth[1]));
|
||||
|
||||
final bool noseStickingOutLeft = (nose[0] < min(leftEye[0], rightEye[0])) &&
|
||||
(nose[0] < min(leftMouth[0], rightMouth[0]));
|
||||
final bool noseStickingOutRight =
|
||||
(nose[0] > max(leftEye[0], rightEye[0])) &&
|
||||
(nose[0] > max(leftMouth[0], rightMouth[0]));
|
||||
|
||||
final bool noseCloseToLeftEye =
|
||||
(nose[0] - leftEye[0]).abs() < 0.2 * eyeDistanceX;
|
||||
final bool noseCloseToRightEye =
|
||||
(nose[0] - rightEye[0]).abs() < 0.2 * eyeDistanceX;
|
||||
|
||||
// if (faceIsUpright && (noseStickingOutLeft || noseCloseToLeftEye)) {
|
||||
if (noseStickingOutLeft || (faceIsUpright && noseCloseToLeftEye)) {
|
||||
return FaceDirection.left;
|
||||
// } else if (faceIsUpright && (noseStickingOutRight || noseCloseToRightEye)) {
|
||||
} else if (noseStickingOutRight || (faceIsUpright && noseCloseToRightEye)) {
|
||||
return FaceDirection.right;
|
||||
}
|
||||
|
||||
return FaceDirection.straight;
|
||||
}
|
||||
|
||||
bool faceIsSideways() {
|
||||
if (isEmpty) {
|
||||
return false;
|
||||
}
|
||||
final leftEye = [landmarks[0].x, landmarks[0].y];
|
||||
final rightEye = [landmarks[1].x, landmarks[1].y];
|
||||
final nose = [landmarks[2].x, landmarks[2].y];
|
||||
final leftMouth = [landmarks[3].x, landmarks[3].y];
|
||||
final rightMouth = [landmarks[4].x, landmarks[4].y];
|
||||
|
||||
final double eyeDistanceX = (rightEye[0] - leftEye[0]).abs();
|
||||
final double eyeDistanceY = (rightEye[1] - leftEye[1]).abs();
|
||||
final double mouthDistanceY = (rightMouth[1] - leftMouth[1]).abs();
|
||||
|
||||
final bool faceIsUpright =
|
||||
(max(leftEye[1], rightEye[1]) + 0.5 * eyeDistanceY < nose[1]) &&
|
||||
(nose[1] + 0.5 * mouthDistanceY < min(leftMouth[1], rightMouth[1]));
|
||||
|
||||
final bool noseStickingOutLeft =
|
||||
(nose[0] < min(leftEye[0], rightEye[0]) - 0.5 * eyeDistanceX) &&
|
||||
(nose[0] < min(leftMouth[0], rightMouth[0]));
|
||||
final bool noseStickingOutRight =
|
||||
(nose[0] > max(leftEye[0], rightEye[0]) + 0.5 * eyeDistanceX) &&
|
||||
(nose[0] > max(leftMouth[0], rightMouth[0]));
|
||||
|
||||
return faceIsUpright && (noseStickingOutLeft || noseStickingOutRight);
|
||||
}
|
||||
}
|
25
mobile/lib/face/model/dimension.dart
Normal file
|
@ -0,0 +1,25 @@
|
|||
class Dimensions {
|
||||
final int width;
|
||||
final int height;
|
||||
|
||||
const Dimensions({required this.width, required this.height});
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'Dimensions(width: $width, height: $height})';
|
||||
}
|
||||
|
||||
Map<String, int> toJson() {
|
||||
return {
|
||||
'width': width,
|
||||
'height': height,
|
||||
};
|
||||
}
|
||||
|
||||
factory Dimensions.fromJson(Map<String, dynamic> json) {
|
||||
return Dimensions(
|
||||
width: json['width'] as int,
|
||||
height: json['height'] as int,
|
||||
);
|
||||
}
|
||||
}
|
85
mobile/lib/face/model/face.dart
Normal file
|
@ -0,0 +1,85 @@
|
|||
import "package:photos/face/model/detection.dart";
|
||||
import 'package:photos/services/machine_learning/face_ml/face_filtering/face_filtering_constants.dart';
|
||||
import "package:photos/services/machine_learning/face_ml/face_ml_result.dart";
|
||||
|
||||
// FileInfo contains the image width and height of the image the face was detected in.
|
||||
class FileInfo {
|
||||
int? imageWidth;
|
||||
int? imageHeight;
|
||||
FileInfo({
|
||||
this.imageWidth,
|
||||
this.imageHeight,
|
||||
});
|
||||
}
|
||||
|
||||
class Face {
|
||||
final String faceID;
|
||||
final List<double> embedding;
|
||||
Detection detection;
|
||||
final double score;
|
||||
final double blur;
|
||||
|
||||
///#region Local DB fields
|
||||
// This is not stored on the server, using it for local DB row
|
||||
FileInfo? fileInfo;
|
||||
final int fileID;
|
||||
///#endregion
|
||||
|
||||
bool get isBlurry => blur < kLaplacianHardThreshold;
|
||||
|
||||
bool get hasHighScore => score > kMinimumQualityFaceScore;
|
||||
|
||||
bool get isHighQuality => (!isBlurry) && hasHighScore;
|
||||
|
||||
int area({int? w, int? h}) {
|
||||
return detection.getFaceArea(
|
||||
fileInfo?.imageWidth ?? w ?? 0,
|
||||
fileInfo?.imageHeight ?? h ?? 0,
|
||||
);
|
||||
}
|
||||
|
||||
Face(
|
||||
this.faceID,
|
||||
this.fileID,
|
||||
this.embedding,
|
||||
this.score,
|
||||
this.detection,
|
||||
this.blur, {
|
||||
this.fileInfo,
|
||||
});
|
||||
|
||||
factory Face.empty(int fileID, {bool error = false}) {
|
||||
return Face(
|
||||
"$fileID-0",
|
||||
fileID,
|
||||
<double>[],
|
||||
error ? -1.0 : 0.0,
|
||||
Detection.empty(),
|
||||
0.0,
|
||||
);
|
||||
}
|
||||
|
||||
factory Face.fromJson(Map<String, dynamic> json) {
|
||||
final String faceID = json['faceID'] as String;
|
||||
final int fileID = getFileIdFromFaceId(faceID);
|
||||
return Face(
|
||||
faceID,
|
||||
fileID,
|
||||
List<double>.from((json['embedding'] ?? json['embeddings']) as List),
|
||||
json['score'] as double,
|
||||
Detection.fromJson(json['detection'] as Map<String, dynamic>),
|
||||
// high value means t
|
||||
(json['blur'] ?? kLapacianDefault) as double,
|
||||
);
|
||||
}
|
||||
|
||||
// Note: Keep the information in toJson minimum. Keep in sync with desktop.
|
||||
// Derive fields like fileID from other values whenever possible
|
||||
Map<String, dynamic> toJson() => {
|
||||
'faceID': faceID,
|
||||
'embedding': embedding,
|
||||
'detection': detection.toJson(),
|
||||
'score': score,
|
||||
'blur': blur,
|
||||
};
|
||||
}
|
33
mobile/lib/face/model/landmark.dart
Normal file
|
@ -0,0 +1,33 @@
|
|||
/// Landmark coordinate data.
|
||||
///
|
||||
/// WARNING: All coordinates are relative to the image size, so in the range [0, 1]!
|
||||
class Landmark {
|
||||
double x;
|
||||
double y;
|
||||
|
||||
Landmark({
|
||||
required this.x,
|
||||
required this.y,
|
||||
});
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
'x': x,
|
||||
'y': y,
|
||||
};
|
||||
|
||||
factory Landmark.fromJson(Map<String, dynamic> json) {
|
||||
return Landmark(
|
||||
x: (json['x'] is int
|
||||
? (json['x'] as int).toDouble()
|
||||
: json['x'] as double),
|
||||
y: (json['y'] is int
|
||||
? (json['y'] as int).toDouble()
|
||||
: json['y'] as double),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
toString() {
|
||||
return '(x: ${x.toStringAsFixed(4)}, y: ${y.toStringAsFixed(4)})';
|
||||
}
|
||||
}
|
139
mobile/lib/face/model/person.dart
Normal file
|
@ -0,0 +1,139 @@
|
|||
// PersonEntity represents information about a Person in the context of FaceClustering that is stored.
|
||||
// On the remote server, the PersonEntity is stored as {Entity} with type person.
|
||||
// On the device, this information is stored as [LocalEntityData] with type person.
|
||||
import "package:flutter/foundation.dart";
|
||||
|
||||
class PersonEntity {
|
||||
final String remoteID;
|
||||
final PersonData data;
|
||||
PersonEntity(
|
||||
this.remoteID,
|
||||
this.data,
|
||||
);
|
||||
|
||||
// copyWith
|
||||
PersonEntity copyWith({
|
||||
String? remoteID,
|
||||
PersonData? data,
|
||||
}) {
|
||||
return PersonEntity(
|
||||
remoteID ?? this.remoteID,
|
||||
data ?? this.data,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class ClusterInfo {
|
||||
final int id;
|
||||
final Set<String> faces;
|
||||
ClusterInfo({
|
||||
required this.id,
|
||||
required this.faces,
|
||||
});
|
||||
|
||||
// toJson
|
||||
Map<String, dynamic> toJson() => {
|
||||
'id': id,
|
||||
'faces': faces.toList(),
|
||||
};
|
||||
|
||||
// from Json
|
||||
factory ClusterInfo.fromJson(Map<String, dynamic> json) {
|
||||
return ClusterInfo(
|
||||
id: json['id'] as int,
|
||||
faces: (json['faces'] as List<dynamic>).map((e) => e as String).toSet(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class PersonData {
|
||||
final String name;
|
||||
final bool isHidden;
|
||||
String? avatarFaceId;
|
||||
List<ClusterInfo>? assigned = List<ClusterInfo>.empty();
|
||||
List<ClusterInfo>? rejected = List<ClusterInfo>.empty();
|
||||
final String? birthDate;
|
||||
|
||||
bool hasAvatar() => avatarFaceId != null;
|
||||
|
||||
bool get isIgnored =>
|
||||
(name.isEmpty || name == '(hidden)' || name == '(ignored)');
|
||||
|
||||
PersonData({
|
||||
required this.name,
|
||||
this.assigned,
|
||||
this.rejected,
|
||||
this.avatarFaceId,
|
||||
this.isHidden = false,
|
||||
this.birthDate,
|
||||
});
|
||||
// copyWith
|
||||
PersonData copyWith({
|
||||
String? name,
|
||||
List<ClusterInfo>? assigned,
|
||||
String? avatarFaceId,
|
||||
bool? isHidden,
|
||||
int? version,
|
||||
String? birthDate,
|
||||
}) {
|
||||
return PersonData(
|
||||
name: name ?? this.name,
|
||||
assigned: assigned ?? this.assigned,
|
||||
avatarFaceId: avatarFaceId ?? this.avatarFaceId,
|
||||
isHidden: isHidden ?? this.isHidden,
|
||||
birthDate: birthDate ?? this.birthDate,
|
||||
);
|
||||
}
|
||||
|
||||
void logStats() {
|
||||
if (kDebugMode == false) return;
|
||||
// log number of assigned and rejected clusters and total number of faces in each cluster
|
||||
final StringBuffer sb = StringBuffer();
|
||||
sb.writeln('Person: $name');
|
||||
int assignedCount = 0;
|
||||
for (final a in (assigned ?? <ClusterInfo>[])) {
|
||||
assignedCount += a.faces.length;
|
||||
}
|
||||
sb.writeln('Assigned: ${assigned?.length} withFaces $assignedCount');
|
||||
sb.writeln('Rejected: ${rejected?.length}');
|
||||
if (assigned != null) {
|
||||
for (var cluster in assigned!) {
|
||||
sb.writeln('Cluster: ${cluster.id} - ${cluster.faces.length}');
|
||||
}
|
||||
}
|
||||
debugPrint(sb.toString());
|
||||
}
|
||||
|
||||
// toJson
|
||||
Map<String, dynamic> toJson() => {
|
||||
'name': name,
|
||||
'assigned': assigned?.map((e) => e.toJson()).toList(),
|
||||
'rejected': rejected?.map((e) => e.toJson()).toList(),
|
||||
'avatarFaceId': avatarFaceId,
|
||||
'isHidden': isHidden,
|
||||
'birthDate': birthDate,
|
||||
};
|
||||
|
||||
// fromJson
|
||||
factory PersonData.fromJson(Map<String, dynamic> json) {
|
||||
final assigned = (json['assigned'] == null || json['assigned'].length == 0)
|
||||
? <ClusterInfo>[]
|
||||
: List<ClusterInfo>.from(
|
||||
json['assigned'].map((x) => ClusterInfo.fromJson(x)),
|
||||
);
|
||||
|
||||
final rejected = (json['rejected'] == null || json['rejected'].length == 0)
|
||||
? <ClusterInfo>[]
|
||||
: List<ClusterInfo>.from(
|
||||
json['rejected'].map((x) => ClusterInfo.fromJson(x)),
|
||||
);
|
||||
return PersonData(
|
||||
name: json['name'] as String,
|
||||
assigned: assigned,
|
||||
rejected: rejected,
|
||||
avatarFaceId: json['avatarFaceId'] as String?,
|
||||
isHidden: json['isHidden'] as bool? ?? false,
|
||||
birthDate: json['birthDate'] as String?,
|
||||
);
|
||||
}
|
||||
}
|
13
mobile/lib/generated/intl/messages_cs.dart
generated
|
@ -34,6 +34,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
"addViewers": m1,
|
||||
"changeLocationOfSelectedItems": MessageLookupByLibrary.simpleMessage(
|
||||
"Change location of selected items?"),
|
||||
"clusteringProgress":
|
||||
MessageLookupByLibrary.simpleMessage("Clustering progress"),
|
||||
"contacts": MessageLookupByLibrary.simpleMessage("Contacts"),
|
||||
"createCollaborativeLink":
|
||||
MessageLookupByLibrary.simpleMessage("Create collaborative link"),
|
||||
|
@ -44,7 +46,16 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
"editsToLocationWillOnlyBeSeenWithinEnte":
|
||||
MessageLookupByLibrary.simpleMessage(
|
||||
"Edits to location will only be seen within Ente"),
|
||||
"enterPersonName":
|
||||
MessageLookupByLibrary.simpleMessage("Enter person name"),
|
||||
"faceRecognition":
|
||||
MessageLookupByLibrary.simpleMessage("Face recognition"),
|
||||
"faceRecognitionIndexingDescription": MessageLookupByLibrary.simpleMessage(
|
||||
"Please note that this will result in a higher bandwidth and battery usage until all items are indexed."),
|
||||
"fileTypes": MessageLookupByLibrary.simpleMessage("File types"),
|
||||
"foundFaces": MessageLookupByLibrary.simpleMessage("Found faces"),
|
||||
"indexingIsPaused": MessageLookupByLibrary.simpleMessage(
|
||||
"Indexing is paused, will automatically resume when device is ready"),
|
||||
"joinDiscord": MessageLookupByLibrary.simpleMessage("Join Discord"),
|
||||
"locations": MessageLookupByLibrary.simpleMessage("Locations"),
|
||||
"longPressAnEmailToVerifyEndToEndEncryption":
|
||||
|
@ -55,6 +66,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
"Modify your query, or try searching for"),
|
||||
"moveToHiddenAlbum":
|
||||
MessageLookupByLibrary.simpleMessage("Move to hidden album"),
|
||||
"removePersonLabel":
|
||||
MessageLookupByLibrary.simpleMessage("Remove person label"),
|
||||
"search": MessageLookupByLibrary.simpleMessage("Search"),
|
||||
"selectALocation":
|
||||
MessageLookupByLibrary.simpleMessage("Select a location"),
|
||||
|
|
16
mobile/lib/generated/intl/messages_de.dart
generated
|
@ -227,6 +227,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
"Ich verstehe, dass ich meine Daten verlieren kann, wenn ich mein Passwort vergesse, da meine Daten <underline>Ende-zu-Ende-verschlüsselt</underline> sind."),
|
||||
"activeSessions":
|
||||
MessageLookupByLibrary.simpleMessage("Aktive Sitzungen"),
|
||||
"addAName": MessageLookupByLibrary.simpleMessage("Add a name"),
|
||||
"addANewEmail": MessageLookupByLibrary.simpleMessage(
|
||||
"Neue E-Mail-Adresse hinzufügen"),
|
||||
"addCollaborator":
|
||||
|
@ -435,6 +436,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
"Nach Aufnahmezeit gruppieren"),
|
||||
"clubByFileName":
|
||||
MessageLookupByLibrary.simpleMessage("Nach Dateiname gruppieren"),
|
||||
"clusteringProgress":
|
||||
MessageLookupByLibrary.simpleMessage("Clustering progress"),
|
||||
"codeAppliedPageTitle":
|
||||
MessageLookupByLibrary.simpleMessage("Code eingelöst"),
|
||||
"codeCopiedToClipboard": MessageLookupByLibrary.simpleMessage(
|
||||
|
@ -675,6 +678,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
MessageLookupByLibrary.simpleMessage("Passwort eingeben"),
|
||||
"enterPasswordToEncrypt": MessageLookupByLibrary.simpleMessage(
|
||||
"Gib ein Passwort ein, mit dem wir deine Daten verschlüsseln können"),
|
||||
"enterPersonName":
|
||||
MessageLookupByLibrary.simpleMessage("Enter person name"),
|
||||
"enterReferralCode": MessageLookupByLibrary.simpleMessage(
|
||||
"Gib den Weiterempfehlungs-Code ein"),
|
||||
"enterThe6digitCodeFromnyourAuthenticatorApp":
|
||||
|
@ -699,6 +704,10 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
MessageLookupByLibrary.simpleMessage("Protokolle exportieren"),
|
||||
"exportYourData":
|
||||
MessageLookupByLibrary.simpleMessage("Daten exportieren"),
|
||||
"faceRecognition":
|
||||
MessageLookupByLibrary.simpleMessage("Face recognition"),
|
||||
"faceRecognitionIndexingDescription": MessageLookupByLibrary.simpleMessage(
|
||||
"Please note that this will result in a higher bandwidth and battery usage until all items are indexed."),
|
||||
"faces": MessageLookupByLibrary.simpleMessage("Gesichter"),
|
||||
"failedToApplyCode": MessageLookupByLibrary.simpleMessage(
|
||||
"Der Code konnte nicht aktiviert werden"),
|
||||
|
@ -738,11 +747,14 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
"filesBackedUpInAlbum": m23,
|
||||
"filesDeleted":
|
||||
MessageLookupByLibrary.simpleMessage("Dateien gelöscht"),
|
||||
"findPeopleByName": MessageLookupByLibrary.simpleMessage(
|
||||
"Find people quickly by searching by name"),
|
||||
"flip": MessageLookupByLibrary.simpleMessage("Spiegeln"),
|
||||
"forYourMemories":
|
||||
MessageLookupByLibrary.simpleMessage("Als Erinnerung"),
|
||||
"forgotPassword":
|
||||
MessageLookupByLibrary.simpleMessage("Passwort vergessen"),
|
||||
"foundFaces": MessageLookupByLibrary.simpleMessage("Found faces"),
|
||||
"freeStorageClaimed": MessageLookupByLibrary.simpleMessage(
|
||||
"Kostenlos hinzugefügter Speicherplatz"),
|
||||
"freeStorageOnReferralSuccess": m24,
|
||||
|
@ -807,6 +819,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
"Falscher Wiederherstellungs-Schlüssel"),
|
||||
"indexedItems":
|
||||
MessageLookupByLibrary.simpleMessage("Indizierte Elemente"),
|
||||
"indexingIsPaused": MessageLookupByLibrary.simpleMessage(
|
||||
"Indexing is paused, will automatically resume when device is ready"),
|
||||
"insecureDevice":
|
||||
MessageLookupByLibrary.simpleMessage("Unsicheres Gerät"),
|
||||
"installManually":
|
||||
|
@ -1164,6 +1178,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
"removeParticipant":
|
||||
MessageLookupByLibrary.simpleMessage("Teilnehmer entfernen"),
|
||||
"removeParticipantBody": m43,
|
||||
"removePersonLabel":
|
||||
MessageLookupByLibrary.simpleMessage("Remove person label"),
|
||||
"removePublicLink":
|
||||
MessageLookupByLibrary.simpleMessage("Öffentlichen Link entfernen"),
|
||||
"removeShareItemsWarning": MessageLookupByLibrary.simpleMessage(
|
||||
|
|
23
mobile/lib/generated/intl/messages_en.dart
generated
|
@ -132,7 +132,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
"Please talk to ${providerName} support if you were charged";
|
||||
|
||||
static String m38(endDate) =>
|
||||
"Free trial valid till ${endDate}.\nYou can purchase a paid plan afterwards.";
|
||||
"Free trial valid till ${endDate}.\nYou can choose a paid plan afterwards.";
|
||||
|
||||
static String m39(toEmail) => "Please email us at ${toEmail}";
|
||||
|
||||
|
@ -225,6 +225,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
"I understand that if I lose my password, I may lose my data since my data is <underline>end-to-end encrypted</underline>."),
|
||||
"activeSessions":
|
||||
MessageLookupByLibrary.simpleMessage("Active sessions"),
|
||||
"addAName": MessageLookupByLibrary.simpleMessage("Add a name"),
|
||||
"addANewEmail": MessageLookupByLibrary.simpleMessage("Add a new email"),
|
||||
"addCollaborator":
|
||||
MessageLookupByLibrary.simpleMessage("Add collaborator"),
|
||||
|
@ -434,6 +435,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
MessageLookupByLibrary.simpleMessage("Club by capture time"),
|
||||
"clubByFileName":
|
||||
MessageLookupByLibrary.simpleMessage("Club by file name"),
|
||||
"clusteringProgress":
|
||||
MessageLookupByLibrary.simpleMessage("Clustering progress"),
|
||||
"codeAppliedPageTitle":
|
||||
MessageLookupByLibrary.simpleMessage("Code applied"),
|
||||
"codeCopiedToClipboard":
|
||||
|
@ -675,6 +678,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
"enterPassword": MessageLookupByLibrary.simpleMessage("Enter password"),
|
||||
"enterPasswordToEncrypt": MessageLookupByLibrary.simpleMessage(
|
||||
"Enter a password we can use to encrypt your data"),
|
||||
"enterPersonName":
|
||||
MessageLookupByLibrary.simpleMessage("Enter person name"),
|
||||
"enterReferralCode":
|
||||
MessageLookupByLibrary.simpleMessage("Enter referral code"),
|
||||
"enterThe6digitCodeFromnyourAuthenticatorApp":
|
||||
|
@ -697,6 +702,10 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
"exportLogs": MessageLookupByLibrary.simpleMessage("Export logs"),
|
||||
"exportYourData":
|
||||
MessageLookupByLibrary.simpleMessage("Export your data"),
|
||||
"faceRecognition":
|
||||
MessageLookupByLibrary.simpleMessage("Face recognition"),
|
||||
"faceRecognitionIndexingDescription": MessageLookupByLibrary.simpleMessage(
|
||||
"Please note that this will result in a higher bandwidth and battery usage until all items are indexed."),
|
||||
"faces": MessageLookupByLibrary.simpleMessage("Faces"),
|
||||
"failedToApplyCode":
|
||||
MessageLookupByLibrary.simpleMessage("Failed to apply code"),
|
||||
|
@ -736,11 +745,14 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
"filesDeleted": MessageLookupByLibrary.simpleMessage("Files deleted"),
|
||||
"filesSavedToGallery":
|
||||
MessageLookupByLibrary.simpleMessage("Files saved to gallery"),
|
||||
"findPeopleByName":
|
||||
MessageLookupByLibrary.simpleMessage("Find people quickly by name"),
|
||||
"flip": MessageLookupByLibrary.simpleMessage("Flip"),
|
||||
"forYourMemories":
|
||||
MessageLookupByLibrary.simpleMessage("for your memories"),
|
||||
"forgotPassword":
|
||||
MessageLookupByLibrary.simpleMessage("Forgot password"),
|
||||
"foundFaces": MessageLookupByLibrary.simpleMessage("Found faces"),
|
||||
"freeStorageClaimed":
|
||||
MessageLookupByLibrary.simpleMessage("Free storage claimed"),
|
||||
"freeStorageOnReferralSuccess": m24,
|
||||
|
@ -801,6 +813,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
"incorrectRecoveryKeyTitle":
|
||||
MessageLookupByLibrary.simpleMessage("Incorrect recovery key"),
|
||||
"indexedItems": MessageLookupByLibrary.simpleMessage("Indexed items"),
|
||||
"indexingIsPaused": MessageLookupByLibrary.simpleMessage(
|
||||
"Indexing is paused. It will automatically resume when device is ready."),
|
||||
"insecureDevice":
|
||||
MessageLookupByLibrary.simpleMessage("Insecure device"),
|
||||
"installManually":
|
||||
|
@ -1022,6 +1036,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
"paymentFailedTalkToProvider": m37,
|
||||
"pendingItems": MessageLookupByLibrary.simpleMessage("Pending items"),
|
||||
"pendingSync": MessageLookupByLibrary.simpleMessage("Pending sync"),
|
||||
"people": MessageLookupByLibrary.simpleMessage("People"),
|
||||
"peopleUsingYourCode":
|
||||
MessageLookupByLibrary.simpleMessage("People using your code"),
|
||||
"permDeleteWarning": MessageLookupByLibrary.simpleMessage(
|
||||
|
@ -1151,6 +1166,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
"removeParticipant":
|
||||
MessageLookupByLibrary.simpleMessage("Remove participant"),
|
||||
"removeParticipantBody": m43,
|
||||
"removePersonLabel":
|
||||
MessageLookupByLibrary.simpleMessage("Remove person label"),
|
||||
"removePublicLink":
|
||||
MessageLookupByLibrary.simpleMessage("Remove public link"),
|
||||
"removeShareItemsWarning": MessageLookupByLibrary.simpleMessage(
|
||||
|
@ -1208,8 +1225,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
"Add descriptions like \"#trip\" in photo info to quickly find them here"),
|
||||
"searchDatesEmptySection": MessageLookupByLibrary.simpleMessage(
|
||||
"Search by a date, month or year"),
|
||||
"searchFaceEmptySection":
|
||||
MessageLookupByLibrary.simpleMessage("Find all photos of a person"),
|
||||
"searchFaceEmptySection": MessageLookupByLibrary.simpleMessage(
|
||||
"Persons will be shown here once indexing is done"),
|
||||
"searchFileTypesAndNamesEmptySection":
|
||||
MessageLookupByLibrary.simpleMessage("File types and names"),
|
||||
"searchHint1":
|
||||
|
|
13
mobile/lib/generated/intl/messages_es.dart
generated
|
@ -367,6 +367,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
"close": MessageLookupByLibrary.simpleMessage("Cerrar"),
|
||||
"clubByCaptureTime": MessageLookupByLibrary.simpleMessage(
|
||||
"Agrupar por tiempo de captura"),
|
||||
"clusteringProgress":
|
||||
MessageLookupByLibrary.simpleMessage("Clustering progress"),
|
||||
"codeAppliedPageTitle":
|
||||
MessageLookupByLibrary.simpleMessage("Código aplicado"),
|
||||
"codeCopiedToClipboard": MessageLookupByLibrary.simpleMessage(
|
||||
|
@ -585,6 +587,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
MessageLookupByLibrary.simpleMessage("Introduzca contraseña"),
|
||||
"enterPasswordToEncrypt": MessageLookupByLibrary.simpleMessage(
|
||||
"Introduzca una contraseña que podamos usar para cifrar sus datos"),
|
||||
"enterPersonName":
|
||||
MessageLookupByLibrary.simpleMessage("Enter person name"),
|
||||
"enterReferralCode": MessageLookupByLibrary.simpleMessage(
|
||||
"Ingresar código de referencia"),
|
||||
"enterThe6digitCodeFromnyourAuthenticatorApp":
|
||||
|
@ -609,6 +613,10 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
MessageLookupByLibrary.simpleMessage("Exportar registros"),
|
||||
"exportYourData":
|
||||
MessageLookupByLibrary.simpleMessage("Exportar tus datos"),
|
||||
"faceRecognition":
|
||||
MessageLookupByLibrary.simpleMessage("Face recognition"),
|
||||
"faceRecognitionIndexingDescription": MessageLookupByLibrary.simpleMessage(
|
||||
"Please note that this will result in a higher bandwidth and battery usage until all items are indexed."),
|
||||
"failedToApplyCode":
|
||||
MessageLookupByLibrary.simpleMessage("Error al aplicar el código"),
|
||||
"failedToCancel":
|
||||
|
@ -647,6 +655,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
MessageLookupByLibrary.simpleMessage("para tus recuerdos"),
|
||||
"forgotPassword":
|
||||
MessageLookupByLibrary.simpleMessage("Olvidé mi contraseña"),
|
||||
"foundFaces": MessageLookupByLibrary.simpleMessage("Found faces"),
|
||||
"freeStorageClaimed": MessageLookupByLibrary.simpleMessage(
|
||||
"Almacenamiento gratuito reclamado"),
|
||||
"freeStorageOnReferralSuccess": m24,
|
||||
|
@ -690,6 +699,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
"La clave de recuperación introducida es incorrecta"),
|
||||
"incorrectRecoveryKeyTitle": MessageLookupByLibrary.simpleMessage(
|
||||
"Clave de recuperación incorrecta"),
|
||||
"indexingIsPaused": MessageLookupByLibrary.simpleMessage(
|
||||
"Indexing is paused, will automatically resume when device is ready"),
|
||||
"insecureDevice":
|
||||
MessageLookupByLibrary.simpleMessage("Dispositivo inseguro"),
|
||||
"installManually":
|
||||
|
@ -997,6 +1008,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
"removeParticipant":
|
||||
MessageLookupByLibrary.simpleMessage("Quitar participante"),
|
||||
"removeParticipantBody": m43,
|
||||
"removePersonLabel":
|
||||
MessageLookupByLibrary.simpleMessage("Remove person label"),
|
||||
"removePublicLink":
|
||||
MessageLookupByLibrary.simpleMessage("Quitar enlace público"),
|
||||
"removeShareItemsWarning": MessageLookupByLibrary.simpleMessage(
|
||||
|
|
13
mobile/lib/generated/intl/messages_fr.dart
generated
|
@ -425,6 +425,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
MessageLookupByLibrary.simpleMessage("Grouper par durée"),
|
||||
"clubByFileName":
|
||||
MessageLookupByLibrary.simpleMessage("Grouper par nom de fichier"),
|
||||
"clusteringProgress":
|
||||
MessageLookupByLibrary.simpleMessage("Clustering progress"),
|
||||
"codeAppliedPageTitle":
|
||||
MessageLookupByLibrary.simpleMessage("Code appliqué"),
|
||||
"codeCopiedToClipboard": MessageLookupByLibrary.simpleMessage(
|
||||
|
@ -665,6 +667,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
MessageLookupByLibrary.simpleMessage("Saisissez le mot de passe"),
|
||||
"enterPasswordToEncrypt": MessageLookupByLibrary.simpleMessage(
|
||||
"Entrez un mot de passe que nous pouvons utiliser pour chiffrer vos données"),
|
||||
"enterPersonName":
|
||||
MessageLookupByLibrary.simpleMessage("Enter person name"),
|
||||
"enterReferralCode": MessageLookupByLibrary.simpleMessage(
|
||||
"Entrez le code de parrainage"),
|
||||
"enterThe6digitCodeFromnyourAuthenticatorApp":
|
||||
|
@ -688,6 +692,10 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
"exportLogs": MessageLookupByLibrary.simpleMessage("Exporter les logs"),
|
||||
"exportYourData":
|
||||
MessageLookupByLibrary.simpleMessage("Exportez vos données"),
|
||||
"faceRecognition":
|
||||
MessageLookupByLibrary.simpleMessage("Face recognition"),
|
||||
"faceRecognitionIndexingDescription": MessageLookupByLibrary.simpleMessage(
|
||||
"Please note that this will result in a higher bandwidth and battery usage until all items are indexed."),
|
||||
"faces": MessageLookupByLibrary.simpleMessage("Visages"),
|
||||
"failedToApplyCode": MessageLookupByLibrary.simpleMessage(
|
||||
"Impossible d\'appliquer le code"),
|
||||
|
@ -732,6 +740,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
MessageLookupByLibrary.simpleMessage("pour vos souvenirs"),
|
||||
"forgotPassword":
|
||||
MessageLookupByLibrary.simpleMessage("Mot de passe oublié"),
|
||||
"foundFaces": MessageLookupByLibrary.simpleMessage("Found faces"),
|
||||
"freeStorageClaimed":
|
||||
MessageLookupByLibrary.simpleMessage("Stockage gratuit réclamé"),
|
||||
"freeStorageOnReferralSuccess": m24,
|
||||
|
@ -795,6 +804,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
"La clé de secours que vous avez entrée est incorrecte"),
|
||||
"incorrectRecoveryKeyTitle":
|
||||
MessageLookupByLibrary.simpleMessage("Clé de secours non valide"),
|
||||
"indexingIsPaused": MessageLookupByLibrary.simpleMessage(
|
||||
"Indexing is paused, will automatically resume when device is ready"),
|
||||
"insecureDevice":
|
||||
MessageLookupByLibrary.simpleMessage("Appareil non sécurisé"),
|
||||
"installManually":
|
||||
|
@ -1129,6 +1140,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
"removeParticipant":
|
||||
MessageLookupByLibrary.simpleMessage("Supprimer le participant"),
|
||||
"removeParticipantBody": m43,
|
||||
"removePersonLabel":
|
||||
MessageLookupByLibrary.simpleMessage("Remove person label"),
|
||||
"removePublicLink":
|
||||
MessageLookupByLibrary.simpleMessage("Supprimer le lien public"),
|
||||
"removeShareItemsWarning": MessageLookupByLibrary.simpleMessage(
|
||||
|
|
13
mobile/lib/generated/intl/messages_it.dart
generated
|
@ -411,6 +411,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
MessageLookupByLibrary.simpleMessage("Club per tempo di cattura"),
|
||||
"clubByFileName":
|
||||
MessageLookupByLibrary.simpleMessage("Unisci per nome file"),
|
||||
"clusteringProgress":
|
||||
MessageLookupByLibrary.simpleMessage("Clustering progress"),
|
||||
"codeAppliedPageTitle":
|
||||
MessageLookupByLibrary.simpleMessage("Codice applicato"),
|
||||
"codeCopiedToClipboard": MessageLookupByLibrary.simpleMessage(
|
||||
|
@ -644,6 +646,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
MessageLookupByLibrary.simpleMessage("Inserisci password"),
|
||||
"enterPasswordToEncrypt": MessageLookupByLibrary.simpleMessage(
|
||||
"Inserisci una password per criptare i tuoi dati"),
|
||||
"enterPersonName":
|
||||
MessageLookupByLibrary.simpleMessage("Enter person name"),
|
||||
"enterReferralCode": MessageLookupByLibrary.simpleMessage(
|
||||
"Inserisci il codice di invito"),
|
||||
"enterThe6digitCodeFromnyourAuthenticatorApp":
|
||||
|
@ -665,6 +669,10 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
"Questo link è scaduto. Si prega di selezionare un nuovo orario di scadenza o disabilitare la scadenza del link."),
|
||||
"exportLogs": MessageLookupByLibrary.simpleMessage("Esporta log"),
|
||||
"exportYourData": MessageLookupByLibrary.simpleMessage("Esporta dati"),
|
||||
"faceRecognition":
|
||||
MessageLookupByLibrary.simpleMessage("Face recognition"),
|
||||
"faceRecognitionIndexingDescription": MessageLookupByLibrary.simpleMessage(
|
||||
"Please note that this will result in a higher bandwidth and battery usage until all items are indexed."),
|
||||
"failedToApplyCode": MessageLookupByLibrary.simpleMessage(
|
||||
"Impossibile applicare il codice"),
|
||||
"failedToCancel":
|
||||
|
@ -704,6 +712,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
MessageLookupByLibrary.simpleMessage("per i tuoi ricordi"),
|
||||
"forgotPassword":
|
||||
MessageLookupByLibrary.simpleMessage("Password dimenticata"),
|
||||
"foundFaces": MessageLookupByLibrary.simpleMessage("Found faces"),
|
||||
"freeStorageClaimed":
|
||||
MessageLookupByLibrary.simpleMessage("Spazio gratuito richiesto"),
|
||||
"freeStorageOnReferralSuccess": m24,
|
||||
|
@ -764,6 +773,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
"Il codice che hai inserito non è corretto"),
|
||||
"incorrectRecoveryKeyTitle":
|
||||
MessageLookupByLibrary.simpleMessage("Chiave di recupero errata"),
|
||||
"indexingIsPaused": MessageLookupByLibrary.simpleMessage(
|
||||
"Indexing is paused, will automatically resume when device is ready"),
|
||||
"insecureDevice":
|
||||
MessageLookupByLibrary.simpleMessage("Dispositivo non sicuro"),
|
||||
"installManually":
|
||||
|
@ -1090,6 +1101,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
"removeParticipant":
|
||||
MessageLookupByLibrary.simpleMessage("Rimuovi partecipante"),
|
||||
"removeParticipantBody": m43,
|
||||
"removePersonLabel":
|
||||
MessageLookupByLibrary.simpleMessage("Remove person label"),
|
||||
"removePublicLink":
|
||||
MessageLookupByLibrary.simpleMessage("Rimuovi link pubblico"),
|
||||
"removeShareItemsWarning": MessageLookupByLibrary.simpleMessage(
|
||||
|
|
13
mobile/lib/generated/intl/messages_ko.dart
generated
|
@ -34,6 +34,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
"addViewers": m1,
|
||||
"changeLocationOfSelectedItems": MessageLookupByLibrary.simpleMessage(
|
||||
"Change location of selected items?"),
|
||||
"clusteringProgress":
|
||||
MessageLookupByLibrary.simpleMessage("Clustering progress"),
|
||||
"contacts": MessageLookupByLibrary.simpleMessage("Contacts"),
|
||||
"createCollaborativeLink":
|
||||
MessageLookupByLibrary.simpleMessage("Create collaborative link"),
|
||||
|
@ -44,7 +46,16 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
"editsToLocationWillOnlyBeSeenWithinEnte":
|
||||
MessageLookupByLibrary.simpleMessage(
|
||||
"Edits to location will only be seen within Ente"),
|
||||
"enterPersonName":
|
||||
MessageLookupByLibrary.simpleMessage("Enter person name"),
|
||||
"faceRecognition":
|
||||
MessageLookupByLibrary.simpleMessage("Face recognition"),
|
||||
"faceRecognitionIndexingDescription": MessageLookupByLibrary.simpleMessage(
|
||||
"Please note that this will result in a higher bandwidth and battery usage until all items are indexed."),
|
||||
"fileTypes": MessageLookupByLibrary.simpleMessage("File types"),
|
||||
"foundFaces": MessageLookupByLibrary.simpleMessage("Found faces"),
|
||||
"indexingIsPaused": MessageLookupByLibrary.simpleMessage(
|
||||
"Indexing is paused, will automatically resume when device is ready"),
|
||||
"joinDiscord": MessageLookupByLibrary.simpleMessage("Join Discord"),
|
||||
"locations": MessageLookupByLibrary.simpleMessage("Locations"),
|
||||
"longPressAnEmailToVerifyEndToEndEncryption":
|
||||
|
@ -55,6 +66,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
"Modify your query, or try searching for"),
|
||||
"moveToHiddenAlbum":
|
||||
MessageLookupByLibrary.simpleMessage("Move to hidden album"),
|
||||
"removePersonLabel":
|
||||
MessageLookupByLibrary.simpleMessage("Remove person label"),
|
||||
"search": MessageLookupByLibrary.simpleMessage("Search"),
|
||||
"selectALocation":
|
||||
MessageLookupByLibrary.simpleMessage("Select a location"),
|
||||
|
|
9
mobile/lib/generated/intl/messages_nl.dart
generated
|
@ -447,6 +447,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
MessageLookupByLibrary.simpleMessage("Samenvoegen op tijd"),
|
||||
"clubByFileName":
|
||||
MessageLookupByLibrary.simpleMessage("Samenvoegen op bestandsnaam"),
|
||||
"clusteringProgress":
|
||||
MessageLookupByLibrary.simpleMessage("Clustering progress"),
|
||||
"codeAppliedPageTitle":
|
||||
MessageLookupByLibrary.simpleMessage("Code toegepast"),
|
||||
"codeCopiedToClipboard": MessageLookupByLibrary.simpleMessage(
|
||||
|
@ -723,6 +725,10 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
MessageLookupByLibrary.simpleMessage("Logboek exporteren"),
|
||||
"exportYourData":
|
||||
MessageLookupByLibrary.simpleMessage("Exporteer je gegevens"),
|
||||
"faceRecognition":
|
||||
MessageLookupByLibrary.simpleMessage("Face recognition"),
|
||||
"faceRecognitionIndexingDescription": MessageLookupByLibrary.simpleMessage(
|
||||
"Please note that this will result in a higher bandwidth and battery usage until all items are indexed."),
|
||||
"faces": MessageLookupByLibrary.simpleMessage("Gezichten"),
|
||||
"failedToApplyCode":
|
||||
MessageLookupByLibrary.simpleMessage("Code toepassen mislukt"),
|
||||
|
@ -771,6 +777,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
MessageLookupByLibrary.simpleMessage("voor uw herinneringen"),
|
||||
"forgotPassword":
|
||||
MessageLookupByLibrary.simpleMessage("Wachtwoord vergeten"),
|
||||
"foundFaces": MessageLookupByLibrary.simpleMessage("Found faces"),
|
||||
"freeStorageClaimed":
|
||||
MessageLookupByLibrary.simpleMessage("Gratis opslag geclaimd"),
|
||||
"freeStorageOnReferralSuccess": m24,
|
||||
|
@ -833,6 +840,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
MessageLookupByLibrary.simpleMessage("Onjuiste herstelsleutel"),
|
||||
"indexedItems":
|
||||
MessageLookupByLibrary.simpleMessage("Geïndexeerde bestanden"),
|
||||
"indexingIsPaused": MessageLookupByLibrary.simpleMessage(
|
||||
"Indexing is paused, will automatically resume when device is ready"),
|
||||
"insecureDevice":
|
||||
MessageLookupByLibrary.simpleMessage("Onveilig apparaat"),
|
||||
"installManually":
|
||||
|
|
13
mobile/lib/generated/intl/messages_no.dart
generated
|
@ -39,6 +39,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
"cancel": MessageLookupByLibrary.simpleMessage("Avbryt"),
|
||||
"changeLocationOfSelectedItems": MessageLookupByLibrary.simpleMessage(
|
||||
"Change location of selected items?"),
|
||||
"clusteringProgress":
|
||||
MessageLookupByLibrary.simpleMessage("Clustering progress"),
|
||||
"confirmAccountDeletion":
|
||||
MessageLookupByLibrary.simpleMessage("Bekreft sletting av konto"),
|
||||
"confirmDeletePrompt": MessageLookupByLibrary.simpleMessage(
|
||||
|
@ -57,12 +59,21 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
MessageLookupByLibrary.simpleMessage(
|
||||
"Edits to location will only be seen within Ente"),
|
||||
"email": MessageLookupByLibrary.simpleMessage("E-post"),
|
||||
"enterPersonName":
|
||||
MessageLookupByLibrary.simpleMessage("Enter person name"),
|
||||
"enterValidEmail": MessageLookupByLibrary.simpleMessage(
|
||||
"Vennligst skriv inn en gyldig e-postadresse."),
|
||||
"enterYourEmailAddress": MessageLookupByLibrary.simpleMessage(
|
||||
"Skriv inn e-postadressen din"),
|
||||
"faceRecognition":
|
||||
MessageLookupByLibrary.simpleMessage("Face recognition"),
|
||||
"faceRecognitionIndexingDescription": MessageLookupByLibrary.simpleMessage(
|
||||
"Please note that this will result in a higher bandwidth and battery usage until all items are indexed."),
|
||||
"feedback": MessageLookupByLibrary.simpleMessage("Tilbakemelding"),
|
||||
"fileTypes": MessageLookupByLibrary.simpleMessage("File types"),
|
||||
"foundFaces": MessageLookupByLibrary.simpleMessage("Found faces"),
|
||||
"indexingIsPaused": MessageLookupByLibrary.simpleMessage(
|
||||
"Indexing is paused, will automatically resume when device is ready"),
|
||||
"invalidEmailAddress":
|
||||
MessageLookupByLibrary.simpleMessage("Ugyldig e-postadresse"),
|
||||
"joinDiscord": MessageLookupByLibrary.simpleMessage("Join Discord"),
|
||||
|
@ -77,6 +88,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
"Modify your query, or try searching for"),
|
||||
"moveToHiddenAlbum":
|
||||
MessageLookupByLibrary.simpleMessage("Move to hidden album"),
|
||||
"removePersonLabel":
|
||||
MessageLookupByLibrary.simpleMessage("Remove person label"),
|
||||
"search": MessageLookupByLibrary.simpleMessage("Search"),
|
||||
"selectALocation":
|
||||
MessageLookupByLibrary.simpleMessage("Select a location"),
|
||||
|
|
13
mobile/lib/generated/intl/messages_pl.dart
generated
|
@ -49,6 +49,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
MessageLookupByLibrary.simpleMessage("Zmień hasło"),
|
||||
"checkInboxAndSpamFolder": MessageLookupByLibrary.simpleMessage(
|
||||
"Sprawdź swoją skrzynkę odbiorczą (i spam), aby zakończyć weryfikację"),
|
||||
"clusteringProgress":
|
||||
MessageLookupByLibrary.simpleMessage("Clustering progress"),
|
||||
"codeCopiedToClipboard": MessageLookupByLibrary.simpleMessage(
|
||||
"Kod został skopiowany do schowka"),
|
||||
"confirm": MessageLookupByLibrary.simpleMessage("Potwierdź"),
|
||||
|
@ -101,6 +103,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
"Wprowadź nowe hasło, którego możemy użyć do zaszyfrowania Twoich danych"),
|
||||
"enterPasswordToEncrypt": MessageLookupByLibrary.simpleMessage(
|
||||
"Wprowadź hasło, którego możemy użyć do zaszyfrowania Twoich danych"),
|
||||
"enterPersonName":
|
||||
MessageLookupByLibrary.simpleMessage("Enter person name"),
|
||||
"enterValidEmail": MessageLookupByLibrary.simpleMessage(
|
||||
"Podaj poprawny adres e-mail."),
|
||||
"enterYourEmailAddress":
|
||||
|
@ -109,10 +113,15 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
MessageLookupByLibrary.simpleMessage("Wprowadź hasło"),
|
||||
"enterYourRecoveryKey": MessageLookupByLibrary.simpleMessage(
|
||||
"Wprowadź swój klucz odzyskiwania"),
|
||||
"faceRecognition":
|
||||
MessageLookupByLibrary.simpleMessage("Face recognition"),
|
||||
"faceRecognitionIndexingDescription": MessageLookupByLibrary.simpleMessage(
|
||||
"Please note that this will result in a higher bandwidth and battery usage until all items are indexed."),
|
||||
"feedback": MessageLookupByLibrary.simpleMessage("Informacja zwrotna"),
|
||||
"fileTypes": MessageLookupByLibrary.simpleMessage("File types"),
|
||||
"forgotPassword":
|
||||
MessageLookupByLibrary.simpleMessage("Nie pamiętam hasła"),
|
||||
"foundFaces": MessageLookupByLibrary.simpleMessage("Found faces"),
|
||||
"generatingEncryptionKeys": MessageLookupByLibrary.simpleMessage(
|
||||
"Generowanie kluczy szyfrujących..."),
|
||||
"howItWorks": MessageLookupByLibrary.simpleMessage("Jak to działa"),
|
||||
|
@ -122,6 +131,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
MessageLookupByLibrary.simpleMessage("Kod jest nieprawidłowy"),
|
||||
"incorrectRecoveryKeyTitle": MessageLookupByLibrary.simpleMessage(
|
||||
"Nieprawidłowy klucz odzyskiwania"),
|
||||
"indexingIsPaused": MessageLookupByLibrary.simpleMessage(
|
||||
"Indexing is paused, will automatically resume when device is ready"),
|
||||
"invalidEmailAddress":
|
||||
MessageLookupByLibrary.simpleMessage("Nieprawidłowy adres e-mail"),
|
||||
"joinDiscord": MessageLookupByLibrary.simpleMessage("Join Discord"),
|
||||
|
@ -166,6 +177,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
"Jeśli zapomnisz hasła, jedynym sposobem odzyskania danych jest ten klucz."),
|
||||
"recoverySuccessful":
|
||||
MessageLookupByLibrary.simpleMessage("Odzyskano pomyślnie!"),
|
||||
"removePersonLabel":
|
||||
MessageLookupByLibrary.simpleMessage("Remove person label"),
|
||||
"resendEmail":
|
||||
MessageLookupByLibrary.simpleMessage("Wyślij e-mail ponownie"),
|
||||
"resetPasswordTitle":
|
||||
|
|
22
mobile/lib/generated/intl/messages_pt.dart
generated
|
@ -98,7 +98,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
"${storageAmountInGB} GB cada vez que alguém se inscrever para um plano pago e aplica o seu código";
|
||||
|
||||
static String m25(freeAmount, storageUnit) =>
|
||||
"${freeAmount} ${storageUnit} grátis";
|
||||
"${freeAmount} ${storageUnit} livre";
|
||||
|
||||
static String m26(endDate) => "Teste gratuito acaba em ${endDate}";
|
||||
|
||||
|
@ -225,6 +225,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
"Eu entendo que se eu perder minha senha, posso perder meus dados, já que meus dados são <underline>criptografados de ponta a ponta</underline>."),
|
||||
"activeSessions":
|
||||
MessageLookupByLibrary.simpleMessage("Sessões ativas"),
|
||||
"addAName": MessageLookupByLibrary.simpleMessage("Adicione um nome"),
|
||||
"addANewEmail":
|
||||
MessageLookupByLibrary.simpleMessage("Adicionar um novo email"),
|
||||
"addCollaborator":
|
||||
|
@ -445,6 +446,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
"Agrupar por tempo de captura"),
|
||||
"clubByFileName": MessageLookupByLibrary.simpleMessage(
|
||||
"Agrupar pelo nome de arquivo"),
|
||||
"clusteringProgress":
|
||||
MessageLookupByLibrary.simpleMessage("Progresso de agrupamento"),
|
||||
"codeAppliedPageTitle":
|
||||
MessageLookupByLibrary.simpleMessage("Código aplicado"),
|
||||
"codeCopiedToClipboard": MessageLookupByLibrary.simpleMessage(
|
||||
|
@ -690,6 +693,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
"enterPassword": MessageLookupByLibrary.simpleMessage("Digite a senha"),
|
||||
"enterPasswordToEncrypt": MessageLookupByLibrary.simpleMessage(
|
||||
"Insira a senha para criptografar seus dados"),
|
||||
"enterPersonName":
|
||||
MessageLookupByLibrary.simpleMessage("Inserir nome da pessoa"),
|
||||
"enterReferralCode": MessageLookupByLibrary.simpleMessage(
|
||||
"Insira o código de referência"),
|
||||
"enterThe6digitCodeFromnyourAuthenticatorApp":
|
||||
|
@ -714,6 +719,10 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
"exportLogs": MessageLookupByLibrary.simpleMessage("Exportar logs"),
|
||||
"exportYourData":
|
||||
MessageLookupByLibrary.simpleMessage("Exportar seus dados"),
|
||||
"faceRecognition":
|
||||
MessageLookupByLibrary.simpleMessage("Reconhecimento facial"),
|
||||
"faceRecognitionIndexingDescription": MessageLookupByLibrary.simpleMessage(
|
||||
"Por favor, note que isso resultará em uma largura de banda maior e uso de bateria até que todos os itens sejam indexados."),
|
||||
"faces": MessageLookupByLibrary.simpleMessage("Rostos"),
|
||||
"failedToApplyCode":
|
||||
MessageLookupByLibrary.simpleMessage("Falha ao aplicar o código"),
|
||||
|
@ -755,11 +764,15 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
MessageLookupByLibrary.simpleMessage("Arquivos excluídos"),
|
||||
"filesSavedToGallery":
|
||||
MessageLookupByLibrary.simpleMessage("Arquivos salvos na galeria"),
|
||||
"findPeopleByName": MessageLookupByLibrary.simpleMessage(
|
||||
"Encontre pessoas rapidamente por nome"),
|
||||
"flip": MessageLookupByLibrary.simpleMessage("Inverter"),
|
||||
"forYourMemories":
|
||||
MessageLookupByLibrary.simpleMessage("para suas memórias"),
|
||||
"forgotPassword":
|
||||
MessageLookupByLibrary.simpleMessage("Esqueceu sua senha"),
|
||||
"foundFaces":
|
||||
MessageLookupByLibrary.simpleMessage("Rostos encontrados"),
|
||||
"freeStorageClaimed": MessageLookupByLibrary.simpleMessage(
|
||||
"Armazenamento gratuito reivindicado"),
|
||||
"freeStorageOnReferralSuccess": m24,
|
||||
|
@ -823,6 +836,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
"incorrectRecoveryKeyTitle": MessageLookupByLibrary.simpleMessage(
|
||||
"Chave de recuperação incorreta"),
|
||||
"indexedItems": MessageLookupByLibrary.simpleMessage("Itens indexados"),
|
||||
"indexingIsPaused": MessageLookupByLibrary.simpleMessage(
|
||||
"Indexing is paused, will automatically resume when device is ready"),
|
||||
"insecureDevice":
|
||||
MessageLookupByLibrary.simpleMessage("Dispositivo não seguro"),
|
||||
"installManually":
|
||||
|
@ -1057,6 +1072,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
"pendingItems": MessageLookupByLibrary.simpleMessage("Itens pendentes"),
|
||||
"pendingSync":
|
||||
MessageLookupByLibrary.simpleMessage("Sincronização pendente"),
|
||||
"people": MessageLookupByLibrary.simpleMessage("Pessoas"),
|
||||
"peopleUsingYourCode":
|
||||
MessageLookupByLibrary.simpleMessage("Pessoas que usam seu código"),
|
||||
"permDeleteWarning": MessageLookupByLibrary.simpleMessage(
|
||||
|
@ -1190,6 +1206,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
"removeParticipant":
|
||||
MessageLookupByLibrary.simpleMessage("Remover participante"),
|
||||
"removeParticipantBody": m43,
|
||||
"removePersonLabel":
|
||||
MessageLookupByLibrary.simpleMessage("Remover etiqueta da pessoa"),
|
||||
"removePublicLink":
|
||||
MessageLookupByLibrary.simpleMessage("Remover link público"),
|
||||
"removeShareItemsWarning": MessageLookupByLibrary.simpleMessage(
|
||||
|
@ -1253,7 +1271,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
"searchDatesEmptySection": MessageLookupByLibrary.simpleMessage(
|
||||
"Pesquisar por data, mês ou ano"),
|
||||
"searchFaceEmptySection": MessageLookupByLibrary.simpleMessage(
|
||||
"Encontre todas as fotos de uma pessoa"),
|
||||
"Pessoas serão exibidas aqui uma vez que a indexação é feita"),
|
||||
"searchFileTypesAndNamesEmptySection":
|
||||
MessageLookupByLibrary.simpleMessage("Tipos de arquivo e nomes"),
|
||||
"searchHint1": MessageLookupByLibrary.simpleMessage(
|
||||
|
|
9
mobile/lib/generated/intl/messages_zh.dart
generated
|
@ -382,6 +382,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
"close": MessageLookupByLibrary.simpleMessage("关闭"),
|
||||
"clubByCaptureTime": MessageLookupByLibrary.simpleMessage("按拍摄时间分组"),
|
||||
"clubByFileName": MessageLookupByLibrary.simpleMessage("按文件名排序"),
|
||||
"clusteringProgress":
|
||||
MessageLookupByLibrary.simpleMessage("Clustering progress"),
|
||||
"codeAppliedPageTitle": MessageLookupByLibrary.simpleMessage("代码已应用"),
|
||||
"codeCopiedToClipboard":
|
||||
MessageLookupByLibrary.simpleMessage("代码已复制到剪贴板"),
|
||||
|
@ -592,6 +594,10 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
MessageLookupByLibrary.simpleMessage("此链接已过期。请选择新的过期时间或禁用链接有效期。"),
|
||||
"exportLogs": MessageLookupByLibrary.simpleMessage("导出日志"),
|
||||
"exportYourData": MessageLookupByLibrary.simpleMessage("导出您的数据"),
|
||||
"faceRecognition":
|
||||
MessageLookupByLibrary.simpleMessage("Face recognition"),
|
||||
"faceRecognitionIndexingDescription": MessageLookupByLibrary.simpleMessage(
|
||||
"Please note that this will result in a higher bandwidth and battery usage until all items are indexed."),
|
||||
"faces": MessageLookupByLibrary.simpleMessage("人脸"),
|
||||
"failedToApplyCode": MessageLookupByLibrary.simpleMessage("无法使用此代码"),
|
||||
"failedToCancel": MessageLookupByLibrary.simpleMessage("取消失败"),
|
||||
|
@ -626,6 +632,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
"flip": MessageLookupByLibrary.simpleMessage("上下翻转"),
|
||||
"forYourMemories": MessageLookupByLibrary.simpleMessage("为您的回忆"),
|
||||
"forgotPassword": MessageLookupByLibrary.simpleMessage("忘记密码"),
|
||||
"foundFaces": MessageLookupByLibrary.simpleMessage("Found faces"),
|
||||
"freeStorageClaimed": MessageLookupByLibrary.simpleMessage("已领取的免费存储"),
|
||||
"freeStorageOnReferralSuccess": m24,
|
||||
"freeStorageSpace": m25,
|
||||
|
@ -679,6 +686,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
"incorrectRecoveryKeyTitle":
|
||||
MessageLookupByLibrary.simpleMessage("不正确的恢复密钥"),
|
||||
"indexedItems": MessageLookupByLibrary.simpleMessage("已索引项目"),
|
||||
"indexingIsPaused": MessageLookupByLibrary.simpleMessage(
|
||||
"Indexing is paused, will automatically resume when device is ready"),
|
||||
"insecureDevice": MessageLookupByLibrary.simpleMessage("设备不安全"),
|
||||
"installManually": MessageLookupByLibrary.simpleMessage("手动安装"),
|
||||
"invalidEmailAddress":
|
||||
|
|
148
mobile/lib/generated/l10n.dart
generated
|
@ -4034,10 +4034,10 @@ class S {
|
|||
);
|
||||
}
|
||||
|
||||
/// `Free trial valid till {endDate}.\nYou can purchase a paid plan afterwards.`
|
||||
/// `Free trial valid till {endDate}.\nYou can choose a paid plan afterwards.`
|
||||
String playStoreFreeTrialValidTill(Object endDate) {
|
||||
return Intl.message(
|
||||
'Free trial valid till $endDate.\nYou can purchase a paid plan afterwards.',
|
||||
'Free trial valid till $endDate.\nYou can choose a paid plan afterwards.',
|
||||
name: 'playStoreFreeTrialValidTill',
|
||||
desc: '',
|
||||
args: [endDate],
|
||||
|
@ -6969,10 +6969,10 @@ class S {
|
|||
);
|
||||
}
|
||||
|
||||
/// `Find all photos of a person`
|
||||
/// `Persons will be shown here once indexing is done`
|
||||
String get searchFaceEmptySection {
|
||||
return Intl.message(
|
||||
'Find all photos of a person',
|
||||
'Persons will be shown here once indexing is done',
|
||||
name: 'searchFaceEmptySection',
|
||||
desc: '',
|
||||
args: [],
|
||||
|
@ -8168,6 +8168,16 @@ class S {
|
|||
);
|
||||
}
|
||||
|
||||
/// `People`
|
||||
String get people {
|
||||
return Intl.message(
|
||||
'People',
|
||||
name: 'people',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Contents`
|
||||
String get contents {
|
||||
return Intl.message(
|
||||
|
@ -8388,26 +8398,6 @@ class S {
|
|||
);
|
||||
}
|
||||
|
||||
/// `Auto pair`
|
||||
String get autoPair {
|
||||
return Intl.message(
|
||||
'Auto pair',
|
||||
name: 'autoPair',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Pair with PIN`
|
||||
String get pairWithPin {
|
||||
return Intl.message(
|
||||
'Pair with PIN',
|
||||
name: 'pairWithPin',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Device not found`
|
||||
String get deviceNotFound {
|
||||
return Intl.message(
|
||||
|
@ -8468,6 +8458,26 @@ class S {
|
|||
);
|
||||
}
|
||||
|
||||
/// `Add a name`
|
||||
String get addAName {
|
||||
return Intl.message(
|
||||
'Add a name',
|
||||
name: 'addAName',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Find people quickly by name`
|
||||
String get findPeopleByName {
|
||||
return Intl.message(
|
||||
'Find people quickly by name',
|
||||
name: 'findPeopleByName',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `{count, plural, zero {Add viewer} one {Add viewer} other {Add viewers}}`
|
||||
String addViewers(num count) {
|
||||
return Intl.plural(
|
||||
|
@ -8594,6 +8604,26 @@ class S {
|
|||
);
|
||||
}
|
||||
|
||||
/// `Enter person name`
|
||||
String get enterPersonName {
|
||||
return Intl.message(
|
||||
'Enter person name',
|
||||
name: 'enterPersonName',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Remove person label`
|
||||
String get removePersonLabel {
|
||||
return Intl.message(
|
||||
'Remove person label',
|
||||
name: 'removePersonLabel',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Auto pair works only with devices that support Chromecast.`
|
||||
String get autoPairDesc {
|
||||
return Intl.message(
|
||||
|
@ -8703,6 +8733,76 @@ class S {
|
|||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Auto pair`
|
||||
String get autoPair {
|
||||
return Intl.message(
|
||||
'Auto pair',
|
||||
name: 'autoPair',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Pair with PIN`
|
||||
String get pairWithPin {
|
||||
return Intl.message(
|
||||
'Pair with PIN',
|
||||
name: 'pairWithPin',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Face recognition`
|
||||
String get faceRecognition {
|
||||
return Intl.message(
|
||||
'Face recognition',
|
||||
name: 'faceRecognition',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Please note that this will result in a higher bandwidth and battery usage until all items are indexed.`
|
||||
String get faceRecognitionIndexingDescription {
|
||||
return Intl.message(
|
||||
'Please note that this will result in a higher bandwidth and battery usage until all items are indexed.',
|
||||
name: 'faceRecognitionIndexingDescription',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Found faces`
|
||||
String get foundFaces {
|
||||
return Intl.message(
|
||||
'Found faces',
|
||||
name: 'foundFaces',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Clustering progress`
|
||||
String get clusteringProgress {
|
||||
return Intl.message(
|
||||
'Clustering progress',
|
||||
name: 'clusteringProgress',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Indexing is paused. It will automatically resume when device is ready.`
|
||||
String get indexingIsPaused {
|
||||
return Intl.message(
|
||||
'Indexing is paused. It will automatically resume when device is ready.',
|
||||
name: 'indexingIsPaused',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class AppLocalizationDelegate extends LocalizationsDelegate<S> {
|
||||
|
|
111
mobile/lib/generated/protos/ente/common/box.pb.dart
Normal file
|
@ -0,0 +1,111 @@
|
|||
//
|
||||
// Generated code. Do not modify.
|
||||
// source: ente/common/box.proto
|
||||
//
|
||||
// @dart = 2.12
|
||||
|
||||
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
|
||||
// ignore_for_file: constant_identifier_names, library_prefixes
|
||||
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
|
||||
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import
|
||||
|
||||
import 'dart:core' as $core;
|
||||
|
||||
import 'package:protobuf/protobuf.dart' as $pb;
|
||||
|
||||
/// CenterBox is a box where x,y is the center of the box
|
||||
class CenterBox extends $pb.GeneratedMessage {
|
||||
factory CenterBox({
|
||||
$core.double? x,
|
||||
$core.double? y,
|
||||
$core.double? height,
|
||||
$core.double? width,
|
||||
}) {
|
||||
final $result = create();
|
||||
if (x != null) {
|
||||
$result.x = x;
|
||||
}
|
||||
if (y != null) {
|
||||
$result.y = y;
|
||||
}
|
||||
if (height != null) {
|
||||
$result.height = height;
|
||||
}
|
||||
if (width != null) {
|
||||
$result.width = width;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
CenterBox._() : super();
|
||||
factory CenterBox.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
|
||||
factory CenterBox.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
|
||||
|
||||
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'CenterBox', package: const $pb.PackageName(_omitMessageNames ? '' : 'ente.common'), createEmptyInstance: create)
|
||||
..a<$core.double>(1, _omitFieldNames ? '' : 'x', $pb.PbFieldType.OF)
|
||||
..a<$core.double>(2, _omitFieldNames ? '' : 'y', $pb.PbFieldType.OF)
|
||||
..a<$core.double>(3, _omitFieldNames ? '' : 'height', $pb.PbFieldType.OF)
|
||||
..a<$core.double>(4, _omitFieldNames ? '' : 'width', $pb.PbFieldType.OF)
|
||||
..hasRequiredFields = false
|
||||
;
|
||||
|
||||
@$core.Deprecated(
|
||||
'Using this can add significant overhead to your binary. '
|
||||
'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
|
||||
'Will be removed in next major version')
|
||||
CenterBox clone() => CenterBox()..mergeFromMessage(this);
|
||||
@$core.Deprecated(
|
||||
'Using this can add significant overhead to your binary. '
|
||||
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
|
||||
'Will be removed in next major version')
|
||||
CenterBox copyWith(void Function(CenterBox) updates) => super.copyWith((message) => updates(message as CenterBox)) as CenterBox;
|
||||
|
||||
$pb.BuilderInfo get info_ => _i;
|
||||
|
||||
@$core.pragma('dart2js:noInline')
|
||||
static CenterBox create() => CenterBox._();
|
||||
CenterBox createEmptyInstance() => create();
|
||||
static $pb.PbList<CenterBox> createRepeated() => $pb.PbList<CenterBox>();
|
||||
@$core.pragma('dart2js:noInline')
|
||||
static CenterBox getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<CenterBox>(create);
|
||||
static CenterBox? _defaultInstance;
|
||||
|
||||
@$pb.TagNumber(1)
|
||||
$core.double get x => $_getN(0);
|
||||
@$pb.TagNumber(1)
|
||||
set x($core.double v) { $_setFloat(0, v); }
|
||||
@$pb.TagNumber(1)
|
||||
$core.bool hasX() => $_has(0);
|
||||
@$pb.TagNumber(1)
|
||||
void clearX() => clearField(1);
|
||||
|
||||
@$pb.TagNumber(2)
|
||||
$core.double get y => $_getN(1);
|
||||
@$pb.TagNumber(2)
|
||||
set y($core.double v) { $_setFloat(1, v); }
|
||||
@$pb.TagNumber(2)
|
||||
$core.bool hasY() => $_has(1);
|
||||
@$pb.TagNumber(2)
|
||||
void clearY() => clearField(2);
|
||||
|
||||
@$pb.TagNumber(3)
|
||||
$core.double get height => $_getN(2);
|
||||
@$pb.TagNumber(3)
|
||||
set height($core.double v) { $_setFloat(2, v); }
|
||||
@$pb.TagNumber(3)
|
||||
$core.bool hasHeight() => $_has(2);
|
||||
@$pb.TagNumber(3)
|
||||
void clearHeight() => clearField(3);
|
||||
|
||||
@$pb.TagNumber(4)
|
||||
$core.double get width => $_getN(3);
|
||||
@$pb.TagNumber(4)
|
||||
set width($core.double v) { $_setFloat(3, v); }
|
||||
@$pb.TagNumber(4)
|
||||
$core.bool hasWidth() => $_has(3);
|
||||
@$pb.TagNumber(4)
|
||||
void clearWidth() => clearField(4);
|
||||
}
|
||||
|
||||
|
||||
const _omitFieldNames = $core.bool.fromEnvironment('protobuf.omit_field_names');
|
||||
const _omitMessageNames = $core.bool.fromEnvironment('protobuf.omit_message_names');
|
11
mobile/lib/generated/protos/ente/common/box.pbenum.dart
Normal file
|
@ -0,0 +1,11 @@
|
|||
//
|
||||
// Generated code. Do not modify.
|
||||
// source: ente/common/box.proto
|
||||
//
|
||||
// @dart = 2.12
|
||||
|
||||
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
|
||||
// ignore_for_file: constant_identifier_names, library_prefixes
|
||||
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
|
||||
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import
|
||||
|
38
mobile/lib/generated/protos/ente/common/box.pbjson.dart
Normal file
|
@ -0,0 +1,38 @@
|
|||
//
|
||||
// Generated code. Do not modify.
|
||||
// source: ente/common/box.proto
|
||||
//
|
||||
// @dart = 2.12
|
||||
|
||||
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
|
||||
// ignore_for_file: constant_identifier_names, library_prefixes
|
||||
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
|
||||
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import
|
||||
|
||||
import 'dart:convert' as $convert;
|
||||
import 'dart:core' as $core;
|
||||
import 'dart:typed_data' as $typed_data;
|
||||
|
||||
@$core.Deprecated('Use centerBoxDescriptor instead')
|
||||
const CenterBox$json = {
|
||||
'1': 'CenterBox',
|
||||
'2': [
|
||||
{'1': 'x', '3': 1, '4': 1, '5': 2, '9': 0, '10': 'x', '17': true},
|
||||
{'1': 'y', '3': 2, '4': 1, '5': 2, '9': 1, '10': 'y', '17': true},
|
||||
{'1': 'height', '3': 3, '4': 1, '5': 2, '9': 2, '10': 'height', '17': true},
|
||||
{'1': 'width', '3': 4, '4': 1, '5': 2, '9': 3, '10': 'width', '17': true},
|
||||
],
|
||||
'8': [
|
||||
{'1': '_x'},
|
||||
{'1': '_y'},
|
||||
{'1': '_height'},
|
||||
{'1': '_width'},
|
||||
],
|
||||
};
|
||||
|
||||
/// Descriptor for `CenterBox`. Decode as a `google.protobuf.DescriptorProto`.
|
||||
final $typed_data.Uint8List centerBoxDescriptor = $convert.base64Decode(
|
||||
'CglDZW50ZXJCb3gSEQoBeBgBIAEoAkgAUgF4iAEBEhEKAXkYAiABKAJIAVIBeYgBARIbCgZoZW'
|
||||
'lnaHQYAyABKAJIAlIGaGVpZ2h0iAEBEhkKBXdpZHRoGAQgASgCSANSBXdpZHRoiAEBQgQKAl94'
|
||||
'QgQKAl95QgkKB19oZWlnaHRCCAoGX3dpZHRo');
|
||||
|
14
mobile/lib/generated/protos/ente/common/box.pbserver.dart
Normal file
|
@ -0,0 +1,14 @@
|
|||
//
|
||||
// Generated code. Do not modify.
|
||||
// source: ente/common/box.proto
|
||||
//
|
||||
// @dart = 2.12
|
||||
|
||||
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
|
||||
// ignore_for_file: constant_identifier_names
|
||||
// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes
|
||||
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
|
||||
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import
|
||||
|
||||
export 'box.pb.dart';
|
||||
|
83
mobile/lib/generated/protos/ente/common/point.pb.dart
Normal file
|
@ -0,0 +1,83 @@
|
|||
//
|
||||
// Generated code. Do not modify.
|
||||
// source: ente/common/point.proto
|
||||
//
|
||||
// @dart = 2.12
|
||||
|
||||
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
|
||||
// ignore_for_file: constant_identifier_names, library_prefixes
|
||||
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
|
||||
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import
|
||||
|
||||
import 'dart:core' as $core;
|
||||
|
||||
import 'package:protobuf/protobuf.dart' as $pb;
|
||||
|
||||
/// EPoint is a point in 2D space
|
||||
class EPoint extends $pb.GeneratedMessage {
|
||||
factory EPoint({
|
||||
$core.double? x,
|
||||
$core.double? y,
|
||||
}) {
|
||||
final $result = create();
|
||||
if (x != null) {
|
||||
$result.x = x;
|
||||
}
|
||||
if (y != null) {
|
||||
$result.y = y;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
EPoint._() : super();
|
||||
factory EPoint.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
|
||||
factory EPoint.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
|
||||
|
||||
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'EPoint', package: const $pb.PackageName(_omitMessageNames ? '' : 'ente.common'), createEmptyInstance: create)
|
||||
..a<$core.double>(1, _omitFieldNames ? '' : 'x', $pb.PbFieldType.OF)
|
||||
..a<$core.double>(2, _omitFieldNames ? '' : 'y', $pb.PbFieldType.OF)
|
||||
..hasRequiredFields = false
|
||||
;
|
||||
|
||||
@$core.Deprecated(
|
||||
'Using this can add significant overhead to your binary. '
|
||||
'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
|
||||
'Will be removed in next major version')
|
||||
EPoint clone() => EPoint()..mergeFromMessage(this);
|
||||
@$core.Deprecated(
|
||||
'Using this can add significant overhead to your binary. '
|
||||
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
|
||||
'Will be removed in next major version')
|
||||
EPoint copyWith(void Function(EPoint) updates) => super.copyWith((message) => updates(message as EPoint)) as EPoint;
|
||||
|
||||
$pb.BuilderInfo get info_ => _i;
|
||||
|
||||
@$core.pragma('dart2js:noInline')
|
||||
static EPoint create() => EPoint._();
|
||||
EPoint createEmptyInstance() => create();
|
||||
static $pb.PbList<EPoint> createRepeated() => $pb.PbList<EPoint>();
|
||||
@$core.pragma('dart2js:noInline')
|
||||
static EPoint getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<EPoint>(create);
|
||||
static EPoint? _defaultInstance;
|
||||
|
||||
@$pb.TagNumber(1)
|
||||
$core.double get x => $_getN(0);
|
||||
@$pb.TagNumber(1)
|
||||
set x($core.double v) { $_setFloat(0, v); }
|
||||
@$pb.TagNumber(1)
|
||||
$core.bool hasX() => $_has(0);
|
||||
@$pb.TagNumber(1)
|
||||
void clearX() => clearField(1);
|
||||
|
||||
@$pb.TagNumber(2)
|
||||
$core.double get y => $_getN(1);
|
||||
@$pb.TagNumber(2)
|
||||
set y($core.double v) { $_setFloat(1, v); }
|
||||
@$pb.TagNumber(2)
|
||||
$core.bool hasY() => $_has(1);
|
||||
@$pb.TagNumber(2)
|
||||
void clearY() => clearField(2);
|
||||
}
|
||||
|
||||
|
||||
const _omitFieldNames = $core.bool.fromEnvironment('protobuf.omit_field_names');
|
||||
const _omitMessageNames = $core.bool.fromEnvironment('protobuf.omit_message_names');
|
11
mobile/lib/generated/protos/ente/common/point.pbenum.dart
Normal file
|
@ -0,0 +1,11 @@
|
|||
//
|
||||
// Generated code. Do not modify.
|
||||
// source: ente/common/point.proto
|
||||
//
|
||||
// @dart = 2.12
|
||||
|
||||
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
|
||||
// ignore_for_file: constant_identifier_names, library_prefixes
|
||||
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
|
||||
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import
|
||||
|
33
mobile/lib/generated/protos/ente/common/point.pbjson.dart
Normal file
|
@ -0,0 +1,33 @@
|
|||
//
|
||||
// Generated code. Do not modify.
|
||||
// source: ente/common/point.proto
|
||||
//
|
||||
// @dart = 2.12
|
||||
|
||||
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
|
||||
// ignore_for_file: constant_identifier_names, library_prefixes
|
||||
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
|
||||
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import
|
||||
|
||||
import 'dart:convert' as $convert;
|
||||
import 'dart:core' as $core;
|
||||
import 'dart:typed_data' as $typed_data;
|
||||
|
||||
@$core.Deprecated('Use ePointDescriptor instead')
|
||||
const EPoint$json = {
|
||||
'1': 'EPoint',
|
||||
'2': [
|
||||
{'1': 'x', '3': 1, '4': 1, '5': 2, '9': 0, '10': 'x', '17': true},
|
||||
{'1': 'y', '3': 2, '4': 1, '5': 2, '9': 1, '10': 'y', '17': true},
|
||||
],
|
||||
'8': [
|
||||
{'1': '_x'},
|
||||
{'1': '_y'},
|
||||
],
|
||||
};
|
||||
|
||||
/// Descriptor for `EPoint`. Decode as a `google.protobuf.DescriptorProto`.
|
||||
final $typed_data.Uint8List ePointDescriptor = $convert.base64Decode(
|
||||
'CgZFUG9pbnQSEQoBeBgBIAEoAkgAUgF4iAEBEhEKAXkYAiABKAJIAVIBeYgBAUIECgJfeEIECg'
|
||||
'JfeQ==');
|
||||
|
14
mobile/lib/generated/protos/ente/common/point.pbserver.dart
Normal file
|
@ -0,0 +1,14 @@
|
|||
//
|
||||
// Generated code. Do not modify.
|
||||
// source: ente/common/point.proto
|
||||
//
|
||||
// @dart = 2.12
|
||||
|
||||
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
|
||||
// ignore_for_file: constant_identifier_names
|
||||
// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes
|
||||
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
|
||||
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import
|
||||
|
||||
export 'point.pb.dart';
|
||||
|
64
mobile/lib/generated/protos/ente/common/vector.pb.dart
Normal file
|
@ -0,0 +1,64 @@
|
|||
//
|
||||
// Generated code. Do not modify.
|
||||
// source: ente/common/vector.proto
|
||||
//
|
||||
// @dart = 2.12
|
||||
|
||||
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
|
||||
// ignore_for_file: constant_identifier_names, library_prefixes
|
||||
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
|
||||
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import
|
||||
|
||||
import 'dart:core' as $core;
|
||||
|
||||
import 'package:protobuf/protobuf.dart' as $pb;
|
||||
|
||||
/// Vector is generic message for dealing with lists of doubles
|
||||
/// It should ideally be used independently and not as a submessage
|
||||
class EVector extends $pb.GeneratedMessage {
|
||||
factory EVector({
|
||||
$core.Iterable<$core.double>? values,
|
||||
}) {
|
||||
final $result = create();
|
||||
if (values != null) {
|
||||
$result.values.addAll(values);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
EVector._() : super();
|
||||
factory EVector.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
|
||||
factory EVector.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
|
||||
|
||||
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'EVector', package: const $pb.PackageName(_omitMessageNames ? '' : 'ente.common'), createEmptyInstance: create)
|
||||
..p<$core.double>(1, _omitFieldNames ? '' : 'values', $pb.PbFieldType.KD)
|
||||
..hasRequiredFields = false
|
||||
;
|
||||
|
||||
@$core.Deprecated(
|
||||
'Using this can add significant overhead to your binary. '
|
||||
'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
|
||||
'Will be removed in next major version')
|
||||
EVector clone() => EVector()..mergeFromMessage(this);
|
||||
@$core.Deprecated(
|
||||
'Using this can add significant overhead to your binary. '
|
||||
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
|
||||
'Will be removed in next major version')
|
||||
EVector copyWith(void Function(EVector) updates) => super.copyWith((message) => updates(message as EVector)) as EVector;
|
||||
|
||||
$pb.BuilderInfo get info_ => _i;
|
||||
|
||||
@$core.pragma('dart2js:noInline')
|
||||
static EVector create() => EVector._();
|
||||
EVector createEmptyInstance() => create();
|
||||
static $pb.PbList<EVector> createRepeated() => $pb.PbList<EVector>();
|
||||
@$core.pragma('dart2js:noInline')
|
||||
static EVector getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<EVector>(create);
|
||||
static EVector? _defaultInstance;
|
||||
|
||||
@$pb.TagNumber(1)
|
||||
$core.List<$core.double> get values => $_getList(0);
|
||||
}
|
||||
|
||||
|
||||
const _omitFieldNames = $core.bool.fromEnvironment('protobuf.omit_field_names');
|
||||
const _omitMessageNames = $core.bool.fromEnvironment('protobuf.omit_message_names');
|
11
mobile/lib/generated/protos/ente/common/vector.pbenum.dart
Normal file
|
@ -0,0 +1,11 @@
|
|||
//
|
||||
// Generated code. Do not modify.
|
||||
// source: ente/common/vector.proto
|
||||
//
|
||||
// @dart = 2.12
|
||||
|
||||
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
|
||||
// ignore_for_file: constant_identifier_names, library_prefixes
|
||||
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
|
||||
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import
|
||||
|
27
mobile/lib/generated/protos/ente/common/vector.pbjson.dart
Normal file
|
@ -0,0 +1,27 @@
|
|||
//
|
||||
// Generated code. Do not modify.
|
||||
// source: ente/common/vector.proto
|
||||
//
|
||||
// @dart = 2.12
|
||||
|
||||
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
|
||||
// ignore_for_file: constant_identifier_names, library_prefixes
|
||||
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
|
||||
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import
|
||||
|
||||
import 'dart:convert' as $convert;
|
||||
import 'dart:core' as $core;
|
||||
import 'dart:typed_data' as $typed_data;
|
||||
|
||||
@$core.Deprecated('Use eVectorDescriptor instead')
|
||||
const EVector$json = {
|
||||
'1': 'EVector',
|
||||
'2': [
|
||||
{'1': 'values', '3': 1, '4': 3, '5': 1, '10': 'values'},
|
||||
],
|
||||
};
|
||||
|
||||
/// Descriptor for `EVector`. Decode as a `google.protobuf.DescriptorProto`.
|
||||
final $typed_data.Uint8List eVectorDescriptor = $convert.base64Decode(
|
||||
'CgdFVmVjdG9yEhYKBnZhbHVlcxgBIAMoAVIGdmFsdWVz');
|
||||
|
14
mobile/lib/generated/protos/ente/common/vector.pbserver.dart
Normal file
|
@ -0,0 +1,14 @@
|
|||
//
|
||||
// Generated code. Do not modify.
|
||||
// source: ente/common/vector.proto
|
||||
//
|
||||
// @dart = 2.12
|
||||
|
||||
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
|
||||
// ignore_for_file: constant_identifier_names
|
||||
// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes
|
||||
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
|
||||
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import
|
||||
|
||||
export 'vector.pb.dart';
|
||||
|
169
mobile/lib/generated/protos/ente/ml/face.pb.dart
Normal file
|
@ -0,0 +1,169 @@
|
|||
//
|
||||
// Generated code. Do not modify.
|
||||
// source: ente/ml/face.proto
|
||||
//
|
||||
// @dart = 2.12
|
||||
|
||||
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
|
||||
// ignore_for_file: constant_identifier_names, library_prefixes
|
||||
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
|
||||
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import
|
||||
|
||||
import 'dart:core' as $core;
|
||||
|
||||
import 'package:protobuf/protobuf.dart' as $pb;
|
||||
|
||||
import '../common/box.pb.dart' as $0;
|
||||
import '../common/point.pb.dart' as $1;
|
||||
|
||||
class Detection extends $pb.GeneratedMessage {
|
||||
factory Detection({
|
||||
$0.CenterBox? box,
|
||||
$1.EPoint? landmarks,
|
||||
}) {
|
||||
final $result = create();
|
||||
if (box != null) {
|
||||
$result.box = box;
|
||||
}
|
||||
if (landmarks != null) {
|
||||
$result.landmarks = landmarks;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
Detection._() : super();
|
||||
factory Detection.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
|
||||
factory Detection.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
|
||||
|
||||
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'Detection', package: const $pb.PackageName(_omitMessageNames ? '' : 'ente.ml'), createEmptyInstance: create)
|
||||
..aOM<$0.CenterBox>(1, _omitFieldNames ? '' : 'box', subBuilder: $0.CenterBox.create)
|
||||
..aOM<$1.EPoint>(2, _omitFieldNames ? '' : 'landmarks', subBuilder: $1.EPoint.create)
|
||||
..hasRequiredFields = false
|
||||
;
|
||||
|
||||
@$core.Deprecated(
|
||||
'Using this can add significant overhead to your binary. '
|
||||
'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
|
||||
'Will be removed in next major version')
|
||||
Detection clone() => Detection()..mergeFromMessage(this);
|
||||
@$core.Deprecated(
|
||||
'Using this can add significant overhead to your binary. '
|
||||
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
|
||||
'Will be removed in next major version')
|
||||
Detection copyWith(void Function(Detection) updates) => super.copyWith((message) => updates(message as Detection)) as Detection;
|
||||
|
||||
$pb.BuilderInfo get info_ => _i;
|
||||
|
||||
@$core.pragma('dart2js:noInline')
|
||||
static Detection create() => Detection._();
|
||||
Detection createEmptyInstance() => create();
|
||||
static $pb.PbList<Detection> createRepeated() => $pb.PbList<Detection>();
|
||||
@$core.pragma('dart2js:noInline')
|
||||
static Detection getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<Detection>(create);
|
||||
static Detection? _defaultInstance;
|
||||
|
||||
@$pb.TagNumber(1)
|
||||
$0.CenterBox get box => $_getN(0);
|
||||
@$pb.TagNumber(1)
|
||||
set box($0.CenterBox v) { setField(1, v); }
|
||||
@$pb.TagNumber(1)
|
||||
$core.bool hasBox() => $_has(0);
|
||||
@$pb.TagNumber(1)
|
||||
void clearBox() => clearField(1);
|
||||
@$pb.TagNumber(1)
|
||||
$0.CenterBox ensureBox() => $_ensure(0);
|
||||
|
||||
@$pb.TagNumber(2)
|
||||
$1.EPoint get landmarks => $_getN(1);
|
||||
@$pb.TagNumber(2)
|
||||
set landmarks($1.EPoint v) { setField(2, v); }
|
||||
@$pb.TagNumber(2)
|
||||
$core.bool hasLandmarks() => $_has(1);
|
||||
@$pb.TagNumber(2)
|
||||
void clearLandmarks() => clearField(2);
|
||||
@$pb.TagNumber(2)
|
||||
$1.EPoint ensureLandmarks() => $_ensure(1);
|
||||
}
|
||||
|
||||
class Face extends $pb.GeneratedMessage {
|
||||
factory Face({
|
||||
$core.String? id,
|
||||
Detection? detection,
|
||||
$core.double? confidence,
|
||||
}) {
|
||||
final $result = create();
|
||||
if (id != null) {
|
||||
$result.id = id;
|
||||
}
|
||||
if (detection != null) {
|
||||
$result.detection = detection;
|
||||
}
|
||||
if (confidence != null) {
|
||||
$result.confidence = confidence;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
Face._() : super();
|
||||
factory Face.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
|
||||
factory Face.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
|
||||
|
||||
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'Face', package: const $pb.PackageName(_omitMessageNames ? '' : 'ente.ml'), createEmptyInstance: create)
|
||||
..aOS(1, _omitFieldNames ? '' : 'id')
|
||||
..aOM<Detection>(2, _omitFieldNames ? '' : 'detection', subBuilder: Detection.create)
|
||||
..a<$core.double>(3, _omitFieldNames ? '' : 'confidence', $pb.PbFieldType.OF)
|
||||
..hasRequiredFields = false
|
||||
;
|
||||
|
||||
@$core.Deprecated(
|
||||
'Using this can add significant overhead to your binary. '
|
||||
'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
|
||||
'Will be removed in next major version')
|
||||
Face clone() => Face()..mergeFromMessage(this);
|
||||
@$core.Deprecated(
|
||||
'Using this can add significant overhead to your binary. '
|
||||
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
|
||||
'Will be removed in next major version')
|
||||
Face copyWith(void Function(Face) updates) => super.copyWith((message) => updates(message as Face)) as Face;
|
||||
|
||||
$pb.BuilderInfo get info_ => _i;
|
||||
|
||||
@$core.pragma('dart2js:noInline')
|
||||
static Face create() => Face._();
|
||||
Face createEmptyInstance() => create();
|
||||
static $pb.PbList<Face> createRepeated() => $pb.PbList<Face>();
|
||||
@$core.pragma('dart2js:noInline')
|
||||
static Face getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<Face>(create);
|
||||
static Face? _defaultInstance;
|
||||
|
||||
@$pb.TagNumber(1)
|
||||
$core.String get id => $_getSZ(0);
|
||||
@$pb.TagNumber(1)
|
||||
set id($core.String v) { $_setString(0, v); }
|
||||
@$pb.TagNumber(1)
|
||||
$core.bool hasId() => $_has(0);
|
||||
@$pb.TagNumber(1)
|
||||
void clearId() => clearField(1);
|
||||
|
||||
@$pb.TagNumber(2)
|
||||
Detection get detection => $_getN(1);
|
||||
@$pb.TagNumber(2)
|
||||
set detection(Detection v) { setField(2, v); }
|
||||
@$pb.TagNumber(2)
|
||||
$core.bool hasDetection() => $_has(1);
|
||||
@$pb.TagNumber(2)
|
||||
void clearDetection() => clearField(2);
|
||||
@$pb.TagNumber(2)
|
||||
Detection ensureDetection() => $_ensure(1);
|
||||
|
||||
@$pb.TagNumber(3)
|
||||
$core.double get confidence => $_getN(2);
|
||||
@$pb.TagNumber(3)
|
||||
set confidence($core.double v) { $_setFloat(2, v); }
|
||||
@$pb.TagNumber(3)
|
||||
$core.bool hasConfidence() => $_has(2);
|
||||
@$pb.TagNumber(3)
|
||||
void clearConfidence() => clearField(3);
|
||||
}
|
||||
|
||||
|
||||
const _omitFieldNames = $core.bool.fromEnvironment('protobuf.omit_field_names');
|
||||
const _omitMessageNames = $core.bool.fromEnvironment('protobuf.omit_message_names');
|
11
mobile/lib/generated/protos/ente/ml/face.pbenum.dart
Normal file
|
@ -0,0 +1,11 @@
|
|||
//
|
||||
// Generated code. Do not modify.
|
||||
// source: ente/ml/face.proto
|
||||
//
|
||||
// @dart = 2.12
|
||||
|
||||
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
|
||||
// ignore_for_file: constant_identifier_names, library_prefixes
|
||||
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
|
||||
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import
|
||||
|
55
mobile/lib/generated/protos/ente/ml/face.pbjson.dart
Normal file
|
@ -0,0 +1,55 @@
|
|||
//
|
||||
// Generated code. Do not modify.
|
||||
// source: ente/ml/face.proto
|
||||
//
|
||||
// @dart = 2.12
|
||||
|
||||
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
|
||||
// ignore_for_file: constant_identifier_names, library_prefixes
|
||||
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
|
||||
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import
|
||||
|
||||
import 'dart:convert' as $convert;
|
||||
import 'dart:core' as $core;
|
||||
import 'dart:typed_data' as $typed_data;
|
||||
|
||||
@$core.Deprecated('Use detectionDescriptor instead')
|
||||
const Detection$json = {
|
||||
'1': 'Detection',
|
||||
'2': [
|
||||
{'1': 'box', '3': 1, '4': 1, '5': 11, '6': '.ente.common.CenterBox', '9': 0, '10': 'box', '17': true},
|
||||
{'1': 'landmarks', '3': 2, '4': 1, '5': 11, '6': '.ente.common.EPoint', '9': 1, '10': 'landmarks', '17': true},
|
||||
],
|
||||
'8': [
|
||||
{'1': '_box'},
|
||||
{'1': '_landmarks'},
|
||||
],
|
||||
};
|
||||
|
||||
/// Descriptor for `Detection`. Decode as a `google.protobuf.DescriptorProto`.
|
||||
final $typed_data.Uint8List detectionDescriptor = $convert.base64Decode(
|
||||
'CglEZXRlY3Rpb24SLQoDYm94GAEgASgLMhYuZW50ZS5jb21tb24uQ2VudGVyQm94SABSA2JveI'
|
||||
'gBARI2CglsYW5kbWFya3MYAiABKAsyEy5lbnRlLmNvbW1vbi5FUG9pbnRIAVIJbGFuZG1hcmtz'
|
||||
'iAEBQgYKBF9ib3hCDAoKX2xhbmRtYXJrcw==');
|
||||
|
||||
@$core.Deprecated('Use faceDescriptor instead')
|
||||
const Face$json = {
|
||||
'1': 'Face',
|
||||
'2': [
|
||||
{'1': 'id', '3': 1, '4': 1, '5': 9, '9': 0, '10': 'id', '17': true},
|
||||
{'1': 'detection', '3': 2, '4': 1, '5': 11, '6': '.ente.ml.Detection', '9': 1, '10': 'detection', '17': true},
|
||||
{'1': 'confidence', '3': 3, '4': 1, '5': 2, '9': 2, '10': 'confidence', '17': true},
|
||||
],
|
||||
'8': [
|
||||
{'1': '_id'},
|
||||
{'1': '_detection'},
|
||||
{'1': '_confidence'},
|
||||
],
|
||||
};
|
||||
|
||||
/// Descriptor for `Face`. Decode as a `google.protobuf.DescriptorProto`.
|
||||
final $typed_data.Uint8List faceDescriptor = $convert.base64Decode(
|
||||
'CgRGYWNlEhMKAmlkGAEgASgJSABSAmlkiAEBEjUKCWRldGVjdGlvbhgCIAEoCzISLmVudGUubW'
|
||||
'wuRGV0ZWN0aW9uSAFSCWRldGVjdGlvbogBARIjCgpjb25maWRlbmNlGAMgASgCSAJSCmNvbmZp'
|
||||
'ZGVuY2WIAQFCBQoDX2lkQgwKCl9kZXRlY3Rpb25CDQoLX2NvbmZpZGVuY2U=');
|
||||
|
14
mobile/lib/generated/protos/ente/ml/face.pbserver.dart
Normal file
|
@ -0,0 +1,14 @@
|
|||
//
|
||||
// Generated code. Do not modify.
|
||||
// source: ente/ml/face.proto
|
||||
//
|
||||
// @dart = 2.12
|
||||
|
||||
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
|
||||
// ignore_for_file: constant_identifier_names
|
||||
// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes
|
||||
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
|
||||
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import
|
||||
|
||||
export 'face.pb.dart';
|
||||
|
179
mobile/lib/generated/protos/ente/ml/fileml.pb.dart
Normal file
|
@ -0,0 +1,179 @@
|
|||
//
|
||||
// Generated code. Do not modify.
|
||||
// source: ente/ml/fileml.proto
|
||||
//
|
||||
// @dart = 2.12
|
||||
|
||||
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
|
||||
// ignore_for_file: constant_identifier_names, library_prefixes
|
||||
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
|
||||
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import
|
||||
|
||||
import 'dart:core' as $core;
|
||||
|
||||
import 'package:fixnum/fixnum.dart' as $fixnum;
|
||||
import 'package:protobuf/protobuf.dart' as $pb;
|
||||
|
||||
import 'face.pb.dart' as $2;
|
||||
|
||||
class FileML extends $pb.GeneratedMessage {
|
||||
factory FileML({
|
||||
$fixnum.Int64? id,
|
||||
$core.Iterable<$core.double>? clip,
|
||||
}) {
|
||||
final $result = create();
|
||||
if (id != null) {
|
||||
$result.id = id;
|
||||
}
|
||||
if (clip != null) {
|
||||
$result.clip.addAll(clip);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
FileML._() : super();
|
||||
factory FileML.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
|
||||
factory FileML.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
|
||||
|
||||
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'FileML', package: const $pb.PackageName(_omitMessageNames ? '' : 'ente.ml'), createEmptyInstance: create)
|
||||
..aInt64(1, _omitFieldNames ? '' : 'id')
|
||||
..p<$core.double>(2, _omitFieldNames ? '' : 'clip', $pb.PbFieldType.KD)
|
||||
..hasRequiredFields = false
|
||||
;
|
||||
|
||||
@$core.Deprecated(
|
||||
'Using this can add significant overhead to your binary. '
|
||||
'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
|
||||
'Will be removed in next major version')
|
||||
FileML clone() => FileML()..mergeFromMessage(this);
|
||||
@$core.Deprecated(
|
||||
'Using this can add significant overhead to your binary. '
|
||||
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
|
||||
'Will be removed in next major version')
|
||||
FileML copyWith(void Function(FileML) updates) => super.copyWith((message) => updates(message as FileML)) as FileML;
|
||||
|
||||
$pb.BuilderInfo get info_ => _i;
|
||||
|
||||
@$core.pragma('dart2js:noInline')
|
||||
static FileML create() => FileML._();
|
||||
FileML createEmptyInstance() => create();
|
||||
static $pb.PbList<FileML> createRepeated() => $pb.PbList<FileML>();
|
||||
@$core.pragma('dart2js:noInline')
|
||||
static FileML getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<FileML>(create);
|
||||
static FileML? _defaultInstance;
|
||||
|
||||
@$pb.TagNumber(1)
|
||||
$fixnum.Int64 get id => $_getI64(0);
|
||||
@$pb.TagNumber(1)
|
||||
set id($fixnum.Int64 v) { $_setInt64(0, v); }
|
||||
@$pb.TagNumber(1)
|
||||
$core.bool hasId() => $_has(0);
|
||||
@$pb.TagNumber(1)
|
||||
void clearId() => clearField(1);
|
||||
|
||||
@$pb.TagNumber(2)
|
||||
$core.List<$core.double> get clip => $_getList(1);
|
||||
}
|
||||
|
||||
class FileFaces extends $pb.GeneratedMessage {
|
||||
factory FileFaces({
|
||||
$core.Iterable<$2.Face>? faces,
|
||||
$core.int? height,
|
||||
$core.int? width,
|
||||
$core.int? version,
|
||||
$core.String? error,
|
||||
}) {
|
||||
final $result = create();
|
||||
if (faces != null) {
|
||||
$result.faces.addAll(faces);
|
||||
}
|
||||
if (height != null) {
|
||||
$result.height = height;
|
||||
}
|
||||
if (width != null) {
|
||||
$result.width = width;
|
||||
}
|
||||
if (version != null) {
|
||||
$result.version = version;
|
||||
}
|
||||
if (error != null) {
|
||||
$result.error = error;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
FileFaces._() : super();
|
||||
factory FileFaces.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
|
||||
factory FileFaces.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
|
||||
|
||||
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'FileFaces', package: const $pb.PackageName(_omitMessageNames ? '' : 'ente.ml'), createEmptyInstance: create)
|
||||
..pc<$2.Face>(1, _omitFieldNames ? '' : 'faces', $pb.PbFieldType.PM, subBuilder: $2.Face.create)
|
||||
..a<$core.int>(2, _omitFieldNames ? '' : 'height', $pb.PbFieldType.O3)
|
||||
..a<$core.int>(3, _omitFieldNames ? '' : 'width', $pb.PbFieldType.O3)
|
||||
..a<$core.int>(4, _omitFieldNames ? '' : 'version', $pb.PbFieldType.O3)
|
||||
..aOS(5, _omitFieldNames ? '' : 'error')
|
||||
..hasRequiredFields = false
|
||||
;
|
||||
|
||||
@$core.Deprecated(
|
||||
'Using this can add significant overhead to your binary. '
|
||||
'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
|
||||
'Will be removed in next major version')
|
||||
FileFaces clone() => FileFaces()..mergeFromMessage(this);
|
||||
@$core.Deprecated(
|
||||
'Using this can add significant overhead to your binary. '
|
||||
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
|
||||
'Will be removed in next major version')
|
||||
FileFaces copyWith(void Function(FileFaces) updates) => super.copyWith((message) => updates(message as FileFaces)) as FileFaces;
|
||||
|
||||
$pb.BuilderInfo get info_ => _i;
|
||||
|
||||
@$core.pragma('dart2js:noInline')
|
||||
static FileFaces create() => FileFaces._();
|
||||
FileFaces createEmptyInstance() => create();
|
||||
static $pb.PbList<FileFaces> createRepeated() => $pb.PbList<FileFaces>();
|
||||
@$core.pragma('dart2js:noInline')
|
||||
static FileFaces getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<FileFaces>(create);
|
||||
static FileFaces? _defaultInstance;
|
||||
|
||||
@$pb.TagNumber(1)
|
||||
$core.List<$2.Face> get faces => $_getList(0);
|
||||
|
||||
@$pb.TagNumber(2)
|
||||
$core.int get height => $_getIZ(1);
|
||||
@$pb.TagNumber(2)
|
||||
set height($core.int v) { $_setSignedInt32(1, v); }
|
||||
@$pb.TagNumber(2)
|
||||
$core.bool hasHeight() => $_has(1);
|
||||
@$pb.TagNumber(2)
|
||||
void clearHeight() => clearField(2);
|
||||
|
||||
@$pb.TagNumber(3)
|
||||
$core.int get width => $_getIZ(2);
|
||||
@$pb.TagNumber(3)
|
||||
set width($core.int v) { $_setSignedInt32(2, v); }
|
||||
@$pb.TagNumber(3)
|
||||
$core.bool hasWidth() => $_has(2);
|
||||
@$pb.TagNumber(3)
|
||||
void clearWidth() => clearField(3);
|
||||
|
||||
@$pb.TagNumber(4)
|
||||
$core.int get version => $_getIZ(3);
|
||||
@$pb.TagNumber(4)
|
||||
set version($core.int v) { $_setSignedInt32(3, v); }
|
||||
@$pb.TagNumber(4)
|
||||
$core.bool hasVersion() => $_has(3);
|
||||
@$pb.TagNumber(4)
|
||||
void clearVersion() => clearField(4);
|
||||
|
||||
@$pb.TagNumber(5)
|
||||
$core.String get error => $_getSZ(4);
|
||||
@$pb.TagNumber(5)
|
||||
set error($core.String v) { $_setString(4, v); }
|
||||
@$pb.TagNumber(5)
|
||||
$core.bool hasError() => $_has(4);
|
||||
@$pb.TagNumber(5)
|
||||
void clearError() => clearField(5);
|
||||
}
|
||||
|
||||
|
||||
const _omitFieldNames = $core.bool.fromEnvironment('protobuf.omit_field_names');
|
||||
const _omitMessageNames = $core.bool.fromEnvironment('protobuf.omit_message_names');
|
11
mobile/lib/generated/protos/ente/ml/fileml.pbenum.dart
Normal file
|
@ -0,0 +1,11 @@
|
|||
//
|
||||
// Generated code. Do not modify.
|
||||
// source: ente/ml/fileml.proto
|
||||
//
|
||||
// @dart = 2.12
|
||||
|
||||
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
|
||||
// ignore_for_file: constant_identifier_names, library_prefixes
|
||||
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
|
||||
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import
|
||||
|
57
mobile/lib/generated/protos/ente/ml/fileml.pbjson.dart
Normal file
|
@ -0,0 +1,57 @@
|
|||
//
|
||||
// Generated code. Do not modify.
|
||||
// source: ente/ml/fileml.proto
|
||||
//
|
||||
// @dart = 2.12
|
||||
|
||||
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
|
||||
// ignore_for_file: constant_identifier_names, library_prefixes
|
||||
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
|
||||
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import
|
||||
|
||||
import 'dart:convert' as $convert;
|
||||
import 'dart:core' as $core;
|
||||
import 'dart:typed_data' as $typed_data;
|
||||
|
||||
@$core.Deprecated('Use fileMLDescriptor instead')
|
||||
const FileML$json = {
|
||||
'1': 'FileML',
|
||||
'2': [
|
||||
{'1': 'id', '3': 1, '4': 1, '5': 3, '9': 0, '10': 'id', '17': true},
|
||||
{'1': 'clip', '3': 2, '4': 3, '5': 1, '10': 'clip'},
|
||||
],
|
||||
'8': [
|
||||
{'1': '_id'},
|
||||
],
|
||||
};
|
||||
|
||||
/// Descriptor for `FileML`. Decode as a `google.protobuf.DescriptorProto`.
|
||||
final $typed_data.Uint8List fileMLDescriptor = $convert.base64Decode(
|
||||
'CgZGaWxlTUwSEwoCaWQYASABKANIAFICaWSIAQESEgoEY2xpcBgCIAMoAVIEY2xpcEIFCgNfaW'
|
||||
'Q=');
|
||||
|
||||
@$core.Deprecated('Use fileFacesDescriptor instead')
|
||||
const FileFaces$json = {
|
||||
'1': 'FileFaces',
|
||||
'2': [
|
||||
{'1': 'faces', '3': 1, '4': 3, '5': 11, '6': '.ente.ml.Face', '10': 'faces'},
|
||||
{'1': 'height', '3': 2, '4': 1, '5': 5, '9': 0, '10': 'height', '17': true},
|
||||
{'1': 'width', '3': 3, '4': 1, '5': 5, '9': 1, '10': 'width', '17': true},
|
||||
{'1': 'version', '3': 4, '4': 1, '5': 5, '9': 2, '10': 'version', '17': true},
|
||||
{'1': 'error', '3': 5, '4': 1, '5': 9, '9': 3, '10': 'error', '17': true},
|
||||
],
|
||||
'8': [
|
||||
{'1': '_height'},
|
||||
{'1': '_width'},
|
||||
{'1': '_version'},
|
||||
{'1': '_error'},
|
||||
],
|
||||
};
|
||||
|
||||
/// Descriptor for `FileFaces`. Decode as a `google.protobuf.DescriptorProto`.
|
||||
final $typed_data.Uint8List fileFacesDescriptor = $convert.base64Decode(
|
||||
'CglGaWxlRmFjZXMSIwoFZmFjZXMYASADKAsyDS5lbnRlLm1sLkZhY2VSBWZhY2VzEhsKBmhlaW'
|
||||
'dodBgCIAEoBUgAUgZoZWlnaHSIAQESGQoFd2lkdGgYAyABKAVIAVIFd2lkdGiIAQESHQoHdmVy'
|
||||
'c2lvbhgEIAEoBUgCUgd2ZXJzaW9uiAEBEhkKBWVycm9yGAUgASgJSANSBWVycm9yiAEBQgkKB1'
|
||||
'9oZWlnaHRCCAoGX3dpZHRoQgoKCF92ZXJzaW9uQggKBl9lcnJvcg==');
|
||||
|
14
mobile/lib/generated/protos/ente/ml/fileml.pbserver.dart
Normal file
|
@ -0,0 +1,14 @@
|
|||
//
|
||||
// Generated code. Do not modify.
|
||||
// source: ente/ml/fileml.proto
|
||||
//
|
||||
// @dart = 2.12
|
||||
|
||||
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
|
||||
// ignore_for_file: constant_identifier_names
|
||||
// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes
|
||||
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
|
||||
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import
|
||||
|
||||
export 'fileml.pb.dart';
|
||||
|
|
@ -18,5 +18,12 @@
|
|||
"addCollaborators": "{count, plural, zero {Add collaborator} one {Add collaborator} other {Add collaborators}}",
|
||||
"longPressAnEmailToVerifyEndToEndEncryption": "Long press an email to verify end to end encryption.",
|
||||
"createCollaborativeLink": "Create collaborative link",
|
||||
"search": "Search"
|
||||
"search": "Search",
|
||||
"enterPersonName": "Enter person name",
|
||||
"removePersonLabel": "Remove person label",
|
||||
"faceRecognition": "Face recognition",
|
||||
"faceRecognitionIndexingDescription": "Please note that this will result in a higher bandwidth and battery usage until all items are indexed.",
|
||||
"foundFaces": "Found faces",
|
||||
"clusteringProgress": "Clustering progress",
|
||||
"indexingIsPaused": "Indexing is paused, will automatically resume when device is ready"
|
||||
}
|