Compare commits
380 Commits
fdroid-v0.
...
fdroid-v0.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
21dc35355d | ||
|
|
446556967d | ||
|
|
ec3213040c | ||
|
|
dc494c02c4 | ||
|
|
333a71a4a1 | ||
|
|
05f80f2bdd | ||
|
|
f82e48e754 | ||
|
|
cbf2947b0f | ||
|
|
1952e5278d | ||
|
|
c5019da4bd | ||
|
|
acb898ecf9 | ||
|
|
aea531ee21 | ||
|
|
22c4a50c2b | ||
|
|
4609d395c7 | ||
|
|
8296c81742 | ||
|
|
290716e8ca | ||
|
|
a1afd8155c | ||
|
|
f96a336b4b | ||
|
|
a6600b4718 | ||
|
|
232f793fb0 | ||
|
|
ce0798fbec | ||
|
|
7cbc5ffb2d | ||
|
|
88ac10d96c | ||
|
|
0a7fd03df7 | ||
|
|
9b47595f2c | ||
|
|
af5e072ea5 | ||
|
|
2bc9251a09 | ||
|
|
12a19a484c | ||
|
|
8906cb2a1d | ||
|
|
6f936a42c4 | ||
|
|
497e546129 | ||
|
|
2736ab5334 | ||
|
|
f04b8ffce6 | ||
|
|
b7f33233d9 | ||
|
|
6dffb1f289 | ||
|
|
5a131e7f83 | ||
|
|
2138ef602a | ||
|
|
6adadcaf93 | ||
|
|
0ce4ed494d | ||
|
|
77257aa6ab | ||
|
|
184bb6ec6c | ||
|
|
2e7e9c1ca8 | ||
|
|
7ef3a7a726 | ||
|
|
fbf27b4544 | ||
|
|
67ba7614db | ||
|
|
b05e675820 | ||
|
|
ff3033f1ae | ||
|
|
4dda92219a | ||
|
|
53618d0e1f | ||
|
|
0642e41a2e | ||
|
|
0be4aed185 | ||
|
|
ef93482523 | ||
|
|
bb161ad3a9 | ||
|
|
bf7be69c3d | ||
|
|
82358812bd | ||
|
|
e52e61c0af | ||
|
|
17ea9dfaaa | ||
|
|
6e045affa4 | ||
|
|
1232b956c9 | ||
|
|
9a284f916f | ||
|
|
df321f9dea | ||
|
|
543411254b | ||
|
|
a3b9b6bb90 | ||
|
|
5b9e1abec3 | ||
|
|
a1e97239c3 | ||
|
|
2f372cdbe1 | ||
|
|
9910049d1d | ||
|
|
fe2771f2e0 | ||
|
|
2e517535b3 | ||
|
|
e459fb5686 | ||
|
|
9498571c10 | ||
|
|
f2a9675911 | ||
|
|
ede505d939 | ||
|
|
65a92f1a77 | ||
|
|
56cdb9064d | ||
|
|
7ddf70eb86 | ||
|
|
6592ddedfd | ||
|
|
1b74049eb5 | ||
|
|
568377d4e7 | ||
|
|
4bd416fd10 | ||
|
|
634ae71a5d | ||
|
|
0ae1557508 | ||
|
|
93071af19a | ||
|
|
ab15263a17 | ||
|
|
d2d02f3591 | ||
|
|
1e79409f73 | ||
|
|
866d2bb00a | ||
|
|
1832005d72 | ||
|
|
b054c070ad | ||
|
|
64a47694d0 | ||
|
|
8af02aa4c8 | ||
|
|
a4e09a40e8 | ||
|
|
82fc1a1434 | ||
|
|
b511aeb401 | ||
|
|
6812527607 | ||
|
|
2263eb684c | ||
|
|
8df68cf529 | ||
|
|
ba11a5a755 | ||
|
|
e31b55499b | ||
|
|
89f917220d | ||
|
|
fad26a960d | ||
|
|
6e3d285428 | ||
|
|
2198eeb372 | ||
|
|
184c044377 | ||
|
|
63d41434a9 | ||
|
|
310f180c5a | ||
|
|
5da05467d6 | ||
|
|
a2decb5030 | ||
|
|
6f891a45de | ||
|
|
4e7d764722 | ||
|
|
9aae713207 | ||
|
|
17aa1b67c1 | ||
|
|
5e22c95bfb | ||
|
|
182fd89356 | ||
|
|
6516b457cb | ||
|
|
bf78b2e671 | ||
|
|
58afaa9405 | ||
|
|
1bffbdad03 | ||
|
|
267d5cef65 | ||
|
|
d391db2dd5 | ||
|
|
8a222d9dc4 | ||
|
|
cf4c20f2d3 | ||
|
|
28c29a0c3a | ||
|
|
3de1c8011a | ||
|
|
7adb166fad | ||
|
|
6447ba6ec0 | ||
|
|
258cdca69b | ||
|
|
2a19c30d0e | ||
|
|
d23c22762b | ||
|
|
bf9d0e3d6b | ||
|
|
a818f062b1 | ||
|
|
f57f1a8636 | ||
|
|
da78c45b1d | ||
|
|
3429a9f3d6 | ||
|
|
cdbd86d63c | ||
|
|
69e1aa18e6 | ||
|
|
6f2079c7c6 | ||
|
|
a14358416a | ||
|
|
57c353a443 | ||
|
|
dd7cea1f96 | ||
|
|
6d2a223acf | ||
|
|
eca0137426 | ||
|
|
e1e2c528c4 | ||
|
|
28ab3c321c | ||
|
|
5c2c6b2a84 | ||
|
|
4ae0683c62 | ||
|
|
0a6740bb2e | ||
|
|
b026020485 | ||
|
|
b71fa478b9 | ||
|
|
b9c992cae0 | ||
|
|
2845d7bfeb | ||
|
|
b09d6ab2a6 | ||
|
|
94ce77c07b | ||
|
|
a292f01187 | ||
|
|
aae2632b19 | ||
|
|
746c85bc9f | ||
|
|
adeab53d3b | ||
|
|
3e23ff9c9b | ||
|
|
dca6e02286 | ||
|
|
daf3fd2a75 | ||
|
|
f5a3b8a3fb | ||
|
|
7cd1ce0a99 | ||
|
|
1b863005ea | ||
|
|
b580756e6b | ||
|
|
26fb47c165 | ||
|
|
3f21011392 | ||
|
|
7348170a36 | ||
|
|
3919fb0db2 | ||
|
|
ad6a0e9c31 | ||
|
|
be3896826d | ||
|
|
268550f292 | ||
|
|
68e557124c | ||
|
|
96863923d1 | ||
|
|
a22b0aec58 | ||
|
|
93e26c6caf | ||
|
|
8a8f5c20c6 | ||
|
|
3c7b6694e9 | ||
|
|
c37d85f6c5 | ||
|
|
e0abb2de9c | ||
|
|
b73ba4a22f | ||
|
|
912279e3cf | ||
|
|
5a0bab9304 | ||
|
|
a9cd56c4ce | ||
|
|
5b4028378b | ||
|
|
57bd5b9d17 | ||
|
|
2bd074bd79 | ||
|
|
a8d831364d | ||
|
|
21f0602161 | ||
|
|
1ac2d60c7b | ||
|
|
a098481b98 | ||
|
|
472339cafb | ||
|
|
d24f5bcee7 | ||
|
|
bd0e8e6fe6 | ||
|
|
c9d2a0a4ca | ||
|
|
1a6eb26f2b | ||
|
|
7c2fce2ebe | ||
|
|
e90871ea6b | ||
|
|
3ca78cac35 | ||
|
|
49ddfdfde5 | ||
|
|
bc76864587 | ||
|
|
4f1d3c23f5 | ||
|
|
cc674183cd | ||
|
|
86bd098406 | ||
|
|
e5fe3a7255 | ||
|
|
df68d3f005 | ||
|
|
9a6a46fd0d | ||
|
|
14c9929451 | ||
|
|
54f9bd880a | ||
|
|
aaa636345c | ||
|
|
6f3e02888e | ||
|
|
42a8b5c826 | ||
|
|
24674f6da6 | ||
|
|
90b45665f5 | ||
|
|
8a217a292b | ||
|
|
047fede844 | ||
|
|
e77b557990 | ||
|
|
c2bfcf23c0 | ||
|
|
646a012734 | ||
|
|
21332c6b92 | ||
|
|
f9c101241e | ||
|
|
bc6f147f5e | ||
|
|
fbaa360741 | ||
|
|
4029398351 | ||
|
|
7602d48bd9 | ||
|
|
f28d50ace6 | ||
|
|
b026b30172 | ||
|
|
977f5c21a6 | ||
|
|
dafbf23d67 | ||
|
|
d9bc6597c0 | ||
|
|
913a80591b | ||
|
|
26c0a8e1d5 | ||
|
|
2e2c972a84 | ||
|
|
748dd2b0e2 | ||
|
|
dbb376056d | ||
|
|
b31fc5cbe9 | ||
|
|
cb76ba7560 | ||
|
|
e915ded2de | ||
|
|
eedc538283 | ||
|
|
294b333d0e | ||
|
|
8f705f2f72 | ||
|
|
c5c0ee5ddf | ||
|
|
5f43f03a65 | ||
|
|
aa62f4003c | ||
|
|
6c5dbc3696 | ||
|
|
1bef409552 | ||
|
|
62155040da | ||
|
|
592dc26d8b | ||
|
|
1af1c3f196 | ||
|
|
6f077310c1 | ||
|
|
905fc2ad78 | ||
|
|
e6e4f313de | ||
|
|
1ae8caa917 | ||
|
|
209228326d | ||
|
|
0533f99313 | ||
|
|
545cf40710 | ||
|
|
8ae8ed20fe | ||
|
|
0df0126af4 | ||
|
|
60ad6ef713 | ||
|
|
fc626c1287 | ||
|
|
4035e364df | ||
|
|
791ec10a0f | ||
|
|
87ab805cf7 | ||
|
|
447bb72556 | ||
|
|
c07e2f1387 | ||
|
|
151a0b3ab7 | ||
|
|
cf15d68bd2 | ||
|
|
e4a05edc12 | ||
|
|
879d6571bc | ||
|
|
2496350fad | ||
|
|
653a7f22ef | ||
|
|
6071df2083 | ||
|
|
f6e93ab060 | ||
|
|
ddc9dfe552 | ||
|
|
b9b87c1570 | ||
|
|
3a413524f8 | ||
|
|
4830451d4e | ||
|
|
4cb11f4b06 | ||
|
|
150faa5d84 | ||
|
|
9b15102058 | ||
|
|
25bb175ff7 | ||
|
|
ec7b61c36a | ||
|
|
85735b4ff0 | ||
|
|
8029829d9b | ||
|
|
87c5f05f84 | ||
|
|
356b2542c9 | ||
|
|
dc3329368e | ||
|
|
92868dccb4 | ||
|
|
49942909b0 | ||
|
|
b36c8de417 | ||
|
|
a0335b82c6 | ||
|
|
01cbf29217 | ||
|
|
7c464a0d60 | ||
|
|
8c20f5f660 | ||
|
|
671199e286 | ||
|
|
6805ee1a2a | ||
|
|
fd8246705c | ||
|
|
65e1745aa0 | ||
|
|
c6c3b1f9bd | ||
|
|
175467267a | ||
|
|
9756c178bf | ||
|
|
af420a8fc3 | ||
|
|
9a5d977419 | ||
|
|
d4ae5c118b | ||
|
|
605fda2710 | ||
|
|
0181693736 | ||
|
|
5c92d093ca | ||
|
|
a6c9a153e7 | ||
|
|
613f7294e1 | ||
|
|
facd05bd89 | ||
|
|
4bbe71e135 | ||
|
|
5583902433 | ||
|
|
664c723c78 | ||
|
|
9b35fe04b9 | ||
|
|
34068d09ba | ||
|
|
c23b22cc5b | ||
|
|
065382ddd2 | ||
|
|
5a72686e53 | ||
|
|
8c5b77cd52 | ||
|
|
d30dce0896 | ||
|
|
c453827cc8 | ||
|
|
1068b6811f | ||
|
|
09fe2c6f7e | ||
|
|
a31803e3f5 | ||
|
|
2ec8ae34b8 | ||
|
|
3263542f5e | ||
|
|
a302f986d7 | ||
|
|
69ccf7d3c9 | ||
|
|
76308cc9d0 | ||
|
|
1d02732719 | ||
|
|
55fa86a6c8 | ||
|
|
39fad29bc8 | ||
|
|
2ebe8712e8 | ||
|
|
1f7176cea2 | ||
|
|
bede7559be | ||
|
|
77563a7483 | ||
|
|
37df79314a | ||
|
|
fc5d1f931c | ||
|
|
243948f182 | ||
|
|
ddc953045b | ||
|
|
f74f285b7f | ||
|
|
2a4a886fca | ||
|
|
43e3e44e5c | ||
|
|
09cc226511 | ||
|
|
d9f62b8956 | ||
|
|
fbbb8edce1 | ||
|
|
7f3d0a5328 | ||
|
|
423a669cff | ||
|
|
4546d60e61 | ||
|
|
eec060ae71 | ||
|
|
70ec18462b | ||
|
|
b3cf07f232 | ||
|
|
2f3639fbbc | ||
|
|
7ce5306f53 | ||
|
|
4150e607eb | ||
|
|
9650eb3ff6 | ||
|
|
32f8075acf | ||
|
|
9fb1dbf67e | ||
|
|
06cad1b996 | ||
|
|
2a4b15ea48 | ||
|
|
c0bbad8f88 | ||
|
|
b5c2991575 | ||
|
|
8b01129cc9 | ||
|
|
58486744e1 | ||
|
|
a0d46ac60e | ||
|
|
2430473a10 | ||
|
|
4f963f250f | ||
|
|
ca70c36ae0 | ||
|
|
1bf8f2749e | ||
|
|
56b8728e79 | ||
|
|
df28a8bf50 | ||
|
|
0a446a6629 | ||
|
|
b8f1bce341 | ||
|
|
be615197fd | ||
|
|
d4a68069ba | ||
|
|
8fc14c72e2 | ||
|
|
69d75644d0 | ||
|
|
1fabaf9aaa | ||
|
|
aa482ea227 | ||
|
|
41c242a0ee | ||
|
|
c2e53c6ec9 |
2
.github/workflows/auth-release.yml
vendored
2
.github/workflows/auth-release.yml
vendored
@@ -151,7 +151,7 @@ jobs:
|
||||
- name: Install dependencies for desktop build
|
||||
run: |
|
||||
sudo apt-get update -y
|
||||
sudo apt-get install -y libsecret-1-dev libsodium-dev libfuse2 ninja-build libgtk-3-dev dpkg-dev pkg-config rpm patchelf libsqlite3-dev locate libayatana-appindicator3-dev libffi-dev libtiff5 xz-utils libarchive-tools
|
||||
sudo apt-get install -y libsecret-1-dev libsodium-dev libfuse2 ninja-build libgtk-3-dev dpkg-dev pkg-config rpm patchelf libsqlite3-dev locate libayatana-appindicator3-dev libffi-dev libtiff5 xz-utils libarchive-tools libcurl4-openssl-dev
|
||||
sudo updatedb --localpaths='/usr/lib/x86_64-linux-gnu'
|
||||
|
||||
- name: Install appimagetool
|
||||
|
||||
2
.github/workflows/cli-release.yml
vendored
2
.github/workflows/cli-release.yml
vendored
@@ -45,7 +45,7 @@ jobs:
|
||||
goarch: ${{ matrix.goarch }}
|
||||
asset_name: ente-${{ github.ref_name }}-${{ matrix.goos }}-${{ matrix.goarch }}
|
||||
release_name: ${{ github.ref_name }}
|
||||
goversion: "1.20"
|
||||
goversion: "1.23"
|
||||
project_path: "./cli"
|
||||
pre_command: export CGO_ENABLED=0
|
||||
build_flags: "-trimpath"
|
||||
|
||||
7
.github/workflows/server-publish.yml
vendored
7
.github/workflows/server-publish.yml
vendored
@@ -1,4 +1,4 @@
|
||||
name: "Publish (server)"
|
||||
name: "Publish ghcr (server)"
|
||||
|
||||
on:
|
||||
# Run manually, providing it the commit.
|
||||
@@ -39,7 +39,6 @@ jobs:
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Tag as server/ghcr
|
||||
- name: Update branch server/ghcr to point to source commit
|
||||
run: |
|
||||
git tag -f server/ghcr
|
||||
git push -f origin server/ghcr
|
||||
git push -f origin HEAD:server/ghcr
|
||||
|
||||
@@ -72,6 +72,10 @@
|
||||
"NGA社区"
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Belo",
|
||||
"hex": "5717d4"
|
||||
},
|
||||
{
|
||||
"title": "Bethesda",
|
||||
"altNames": [
|
||||
@@ -175,6 +179,9 @@
|
||||
{
|
||||
"title": "Bybit"
|
||||
},
|
||||
{
|
||||
"title": "Caixa"
|
||||
},
|
||||
{
|
||||
"title": "Canva"
|
||||
},
|
||||
@@ -637,7 +644,7 @@
|
||||
{
|
||||
"title": "nordvpn",
|
||||
"slug": "nordaccount",
|
||||
"hex": "#4687FF",
|
||||
"hex": "4687FF",
|
||||
"altNames": [
|
||||
"Nord Account"
|
||||
]
|
||||
@@ -747,7 +754,7 @@
|
||||
},
|
||||
{
|
||||
"title": "randstad",
|
||||
"hex": "#2175D9"
|
||||
"hex": "2175D9"
|
||||
},
|
||||
{
|
||||
"title": "Real-Debrid",
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
<svg width="500" height="500" viewBox="0 0 500 500" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M442.375 441.562C390.672 479.687 315.75 500 251.25 500C160.625 500 79.344 466.562 17.7346 410.89C13.0471 406.515 17.2346 400.547 23.0471 403.953C89.5315 442.656 171.875 465.937 256.656 465.937C317.884 465.655 378.451 453.272 434.875 429.5C443.625 425.781 450.969 435.218 442.375 441.562ZM463.875 416.968C457.313 408.531 420.188 412.984 403.563 414.937C398.485 415.562 397.719 411.14 402.281 407.968C431.969 387.187 480.313 393.172 485.969 400.156C491.625 407.14 484.5 455.781 456.75 478.968C452.485 482.531 448.422 480.64 450.5 475.906C456.75 460.343 470.719 425.437 464.094 416.968" fill="#FF9900"/>
|
||||
<g style="mix-blend-mode:difference">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M287.969 216.625C287.969 243.063 288.641 265.109 275.281 288.578C264.344 307.641 247.156 319.406 228.328 319.406C202.281 319.406 187.016 299.563 187.016 270.266C187.016 212.453 238.828 201.938 287.984 201.938L287.969 216.625ZM356.422 382C351.938 386.016 345.453 386.297 340.391 383.625C317.891 364.922 313.766 356.234 301.453 338.391C264.234 376.359 237.797 387.719 189.609 387.719C132.453 387.719 88.0781 352.5 88.0781 281.984C88.0781 226.922 117.844 189.422 160.422 171.094C197.25 154.875 248.703 152.031 288 147.656V139.062C288 122.938 289.25 103.844 279.719 89.9219C271.516 77.4219 255.656 72.2656 241.641 72.2656C215.781 72.2656 192.781 85.5469 187.156 113.016C186.016 119.266 181.531 125.141 175.328 125.422L109.375 118.047C103.844 116.797 97.6563 112.328 99.2656 103.984C114.5 24.0625 186.641 0 251.156 0C284.172 0 327.313 8.78125 353.344 33.7812C386.359 64.6094 383.219 105.734 383.219 150.5V256.25C383.219 288.031 396.391 301.953 408.797 319.141C413.094 325.391 414.047 332.578 408.516 337.172C391.003 351.98 373.669 366.997 356.516 382.219L356.422 382.031" fill="white"/>
|
||||
</g>
|
||||
</svg>
|
||||
<svg width="500" height="500" viewBox="0 0 500 500" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M16.05 385.03C13.89 386.74 13.44 389.58 14.69 393.56C15.83 397.09 18.5 401.47 22.71 406.7C39.65 427.63 59.84 445.03 83.27 458.9C106.7 472.78 131.78 483.01 158.51 489.61C185.35 496.32 212.76 499.68 240.73 499.68C276.56 499.68 310.68 494.44 343.09 483.98C375.51 473.63 402.58 459.07 424.3 440.31C431.92 433.6 435.73 428.25 435.73 424.27C435.73 422.79 435.1 421.31 433.85 419.83C432.15 418.13 430.1 417.56 427.71 418.13C425.32 418.7 421.97 420.12 417.65 422.39C396.83 433.31 371.47 442.01 341.56 448.49C311.76 455.09 280.65 458.39 248.24 458.39C208.09 458.39 169.31 452.93 131.89 442.01C94.47 431.09 61.32 414.03 32.43 390.83C28.22 387.53 24.81 385.43 22.19 384.52C19.69 383.61 17.65 383.78 16.05 385.03Z"
|
||||
fill="#FF6200"/>
|
||||
<path d="M395.12 393.57C392.73 395.85 392.11 398.24 393.24 400.74C394.04 402.56 395.58 403.58 397.85 403.81C400.12 404.15 403.37 403.92 407.57 403.13C414.4 401.65 421.51 400.62 428.9 400.06C436.29 399.6 442.72 399.71 448.18 400.4C453.64 401.19 457.05 402.56 458.41 404.49C460.46 407.56 459.72 414.04 456.2 423.94C452.78 433.83 448.12 443.44 442.21 452.77C439.93 456.52 438.57 459.48 438.11 461.64C437.66 463.8 438.23 465.62 439.82 467.1C440.84 468.12 441.98 468.64 443.23 468.64C446.53 468.64 451.31 465.74 457.56 459.94C468.82 450.16 476.72 438.55 481.27 425.13C483.78 418.2 485.31 410.92 485.88 403.3C486.45 395.68 485.6 390.22 483.32 386.92C481.16 383.73 476.38 381.12 468.99 379.07C461.71 377.02 454.38 376 446.98 376C432.54 376 418.83 379.41 405.87 386.24C401.09 388.85 397.51 391.3 395.12 393.57Z"
|
||||
fill="#FF6200"/>
|
||||
<g style="mix-blend-mode:difference">
|
||||
<path d="M209.76 387.72C188.61 387.72 170 383.1 153.92 373.87C137.84 364.34 125.33 351.24 116.4 334.56C107.47 317.59 103 298.09 103 276.05C103 249.55 109.55 226.32 122.65 206.37C136.05 186.42 154.96 171.08 179.38 160.36C204.1 149.64 232.98 144.28 266.04 144.28C281.23 144.28 293.58 145.32 303.11 147.41V138.03C303.11 115.39 298.94 98.57 290.61 87.55C282.27 76.23 269.61 70.58 252.64 70.58C225.24 70.58 207.67 85.02 199.93 113.9C197.55 122.24 192.63 125.82 185.19 124.62L124.44 113.9C119.97 113.01 116.85 111.08 115.06 108.1C113.57 105.12 113.42 101.1 114.61 96.04C122.36 65.66 138.74 42.14 163.75 25.46C189.06 8.49 220.78 0 258.89 0C304.16 0 338.55 12.21 362.08 36.63C385.9 61.05 397.81 96.63 397.81 143.39V368.07C397.81 371.34 396.62 374.17 394.24 376.55C392.15 378.64 389.47 379.68 386.2 379.68H328.13C320.98 379.68 316.51 375.81 314.73 368.07L305.79 326.08H302.22C294.18 345.73 282.12 360.92 266.04 371.64C250.26 382.36 231.49 387.72 209.76 387.72ZM200.38 265.33C200.38 281.11 204.4 293.77 212.44 303.3C220.78 312.53 231.94 317.14 245.94 317.14C264.4 317.14 278.55 308.95 288.37 292.58C298.2 275.9 303.11 252.08 303.11 221.11V197.43C294.78 195.94 286.88 195.2 279.44 195.2C255.02 195.2 235.66 201.6 221.37 214.41C207.37 226.91 200.38 243.89 200.38 265.33Z"
|
||||
fill="white"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 2.9 KiB |
1
auth/assets/custom-icons/icons/belo.svg
Normal file
1
auth/assets/custom-icons/icons/belo.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="87" height="87" fill="none"><rect width="86.1667" height="86.2257" fill="#5717D4" rx="14.7344"/><path fill="#00FFB2" fill-rule="evenodd" d="M24.448 35.976c.461-.504 1.242-.536 1.767-.098a26.25 26.25 0 0 0 16.867 6.09 26.25 26.25 0 0 0 16.867-6.09c.525-.438 1.306-.406 1.767.098l4.178 4.562a1.204 1.204 0 0 1-.092 1.732 34.9 34.9 0 0 1-22.72 8.36 34.9 34.9 0 0 1-22.72-8.36 1.204 1.204 0 0 1-.092-1.732z" clip-rule="evenodd"/></svg>
|
||||
|
After Width: | Height: | Size: 478 B |
9
auth/assets/custom-icons/icons/caixa.svg
Normal file
9
auth/assets/custom-icons/icons/caixa.svg
Normal file
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="500px" height="500px" style="shape-rendering:geometricPrecision; text-rendering:geometricPrecision; image-rendering:optimizeQuality; fill-rule:evenodd; clip-rule:evenodd" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g><path style="opacity:0.99" fill="#0170ae" d="M 268.5,114.5 C 268.343,115.873 268.51,117.207 269,118.5C 291.11,156.392 312.943,194.392 334.5,232.5C 281.008,234.166 227.341,235.166 173.5,235.5C 135.941,171.393 98.6076,107.06 61.5,42.5C 116.5,41.1667 171.5,41.1667 226.5,42.5C 240.022,66.8911 254.022,90.8911 268.5,114.5 Z"/></g>
|
||||
<g><path style="opacity:0.982" fill="#f5812a" d="M 499.5,43.5 C 499.5,44.5 499.5,45.5 499.5,46.5C 449.174,108.835 399.174,171.502 349.5,234.5C 345.217,235.492 340.884,235.826 336.5,235.5C 336.573,233.973 335.906,232.973 334.5,232.5C 312.943,194.392 291.11,156.392 269,118.5C 268.51,117.207 268.343,115.873 268.5,114.5C 286.953,90.8749 305.619,67.3749 324.5,44C 382.832,43.5 441.166,43.3333 499.5,43.5 Z"/></g>
|
||||
<g><path style="opacity:0.561" fill="#337394" d="M 334.5,232.5 C 335.906,232.973 336.573,233.973 336.5,235.5C 282.167,235.5 227.833,235.5 173.5,235.5C 227.341,235.166 281.008,234.166 334.5,232.5 Z"/></g>
|
||||
<g><path style="opacity:0.988" fill="#f5812a" d="M 325.5,264.5 C 322.22,267.043 319.387,270.043 317,273.5C 289.381,309.454 261.381,345.12 233,380.5C 231.121,382.527 229.954,384.86 229.5,387.5C 211.307,410.688 192.973,433.855 174.5,457C 116.168,457.5 57.8343,457.667 -0.5,457.5C -0.5,456.5 -0.5,455.5 -0.5,454.5C 50.0174,391.474 100.017,327.974 149.5,264C 208.335,263.168 267.001,263.335 325.5,264.5 Z"/></g>
|
||||
<g><path style="opacity:0.99" fill="#0170ae" d="M 325.5,264.5 C 364.664,327.999 402.998,391.999 440.5,456.5C 383.829,456.833 327.163,456.5 270.5,455.5C 256.822,432.806 243.155,410.139 229.5,387.5C 229.954,384.86 231.121,382.527 233,380.5C 261.381,345.12 289.381,309.454 317,273.5C 319.387,270.043 322.22,267.043 325.5,264.5 Z"/></g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.1 KiB |
Submodule auth/assets/simple-icons updated: 954790ce65...6dcfdc2f58
@@ -82,9 +82,9 @@ PODS:
|
||||
- qr_code_scanner (0.2.0):
|
||||
- Flutter
|
||||
- MTBBarcodeScanner
|
||||
- SDWebImage (5.19.7):
|
||||
- SDWebImage/Core (= 5.19.7)
|
||||
- SDWebImage/Core (5.19.7)
|
||||
- SDWebImage (5.20.0):
|
||||
- SDWebImage/Core (= 5.20.0)
|
||||
- SDWebImage/Core (5.20.0)
|
||||
- Sentry/HybridSDK (8.36.0)
|
||||
- sentry_flutter (8.9.0):
|
||||
- Flutter
|
||||
@@ -245,7 +245,7 @@ SPEC CHECKSUMS:
|
||||
path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46
|
||||
privacy_screen: 1a131c052ceb3c3659934b003b0d397c2381a24e
|
||||
qr_code_scanner: bb67d64904c3b9658ada8c402e8b4d406d5d796e
|
||||
SDWebImage: 8a6b7b160b4d710e2a22b6900e25301075c34cb3
|
||||
SDWebImage: 73c6079366fea25fa4bb9640d5fb58f0893facd8
|
||||
Sentry: f8374b5415bc38dfb5645941b3ae31230fbeae57
|
||||
sentry_flutter: 0eb93e5279eb41e2392212afe1ccd2fecb4f8cbe
|
||||
share_plus: 8875f4f2500512ea181eef553c3e27dba5135aad
|
||||
|
||||
@@ -8,6 +8,8 @@ const String sentryDSN =
|
||||
const String sentryTunnel = "https://sentry-reporter.ente.io";
|
||||
const String roadmapURL = "https://roadmap.ente.io";
|
||||
|
||||
const String kAccountsUrl = "https://accounts.ente.io";
|
||||
|
||||
const String githubFeatureRequestUrl =
|
||||
"https://github.com/ente-io/ente/discussions/categories/feature-requests?discussions_q=is%3Aopen+category%3A%22Feature+requests%22+label%3A%22-+auth%22+sort%3Atop";
|
||||
const int microSecondsInDay = 86400000000;
|
||||
|
||||
@@ -258,6 +258,10 @@
|
||||
"areYouSureYouWantToLogout": "Наистина ли искате да излезете от профила си?",
|
||||
"yesLogout": "Да, излез",
|
||||
"exit": "Изход",
|
||||
"theme": "Тема",
|
||||
"lightTheme": "Светла",
|
||||
"darkTheme": "Тъмна",
|
||||
"systemTheme": "Системна",
|
||||
"verifyingRecoveryKey": "Проверка на ключа за възстановяване...",
|
||||
"recoveryKeyVerified": "Ключът за възстановяване е проверен",
|
||||
"recoveryKeySuccessBody": "Страхотно! Вашият ключ за възстановяване е валиден. Благодарим Ви за проверката.\n\nМоля, не забравяйте да запазите безопасно архивирания си ключ за възстановяване.",
|
||||
@@ -490,5 +494,13 @@
|
||||
"appLockNotEnabled": "Заключването на приложението не е активирано",
|
||||
"appLockNotEnabledDescription": "Моля, активирайте заключването на приложението от Сигурност > Заключване на приложението",
|
||||
"authToViewPasskey": "Моля, удостоверете се, за да видите Вашите ключове за парола",
|
||||
"appLockOfflineModeWarning": "Избрахте да продължите без резервни копия. Ако забравите паролата на приложението си, ще бъдете заключени от достъп до вашите данни."
|
||||
"appLockOfflineModeWarning": "Избрахте да продължите без резервни копия. Ако забравите паролата на приложението си, ще бъдете заключени от достъп до вашите данни.",
|
||||
"duplicateCodes": "Повтарящи се кодове",
|
||||
"noDuplicates": "✨ Няма дубликати",
|
||||
"youveNoDuplicateCodesThatCanBeCleared": "Нямате повтарящи се кодове, които могат да бъдат изчистени",
|
||||
"deduplicateCodes": "Премахване на повтарящи се кодове",
|
||||
"deselectAll": "Демаркиране на всички",
|
||||
"selectAll": "Избиране на всички",
|
||||
"deleteDuplicates": "Изтриване на дубликатите",
|
||||
"plainHTML": "Обикновен HTML"
|
||||
}
|
||||
@@ -156,6 +156,7 @@
|
||||
"twoFactorAuthTitle": "Autenticació de dos factors",
|
||||
"passkeyAuthTitle": "Verificació per passkey",
|
||||
"verifyPasskey": "Verifica la passkey",
|
||||
"loginWithTOTP": "Inici de sessió amb TOTP",
|
||||
"recoverAccount": "Recupera el compte",
|
||||
"enterRecoveryKeyHint": "Introdueix la teva clau de recuperació",
|
||||
"recover": "Recupera",
|
||||
@@ -257,6 +258,10 @@
|
||||
"areYouSureYouWantToLogout": "Segur que vols tancar la sessió?",
|
||||
"yesLogout": "Sí, tanca la sessió",
|
||||
"exit": "Surt",
|
||||
"theme": "Tema",
|
||||
"lightTheme": "Clar",
|
||||
"darkTheme": "Fosc",
|
||||
"systemTheme": "Del sistema",
|
||||
"verifyingRecoveryKey": "Verificant clau de recuperació...",
|
||||
"recoveryKeyVerified": "Clau de recuperació verificada",
|
||||
"recoveryKeySuccessBody": "Perfecte! La teva clau de recuperació és vàlida. Gràcies per verificar-ho.\n\nSi us plau, recorda mantenir una còpia de seguretat de la teva clau de recuperació en un lloc segur.",
|
||||
@@ -327,6 +332,10 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"manualSort": "Personalitzat",
|
||||
"editOrder": "Edita l'ordre",
|
||||
"mostFrequentlyUsed": "Usats sovint",
|
||||
"mostRecentlyUsed": "Usats recentment",
|
||||
"activeSessions": "Sessions actives",
|
||||
"somethingWentWrongPleaseTryAgain": "S'ha produït un error, si us plau, intenta-ho de nou",
|
||||
"thisWillLogYouOutOfThisDevice": "Això tancarà la sessió en aquest dispositiu!",
|
||||
@@ -446,6 +455,9 @@
|
||||
"customEndpoint": "Connectat a {endpoint}",
|
||||
"pinText": "Fixa",
|
||||
"unpinText": "Desfixa",
|
||||
"pinnedCodeMessage": "{code} s'ha fixat",
|
||||
"unpinnedCodeMessage": "{code} s'ha deixat de fixar",
|
||||
"pinned": "Fixat",
|
||||
"tags": "Etiquetes",
|
||||
"createNewTag": "Crea una nova etiqueta",
|
||||
"tag": "Etiqueta",
|
||||
@@ -482,5 +494,13 @@
|
||||
"appLockNotEnabled": "Bloqueig de l'aplicació no habilitat",
|
||||
"appLockNotEnabledDescription": "Si us plau, habilita el bloqueig de l'aplicació a Seguretat > Bloqueig de l'aplicació",
|
||||
"authToViewPasskey": "Autentica't per veure la passkey",
|
||||
"appLockOfflineModeWarning": "Has triat procedir sense còpies de seguretat. Si oblides el bloqueig de l'aplicació, no podràs accedir a les teves dades."
|
||||
"appLockOfflineModeWarning": "Has triat procedir sense còpies de seguretat. Si oblides el bloqueig de l'aplicació, no podràs accedir a les teves dades.",
|
||||
"duplicateCodes": "Codis duplicats",
|
||||
"noDuplicates": "✨ Sense duplicats",
|
||||
"youveNoDuplicateCodesThatCanBeCleared": "No teniu codis duplicats que es puguin esborrar",
|
||||
"deduplicateCodes": "Desduplica codis",
|
||||
"deselectAll": "Desselecciona-ho tot",
|
||||
"selectAll": "Seleccionar-ho tot",
|
||||
"deleteDuplicates": "Elimina duplicats",
|
||||
"plainHTML": "HTML pla"
|
||||
}
|
||||
@@ -458,7 +458,6 @@
|
||||
"pinnedCodeMessage": "{code} has been pinned",
|
||||
"unpinnedCodeMessage": "{code} has been unpinned",
|
||||
"pinned": "Pinned",
|
||||
|
||||
"tags": "Tags",
|
||||
"createNewTag": "Create New Tag",
|
||||
"tag": "Tag",
|
||||
@@ -502,5 +501,6 @@
|
||||
"deduplicateCodes": "Deduplicate codes",
|
||||
"deselectAll": "Deselect all",
|
||||
"selectAll": "Select all",
|
||||
"deleteDuplicates": "Delete duplicates"
|
||||
"deleteDuplicates": "Delete duplicates",
|
||||
"plainHTML": "Plain HTML"
|
||||
}
|
||||
@@ -54,7 +54,7 @@
|
||||
"viewLogsAction": "Ver Registros",
|
||||
"sendLogsDescription": "Esto enviará registros para ayudarnos a depurar su problema. Aunque tomamos precauciones para asegurarnos que no se registre información sensible, le recomendamos que consulte estos registros antes de compartirlos.",
|
||||
"preparingLogsTitle": "Preparando registros...",
|
||||
"emailLogsTitle": "Enviar registros por email",
|
||||
"emailLogsTitle": "Enviar registros por correo electrónico",
|
||||
"emailLogsMessage": "Por favor, envíe los registros a {email}",
|
||||
"@emailLogsMessage": {
|
||||
"placeholders": {
|
||||
@@ -115,7 +115,7 @@
|
||||
"importCodeDelimiterInfo": "Los códigos pueden separarse por una coma o una nueva línea",
|
||||
"selectFile": "Seleccionar archivo",
|
||||
"emailVerificationToggle": "Verificación de correo electrónico",
|
||||
"emailVerificationEnableWarning": "Para evitar quedarte bloqueado fuera de tu cuenta, asegúrate de guardar una copia de su código 2FA de tu correo electrónico fuera de Ente Auth antes de habilitar la verificación de correo electrónico.",
|
||||
"emailVerificationEnableWarning": "Para evitar quedarte bloqueado fuera de tu cuenta, asegúrate de guardar una copia de tu código 2FA de tu correo electrónico fuera de Ente Auth antes de habilitar la verificación de correo electrónico.",
|
||||
"authToChangeEmailVerificationSetting": "Por favor, autentícate para cambiar tu correo electrónico",
|
||||
"authenticateGeneric": "Por favor, autentícate",
|
||||
"authToViewYourRecoveryKey": "Por favor, autentícate para ver tu clave de recuperación",
|
||||
@@ -160,7 +160,7 @@
|
||||
"recoverAccount": "Recuperar cuenta",
|
||||
"enterRecoveryKeyHint": "Introduce tu clave de recuperación",
|
||||
"recover": "Recuperar",
|
||||
"contactSupportViaEmailMessage": "Por favor, envía un email a {email} desde la dirección de correo electrónico que usó durante el registro",
|
||||
"contactSupportViaEmailMessage": "Por favor, envía un correo electrónico a {email} desde la dirección de correo electrónico que usó durante el registro",
|
||||
"@contactSupportViaEmailMessage": {
|
||||
"placeholders": {
|
||||
"email": {
|
||||
@@ -258,6 +258,10 @@
|
||||
"areYouSureYouWantToLogout": "¿Seguro que quieres cerrar la sesión?",
|
||||
"yesLogout": "Sí, cerrar la sesión",
|
||||
"exit": "Salir",
|
||||
"theme": "Tema",
|
||||
"lightTheme": "Claro",
|
||||
"darkTheme": "Oscuro",
|
||||
"systemTheme": "Sistema",
|
||||
"verifyingRecoveryKey": "Verificando clave de recuperación...",
|
||||
"recoveryKeyVerified": "Clave de recuperación verificada",
|
||||
"recoveryKeySuccessBody": "¡Genial! Su clave de recuperación es válida. Gracias por verificar.\n\nPor favor, recuerde mantener su clave de recuperación segura.",
|
||||
@@ -317,7 +321,7 @@
|
||||
"checkInboxAndSpamFolder": "Por favor revisa tu bandeja de entrada (y spam) para completar la verificación",
|
||||
"tapToEnterCode": "Toca para introducir el código",
|
||||
"resendEmail": "Reenviar correo electrónico",
|
||||
"weHaveSendEmailTo": "Hemos enviado un correo a <green>{email}</green>",
|
||||
"weHaveSendEmailTo": "Hemos enviado un correo electrónico a <green>{email}</green>",
|
||||
"@weHaveSendEmailTo": {
|
||||
"description": "Text to indicate that we have sent a mail to the user",
|
||||
"placeholders": {
|
||||
@@ -483,7 +487,7 @@
|
||||
"hideContentDescriptioniOS": "Ocultar el contenido de la aplicación en el selector de aplicaciones",
|
||||
"autoLockFeatureDescription": "Tiempo tras el cual la aplicación se bloquea después de ser colocada en segundo plano",
|
||||
"appLockDescription": "Elija entre la pantalla de bloqueo por defecto de su dispositivo y una pantalla de bloqueo personalizada con un PIN o contraseña.",
|
||||
"pinLock": "Bloqueo con Pin",
|
||||
"pinLock": "Bloqueo con PIN",
|
||||
"enterPin": "Ingresa el PIN",
|
||||
"setNewPin": "Establecer nuevo PIN",
|
||||
"importFailureDescNew": "No se pudo analizar el archivo seleccionado.",
|
||||
@@ -497,5 +501,6 @@
|
||||
"deduplicateCodes": "Desduplicar códigos",
|
||||
"deselectAll": "Deseleccionar todo",
|
||||
"selectAll": "Seleccionar todo",
|
||||
"deleteDuplicates": "Eliminar duplicados"
|
||||
"deleteDuplicates": "Eliminar duplicados",
|
||||
"plainHTML": "HTML plano"
|
||||
}
|
||||
@@ -1,16 +1,16 @@
|
||||
{
|
||||
"account": "Akun\n",
|
||||
"account": "Akun",
|
||||
"unlock": "Buka",
|
||||
"recoveryKey": "Kunci pemulihan",
|
||||
"counterAppBarTitle": "Pencacah",
|
||||
"counterAppBarTitle": "Penghitung",
|
||||
"@counterAppBarTitle": {
|
||||
"description": "Text shown in the AppBar of the Counter Page"
|
||||
},
|
||||
"onBoardingBody": "Cadangkan kode autentikasi 2 langkah Anda dengan aman",
|
||||
"onBoardingBody": "Cadangkan kode 2FA Anda dengan aman",
|
||||
"onBoardingGetStarted": "Mulai",
|
||||
"setupFirstAccount": "Siapkan akun pertama Anda",
|
||||
"importScanQrCode": "Pindai Kode Respons Cepat (QR)",
|
||||
"qrCode": "Kode Respons Cepat (QR)",
|
||||
"importScanQrCode": "Pindai Kode QR",
|
||||
"qrCode": "Kode QR",
|
||||
"importEnterSetupKey": "Masukkan kunci penyiapan",
|
||||
"importAccountPageTitle": "Masukkan rincian akun",
|
||||
"secretCanNotBeEmpty": "Rahasia tidak boleh kosong",
|
||||
@@ -22,7 +22,7 @@
|
||||
"secret": "Rahasia",
|
||||
"all": "Semua",
|
||||
"notes": "Catatan",
|
||||
"notesLengthLimit": "Banyaknya karakter pada catatan yang diperbolehkan paling banyak adalah sebanyak {count} karakter",
|
||||
"notesLengthLimit": "Catatan dapat memiliki panjang maksimal {count} karakter",
|
||||
"@notesLengthLimit": {
|
||||
"description": "Text to indicate the maximum number of characters allowed for notes",
|
||||
"placeholders": {
|
||||
@@ -33,29 +33,29 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"codeAccountHint": "Akun (nama@domain.com)",
|
||||
"codeAccountHint": "Akun (anda@domain.com)",
|
||||
"codeTagHint": "Tag",
|
||||
"accountKeyType": "Jenis kunci",
|
||||
"sessionExpired": "Sesi berakhir",
|
||||
"@sessionExpired": {
|
||||
"description": "Title of the dialog when the users current session is invalid/expired"
|
||||
},
|
||||
"pleaseLoginAgain": "Silakan masuk akun lagi",
|
||||
"loggingOut": "Keluar dari akun...",
|
||||
"pleaseLoginAgain": "Silakan masuk lagi",
|
||||
"loggingOut": "Mengeluarkan akun...",
|
||||
"timeBasedKeyType": "Berbasis waktu (TOTP)",
|
||||
"counterBasedKeyType": "Berbasis pencacah (HOTP)",
|
||||
"counterBasedKeyType": "Berbasis Penghitung (HOTP)",
|
||||
"saveAction": "Simpan",
|
||||
"nextTotpTitle": "berikutnya",
|
||||
"deleteCodeTitle": "Hapus kode?",
|
||||
"deleteCodeMessage": "Anda yakin ingin menghapus kode ini? Tindakan ini tidak dapat dikembalikan ke semula.",
|
||||
"deleteCodeMessage": "Apakah Anda yakin ingin menghapus kode ini? Tindakan ini tidak dapat dibatalkan.",
|
||||
"trashCode": "Hapus kode?",
|
||||
"trashCodeMessage": "Anda yakin ingin menghapus kode untuk akun {account}?",
|
||||
"trashCodeMessage": "Apakah anda yakin ingin menghapus kode untuk {account}?",
|
||||
"trash": "Hapus",
|
||||
"viewLogsAction": "Lihat log",
|
||||
"sendLogsDescription": "Langkah ini akan mengirimkan log untuk membantu kami menyelesaikan masalah Anda. Kami menyarankan Anda untuk meninjau log-log berikut sebelum dibagikan walaupun kami sudah berupaya untuk memastikan agar segala informasi yang bersifat sensitif tidak terlog.",
|
||||
"preparingLogsTitle": "Menyiapkan log...",
|
||||
"emailLogsTitle": "Log surel",
|
||||
"emailLogsMessage": "Harap kirim log ke {email}",
|
||||
"viewLogsAction": "Lihat catatan",
|
||||
"sendLogsDescription": "Ini akan mengirimkan catatan untuk membantu kami memecahkan masalah Anda. Meskipun kami mengambil langkah-langkah untuk memastikan informasi sensitif tidak tercatat, kami menyarankan Anda untuk melihat catatan ini sebelum membagikannya.",
|
||||
"preparingLogsTitle": "Menyiapkan catatan...",
|
||||
"emailLogsTitle": "Catatan email",
|
||||
"emailLogsMessage": "Harap kirim catatan ke {email}",
|
||||
"@emailLogsMessage": {
|
||||
"placeholders": {
|
||||
"email": {
|
||||
@@ -63,12 +63,12 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"copyEmailAction": "Salin surel",
|
||||
"exportLogsAction": "Ekspor log",
|
||||
"reportABug": "Laporkan keberadaan kutu",
|
||||
"crashAndErrorReporting": "Pelaporan Galat dan Kemogokan",
|
||||
"reportBug": "Laporkan kutu",
|
||||
"emailUsMessage": "Harap kirimkan surel ke {email}",
|
||||
"copyEmailAction": "Salin alamat email",
|
||||
"exportLogsAction": "Ekspor catatan",
|
||||
"reportABug": "Laporkan bug",
|
||||
"crashAndErrorReporting": "Pelaporan Kerusakan & Kesalahan",
|
||||
"reportBug": "Laporkan bug",
|
||||
"emailUsMessage": "Harap kirim email kepada kami di {email}",
|
||||
"@emailUsMessage": {
|
||||
"placeholders": {
|
||||
"email": {
|
||||
@@ -76,91 +76,91 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"contactSupport": "Hubungi bantuan",
|
||||
"rateUsOnStore": "Beri kami penilaian di {storeName}",
|
||||
"contactSupport": "Hubungi dukungan",
|
||||
"rateUsOnStore": "Nilai kami di {storeName}",
|
||||
"blog": "Blog",
|
||||
"merchandise": "Toko kami",
|
||||
"merchandise": "Merchandise",
|
||||
"verifyPassword": "Verifikasi kata sandi",
|
||||
"pleaseWait": "Mohon tunggu...",
|
||||
"generatingEncryptionKeysTitle": "Membuat kunci enkripsi...",
|
||||
"generatingEncryptionKeysTitle": "Sedang membuat kunci enkripsi...",
|
||||
"recreatePassword": "Buat ulang kata sandi",
|
||||
"recreatePasswordMessage": "Gawai ini tidak cukup mutakhir untuk memverifikasi kata sandi Anda, sehingga kami perlu membuat ulang kata sandi Anda sekali lagi dengan cara yang dapat digunakan di semua perangkat.\n\nSilakan masuk dengan kunci pemulihan dan buat ulang kata sandi Anda (Gunakan kata sandi yang sama lagi jika Anda mau).",
|
||||
"recreatePasswordMessage": "Perangkat saat ini tidak cukup kuat untuk memverifikasi kata sandi Anda, jadi kami perlu membuat ulang kata sandi Anda dengan cara yang dapat digunakan di semua perangkat.\n\nHarap masuk menggunakan kunci pemulihan Anda dan buat ulang kata sandi Anda (Anda dapat menggunakan yang sama lagi jika diinginkan).",
|
||||
"useRecoveryKey": "Gunakan kunci pemulihan",
|
||||
"incorrectPasswordTitle": "Kata sandi salah",
|
||||
"welcomeBack": "Selamat datang kembali!",
|
||||
"madeWithLoveAtPrefix": "dibuat dengan ❤️ di ",
|
||||
"supportDevs": "Berlangganan <bold-green>ente</bold-green> untuk memberikan kami dukungan",
|
||||
"supportDiscount": "Gunakan kode kupon \"AUTH\" untuk mendapatkan diskon 10% pada tahun Anda berlangganan",
|
||||
"changeEmail": "Ubah surel",
|
||||
"supportDevs": "Berlangganan <bold-green>ente</bold-green> untuk mendukung kami",
|
||||
"supportDiscount": "Gunakan kode kupon \"AUTH\" untuk mendapatkan potongan 10% untuk tahun pertama",
|
||||
"changeEmail": "Ubah alamat email",
|
||||
"changePassword": "Ubah kata sandi",
|
||||
"data": "Data",
|
||||
"importCodes": "Impor kode",
|
||||
"importTypePlainText": "Teks biasa",
|
||||
"importTypeEnteEncrypted": "Eksporan Ente Terenkripsi",
|
||||
"passwordForDecryptingExport": "Kata sandi untuk mendekripsi eksporan",
|
||||
"passwordForDecryptingExport": "Kata sandi untuk mendekripsi ekspor",
|
||||
"passwordEmptyError": "Kata sandi tidak boleh kosong",
|
||||
"importFromApp": "Impor kode dari {appName}",
|
||||
"importGoogleAuthGuide": "Ekspor semua akun Anda dari Google Authenticator ke kode respons cepat (QR) dengan pilihan \"Transfer Akun\". Kemudian, pindai kode respons cepat tersebut dengan perangkat lain.\n\nKiat: webcam laptop juga dapat digunakan untuk untuk memindai kode respons cepat.",
|
||||
"importGoogleAuthGuide": "Ekspor akun Anda dari Google Authenticator ke kode QR menggunakan opsi \"Transfer Akun\". Kemudian, gunakan perangkat lain untuk memindai kode QR tersebut.\n\nTip: Anda bisa menggunakan webcam laptop Anda untuk memotret kode QR.",
|
||||
"importSelectJsonFile": "Pilih berkas JSON",
|
||||
"importSelectAppExport": "Pilih berkas eksporan dari {appName}",
|
||||
"importEnteEncGuide": "Pilih berkas JSON terenkripsi yang telah diekspor dari Ente",
|
||||
"importRaivoGuide": "Gunakan pilihan \"Export OTPs to Zip archive\" pada pengaturan Raivo.\n\nEkstrak berkas zip dan impor berkas JSON tersebut.",
|
||||
"importBitwardenGuide": "Gunakan pilihan \"Export vault\" pada Bitwarden Tools dan impor ber JSON yang takterenkripsi.",
|
||||
"importAegisGuide": "Gunakan pilihan \"Export vault\" pada pengaturan Aegis.\n\nJika brankas terenkripsi, masukkan kata sandi brankas untuk mendekripsi brankas.",
|
||||
"import2FasGuide": "Gunakan pilihan \"Pengaturan->Cadangkan -Eksport\" pada 2FAS.\n\nJika cadangan Anda dienkripsi, kata sandi akan Anda perlukan untuk mendekripsi cadangan",
|
||||
"importLastpassGuide": "Gunakan pilihan \"Transfer accounts\" pada pengaturan Lastpass Authenticator dan tekan \"Export accounts to file\". Impor berkas JSON terunduh.",
|
||||
"exportCodes": "Kode pengeksporan",
|
||||
"importEnteEncGuide": "Pilih file enkripsi JSON yang telah diekspor dari Ente",
|
||||
"importRaivoGuide": "Gunakan opsi \"Export OTPs to Zip archive\" pada pengaturan Raivo.\n\nEkstrak file zip dan impor file JSON tersebut.",
|
||||
"importBitwardenGuide": "Gunakan opsi \"Export vault\" di Bitwarden dan impor file JSON yang tidak terenkripsi.",
|
||||
"importAegisGuide": "Gunakan opsi \"Export the vault\" di Pengaturan Aegis.\n\nJika brankas Anda terenkripsi, Anda perlu memasukkan kata sandi brankas untuk mendekripsi brankas.",
|
||||
"import2FasGuide": "Gunakan opsi \"Settings->Backup -Export\" di 2FAS.\n\nJika cadangan Anda terenkripsi, Anda perlu memasukkan kata sandi untuk mendekripsi cadangan",
|
||||
"importLastpassGuide": "Gunakan opsi \"Transfer accounts\" di Pengaturan Lastpass Authenticator dan tekan \"Export accounts to file\". Impor file JSON yang diunduh.",
|
||||
"exportCodes": "Ekspor kode",
|
||||
"importLabel": "Impor",
|
||||
"importInstruction": "Mohon pilih berkas yang mengandung daftar kode dalam format seperti berikut",
|
||||
"importCodeDelimiterInfo": "Kode dapat dipisahkan oleh tanda koma atau baris baru",
|
||||
"importInstruction": "Harap pilih file yang berisi daftar kode Anda dalam format berikut",
|
||||
"importCodeDelimiterInfo": "Kode dapat dipisahkan dengan koma atau baris baru",
|
||||
"selectFile": "Pilih file",
|
||||
"emailVerificationToggle": "Verifikasi surel",
|
||||
"emailVerificationEnableWarning": "Agar tidak akun Anda tidak terkunci, pastikan simpan salinan pengaturan 2FA surel Anda di luar aplikasi Ente Auth sebelum verifikasi surel Anda nyalakan.",
|
||||
"authToChangeEmailVerificationSetting": "Mohon autentikasikan untuk mengubah verifikasi surel",
|
||||
"authenticateGeneric": "Mohon autentikasikan",
|
||||
"authToViewYourRecoveryKey": "Mohon autentikasikan untuk menampilkan kunci pemulihan",
|
||||
"authToChangeYourEmail": "Moohn autentikasikan untuk mengubah surel",
|
||||
"authToChangeYourPassword": "Mohon autentikasikan untuk mengubah kata sandi",
|
||||
"authToViewSecrets": "Mohon autentikasikan untuk menampilkan RahasiaKu",
|
||||
"authToInitiateSignIn": "Mohon autentikasikan untuk memulai proses pencadangan.",
|
||||
"emailVerificationToggle": "Verifikasi email",
|
||||
"emailVerificationEnableWarning": "Untuk menghindari terkunci dari akun Anda, pastikan untuk menyimpan salinan 2FA email Anda di luar Ente Auth sebelum mengaktifkan verifikasi email.",
|
||||
"authToChangeEmailVerificationSetting": "Harap lakukan autentikasi untuk mengubah verifikasi email",
|
||||
"authenticateGeneric": "Harap lakukan autentikasi",
|
||||
"authToViewYourRecoveryKey": "Harap lakukan autentikasi untuk melihat kunci pemulihan Anda",
|
||||
"authToChangeYourEmail": "Harap lakukan autentikasi untuk mengubah email Anda",
|
||||
"authToChangeYourPassword": "Harap lakukan autentikasi untuk mengubah kata sandi Anda",
|
||||
"authToViewSecrets": "Harap lakukan autentikasi untuk melihat rahasia Anda",
|
||||
"authToInitiateSignIn": "Harap lakukan autentikasi untuk memulai proses masuk untuk pencadangan.",
|
||||
"ok": "Oke",
|
||||
"cancel": "Batal",
|
||||
"yes": "Ya",
|
||||
"no": "Tidak",
|
||||
"email": "Surel",
|
||||
"support": "Bantuan",
|
||||
"email": "Email",
|
||||
"support": "Dukungan",
|
||||
"general": "Umum",
|
||||
"settings": "Pengaturan",
|
||||
"copied": "Disalin",
|
||||
"pleaseTryAgain": "Mohon coba lagi",
|
||||
"existingUser": "Pengguna yang Sudah Ada",
|
||||
"pleaseTryAgain": "Harap coba lagi",
|
||||
"existingUser": "Pengguna yang ada",
|
||||
"newUser": "Baru di Ente",
|
||||
"delete": "Hapus",
|
||||
"enterYourPasswordHint": "Masukkan kata sandi Anda",
|
||||
"forgotPassword": "Lupa kata sandi",
|
||||
"oops": "Aduh",
|
||||
"oops": "Ups",
|
||||
"suggestFeatures": "Sarankan fitur",
|
||||
"faq": "Tanya Jawab Umum",
|
||||
"faq": "Pertanyaan yang sering ditanyakan",
|
||||
"somethingWentWrongMessage": "Terjadi kesalahan, silakan coba lagi",
|
||||
"leaveFamily": "Tinggalkan keluarga",
|
||||
"leaveFamilyMessage": "Anda yakin sudah tidak ingin berlangganan paket keluarga ini?",
|
||||
"leaveFamilyMessage": "Apakah Anda yakin sudah tidak ingin berlangganan paket keluarga ini?",
|
||||
"inFamilyPlanMessage": "Anda sedang berlangganan paket keluarga!",
|
||||
"hintForMobile": "Tekan lama kode untuk menyunting atau menghapus.",
|
||||
"hintForDesktop": "Klik kanan kode untuk menyunting atau menghapus.",
|
||||
"hintForMobile": "Tekan lama kode untuk mengedit atau menghapusnya.",
|
||||
"hintForDesktop": "Klik kanan kode untuk mengedit atau menghapus.",
|
||||
"scan": "Pindai",
|
||||
"scanACode": "Pindai kode",
|
||||
"verify": "Verifikasi",
|
||||
"verifyEmail": "Verifikasi email",
|
||||
"enterCodeHint": "Masukkan kode 6 angka pada aplikasi pengautentikasi Anda",
|
||||
"enterCodeHint": "Masukkan kode 6 digit dari aplikasi autentikator Anda",
|
||||
"lostDeviceTitle": "Perangkat hilang?",
|
||||
"twoFactorAuthTitle": "Autentikasi dua langkah",
|
||||
"passkeyAuthTitle": "Verifikasi passkey",
|
||||
"verifyPasskey": "Verifikasi passkey",
|
||||
"loginWithTOTP": "Login menggunakan TOTP",
|
||||
"loginWithTOTP": "Masuk menggunakan TOTP",
|
||||
"recoverAccount": "Pulihkan akun",
|
||||
"enterRecoveryKeyHint": "Masukkan kunci pemulihanmu",
|
||||
"enterRecoveryKeyHint": "Masukkan kunci pemulihan Anda",
|
||||
"recover": "Pulihkan",
|
||||
"contactSupportViaEmailMessage": "Silakan kirimkan surel ke {email} dari alamat surelmu yang terdaftar",
|
||||
"contactSupportViaEmailMessage": "Harap kirim email ke {email} dari alamat email terdaftar Anda",
|
||||
"@contactSupportViaEmailMessage": {
|
||||
"placeholders": {
|
||||
"email": {
|
||||
@@ -168,13 +168,13 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"invalidQRCode": "Kode QR tidak sah",
|
||||
"invalidQRCode": "Kode QR tidak valid",
|
||||
"noRecoveryKeyTitle": "Tidak punya kunci pemulihan?",
|
||||
"enterEmailHint": "Masukkan alamat surelmu",
|
||||
"invalidEmailTitle": "Alamat surel tidak sah",
|
||||
"invalidEmailMessage": "Harap masukkan alamat surel yang sah.",
|
||||
"enterEmailHint": "Masukkan alamat email Anda",
|
||||
"invalidEmailTitle": "Alamat email tidak valid",
|
||||
"invalidEmailMessage": "Harap masukkan alamat email yang valid.",
|
||||
"deleteAccount": "Hapus akun",
|
||||
"deleteAccountQuery": "Sayang sekali Anda harus pergi. Apakah ada masalah?",
|
||||
"deleteAccountQuery": "Kami akan merasa kehilangan Anda. Apakah Anda menghadapi masalah?",
|
||||
"yesSendFeedbackAction": "Ya, kirim umpan balik",
|
||||
"noDeleteAccountAction": "Tidak, hapus akun",
|
||||
"initiateAccountDeleteTitle": "Harap autentikasi untuk memulai penghapusan akun",
|
||||
@@ -183,37 +183,37 @@
|
||||
"weakStrength": "Lemah",
|
||||
"strongStrength": "Kuat",
|
||||
"moderateStrength": "Sedang",
|
||||
"confirmPassword": "Konfirmasi sandi",
|
||||
"confirmPassword": "Konfirmasi kata sandi",
|
||||
"close": "Tutup",
|
||||
"oopsSomethingWentWrong": "Ups, sepertinya ada yang salah.",
|
||||
"oopsSomethingWentWrong": "Ups, Ada yang tidak beres.",
|
||||
"selectLanguage": "Pilih bahasa",
|
||||
"language": "Bahasa",
|
||||
"social": "Sosial",
|
||||
"security": "Keamanan",
|
||||
"lockscreen": "Layar kunci",
|
||||
"authToChangeLockscreenSetting": "Mohon autentikan untuk mengganti pengaturan layar kunci",
|
||||
"authToChangeLockscreenSetting": "Harap lakukan autentikasi untuk mengubah pengaturan layar kunci",
|
||||
"deviceLockEnablePreSteps": "Pasang kunci sandi atau kunci layar pada pengaturan sistem untuk menyalakan Pengunci Gawai.",
|
||||
"viewActiveSessions": "Tampilkan sesi yang aktif",
|
||||
"authToViewYourActiveSessions": "Mohon autentikasikan untuk menampilkan sesi aktif Anda",
|
||||
"viewActiveSessions": "Lihat sesi aktif",
|
||||
"authToViewYourActiveSessions": "Harap lakukan autentikasi untuk melihat sesi aktif Anda",
|
||||
"searchHint": "Cari...",
|
||||
"search": "Cari",
|
||||
"sorryUnableToGenCode": "Maaf, kami tidak dapat membuat kode untuk {issuerName}",
|
||||
"noResult": "Tiada hasil",
|
||||
"sorryUnableToGenCode": "Maaf, tidak dapat menghasilkan kode untuk {issuerName}",
|
||||
"noResult": "Tidak ada hasil",
|
||||
"addCode": "Tambahkan kode",
|
||||
"scanAQrCode": "Pindai kode Respons Cepat (QR)",
|
||||
"scanAQrCode": "Pindai kode QR",
|
||||
"enterDetailsManually": "Masukkan rincian secara manual",
|
||||
"edit": "Sunting",
|
||||
"edit": "Edit",
|
||||
"share": "Bagikan",
|
||||
"shareCodes": "Bagikan kode",
|
||||
"shareCodesDuration": "Pilih durasi untuk membagikan kode.",
|
||||
"shareCodesDuration": "Pilih durasi untuk berbagi kode.",
|
||||
"restore": "Pulihkan",
|
||||
"copiedToClipboard": "Tersalin ke papan klip",
|
||||
"copiedNextToClipboard": "",
|
||||
"error": "Galat",
|
||||
"recoveryKeyCopiedToClipboard": "Kunci pemulihan tersalin ke papan klip",
|
||||
"recoveryKeyOnForgotPassword": "Jika Anda lupa kata sandi Anda, satu-satunya cara untuk memulihkan data Anda adalah dengan kunci ini.",
|
||||
"recoveryKeySaveDescription": "Kami tidak menyimpan kunci ini, tolong simpan kunci berisikan 24 kata ini di tempat yang aman.",
|
||||
"doThisLater": "Nanti saja",
|
||||
"copiedToClipboard": "Disalin ke papan klip",
|
||||
"copiedNextToClipboard": "Kode berikutnya telah disalin ke papan klip",
|
||||
"error": "Kesalahan",
|
||||
"recoveryKeyCopiedToClipboard": "Kunci pemulihan disalin ke papan klip",
|
||||
"recoveryKeyOnForgotPassword": "Jika Anda lupa kata sandi, satu-satunya cara memulihkan data Anda adalah dengan kunci ini.",
|
||||
"recoveryKeySaveDescription": "Kami tidak menyimpan kunci ini, jadi harap simpan kunci yang berisi 24 kata ini dengan aman.",
|
||||
"doThisLater": "Lakukan lain kali",
|
||||
"saveKey": "Simpan kunci",
|
||||
"save": "Simpan",
|
||||
"send": "Kirim",
|
||||
@@ -248,7 +248,7 @@
|
||||
"passwordChangedSuccessfully": "Kata sandi sukses diubah",
|
||||
"generatingEncryptionKeys": "Sedang membuat kunci enkripsi...",
|
||||
"continueLabel": "Lanjutkan",
|
||||
"insecureDevice": "Gawai takaman",
|
||||
"insecureDevice": "Perangkat tidak aman",
|
||||
"sorryWeCouldNotGenerateSecureKeysOnThisDevicennplease": "Maaf, kami tidak dapat membuat kunci yang aman pada perangkat ini.\n\nHarap mendaftar dengan perangkat lain.",
|
||||
"howItWorks": "Cara kerjanya",
|
||||
"ackPasswordLostWarning": "Saya mengerti bahwa jika saya lupa kata sandi saya, data saya dapat hilang karena data saya <underline>terenkripsi secara end-to-end</underline>.",
|
||||
@@ -258,6 +258,10 @@
|
||||
"areYouSureYouWantToLogout": "Anda yakin ingin keluar dari akun ini?",
|
||||
"yesLogout": "Ya, keluar akun",
|
||||
"exit": "Keluar",
|
||||
"theme": "Tema",
|
||||
"lightTheme": "Terang",
|
||||
"darkTheme": "Gelap",
|
||||
"systemTheme": "Sistem",
|
||||
"verifyingRecoveryKey": "Memverifikasi kunci pemulihan...",
|
||||
"recoveryKeyVerified": "Kunci pemulihan terverifikasi",
|
||||
"recoveryKeySuccessBody": "Bagus! Kunci pemulihan ada valid. Terima kasih.\n\nMohon ingat-ingat untuk mencadangkan kunci pemulihan Anda dengan aman.",
|
||||
@@ -391,7 +395,7 @@
|
||||
"@androidCancelButton": {
|
||||
"description": "Message showed on a button that the user can click to leave the current dialog. It is used on Android side. Maximum 30 characters."
|
||||
},
|
||||
"androidSignInTitle": "Autentikasi",
|
||||
"androidSignInTitle": "Autentikasi diperlukan",
|
||||
"@androidSignInTitle": {
|
||||
"description": "Message showed as a title in a dialog which indicates the user that they need to scan biometric to continue. It is used on Android side. Maximum 60 characters."
|
||||
},
|
||||
@@ -399,15 +403,15 @@
|
||||
"@androidBiometricRequiredTitle": {
|
||||
"description": "Message showed as a title in a dialog which indicates the user has not set up biometric authentication on their device. It is used on Android side. Maximum 60 characters."
|
||||
},
|
||||
"androidDeviceCredentialsRequiredTitle": "Kredensial gawal diperlukan",
|
||||
"androidDeviceCredentialsRequiredTitle": "Kredensial perangkat diperlukan",
|
||||
"@androidDeviceCredentialsRequiredTitle": {
|
||||
"description": "Message showed as a title in a dialog which indicates the user has not set up credentials authentication on their device. It is used on Android side. Maximum 60 characters."
|
||||
},
|
||||
"androidDeviceCredentialsSetupDescription": "Kredensial gawal diperlukan",
|
||||
"androidDeviceCredentialsSetupDescription": "Kredensial perangkat diperlukan",
|
||||
"@androidDeviceCredentialsSetupDescription": {
|
||||
"description": "Message advising the user to go to the settings and configure device credentials on their device. It shows in a dialog on Android side."
|
||||
},
|
||||
"goToSettings": "Ke pengaturan",
|
||||
"goToSettings": "Pergi ke pengaturan",
|
||||
"@goToSettings": {
|
||||
"description": "Message showed on a button that the user can click to go to settings pages from the current dialog. It is used on both Android and iOS side. Maximum 30 characters."
|
||||
},
|
||||
@@ -447,45 +451,56 @@
|
||||
"serverEndpoint": "Peladen endpoint",
|
||||
"invalidEndpoint": "Endpoint takvalid",
|
||||
"invalidEndpointMessage": "Maaf, endpoint yang Anda masukkan takvalid. Mohon masukkan endpoint yang valid, lalu coba kembali.",
|
||||
"endpointUpdatedMessage": "Endpoint sukses dimutakhirkan",
|
||||
"customEndpoint": "Terkoneksi ke {endpoint}",
|
||||
"endpointUpdatedMessage": "Endpoint berhasil diubah",
|
||||
"customEndpoint": "Terhubung ke {endpoint}",
|
||||
"pinText": "Sematkan",
|
||||
"unpinText": "Awasematkan",
|
||||
"pinnedCodeMessage": "{code} telah disematkan",
|
||||
"unpinnedCodeMessage": "{code} telah dilepas",
|
||||
"pinned": "Disematkan",
|
||||
"tags": "Tanda",
|
||||
"createNewTag": "Buat Tanda Baru",
|
||||
"tag": "Tanda",
|
||||
"create": "Buat",
|
||||
"editTag": "Sunting tanda",
|
||||
"editTag": "Ubah tanda",
|
||||
"deleteTagTitle": "Hapus tanda?",
|
||||
"deleteTagMessage": "Anda yakin ingin menghapus tanda? Langkah ini tidak akan dapat dikembalikan seperti semula.",
|
||||
"deleteTagMessage": "Apakah Anda yakin ingin menghapus tanda ini? Tindakan ini tidak dapat dibatalkan.",
|
||||
"somethingWentWrongParsingCode": "Kode {x} tidak dapat kami urai.",
|
||||
"updateNotAvailable": "Pemutakhiran tidak tersedia",
|
||||
"viewRawCodes": "Tampilkan kode mentahan",
|
||||
"rawCodes": "Kode mentahan",
|
||||
"rawCodeData": "Data kode mentahan",
|
||||
"appLock": "Pengunci Apl",
|
||||
"noSystemLockFound": "Pengunci sistem tidak ditemukan",
|
||||
"toEnableAppLockPleaseSetupDevicePasscodeOrScreen": "Untuk menyalakan Pengunci Apl, mohon pasang kode sandi atau kunci layar di pengaturan sistem gawai Anda",
|
||||
"autoLock": "Autokunci",
|
||||
"immediately": "Dengan segera",
|
||||
"updateNotAvailable": "Pembaruan tidak tersedia",
|
||||
"viewRawCodes": "Lihat kode mentah",
|
||||
"rawCodes": "Kode mentah",
|
||||
"rawCodeData": "Data kode mentah",
|
||||
"appLock": "Kunci aplikasi",
|
||||
"noSystemLockFound": "Tidak ditemukan kunci sistem",
|
||||
"toEnableAppLockPleaseSetupDevicePasscodeOrScreen": "Untuk mengaktifkan kunci aplikasi, harap atur kode sandi perangkat atau kunci layar di pengaturan sistem Anda.",
|
||||
"autoLock": "Kunci otomatis",
|
||||
"immediately": "Segera",
|
||||
"reEnterPassword": "Masukkan kembali kata sandi",
|
||||
"reEnterPin": "Masukkan kembali PIN",
|
||||
"next": "Selanjutnya",
|
||||
"tooManyIncorrectAttempts": "Terlalu banyak percobaan yang salah",
|
||||
"tapToUnlock": "Ketuk untuk membuka",
|
||||
"setNewPassword": "Pasang kata sandi baru",
|
||||
"deviceLock": "Pengunci bawaan gawai",
|
||||
"deviceLock": "Kunci perangkat",
|
||||
"hideContent": "Sembunyikan isi",
|
||||
"hideContentDescriptionAndroid": "Sembunyikan isi aplikasi pada pengganti apl dan matikan penangkap layar",
|
||||
"hideContentDescriptioniOS": "Sembunyikan isi aplikasi di pengganti apl",
|
||||
"hideContentDescriptionAndroid": "Menyembunyikan konten aplikasi di pemilih aplikasi dan menonaktifkan tangkapan layar",
|
||||
"hideContentDescriptioniOS": "Menyembunyikan konten aplikasi di pemilih aplikasi",
|
||||
"autoLockFeatureDescription": "Durasi waktu aplikasi akan terkunci setelah aplikasi ditutup",
|
||||
"appLockDescription": "Pilih layar kunci bawaan gawai Anda ATAU layar kunci kustom dengan PIN atau kata sandi.",
|
||||
"pinLock": "PIN",
|
||||
"enterPin": "Masukkan PIN",
|
||||
"setNewPin": "Pasang PIN yang baru",
|
||||
"importFailureDescNew": "Berkas yang dipilih tidak dapat diurai",
|
||||
"appLockNotEnabled": "Pengunci Apl tidak dinyalakan",
|
||||
"appLockNotEnabled": "Kunci aplikasi tidak diaktifkan",
|
||||
"appLockNotEnabledDescription": "Mohon nyalakan pengunci apl di Keamanan > Pengunci Apl",
|
||||
"authToViewPasskey": "Mohon autentikasikan untuk menampilkan kunci sandi",
|
||||
"appLockOfflineModeWarning": "Anda telah memilih untuk mengunci aplikasi tanpa cadangan apa pun. Jika Anda lupa kode Pengunci Apl Anda, Anda tidak akan dapat mengakses data-data Anda."
|
||||
"appLockOfflineModeWarning": "Anda telah memilih untuk mengunci aplikasi tanpa cadangan apa pun. Jika Anda lupa kode Pengunci Apl Anda, Anda tidak akan dapat mengakses data-data Anda.",
|
||||
"duplicateCodes": "Kode duplikat",
|
||||
"noDuplicates": "✨ Tak ada duplikat",
|
||||
"youveNoDuplicateCodesThatCanBeCleared": "Kamu tidak memiliki kode duplikat yang dapat dihapus",
|
||||
"deduplicateCodes": "Hapus kode duplikat",
|
||||
"deselectAll": "Batalkan semua pilihan",
|
||||
"selectAll": "Pilih semua",
|
||||
"deleteDuplicates": "Hapus duplikat",
|
||||
"plainHTML": "HTML Sederhana"
|
||||
}
|
||||
@@ -258,6 +258,10 @@
|
||||
"areYouSureYouWantToLogout": "Sei sicuro di volerti disconnettere?",
|
||||
"yesLogout": "Si, effettua la disconnessione",
|
||||
"exit": "Esci",
|
||||
"theme": "Tema",
|
||||
"lightTheme": "Chiaro",
|
||||
"darkTheme": "Scuro",
|
||||
"systemTheme": "Sistema",
|
||||
"verifyingRecoveryKey": "Verifica della chiave di recupero...",
|
||||
"recoveryKeyVerified": "Chiave di recupero verificata",
|
||||
"recoveryKeySuccessBody": "Ottimo! La tua chiave di recupero è valida. Grazie per averla verificata.\n\nRicordati di effettuare il backup sicuro della tua chiave di recupero.",
|
||||
@@ -497,5 +501,6 @@
|
||||
"deduplicateCodes": "Codici deduplicati",
|
||||
"deselectAll": "Deselezionare tutti",
|
||||
"selectAll": "Seleziona tutti",
|
||||
"deleteDuplicates": "Elimina i duplicati"
|
||||
"deleteDuplicates": "Elimina i duplicati",
|
||||
"plainHTML": "HTML semplice"
|
||||
}
|
||||
@@ -258,6 +258,10 @@
|
||||
"areYouSureYouWantToLogout": "로그아웃 하시겠습니까?",
|
||||
"yesLogout": "네, 로그아웃하기",
|
||||
"exit": "나가기",
|
||||
"theme": "테마",
|
||||
"lightTheme": "라이트",
|
||||
"darkTheme": "다크",
|
||||
"systemTheme": "시스템",
|
||||
"verifyingRecoveryKey": "복구 키 확인 중...",
|
||||
"recoveryKeyVerified": "복구 키 확인 됨",
|
||||
"recoveryKeySuccessBody": "좋습니다! 복구 키가 확인되었습니다. 확인 절차를 거쳐주셔서 감사합니다.\n\n잊지 마시고 꼭 복구 키를 안전하게 보관해주세요.",
|
||||
@@ -490,5 +494,13 @@
|
||||
"appLockNotEnabled": "어플 잠금 설정되지 않음",
|
||||
"appLockNotEnabledDescription": "설정 > 어플 잠금에서 어플 잠금을 활성화해주세요",
|
||||
"authToViewPasskey": "패스키를 보려면 인증절차를 거쳐주세요",
|
||||
"appLockOfflineModeWarning": "백업 없이 진행하는 것을 선택하셨습니다. 어플 잠금 방법을 잊어버리신 경우, 데이터에 접근하실 수 없게 됩니다."
|
||||
"appLockOfflineModeWarning": "백업 없이 진행하는 것을 선택하셨습니다. 어플 잠금 방법을 잊어버리신 경우, 데이터에 접근하실 수 없게 됩니다.",
|
||||
"duplicateCodes": "중복된 코드",
|
||||
"noDuplicates": "✨ 중복 없음",
|
||||
"youveNoDuplicateCodesThatCanBeCleared": "지울 수 있는 중복 코드가 없습니다",
|
||||
"deduplicateCodes": "중복된 코드 제거",
|
||||
"deselectAll": "모두 선택 해제",
|
||||
"selectAll": "모두 선택",
|
||||
"deleteDuplicates": "중복 제거",
|
||||
"plainHTML": "일반 HTML"
|
||||
}
|
||||
@@ -258,6 +258,10 @@
|
||||
"areYouSureYouWantToLogout": "Ar tikrai norite atsijungti?",
|
||||
"yesLogout": "Taip, atsijungti",
|
||||
"exit": "Išeiti",
|
||||
"theme": "Tema",
|
||||
"lightTheme": "Šviesi",
|
||||
"darkTheme": "Tamsi",
|
||||
"systemTheme": "Sistemos",
|
||||
"verifyingRecoveryKey": "Patvirtinima atkūrimo raktą...",
|
||||
"recoveryKeyVerified": "Patvirtintas atkūrimo raktas",
|
||||
"recoveryKeySuccessBody": "Puiku! Jūsų atkūrimo raktas tinkamas. Dėkojame už patvirtinimą.\n\nNepamirškite sukurti saugią atkūrimo rakto atsarginę kopiją.",
|
||||
@@ -490,5 +494,13 @@
|
||||
"appLockNotEnabled": "Programos užraktas neįjungtas",
|
||||
"appLockNotEnabledDescription": "Įjunkite programos užraktą iš Saugumas > Programos užraktas",
|
||||
"authToViewPasskey": "Nustatykite tapatybę, kad peržiūrėtumėte slaptaraktį",
|
||||
"appLockOfflineModeWarning": "Pasirinkote tęsti be atsarginių kopijų. Jei pamiršite programos užraktą, jums bus užrakinta prieiga prie duomenų."
|
||||
"appLockOfflineModeWarning": "Pasirinkote tęsti be atsarginių kopijų. Jei pamiršite programos užraktą, jums bus užrakinta prieiga prie duomenų.",
|
||||
"duplicateCodes": "Dubliuoti kodus",
|
||||
"noDuplicates": "✨ Dublikatų nėra",
|
||||
"youveNoDuplicateCodesThatCanBeCleared": "Neturite dubliuotų kodų, kuriuos būtų galima išvalyti.",
|
||||
"deduplicateCodes": "Atdubliuoti kodus",
|
||||
"deselectAll": "Naikinti visų pasirinkimą",
|
||||
"selectAll": "Pasirinkti viską",
|
||||
"deleteDuplicates": "Ištrinti dublikatus",
|
||||
"plainHTML": "Grynasis HTML"
|
||||
}
|
||||
@@ -258,6 +258,10 @@
|
||||
"areYouSureYouWantToLogout": "Weet je zeker dat je wilt uitloggen?",
|
||||
"yesLogout": "Ja, uitloggen",
|
||||
"exit": "Afsluiten",
|
||||
"theme": "Thema",
|
||||
"lightTheme": "Licht",
|
||||
"darkTheme": "Donker",
|
||||
"systemTheme": "Systeem",
|
||||
"verifyingRecoveryKey": "Herstelsleutel verifiëren...",
|
||||
"recoveryKeyVerified": "Herstelsleutel geverifieerd",
|
||||
"recoveryKeySuccessBody": "Super! Je herstelsleutel is geldig. Bedankt voor het verifiëren.\n\nVergeet niet om je herstelsleutel veilig te bewaren.",
|
||||
@@ -490,5 +494,12 @@
|
||||
"appLockNotEnabled": "App-vergrendeling niet ingeschakeld",
|
||||
"appLockNotEnabledDescription": "Schakel app vergrendeling in vanuit Beveiliging > App vergrendeling",
|
||||
"authToViewPasskey": "Verifieer uzelf om uw passkey te bekijken",
|
||||
"appLockOfflineModeWarning": "Je hebt ervoor gekozen om verder te gaan zonder backups. Als je jouw applock vergeet, wordt je uitgesloten van toegang tot je gegevens."
|
||||
"appLockOfflineModeWarning": "Je hebt ervoor gekozen om verder te gaan zonder backups. Als je jouw applock vergeet, wordt je uitgesloten van toegang tot je gegevens.",
|
||||
"duplicateCodes": "Dubbele codes",
|
||||
"noDuplicates": "✨ Geen dubbele",
|
||||
"youveNoDuplicateCodesThatCanBeCleared": "Je hebt geen dubbele codes die kunnen worden gewist",
|
||||
"deduplicateCodes": "Dubbele codes",
|
||||
"deselectAll": "Alles deselecteren",
|
||||
"selectAll": "Alles selecteren",
|
||||
"deleteDuplicates": "Dubbelen verwijderen"
|
||||
}
|
||||
@@ -258,6 +258,10 @@
|
||||
"areYouSureYouWantToLogout": "Czy na pewno chcesz się wylogować?",
|
||||
"yesLogout": "Tak, wyloguj",
|
||||
"exit": "Wyjdź",
|
||||
"theme": "Motyw",
|
||||
"lightTheme": "Jasny",
|
||||
"darkTheme": "Ciemny",
|
||||
"systemTheme": "Systemowy",
|
||||
"verifyingRecoveryKey": "Weryfikowanie klucza odzyskiwania...",
|
||||
"recoveryKeyVerified": "Klucz odzyskiwania zweryfikowany",
|
||||
"recoveryKeySuccessBody": "Znakomicie! Klucz odzyskiwania jest prawidłowy. Dziękujemy za weryfikację.\n\nPamiętaj, aby bezpiecznie przechowywać kopię zapasową klucza odzyskiwania.",
|
||||
@@ -491,11 +495,12 @@
|
||||
"appLockNotEnabledDescription": "Prosimy włączyć blokadę aplikacji z Zabezpieczenia > Blokada aplikacji",
|
||||
"authToViewPasskey": "Prosimy uwierzytelnić się, aby wyświetlić klucz dostępu",
|
||||
"appLockOfflineModeWarning": "Wybrano kontynuowanie bez kopii zapasowych. Jeśli zapomnisz blokady aplikacji, utracisz dostęp do swoich danych.",
|
||||
"duplicateCodes": "Duplikuj kody",
|
||||
"duplicateCodes": "Zduplikowane kody",
|
||||
"noDuplicates": "✨ Brak duplikatów",
|
||||
"youveNoDuplicateCodesThatCanBeCleared": "Nie masz duplikatów kodów, które mogą być wyczyszczone",
|
||||
"deduplicateCodes": "Deduplikuj kody",
|
||||
"deselectAll": "Odznacz wszystko",
|
||||
"selectAll": "Zaznacz wszystko",
|
||||
"deleteDuplicates": "Usuń duplikaty"
|
||||
"deleteDuplicates": "Usuń duplikaty",
|
||||
"plainHTML": "Zwykły HTML"
|
||||
}
|
||||
@@ -11,7 +11,7 @@
|
||||
"setupFirstAccount": "Configure sua primeira conta",
|
||||
"importScanQrCode": "Escanear QR code",
|
||||
"qrCode": "QR Code",
|
||||
"importEnterSetupKey": "Insira uma chave de configuração",
|
||||
"importEnterSetupKey": "Inserir chave de config.",
|
||||
"importAccountPageTitle": "Inserir detalhes da conta",
|
||||
"secretCanNotBeEmpty": "A chave secreta não pode estar vazia",
|
||||
"bothIssuerAndAccountCanNotBeEmpty": "O emissor e a conta não podem estar vazios",
|
||||
@@ -40,16 +40,16 @@
|
||||
"@sessionExpired": {
|
||||
"description": "Title of the dialog when the users current session is invalid/expired"
|
||||
},
|
||||
"pleaseLoginAgain": "Entre novamente",
|
||||
"loggingOut": "Saindo...",
|
||||
"pleaseLoginAgain": "Registre-se novamente",
|
||||
"loggingOut": "Desconectando...",
|
||||
"timeBasedKeyType": "Baseado no horário (TOTP)",
|
||||
"counterBasedKeyType": "Baseado no contador (HOTP)",
|
||||
"saveAction": "Salvar",
|
||||
"nextTotpTitle": "avançar",
|
||||
"nextTotpTitle": "próximo",
|
||||
"deleteCodeTitle": "Excluir código?",
|
||||
"deleteCodeMessage": "Deseja mesmo excluir este código? Esta ação é irreversível.",
|
||||
"trashCode": "Excluir código?",
|
||||
"trashCodeMessage": "Você tem certeza de que quer excluir o código para {account}?",
|
||||
"trashCodeMessage": "Deseja mesmo excluir o código da {account}?",
|
||||
"trash": "Excluir",
|
||||
"viewLogsAction": "Ver registros",
|
||||
"sendLogsDescription": "Isso compartilhará seus dados para lhe ajudarmos a resolver seu problema. Enquanto tomamos precauções para ter certeza que as informações sensíveis não estejam registradas, nós encorajamos você a visualizar esses dados antes de compartilhá-los.",
|
||||
@@ -65,7 +65,7 @@
|
||||
},
|
||||
"copyEmailAction": "Copiar e-mail",
|
||||
"exportLogsAction": "Exportar registros",
|
||||
"reportABug": "Informe um erro",
|
||||
"reportABug": "Informar erro",
|
||||
"crashAndErrorReporting": "Relatórios de erros e falhas",
|
||||
"reportBug": "Informar erro",
|
||||
"emailUsMessage": "Envie um e-mail para {email}",
|
||||
@@ -77,7 +77,7 @@
|
||||
}
|
||||
},
|
||||
"contactSupport": "Contatar suporte",
|
||||
"rateUsOnStore": "Avalie nós na {storeName}",
|
||||
"rateUsOnStore": "Avalie-nos na {storeName}",
|
||||
"blog": "Blog",
|
||||
"merchandise": "Produtos",
|
||||
"verifyPassword": "Verificar senha",
|
||||
@@ -89,7 +89,7 @@
|
||||
"incorrectPasswordTitle": "Senha incorreta",
|
||||
"welcomeBack": "Bem-vindo(a) de volta!",
|
||||
"madeWithLoveAtPrefix": "feito com ❤️ em ",
|
||||
"supportDevs": "Inscreva-se no <bold-green>ente</bold-green> para nos apoiar",
|
||||
"supportDevs": "Inscreva-se no <bold-green>Ente</bold-green> para apoiar-nos",
|
||||
"supportDiscount": "Use o cupom \"AUTH\" para obter 10% de desconto no primeiro ano",
|
||||
"changeEmail": "Alterar e-mail",
|
||||
"changePassword": "Alterar senha",
|
||||
@@ -112,25 +112,25 @@
|
||||
"exportCodes": "Exportar códigos",
|
||||
"importLabel": "Importar",
|
||||
"importInstruction": "Selecione um arquivo que contenha uma lista de códigos no formato a seguir",
|
||||
"importCodeDelimiterInfo": "Os códigos podem ser separados por uma vírgula ou uma nova linha",
|
||||
"importCodeDelimiterInfo": "Códigos podem ser separados por vírgula ou uma nova linha",
|
||||
"selectFile": "Selecionar arquivo",
|
||||
"emailVerificationToggle": "Verificação por e-mail",
|
||||
"emailVerificationEnableWarning": "Para evitar ser bloqueado da sua conta, certifique-se de guardar uma cópia do seu e-mail 2FA fora do Ente Auth antes de ativar a verificação de e-mail.",
|
||||
"authToChangeEmailVerificationSetting": "Autentique-se para alterar a verificação de e-mail",
|
||||
"authenticateGeneric": "Autentique",
|
||||
"authToViewYourRecoveryKey": "Autentique para ver sua chave de recuperação",
|
||||
"authToChangeYourEmail": "Autentique para alterar o seu e-mail",
|
||||
"authToChangeYourPassword": "Autentique para alterar sua senha",
|
||||
"authToViewSecrets": "Autentique para ver suas chaves secretas",
|
||||
"authToInitiateSignIn": "Autentique para iniciar sessão para fazer uma cópia de segurança.",
|
||||
"ok": "OK",
|
||||
"authenticateGeneric": "Autentique-se",
|
||||
"authToViewYourRecoveryKey": "Autentique-se para ver sua chave de recuperação",
|
||||
"authToChangeYourEmail": "Autentique-se para alterar o seu e-mail",
|
||||
"authToChangeYourPassword": "Autentique-se para alterar sua senha",
|
||||
"authToViewSecrets": "Autentique-se para ver suas chaves secretas",
|
||||
"authToInitiateSignIn": "Autentique-se para registrar e fazer uma cópia de segurança.",
|
||||
"ok": "Ok",
|
||||
"cancel": "Cancelar",
|
||||
"yes": "Sim",
|
||||
"no": "Não",
|
||||
"email": "E-mail",
|
||||
"support": "Suporte",
|
||||
"general": "Geral",
|
||||
"settings": "Ajustes",
|
||||
"settings": "Opções",
|
||||
"copied": "Copiado",
|
||||
"pleaseTryAgain": "Tente novamente",
|
||||
"existingUser": "Usuário existente",
|
||||
@@ -151,8 +151,8 @@
|
||||
"scanACode": "Escanear código",
|
||||
"verify": "Verificar",
|
||||
"verifyEmail": "Verificar e-mail",
|
||||
"enterCodeHint": "Digite o código de 6 dígitos\ndo seu app autenticador",
|
||||
"lostDeviceTitle": "Perdeu um dispositivo?",
|
||||
"enterCodeHint": "Insira o código de 6 dígitos do aplicativo autenticador",
|
||||
"lostDeviceTitle": "Perdeu o dispositivo?",
|
||||
"twoFactorAuthTitle": "Autenticação de dois fatores",
|
||||
"passkeyAuthTitle": "Verificação de chave de acesso",
|
||||
"verifyPasskey": "Verificar chave de acesso",
|
||||
@@ -177,7 +177,7 @@
|
||||
"deleteAccountQuery": "Estamos tristes por vê-lo sair. Você enfrentou algum problema?",
|
||||
"yesSendFeedbackAction": "Sim, enviar feedback",
|
||||
"noDeleteAccountAction": "Não, excluir conta",
|
||||
"initiateAccountDeleteTitle": "Autentique para iniciar a exclusão de conta",
|
||||
"initiateAccountDeleteTitle": "Autentique-se para iniciar a exclusão de conta",
|
||||
"sendEmail": "Enviar e-mail",
|
||||
"createNewAccount": "Criar nova conta",
|
||||
"weakStrength": "Fraca",
|
||||
@@ -186,15 +186,15 @@
|
||||
"confirmPassword": "Confirmar senha",
|
||||
"close": "Fechar",
|
||||
"oopsSomethingWentWrong": "Opa. Algo deu errado.",
|
||||
"selectLanguage": "Trocar idioma",
|
||||
"selectLanguage": "Alterar idioma",
|
||||
"language": "Idioma",
|
||||
"social": "Redes sociais",
|
||||
"security": "Segurança",
|
||||
"lockscreen": "Tela de bloqueio",
|
||||
"authToChangeLockscreenSetting": "Autentique para alterar a opção de tela de bloqueio",
|
||||
"authToChangeLockscreenSetting": "Autentique-se para alterar a opção da tela de bloqueio",
|
||||
"deviceLockEnablePreSteps": "Para ativar o bloqueio do dispositivo, configure a senha do dispositivo ou o bloqueio de tela nas configurações do seu sistema.",
|
||||
"viewActiveSessions": "Ver sessões ativas",
|
||||
"authToViewYourActiveSessions": "Autentique para ver suas sessões ativas",
|
||||
"authToViewYourActiveSessions": "Autentique-se para ver suas sessões ativas",
|
||||
"searchHint": "Buscar...",
|
||||
"search": "Buscar",
|
||||
"sorryUnableToGenCode": "Desculpe, não foi possível gerar um código para {issuerName}",
|
||||
@@ -208,7 +208,7 @@
|
||||
"shareCodesDuration": "Selecione a duração em que você queira compartilhar os códigos.",
|
||||
"restore": "Restaurar",
|
||||
"copiedToClipboard": "Copiado para a área de transferência",
|
||||
"copiedNextToClipboard": "Próximo código copiado para a área de transferência",
|
||||
"copiedNextToClipboard": "Copiado próximo código à área de transferência",
|
||||
"error": "Erro",
|
||||
"recoveryKeyCopiedToClipboard": "Chave de recuperação copiada para a área de transferência",
|
||||
"recoveryKeyOnForgotPassword": "Caso esqueça sua senha, a única maneira de recuperar seus dados é com esta chave.",
|
||||
@@ -217,8 +217,8 @@
|
||||
"saveKey": "Salvar chave",
|
||||
"save": "Salvar",
|
||||
"send": "Enviar",
|
||||
"saveOrSendDescription": "Deseja mesmo salvar em seu armazenamento (pasta Downloads por padrão) ou enviar para outros apps?",
|
||||
"saveOnlyDescription": "Deseja mesmo salvar em seu armazenamento (pasta Downloads por padrão)?",
|
||||
"saveOrSendDescription": "Deseja mesmo salvar isso no armazenamento (pasta de Downloads por padrão) ou enviar a outros aplicativos?",
|
||||
"saveOnlyDescription": "Deseja mesmo salvar em seu armazenamento (pasta de Downloads por padrão)?",
|
||||
"back": "Voltar",
|
||||
"createAccount": "Criar conta",
|
||||
"passwordStrength": "Força da senha: {passwordStrengthValue}",
|
||||
@@ -258,6 +258,10 @@
|
||||
"areYouSureYouWantToLogout": "Deseja mesmo sair?",
|
||||
"yesLogout": "Sim, quero sair",
|
||||
"exit": "Sair",
|
||||
"theme": "Tema",
|
||||
"lightTheme": "Claro",
|
||||
"darkTheme": "Escuro",
|
||||
"systemTheme": "Sistema",
|
||||
"verifyingRecoveryKey": "Verificando chave de recuperação...",
|
||||
"recoveryKeyVerified": "Chave de recuperação verificada",
|
||||
"recoveryKeySuccessBody": "Ótimo! Sua chave de recuperação é válida. Obrigada por verificar.\n\nLembre-se de manter sua chave de recuperação copiada com segurança.",
|
||||
@@ -299,7 +303,7 @@
|
||||
"description": "Text for the button to confirm the user understands the warning"
|
||||
},
|
||||
"authToExportCodes": "Autentique para exportar seus códigos",
|
||||
"importSuccessTitle": "Oba!",
|
||||
"importSuccessTitle": "Sucesso!",
|
||||
"importSuccessDesc": "Você importou {count} códigos!",
|
||||
"@importSuccessDesc": {
|
||||
"placeholders": {
|
||||
@@ -383,7 +387,7 @@
|
||||
"@androidBiometricNotRecognized": {
|
||||
"description": "Message to let the user know that authentication was failed. It is used on Android side. Maximum 60 characters."
|
||||
},
|
||||
"androidBiometricSuccess": "Êxito",
|
||||
"androidBiometricSuccess": "Sucesso",
|
||||
"@androidBiometricSuccess": {
|
||||
"description": "Message to let the user know that authentication was successful. It is used on Android side. Maximum 60 characters."
|
||||
},
|
||||
@@ -399,15 +403,15 @@
|
||||
"@androidBiometricRequiredTitle": {
|
||||
"description": "Message showed as a title in a dialog which indicates the user has not set up biometric authentication on their device. It is used on Android side. Maximum 60 characters."
|
||||
},
|
||||
"androidDeviceCredentialsRequiredTitle": "Credenciais do dispositivo necessárias",
|
||||
"androidDeviceCredentialsRequiredTitle": "Credenciais necessários do dispositivo",
|
||||
"@androidDeviceCredentialsRequiredTitle": {
|
||||
"description": "Message showed as a title in a dialog which indicates the user has not set up credentials authentication on their device. It is used on Android side. Maximum 60 characters."
|
||||
},
|
||||
"androidDeviceCredentialsSetupDescription": "Credenciais do dispositivo necessárias",
|
||||
"androidDeviceCredentialsSetupDescription": "Credenciais necessários do dispositivo",
|
||||
"@androidDeviceCredentialsSetupDescription": {
|
||||
"description": "Message advising the user to go to the settings and configure device credentials on their device. It shows in a dialog on Android side."
|
||||
},
|
||||
"goToSettings": "Ir para Ajustes",
|
||||
"goToSettings": "Ir para Opções",
|
||||
"@goToSettings": {
|
||||
"description": "Message showed on a button that the user can click to go to settings pages from the current dialog. It is used on both Android and iOS side. Maximum 30 characters."
|
||||
},
|
||||
@@ -434,7 +438,7 @@
|
||||
"signOutOtherDevices": "Sair em outros dispositivos",
|
||||
"doNotSignOut": "Não sair",
|
||||
"hearUsWhereTitle": "Como você descobriu o Ente? (opcional)",
|
||||
"hearUsExplanation": "Não sabemos como você encontrou nosso app. Seria útil se você nos contasse!",
|
||||
"hearUsExplanation": "Não rastreamos instalações. Ajudaria bastante se você contasse onde nos achou!",
|
||||
"recoveryKeySaved": "Chave de recuperação salva na pasta Downloads!",
|
||||
"waitingForBrowserRequest": "Aguardando solicitação do navegador...",
|
||||
"waitingForVerification": "Aguardando verificação...",
|
||||
@@ -442,8 +446,8 @@
|
||||
"passKeyPendingVerification": "A verificação ainda está pendente",
|
||||
"loginSessionExpired": "Sessão expirada",
|
||||
"loginSessionExpiredDetails": "Sua sessão expirou. Registre-se novamente.",
|
||||
"developerSettingsWarning": "Deseja mesmo alterar os ajustes de Desenvolvedor?",
|
||||
"developerSettings": "Ajustes de Desenvolvedor",
|
||||
"developerSettingsWarning": "Deseja mesmo alterar as Opções de Desenvolvedor?",
|
||||
"developerSettings": "Opções de Desenvolvedor",
|
||||
"serverEndpoint": "Endpoint do servidor",
|
||||
"invalidEndpoint": "Endpoint inválido",
|
||||
"invalidEndpointMessage": "Desculpe, o ponto de acesso inserido é inválido. Insira um ponto de acesso válido e tente novamente.",
|
||||
@@ -459,16 +463,16 @@
|
||||
"tag": "Etiqueta",
|
||||
"create": "Criar",
|
||||
"editTag": "Editar etiqueta",
|
||||
"deleteTagTitle": "Apagar etiqueta?",
|
||||
"deleteTagTitle": "Excluir etiqueta?",
|
||||
"deleteTagMessage": "Deseja mesmo excluir esta etiqueta? Essa ação é irreversível.",
|
||||
"somethingWentWrongParsingCode": "Não foi possível analisar os códigos {x}.",
|
||||
"updateNotAvailable": "Atualização indisponível",
|
||||
"viewRawCodes": "Ver códigos brutos",
|
||||
"rawCodes": "Códigos brutos",
|
||||
"rawCodeData": "Dados de códigos brutos",
|
||||
"appLock": "Bloqueio do app",
|
||||
"appLock": "Bloqueio do aplicativo",
|
||||
"noSystemLockFound": "Nenhum bloqueio do sistema encontrado",
|
||||
"toEnableAppLockPleaseSetupDevicePasscodeOrScreen": "Para ativar o bloqueio do app, configure uma senha no dispositivo ou tela de bloqueio nas configurações do sistema.",
|
||||
"toEnableAppLockPleaseSetupDevicePasscodeOrScreen": "Para ativar o bloqueio do aplicativo, configure uma senha no dispositivo ou tela de bloqueio nas opções do sistema.",
|
||||
"autoLock": "Bloqueio automático",
|
||||
"immediately": "Imediatamente",
|
||||
"reEnterPassword": "Reinserir senha",
|
||||
@@ -479,17 +483,17 @@
|
||||
"setNewPassword": "Defina a nova senha",
|
||||
"deviceLock": "Bloqueio do dispositivo",
|
||||
"hideContent": "Ocultar conteúdo",
|
||||
"hideContentDescriptionAndroid": "Oculta o conteúdo do app no seletor de apps e desativa as capturas de tela",
|
||||
"hideContentDescriptioniOS": "Oculta o conteúdo do seletor de apps",
|
||||
"autoLockFeatureDescription": "Tempo de bloqueio do app em segundo plano",
|
||||
"hideContentDescriptionAndroid": "Oculta o conteúdo do aplicativo no seletor de aplicativos e desativa as capturas de tela",
|
||||
"hideContentDescriptioniOS": "Oculta o conteúdo do seletor de aplicativos",
|
||||
"autoLockFeatureDescription": "Tempo de bloqueio do aplicativo em segundo plano",
|
||||
"appLockDescription": "Escolha entre a tela de bloqueio padrão do seu dispositivo e uma tela de bloqueio personalizada com PIN ou senha.",
|
||||
"pinLock": "Bloqueio PIN",
|
||||
"enterPin": "Insira o PIN",
|
||||
"pinLock": "PIN de bloqueio",
|
||||
"enterPin": "Inserir PIN",
|
||||
"setNewPin": "Definir novo PIN",
|
||||
"importFailureDescNew": "Não foi possível analisar o arquivo selecionado.",
|
||||
"appLockNotEnabled": "Bloqueio de aplicativo não ativado",
|
||||
"appLockNotEnabledDescription": "Ative o bloqueio de aplicativo em Segurança > Bloqueio de aplicativo",
|
||||
"authToViewPasskey": "Autentique para ver a sua chave de acesso",
|
||||
"authToViewPasskey": "Autentique-se para ver a sua chave de acesso",
|
||||
"appLockOfflineModeWarning": "Você prosseguiu sem cópias de segurança. Caso, se esqueça de seu aplicativo de bloqueio, você não poderá mais acessar seus dados.",
|
||||
"duplicateCodes": "Duplicar códigos",
|
||||
"noDuplicates": "✨ Sem duplicados",
|
||||
@@ -497,5 +501,6 @@
|
||||
"deduplicateCodes": "Desduplicar códigos",
|
||||
"deselectAll": "Deselecionar tudo",
|
||||
"selectAll": "Selecionar tudo",
|
||||
"deleteDuplicates": "Excluir duplicados"
|
||||
"deleteDuplicates": "Excluir duplicados",
|
||||
"plainHTML": "HTML simples"
|
||||
}
|
||||
@@ -2,6 +2,10 @@
|
||||
"account": "Konto",
|
||||
"unlock": "Lås upp",
|
||||
"recoveryKey": "Återställningsnyckel",
|
||||
"counterAppBarTitle": "Räknare",
|
||||
"@counterAppBarTitle": {
|
||||
"description": "Text shown in the AppBar of the Counter Page"
|
||||
},
|
||||
"onBoardingBody": "Säkerhetskopiera dina 2FA-koder",
|
||||
"onBoardingGetStarted": "Kom igång",
|
||||
"setupFirstAccount": "Konfigurera ditt första konto",
|
||||
@@ -15,22 +19,41 @@
|
||||
"pleaseVerifyDetails": "Kontrollera dina detaljer och försök igen",
|
||||
"codeIssuerHint": "Utfärdare",
|
||||
"codeSecretKeyHint": "Secret Key",
|
||||
"secret": "Säkerhets nyckel",
|
||||
"all": "Alla",
|
||||
"notes": "Anteckningar",
|
||||
"notesLengthLimit": "Anteckningar kan vara högst {count} tecken långa",
|
||||
"@notesLengthLimit": {
|
||||
"description": "Text to indicate the maximum number of characters allowed for notes",
|
||||
"placeholders": {
|
||||
"count": {
|
||||
"description": "The maximum number of characters allowed for notes",
|
||||
"type": "int",
|
||||
"example": "100"
|
||||
}
|
||||
}
|
||||
},
|
||||
"codeAccountHint": "Konto (du@domän.com)",
|
||||
"codeTagHint": "Tagg",
|
||||
"accountKeyType": "Typ av nyckel",
|
||||
"sessionExpired": "Sessionen har gått ut",
|
||||
"@sessionExpired": {
|
||||
"description": "Title of the dialog when the users current session is invalid/expired"
|
||||
},
|
||||
"pleaseLoginAgain": "Logga in igen",
|
||||
"loggingOut": "Loggar ut...",
|
||||
"timeBasedKeyType": "Tidsbaserad (TOTP)",
|
||||
"counterBasedKeyType": "Räknarbaserad (HOTP)",
|
||||
"saveAction": "Spara",
|
||||
"nextTotpTitle": "nästa",
|
||||
"deleteCodeTitle": "Radera kod?",
|
||||
"deleteCodeMessage": "Vill du ta bort den här koden? Det går inte att ångra den här åtgärden.",
|
||||
"trashCode": "Ta bort kod?",
|
||||
"trashCodeMessage": "Är du säker på att du vill ta bort koden för {account}?",
|
||||
"trash": "Papperskorg",
|
||||
"viewLogsAction": "Visa loggar",
|
||||
"sendLogsDescription": "Detta kommer att skicka över loggar för att hjälpa oss felsöka ditt problem. Även om vi vidtar försiktighetsåtgärder för att säkerställa att känslig information inte loggas, uppmuntrar vi dig att se dessa loggar innan du delar dem.",
|
||||
"preparingLogsTitle": "Förbereder loggar...",
|
||||
"emailLogsTitle": "E-posta loggar",
|
||||
"emailLogsMessage": "Skicka loggarna till {email}",
|
||||
"@emailLogsMessage": {
|
||||
@@ -61,55 +84,111 @@
|
||||
"pleaseWait": "Vänligen vänta...",
|
||||
"generatingEncryptionKeysTitle": "Skapar krypteringsnycklar...",
|
||||
"recreatePassword": "Återskapa lösenord",
|
||||
"recreatePasswordMessage": "Denna enhet är inte tillräckligt kraftfull för att verifiera ditt lösenord, men vi kan återskapa det på ett sätt som fungerar med alla enheter.\n\nLogga in med din återställningsnyckel och återskapa ditt lösenord (du kan använda samma igen om du vill).",
|
||||
"useRecoveryKey": "Använd återställningsnyckel",
|
||||
"incorrectPasswordTitle": "Felaktigt lösenord",
|
||||
"welcomeBack": "Välkommen tillbaka!",
|
||||
"madeWithLoveAtPrefix": "gjord med ❤️ av ",
|
||||
"supportDevs": "Prenumerera på <bold-green>ente</bold-green> för att stödja oss",
|
||||
"supportDiscount": "Använd kupongkoden \"AUTH\" för att få 10% rabatt första året",
|
||||
"changeEmail": "Ändra e-postadress",
|
||||
"changePassword": "Ändra lösenord",
|
||||
"data": "Data",
|
||||
"importCodes": "Importera koder",
|
||||
"importTypePlainText": "Enkel text",
|
||||
"importTypeEnteEncrypted": "Ente krypterad export",
|
||||
"passwordForDecryptingExport": "Lösenord för att dekryptera export",
|
||||
"passwordEmptyError": "Lösenordet får inte vara tomt",
|
||||
"importFromApp": "Importera koder från {appName}",
|
||||
"importGoogleAuthGuide": "Exportera dina konton från Google Authenticator till en QR-kod med alternativet \"Överföra konton\". Använd sedan en annan enhet och skanna QR-koden.\n\nTips: Du kan använda din bärbara dators webbkamera för att ta en bild av QR-koden.",
|
||||
"importSelectJsonFile": "Välj JSON-fil",
|
||||
"importSelectAppExport": "Välj {appName} exportfil",
|
||||
"importEnteEncGuide": "Välj den krypterade JSON-filen som exporteras från Ente",
|
||||
"importRaivoGuide": "Använd alternativet \"Exportera OTPs till zip-arkiv\" i Raivos inställningar.\n\nExtrahera zip-filen och importera JSON-filen.",
|
||||
"importBitwardenGuide": "Använd alternativet \"Exportera valv\" inom Bitwarden Tools och importera den okrypterade JSON-filen.",
|
||||
"exportCodes": "Exportera koder",
|
||||
"importLabel": "Importera",
|
||||
"importInstruction": "Vänligen välj en fil som innehåller en lista över dina koder i följande format",
|
||||
"importCodeDelimiterInfo": "Koderna kan separeras med kommatecken eller en ny rad",
|
||||
"selectFile": "Välj fil",
|
||||
"emailVerificationToggle": "E-postverifiering",
|
||||
"emailVerificationEnableWarning": "För att undvika att bli låst från ditt konto, se till att spara en kopia av din e-post 2FA utanför Ente Auth innan du aktiverar e-postverifiering.",
|
||||
"authToChangeEmailVerificationSetting": "Autentisera för att ändra din e-postadress",
|
||||
"authenticateGeneric": "Var god autentisera",
|
||||
"authToViewYourRecoveryKey": "Autentisera för att visa din återställningsnyckel",
|
||||
"authToChangeYourEmail": "Autentisera för att ändra din e-postadress",
|
||||
"authToChangeYourPassword": "Autentisera för att ändra ditt lösenord",
|
||||
"authToViewSecrets": "Autentisera för att visa din återställningsnyckel",
|
||||
"authToInitiateSignIn": "Vänligen autentisera för att initiera inloggning för säkerhetskopiering.",
|
||||
"ok": "OK",
|
||||
"cancel": "Avbryt",
|
||||
"yes": "Ja",
|
||||
"no": "Nej",
|
||||
"email": "E-post",
|
||||
"support": "Support",
|
||||
"general": "Allmänt",
|
||||
"settings": "Inställningar",
|
||||
"copied": "Kopierat",
|
||||
"pleaseTryAgain": "Försök igen",
|
||||
"existingUser": "Befintlig användare",
|
||||
"newUser": "Ny hos Ente",
|
||||
"delete": "Radera",
|
||||
"enterYourPasswordHint": "Ange ditt lösenord",
|
||||
"forgotPassword": "Glömt lösenord",
|
||||
"oops": "Hoppsan",
|
||||
"suggestFeatures": "Föreslå funktionalitet",
|
||||
"faq": "FAQ",
|
||||
"somethingWentWrongMessage": "Något gick fel, vänligen försök igen",
|
||||
"leaveFamily": "Lämna familjen",
|
||||
"leaveFamilyMessage": "Är du säker på att du vill lämna familjeplanen?",
|
||||
"inFamilyPlanMessage": "Du är på en familjeplan!",
|
||||
"hintForMobile": "Håll i på en kod för att redigera eller ta bort.",
|
||||
"hintForDesktop": "Högerklicka på en kod för att redigera eller ta bort.",
|
||||
"scan": "Skanna",
|
||||
"scanACode": "Skanna kod",
|
||||
"verify": "Verifiera",
|
||||
"verifyEmail": "Verifiera e-postadress",
|
||||
"enterCodeHint": "Ange den 6-siffriga koden från din autentiseringsapp",
|
||||
"lostDeviceTitle": "Förlorad enhet?",
|
||||
"twoFactorAuthTitle": "Tvåfaktorsautentisering",
|
||||
"passkeyAuthTitle": "Lösenordsverifiering",
|
||||
"verifyPasskey": "Verifiera nyckel",
|
||||
"loginWithTOTP": "Logga in med TOTP",
|
||||
"recoverAccount": "Återställ konto",
|
||||
"enterRecoveryKeyHint": "Ange din återställningsnyckel",
|
||||
"recover": "Återställ",
|
||||
"contactSupportViaEmailMessage": "Vänligen skicka ett e-postmeddelande till {email} från din registrerade e-postadress",
|
||||
"@contactSupportViaEmailMessage": {
|
||||
"placeholders": {
|
||||
"email": {
|
||||
"type": "String"
|
||||
}
|
||||
}
|
||||
},
|
||||
"invalidQRCode": "Ogiltig QR-kod",
|
||||
"noRecoveryKeyTitle": "Ingen återställningsnyckel?",
|
||||
"enterEmailHint": "Ange din e-postadress",
|
||||
"invalidEmailTitle": "Ogiltig e-postadress",
|
||||
"invalidEmailMessage": "Ange en giltig e-postadress.",
|
||||
"deleteAccount": "Radera konto",
|
||||
"deleteAccountQuery": "Vi kommer att vara ledsna över att se dig gå. Har du något problem?",
|
||||
"yesSendFeedbackAction": "Ja, skicka feedback",
|
||||
"noDeleteAccountAction": "Nej, radera konto",
|
||||
"initiateAccountDeleteTitle": "Vänligen autentisera för att initiera borttagning av konto",
|
||||
"sendEmail": "Skicka e-post",
|
||||
"createNewAccount": "Skapa nytt konto",
|
||||
"weakStrength": "Svag",
|
||||
"strongStrength": "Stark",
|
||||
"moderateStrength": "Måttligt",
|
||||
"confirmPassword": "Bekräfta lösenord",
|
||||
"close": "Stäng",
|
||||
"oopsSomethingWentWrong": "Hoppsan! Något gick fel.",
|
||||
"selectLanguage": "Välj språk",
|
||||
"language": "Språk",
|
||||
"social": "Social",
|
||||
"security": "Säkerhet",
|
||||
"lockscreen": "Låsskärm",
|
||||
"authToChangeLockscreenSetting": "Vänligen autentisera för att ändra låsskärms inställningar",
|
||||
"viewActiveSessions": "Visa aktiva sessioner",
|
||||
"authToViewYourActiveSessions": "Autentisera för att visa dina aktiva sessioner",
|
||||
"searchHint": "Sök...",
|
||||
@@ -128,9 +207,13 @@
|
||||
"error": "Fel",
|
||||
"recoveryKeyCopiedToClipboard": "Återställningsnyckel kopierad till urklipp",
|
||||
"recoveryKeyOnForgotPassword": "Om du glömmer ditt lösenord är det enda sättet du kan återställa dina data med denna nyckel.",
|
||||
"recoveryKeySaveDescription": "Vi lagrar inte och har därför inte åtkomst till denna nyckel, vänligen spara denna 24 ords nyckel på en säker plats.",
|
||||
"doThisLater": "Gör detta senare",
|
||||
"saveKey": "Spara nyckel",
|
||||
"save": "Spara",
|
||||
"send": "Skicka",
|
||||
"saveOrSendDescription": "Vill du spara detta till din lagringsmapp (Nedladdningsmappen som standard) eller skicka den till andra appar?",
|
||||
"saveOnlyDescription": "Vill du spara detta till din lagringsmapp (Nedladdningsmappen som standard)?",
|
||||
"back": "Tillbaka",
|
||||
"createAccount": "Skapa konto",
|
||||
"passwordStrength": "Lösenordsstyrka: {passwordStrengthValue}",
|
||||
@@ -146,6 +229,7 @@
|
||||
"message": "Password Strength: {passwordStrengthText}"
|
||||
},
|
||||
"password": "Lösenord",
|
||||
"signUpTerms": "Jag samtycker till <u-terms>användarvillkoren</u-terms> och <u-policy>integritetspolicyn</u-policy>",
|
||||
"privacyPolicyTitle": "Integritetspolicy",
|
||||
"termsOfServicesTitle": "Villkor",
|
||||
"encryption": "Kryptering",
|
||||
@@ -153,24 +237,58 @@
|
||||
"changePasswordTitle": "Ändra lösenord",
|
||||
"resetPasswordTitle": "Återställ lösenord",
|
||||
"encryptionKeys": "Krypteringsnycklar",
|
||||
"passwordWarning": "Vi lagrar inte detta lösenord, så om du glömmer bort det, <underline>kan vi inte dekryptera dina data</underline>",
|
||||
"enterPasswordToEncrypt": "Ange ett lösenord som vi kan använda för att kryptera din data",
|
||||
"enterNewPasswordToEncrypt": "Ange ett nytt lösenord som vi kan använda för att kryptera din data",
|
||||
"passwordChangedSuccessfully": "Lösenordet har ändrats",
|
||||
"generatingEncryptionKeys": "Skapar krypteringsnycklar...",
|
||||
"continueLabel": "Fortsätt",
|
||||
"insecureDevice": "Osäker enhet",
|
||||
"sorryWeCouldNotGenerateSecureKeysOnThisDevicennplease": "Tyvärr, kunde vi inte generera säkra nycklar på den här enheten.\n\nvänligen registrera dig från en annan enhet.",
|
||||
"howItWorks": "Så här fungerar det",
|
||||
"ackPasswordLostWarning": "Jag förstår att om jag förlorar mitt lösenord kan jag förlora mina data eftersom min data är <underline>end-to-end-krypterad</underline>.",
|
||||
"loginTerms": "Jag samtycker till <u-terms>användarvillkoren</u-terms> och <u-policy>integritetspolicyn</u-policy>",
|
||||
"logInLabel": "Logga in",
|
||||
"logout": "Logga ut",
|
||||
"areYouSureYouWantToLogout": "Är du säker på att du vill logga ut?",
|
||||
"yesLogout": "Ja, logga ut",
|
||||
"exit": "Avsluta",
|
||||
"theme": "Tema",
|
||||
"lightTheme": "Ljust",
|
||||
"darkTheme": "Mörkt",
|
||||
"systemTheme": "System",
|
||||
"verifyingRecoveryKey": "Verifierar återställningsnyckel...",
|
||||
"recoveryKeyVerified": "Återställningsnyckel verifierad",
|
||||
"recoveryKeySuccessBody": "Grymt! Din återställningsnyckel är giltig. Tack för att du verifierade.\n\nKom ihåg att hålla din återställningsnyckel säker med backups.",
|
||||
"recreatePasswordTitle": "Återskapa lösenord",
|
||||
"invalidKey": "Ogiltig nyckel",
|
||||
"tryAgain": "Försök igen",
|
||||
"viewRecoveryKey": "Visa återställningsnyckel",
|
||||
"confirmRecoveryKey": "Bekräfta återställningsnyckel",
|
||||
"confirmYourRecoveryKey": "Bekräfta din återställningsnyckel",
|
||||
"confirm": "Bekräfta",
|
||||
"emailYourLogs": "Maila dina loggar",
|
||||
"copyEmailAddress": "Kopiera e-postadress",
|
||||
"exportLogs": "Exportera loggar",
|
||||
"enterYourRecoveryKey": "Ange din återställningsnyckel",
|
||||
"about": "Om",
|
||||
"weAreOpenSource": "Vi är öppen källkod!",
|
||||
"privacy": "Sekretess",
|
||||
"terms": "Villkor",
|
||||
"checkForUpdates": "Sök efter uppdateringar",
|
||||
"checkStatus": "Kontrollera status",
|
||||
"downloadUpdate": "Ladda ner",
|
||||
"criticalUpdateAvailable": "Kritisk uppdatering tillgänglig",
|
||||
"update": "Uppdatera",
|
||||
"checking": "Kontrollerar ...",
|
||||
"youAreOnTheLatestVersion": "Du är på den senaste versionen",
|
||||
"warning": "Varning",
|
||||
"iUnderStand": "Jag förstår",
|
||||
"@iUnderStand": {
|
||||
"description": "Text for the button to confirm the user understands the warning"
|
||||
},
|
||||
"authToExportCodes": "Autentisera för att exportera dina koder",
|
||||
"importSuccessTitle": "Jippi!",
|
||||
"importSuccessDesc": "Du har importerat {count} koder!",
|
||||
"@importSuccessDesc": {
|
||||
"placeholders": {
|
||||
@@ -181,40 +299,108 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"sorry": "Tyvärr",
|
||||
"pendingSyncs": "Varning",
|
||||
"activeSessions": "Aktiva sessioner",
|
||||
"incorrectCode": "Felaktig kod",
|
||||
"authenticationSuccessful": "Autentisering lyckades!",
|
||||
"twofactorAuthenticationSuccessfullyReset": "Tvåfaktorsautentisering återställd",
|
||||
"incorrectRecoveryKey": "Felaktig återställningsnyckel",
|
||||
"enterPassword": "Ange lösenord",
|
||||
"selectExportFormat": "Välj exportformat",
|
||||
"encrypted": "Krypterad",
|
||||
"plainText": "Enkel text",
|
||||
"passwordToEncryptExport": "Lösenord för att kryptera export",
|
||||
"export": "Exportera",
|
||||
"useOffline": "Använd utan säkerhetskopior",
|
||||
"signInToBackup": "Logga in för att säkerhetskopiera dina koder",
|
||||
"singIn": "Logga in",
|
||||
"showLargeIcons": "Visa stora ikoner",
|
||||
"shouldHideCode": "Dölj koder",
|
||||
"minimizeAppOnCopy": "Minimera appen vid kopiering",
|
||||
"editCodeAuthMessage": "Autentisera för att redigera kod",
|
||||
"deleteCodeAuthMessage": "Autentisera för att radera kod",
|
||||
"showQRAuthMessage": "Autentisera för att visa QR-kod",
|
||||
"confirmAccountDeleteTitle": "Bekräfta radering av kontot",
|
||||
"androidBiometricHint": "Verifiera identitet",
|
||||
"@androidBiometricHint": {
|
||||
"description": "Hint message advising the user how to authenticate with biometrics. It is used on Android side. Maximum 60 characters."
|
||||
},
|
||||
"androidBiometricNotRecognized": "Ej godkänd. Försök igen.",
|
||||
"@androidBiometricNotRecognized": {
|
||||
"description": "Message to let the user know that authentication was failed. It is used on Android side. Maximum 60 characters."
|
||||
},
|
||||
"androidBiometricSuccess": "Slutförd",
|
||||
"@androidBiometricSuccess": {
|
||||
"description": "Message to let the user know that authentication was successful. It is used on Android side. Maximum 60 characters."
|
||||
},
|
||||
"androidCancelButton": "Avbryt",
|
||||
"@androidCancelButton": {
|
||||
"description": "Message showed on a button that the user can click to leave the current dialog. It is used on Android side. Maximum 30 characters."
|
||||
},
|
||||
"androidSignInTitle": "Obligatorisk autentisering",
|
||||
"@androidSignInTitle": {
|
||||
"description": "Message showed as a title in a dialog which indicates the user that they need to scan biometric to continue. It is used on Android side. Maximum 60 characters."
|
||||
},
|
||||
"androidBiometricRequiredTitle": "Biometriska uppgifter krävs",
|
||||
"@androidBiometricRequiredTitle": {
|
||||
"description": "Message showed as a title in a dialog which indicates the user has not set up biometric authentication on their device. It is used on Android side. Maximum 60 characters."
|
||||
},
|
||||
"androidDeviceCredentialsRequiredTitle": "Enhetsuppgifter krävs",
|
||||
"@androidDeviceCredentialsRequiredTitle": {
|
||||
"description": "Message showed as a title in a dialog which indicates the user has not set up credentials authentication on their device. It is used on Android side. Maximum 60 characters."
|
||||
},
|
||||
"androidDeviceCredentialsSetupDescription": "Enhetsuppgifter krävs",
|
||||
"@androidDeviceCredentialsSetupDescription": {
|
||||
"description": "Message advising the user to go to the settings and configure device credentials on their device. It shows in a dialog on Android side."
|
||||
},
|
||||
"goToSettings": "Gå till inställningar",
|
||||
"@goToSettings": {
|
||||
"description": "Message showed on a button that the user can click to go to settings pages from the current dialog. It is used on both Android and iOS side. Maximum 30 characters."
|
||||
},
|
||||
"iOSOkButton": "OK",
|
||||
"@iOSOkButton": {
|
||||
"description": "Message showed on a button that the user can click to leave the current dialog. It is used on iOS side. Maximum 30 characters."
|
||||
},
|
||||
"noInternetConnection": "Ingen internetanslutning",
|
||||
"pleaseCheckYourInternetConnectionAndTryAgain": "Kontrollera din internetanslutning och försök igen.",
|
||||
"signOutFromOtherDevices": "Logga ut från andra enheter",
|
||||
"signOutOtherDevices": "Logga ut andra enheter",
|
||||
"doNotSignOut": "Logga inte ut",
|
||||
"hearUsWhereTitle": "Hur hörde du talas om Ente? (valfritt)",
|
||||
"hearUsExplanation": "Vi spårar inte appinstallationer, Det skulle hjälpa oss om du berättade var du hittade oss!",
|
||||
"recoveryKeySaved": "Återställningsnyckel sparad i nedladdningsmappen!",
|
||||
"waitingForBrowserRequest": "Väntar på webbläsarbegäran...",
|
||||
"waitingForVerification": "Väntar på verifiering...",
|
||||
"passkey": "Nyckel",
|
||||
"passKeyPendingVerification": "Verifiering pågår fortfarande",
|
||||
"loginSessionExpired": "Sessionen har gått ut",
|
||||
"loginSessionExpiredDetails": "Din session har upphört. Logga in igen.",
|
||||
"developerSettingsWarning": "Är du säker på att du vill ändra på utvecklarinställningar?",
|
||||
"developerSettings": "Utvecklarinställningar",
|
||||
"serverEndpoint": "Serverns slutpunkt",
|
||||
"invalidEndpoint": "Ogiltig slutpunkt",
|
||||
"invalidEndpointMessage": "Tyvärr, slutpunkten du angav är ogiltig. Ange en giltig slutpunkt och försök igen.",
|
||||
"endpointUpdatedMessage": "Slutpunkten har uppdaterats",
|
||||
"customEndpoint": "Ansluten till {endpoint}",
|
||||
"pinText": "Fäst",
|
||||
"unpinText": "Ångra fäst",
|
||||
"pinnedCodeMessage": "{code} har fästs",
|
||||
"pinned": "Fastmarkerad",
|
||||
"tags": "Taggar",
|
||||
"createNewTag": "Skapa ny tagg",
|
||||
"tag": "Tagg",
|
||||
"create": "Skapa",
|
||||
"editTag": "Redigera tagg",
|
||||
"deleteTagTitle": "Radera tagg?",
|
||||
"updateNotAvailable": "Uppdateringen är inte tillgänglig",
|
||||
"viewRawCodes": "Visa råa koder",
|
||||
"rawCodes": "Råa koder",
|
||||
"rawCodeData": "Rå koddata",
|
||||
"appLock": "Applås",
|
||||
"noSystemLockFound": "Inget systemlås hittades",
|
||||
"toEnableAppLockPleaseSetupDevicePasscodeOrScreen": "För att aktivera applås, vänligen ställ in enhetens lösenord eller skärmlås i systeminställningarna.",
|
||||
"autoLock": "Automatisk låsning",
|
||||
"immediately": "Omedelbart",
|
||||
"reEnterPassword": "Ange lösenord igen",
|
||||
"reEnterPin": "Ange PIN-kod igen",
|
||||
@@ -224,6 +410,8 @@
|
||||
"setNewPassword": "Ställ in nytt lösenord",
|
||||
"deviceLock": "Enhetslås",
|
||||
"hideContent": "Dölj innehåll",
|
||||
"hideContentDescriptionAndroid": "Döljer appinnehåll i app-växlaren och inaktiverar skärmdumpar",
|
||||
"hideContentDescriptioniOS": "Döljer appinnehåll i app-växlaren",
|
||||
"enterPin": "Ange PIN-kod",
|
||||
"setNewPin": "Ställ in ny PIN-kod",
|
||||
"authToViewPasskey": "Autentisera för att visa nyckel"
|
||||
|
||||
@@ -258,6 +258,10 @@
|
||||
"areYouSureYouWantToLogout": "Ви впевнені, що хочете вийти з системи?",
|
||||
"yesLogout": "Так, вийти з системи",
|
||||
"exit": "Вийти",
|
||||
"theme": "Тема",
|
||||
"lightTheme": "Світла",
|
||||
"darkTheme": "Темна",
|
||||
"systemTheme": "Як в системі",
|
||||
"verifyingRecoveryKey": "Перевірка ключа відновлення...",
|
||||
"recoveryKeyVerified": "Ключ відновлення перевірено",
|
||||
"recoveryKeySuccessBody": "Чудово! Ваш ключ відновлення дійсний. Дякуємо за перевірку.\n\nБудь ласка, не забувайте зберігати надійну резервну копію ключа відновлення.",
|
||||
@@ -490,5 +494,13 @@
|
||||
"appLockNotEnabled": "Блокування програм не увімкнено",
|
||||
"appLockNotEnabledDescription": "Увімкніть блокування програм від безпеки > Блокування програм",
|
||||
"authToViewPasskey": "Будь ласка, авторизуйтеся для перегляду ключа доступу",
|
||||
"appLockOfflineModeWarning": "Ви обрали продовжити без резервних копій. Якщо ви забудете свій пароль, доступ до ваших даних буде заблоковано."
|
||||
"appLockOfflineModeWarning": "Ви обрали продовжити без резервних копій. Якщо ви забудете свій пароль, доступ до ваших даних буде заблоковано.",
|
||||
"duplicateCodes": "Дублювати коди",
|
||||
"noDuplicates": "✨ Немає дублікатів",
|
||||
"youveNoDuplicateCodesThatCanBeCleared": "У вас немає дублікатів кодів, які можна очистити",
|
||||
"deduplicateCodes": "Дедуплікувати коди",
|
||||
"deselectAll": "Зняти виділення",
|
||||
"selectAll": "Вибрати все",
|
||||
"deleteDuplicates": "Видалити дублікати",
|
||||
"plainHTML": "Звичайний HTML"
|
||||
}
|
||||
@@ -258,6 +258,10 @@
|
||||
"areYouSureYouWantToLogout": "Bạn có chắc chắn muốn đăng xuất?",
|
||||
"yesLogout": "Có, đăng xuất",
|
||||
"exit": "Thoát",
|
||||
"theme": "Chủ đề",
|
||||
"lightTheme": "Sáng",
|
||||
"darkTheme": "Tối",
|
||||
"systemTheme": "Hệ thống",
|
||||
"verifyingRecoveryKey": "Đang xác minh khóa khôi phục...",
|
||||
"recoveryKeyVerified": "Khóa khôi phục đã được xác thực",
|
||||
"recoveryKeySuccessBody": "Tuyệt vời! Khóa khôi phục của bạn hợp lệ. Cảm ơn bạn đã xác minh.\n\nHãy nhớ sao lưu khóa khôi phục của bạn một cách an toàn.",
|
||||
@@ -490,5 +494,13 @@
|
||||
"appLockNotEnabled": "Khóa ứng dụng chưa được bật",
|
||||
"appLockNotEnabledDescription": "Vui lòng bật khóa ứng dụng từ Bảo mật > Khóa ứng dụng",
|
||||
"authToViewPasskey": "Vui lòng xác thực để xem mã khóa",
|
||||
"appLockOfflineModeWarning": "Bạn đã chọn tiếp tục mà không có bản sao lưu. Nếu bạn quên khóa ứng dụng, bạn sẽ bị khóa khỏi việc truy cập dữ liệu của mình."
|
||||
"appLockOfflineModeWarning": "Bạn đã chọn tiếp tục mà không có bản sao lưu. Nếu bạn quên khóa ứng dụng, bạn sẽ bị khóa khỏi việc truy cập dữ liệu của mình.",
|
||||
"duplicateCodes": "Mã trùng lặp",
|
||||
"noDuplicates": "✨ Không có trùng lặp",
|
||||
"youveNoDuplicateCodesThatCanBeCleared": "Bạn không có mã trùng lặp nào có thể được xóa",
|
||||
"deduplicateCodes": "Loại bỏ mã trùng lặp",
|
||||
"deselectAll": "Bỏ chọn tất cả",
|
||||
"selectAll": "Chọn tất cả",
|
||||
"deleteDuplicates": "Xóa trùng lặp",
|
||||
"plainHTML": "HTML thuần"
|
||||
}
|
||||
@@ -258,6 +258,10 @@
|
||||
"areYouSureYouWantToLogout": "您确定要登出吗?",
|
||||
"yesLogout": "是的,登出",
|
||||
"exit": "退出",
|
||||
"theme": "主题",
|
||||
"lightTheme": "浅色",
|
||||
"darkTheme": "深色",
|
||||
"systemTheme": "系统",
|
||||
"verifyingRecoveryKey": "正在验证恢复密钥...",
|
||||
"recoveryKeyVerified": "恢复密钥已验证",
|
||||
"recoveryKeySuccessBody": "太棒了! 您的恢复密钥是有效的。 感谢您的验证。\n\n请记住要安全备份您的恢复密钥。",
|
||||
@@ -490,5 +494,13 @@
|
||||
"appLockNotEnabled": "应用锁未启用",
|
||||
"appLockNotEnabledDescription": "请从“安全”>“应用锁”启用应用锁",
|
||||
"authToViewPasskey": "请验证身份以查看通行密钥",
|
||||
"appLockOfflineModeWarning": "您已选择继续而不备份。如果您忘记了应用锁,您将无法访问数据。"
|
||||
"appLockOfflineModeWarning": "您已选择继续而不备份。如果您忘记了应用锁,您将无法访问数据。",
|
||||
"duplicateCodes": "重复代码",
|
||||
"noDuplicates": "✨ 没有重复",
|
||||
"youveNoDuplicateCodesThatCanBeCleared": "您没有可清除的重复代码",
|
||||
"deduplicateCodes": "删除重复代码",
|
||||
"deselectAll": "取消全选",
|
||||
"selectAll": "全选",
|
||||
"deleteDuplicates": "删除重复项",
|
||||
"plainHTML": "Plain HTML"
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
import 'package:ente_auth/core/constants.dart';
|
||||
import 'package:ente_auth/core/network.dart';
|
||||
import 'package:ente_auth/utils/dialog_util.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:url_launcher/url_launcher_string.dart';
|
||||
@@ -11,11 +11,13 @@ class PasskeyService {
|
||||
|
||||
final _enteDio = Network.instance.enteDio;
|
||||
|
||||
Future<String> getJwtToken() async {
|
||||
Future<String> getAccountsUrl() async {
|
||||
final response = await _enteDio.get(
|
||||
"/users/accounts-token",
|
||||
);
|
||||
return response.data!["accountsToken"] as String;
|
||||
final accountsUrl = response.data!["accountsUrl"] ?? kAccountsUrl;
|
||||
final jwtToken = response.data!["accountsToken"] as String;
|
||||
return "$accountsUrl/passkeys?token=$jwtToken";
|
||||
}
|
||||
|
||||
Future<bool> isPasskeyRecoveryEnabled() async {
|
||||
@@ -25,10 +27,6 @@ class PasskeyService {
|
||||
return response.data!["isPasskeyRecoveryEnabled"] as bool;
|
||||
}
|
||||
|
||||
String get accountsUrl {
|
||||
return kDebugMode ? "http://localhost:3001" : "https://accounts.ente.io";
|
||||
}
|
||||
|
||||
Future<void> configurePasskeyRecovery(
|
||||
String secret,
|
||||
String userEncryptedSecret,
|
||||
@@ -46,8 +44,7 @@ class PasskeyService {
|
||||
|
||||
Future<void> openPasskeyPage(BuildContext context) async {
|
||||
try {
|
||||
final jwtToken = await getJwtToken();
|
||||
final url = "$accountsUrl/passkeys?token=$jwtToken";
|
||||
final url = await getAccountsUrl();
|
||||
await launchUrlString(
|
||||
url,
|
||||
mode: LaunchMode.externalApplication,
|
||||
|
||||
@@ -379,6 +379,7 @@ class UserService {
|
||||
if (response.statusCode == 200) {
|
||||
Widget page;
|
||||
final String passkeySessionID = response.data["passkeySessionID"];
|
||||
final String accountsUrl = response.data["accountsUrl"] ?? kAccountsUrl;
|
||||
String twoFASessionID = response.data["twoFactorSessionID"];
|
||||
if (twoFASessionID.isEmpty &&
|
||||
response.data["twoFactorSessionIDV2"] != null) {
|
||||
@@ -388,6 +389,7 @@ class UserService {
|
||||
page = PasskeyPage(
|
||||
passkeySessionID,
|
||||
totp2FASessionID: twoFASessionID,
|
||||
accountsUrl: accountsUrl,
|
||||
);
|
||||
} else if (twoFASessionID.isNotEmpty) {
|
||||
page = TwoFactorAuthenticationPage(twoFASessionID);
|
||||
@@ -692,6 +694,7 @@ class UserService {
|
||||
if (response.statusCode == 200) {
|
||||
Widget? page;
|
||||
final String passkeySessionID = response.data["passkeySessionID"];
|
||||
final String accountsUrl = response.data["accountsUrl"] ?? kAccountsUrl;
|
||||
String twoFASessionID = response.data["twoFactorSessionID"];
|
||||
if (twoFASessionID.isEmpty &&
|
||||
response.data["twoFactorSessionIDV2"] != null) {
|
||||
@@ -702,6 +705,7 @@ class UserService {
|
||||
page = PasskeyPage(
|
||||
passkeySessionID,
|
||||
totp2FASessionID: twoFASessionID,
|
||||
accountsUrl: accountsUrl,
|
||||
);
|
||||
} else if (twoFASessionID.isNotEmpty) {
|
||||
page = TwoFactorAuthenticationPage(twoFASessionID);
|
||||
|
||||
@@ -1,58 +1,63 @@
|
||||
import 'package:ente_auth/services/preference_service.dart';
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:ente_auth/theme/ente_theme.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/scheduler.dart';
|
||||
|
||||
class CodeTimerProgressCache {
|
||||
static final Map<int, CodeTimerProgress> _cache = {};
|
||||
|
||||
static CodeTimerProgress getCachedWidget(int period) {
|
||||
if (!_cache.containsKey(period)) {
|
||||
_cache[period] = CodeTimerProgress(period: period);
|
||||
}
|
||||
return _cache[period]!;
|
||||
}
|
||||
}
|
||||
|
||||
class CodeTimerProgress extends StatefulWidget {
|
||||
final int period;
|
||||
|
||||
final bool isCompactMode;
|
||||
const CodeTimerProgress({
|
||||
super.key,
|
||||
required this.period,
|
||||
this.isCompactMode = false,
|
||||
});
|
||||
|
||||
@override
|
||||
State<CodeTimerProgress> createState() => _CodeTimerProgressState();
|
||||
}
|
||||
|
||||
class _CodeTimerProgressState extends State<CodeTimerProgress>
|
||||
with SingleTickerProviderStateMixin {
|
||||
late final Ticker _ticker;
|
||||
class _CodeTimerProgressState extends State<CodeTimerProgress> {
|
||||
late final Timer _timer;
|
||||
late final ValueNotifier<double> _progress;
|
||||
late final int _microSecondsInPeriod;
|
||||
late bool _isCompactMode=false;
|
||||
late final int _periodInMicros;
|
||||
|
||||
// Reduce update frequency
|
||||
final int _updateIntervalMs =
|
||||
(Platform.isAndroid || Platform.isIOS) ? 16 : 500; // approximately 60 FPS
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_microSecondsInPeriod = widget.period * 1000000;
|
||||
_periodInMicros = widget.period * 1000000;
|
||||
_progress = ValueNotifier<double>(0.0);
|
||||
_ticker = createTicker(_updateTimeRemaining);
|
||||
_ticker.start();
|
||||
_isCompactMode = PreferenceService.instance.isCompactMode();
|
||||
_updateTimeRemaining(Duration.zero);
|
||||
_updateTimeRemaining(DateTime.now().microsecondsSinceEpoch);
|
||||
|
||||
_timer = Timer.periodic(Duration(milliseconds: _updateIntervalMs), (timer) {
|
||||
final now = DateTime.now().microsecondsSinceEpoch;
|
||||
_updateTimeRemaining(now);
|
||||
});
|
||||
}
|
||||
|
||||
void _updateTimeRemaining(Duration elapsed) {
|
||||
int timeRemaining = _microSecondsInPeriod -
|
||||
(DateTime.now().microsecondsSinceEpoch % _microSecondsInPeriod);
|
||||
_progress.value = timeRemaining / _microSecondsInPeriod;
|
||||
void _updateTimeRemaining(int currentMicros) {
|
||||
// More efficient time calculation using modulo
|
||||
final elapsed = (currentMicros) % _periodInMicros;
|
||||
final timeRemaining = _periodInMicros - elapsed;
|
||||
_progress.value = timeRemaining / _periodInMicros;
|
||||
}
|
||||
|
||||
@override
|
||||
void didUpdateWidget(covariant CodeTimerProgress oldWidget) {
|
||||
super.didUpdateWidget(oldWidget);
|
||||
if (oldWidget.period != widget.period) {
|
||||
_periodInMicros = widget.period * 1000000;
|
||||
_updateTimeRemaining(DateTime.now().microsecondsSinceEpoch);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_ticker.dispose();
|
||||
_timer.cancel();
|
||||
_progress.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
@@ -60,18 +65,19 @@ class _CodeTimerProgressState extends State<CodeTimerProgress>
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SizedBox(
|
||||
height: _isCompactMode ?1:3,
|
||||
height: widget.isCompactMode ? 1 : 3,
|
||||
child: ValueListenableBuilder<double>(
|
||||
valueListenable: _progress,
|
||||
builder: (context, progress, _) {
|
||||
return CustomPaint(
|
||||
key: Key(progress.toString()), // Add key here
|
||||
painter: _ProgressPainter(
|
||||
progress: progress,
|
||||
color: progress > 0.4
|
||||
? getEnteColorScheme(context).primary700
|
||||
: Colors.orange,
|
||||
),
|
||||
size: Size.infinite,
|
||||
size: const Size.fromHeight(double.infinity),
|
||||
);
|
||||
},
|
||||
),
|
||||
@@ -83,7 +89,10 @@ class _ProgressPainter extends CustomPainter {
|
||||
final double progress;
|
||||
final Color color;
|
||||
|
||||
_ProgressPainter({required this.progress, required this.color});
|
||||
const _ProgressPainter({
|
||||
required this.progress,
|
||||
required this.color,
|
||||
});
|
||||
|
||||
@override
|
||||
void paint(Canvas canvas, Size size) {
|
||||
|
||||
@@ -146,8 +146,10 @@ class _CodeWidgetState extends State<CodeWidget> {
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
if (widget.code.type.isTOTPCompatible)
|
||||
CodeTimerProgressCache.getCachedWidget(
|
||||
widget.code.period,
|
||||
CodeTimerProgress(
|
||||
key: ValueKey('period_${widget.code.period}'),
|
||||
period: widget.code.period,
|
||||
isCompactMode: widget.isCompactMode,
|
||||
),
|
||||
widget.isCompactMode
|
||||
? const SizedBox(height: 4)
|
||||
|
||||
@@ -21,8 +21,10 @@ Future<ButtonResult?> showDialogWidget({
|
||||
required List<ButtonWidget> buttons,
|
||||
IconData? icon,
|
||||
bool isDismissible = true,
|
||||
bool useRootNavigator = false,
|
||||
}) {
|
||||
return showDialog(
|
||||
useRootNavigator: useRootNavigator,
|
||||
barrierDismissible: isDismissible,
|
||||
barrierColor: backdropFaintDark,
|
||||
context: context,
|
||||
|
||||
@@ -4,6 +4,7 @@ import 'package:ente_auth/services/preference_service.dart';
|
||||
import 'package:ente_auth/theme/ente_theme.dart';
|
||||
import 'package:ente_auth/ui/utils/icon_utils.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
class CustomIconPage extends StatefulWidget {
|
||||
final Map<String, AllIconData> allIcons;
|
||||
@@ -29,12 +30,15 @@ class _CustomIconPageState extends State<CustomIconPage> {
|
||||
|
||||
// Used to request focus on the search box when clicked the search icon
|
||||
late FocusNode searchBoxFocusNode;
|
||||
final Set<LogicalKeyboardKey> _pressedKeys = <LogicalKeyboardKey>{};
|
||||
final ScrollController _scrollController = ScrollController();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
_filteredIcons = widget.allIcons;
|
||||
_showSearchBox = _autoFocusSearch;
|
||||
searchBoxFocusNode = FocusNode();
|
||||
ServicesBinding.instance.keyboard.addHandler(_handleKeyEvent);
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@@ -42,9 +46,41 @@ class _CustomIconPageState extends State<CustomIconPage> {
|
||||
void dispose() {
|
||||
_textController.dispose();
|
||||
searchBoxFocusNode.dispose();
|
||||
_scrollController.dispose();
|
||||
ServicesBinding.instance.keyboard.removeHandler(_handleKeyEvent);
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
bool _handleKeyEvent(KeyEvent event) {
|
||||
if (event is KeyDownEvent) {
|
||||
_pressedKeys.add(event.logicalKey);
|
||||
if ((_pressedKeys.contains(LogicalKeyboardKey.controlLeft) ||
|
||||
_pressedKeys.contains(LogicalKeyboardKey.control) ||
|
||||
_pressedKeys.contains(LogicalKeyboardKey.controlRight)) &&
|
||||
event.logicalKey == LogicalKeyboardKey.keyF) {
|
||||
setState(() {
|
||||
_showSearchBox = true;
|
||||
searchBoxFocusNode.requestFocus();
|
||||
_textController.clear();
|
||||
_searchText = "";
|
||||
});
|
||||
return true;
|
||||
}
|
||||
if (event.logicalKey == LogicalKeyboardKey.escape) {
|
||||
setState(() {
|
||||
_textController.clear();
|
||||
_searchText = "";
|
||||
_showSearchBox = false;
|
||||
_applyFilteringAndRefresh();
|
||||
});
|
||||
return true;
|
||||
}
|
||||
} else if (event is KeyUpEvent) {
|
||||
_pressedKeys.remove(event.logicalKey);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void _applyFilteringAndRefresh() {
|
||||
if (_searchText.isEmpty) {
|
||||
setState(() {
|
||||
@@ -120,91 +156,98 @@ class _CustomIconPageState extends State<CustomIconPage> {
|
||||
child: Column(
|
||||
children: [
|
||||
Expanded(
|
||||
child: GridView.builder(
|
||||
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: (MediaQuery.sizeOf(context).width ~/ 90)
|
||||
.clamp(1, double.infinity)
|
||||
.toInt(),
|
||||
crossAxisSpacing: 14,
|
||||
mainAxisSpacing: 14,
|
||||
childAspectRatio: 1,
|
||||
),
|
||||
itemCount: _filteredIcons.length,
|
||||
itemBuilder: (context, index) {
|
||||
final title = _filteredIcons.keys.elementAt(index);
|
||||
final iconData = _filteredIcons[title]!;
|
||||
IconType iconType = iconData.type;
|
||||
String? color = iconData.color;
|
||||
String? slug = iconData.slug;
|
||||
|
||||
Widget iconWidget;
|
||||
if (iconType == IconType.simpleIcon) {
|
||||
iconWidget = IconUtils.instance.getSVGIcon(
|
||||
"assets/simple-icons/icons/$title.svg",
|
||||
title,
|
||||
color,
|
||||
40,
|
||||
context,
|
||||
);
|
||||
} else {
|
||||
iconWidget = IconUtils.instance.getSVGIcon(
|
||||
"assets/custom-icons/icons/${slug ?? title}.svg",
|
||||
title,
|
||||
color,
|
||||
40,
|
||||
context,
|
||||
);
|
||||
}
|
||||
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
final newIcon = AllIconData(
|
||||
title: title,
|
||||
type: iconType,
|
||||
color: color,
|
||||
slug: slug,
|
||||
child: Scrollbar(
|
||||
controller: _scrollController,
|
||||
thumbVisibility: true,
|
||||
interactive: true,
|
||||
child: GridView.builder(
|
||||
controller: _scrollController,
|
||||
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: (MediaQuery.sizeOf(context).width ~/ 90)
|
||||
.clamp(1, double.infinity)
|
||||
.toInt(),
|
||||
crossAxisSpacing: 14,
|
||||
mainAxisSpacing: 14,
|
||||
childAspectRatio: 1,
|
||||
),
|
||||
itemCount: _filteredIcons.length,
|
||||
itemBuilder: (context, index) {
|
||||
final title = _filteredIcons.keys.elementAt(index);
|
||||
final iconData = _filteredIcons[title]!;
|
||||
IconType iconType = iconData.type;
|
||||
String? color = iconData.color;
|
||||
String? slug = iconData.slug;
|
||||
Widget iconWidget;
|
||||
if (iconType == IconType.simpleIcon) {
|
||||
final simpleIconPath = normalizeSimpleIconName(title);
|
||||
iconWidget = IconUtils.instance.getSVGIcon(
|
||||
"assets/simple-icons/icons/$simpleIconPath.svg",
|
||||
title,
|
||||
color,
|
||||
40,
|
||||
context,
|
||||
);
|
||||
Navigator.of(context).pop(newIcon);
|
||||
},
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(
|
||||
width: 1.5,
|
||||
color: title.toLowerCase() ==
|
||||
widget.currentIcon.toLowerCase()
|
||||
? getEnteColorScheme(context)
|
||||
.tagChipSelectedColor
|
||||
: Colors.transparent,
|
||||
),
|
||||
borderRadius: const BorderRadius.all(
|
||||
Radius.circular(12.0),
|
||||
),
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
const SizedBox(height: 8),
|
||||
Expanded(
|
||||
child: iconWidget,
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
Padding(
|
||||
padding: title.toLowerCase() ==
|
||||
} else {
|
||||
iconWidget = IconUtils.instance.getSVGIcon(
|
||||
"assets/custom-icons/icons/${slug ?? title}.svg",
|
||||
title,
|
||||
color,
|
||||
40,
|
||||
context,
|
||||
);
|
||||
}
|
||||
|
||||
return GestureDetector(
|
||||
key: ValueKey(title),
|
||||
onTap: () {
|
||||
final newIcon = AllIconData(
|
||||
title: title,
|
||||
type: iconType,
|
||||
color: color,
|
||||
slug: slug,
|
||||
);
|
||||
Navigator.of(context).pop(newIcon);
|
||||
},
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(
|
||||
width: 1.5,
|
||||
color: title.toLowerCase() ==
|
||||
widget.currentIcon.toLowerCase()
|
||||
? const EdgeInsets.only(left: 2, right: 2)
|
||||
: const EdgeInsets.all(0.0),
|
||||
child: Text(
|
||||
'${title[0].toUpperCase()}${title.substring(1)}',
|
||||
style: getEnteTextTheme(context).mini,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
maxLines: 1,
|
||||
),
|
||||
? getEnteColorScheme(context)
|
||||
.tagChipSelectedColor
|
||||
: Colors.transparent,
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
],
|
||||
borderRadius: const BorderRadius.all(
|
||||
Radius.circular(12.0),
|
||||
),
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
const SizedBox(height: 8),
|
||||
Expanded(
|
||||
child: iconWidget,
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
Padding(
|
||||
padding: title.toLowerCase() ==
|
||||
widget.currentIcon.toLowerCase()
|
||||
? const EdgeInsets.only(left: 2, right: 2)
|
||||
: const EdgeInsets.all(0.0),
|
||||
child: Text(
|
||||
'${title[0].toUpperCase()}${title.substring(1)}',
|
||||
style: getEnteTextTheme(context).mini,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
maxLines: 1,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
@@ -18,6 +18,7 @@ import 'package:ente_auth/services/preference_service.dart';
|
||||
import 'package:ente_auth/services/user_service.dart';
|
||||
import 'package:ente_auth/store/code_display_store.dart';
|
||||
import 'package:ente_auth/store/code_store.dart';
|
||||
import 'package:ente_auth/theme/text_style.dart';
|
||||
import 'package:ente_auth/ui/account/logout_dialog.dart';
|
||||
import 'package:ente_auth/ui/code_error_widget.dart';
|
||||
import 'package:ente_auth/ui/code_widget.dart';
|
||||
@@ -82,6 +83,7 @@ class _HomePageState extends State<HomePage> {
|
||||
bool isCompactMode = false;
|
||||
|
||||
late CodeSortKey _codeSortKey;
|
||||
final Set<LogicalKeyboardKey> _pressedKeys = <LogicalKeyboardKey>{};
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
@@ -108,6 +110,40 @@ class _HomePageState extends State<HomePage> {
|
||||
_showSearchBox = _autoFocusSearch;
|
||||
|
||||
searchBoxFocusNode = FocusNode();
|
||||
ServicesBinding.instance.keyboard.addHandler(_handleKeyEvent);
|
||||
}
|
||||
|
||||
bool _handleKeyEvent(KeyEvent event) {
|
||||
if (event is KeyDownEvent) {
|
||||
_pressedKeys.add(event.logicalKey);
|
||||
bool isMetaKeyPressed = Platform.isMacOS || Platform.isIOS
|
||||
? (_pressedKeys.contains(LogicalKeyboardKey.metaLeft) ||
|
||||
_pressedKeys.contains(LogicalKeyboardKey.meta) ||
|
||||
_pressedKeys.contains(LogicalKeyboardKey.metaRight))
|
||||
: (_pressedKeys.contains(LogicalKeyboardKey.controlLeft) ||
|
||||
_pressedKeys.contains(LogicalKeyboardKey.control) ||
|
||||
_pressedKeys.contains(LogicalKeyboardKey.controlRight));
|
||||
|
||||
if (isMetaKeyPressed && event.logicalKey == LogicalKeyboardKey.keyF) {
|
||||
setState(() {
|
||||
_showSearchBox = true;
|
||||
searchBoxFocusNode.requestFocus();
|
||||
});
|
||||
return true;
|
||||
}
|
||||
if (event.logicalKey == LogicalKeyboardKey.escape) {
|
||||
setState(() {
|
||||
_textController.clear();
|
||||
_searchText = "";
|
||||
_showSearchBox = false;
|
||||
_applyFilteringAndRefresh();
|
||||
});
|
||||
return true;
|
||||
}
|
||||
} else if (event is KeyUpEvent) {
|
||||
_pressedKeys.remove(event.logicalKey);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void _loadCodes() {
|
||||
@@ -207,8 +243,9 @@ class _HomePageState extends State<HomePage> {
|
||||
_streamSubscription?.cancel();
|
||||
_triggerLogoutEvent?.cancel();
|
||||
_iconsChangedEvent?.cancel();
|
||||
_textController.dispose();
|
||||
_textController.removeListener(_applyFilteringAndRefresh);
|
||||
|
||||
ServicesBinding.instance.keyboard.removeHandler(_handleKeyEvent);
|
||||
searchBoxFocusNode.dispose();
|
||||
|
||||
super.dispose();
|
||||
@@ -354,7 +391,7 @@ class _HomePageState extends State<HomePage> {
|
||||
resizeToAvoidBottomInset: false,
|
||||
appBar: AppBar(
|
||||
title: !_showSearchBox
|
||||
? const Text('Ente Auth')
|
||||
? const Text('Ente Auth', style: brandStyleMedium)
|
||||
: TextField(
|
||||
autocorrect: false,
|
||||
enableSuggestions: false,
|
||||
|
||||
@@ -5,7 +5,6 @@ import 'package:ente_auth/core/configuration.dart';
|
||||
import 'package:ente_auth/core/errors.dart';
|
||||
import 'package:ente_auth/l10n/l10n.dart';
|
||||
import 'package:ente_auth/models/account/two_factor.dart';
|
||||
import 'package:ente_auth/services/passkey_service.dart';
|
||||
import 'package:ente_auth/services/user_service.dart';
|
||||
import 'package:ente_auth/ui/components/buttons/button_widget.dart';
|
||||
import 'package:ente_auth/ui/components/models/button_type.dart';
|
||||
@@ -20,10 +19,12 @@ import 'package:url_launcher/url_launcher_string.dart';
|
||||
class PasskeyPage extends StatefulWidget {
|
||||
final String sessionID;
|
||||
final String totp2FASessionID;
|
||||
final String accountsUrl;
|
||||
|
||||
const PasskeyPage(
|
||||
this.sessionID, {
|
||||
required this.totp2FASessionID,
|
||||
required this.accountsUrl,
|
||||
super.key,
|
||||
});
|
||||
|
||||
@@ -47,9 +48,8 @@ class _PasskeyPageState extends State<PasskeyPage> {
|
||||
}
|
||||
|
||||
Future<void> launchPasskey() async {
|
||||
final String accountsUrl = PasskeyService.instance.accountsUrl;
|
||||
await launchUrlString(
|
||||
"$accountsUrl/passkeys/verify?"
|
||||
"${widget.accountsUrl}/passkeys/verify?"
|
||||
"passkeySessionID=${widget.sessionID}"
|
||||
"&redirect=enteauth://passkey"
|
||||
"&clientPackage=io.ente.auth",
|
||||
|
||||
@@ -20,6 +20,14 @@ class _ReorderCodesPageState extends State<ReorderCodesPage> {
|
||||
bool hasChanged = false;
|
||||
final logger = Logger('ReorderCodesPage');
|
||||
|
||||
final ScrollController _scrollController = ScrollController();
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_scrollController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final bool isCompactMode = PreferenceService.instance.isCompactMode();
|
||||
@@ -55,33 +63,40 @@ class _ReorderCodesPageState extends State<ReorderCodesPage> {
|
||||
),
|
||||
],
|
||||
),
|
||||
body: ReorderableListView(
|
||||
buildDefaultDragHandles: false,
|
||||
proxyDecorator: (Widget child, int index, Animation<double> animation) {
|
||||
return AnimatedBuilder(
|
||||
animation: animation,
|
||||
builder: (BuildContext context, _) {
|
||||
final animValue = Curves.easeInOut.transform(animation.value);
|
||||
final scale = lerpDouble(1, 1.05, animValue)!;
|
||||
return Transform.scale(scale: scale, child: child);
|
||||
},
|
||||
);
|
||||
},
|
||||
children: [
|
||||
for (final code in widget.codes)
|
||||
ReorderableDragStartListener(
|
||||
key: ValueKey('${code.hashCode}_${code.generatedID}'),
|
||||
index: widget.codes.indexOf(code),
|
||||
child: CodeWidget(
|
||||
key: ValueKey(code.generatedID),
|
||||
code,
|
||||
isCompactMode: isCompactMode,
|
||||
body: Scrollbar(
|
||||
controller: _scrollController,
|
||||
thumbVisibility: true,
|
||||
interactive: true,
|
||||
child: ReorderableListView(
|
||||
scrollController: _scrollController,
|
||||
buildDefaultDragHandles: false,
|
||||
proxyDecorator:
|
||||
(Widget child, int index, Animation<double> animation) {
|
||||
return AnimatedBuilder(
|
||||
animation: animation,
|
||||
builder: (BuildContext context, _) {
|
||||
final animValue = Curves.easeInOut.transform(animation.value);
|
||||
final scale = lerpDouble(1, 1.05, animValue)!;
|
||||
return Transform.scale(scale: scale, child: child);
|
||||
},
|
||||
);
|
||||
},
|
||||
children: [
|
||||
for (final code in widget.codes)
|
||||
ReorderableDragStartListener(
|
||||
key: ValueKey('${code.hashCode}_${code.generatedID}'),
|
||||
index: widget.codes.indexOf(code),
|
||||
child: CodeWidget(
|
||||
key: ValueKey(code.generatedID),
|
||||
code,
|
||||
isCompactMode: isCompactMode,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
onReorder: (oldIndex, newIndex) {
|
||||
updateCodeIndex(oldIndex, newIndex);
|
||||
},
|
||||
],
|
||||
onReorder: (oldIndex, newIndex) {
|
||||
updateCodeIndex(oldIndex, newIndex);
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -70,10 +70,12 @@ class DataSectionWidget extends StatelessWidget {
|
||||
await DeduplicationService.instance.getDuplicateCodes();
|
||||
if (duplicateCodes.isEmpty) {
|
||||
unawaited(
|
||||
showErrorDialog(
|
||||
showChoiceDialog(
|
||||
context,
|
||||
l10n.noDuplicates,
|
||||
l10n.youveNoDuplicateCodesThatCanBeCleared,
|
||||
title: l10n.noDuplicates,
|
||||
firstButtonLabel: "OK",
|
||||
secondButtonLabel: null,
|
||||
body: l10n.youveNoDuplicateCodesThatCanBeCleared,
|
||||
),
|
||||
);
|
||||
return;
|
||||
|
||||
@@ -39,9 +39,9 @@ Future<void> handleExportClick(BuildContext context) async {
|
||||
isInAlert: true,
|
||||
buttonAction: ButtonAction.second,
|
||||
),
|
||||
const ButtonWidget(
|
||||
ButtonWidget(
|
||||
buttonType: ButtonType.secondary,
|
||||
labelText: "HTML",
|
||||
labelText: context.l10n.plainHTML,
|
||||
buttonSize: ButtonSize.large,
|
||||
isInAlert: true,
|
||||
buttonAction: ButtonAction.third,
|
||||
|
||||
@@ -33,29 +33,29 @@ Future<String> generateQRImageBase64(String data) async {
|
||||
return base64Encode(pngBytes);
|
||||
}
|
||||
|
||||
Future<String> generateOTPEntryHtml(
|
||||
Code code,
|
||||
BuildContext context,
|
||||
) async {
|
||||
Future<String> generateOTPEntryHtml(Code code, BuildContext context) async {
|
||||
final qrBase64 = await generateQRImageBase64(code.rawData);
|
||||
String notes = code.display.note;
|
||||
if (notes.isNotEmpty) {
|
||||
notes = '<p>Note: <b>$notes</b></p>';
|
||||
notes = '<p class="group">Note: <b>$notes</b></p>';
|
||||
}
|
||||
return '''
|
||||
<div class="otp-entry">
|
||||
<div>
|
||||
<p><b>${code.issuer}</b> </p>
|
||||
<p><b>${code.account}</b></p>
|
||||
<br />
|
||||
<p>Type: <b>${code.type.name}</b></p>
|
||||
<p>Algorithm: <b>${code.algorithm.name}</b></p>
|
||||
<p>Digits: <b>${code.digits}</b></p>
|
||||
<p>Recovery Code: <b>${code.secret}</b></p>
|
||||
$notes
|
||||
</div>
|
||||
<img src="data:image/png;base64,$qrBase64" alt="QR Code">
|
||||
</div>
|
||||
<table class="otp-entry">
|
||||
<tr>
|
||||
<td>
|
||||
<p><b>${code.issuer}</b></p>
|
||||
<p><b>${code.account}</b></p>
|
||||
<p class="group">Type: <b>${code.type.name}</b></p>
|
||||
<p>Algorithm: <b>${code.algorithm.name}</b></p>
|
||||
<p>Digits: <b>${code.digits}</b></p>
|
||||
<p>Secret: <b>${code.secret}</b></p>
|
||||
$notes
|
||||
</td>
|
||||
<td class="otp-qr">
|
||||
<img src="data:image/png;base64,$qrBase64" alt="QR Code">
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<br/>
|
||||
<hr class="red-separator" />
|
||||
<br/>
|
||||
@@ -80,116 +80,144 @@ Future<String> generateHtml(BuildContext context) async {
|
||||
<meta content="text/html; charset=utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
|
||||
<style>
|
||||
body {
|
||||
background-color: #f0f1f3;
|
||||
font-family: "Helvetica Neue", "Segoe UI", Helvetica, sans-serif;
|
||||
font-size: 16px;
|
||||
line-height: 27px;
|
||||
margin: 0;
|
||||
color: #444;
|
||||
}
|
||||
body {
|
||||
background-color: #f0f1f3;
|
||||
font-family: "Helvetica Neue", "Segoe UI", Helvetica, sans-serif;
|
||||
font-size: 16px;
|
||||
line-height: 27px;
|
||||
margin: 0;
|
||||
color: #444;
|
||||
}
|
||||
|
||||
pre {
|
||||
background: #f4f4f4f4;
|
||||
padding: 2px;
|
||||
}
|
||||
pre {
|
||||
background: #f4f4f4f4;
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
border: 1px solid #ddd;
|
||||
}
|
||||
table {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
table td {
|
||||
border-color: #ddd;
|
||||
padding: 5px;
|
||||
}
|
||||
table td {
|
||||
border-color: #ddd;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.wrap {
|
||||
background-color: #fff;
|
||||
padding: 30px;
|
||||
max-width: 600px;
|
||||
margin: 0 auto;
|
||||
border-radius: 5px;
|
||||
}
|
||||
.wrap {
|
||||
background-color: #fff;
|
||||
padding: 30px;
|
||||
max-width: 600px;
|
||||
margin: 0 auto;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.button {
|
||||
background: #0055d4;
|
||||
border-radius: 3px;
|
||||
text-decoration: none !important;
|
||||
color: #fff !important;
|
||||
font-weight: bold;
|
||||
padding: 10px 30px;
|
||||
display: inline-block;
|
||||
}
|
||||
.button {
|
||||
background: #0055d4;
|
||||
border-radius: 3px;
|
||||
text-decoration: none !important;
|
||||
color: #fff !important;
|
||||
font-weight: bold;
|
||||
padding: 10px 30px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.button:hover {
|
||||
background: #111;
|
||||
}
|
||||
.button:hover {
|
||||
background: #111;
|
||||
}
|
||||
|
||||
.footer {
|
||||
text-align: center;
|
||||
font-size: 12px;
|
||||
color: #888;
|
||||
}
|
||||
.footer {
|
||||
text-align: center;
|
||||
font-size: 12px;
|
||||
color: #888;
|
||||
}
|
||||
|
||||
.footer a {
|
||||
color: #888;
|
||||
margin-right: 5px;
|
||||
}
|
||||
.footer a {
|
||||
color: #888;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.gutter {
|
||||
padding: 30px;
|
||||
}
|
||||
.gutter {
|
||||
padding: 30px;
|
||||
}
|
||||
|
||||
img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #0055d4;
|
||||
}
|
||||
a {
|
||||
color: #0055d4;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: #111;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 700px) {
|
||||
.wrap {
|
||||
max-width: auto;
|
||||
}
|
||||
|
||||
.gutter {
|
||||
padding: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.footer-icons {
|
||||
padding: 4px !important;
|
||||
width: 24px !important;
|
||||
}
|
||||
a:hover {
|
||||
color: #111;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 700px) {
|
||||
.otp-entry {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.otp-entry div {
|
||||
flex: 1;
|
||||
.otp-entry td {
|
||||
display: block;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.otp-entry p {
|
||||
margin: 2px 0;
|
||||
.otp-qr img {
|
||||
margin-top: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
hr.red-separator {
|
||||
border: none;
|
||||
height: 1px;
|
||||
background-color: rgb(173, 0, 255);
|
||||
}
|
||||
.footer-icons {
|
||||
padding: 4px !important;
|
||||
width: 24px !important;
|
||||
}
|
||||
|
||||
</style>
|
||||
.otp-entry {
|
||||
width: 100%;
|
||||
table-layout: fixed;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
.otp-entry td {
|
||||
padding: 20px;
|
||||
margin: 0px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.otp-entry td:first-child {
|
||||
width: 70%;
|
||||
word-wrap: break-word;
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
|
||||
.otp-qr img {
|
||||
max-width: 200px;
|
||||
height: auto;
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.otp-entry td.otp-qr {
|
||||
width: 30%;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.otp-entry p {
|
||||
margin: 2px 0;
|
||||
}
|
||||
|
||||
.otp-entry p.group {
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
hr.red-separator {
|
||||
border: none;
|
||||
height: 1px;
|
||||
background-color: rgb(173, 0, 255);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1 style="text-align: center;">Ente Auth</h1>
|
||||
|
||||
@@ -329,7 +329,7 @@ class _LockScreenState extends State<LockScreen> with WidgetsBindingObserver {
|
||||
_isShowingLockScreen = false;
|
||||
if (result) {
|
||||
lastAuthenticatingTime = DateTime.now().millisecondsSinceEpoch;
|
||||
AppLock.of(context)!.didUnlock();
|
||||
AppLock.of(context)?.didUnlock();
|
||||
await _lockscreenSetting.setInvalidAttemptCount(0);
|
||||
setState(() {
|
||||
lockedTimeInSeconds = 15;
|
||||
|
||||
@@ -121,8 +121,9 @@ class IconUtils {
|
||||
context,
|
||||
);
|
||||
} else if (_simpleIcons.containsKey(title)) {
|
||||
final simpleIconPath = normalizeSimpleIconName(title);
|
||||
return getSVGIcon(
|
||||
"assets/simple-icons/icons/$title.svg",
|
||||
"assets/simple-icons/icons/$simpleIconPath.svg",
|
||||
title,
|
||||
_simpleIcons[title],
|
||||
width,
|
||||
@@ -199,7 +200,7 @@ class IconUtils {
|
||||
final simpleIconData = await rootBundle
|
||||
.loadString('assets/simple-icons/_data/simple-icons.json');
|
||||
final simpleIcons = json.decode(simpleIconData);
|
||||
for (final icon in simpleIcons["icons"]) {
|
||||
for (final icon in simpleIcons) {
|
||||
_simpleIcons[icon["title"]
|
||||
.toString()
|
||||
.replaceAll(' ', '')
|
||||
@@ -220,14 +221,14 @@ class IconUtils {
|
||||
for (final name in icon["altNames"]) {
|
||||
_customIcons[name.toString().replaceAll(' ', '').toLowerCase()] =
|
||||
CustomIconData(
|
||||
icon["slug"],
|
||||
icon["slug"] ?? ((icon["title"] as String).toLowerCase()),
|
||||
icon["hex"],
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
Logger("IconUtils").severe("Error loading icons", e);
|
||||
} catch (e, s) {
|
||||
Logger("IconUtils").severe("Error loading icons", e, s);
|
||||
if (kDebugMode) {
|
||||
rethrow;
|
||||
}
|
||||
@@ -245,3 +246,43 @@ class CustomIconData {
|
||||
|
||||
CustomIconData(this.slug, this.color);
|
||||
}
|
||||
|
||||
final charMap = {
|
||||
'á': 'a',
|
||||
'à': 'a',
|
||||
'â': 'a',
|
||||
'ä': 'a',
|
||||
'é': 'e',
|
||||
'è': 'e',
|
||||
'ê': 'e',
|
||||
'ë': 'e',
|
||||
'í': 'i',
|
||||
'ì': 'i',
|
||||
'î': 'i',
|
||||
'ï': 'i',
|
||||
'ó': 'o',
|
||||
'ò': 'o',
|
||||
'ô': 'o',
|
||||
'ö': 'o',
|
||||
'ú': 'u',
|
||||
'ù': 'u',
|
||||
'û': 'u',
|
||||
'ü': 'u',
|
||||
'ç': 'c',
|
||||
'ñ': 'n',
|
||||
'.': 'dot',
|
||||
'-': '',
|
||||
'&': 'and',
|
||||
'+': 'plus',
|
||||
':': '',
|
||||
"'": '',
|
||||
'/': '',
|
||||
'!': '',
|
||||
};
|
||||
String normalizeSimpleIconName(String input) {
|
||||
final buffer = StringBuffer();
|
||||
for (var char in input.characters) {
|
||||
buffer.write(charMap[char] ?? char);
|
||||
}
|
||||
return buffer.toString().trim();
|
||||
}
|
||||
|
||||
@@ -413,9 +413,11 @@ Future<dynamic> showTextInputDialog(
|
||||
TextCapitalization textCapitalization = TextCapitalization.none,
|
||||
bool alwaysShowSuccessState = false,
|
||||
bool isPasswordInput = false,
|
||||
bool useRootNavigator = false,
|
||||
}) {
|
||||
return showDialog(
|
||||
barrierColor: backdropFaintDark,
|
||||
useRootNavigator: useRootNavigator,
|
||||
context: context,
|
||||
builder: (context) {
|
||||
final bottomInset = MediaQuery.of(context).viewInsets.bottom;
|
||||
|
||||
@@ -174,4 +174,4 @@ SPEC CHECKSUMS:
|
||||
|
||||
PODFILE CHECKSUM: f401c31c8f7c5571f6f565c78915d54338812dab
|
||||
|
||||
COCOAPODS: 1.15.2
|
||||
COCOAPODS: 1.16.2
|
||||
|
||||
@@ -429,6 +429,7 @@
|
||||
"@executable_path/../Frameworks",
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.14;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = io.ente.auth.mac;
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SWIFT_VERSION = 5.0;
|
||||
|
||||
@@ -42,10 +42,10 @@ packages:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: app_links
|
||||
sha256: ad1a6d598e7e39b46a34f746f9a8b011ee147e4c275d407fa457e7a62f84dd99
|
||||
sha256: "433df2e61b10519407475d7f69e470789d23d593f28224c38ba1068597be7950"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.3.2"
|
||||
version: "6.3.3"
|
||||
app_links_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -528,10 +528,10 @@ packages:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: flutter_inappwebview
|
||||
sha256: "93cfcca02bdda4b26cd700cf70d9ddba09d8348e3e8f2857638c23ed23a4fcb4"
|
||||
sha256: "80092d13d3e29b6227e25b67973c67c7210bd5e35c4b747ca908e31eb71a46d5"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.1.4"
|
||||
version: "6.1.5"
|
||||
flutter_inappwebview_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -584,10 +584,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_inappwebview_windows
|
||||
sha256: "95ebc65aecfa63b2084c822aec6ba0545f0a0afaa3899f2c752ec96c09108db5"
|
||||
sha256: "8b4d3a46078a2cdc636c4a3d10d10f2a16882f6be607962dbfff8874d1642055"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.5.0+2"
|
||||
version: "0.6.0"
|
||||
flutter_launcher_icons:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@@ -985,10 +985,10 @@ packages:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: logging
|
||||
sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340"
|
||||
sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
version: "1.3.0"
|
||||
macros:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -1655,10 +1655,10 @@ packages:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: url_launcher
|
||||
sha256: "21b704ce5fa560ea9f3b525b43601c678728ba46725bab9b01187b4831377ed3"
|
||||
sha256: "9d06212b1362abc2f0f0d78e6f09f726608c74e3b9462e8368bb03314aa8d603"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.3.0"
|
||||
version: "6.3.1"
|
||||
url_launcher_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -1668,7 +1668,7 @@ packages:
|
||||
source: hosted
|
||||
version: "6.3.11"
|
||||
url_launcher_ios:
|
||||
dependency: transitive
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: url_launcher_ios
|
||||
sha256: e43b677296fadce447e987a2f519dcf5f6d1e527dc35d01ffab4fff5b8a7063e
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
name: ente_auth
|
||||
description: ente two-factor authenticator
|
||||
version: 4.1.8+418
|
||||
version: 4.2.3+423
|
||||
publish_to: none
|
||||
|
||||
environment:
|
||||
@@ -8,7 +8,7 @@ environment:
|
||||
|
||||
dependencies:
|
||||
adaptive_theme: ^3.1.0 # done
|
||||
app_links: ^6.2.1
|
||||
app_links: ^6.3.3
|
||||
archive: ^3.3.7
|
||||
auto_size_text: ^3.0.0
|
||||
base32: ^2.1.3
|
||||
@@ -44,7 +44,7 @@ dependencies:
|
||||
flutter_context_menu: ^0.2.0
|
||||
flutter_displaymode: ^0.6.0
|
||||
flutter_email_sender: ^6.0.2
|
||||
flutter_inappwebview: ^6.0.0
|
||||
flutter_inappwebview: ^6.1.5
|
||||
flutter_launcher_icons: ^0.14.1
|
||||
flutter_local_authentication:
|
||||
git:
|
||||
@@ -98,7 +98,8 @@ dependencies:
|
||||
styled_text: ^8.1.0
|
||||
tray_manager: ^0.2.1
|
||||
tuple: ^2.0.0
|
||||
url_launcher: ^6.1.5
|
||||
url_launcher: ^6.3.1
|
||||
url_launcher_ios: ^6.3.1
|
||||
uuid: ^4.2.2
|
||||
win32: ^5.1.1
|
||||
window_manager: ^0.4.2
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM golang:1.20-alpine3.17 AS builder
|
||||
FROM golang:1.23-alpine3.21 AS builder
|
||||
RUN apk add --no-cache gcc musl-dev git build-base pkgconfig libsodium-dev
|
||||
|
||||
ENV GOOS=linux
|
||||
@@ -14,7 +14,7 @@ COPY . .
|
||||
RUN --mount=type=cache,target=/root/.cache/go-build \
|
||||
go build -o ente-cli main.go
|
||||
|
||||
FROM alpine:3.17
|
||||
FROM alpine:3.21
|
||||
RUN apk add libsodium-dev
|
||||
COPY --from=builder /etc/ente/ente-cli .
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM golang:1.20-alpine3.17@sha256:9c2f89db6fda13c3c480749787f62fed5831699bb2c32881b8f327f1cf7bae42 AS builder386
|
||||
FROM golang:1.23-alpine3.21@sha256:6c5c9590f169f77c8046e45c611d3b28fe477789acd8d3762d23d4744de69812 AS builder386
|
||||
RUN apt-get update
|
||||
RUN apt-get install -y gcc
|
||||
RUN apt-get install -y git
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
module github.com/ente-io/cli
|
||||
|
||||
go 1.20
|
||||
go 1.23
|
||||
|
||||
require (
|
||||
github.com/go-resty/resty/v2 v2.7.0
|
||||
@@ -33,7 +33,7 @@ require (
|
||||
github.com/spf13/cast v1.5.1 // indirect
|
||||
github.com/spf13/cobra v1.7.0
|
||||
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/spf13/pflag v1.0.5
|
||||
github.com/spf13/viper v1.16.0
|
||||
github.com/subosito/gotenv v1.6.0 // indirect
|
||||
go.etcd.io/bbolt v1.3.7
|
||||
|
||||
@@ -64,6 +64,7 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7
|
||||
github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs=
|
||||
github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw=
|
||||
github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY=
|
||||
github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
||||
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
|
||||
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
|
||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||
@@ -110,6 +111,7 @@ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
||||
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||
github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||
@@ -146,9 +148,11 @@ github.com/kong/go-srp v0.0.0-20191210190804-cde1efa3c083/go.mod h1:Zde5RRLiH8/2
|
||||
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
|
||||
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
|
||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||
@@ -169,6 +173,7 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
|
||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/spf13/afero v1.9.5 h1:stMpOSZFs//0Lv29HduCmli3GUfpFoF3Y1Q/aXj/wVM=
|
||||
|
||||
@@ -2,56 +2,56 @@
|
||||
|
||||
## v1.7.8 (Unreleased)
|
||||
|
||||
- .
|
||||
- .
|
||||
|
||||
## v1.7.7
|
||||
|
||||
- Retain JPEG originals even on date modifications.
|
||||
- Support Portuguese and Vietnamese translations.
|
||||
- Retain JPEG originals even on date modifications.
|
||||
- Support Portuguese and Vietnamese translations.
|
||||
|
||||
## v1.7.6
|
||||
|
||||
- Face merging and suggestions (beta).
|
||||
- Parse description from metadata JSON.
|
||||
- Support Italian, Ukrainian and Lithuanian translations.
|
||||
- Fix an out of memory crash on uploading large libraries.
|
||||
- Face merging and suggestions (beta).
|
||||
- Parse description from metadata JSON.
|
||||
- Support Italian, Ukrainian and Lithuanian translations.
|
||||
- Fix an out of memory crash on uploading large libraries.
|
||||
|
||||
## v1.7.5
|
||||
|
||||
- Face grouping (beta).
|
||||
- Include shared files in export.
|
||||
- Directly upload to selected album on drag and drop.
|
||||
- Improve heuristics for clubbing a photo and video into a live photo.
|
||||
- Face grouping (beta).
|
||||
- Include shared files in export.
|
||||
- Directly upload to selected album on drag and drop.
|
||||
- Improve heuristics for clubbing a photo and video into a live photo.
|
||||
|
||||
## v1.7.4
|
||||
|
||||
- Improved date search, including support for day of week and hour of day.
|
||||
- Fix video thumbnail generation and upload on Intel macOS.
|
||||
- Club a photo and video into a live photo only if both are within 2 minutes.
|
||||
- Fix an issue causing ZIP uploads to sometimes fail.
|
||||
- Improved date search, including support for day of week and hour of day.
|
||||
- Fix video thumbnail generation and upload on Intel macOS.
|
||||
- Club a photo and video into a live photo only if both are within 2 minutes.
|
||||
- Fix an issue causing ZIP uploads to sometimes fail.
|
||||
|
||||
## v1.7.3
|
||||
|
||||
- Face recognition and magic search (public beta).
|
||||
- Support Polish translations.
|
||||
- Face recognition and magic search (public beta).
|
||||
- Support Polish translations.
|
||||
|
||||
## v1.7.2
|
||||
|
||||
- Significantly improve the speed of the metadata parsing step during imports
|
||||
of Google takeouts.
|
||||
- Add a option to set and use a custom endpoint.
|
||||
- Fix an issue preventing subscription purchases and renewals.
|
||||
- Clear cached password after changing it on a different device.
|
||||
- Reconcile exported files with disk on app start and resync.
|
||||
- Significantly improve the speed of the metadata parsing step during imports of
|
||||
Google takeouts.
|
||||
- Add a option to set and use a custom endpoint.
|
||||
- Fix an issue preventing subscription purchases and renewals.
|
||||
- Clear cached password after changing it on a different device.
|
||||
- Reconcile exported files with disk on app start and resync.
|
||||
|
||||
## v1.7.1
|
||||
|
||||
- Support for passkeys as a second factor authentication mechanism.
|
||||
- Remember the window size across app restarts.
|
||||
- Revert changes to the Linux icon.
|
||||
- Fix an issue causing deleted items in watched folders to not move to
|
||||
uncategorized.
|
||||
- Fix duplicate file uploads when initializing a folder watch (sometimes).
|
||||
- Support for passkeys as a second factor authentication mechanism.
|
||||
- Remember the window size across app restarts.
|
||||
- Revert changes to the Linux icon.
|
||||
- Fix an issue causing deleted items in watched folders to not move to
|
||||
uncategorized.
|
||||
- Fix duplicate file uploads when initializing a folder watch (sometimes).
|
||||
|
||||
## v1.7.0
|
||||
|
||||
@@ -61,138 +61,138 @@ communicate only using a predefined IPC boundary.
|
||||
|
||||
Other highlights:
|
||||
|
||||
- View your photos on big screens and Chromecast devices by using the "Play
|
||||
album on TV" option in the album menu.
|
||||
- Support Brazilian Portuguese, German and Russian.
|
||||
- Provide a checkbox to select all photos in a day.
|
||||
- Fix a case where the dedup screen would not refresh after removing items.
|
||||
- View your photos on big screens and Chromecast devices by using the "Play
|
||||
album on TV" option in the album menu.
|
||||
- Support Brazilian Portuguese, German and Russian.
|
||||
- Provide a checkbox to select all photos in a day.
|
||||
- Fix a case where the dedup screen would not refresh after removing items.
|
||||
|
||||
## v1.6.63
|
||||
|
||||
### New
|
||||
|
||||
- Option to select file download location.
|
||||
- Add support for searching popular cities
|
||||
- Sorted duplicates in desecending order of size
|
||||
- Add Counter to upload section
|
||||
- Display full name and collection name on hover on dedupe screen photos
|
||||
- Option to select file download location.
|
||||
- Add support for searching popular cities
|
||||
- Sorted duplicates in desecending order of size
|
||||
- Add Counter to upload section
|
||||
- Display full name and collection name on hover on dedupe screen photos
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- Fix add to album padding issue
|
||||
- Fix double uncategorized album issue
|
||||
- Hide Hidden collection files from all section
|
||||
- Fix add to album padding issue
|
||||
- Fix double uncategorized album issue
|
||||
- Hide Hidden collection files from all section
|
||||
|
||||
## v1.6.62
|
||||
|
||||
### New
|
||||
|
||||
- Integrated onnx clip runner
|
||||
- Integrated onnx clip runner
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- Fixes login button requiring double click issue
|
||||
- Fixes Collection sort state not preserved issue
|
||||
- Fixes continuous export causing app crash
|
||||
- Improves ML related copies for better distinction from clip
|
||||
- Added Better favicon for light mode
|
||||
- Fixed face indexing issues
|
||||
- Fixed thumbnail load issue
|
||||
- Fixes login button requiring double click issue
|
||||
- Fixes Collection sort state not preserved issue
|
||||
- Fixes continuous export causing app crash
|
||||
- Improves ML related copies for better distinction from clip
|
||||
- Added Better favicon for light mode
|
||||
- Fixed face indexing issues
|
||||
- Fixed thumbnail load issue
|
||||
|
||||
## v1.6.60
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- Fix Thumbnail Orientation issue
|
||||
- Fix ML logging issue
|
||||
- Fix Thumbnail Orientation issue
|
||||
- Fix ML logging issue
|
||||
|
||||
## v1.6.59
|
||||
|
||||
### New
|
||||
|
||||
- Added arm64 builds for linux
|
||||
- Added arm64 builds for linux
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- Fix Editor file not loading issue
|
||||
- Fix ML results missing thumbnail issue
|
||||
- Fix Editor file not loading issue
|
||||
- Fix ML results missing thumbnail issue
|
||||
|
||||
## v1.6.58
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- Fix File load issue
|
||||
- Fix File load issue
|
||||
|
||||
## v1.6.57
|
||||
|
||||
### New Features
|
||||
|
||||
- Added encrypted Disk caching for files
|
||||
- Added option to customize cache folder location
|
||||
- Added encrypted Disk caching for files
|
||||
- Added option to customize cache folder location
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- Fixed caching issue,causing multiple download of file during ml sync
|
||||
- Fixed caching issue,causing multiple download of file during ml sync
|
||||
|
||||
## v1.6.55
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- Added manage family portal option if add-on is active
|
||||
- Fixed filename date parsing issue
|
||||
- Fixed storage limit ui glitch
|
||||
- Fixed dedupe page layout issue
|
||||
- Fixed ElectronAPI refactoring issue
|
||||
- Fixed Search related issues
|
||||
- Added manage family portal option if add-on is active
|
||||
- Fixed filename date parsing issue
|
||||
- Fixed storage limit ui glitch
|
||||
- Fixed dedupe page layout issue
|
||||
- Fixed ElectronAPI refactoring issue
|
||||
- Fixed Search related issues
|
||||
|
||||
## v1.6.54
|
||||
|
||||
### New Features
|
||||
|
||||
- Added support for HEIC and raw image in photo editor
|
||||
- Added support for HEIC and raw image in photo editor
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- Fixed 16bit HDR HEIC images support
|
||||
- Fixed blocked login due safe storage issue
|
||||
- Fixed Search related issues
|
||||
- Fixed issue of watch folder not cleared on logout
|
||||
- other under the hood ui/ux improvements
|
||||
- Fixed 16bit HDR HEIC images support
|
||||
- Fixed blocked login due safe storage issue
|
||||
- Fixed Search related issues
|
||||
- Fixed issue of watch folder not cleared on logout
|
||||
- other under the hood ui/ux improvements
|
||||
|
||||
## v1.6.53
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- Fixed watch folder disabled issue
|
||||
- Fixed BF Add on related issues
|
||||
- Fixed clip sync issue and added better logging
|
||||
- Fixed mov file upload
|
||||
- Fixed clip extraction related issue
|
||||
- Fixed watch folder disabled issue
|
||||
- Fixed BF Add on related issues
|
||||
- Fixed clip sync issue and added better logging
|
||||
- Fixed mov file upload
|
||||
- Fixed clip extraction related issue
|
||||
|
||||
## v1.6.52
|
||||
|
||||
### New Features
|
||||
|
||||
- Added Clip Desktop on windows
|
||||
- Added Clip Desktop on windows
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- fixed google json matching issue
|
||||
- other under-the-hood changes to improve performance and bug fixes
|
||||
- fixed google json matching issue
|
||||
- other under-the-hood changes to improve performance and bug fixes
|
||||
|
||||
## v1.6.50
|
||||
|
||||
### New Features
|
||||
|
||||
- Added Clip desktop
|
||||
- Added Clip desktop
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- Fixed desktop downloaded file had extra dot in the name
|
||||
- Cleanup error messages
|
||||
- fix the motion photo clustering issue
|
||||
- Add option to disable cf proxy locally
|
||||
- other under-the-hood changes to improve UX
|
||||
- Fixed desktop downloaded file had extra dot in the name
|
||||
- Cleanup error messages
|
||||
- fix the motion photo clustering issue
|
||||
- Add option to disable cf proxy locally
|
||||
- other under-the-hood changes to improve UX
|
||||
|
||||
## v1.6.49
|
||||
|
||||
@@ -205,63 +205,63 @@ to know about feature and functionalities.
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- Fixed misaligned icons in photo-viewer
|
||||
- Fixed issue with Motion photo upload
|
||||
- Fixed issue with Live-photo upload
|
||||
- other minor ux improvement
|
||||
- Fixed misaligned icons in photo-viewer
|
||||
- Fixed issue with Motion photo upload
|
||||
- Fixed issue with Live-photo upload
|
||||
- other minor ux improvement
|
||||
|
||||
## v1.6.46
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- Fixes OOM crashes during file upload
|
||||
[#1379](https://github.com/ente-io/photos-web/pull/1379)
|
||||
- Fixes OOM crashes during file upload
|
||||
[#1379](https://github.com/ente-io/photos-web/pull/1379)
|
||||
|
||||
## v1.6.45
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- Fixed app keeps reloading issue
|
||||
[#235](https://github.com/ente-io/photos-desktop/pull/235)
|
||||
- Fixed dng and arw preview issue
|
||||
[#1378](https://github.com/ente-io/photos-web/pull/1378)
|
||||
- Added view crash report option (help menu) for user to share electron crash
|
||||
report locally
|
||||
- Fixed app keeps reloading issue
|
||||
[#235](https://github.com/ente-io/photos-desktop/pull/235)
|
||||
- Fixed dng and arw preview issue
|
||||
[#1378](https://github.com/ente-io/photos-web/pull/1378)
|
||||
- Added view crash report option (help menu) for user to share electron crash
|
||||
report locally
|
||||
|
||||
## v1.6.44
|
||||
|
||||
- Upgraded electron to get latest security patches and other improvements.
|
||||
- Upgraded electron to get latest security patches and other improvements.
|
||||
|
||||
## v1.6.43
|
||||
|
||||
### Added
|
||||
|
||||
- #### Check for update and changelog option
|
||||
- #### Check for update and changelog option
|
||||
|
||||
Added options to check for update manually and a view changelog via the app
|
||||
menubar
|
||||
|
||||
- #### Opt out of crash reporting
|
||||
- #### Opt out of crash reporting
|
||||
|
||||
Added option to out of a crash reporting, it can accessed from the settings
|
||||
-> preferences -> disable crash reporting
|
||||
|
||||
- #### Type search
|
||||
- #### Type search
|
||||
|
||||
Added new search option to search files based on file type i.e, image,
|
||||
video, live-photo.
|
||||
|
||||
- #### Manual Convert Button
|
||||
- #### Manual Convert Button
|
||||
|
||||
In case the video is not playable, Now there is a convert button which can
|
||||
be used to trigger conversion of the video to supported format.
|
||||
|
||||
- #### File Download Progress
|
||||
- #### File Download Progress
|
||||
|
||||
The file loader now also shows the exact percentage download progress,
|
||||
instead of just a simple loader.
|
||||
|
||||
- #### Bug fixes & other enhancements
|
||||
- #### Bug fixes & other enhancements
|
||||
|
||||
We have squashed a few pesky bugs that were reported by our community
|
||||
|
||||
@@ -269,23 +269,23 @@ to know about feature and functionalities.
|
||||
|
||||
### Added
|
||||
|
||||
- #### Hidden albums
|
||||
- #### Hidden albums
|
||||
|
||||
You can now hide albums, just like individual memories.
|
||||
|
||||
- #### Email verification
|
||||
- #### Email verification
|
||||
|
||||
We have now made email verification optional, so you can sign in with just
|
||||
your email address and password, without waiting for a verification code.
|
||||
|
||||
You can opt in / out of email verification from Settings > Security.
|
||||
|
||||
- #### Download Album
|
||||
- #### Download Album
|
||||
|
||||
You can now chose the download location for downloading albums. Along with
|
||||
that we have also added progress bar for album download.
|
||||
|
||||
- #### Bug fixes & other enhancements
|
||||
- #### Bug fixes & other enhancements
|
||||
|
||||
We have squashed a few pesky bugs that were reported by our community
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# Dependencies
|
||||
|
||||
- [Electron](#electron)
|
||||
- [Dev dependencies](#dev)
|
||||
- [Functionality](#functionality)
|
||||
- [Electron](#electron)
|
||||
- [Dev dependencies](#dev)
|
||||
- [Functionality](#functionality)
|
||||
|
||||
## Electron
|
||||
|
||||
@@ -13,24 +13,24 @@ Electron embeds Chromium and Node.js in the generated app's binary. The
|
||||
generated app thus consists of two separate processes - the _main_ process, and
|
||||
a _renderer_ process.
|
||||
|
||||
- The _main_ process runs the embedded node. This process can deal with the
|
||||
host OS - it is conceptually like a `node` repl running on your machine. In
|
||||
our case, the TypeScript code (in the `src/` directory) gets transpiled by
|
||||
`tsc` into JavaScript in the `build/app/` directory, which gets bundled in
|
||||
the generated app's binary and is loaded by the node (main) process when the
|
||||
app starts.
|
||||
- The _main_ process runs the embedded node. This process can deal with the host
|
||||
OS - it is conceptually like a `node` repl running on your machine. In our
|
||||
case, the TypeScript code (in the `src/` directory) gets transpiled by `tsc`
|
||||
into JavaScript in the `build/app/` directory, which gets bundled in the
|
||||
generated app's binary and is loaded by the node (main) process when the app
|
||||
starts.
|
||||
|
||||
- The _renderer_ process is a regular web app that gets loaded into the
|
||||
embedded Chromium. When the main process starts, it creates a new "window"
|
||||
that shows this embedded Chromium. In our case, we build and bundle a static
|
||||
export of the [Photos web app](../../web/README.md) in the generated desktop
|
||||
app. This gets loaded by the embedded Chromium at runtime, acting as the
|
||||
desktop app's UI.
|
||||
- The _renderer_ process is a regular web app that gets loaded into the embedded
|
||||
Chromium. When the main process starts, it creates a new "window" that shows
|
||||
this embedded Chromium. In our case, we build and bundle a static export of
|
||||
the [Photos web app](../../web/README.md) in the generated desktop app. This
|
||||
gets loaded by the embedded Chromium at runtime, acting as the desktop app's
|
||||
UI.
|
||||
|
||||
There is also a third environment that gets temporarily created:
|
||||
|
||||
- The [preload script](../src/preload.ts) acts as a gateway between the _main_
|
||||
and the _renderer_ process. It runs in its own isolated environment.
|
||||
- The [preload script](../src/preload.ts) acts as a gateway between the _main_
|
||||
and the _renderer_ process. It runs in its own isolated environment.
|
||||
|
||||
### Packaging
|
||||
|
||||
@@ -66,15 +66,15 @@ Electron process. This allows us to directly use the output produced by
|
||||
|
||||
### Others
|
||||
|
||||
- [any-shell-escape](https://github.com/boazy/any-shell-escape) is for
|
||||
escaping shell commands before we execute them (e.g. say when invoking the
|
||||
embedded ffmpeg CLI).
|
||||
- [any-shell-escape](https://github.com/boazy/any-shell-escape) is for escaping
|
||||
shell commands before we execute them (e.g. say when invoking the embedded
|
||||
ffmpeg CLI).
|
||||
|
||||
- [auto-launch](https://github.com/Teamwork/node-auto-launch) is for
|
||||
automatically starting our app on login, if the user so wishes.
|
||||
- [auto-launch](https://github.com/Teamwork/node-auto-launch) is for
|
||||
automatically starting our app on login, if the user so wishes.
|
||||
|
||||
- [electron-store](https://github.com/sindresorhus/electron-store) is used for
|
||||
persisting user preferences and other arbitrary data.
|
||||
- [electron-store](https://github.com/sindresorhus/electron-store) is used for
|
||||
persisting user preferences and other arbitrary data.
|
||||
|
||||
## Dev
|
||||
|
||||
@@ -84,20 +84,20 @@ are similar to that in the web code.
|
||||
|
||||
Some extra ones specific to the code here are:
|
||||
|
||||
- [@tsconfig/recommended](https://github.com/tsconfig/bases) gives us a base
|
||||
tsconfig for the Node.js version that our current Electron version uses.
|
||||
- [@tsconfig/recommended](https://github.com/tsconfig/bases) gives us a base
|
||||
tsconfig for the Node.js version that our current Electron version uses.
|
||||
|
||||
- [shx](https://github.com/shelljs/shx) provides us a portable way to use Unix
|
||||
commands in our `package.json` scripts. This allows us to use the same
|
||||
commands (like `ln`) across both POSIX platforms (Linux, macOS) and Windows.
|
||||
- [shx](https://github.com/shelljs/shx) provides us a portable way to use Unix
|
||||
commands in our `package.json` scripts. This allows us to use the same
|
||||
commands (like `ln`) across both POSIX platforms (Linux, macOS) and Windows.
|
||||
|
||||
- [cross-env](https://github.com/kentcdodds/cross-env) is similar to shx, but
|
||||
for allowing us to set environment variables in a way that also works on
|
||||
Windows.
|
||||
- [cross-env](https://github.com/kentcdodds/cross-env) is similar to shx, but
|
||||
for allowing us to set environment variables in a way that also works on
|
||||
Windows.
|
||||
|
||||
- We don't need `ajv`, but it is a transitive dependency which breaks the
|
||||
build if we let its version be resolved via the yarn resolution mechanism.
|
||||
Taking a direct dependency on it is the easiest workaround for now.
|
||||
- We don't need `ajv`, but it is a transitive dependency which breaks the build
|
||||
if we let its version be resolved via the yarn resolution mechanism. Taking a
|
||||
direct dependency on it is the easiest workaround for now.
|
||||
|
||||
## Functionality
|
||||
|
||||
|
||||
@@ -6,9 +6,9 @@
|
||||
|
||||
Launch the app in development mode:
|
||||
|
||||
- Transpiles the files in `src/` and starts the main process.
|
||||
- Transpiles the files in `src/` and starts the main process.
|
||||
|
||||
- Runs a development server for the renderer, with hot module reload.
|
||||
- Runs a development server for the renderer, with hot module reload.
|
||||
|
||||
### yarn build
|
||||
|
||||
|
||||
@@ -2,21 +2,21 @@
|
||||
|
||||
Conceptually, the release is straightforward:
|
||||
|
||||
1. We trigger a GitHub workflow that creates a (pre-)release with the build.
|
||||
1. We trigger a GitHub workflow that creates a (pre-)release with the build.
|
||||
|
||||
2. When ready, we make that release the latest.
|
||||
2. When ready, we make that release the latest.
|
||||
|
||||
3. The download links on our website, and existing apps already check the
|
||||
latest GitHub release and update automatically.
|
||||
3. The download links on our website, and existing apps already check the latest
|
||||
GitHub release and update automatically.
|
||||
|
||||
The complication comes from the fact that electron-builder's auto updater (the
|
||||
mechanism that we use for auto updates) doesn't work with monorepos. So we need
|
||||
to keep a separate repository just for holding the releases.
|
||||
|
||||
- Source code lives here, in [ente-io/ente](https://github.com/ente-io/ente).
|
||||
- Source code lives here, in [ente-io/ente](https://github.com/ente-io/ente).
|
||||
|
||||
- Releases are done from
|
||||
[ente-io/photos-desktop](https://github.com/ente-io/photos-desktop).
|
||||
- Releases are done from
|
||||
[ente-io/photos-desktop](https://github.com/ente-io/photos-desktop).
|
||||
|
||||
## Nightly builds
|
||||
|
||||
@@ -32,17 +32,17 @@ gh workflow run desktop-release.yml --source=<branch>
|
||||
|
||||
## Release checklist
|
||||
|
||||
1. Update source repo to set version `1.x.x` in `package.json` and finalize the
|
||||
CHANGELOG.
|
||||
1. Update source repo to set version `1.x.x` in `package.json` and finalize the
|
||||
CHANGELOG.
|
||||
|
||||
2. Merge PR then tag the merge commit on `main` in the source repo:
|
||||
2. Merge PR then tag the merge commit on `main` in the source repo:
|
||||
|
||||
```sh
|
||||
git tag photosd-v1.x.x
|
||||
git push origin photosd-v1.x.x
|
||||
```
|
||||
|
||||
3. In the release repo:
|
||||
3. In the release repo:
|
||||
|
||||
```sh
|
||||
./.github/trigger-release.sh v1.x.x
|
||||
@@ -56,20 +56,20 @@ Once it is marked as latest, the release goes live.
|
||||
We are done at this point, and can now update the other pre-release that'll hold
|
||||
subsequent nightly builds.
|
||||
|
||||
1. Update `package.json` in the source repo to use version `1.x.x-beta`, and
|
||||
merge these changes into `main`.
|
||||
1. Update `package.json` in the source repo to use version `1.x.x-beta`, and
|
||||
merge these changes into `main`.
|
||||
|
||||
2. In the release repo, delete the existing _nightly_ pre-release, then:
|
||||
2. In the release repo, delete the existing _nightly_ pre-release, then:
|
||||
|
||||
```sh
|
||||
git tag v1.x.x-beta
|
||||
git push origin v1.x.x-beta
|
||||
```
|
||||
|
||||
3. Start a new run of the workflow (`gh workflow run desktop-release.yml`).
|
||||
3. Start a new run of the workflow (`gh workflow run desktop-release.yml`).
|
||||
|
||||
4. Once the workflow creates the new 1.x.x-beta pre-release, edit its
|
||||
description to "Nightly builds".
|
||||
4. Once the workflow creates the new 1.x.x-beta pre-release, edit its
|
||||
description to "Nightly builds".
|
||||
|
||||
Subsequent scheduled nightly workflows will keep updating this pre-release.
|
||||
|
||||
@@ -77,14 +77,14 @@ Subsequent scheduled nightly workflows will keep updating this pre-release.
|
||||
|
||||
To create extra one-off pre-releases in addition to the nightly `1.x.x-beta`s,
|
||||
|
||||
1. In your branch in the source repository, set the version in `package.json`
|
||||
to something different, say `1.x.x-foo`.
|
||||
1. In your branch in the source repository, set the version in `package.json` to
|
||||
something different, say `1.x.x-foo`.
|
||||
|
||||
2. Create a new pre-release in the release repo with title `1.x.x-foo`. In the
|
||||
tag input enter `v1.x.x-foo` and select the option to "Create a new tag on
|
||||
publish".
|
||||
2. Create a new pre-release in the release repo with title `1.x.x-foo`. In the
|
||||
tag input enter `v1.x.x-foo` and select the option to "Create a new tag on
|
||||
publish".
|
||||
|
||||
3. Trigger the workflow in the release repo:
|
||||
3. Trigger the workflow in the release repo:
|
||||
|
||||
```sh
|
||||
gh workflow run desktop-release.yml --source=my-branch
|
||||
@@ -95,9 +95,9 @@ To create extra one-off pre-releases in addition to the nightly `1.x.x-beta`s,
|
||||
The GitHub Action runs on Windows, Linux and macOS. It produces the artifacts
|
||||
defined in the `build` value in `package.json`.
|
||||
|
||||
- Windows - An NSIS installer.
|
||||
- Linux - An AppImage, and 3 other packages (`.rpm`, `.deb`, `.pacman`)
|
||||
- macOS - A universal DMG
|
||||
- Windows - An NSIS installer.
|
||||
- Linux - An AppImage, and 3 other packages (`.rpm`, `.deb`, `.pacman`)
|
||||
- macOS - A universal DMG
|
||||
|
||||
Additionally, the GitHub action notarizes and signs the macOS DMG (For this it
|
||||
uses credentials provided via GitHub secrets).
|
||||
@@ -105,16 +105,16 @@ uses credentials provided via GitHub secrets).
|
||||
To rollout the build, we need to publish the draft release. Thereafter,
|
||||
everything is automated:
|
||||
|
||||
- The website automatically redirects to the latest release on GitHub when
|
||||
people try to download.
|
||||
- The website automatically redirects to the latest release on GitHub when
|
||||
people try to download.
|
||||
|
||||
- The file formats with support auto update (Windows `exe`, the Linux AppImage
|
||||
and the macOS DMG) also check the latest GitHub release automatically to
|
||||
download and apply the update (the rest of the formats don't support auto
|
||||
updates yet).
|
||||
- The file formats with support auto update (Windows `exe`, the Linux AppImage
|
||||
and the macOS DMG) also check the latest GitHub release automatically to
|
||||
download and apply the update (the rest of the formats don't support auto
|
||||
updates yet).
|
||||
|
||||
- We're not putting the desktop app in other stores currently. It is available
|
||||
as a `brew cask`, but we only had to open a PR to add the initial formula,
|
||||
now their maintainers automatically bump the SHA, version number and the
|
||||
(derived from the version) URL in the formula when their tools notice a new
|
||||
release on our GitHub.
|
||||
- We're not putting the desktop app in other stores currently. It is available
|
||||
as a `brew cask`, but we only had to open a PR to add the initial formula, now
|
||||
their maintainers automatically bump the SHA, version number and the (derived
|
||||
from the version) URL in the formula when their tools notice a new release on
|
||||
our GitHub.
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
"clip-bpe-js": "^0.0.6",
|
||||
"comlink": "^4.4.2",
|
||||
"compare-versions": "^6.1.1",
|
||||
"electron-log": "^5.2.3",
|
||||
"electron-log": "^5.2.4",
|
||||
"electron-store": "^8.2.0",
|
||||
"electron-updater": "^6.3.9",
|
||||
"ffmpeg-static": "^5.2.0",
|
||||
@@ -40,23 +40,23 @@
|
||||
"onnxruntime-node": "^1.20.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^9.15.0",
|
||||
"@eslint/js": "^9.17.0",
|
||||
"@tsconfig/node20": "^20.1.4",
|
||||
"@types/auto-launch": "^5.0.5",
|
||||
"@types/eslint__js": "^8.42.3",
|
||||
"@types/ffmpeg-static": "^3.0.3",
|
||||
"ajv": "^8.17.1",
|
||||
"concurrently": "^9.1.0",
|
||||
"concurrently": "^9.1.1",
|
||||
"cross-env": "^7.0.3",
|
||||
"electron": "^33.2.1",
|
||||
"electron-builder": "^25.1.8",
|
||||
"eslint": "^9",
|
||||
"prettier": "3.3.3",
|
||||
"prettier": "3.4.2",
|
||||
"prettier-plugin-organize-imports": "^4.1.0",
|
||||
"prettier-plugin-packagejson": "^2.5.6",
|
||||
"shx": "^0.3.4",
|
||||
"typescript": "^5.7.2",
|
||||
"typescript-eslint": "^8.16.0"
|
||||
"typescript-eslint": "^8.18.2"
|
||||
},
|
||||
"packageManager": "yarn@1.22.22",
|
||||
"productName": "ente"
|
||||
|
||||
@@ -255,10 +255,10 @@ const registerPrivilegedSchemes = () => {
|
||||
* See: [Note: Passkey verification in the desktop app].
|
||||
*
|
||||
* Implementation notes:
|
||||
* - https://www.electronjs.org/docs/latest/tutorial/launch-app-from-url-in-another-app
|
||||
* - This works only when the app is packaged.
|
||||
* - On Windows and Linux, we get the deeplink in the "second-instance" event.
|
||||
* - On macOS, we get the deeplink in the "open-url" event.
|
||||
* - https://www.electronjs.org/docs/latest/tutorial/launch-app-from-url-in-another-app
|
||||
* - This works only when the app is packaged.
|
||||
* - On Windows and Linux, we get the deeplink in the "second-instance" event.
|
||||
* - On macOS, we get the deeplink in the "open-url" event.
|
||||
*/
|
||||
const registerForEnteLinks = () => app.setAsDefaultProtocolClient("ente");
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ export const fsReadTextFile = async (filePath: string) =>
|
||||
fs.readFile(filePath, "utf-8");
|
||||
|
||||
export const fsWriteFile = (path: string, contents: string) =>
|
||||
fs.writeFile(path, contents);
|
||||
fs.writeFile(path, contents, { flush: true });
|
||||
|
||||
export const fsIsDir = async (dirPath: string) => {
|
||||
if (!existsSync(dirPath)) return false;
|
||||
|
||||
@@ -57,9 +57,9 @@ let _child: UtilityProcess | undefined;
|
||||
*
|
||||
* So we
|
||||
*
|
||||
* 1. In the utility process create a message channel.
|
||||
* 2. Spawn a utility process, and send one port of the pair to it.
|
||||
* 3. Send the other port of the pair to the renderer.
|
||||
* 1. In the utility process create a message channel.
|
||||
* 2. Spawn a utility process, and send one port of the pair to it.
|
||||
* 3. Send the other port of the pair to the renderer.
|
||||
*
|
||||
* The renderer will forward that port to the web worker that is coordinating
|
||||
* the ML indexing on the web layer. Thereafter, the utility process and web
|
||||
|
||||
@@ -31,9 +31,9 @@
|
||||
* and when changing one of them, remember to see if the other two also need
|
||||
* changing:
|
||||
*
|
||||
* - [renderer] web/packages/base/types/ipc.ts contains docs
|
||||
* - [preload] desktop/src/preload.ts ↕︎
|
||||
* - [main] desktop/src/main/ipc.ts contains impl
|
||||
* - [renderer] web/packages/base/types/ipc.ts contains docs
|
||||
* - [preload] desktop/src/preload.ts ↕︎
|
||||
* - [main] desktop/src/main/ipc.ts contains impl
|
||||
*/
|
||||
|
||||
// This code runs in the (isolated) web layer. Contrary to the impression given
|
||||
|
||||
@@ -144,10 +144,10 @@
|
||||
resolved "https://registry.yarnpkg.com/@eslint/js/-/js-9.9.1.tgz#4a97e85e982099d6c7ee8410aacb55adaa576f06"
|
||||
integrity sha512-xIDQRsfg5hNBqHz04H1R3scSVwmI+KUbqjsQKHKQ1DAUSaUjYPReZZmS/5PNiKu1fUvzDd6H7DEDKACSEhu+TQ==
|
||||
|
||||
"@eslint/js@^9.15.0":
|
||||
version "9.15.0"
|
||||
resolved "https://registry.yarnpkg.com/@eslint/js/-/js-9.15.0.tgz#df0e24fe869143b59731942128c19938fdbadfb5"
|
||||
integrity sha512-tMTqrY+EzbXmKJR5ToI8lxu7jaN5EdmrBFJpQk5JmSlyLsx6o4t27r883K5xsLuCYCpfKBCGswMSWXsM+jB7lg==
|
||||
"@eslint/js@^9.17.0":
|
||||
version "9.17.0"
|
||||
resolved "https://registry.yarnpkg.com/@eslint/js/-/js-9.17.0.tgz#1523e586791f80376a6f8398a3964455ecc651ec"
|
||||
integrity sha512-Sxc4hqcs1kTu0iID3kcZDW3JHq2a77HO9P8CP6YEA/FpH3Ll8UXE2r/86Rz9YJLKme39S9vU5OWNjC6Xl0Cr3w==
|
||||
|
||||
"@eslint/object-schema@^2.1.4":
|
||||
version "2.1.4"
|
||||
@@ -384,62 +384,62 @@
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
"@typescript-eslint/eslint-plugin@8.16.0":
|
||||
version "8.16.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.16.0.tgz#ac56825bcdf3b392fc76a94b1315d4a162f201a6"
|
||||
integrity sha512-5YTHKV8MYlyMI6BaEG7crQ9BhSc8RxzshOReKwZwRWN0+XvvTOm+L/UYLCYxFpfwYuAAqhxiq4yae0CMFwbL7Q==
|
||||
"@typescript-eslint/eslint-plugin@8.18.2":
|
||||
version "8.18.2"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.18.2.tgz#c78e363ab5fe3b21dd1c90d8be9581534417f78e"
|
||||
integrity sha512-adig4SzPLjeQ0Tm+jvsozSGiCliI2ajeURDGHjZ2llnA+A67HihCQ+a3amtPhUakd1GlwHxSRvzOZktbEvhPPg==
|
||||
dependencies:
|
||||
"@eslint-community/regexpp" "^4.10.0"
|
||||
"@typescript-eslint/scope-manager" "8.16.0"
|
||||
"@typescript-eslint/type-utils" "8.16.0"
|
||||
"@typescript-eslint/utils" "8.16.0"
|
||||
"@typescript-eslint/visitor-keys" "8.16.0"
|
||||
"@typescript-eslint/scope-manager" "8.18.2"
|
||||
"@typescript-eslint/type-utils" "8.18.2"
|
||||
"@typescript-eslint/utils" "8.18.2"
|
||||
"@typescript-eslint/visitor-keys" "8.18.2"
|
||||
graphemer "^1.4.0"
|
||||
ignore "^5.3.1"
|
||||
natural-compare "^1.4.0"
|
||||
ts-api-utils "^1.3.0"
|
||||
|
||||
"@typescript-eslint/parser@8.16.0":
|
||||
version "8.16.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.16.0.tgz#ee5b2d6241c1ab3e2e53f03fd5a32d8e266d8e06"
|
||||
integrity sha512-D7DbgGFtsqIPIFMPJwCad9Gfi/hC0PWErRRHFnaCWoEDYi5tQUDiJCTmGUbBiLzjqAck4KcXt9Ayj0CNlIrF+w==
|
||||
"@typescript-eslint/parser@8.18.2":
|
||||
version "8.18.2"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.18.2.tgz#0379a2e881d51d8fcf7ebdfa0dd18eee79182ce2"
|
||||
integrity sha512-y7tcq4StgxQD4mDr9+Jb26dZ+HTZ/SkfqpXSiqeUXZHxOUyjWDKsmwKhJ0/tApR08DgOhrFAoAhyB80/p3ViuA==
|
||||
dependencies:
|
||||
"@typescript-eslint/scope-manager" "8.16.0"
|
||||
"@typescript-eslint/types" "8.16.0"
|
||||
"@typescript-eslint/typescript-estree" "8.16.0"
|
||||
"@typescript-eslint/visitor-keys" "8.16.0"
|
||||
"@typescript-eslint/scope-manager" "8.18.2"
|
||||
"@typescript-eslint/types" "8.18.2"
|
||||
"@typescript-eslint/typescript-estree" "8.18.2"
|
||||
"@typescript-eslint/visitor-keys" "8.18.2"
|
||||
debug "^4.3.4"
|
||||
|
||||
"@typescript-eslint/scope-manager@8.16.0":
|
||||
version "8.16.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.16.0.tgz#ebc9a3b399a69a6052f3d88174456dd399ef5905"
|
||||
integrity sha512-mwsZWubQvBki2t5565uxF0EYvG+FwdFb8bMtDuGQLdCCnGPrDEDvm1gtfynuKlnpzeBRqdFCkMf9jg1fnAK8sg==
|
||||
"@typescript-eslint/scope-manager@8.18.2":
|
||||
version "8.18.2"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.18.2.tgz#d193c200d61eb0ddec5987c8e48c9d4e1c0510bd"
|
||||
integrity sha512-YJFSfbd0CJjy14r/EvWapYgV4R5CHzptssoag2M7y3Ra7XNta6GPAJPPP5KGB9j14viYXyrzRO5GkX7CRfo8/g==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "8.16.0"
|
||||
"@typescript-eslint/visitor-keys" "8.16.0"
|
||||
"@typescript-eslint/types" "8.18.2"
|
||||
"@typescript-eslint/visitor-keys" "8.18.2"
|
||||
|
||||
"@typescript-eslint/type-utils@8.16.0":
|
||||
version "8.16.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.16.0.tgz#585388735f7ac390f07c885845c3d185d1b64740"
|
||||
integrity sha512-IqZHGG+g1XCWX9NyqnI/0CX5LL8/18awQqmkZSl2ynn8F76j579dByc0jhfVSnSnhf7zv76mKBQv9HQFKvDCgg==
|
||||
"@typescript-eslint/type-utils@8.18.2":
|
||||
version "8.18.2"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.18.2.tgz#5ad07e09002eee237591881df674c1c0c91ca52f"
|
||||
integrity sha512-AB/Wr1Lz31bzHfGm/jgbFR0VB0SML/hd2P1yxzKDM48YmP7vbyJNHRExUE/wZsQj2wUCvbWH8poNHFuxLqCTnA==
|
||||
dependencies:
|
||||
"@typescript-eslint/typescript-estree" "8.16.0"
|
||||
"@typescript-eslint/utils" "8.16.0"
|
||||
"@typescript-eslint/typescript-estree" "8.18.2"
|
||||
"@typescript-eslint/utils" "8.18.2"
|
||||
debug "^4.3.4"
|
||||
ts-api-utils "^1.3.0"
|
||||
|
||||
"@typescript-eslint/types@8.16.0":
|
||||
version "8.16.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.16.0.tgz#49c92ae1b57942458ab83d9ec7ccab3005e64737"
|
||||
integrity sha512-NzrHj6thBAOSE4d9bsuRNMvk+BvaQvmY4dDglgkgGC0EW/tB3Kelnp3tAKH87GEwzoxgeQn9fNGRyFJM/xd+GQ==
|
||||
"@typescript-eslint/types@8.18.2":
|
||||
version "8.18.2"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.18.2.tgz#5ebad5b384c8aa1c0f86cee1c61bcdbe7511f547"
|
||||
integrity sha512-Z/zblEPp8cIvmEn6+tPDIHUbRu/0z5lqZ+NvolL5SvXWT5rQy7+Nch83M0++XzO0XrWRFWECgOAyE8bsJTl1GQ==
|
||||
|
||||
"@typescript-eslint/typescript-estree@8.16.0":
|
||||
version "8.16.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.16.0.tgz#9d741e56e5b13469b5190e763432ce5551a9300c"
|
||||
integrity sha512-E2+9IzzXMc1iaBy9zmo+UYvluE3TW7bCGWSF41hVWUE01o8nzr1rvOQYSxelxr6StUvRcTMe633eY8mXASMaNw==
|
||||
"@typescript-eslint/typescript-estree@8.18.2":
|
||||
version "8.18.2"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.18.2.tgz#fffb85527f8304e29bfbbdc712f4515da9f8b47c"
|
||||
integrity sha512-WXAVt595HjpmlfH4crSdM/1bcsqh+1weFRWIa9XMTx/XHZ9TCKMcr725tLYqWOgzKdeDrqVHxFotrvWcEsk2Tg==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "8.16.0"
|
||||
"@typescript-eslint/visitor-keys" "8.16.0"
|
||||
"@typescript-eslint/types" "8.18.2"
|
||||
"@typescript-eslint/visitor-keys" "8.18.2"
|
||||
debug "^4.3.4"
|
||||
fast-glob "^3.3.2"
|
||||
is-glob "^4.0.3"
|
||||
@@ -447,22 +447,22 @@
|
||||
semver "^7.6.0"
|
||||
ts-api-utils "^1.3.0"
|
||||
|
||||
"@typescript-eslint/utils@8.16.0":
|
||||
version "8.16.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.16.0.tgz#c71264c437157feaa97842809836254a6fc833c3"
|
||||
integrity sha512-C1zRy/mOL8Pj157GiX4kaw7iyRLKfJXBR3L82hk5kS/GyHcOFmy4YUq/zfZti72I9wnuQtA/+xzft4wCC8PJdA==
|
||||
"@typescript-eslint/utils@8.18.2":
|
||||
version "8.18.2"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.18.2.tgz#a2635f71904a84f9e47fe1b6f65a6d944ff1adf9"
|
||||
integrity sha512-Cr4A0H7DtVIPkauj4sTSXVl+VBWewE9/o40KcF3TV9aqDEOWoXF3/+oRXNby3DYzZeCATvbdksYsGZzplwnK/Q==
|
||||
dependencies:
|
||||
"@eslint-community/eslint-utils" "^4.4.0"
|
||||
"@typescript-eslint/scope-manager" "8.16.0"
|
||||
"@typescript-eslint/types" "8.16.0"
|
||||
"@typescript-eslint/typescript-estree" "8.16.0"
|
||||
"@typescript-eslint/scope-manager" "8.18.2"
|
||||
"@typescript-eslint/types" "8.18.2"
|
||||
"@typescript-eslint/typescript-estree" "8.18.2"
|
||||
|
||||
"@typescript-eslint/visitor-keys@8.16.0":
|
||||
version "8.16.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.16.0.tgz#d5086afc060b01ff7a4ecab8d49d13d5a7b07705"
|
||||
integrity sha512-pq19gbaMOmFE3CbL0ZB8J8BFCo2ckfHBfaIsaOZgBIF4EoISJIdLX5xRhd0FGB0LlHReNRuzoJoMGpTjq8F2CQ==
|
||||
"@typescript-eslint/visitor-keys@8.18.2":
|
||||
version "8.18.2"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.18.2.tgz#b3e434b701f086b10a7c82416ebc56899d27ef2f"
|
||||
integrity sha512-zORcwn4C3trOWiCqFQP1x6G3xTRyZ1LYydnj51cRnJ6hxBlr/cKPckk+PKPUw/fXmvfKTcw7bwY3w9izgx5jZw==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "8.16.0"
|
||||
"@typescript-eslint/types" "8.18.2"
|
||||
eslint-visitor-keys "^4.2.0"
|
||||
|
||||
"@xmldom/xmldom@^0.8.8":
|
||||
@@ -999,10 +999,10 @@ concat-stream@^2.0.0:
|
||||
readable-stream "^3.0.2"
|
||||
typedarray "^0.0.6"
|
||||
|
||||
concurrently@^9.1.0:
|
||||
version "9.1.0"
|
||||
resolved "https://registry.yarnpkg.com/concurrently/-/concurrently-9.1.0.tgz#8da6d609f4321752912dab9be8710232ac496aa0"
|
||||
integrity sha512-VxkzwMAn4LP7WyMnJNbHN5mKV9L2IbyDjpzemKr99sXNR3GqRNMMHdm7prV1ws9wg7ETj6WUkNOigZVsptwbgg==
|
||||
concurrently@^9.1.1:
|
||||
version "9.1.1"
|
||||
resolved "https://registry.yarnpkg.com/concurrently/-/concurrently-9.1.1.tgz#609dde2ce12f4f12d6a5ea6eace4c38bb7ab2ead"
|
||||
integrity sha512-6VX8lrBIycgZKTwBsWS+bLrmkGRkDmvtGsYylRN9b93CygN6CbK46HmnQ3rdSOR8HRjdahDrxb5MqD9cEFOg5Q==
|
||||
dependencies:
|
||||
chalk "^4.1.2"
|
||||
lodash "^4.17.21"
|
||||
@@ -1233,10 +1233,10 @@ electron-builder@^25.1.8:
|
||||
simple-update-notifier "2.0.0"
|
||||
yargs "^17.6.2"
|
||||
|
||||
electron-log@^5.2.3:
|
||||
version "5.2.3"
|
||||
resolved "https://registry.yarnpkg.com/electron-log/-/electron-log-5.2.3.tgz#b58447b2158b9aa5faa07c4d15340113069d3f15"
|
||||
integrity sha512-BabCiEV+p362LzY0EFE8hyzeGknzKDWSbhS0VFfRYQGA4FHWXWSfaKJlvTR9LFepNoORXxc/BWvqBXIPgsVFgA==
|
||||
electron-log@^5.2.4:
|
||||
version "5.2.4"
|
||||
resolved "https://registry.yarnpkg.com/electron-log/-/electron-log-5.2.4.tgz#6b488d9db80aa3c6f3dc39bcd635fc9d1f79c8af"
|
||||
integrity sha512-iX12WXc5XAaKeHg2QpiFjVwL+S1NVHPFd3V5RXtCmKhpAzXsVQnR3UEc0LovM6p6NkUQxDWnkdkaam9FNUVmCA==
|
||||
|
||||
electron-publish@25.1.7:
|
||||
version "25.1.7"
|
||||
@@ -2732,10 +2732,10 @@ prettier-plugin-packagejson@^2.5.6:
|
||||
sort-package-json "2.12.0"
|
||||
synckit "0.9.2"
|
||||
|
||||
prettier@3.3.3:
|
||||
version "3.3.3"
|
||||
resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.3.3.tgz#30c54fe0be0d8d12e6ae61dbb10109ea00d53105"
|
||||
integrity sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==
|
||||
prettier@3.4.2:
|
||||
version "3.4.2"
|
||||
resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.4.2.tgz#a5ce1fb522a588bf2b78ca44c6e6fe5aa5a2b13f"
|
||||
integrity sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==
|
||||
|
||||
progress@^2.0.3:
|
||||
version "2.0.3"
|
||||
@@ -3264,14 +3264,14 @@ typedarray@^0.0.6:
|
||||
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
|
||||
integrity sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==
|
||||
|
||||
typescript-eslint@^8.16.0:
|
||||
version "8.16.0"
|
||||
resolved "https://registry.yarnpkg.com/typescript-eslint/-/typescript-eslint-8.16.0.tgz#d608c972d6b2461ca10ec30fd3fa62a080baba19"
|
||||
integrity sha512-wDkVmlY6O2do4V+lZd0GtRfbtXbeD0q9WygwXXSJnC1xorE8eqyC2L1tJimqpSeFrOzRlYtWnUp/uzgHQOgfBQ==
|
||||
typescript-eslint@^8.18.2:
|
||||
version "8.18.2"
|
||||
resolved "https://registry.yarnpkg.com/typescript-eslint/-/typescript-eslint-8.18.2.tgz#71334dcf843adc3fbb771dce5ade7876aa0d62b7"
|
||||
integrity sha512-KuXezG6jHkvC3MvizeXgupZzaG5wjhU3yE8E7e6viOvAvD9xAWYp8/vy0WULTGe9DYDWcQu7aW03YIV3mSitrQ==
|
||||
dependencies:
|
||||
"@typescript-eslint/eslint-plugin" "8.16.0"
|
||||
"@typescript-eslint/parser" "8.16.0"
|
||||
"@typescript-eslint/utils" "8.16.0"
|
||||
"@typescript-eslint/eslint-plugin" "8.18.2"
|
||||
"@typescript-eslint/parser" "8.18.2"
|
||||
"@typescript-eslint/utils" "8.18.2"
|
||||
|
||||
typescript@^5.4.3:
|
||||
version "5.5.4"
|
||||
|
||||
@@ -231,11 +231,14 @@ export const sidebar = [
|
||||
collapsed: true,
|
||||
items: [
|
||||
{ text: "Getting started", link: "/self-hosting/" },
|
||||
{ text: "System requirements", link: "/self-hosting/guides/system-requirements", },
|
||||
{
|
||||
text: "System requirements",
|
||||
link: "/self-hosting/guides/system-requirements",
|
||||
},
|
||||
{
|
||||
text: "Guides",
|
||||
items: [
|
||||
{ text: "Introduction", link: "/self-hosting/guides/" },
|
||||
{ text: "Introduction", link: "/self-hosting/guides/" },
|
||||
{
|
||||
text: "Connect to custom server",
|
||||
link: "/self-hosting/guides/custom-server/",
|
||||
@@ -258,7 +261,7 @@ export const sidebar = [
|
||||
link: "/self-hosting/guides/configuring-s3",
|
||||
},
|
||||
{
|
||||
text: "Using external S3",
|
||||
text: "Hosting Ente with external S3 (Community)",
|
||||
link: "/self-hosting/guides/external-s3",
|
||||
},
|
||||
{
|
||||
@@ -271,8 +274,8 @@ export const sidebar = [
|
||||
},
|
||||
{
|
||||
text: "Configure CLI for Self Hosted Instance",
|
||||
link: "/self-hosting/guides/selfhost-cli"
|
||||
}
|
||||
link: "/self-hosting/guides/selfhost-cli",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
|
||||
@@ -11,9 +11,9 @@ Ente is a end-to-end encrypted platform for privately, reliably, and securely
|
||||
storing your data on the cloud. On top of this platform, Ente offers two
|
||||
products:
|
||||
|
||||
- **Ente Photos** - An alternative to Google Photos and Apple Photos
|
||||
- **Ente Photos** - An alternative to Google Photos and Apple Photos
|
||||
|
||||
- **Ente Auth** - A free 2FA alternative to Authy
|
||||
- **Ente Auth** - A free 2FA alternative to Authy
|
||||
|
||||
Both these apps are available for all desktop (Linux, Mac, Windows) and mobile
|
||||
(Android, iOS and F-Droid) platforms. They also work directly in your web
|
||||
@@ -46,7 +46,8 @@ the name, and also led to the adoption of "Ducky", Ente's mascot:
|
||||
|
||||
</div>
|
||||
|
||||
For the full origin story of Ducky you can check out [this blog post](https://ente.io/blog/ducky/).
|
||||
For the full origin story of Ducky you can check out
|
||||
[this blog post](https://ente.io/blog/ducky/).
|
||||
|
||||
### How do I pronounce Ente?
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@ You can install Auth directly from
|
||||
Reproducible builds for Auth are available on
|
||||
[F-Droid](https://f-droid.org/packages/io.ente.auth/).
|
||||
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> Releases over F-Droid are generally slower since they run their own build
|
||||
@@ -34,20 +33,22 @@ you stay updated.
|
||||
### Obtainium
|
||||
|
||||
You can setup [Obtainium](https://github.com/ImranR98/Obtainium) to track our
|
||||
GitHub releases by [clicking this link](https://apps.obtainium.imranr.dev/redirect?r=obtainium://app/%7B%22id%22%3A%22io.ente.auth.independent%22%2C%22url%22%3A%22https%3A%2F%2Fgithub.com%2Fente-io%2Fente%22%2C%22author%22%3A%22ente-io%22%2C%22name%22%3A%22Ente%20Auth%22%2C%22preferredApkIndex%22%3A0%2C%22additionalSettings%22%3A%22%7B%5C%22includePrereleases%5C%22%3Afalse%2C%5C%22fallbackToOlderReleases%5C%22%3Atrue%2C%5C%22filterReleaseTitlesByRegEx%5C%22%3A%5C%22%5C%22%2C%5C%22filterReleaseNotesByRegEx%5C%22%3A%5C%22%5C%22%2C%5C%22verifyLatestTag%5C%22%3Afalse%2C%5C%22dontSortReleasesList%5C%22%3Atrue%2C%5C%22useLatestAssetDateAsReleaseDate%5C%22%3Afalse%2C%5C%22releaseTitleAsVersion%5C%22%3Afalse%2C%5C%22trackOnly%5C%22%3Afalse%2C%5C%22versionExtractionRegEx%5C%22%3A%5C%22%5C%22%2C%5C%22matchGroupToUse%5C%22%3A%5C%22%5C%22%2C%5C%22versionDetection%5C%22%3Atrue%2C%5C%22releaseDateAsVersion%5C%22%3Afalse%2C%5C%22useVersionCodeAsOSVersion%5C%22%3Afalse%2C%5C%22apkFilterRegEx%5C%22%3A%5C%22ente-auth*%5C%22%2C%5C%22invertAPKFilter%5C%22%3Afalse%2C%5C%22autoApkFilterByArch%5C%22%3Atrue%2C%5C%22appName%5C%22%3A%5C%22%5C%22%2C%5C%22shizukuPretendToBeGooglePlay%5C%22%3Afalse%2C%5C%22allowInsecure%5C%22%3Afalse%2C%5C%22exemptFromBackgroundUpdates%5C%22%3Afalse%2C%5C%22skipUpdateNotifications%5C%22%3Afalse%2C%5C%22about%5C%22%3A%5C%22%5C%22%7D%22%2C%22overrideSource%22%3Anull%7D) to add it instantly.
|
||||
GitHub releases by
|
||||
[clicking this link](https://apps.obtainium.imranr.dev/redirect?r=obtainium://app/%7B%22id%22%3A%22io.ente.auth.independent%22%2C%22url%22%3A%22https%3A%2F%2Fgithub.com%2Fente-io%2Fente%22%2C%22author%22%3A%22ente-io%22%2C%22name%22%3A%22Ente%20Auth%22%2C%22preferredApkIndex%22%3A0%2C%22additionalSettings%22%3A%22%7B%5C%22includePrereleases%5C%22%3Afalse%2C%5C%22fallbackToOlderReleases%5C%22%3Atrue%2C%5C%22filterReleaseTitlesByRegEx%5C%22%3A%5C%22%5C%22%2C%5C%22filterReleaseNotesByRegEx%5C%22%3A%5C%22%5C%22%2C%5C%22verifyLatestTag%5C%22%3Afalse%2C%5C%22dontSortReleasesList%5C%22%3Atrue%2C%5C%22useLatestAssetDateAsReleaseDate%5C%22%3Afalse%2C%5C%22releaseTitleAsVersion%5C%22%3Afalse%2C%5C%22trackOnly%5C%22%3Afalse%2C%5C%22versionExtractionRegEx%5C%22%3A%5C%22%5C%22%2C%5C%22matchGroupToUse%5C%22%3A%5C%22%5C%22%2C%5C%22versionDetection%5C%22%3Atrue%2C%5C%22releaseDateAsVersion%5C%22%3Afalse%2C%5C%22useVersionCodeAsOSVersion%5C%22%3Afalse%2C%5C%22apkFilterRegEx%5C%22%3A%5C%22ente-auth*%5C%22%2C%5C%22invertAPKFilter%5C%22%3Afalse%2C%5C%22autoApkFilterByArch%5C%22%3Atrue%2C%5C%22appName%5C%22%3A%5C%22%5C%22%2C%5C%22shizukuPretendToBeGooglePlay%5C%22%3Afalse%2C%5C%22allowInsecure%5C%22%3Afalse%2C%5C%22exemptFromBackgroundUpdates%5C%22%3Afalse%2C%5C%22skipUpdateNotifications%5C%22%3Afalse%2C%5C%22about%5C%22%3A%5C%22%5C%22%7D%22%2C%22overrideSource%22%3Anull%7D)
|
||||
to add it instantly.
|
||||
|
||||
Alternatively, you can follow these steps:
|
||||
|
||||
1. Click **Add App** to open a new app config screen
|
||||
2. Enter `https://github.com/ente-io/ente` in the **App Source URL** field
|
||||
3. Enable the **Retain release order** from API toggle
|
||||
4. Scroll down to the **Filter APKs by Regular Expression** field and enter `ente-auth*`
|
||||
4. Scroll down to the **Filter APKs by Regular Expression** field and enter
|
||||
`ente-auth*`
|
||||
5. Enable the **Attempt to filter APKs by CPU architecture** if possible toggle
|
||||
6. Select any applicable app category labels you may have setup
|
||||
7. Enable the **Try inferring app ID from source code** toggle
|
||||
8. Scroll back to the top and click **Add** to complete the setup
|
||||
|
||||
|
||||
<br/>
|
||||
|
||||
---
|
||||
@@ -78,7 +79,8 @@ You can grab the latest version of Ente Auth for Mac, Windows and Linux from
|
||||
|
||||
# Web
|
||||
|
||||
Latest versions of our web app are available at [auth.ente.io](https://auth.ente.io).
|
||||
Latest versions of our web app are available at
|
||||
[auth.ente.io](https://auth.ente.io).
|
||||
|
||||
<br/>
|
||||
|
||||
|
||||
@@ -150,55 +150,57 @@ Authenticator. To import your codes, please follow one of the steps below,
|
||||
depending on which method you used to export your codes.
|
||||
|
||||
## Method 3
|
||||
**Who should use this?** Power users who have spare time on their hands and
|
||||
who have a rooted android phone running android 6 or newer that passes Play
|
||||
|
||||
**Who should use this?** Power users who have spare time on their hands and who
|
||||
have a rooted android phone running android 6 or newer that passes Play
|
||||
Integrity.
|
||||
|
||||
This way of exporting your data will require a rooted phone.
|
||||
|
||||
### Exporting codes using Android OTP Extractor
|
||||
|
||||
This uses the tool [Android OTP Extractor](https://github.com/puddly/android-otp-extractor) from [puddly](https://github.com/puddly) on GitHub
|
||||
This uses the tool
|
||||
[Android OTP Extractor](https://github.com/puddly/android-otp-extractor) from
|
||||
[puddly](https://github.com/puddly) on GitHub
|
||||
|
||||
1. Install python 3 and adb to your computer you can download binaries for
|
||||
it from [Google](https://developer.android.com/tools/releases/platform-tools)
|
||||
2. Add adb to your path.
|
||||
2.1. On windows search for "Edit the system environment variables"
|
||||
2.2. Click "Environment Variables"
|
||||
2.3. At the top in "User variables" click the "path" variable and then click "Edit"
|
||||
2.4. Click "New" and type the path to where you extracted the Platform Tools
|
||||
3. Enable USB debugging on the Android Phone
|
||||
3.1. Open settings
|
||||
3.2. Open "About phone" (Might say tablet depending on what device you use)
|
||||
(skip steps 3.2 and 3.3 if you already have developer options enabled)
|
||||
3.3. Tap "Build Number" 7 or more times
|
||||
3.4. Go to the main settings page
|
||||
3.5. Open "System Settings"
|
||||
3.6. Open "Developer options"
|
||||
3.7. Enable "USB Debugging"
|
||||
3.8. On your computer verify the phone is connected by running `adb devices`
|
||||
(You may need to tap "Allow" on the device to allow the computer to access it)
|
||||
5. Install Android OTP Extractor using pip
|
||||
```
|
||||
pip install git+https://github.com/puddly/android-otp-extractor
|
||||
```
|
||||
6. Install Authy from the playstore and login to your account
|
||||
7. Run the command below to export the TOTP to QRCodes and URLS
|
||||
```
|
||||
python -m android_otp_extractor --prepend-issuer --include authy
|
||||
```
|
||||
1. Install python 3 and adb to your computer you can download binaries for it
|
||||
from [Google](https://developer.android.com/tools/releases/platform-tools)
|
||||
2. Add adb to your path. 2.1. On windows search for "Edit the system environment
|
||||
variables" 2.2. Click "Environment Variables" 2.3. At the top in "User
|
||||
variables" click the "path" variable and then click "Edit" 2.4. Click "New"
|
||||
and type the path to where you extracted the Platform Tools
|
||||
3. Enable USB debugging on the Android Phone 3.1. Open settings 3.2. Open "About
|
||||
phone" (Might say tablet depending on what device you use) (skip steps 3.2
|
||||
and 3.3 if you already have developer options enabled) 3.3. Tap "Build
|
||||
Number" 7 or more times 3.4. Go to the main settings page 3.5. Open "System
|
||||
Settings" 3.6. Open "Developer options" 3.7. Enable "USB Debugging" 3.8. On
|
||||
your computer verify the phone is connected by running `adb devices` (You may
|
||||
need to tap "Allow" on the device to allow the computer to access it)
|
||||
4. Install Android OTP Extractor using pip
|
||||
```
|
||||
pip install git+https://github.com/puddly/android-otp-extractor
|
||||
```
|
||||
5. Install Authy from the playstore and login to your account
|
||||
6. Run the command below to export the TOTP to QRCodes and URLS
|
||||
```
|
||||
python -m android_otp_extractor --prepend-issuer --include authy
|
||||
```
|
||||
|
||||
### Exporting codes using Aegis Authenticator
|
||||
|
||||
This uses the tool [Aegis Authenticator](https://getaegis.app/) from [beemdevelopment](
|
||||
https://github.com/beemdevelopment).
|
||||
This uses the tool [Aegis Authenticator](https://getaegis.app/) from
|
||||
[beemdevelopment](https://github.com/beemdevelopment).
|
||||
|
||||
1. Install Authy and login on your rooted phone.
|
||||
2. Install Aegis Authenticator from the [Google Play Store](https://play.google.com/store/apps/details?id=com.beemdevelopment.aegis).
|
||||
3. In the app, click the three dots in the top right corner and click "Import & Export".
|
||||
2. Install Aegis Authenticator from the
|
||||
[Google Play Store](https://play.google.com/store/apps/details?id=com.beemdevelopment.aegis).
|
||||
3. In the app, click the three dots in the top right corner and click "Import &
|
||||
Export".
|
||||
4. Click "Import from another app" and choose Authy.
|
||||
5. The app will ask for root permissions, then automatically import your codes from Authy.
|
||||
6. Then export the codes from Aegis Authenticator to `json` or `txt` using the "Export to file" option in the "Import & Export" menu.
|
||||
5. The app will ask for root permissions, then automatically import your codes
|
||||
from Authy.
|
||||
6. Then export the codes from Aegis Authenticator to `json` or `txt` using the
|
||||
"Export to file" option in the "Import & Export" menu.
|
||||
|
||||
## Importing to Ente Authenticator (Method 1, method 2.1)
|
||||
|
||||
|
||||
@@ -31,10 +31,10 @@ exported data, including versioning and key derivation parameters.
|
||||
The main object used to represent the export data. It contains the following
|
||||
key-value pairs:
|
||||
|
||||
- `version`: The version of the export format.
|
||||
- `kdfParams`: Key derivation function parameters.
|
||||
- `encryptedData"`: The encrypted authentication data.
|
||||
- `encryptionNonce`: The nonce used for encryption.
|
||||
- `version`: The version of the export format.
|
||||
- `kdfParams`: Key derivation function parameters.
|
||||
- `encryptedData"`: The encrypted authentication data.
|
||||
- `encryptionNonce`: The nonce used for encryption.
|
||||
|
||||
#### Version
|
||||
|
||||
@@ -42,17 +42,17 @@ Export version is used to identify the format of the export data.
|
||||
|
||||
##### Ver: 1
|
||||
|
||||
- KDF Algorithm: `ARGON2ID`
|
||||
- Decrypted data format: `otpauth://totp/...`, separated by a new line.
|
||||
- Encryption Algo: `XChaCha20-Poly1305`
|
||||
- KDF Algorithm: `ARGON2ID`
|
||||
- Decrypted data format: `otpauth://totp/...`, separated by a new line.
|
||||
- Encryption Algo: `XChaCha20-Poly1305`
|
||||
|
||||
##### Key Derivation Function Params (KDF)
|
||||
|
||||
This section contains the parameters that were using during KDF operation:
|
||||
|
||||
- `memLimit`: Memory limit for the algorithm.
|
||||
- `opsLimit`: Operations limit for the algorithm.
|
||||
- `salt`: The salt used in the derivation process.
|
||||
- `memLimit`: Memory limit for the algorithm.
|
||||
- `opsLimit`: Operations limit for the algorithm.
|
||||
- `salt`: The salt used in the derivation process.
|
||||
|
||||
##### Encrypted Data
|
||||
|
||||
@@ -77,14 +77,14 @@ ente account update --app auth --email <email> --dir <path>
|
||||
|
||||
## How to use the exported data
|
||||
|
||||
- **Ente Authenticator app**: You can directly import the codes in the Ente
|
||||
Authenticator app.
|
||||
- **Ente Authenticator app**: You can directly import the codes in the Ente
|
||||
Authenticator app.
|
||||
|
||||
> Settings -> Data -> Import Codes -> Ente Encrypted export.
|
||||
|
||||
- **Decrypt using Ente CLI** : Download the latest version of [Ente
|
||||
CLI](https://github.com/ente-io/ente/releases?q=tag%3Acli-v0), and run the
|
||||
following command
|
||||
- **Decrypt using Ente CLI** : Download the latest version of
|
||||
[Ente CLI](https://github.com/ente-io/ente/releases?q=tag%3Acli-v0), and run
|
||||
the following command
|
||||
|
||||
```
|
||||
./ente auth decrypt <export_file> <output_file>
|
||||
|
||||
@@ -12,12 +12,12 @@ description:
|
||||
Ente Auth natively supports imports from many 2FA providers. In addition to the
|
||||
providers specifically listed in the documentation, the supported providers are:
|
||||
|
||||
- 2FAS Authenticator
|
||||
- Aegis Authenticator
|
||||
- Bitwarden
|
||||
- Google Authenticator
|
||||
- Raivo OTP
|
||||
- LastPass
|
||||
- 2FAS Authenticator
|
||||
- Aegis Authenticator
|
||||
- Bitwarden
|
||||
- Google Authenticator
|
||||
- Raivo OTP
|
||||
- LastPass
|
||||
|
||||
Details as to how codes may be imported from these providers may be found within
|
||||
the app.
|
||||
|
||||
@@ -6,7 +6,7 @@ description:
|
||||
|
||||
# Migrating to/from Ente Auth
|
||||
|
||||
- [Migrating from Authy](authy/)
|
||||
- [Importing codes from Steam](steam/)
|
||||
- [Migrating from other apps](import)
|
||||
- [Exporting your data out of Ente Auth](export)
|
||||
- [Migrating from Authy](authy/)
|
||||
- [Importing codes from Steam](steam/)
|
||||
- [Migrating from other apps](import)
|
||||
- [Exporting your data out of Ente Auth](export)
|
||||
|
||||
@@ -12,17 +12,15 @@ to your local drive. This way, you can use Ente in your day to day use, but will
|
||||
have an additional guarantee that a copy of your original photos and videos are
|
||||
always available in normal directories and files.
|
||||
|
||||
- You can use
|
||||
[Ente's CLI](https://github.com/ente-io/ente/tree/main/cli#export) to export
|
||||
your data in a cron job to a location of your choice. The exports are
|
||||
incremental, and will also gracefully handle interruptions.
|
||||
- You can use [Ente's CLI](https://github.com/ente-io/ente/tree/main/cli#export)
|
||||
to export your data in a cron job to a location of your choice. The exports
|
||||
are incremental, and will also gracefully handle interruptions.
|
||||
|
||||
- Similarly, you can use Ente's
|
||||
[desktop app](https://ente.io/download/desktop) to export your data to a
|
||||
folder of your choice. The desktop app also supports "continuous" exports,
|
||||
where it will automatically export new items in the background without you
|
||||
needing to run any other cron jobs. See
|
||||
[migration/export](/photos/migration/export/) for more details.
|
||||
- Similarly, you can use Ente's [desktop app](https://ente.io/download/desktop)
|
||||
to export your data to a folder of your choice. The desktop app also supports
|
||||
"continuous" exports, where it will automatically export new items in the
|
||||
background without you needing to run any other cron jobs. See
|
||||
[migration/export](/photos/migration/export/) for more details.
|
||||
|
||||
## Does the exported data preserve folder structure?
|
||||
|
||||
@@ -32,8 +30,8 @@ album structure how you have set up within Ente.
|
||||
## Does the exported data preserve metadata?
|
||||
|
||||
Yes, the metadata is written out to a separate JSON file during export. Note
|
||||
that the original is not modified. For more details, see the [description of the
|
||||
exported metadata](https://help.ente.io/photos/faq/photo-dates#export).
|
||||
that the original is not modified. For more details, see the
|
||||
[description of the exported metadata](https://help.ente.io/photos/faq/photo-dates#export).
|
||||
|
||||
## Can I do a 2-way sync?
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@ You can install Ente directly from
|
||||
Reproducible builds for Ente are available on
|
||||
[F-Droid](https://f-droid.org/packages/io.ente.photos.fdroid/).
|
||||
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> Releases over F-Droid are generally slower since they run their own build
|
||||
@@ -34,20 +33,22 @@ you stay updated.
|
||||
### Obtainium
|
||||
|
||||
You can setup [Obtainium](https://github.com/ImranR98/Obtainium) to track our
|
||||
GitHub releases by [clicking this link](https://apps.obtainium.imranr.dev/redirect?r=obtainium://app/%7B%22id%22%3A%22io.ente.photos.independent%22%2C%22url%22%3A%22https%3A%2F%2Fgithub.com%2Fente-io%2Fente%22%2C%22author%22%3A%22ente-io%22%2C%22name%22%3A%22Ente%20Photos%22%2C%22preferredApkIndex%22%3A0%2C%22additionalSettings%22%3A%22%7B%5C%22includePrereleases%5C%22%3Afalse%2C%5C%22fallbackToOlderReleases%5C%22%3Atrue%2C%5C%22filterReleaseTitlesByRegEx%5C%22%3A%5C%22%5C%22%2C%5C%22filterReleaseNotesByRegEx%5C%22%3A%5C%22%5C%22%2C%5C%22verifyLatestTag%5C%22%3Afalse%2C%5C%22dontSortReleasesList%5C%22%3Atrue%2C%5C%22useLatestAssetDateAsReleaseDate%5C%22%3Afalse%2C%5C%22releaseTitleAsVersion%5C%22%3Afalse%2C%5C%22trackOnly%5C%22%3Afalse%2C%5C%22versionExtractionRegEx%5C%22%3A%5C%22%5C%22%2C%5C%22matchGroupToUse%5C%22%3A%5C%22%5C%22%2C%5C%22versionDetection%5C%22%3Atrue%2C%5C%22releaseDateAsVersion%5C%22%3Afalse%2C%5C%22useVersionCodeAsOSVersion%5C%22%3Afalse%2C%5C%22apkFilterRegEx%5C%22%3A%5C%22ente-photos*%5C%22%2C%5C%22invertAPKFilter%5C%22%3Afalse%2C%5C%22autoApkFilterByArch%5C%22%3Atrue%2C%5C%22appName%5C%22%3A%5C%22%5C%22%2C%5C%22shizukuPretendToBeGooglePlay%5C%22%3Afalse%2C%5C%22allowInsecure%5C%22%3Afalse%2C%5C%22exemptFromBackgroundUpdates%5C%22%3Afalse%2C%5C%22skipUpdateNotifications%5C%22%3Afalse%2C%5C%22about%5C%22%3A%5C%22%5C%22%7D%22%2C%22overrideSource%22%3Anull%7D) to add it instantly.
|
||||
GitHub releases by
|
||||
[clicking this link](https://apps.obtainium.imranr.dev/redirect?r=obtainium://app/%7B%22id%22%3A%22io.ente.photos.independent%22%2C%22url%22%3A%22https%3A%2F%2Fgithub.com%2Fente-io%2Fente%22%2C%22author%22%3A%22ente-io%22%2C%22name%22%3A%22Ente%20Photos%22%2C%22preferredApkIndex%22%3A0%2C%22additionalSettings%22%3A%22%7B%5C%22includePrereleases%5C%22%3Afalse%2C%5C%22fallbackToOlderReleases%5C%22%3Atrue%2C%5C%22filterReleaseTitlesByRegEx%5C%22%3A%5C%22%5C%22%2C%5C%22filterReleaseNotesByRegEx%5C%22%3A%5C%22%5C%22%2C%5C%22verifyLatestTag%5C%22%3Afalse%2C%5C%22dontSortReleasesList%5C%22%3Atrue%2C%5C%22useLatestAssetDateAsReleaseDate%5C%22%3Afalse%2C%5C%22releaseTitleAsVersion%5C%22%3Afalse%2C%5C%22trackOnly%5C%22%3Afalse%2C%5C%22versionExtractionRegEx%5C%22%3A%5C%22%5C%22%2C%5C%22matchGroupToUse%5C%22%3A%5C%22%5C%22%2C%5C%22versionDetection%5C%22%3Atrue%2C%5C%22releaseDateAsVersion%5C%22%3Afalse%2C%5C%22useVersionCodeAsOSVersion%5C%22%3Afalse%2C%5C%22apkFilterRegEx%5C%22%3A%5C%22ente-photos*%5C%22%2C%5C%22invertAPKFilter%5C%22%3Afalse%2C%5C%22autoApkFilterByArch%5C%22%3Atrue%2C%5C%22appName%5C%22%3A%5C%22%5C%22%2C%5C%22shizukuPretendToBeGooglePlay%5C%22%3Afalse%2C%5C%22allowInsecure%5C%22%3Afalse%2C%5C%22exemptFromBackgroundUpdates%5C%22%3Afalse%2C%5C%22skipUpdateNotifications%5C%22%3Afalse%2C%5C%22about%5C%22%3A%5C%22%5C%22%7D%22%2C%22overrideSource%22%3Anull%7D)
|
||||
to add it instantly.
|
||||
|
||||
Alternatively, you can follow these steps:
|
||||
|
||||
1. Click **Add App** to open a new app config screen
|
||||
2. Enter `https://github.com/ente-io/ente` in the **App Source URL** field
|
||||
3. Enable the **Retain release order** from API toggle
|
||||
4. Scroll down to the **Filter APKs by Regular Expression** field and enter `ente-photos*`
|
||||
4. Scroll down to the **Filter APKs by Regular Expression** field and enter
|
||||
`ente-photos*`
|
||||
5. Enable the **Attempt to filter APKs by CPU architecture** if possible toggle
|
||||
6. Select any applicable app category labels you may have setup
|
||||
7. Enable the **Try inferring app ID from source code** toggle
|
||||
8. Scroll back to the top and click **Add** to complete the setup
|
||||
|
||||
|
||||
<br/>
|
||||
|
||||
---
|
||||
@@ -78,7 +79,8 @@ You can grab the latest version of Ente for Mac, Windows and Linux from
|
||||
|
||||
# Web
|
||||
|
||||
Latest versions of our web app are available at [web.ente.io](https://web.ente.io).
|
||||
Latest versions of our web app are available at
|
||||
[web.ente.io](https://web.ente.io).
|
||||
|
||||
<br/>
|
||||
|
||||
|
||||
@@ -25,9 +25,9 @@ your files. For technical details, please see our
|
||||
|
||||
We use the following encryption algorithms:
|
||||
|
||||
- Encryption: `XChaCha20` and `XSalsa20`
|
||||
- Authentication: Poly1305 message authentication code (MAC)
|
||||
- Key derivation: Argon2id with high memory and computation parameters
|
||||
- Encryption: `XChaCha20` and `XSalsa20`
|
||||
- Authentication: Poly1305 message authentication code (MAC)
|
||||
- Key derivation: Argon2id with high memory and computation parameters
|
||||
|
||||
These algorithms are implemented using
|
||||
[libsodium](https://libsodium.gitbook.io/doc/), a externally audited
|
||||
@@ -38,9 +38,9 @@ provides full technical specifications.
|
||||
|
||||
Your encrypted data is stored redundantly across multiple providers in the EU:
|
||||
|
||||
- Amsterdam, Netherlands
|
||||
- Paris, France
|
||||
- Frankfurt, Germany
|
||||
- Amsterdam, Netherlands
|
||||
- Paris, France
|
||||
- Frankfurt, Germany
|
||||
|
||||
We use a combination of object storage and distributed databases to ensure high
|
||||
availability and durability. Our
|
||||
@@ -79,8 +79,8 @@ please choose a strong one.
|
||||
|
||||
Yes, we recommend enabling 2FA for an additional layer of security. We support:
|
||||
|
||||
- Time-based One-Time Passwords (TOTP)
|
||||
- WebAuthn/FIDO2 for hardware security keys
|
||||
- Time-based One-Time Passwords (TOTP)
|
||||
- WebAuthn/FIDO2 for hardware security keys
|
||||
|
||||
You can set up 2FA in the settings of our mobile or desktop apps.
|
||||
|
||||
|
||||
@@ -15,17 +15,16 @@ Yes we do! Please check out our announcement post
|
||||
|
||||
In brief,
|
||||
|
||||
- Your family members can use storage space from your plan without paying
|
||||
extra.
|
||||
- Your family members can use storage space from your plan without paying extra.
|
||||
|
||||
- Ask them to sign up for Ente, and then just add them to your existing plan
|
||||
using the "Manage family" option within your Subscription settings.
|
||||
- Ask them to sign up for Ente, and then just add them to your existing plan
|
||||
using the "Manage family" option within your Subscription settings.
|
||||
|
||||
- Each member gets their own private space, and cannot see each other's files
|
||||
unless they're shared.
|
||||
- Each member gets their own private space, and cannot see each other's files
|
||||
unless they're shared.
|
||||
|
||||
- You can invite 5 family members. So including yourself, it will be 6 people
|
||||
who can share a single subscription, paying only once.
|
||||
- You can invite 5 family members. So including yourself, it will be 6 people
|
||||
who can share a single subscription, paying only once.
|
||||
|
||||
Note that family plans are meant as a way to share storage. For sharing photos,
|
||||
you can create [shared albums and links](/photos/features/share).
|
||||
@@ -72,9 +71,9 @@ Once the payment is completed, your account will be upgraded to the chosen plan.
|
||||
|
||||
We accept the following crypto currencies:
|
||||
|
||||
- Bitcoin
|
||||
- Ethereum
|
||||
- Dogecoin
|
||||
- Bitcoin
|
||||
- Ethereum
|
||||
- Dogecoin
|
||||
|
||||
To purchase a subscription with any of the above mentioned currencies, please
|
||||
write to crypto@ente.io from your registered email address, citing the
|
||||
@@ -129,11 +128,10 @@ invoicing you for the new plan.
|
||||
For example, if you are half way through the year on the 50 GB yearly plan, and
|
||||
upgrade to the 200 GB yearly plan, then
|
||||
|
||||
- The new 200 GB yearly plan will go into effect immediately.
|
||||
- The new 200 GB yearly plan will go into effect immediately.
|
||||
|
||||
- But we will reduce the charges for the first year by subtracting the
|
||||
remaining half year balance of the 50 GB yearly plan that you'd already
|
||||
paid.
|
||||
- But we will reduce the charges for the first year by subtracting the remaining
|
||||
half year balance of the 50 GB yearly plan that you'd already paid.
|
||||
|
||||
The same applies to monthly plans.
|
||||
|
||||
@@ -146,14 +144,13 @@ future invoices.
|
||||
For example, if you are half way through the year on the 200 GB yearly plan, and
|
||||
downgrade to the 50 GB yearly plan, then
|
||||
|
||||
- The new 50 GB yearly plan will go into effect immediately.
|
||||
- The new 50 GB yearly plan will go into effect immediately.
|
||||
|
||||
- We will calculate a credit by subtracting half the price of the 50 GB plan
|
||||
from half the price of the 200 GB plan. This will be credited to your
|
||||
account.
|
||||
- We will calculate a credit by subtracting half the price of the 50 GB plan
|
||||
from half the price of the 200 GB plan. This will be credited to your account.
|
||||
|
||||
- This credited amount will be discounted from your next invoice, which will
|
||||
be due in half a year.
|
||||
- This credited amount will be discounted from your next invoice, which will be
|
||||
due in half a year.
|
||||
|
||||
The same applies to monthly plans.
|
||||
|
||||
|
||||
@@ -29,28 +29,28 @@ If the folder you're trying to upload has nesting and you select the option to
|
||||
create a new album, you will see two options - **A single album** and **Separate
|
||||
albums**.
|
||||
|
||||
- **Single album** will create a new Ente album with the same name as the
|
||||
folder's name, and will then sync all the changes in the folder (and any
|
||||
nested folders) to this single album.
|
||||
- **Single album** will create a new Ente album with the same name as the
|
||||
folder's name, and will then sync all the changes in the folder (and any
|
||||
nested folders) to this single album.
|
||||
|
||||
- **Separate albums** will create separate albums for each nested folder of
|
||||
the selected folder, and will then sync the changes in each nested folder
|
||||
separately.
|
||||
- **Separate albums** will create separate albums for each nested folder of the
|
||||
selected folder, and will then sync the changes in each nested folder
|
||||
separately.
|
||||
|
||||
- For example, suppose you have a folder name `Photos` on your computer, and
|
||||
inside that folder you have two nested folders named `New Year` and
|
||||
`Summer`. In the single album mode, the app will create an Ente album named
|
||||
"Photos" and put all the files from both `New Year` and `Summer` there. In
|
||||
the separate album mode, the app will create two Ente albums, "New Year" and
|
||||
"Summer", each only containing the respective files.
|
||||
- For example, suppose you have a folder name `Photos` on your computer, and
|
||||
inside that folder you have two nested folders named `New Year` and `Summer`.
|
||||
In the single album mode, the app will create an Ente album named "Photos" and
|
||||
put all the files from both `New Year` and `Summer` there. In the separate
|
||||
album mode, the app will create two Ente albums, "New Year" and "Summer", each
|
||||
only containing the respective files.
|
||||
|
||||
- In separate album mode, only nested folders that have at least one file will
|
||||
result in the creation of a new album – empty folders (or folders that only
|
||||
contain other folders) will be ignored.
|
||||
- In separate album mode, only nested folders that have at least one file will
|
||||
result in the creation of a new album – empty folders (or folders that only
|
||||
contain other folders) will be ignored.
|
||||
|
||||
- In separate album mode, only the leafmost folder name is considered. For
|
||||
example, both `A/B/C/D/x.png` and `1/2/3/D/y.png` will get uploaded into the
|
||||
same Ente album named "D".
|
||||
- In separate album mode, only the leafmost folder name is considered. For
|
||||
example, both `A/B/C/D/x.png` and `1/2/3/D/y.png` will get uploaded into the
|
||||
same Ente album named "D".
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
@@ -64,18 +64,18 @@ Personalize your albums by giving them a meaningful name.
|
||||
|
||||
### How to rename an album on your mobile?
|
||||
|
||||
- Open the album
|
||||
- Tap the three dots button in the top right corner of the screen
|
||||
- Tap _Rename album_, then type in a new name
|
||||
- Tap on _Rename_ button
|
||||
- Open the album
|
||||
- Tap the three dots button in the top right corner of the screen
|
||||
- Tap _Rename album_, then type in a new name
|
||||
- Tap on _Rename_ button
|
||||
|
||||
### How to rename an album on your web / desktop?
|
||||
|
||||
- Open the album
|
||||
- Click on the overflow menu in the top right corner
|
||||
- Click the _Rename album_ button
|
||||
- Type in a new name
|
||||
- Click on _Rename_ or press enter
|
||||
- Open the album
|
||||
- Click on the overflow menu in the top right corner
|
||||
- Click the _Rename album_ button
|
||||
- Type in a new name
|
||||
- Click on _Rename_ or press enter
|
||||
|
||||
## Set album cover
|
||||
|
||||
@@ -83,13 +83,13 @@ Select any photo you want to use as the cover for your album.
|
||||
|
||||
### How to set an album cover on mobile?
|
||||
|
||||
- Open the album you want to change
|
||||
- Tap the three dots button in the top right corner
|
||||
- From the menu options, select _Set cover_
|
||||
- A new screen will appear, propmpting you to select the cover photo
|
||||
- Browse through your photos and tap on the image you want to set as the album
|
||||
cover
|
||||
- Then tap on _Use selected photo_
|
||||
- Open the album you want to change
|
||||
- Tap the three dots button in the top right corner
|
||||
- From the menu options, select _Set cover_
|
||||
- A new screen will appear, propmpting you to select the cover photo
|
||||
- Browse through your photos and tap on the image you want to set as the album
|
||||
cover
|
||||
- Then tap on _Use selected photo_
|
||||
|
||||
## View your photos on a map
|
||||
|
||||
@@ -97,10 +97,10 @@ Explore your memories based on their location.
|
||||
|
||||
### How to explore the album's photos in map view?
|
||||
|
||||
- Open the album
|
||||
- Tap on the three dots button in the top right corner
|
||||
- Select _Map_
|
||||
- This will show all photos of the album in a map view
|
||||
- Open the album
|
||||
- Tap on the three dots button in the top right corner
|
||||
- Select _Map_
|
||||
- This will show all photos of the album in a map view
|
||||
|
||||
## Sort albums
|
||||
|
||||
@@ -108,17 +108,17 @@ Maintain order in your albums by arranging them from the newest to the oldest.
|
||||
|
||||
### How to change the sort order on mobile?
|
||||
|
||||
- Open the album
|
||||
- Tap on the three dots button in the top right corner
|
||||
- Select _Sort by_
|
||||
- Tap on the _Newest first_ for the latest, Or _Oldest first_ for the oldest
|
||||
- Open the album
|
||||
- Tap on the three dots button in the top right corner
|
||||
- Select _Sort by_
|
||||
- Tap on the _Newest first_ for the latest, Or _Oldest first_ for the oldest
|
||||
|
||||
### How to change the sort order on web / desktop?
|
||||
|
||||
- Open the album
|
||||
- Click on the three dots button in the top right corner
|
||||
- Click _Sort by_
|
||||
- Tap on the _Newest first_ for the latest, Or _Oldest first_ for the oldest
|
||||
- Open the album
|
||||
- Click on the three dots button in the top right corner
|
||||
- Click _Sort by_
|
||||
- Tap on the _Newest first_ for the latest, Or _Oldest first_ for the oldest
|
||||
|
||||
## Pin albums
|
||||
|
||||
@@ -126,6 +126,6 @@ Keep your favorite album at the top by pinning them for quick access.
|
||||
|
||||
### How to pin/unpin an album on mobile?
|
||||
|
||||
- Open the album
|
||||
- Tap on the three dots button in the top right corner
|
||||
- Tap on _Pin album_ / _Unpin album_
|
||||
- Open the album
|
||||
- Tap on the three dots button in the top right corner
|
||||
- Tap on _Pin album_ / _Unpin album_
|
||||
|
||||
@@ -11,43 +11,43 @@ You can remove a photo (owned by you) or an album from your **home timeline** by
|
||||
archiving it. Archived photos won't be included in the memories section on the
|
||||
mobile app.
|
||||
|
||||
- All photos within a archived album will be removed from home timeline, even
|
||||
when some of the photos are also present in a non-archived album.
|
||||
- You can archive albums that are owned by you or shared with you.
|
||||
- Search results will include archived photos. If you want to hide photos from
|
||||
search result, use [Hide](./hide) feature.
|
||||
- All photos within a archived album will be removed from home timeline, even
|
||||
when some of the photos are also present in a non-archived album.
|
||||
- You can archive albums that are owned by you or shared with you.
|
||||
- Search results will include archived photos. If you want to hide photos from
|
||||
search result, use [Hide](./hide) feature.
|
||||
|
||||
## How to
|
||||
|
||||
### Archive Album
|
||||
|
||||
- Open the album
|
||||
- Click on the overflow menu
|
||||
- Click on Archive album
|
||||
- Open the album
|
||||
- Click on the overflow menu
|
||||
- Click on Archive album
|
||||
|
||||
### Archive Photo
|
||||
|
||||
- Long press to select the photo
|
||||
- Select Archive option from the bottom menu.
|
||||
- Long press to select the photo
|
||||
- Select Archive option from the bottom menu.
|
||||
|
||||
### View Archived Photos and Albums
|
||||
|
||||
#### Mobile
|
||||
|
||||
- Go to Albums tab
|
||||
- Scroll down to bottom
|
||||
- Click on Archive button.
|
||||
- Go to Albums tab
|
||||
- Scroll down to bottom
|
||||
- Click on Archive button.
|
||||
|
||||
#### Web / Desktop
|
||||
|
||||
- Click on the topleft hamburger menu
|
||||
- Click on Archive
|
||||
- Click on the topleft hamburger menu
|
||||
- Click on Archive
|
||||
|
||||
### Metadata Privacy
|
||||
|
||||
Both Ente and the person with whom you are sharing an album or photo have no
|
||||
information about whether you have:
|
||||
|
||||
- Archived a photo
|
||||
- Archived an album
|
||||
- Archived a shared album
|
||||
- Archived a photo
|
||||
- Archived an album
|
||||
- Archived a shared album
|
||||
|
||||
@@ -52,6 +52,6 @@ app, though the [way that works](watch-folders) is a bit different.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
- On iOS, make sure that you're not killing the Ente app.
|
||||
- On Android, make sure that "Optimize battery usage" is not turned on in
|
||||
system settings for the Ente app.
|
||||
- On iOS, make sure that you're not killing the Ente app.
|
||||
- On Android, make sure that "Optimize battery usage" is not turned on in system
|
||||
settings for the Ente app.
|
||||
|
||||
@@ -7,9 +7,9 @@ description: Collaborate with other people using shared albums and public links
|
||||
|
||||
Ente allows you to collaborate with people in 2 ways:
|
||||
|
||||
- Collaborative albums
|
||||
- Collaborative albums
|
||||
|
||||
- Collaborative links
|
||||
- Collaborative links
|
||||
|
||||
## Collaborative albums
|
||||
|
||||
@@ -17,25 +17,25 @@ Collaborative albums allow multiple Ente users to add photos to the same shared
|
||||
album. Storage is only counted once, irrespective of the number of collaborators
|
||||
and viewers.
|
||||
|
||||
- The owner of the album is the person who created it.
|
||||
- The owner of the album is the person who created it.
|
||||
|
||||
- The owner can add collaborators and viewers by their email. The owner can
|
||||
also change permissions of participants at any time, and remove them.
|
||||
- The owner can add collaborators and viewers by their email. The owner can also
|
||||
change permissions of participants at any time, and remove them.
|
||||
|
||||
- Collaborators can add photos (and videos) to the shared album.
|
||||
- Collaborators can add photos (and videos) to the shared album.
|
||||
|
||||
- The storage of the photo is counted towards the owner of the photo - the
|
||||
person who uploaded it. Since the uploader usually has the photo in their
|
||||
account anyway, effectively this means that the photo can be added to a
|
||||
collaborative album without paying anything extra.
|
||||
- The storage of the photo is counted towards the owner of the photo - the
|
||||
person who uploaded it. Since the uploader usually has the photo in their
|
||||
account anyway, effectively this means that the photo can be added to a
|
||||
collaborative album without paying anything extra.
|
||||
|
||||
- The owner of the photo can remove it from the album (or delete it).
|
||||
- The owner of the photo can remove it from the album (or delete it).
|
||||
|
||||
- The owner of the album can remove all photos from the album (they can only
|
||||
delete the photos they own).
|
||||
- The owner of the album can remove all photos from the album (they can only
|
||||
delete the photos they own).
|
||||
|
||||
- When a collaborator is removed from a shared album (or when they leave the
|
||||
album), any photos they'd uploaded will also be removed.
|
||||
- When a collaborator is removed from a shared album (or when they leave the
|
||||
album), any photos they'd uploaded will also be removed.
|
||||
|
||||
Currently collaborative albums can only be used from the mobile app. A
|
||||
collaborator will see them in view only mode in the web and desktop apps; we're
|
||||
@@ -46,13 +46,12 @@ actively working on adding support for them on web and desktop too.
|
||||
Collaborative links allow you to collaborate with people who might not have an
|
||||
Ente account or the Ente apps.
|
||||
|
||||
- You can create a public link, and anyone with access to the link will be
|
||||
able to view the shared photos using just their web browser (no login
|
||||
required).
|
||||
- You can create a public link, and anyone with access to the link will be able
|
||||
to view the shared photos using just their web browser (no login required).
|
||||
|
||||
- You can enable the "Allow adding photos" option on a public link to allow
|
||||
people to also add photos the same way (from their web browser, no login
|
||||
required).
|
||||
- You can enable the "Allow adding photos" option on a public link to allow
|
||||
people to also add photos the same way (from their web browser, no login
|
||||
required).
|
||||
|
||||
Such collaborative links are also sometimes called "collect links", since they
|
||||
allow you to collect photos from people without them needing Ente accounts. A
|
||||
|
||||
@@ -7,27 +7,26 @@ description: Collecting photos from others using Ente Photos
|
||||
|
||||
Collecting memories from events is now a breeze!
|
||||
|
||||
- Whether it's a birthday party, vacation trip or wedding, easily share your
|
||||
album using a unique, secure, end-to-end encrypted link.
|
||||
- Introduce the 'collect photos' feature to your friends and family who can
|
||||
contribute without an Ente account.
|
||||
- This allows them to effortlessly add, view, and download photos from the
|
||||
link without an Ente account.
|
||||
- Also preserves metadata and photo quality.
|
||||
- Whether it's a birthday party, vacation trip or wedding, easily share your
|
||||
album using a unique, secure, end-to-end encrypted link.
|
||||
- Introduce the 'collect photos' feature to your friends and family who can
|
||||
contribute without an Ente account.
|
||||
- This allows them to effortlessly add, view, and download photos from the link
|
||||
without an Ente account.
|
||||
- Also preserves metadata and photo quality.
|
||||
|
||||
## How to collect photos on mobile?
|
||||
|
||||
- Open the album you want to share with
|
||||
- Tap on the Share album icon in the top right corner of the screen
|
||||
- Select _Collect photos_
|
||||
- Tap _Copy link_
|
||||
- The link will get copied to your clipboard. Now, feel free to share it
|
||||
- Open the album you want to share with
|
||||
- Tap on the Share album icon in the top right corner of the screen
|
||||
- Select _Collect photos_
|
||||
- Tap _Copy link_
|
||||
- The link will get copied to your clipboard. Now, feel free to share it
|
||||
|
||||
## How to Collect photos on web / desktop?
|
||||
|
||||
- Open the album
|
||||
- Click on the share album icon
|
||||
- Select _Collect photos_
|
||||
- Click on _Copy link_
|
||||
- The link will get copied to your clipboard. Share it effortlessly with
|
||||
others!
|
||||
- Open the album
|
||||
- Click on the share album icon
|
||||
- Select _Collect photos_
|
||||
- Click on _Copy link_
|
||||
- The link will get copied to your clipboard. Share it effortlessly with others!
|
||||
|
||||
@@ -21,16 +21,16 @@ the platform's nuances.
|
||||
|
||||
#### Mobile
|
||||
|
||||
- On iOS, a hash will be used to detect exact duplicates. If the duplicate is
|
||||
being uploaded to an album where a photo with the same hash already exists,
|
||||
then the duplicate will be skipped. If it is being uploaded to a different
|
||||
album, then a symlink will be created (so no actual data will need to be
|
||||
uploaded, just a symlink will be created to the existing file).
|
||||
- On iOS, a hash will be used to detect exact duplicates. If the duplicate is
|
||||
being uploaded to an album where a photo with the same hash already exists,
|
||||
then the duplicate will be skipped. If it is being uploaded to a different
|
||||
album, then a symlink will be created (so no actual data will need to be
|
||||
uploaded, just a symlink will be created to the existing file).
|
||||
|
||||
- On Android also, a hash check is used. But unlike iOS, the native Android
|
||||
filesystem behaviour is to keep physical copies if the same photo is in
|
||||
different albums. So Ente does the same: duplicates to same album will be
|
||||
skipped, duplicates when going to separate albums will create copies.
|
||||
- On Android also, a hash check is used. But unlike iOS, the native Android
|
||||
filesystem behaviour is to keep physical copies if the same photo is in
|
||||
different albums. So Ente does the same: duplicates to same album will be
|
||||
skipped, duplicates when going to separate albums will create copies.
|
||||
|
||||
#### Web and desktop
|
||||
|
||||
|
||||
@@ -11,22 +11,21 @@ additional cost** as you have already paid for the storage.
|
||||
|
||||
In brief,
|
||||
|
||||
- Your family members can use storage space from your plan without paying
|
||||
extra.
|
||||
- Your family members can use storage space from your plan without paying extra.
|
||||
|
||||
- Ask them to sign up for Ente, and then just add them to your existing plan
|
||||
using the "Manage family" option within your Subscription settings.
|
||||
- Ask them to sign up for Ente, and then just add them to your existing plan
|
||||
using the "Manage family" option within your Subscription settings.
|
||||
|
||||
- Each member gets their own private space, and cannot see each other's files
|
||||
unless they're shared.
|
||||
- Each member gets their own private space, and cannot see each other's files
|
||||
unless they're shared.
|
||||
|
||||
- You can invite 5 family members. So including yourself, it will be 6 people
|
||||
who can share a single subscription, paying only once.
|
||||
- You can invite 5 family members. So including yourself, it will be 6 people
|
||||
who can share a single subscription, paying only once.
|
||||
|
||||
## FAQ
|
||||
|
||||
- **Can you assign a storage quota for each individual member in the family
|
||||
plan?**
|
||||
- **Can you assign a storage quota for each individual member in the family
|
||||
plan?**
|
||||
|
||||
Unfortunately, at this moment, assigning a storage quota for each individual
|
||||
member in the family plan is not supported. For updates on this feature
|
||||
|
||||
@@ -12,54 +12,54 @@ that the hidden photos won't be surfaced anywhere in the app without explicit
|
||||
authentication, whereas archiving only removes them from the home timeline and
|
||||
memories sections.
|
||||
|
||||
- Hidden photos and albums will be removed from home timelines, memories,
|
||||
albums tab, search results, and any other visable place in the app.
|
||||
- Hidden photos and albums will be removed from home timelines, memories, albums
|
||||
tab, search results, and any other visable place in the app.
|
||||
|
||||
- Hidden photos will be removed from all regular albums. If you want to unhide
|
||||
again you will have to specify the album to move it to.
|
||||
- Hidden photos will be removed from all regular albums. If you want to unhide
|
||||
again you will have to specify the album to move it to.
|
||||
|
||||
- You cannot hide photos or albums shared with you. You can archive shared
|
||||
albums instead.
|
||||
- You cannot hide photos or albums shared with you. You can archive shared
|
||||
albums instead.
|
||||
|
||||
## How to
|
||||
|
||||
### Hide album
|
||||
|
||||
- Open the album
|
||||
- Click on the overflow menu
|
||||
- Click on _Hide album_
|
||||
- Open the album
|
||||
- Click on the overflow menu
|
||||
- Click on _Hide album_
|
||||
|
||||
### Hide photo
|
||||
|
||||
- Select the photo
|
||||
- Click on _Hide_ option from the select menu
|
||||
- Select the photo
|
||||
- Click on _Hide_ option from the select menu
|
||||
|
||||
### View hidden photos and albums
|
||||
|
||||
#### Mobile
|
||||
|
||||
- Go to Albums tab
|
||||
- Scroll down to bottom
|
||||
- Click on _Hidden_ button
|
||||
- Authenticate in app
|
||||
- Go to Albums tab
|
||||
- Scroll down to bottom
|
||||
- Click on _Hidden_ button
|
||||
- Authenticate in app
|
||||
|
||||
#### Web / Desktop
|
||||
|
||||
- Click on the topleft hamburger menu
|
||||
- Click on _Hidden_
|
||||
- Authenticate in app
|
||||
- Click on the topleft hamburger menu
|
||||
- Click on _Hidden_
|
||||
- Authenticate in app
|
||||
|
||||
### Unhide album
|
||||
|
||||
- Open the hidden album
|
||||
- Click on the overflow menu
|
||||
- Click on _Unhide album_
|
||||
- Open the hidden album
|
||||
- Click on the overflow menu
|
||||
- Click on _Unhide album_
|
||||
|
||||
### Unhide photo
|
||||
|
||||
- Select the hidden photo
|
||||
- Click on _Unhide_ option from the select menu
|
||||
- Click on the album the photo should be restored to
|
||||
- Select the hidden photo
|
||||
- Click on _Unhide_ option from the select menu
|
||||
- Click on the album the photo should be restored to
|
||||
|
||||
## Metadata Privacy
|
||||
|
||||
|
||||
@@ -5,15 +5,21 @@ description: Using Legacy to pass on your memories to loved ones
|
||||
|
||||
# Legacy
|
||||
|
||||
Legacy allows trusted contacts to recover your account in your absence. The main usecase here is to pass on your memories after your death. It can also be useful for other cases - for e.g., when you forget your password and recovery key.
|
||||
Legacy allows trusted contacts to recover your account in your absence. The main
|
||||
usecase here is to pass on your memories after your death. It can also be useful
|
||||
for other cases - for e.g., when you forget your password and recovery key.
|
||||
|
||||
Trusted Contacts can initiate a recovery, and if not blocked in 30 days, would be able to change the password to your account and thereby access your memories.
|
||||
Trusted Contacts can initiate a recovery, and if not blocked in 30 days, would
|
||||
be able to change the password to your account and thereby access your memories.
|
||||
|
||||
## Adding a trusted contact
|
||||
|
||||
You can add a trusted contact for your account using the mobile app for Ente Photos. Go to Settings -> Account -> Legacy, and click on "Add Trusted Contact".
|
||||
You can add a trusted contact for your account using the mobile app for Ente
|
||||
Photos. Go to Settings -> Account -> Legacy, and click on "Add Trusted Contact".
|
||||
|
||||
You would be asked to enter the email address of the trusted contact you want to add or choose from a list of contacts on Ente. Please note that the trusted contact must be an Ente user.
|
||||
You would be asked to enter the email address of the trusted contact you want to
|
||||
add or choose from a list of contacts on Ente. Please note that the trusted
|
||||
contact must be an Ente user.
|
||||
|
||||
<div align="center">
|
||||
|
||||
@@ -21,7 +27,10 @@ You would be asked to enter the email address of the trusted contact you want to
|
||||
|
||||
</div>
|
||||
|
||||
The trusted contact must accept your request. They can do so by going to Settings -> Account -> Legacy in the Ente Photos mobile app, and clicking on your email address within the Legacy accounts sections. Ente would also send an email notification to the trusted contact to nudge them to accept the invite.
|
||||
The trusted contact must accept your request. They can do so by going to
|
||||
Settings -> Account -> Legacy in the Ente Photos mobile app, and clicking on
|
||||
your email address within the Legacy accounts sections. Ente would also send an
|
||||
email notification to the trusted contact to nudge them to accept the invite.
|
||||
|
||||
<div align="center">
|
||||
|
||||
@@ -31,7 +40,9 @@ The trusted contact must accept your request. They can do so by going to Setting
|
||||
|
||||
## Recovering an account as a trusted contact
|
||||
|
||||
As a trusted contact, you can recover an account by going to Settings -> Account -> Legacy in the Ente photos app, tapping on the email address of the account within the Legacy account sections.
|
||||
As a trusted contact, you can recover an account by going to Settings -> Account
|
||||
-> Legacy in the Ente photos app, tapping on the email address of the account
|
||||
within the Legacy account sections.
|
||||
|
||||
<div align="center">
|
||||
|
||||
@@ -39,12 +50,20 @@ As a trusted contact, you can recover an account by going to Settings -> Account
|
||||
|
||||
</div>
|
||||
|
||||
Once the recovery is initiated, the account owner would get 30 days to block the recovery. After 30 days, you can go the same page in the app, where you will be prompted to change the password of the account. Once you change the password, you would be able to access the recovered account with the new password.
|
||||
Once the recovery is initiated, the account owner would get 30 days to block the
|
||||
recovery. After 30 days, you can go the same page in the app, where you will be
|
||||
prompted to change the password of the account. Once you change the password,
|
||||
you would be able to access the recovered account with the new password.
|
||||
|
||||
## Blocking account recovery by a trusted contact
|
||||
|
||||
After a trusted contact initiates a recover, you, as the account owner, would get 30 days to block the recovery. To do this, you must go to Settings -> Account -> Legacy, where you will see a message that recovery of the account has been initiated. Tapping on that will allow you to block the recovery.
|
||||
After a trusted contact initiates a recover, you, as the account owner, would
|
||||
get 30 days to block the recovery. To do this, you must go to Settings ->
|
||||
Account -> Legacy, where you will see a message that recovery of the account has
|
||||
been initiated. Tapping on that will allow you to block the recovery.
|
||||
|
||||
## Removing a trusted contact
|
||||
|
||||
You can remove a trusted contact by going to Settings -> Account -> Legacy, tapping on the trusted contact you want to remove, and choosing "Remove" in the popup.
|
||||
You can remove a trusted contact by going to Settings -> Account -> Legacy,
|
||||
tapping on the trusted contact you want to remove, and choosing "Remove" in the
|
||||
popup.
|
||||
|
||||
@@ -30,14 +30,14 @@ device.
|
||||
|
||||
## Tips
|
||||
|
||||
- The app will automatically cluster photos falling within a radius under a
|
||||
specified location.
|
||||
- The app will automatically cluster photos falling within a radius under a
|
||||
specified location.
|
||||
|
||||
- Location Tags provide a seamless way to filter photos without compromising
|
||||
your privacy.
|
||||
- Location Tags provide a seamless way to filter photos without compromising
|
||||
your privacy.
|
||||
|
||||
- Location tags are stored end-to-end encrypted, ensuring the security of your
|
||||
data.
|
||||
- Location tags are stored end-to-end encrypted, ensuring the security of your
|
||||
data.
|
||||
|
||||
- Enjoy a more organized photo library by tagging important places like home,
|
||||
office, and vacation spots.
|
||||
- Enjoy a more organized photo library by tagging important places like home,
|
||||
office, and vacation spots.
|
||||
|
||||
@@ -10,15 +10,15 @@ description:
|
||||
Ente supports on-device machine learning. This allows you to use the latest
|
||||
advances in AI in a privacy preserving manner.
|
||||
|
||||
- You can search for your photos by the **Faces** of the people in them. Ente
|
||||
will show you all the faces in a photo, and will also try to group similar
|
||||
faces together to create clusters of people so that you can give them names,
|
||||
and quickly find all photos with a given person in them.
|
||||
- You can search for your photos by the **Faces** of the people in them. Ente
|
||||
will show you all the faces in a photo, and will also try to group similar
|
||||
faces together to create clusters of people so that you can give them names,
|
||||
and quickly find all photos with a given person in them.
|
||||
|
||||
- You can search for your photos by typing natural language descriptions of
|
||||
them. For example, you can search for "night", "by the seaside", or "the red
|
||||
motorcycle next to a fountain". Within the app, this ability is referred to
|
||||
as **Magic search**.
|
||||
- You can search for your photos by typing natural language descriptions of
|
||||
them. For example, you can search for "night", "by the seaside", or "the red
|
||||
motorcycle next to a fountain". Within the app, this ability is referred to as
|
||||
**Magic search**.
|
||||
|
||||
You can enable face recognition and magic search in the app's preferences on
|
||||
either the mobile app or the desktop app.
|
||||
|
||||
@@ -9,31 +9,30 @@ _View and explore your photos on the map_
|
||||
|
||||
## How can I view photos on the map on mobile?
|
||||
|
||||
- Find the search icon located at the bottom right corner of your screen.
|
||||
- Tap on the globe icon (Your map) withing the location
|
||||
- Enter the map view and start exploring your photos from around the world.
|
||||
- Find the search icon located at the bottom right corner of your screen.
|
||||
- Tap on the globe icon (Your map) withing the location
|
||||
- Enter the map view and start exploring your photos from around the world.
|
||||
|
||||
## How to enable map on your mobile app?
|
||||
|
||||
- Tap the three horizontal lines located at the top left corner of your home
|
||||
screen or swipe left on the home screen.
|
||||
- Select _General_ settings.
|
||||
- Enter the _Advanced_ settings.
|
||||
- Use the toggle switch to turn the map feature on or off.
|
||||
- Tap the three horizontal lines located at the top left corner of your home
|
||||
screen or swipe left on the home screen.
|
||||
- Select _General_ settings.
|
||||
- Enter the _Advanced_ settings.
|
||||
- Use the toggle switch to turn the map feature on or off.
|
||||
|
||||
## How to view Album photos on the map?
|
||||
|
||||
- Open the album containing the photos you want to view
|
||||
- Tap on the three horizontal lines located in the top right corner of the
|
||||
screen.
|
||||
- Select _Map_ from the options.
|
||||
- View and explore your photos on the map.
|
||||
- Open the album containing the photos you want to view
|
||||
- Tap on the three horizontal lines located in the top right corner of the
|
||||
screen.
|
||||
- Select _Map_ from the options.
|
||||
- View and explore your photos on the map.
|
||||
|
||||
## How to enable map on desktop?
|
||||
|
||||
- Click on the three horizontal lines located in the top left corner of the
|
||||
app.
|
||||
- Navigate to _Preferences_ from the menu.
|
||||
- Select _Advanced_ in the preferences menu.
|
||||
- Click on _Map_ to access map settings.
|
||||
- Toggle the map settings on and off based on your preferences.
|
||||
- Click on the three horizontal lines located in the top left corner of the app.
|
||||
- Navigate to _Preferences_ from the menu.
|
||||
- Select _Advanced_ in the preferences menu.
|
||||
- Click on _Map_ to access map settings.
|
||||
- Toggle the map settings on and off based on your preferences.
|
||||
|
||||
@@ -14,11 +14,11 @@ a second factor to secure your Ente account.**
|
||||
> Passkeys are the colloquial term for a WebAuthn (Web Authentication)
|
||||
> credentials.
|
||||
>
|
||||
> - More details about why and how are in the Passkeys announcement
|
||||
> [blog post](https://ente.io/blog/introducing-passkeys-on-ente/).
|
||||
> - And to know more technical details about how our passkey verification
|
||||
> works, you can see this
|
||||
> [technical note in our source code](https://github.com/ente-io/ente/blob/main/web/docs/webauthn-passkeys.md).
|
||||
> - More details about why and how are in the Passkeys announcement
|
||||
> [blog post](https://ente.io/blog/introducing-passkeys-on-ente/).
|
||||
> - And to know more technical details about how our passkey verification works,
|
||||
> you can see this
|
||||
> [technical note in our source code](https://github.com/ente-io/ente/blob/main/web/docs/webauthn-passkeys.md).
|
||||
|
||||
## Passkeys and TOTP
|
||||
|
||||
|
||||
@@ -20,8 +20,8 @@ or event. Everything they add also remains end-to-end encrypted.
|
||||
|
||||
In addition to this, links support the following features:
|
||||
|
||||
- Link expiry (so the links go poof after a duration you define)
|
||||
- Device limits (in case you don't want someone to forwarding your link)
|
||||
- Password lock (to add an additional level of protection to your photos)
|
||||
- Prevent downloads (while we can't prevent screenshots, we can disable the
|
||||
option to download your original photos)
|
||||
- Link expiry (so the links go poof after a duration you define)
|
||||
- Device limits (in case you don't want someone to forwarding your link)
|
||||
- Password lock (to add an additional level of protection to your photos)
|
||||
- Prevent downloads (while we can't prevent screenshots, we can disable the
|
||||
option to download your original photos)
|
||||
|
||||
@@ -11,12 +11,12 @@ that you can then share. You don't need to create an album first.
|
||||
> Behind the scene, Ente creates a special album and put all the selected files
|
||||
> in that special album.
|
||||
|
||||
- You can view all quick links created by you in the sharing tab, under Quick
|
||||
links section.
|
||||
- You can view all quick links created by you in the sharing tab, under Quick
|
||||
links section.
|
||||
|
||||
- Quick links can be converted to regular album.
|
||||
- Quick links can be converted to regular album.
|
||||
|
||||
- Removing a link will not delete the photos that are present in that link.
|
||||
- Removing a link will not delete the photos that are present in that link.
|
||||
|
||||
- Similar to a [public-link](./public-link), you can set link expiry,
|
||||
passwords or device limits.
|
||||
- Similar to a [public-link](./public-link), you can set link expiry, passwords
|
||||
or device limits.
|
||||
|
||||
@@ -11,14 +11,14 @@ This allows you to share your photos and videos with only the people you want,
|
||||
without them being visible to anybody else. The files remain encrypted at all
|
||||
times, and only the people you have shared with get the decryption keys.
|
||||
|
||||
- If the person you want to share with is already on Ente, you can share an
|
||||
album with them by entering their email address.
|
||||
- If the person you want to share with is already on Ente, you can share an
|
||||
album with them by entering their email address.
|
||||
|
||||
- If they are not already on Ente, you can send them an invite and then share
|
||||
with them after they've signed up.
|
||||
- If they are not already on Ente, you can send them an invite and then share
|
||||
with them after they've signed up.
|
||||
|
||||
- Alternatively, you can create public links to share albums with people who
|
||||
are not on Ente.
|
||||
- Alternatively, you can create public links to share albums with people who are
|
||||
not on Ente.
|
||||
|
||||
With public links, the files are still end-to-end encrypted, so the sharing is
|
||||
still secure. Note that the decryption keys are part of the public link so keep
|
||||
@@ -82,14 +82,14 @@ sounds useful to you, please participate in
|
||||
More details, including technical aspect about how the sharing features were
|
||||
implemented, are in various blog posts announcing these features.
|
||||
|
||||
- [Collaborative albums](https://ente.io/blog/collaborative-albums)
|
||||
- [Collaborative albums](https://ente.io/blog/collaborative-albums)
|
||||
|
||||
- [Collect photos from people not on ente](https://ente.io/blog/collect-photos)
|
||||
- [Collect photos from people not on ente](https://ente.io/blog/collect-photos)
|
||||
|
||||
- [Shareable links for albums](https://ente.io/blog/shareable-links),
|
||||
[and their underlying technical implementation](https://ente.io/blog/building-shareable-links).
|
||||
Since then, we have also added the ability to password protect public links,
|
||||
and configure a duration after which the link will automatically expire.
|
||||
- [Shareable links for albums](https://ente.io/blog/shareable-links),
|
||||
[and their underlying technical implementation](https://ente.io/blog/building-shareable-links).
|
||||
Since then, we have also added the ability to password protect public links,
|
||||
and configure a duration after which the link will automatically expire.
|
||||
|
||||
We are now working on the other requested features around sharing, including
|
||||
comments and reactions.
|
||||
|
||||
@@ -8,12 +8,12 @@ description: Uncategorized items in Ente Photos
|
||||
_Uncategorized_ is a special album type where photos are automatically added
|
||||
under the following circumstances:
|
||||
|
||||
- When you remove a photo from the last album, it is relocated to
|
||||
_Uncategorized_ section.
|
||||
- When you remove a photo from the last album, it is relocated to
|
||||
_Uncategorized_ section.
|
||||
|
||||
- During album deletion, if you choose to keep photos but delete the album,
|
||||
all photos exclusive to the current album are moved to the _Uncategorized_
|
||||
section.
|
||||
- During album deletion, if you choose to keep photos but delete the album, all
|
||||
photos exclusive to the current album are moved to the _Uncategorized_
|
||||
section.
|
||||
|
||||
Note: This does not include photos uploaded by others.
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ data reflects the latest album states with new files, moves, and deletions.
|
||||
If you run into any issues during your data export, please reach out to
|
||||
[support@ente.io](mailto:support@ente.io) and we will be happy to help you!
|
||||
|
||||
Note that we also provide a [CLI
|
||||
tool](https://github.com/ente-io/ente/tree/main/cli#export) to export your data.
|
||||
You can find more information about the export in the [export
|
||||
FAQ](/photos/faq/export).
|
||||
Note that we also provide a
|
||||
[CLI tool](https://github.com/ente-io/ente/tree/main/cli#export) to export your
|
||||
data. You can find more information about the export in the
|
||||
[export FAQ](/photos/faq/export).
|
||||
|
||||
@@ -72,6 +72,7 @@ If you run into any issues during this migration, please reach out to
|
||||
> [!TIP]
|
||||
>
|
||||
> In case you wish to use face recognition and other advanced search features
|
||||
> provided by Ente, we recommend that you enable [machine
|
||||
> learning](/photos/features/machine-learning) before importing your photos so
|
||||
> that the Ente app can directly index files as they are getting uploaded.
|
||||
> provided by Ente, we recommend that you enable
|
||||
> [machine learning](/photos/features/machine-learning) before importing your
|
||||
> photos so that the Ente app can directly index files as they are getting
|
||||
> uploaded.
|
||||
|
||||
@@ -7,8 +7,8 @@ description:
|
||||
|
||||
# Migrating to/from Ente Photos
|
||||
|
||||
- [Import from Google Photos](from-google-photos/)
|
||||
- [Import from Apple Photos](from-apple-photos/)
|
||||
- [Import from Amazon Photos](from-amazon-photos)
|
||||
- [Import from local hard disk](from-local-hard-disk)
|
||||
- [Export out of Ente Photos](export/)
|
||||
- [Import from Google Photos](from-google-photos/)
|
||||
- [Import from Apple Photos](from-apple-photos/)
|
||||
- [Import from Amazon Photos](from-amazon-photos)
|
||||
- [Import from local hard disk](from-local-hard-disk)
|
||||
- [Export out of Ente Photos](export/)
|
||||
|
||||
@@ -9,8 +9,8 @@ The latest version of the Ente Photos desktop app can be downloaded from
|
||||
[ente.io/download](https://ente.io/download). If you're having trouble, please
|
||||
see if any of the following cases apply.
|
||||
|
||||
- [Windows](#windows)
|
||||
- [Linux](#linux)
|
||||
- [Windows](#windows)
|
||||
- [Linux](#linux)
|
||||
|
||||
## Windows
|
||||
|
||||
@@ -36,9 +36,9 @@ https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist?view=ms
|
||||
AppImages are not fully standalone, and they require additional steps to enable
|
||||
full "desktop integration":
|
||||
|
||||
- Showing the app icon,
|
||||
- Surfacing the app in the list of installed apps,
|
||||
- Handling redirection after passkey verification.
|
||||
- Showing the app icon,
|
||||
- Surfacing the app in the list of installed apps,
|
||||
- Handling redirection after passkey verification.
|
||||
|
||||
All the ways of enabling AppImage desktop integration are mentioned in
|
||||
[AppImage documentation](https://docs.appimage.org/user-guide/run-appimages.html#integrating-appimages-into-the-desktop).
|
||||
@@ -62,11 +62,11 @@ It is possible that the exact path might be different on your machine. Briefly,
|
||||
what we need to do is create `libz.so` as an alias for `libz.so.1`. For more
|
||||
details, see the following upstream issues:
|
||||
|
||||
- libz.so cannot open shared object file on ARM64 -
|
||||
[AppImage/AppImageKit/issues/1092](https://github.com/AppImage/AppImageKit/issues/1092)
|
||||
- libz.so cannot open shared object file on ARM64 -
|
||||
[AppImage/AppImageKit/issues/1092](https://github.com/AppImage/AppImageKit/issues/1092)
|
||||
|
||||
- libz.so: cannot open shared object file with Ubuntu arm64 -
|
||||
[electron-userland/electron-builder/issues/7835](https://github.com/electron-userland/electron-builder/issues/7835)
|
||||
- libz.so: cannot open shared object file with Ubuntu arm64 -
|
||||
[electron-userland/electron-builder/issues/7835](https://github.com/electron-userland/electron-builder/issues/7835)
|
||||
|
||||
### AppImage says it requires FUSE
|
||||
|
||||
|
||||
@@ -15,28 +15,28 @@ the logs just make the process a bit faster and easier.
|
||||
|
||||
## Mobile
|
||||
|
||||
- Open settings (tap on the three horizontal lines button).
|
||||
- Tap on _Support_ from the settings.
|
||||
- Select for the option to _Report a Bug_.
|
||||
- Tap on _Report a bug_.
|
||||
- Open settings (tap on the three horizontal lines button).
|
||||
- Tap on _Support_ from the settings.
|
||||
- Select for the option to _Report a Bug_.
|
||||
- Tap on _Report a bug_.
|
||||
|
||||
## Desktop
|
||||
|
||||
- Click on _Help_ menu at the top of your screen, and select the _View logs_
|
||||
option.
|
||||
- Open settings (click on the three horizontal lines button located at the top
|
||||
left corner of the screen).
|
||||
- Click on _Support_. This will open your email client where you can attach
|
||||
the logs in the email and describe the issue.
|
||||
- Click on _Help_ menu at the top of your screen, and select the _View logs_
|
||||
option.
|
||||
- Open settings (click on the three horizontal lines button located at the top
|
||||
left corner of the screen).
|
||||
- Click on _Support_. This will open your email client where you can attach the
|
||||
logs in the email and describe the issue.
|
||||
|
||||
## Web
|
||||
|
||||
- Open settings (click on the three horizontal lines button located at the top
|
||||
left corner of the screen).
|
||||
- Click on _Debug Logs_ towards the bottom of settings.
|
||||
- Click on _Download logs_
|
||||
- Click on _Support_. This will open your email client where you can attach
|
||||
the logs in the email and describe the issue.
|
||||
- Open settings (click on the three horizontal lines button located at the top
|
||||
left corner of the screen).
|
||||
- Click on _Debug Logs_ towards the bottom of settings.
|
||||
- Click on _Download logs_
|
||||
- Click on _Support_. This will open your email client where you can attach the
|
||||
logs in the email and describe the issue.
|
||||
|
||||
## Send email manually
|
||||
|
||||
|
||||
@@ -8,9 +8,9 @@ description: Getting the OTP for a self hosted Ente
|
||||
The self-hosted Ente by default does not send out emails, so you can pick the
|
||||
verification code by:
|
||||
|
||||
- Getting it from the server logs, or
|
||||
- Getting it from the server logs, or
|
||||
|
||||
- Reading it from the DB (otts table)
|
||||
- Reading it from the DB (otts table)
|
||||
|
||||
You can also set pre-defined hardcoded OTTs for certain users when running
|
||||
locally by creating a `museum.yaml` and adding the `internal.hardcoded-ott`
|
||||
|
||||
@@ -50,16 +50,15 @@ explicit whitelist of admins.
|
||||
To whitelist the user IDs that can perform admin actions on the server, use the
|
||||
following steps:
|
||||
|
||||
- Create a `museum.yaml` in the directory where you're starting museum from.
|
||||
For example, if you're running using `docker compose up`, then this file
|
||||
should be in the same directory as `compose.yaml` (generally,
|
||||
`server/museum.yaml`).
|
||||
- Create a `museum.yaml` in the directory where you're starting museum from. For
|
||||
example, if you're running using `docker compose up`, then this file should be
|
||||
in the same directory as `compose.yaml` (generally, `server/museum.yaml`).
|
||||
|
||||
> Docker might've created an empty `museum.yaml` _directory_ on your machine
|
||||
> previously. If so, delete that empty directory and create a new file named
|
||||
> `museum.yaml`.
|
||||
|
||||
- In this `museum.yaml` we can add overrides over the default configuration.
|
||||
- In this `museum.yaml` we can add overrides over the default configuration.
|
||||
|
||||
For whitelisting the admin userIDs we need to define an `internal.admins`. See
|
||||
the "internal" section in
|
||||
|
||||
@@ -7,6 +7,14 @@ description:
|
||||
|
||||
# Hosting server and web app using external S3
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> This is a community contributed guide, and some of these steps might be out of
|
||||
> sync with the upstream documentation. If something is not working correctly,
|
||||
> please also see the latest
|
||||
> [READMEs](https://github.com/ente-io/ente/blob/main/server/README.md) in the
|
||||
> repository and/or other guides in [self-hosting](/self-hosting/).
|
||||
|
||||
This guide is for self hosting the server and the web application of Ente Photos
|
||||
using docker compose and an external S3 bucket. So we assume that you already
|
||||
have the keys and secrets for the S3 bucket. The plan is as follows:
|
||||
@@ -17,14 +25,6 @@ have the keys and secrets for the S3 bucket. The plan is as follows:
|
||||
4. Create an account and increase storage quota
|
||||
5. Fix potential CORS issue with your bucket
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> This is a community contributed guide, and some of these steps might be out of
|
||||
> sync with the upstream documentation. If something is not working correctly,
|
||||
> please also see the latest
|
||||
> [READMEs](https://github.com/ente-io/ente/blob/main/server/README.md) in the
|
||||
> repository and/or other guides in [self-hosting](/self-hosting/).
|
||||
|
||||
## 1. Create a `compose.yaml` file
|
||||
|
||||
After cloning the main repository with
|
||||
@@ -40,7 +40,6 @@ Create a `compose.yaml` file at the root of the project with the following
|
||||
content (there is nothing to change here):
|
||||
|
||||
```yaml
|
||||
version: "3"
|
||||
services:
|
||||
museum:
|
||||
build:
|
||||
@@ -168,10 +167,10 @@ RUN chmod +x /docker-entrypoint.d/replace_ente_endpoints.sh
|
||||
This runs nginx inside to handle both the web & album URLs so we don't have to
|
||||
make two web images with different port.
|
||||
|
||||
- `DOCKER_RUNTIME_REPLACE_ENDPOINT` this is your public museum API URL.
|
||||
- `DOCKER_RUNTIME_REPLACE_ALBUMS_ENDPOINT` this is the shared albums URL (for
|
||||
more details about configuring shared albums, see
|
||||
[faq/sharing](/self-hosting/faq/sharing)).
|
||||
- `DOCKER_RUNTIME_REPLACE_ENDPOINT` this is your public museum API URL.
|
||||
- `DOCKER_RUNTIME_REPLACE_ALBUMS_ENDPOINT` this is the shared albums URL (for
|
||||
more details about configuring shared albums, see
|
||||
[faq/sharing](/self-hosting/faq/sharing)).
|
||||
|
||||
Note how above we had updated the `compose.yaml` file for the server with
|
||||
|
||||
@@ -219,11 +218,11 @@ s3:
|
||||
use_path_style_urls: true
|
||||
# The key must be named like so
|
||||
b2-eu-cen:
|
||||
key: $YOUR_S3_KEY
|
||||
secret: $YOUR_S3_SECRET
|
||||
key: $YOUR_S3_KEY
|
||||
secret: $YOUR_S3_SECRET
|
||||
endpoint: $YOUR_S3_ENDPOINT
|
||||
region: $YOUR_S3_REGION
|
||||
bucket: $YOUR_S3_BUCKET_NAME
|
||||
region: $YOUR_S3_REGION
|
||||
bucket: $YOUR_S3_BUCKET_NAME
|
||||
# The same value as the one specified in ALBUMS_ENDPOINT
|
||||
apps:
|
||||
public-albums: http://localhost:8082
|
||||
@@ -236,9 +235,12 @@ background).
|
||||
|
||||
## 4. Create an account and increase storage quota
|
||||
|
||||
Open `http://localhost:8081` (or the url of your server) in your browser and
|
||||
create an account. Choose 123456 as the value for the one-time token if your
|
||||
email has the correct domain as defined in the `.credentials.env` file.
|
||||
Open `http://localhost:8080` or whatever Endpoint you mentioned for the web app
|
||||
and create an account. If your SMTP related configurations are all set and
|
||||
right, you will receive an email with your OTT in it. There are two work arounds
|
||||
to retrieve the OTP, checkout
|
||||
[this document](https://help.ente.io/self-hosting/faq/otp) for getting your
|
||||
OTT's..
|
||||
|
||||
If you successfully log in, select any plan and increase the storage quota with
|
||||
the following command:
|
||||
@@ -251,6 +253,8 @@ After few reloads, you should see 1 To of quota.
|
||||
|
||||
## 5. Fix potential CORS issue with your bucket
|
||||
|
||||
### For AWS S3
|
||||
|
||||
If you cannot upload a photo due to a CORS issue, you need to fix the CORS
|
||||
configuration of your bucket.
|
||||
|
||||
@@ -272,19 +276,43 @@ Create a `cors.json` file with the following content:
|
||||
|
||||
You may want to change the `AllowedOrigins` to a more restrictive value.
|
||||
|
||||
Then run the following command with the aws command to update the CORS
|
||||
configuration of your bucket:
|
||||
If you are using AWS for S3, you can execute the below command to get rid of
|
||||
CORS. Make sure to enter the right path for the `cors.json` file.
|
||||
|
||||
```bash
|
||||
aws s3api put-bucket-cors --bucket YOUR_S3_BUCKET --cors-configuration file://cors.json
|
||||
aws s3api put-bucket-cors --bucket YOUR_S3_BUCKET --cors-configuration /path/to/cors.json
|
||||
```
|
||||
|
||||
Upload should now work.
|
||||
### For Self-hosted Minio Instance
|
||||
|
||||
> Important: MinIO does not take JSON CORS file as the input, instead you will
|
||||
> have to build a CORS.xml file or just convert the above `cors.json` to XML.
|
||||
|
||||
A minor requirement here is the tool `mc` for managing buckets via command line
|
||||
interface. Checkout the `mc set alias` document to configure alias for your
|
||||
instance and bucket. After this you will be prompted for your AccessKey and
|
||||
Secret, which is your username and password, go ahead and enter that.
|
||||
|
||||
```sh
|
||||
mc cors set <your-minio>/<your-bucket-name /path/to/cors.xml
|
||||
```
|
||||
|
||||
or, if you just want to just set the `AllowedOrigins` Header, you can use the
|
||||
following command to do so.
|
||||
|
||||
```sh
|
||||
mc admin config set <your-minio>/<your-bucket-name> set "cors_allowed_origin=*"
|
||||
```
|
||||
|
||||
You can create also `.csv` file and dump the list of origins you would like to
|
||||
allow and replace the `*` with `path` to the CSV file.
|
||||
|
||||
Now, uploads should be working fine.
|
||||
|
||||
## Related
|
||||
|
||||
Some other users have also shared their setups.
|
||||
|
||||
- [Using Traefik](https://github.com/ente-io/ente/pull/3663)
|
||||
- [Using Traefik](https://github.com/ente-io/ente/pull/3663)
|
||||
|
||||
- [Building custom images from source (Linux)](https://github.com/ente-io/ente/discussions/3778)
|
||||
- [Building custom images from source (Linux)](https://github.com/ente-io/ente/discussions/3778)
|
||||
|
||||
@@ -10,14 +10,14 @@ walkthroughs, tutorials and other FAQ pages in this directory.
|
||||
|
||||
See the sidebar for existing guides. In particular:
|
||||
|
||||
- If you're just looking to get started, see
|
||||
[configure custom server](custom-server/).
|
||||
- If you're just looking to get started, see
|
||||
[configure custom server](custom-server/).
|
||||
|
||||
- For various admin related tasks, e.g. increasing the storage quota on your
|
||||
self hosted instance, see [administering your custom server](admin).
|
||||
- For various admin related tasks, e.g. increasing the storage quota on your
|
||||
self hosted instance, see [administering your custom server](admin).
|
||||
|
||||
- For configuring your S3 buckets to get the object storage to work from your
|
||||
mobile device or for fixing an upload errors, see
|
||||
[configuring S3](configuring-s3). There is also a longer
|
||||
[community contributed guide](external-s3) for a more self hosted setup of
|
||||
both the server and web app using external S3 buckets for object storage.
|
||||
- For configuring your S3 buckets to get the object storage to work from your
|
||||
mobile device or for fixing an upload errors, see
|
||||
[configuring S3](configuring-s3). There is also a longer
|
||||
[community contributed guide](external-s3) for a more self hosted setup of
|
||||
both the server and web app using external S3 buckets for object storage.
|
||||
|
||||
@@ -5,33 +5,35 @@ description: Guide to configuring Ente CLI for Self Hosted Instance
|
||||
|
||||
## Self Hosting
|
||||
|
||||
If you are self-hosting the server, you can still configure CLI to export
|
||||
data & perform basic admin actions.
|
||||
If you are self-hosting the server, you can still configure CLI to export data &
|
||||
perform basic admin actions.
|
||||
|
||||
To do this, first configure the CLI to point to your server. Define a config.yaml
|
||||
and put it either in the same directory as CLI binary
|
||||
or path defined in env variable `ENTE_CLI_CONFIG_DIR`
|
||||
To do this, first configure the CLI to point to your server. Define a
|
||||
config.yaml and put it either in the same directory as CLI binary or path
|
||||
defined in env variable `ENTE_CLI_CONFIG_DIR`
|
||||
|
||||
```yaml
|
||||
endpoint:
|
||||
api: "http://localhost:8080"
|
||||
api: "http://localhost:8080"
|
||||
```
|
||||
|
||||
You should be able to [add an account](https://github.com/ente-io/ente/blob/main/cli/docs/generated/ente_account_add.md),
|
||||
and subsequently increase the
|
||||
[storage and account validity](https://github.com/ente-io/ente/blob/main/cli/docs/generated/ente_admin_update-subscription.md) using the CLI.
|
||||
You should be able to
|
||||
[add an account](https://github.com/ente-io/ente/blob/main/cli/docs/generated/ente_account_add.md),
|
||||
and subsequently increase the
|
||||
[storage and account validity](https://github.com/ente-io/ente/blob/main/cli/docs/generated/ente_admin_update-subscription.md)
|
||||
using the CLI.
|
||||
|
||||
|
||||
For the admin actions, you first need to whitelist admin users. You can create
|
||||
`server/museum.yaml`, and whitelist add the admin userID `internal.admins`.
|
||||
See [local.yaml](https://github.com/ente-io/ente/blob/main/server/configurations/local.yaml#L211C1-L232C1)
|
||||
For the admin actions, you first need to whitelist admin users. You can create
|
||||
`server/museum.yaml`, and whitelist add the admin userID `internal.admins`. See
|
||||
[local.yaml](https://github.com/ente-io/ente/blob/main/server/configurations/local.yaml#L211C1-L232C1)
|
||||
in the server source code for details about how to define this.
|
||||
|
||||
You can use [account list](https://github.com/ente-io/ente/blob/main/cli/docs/generated/ente_account_list.md)
|
||||
You can use
|
||||
[account list](https://github.com/ente-io/ente/blob/main/cli/docs/generated/ente_account_list.md)
|
||||
command to find the user id of any account.
|
||||
|
||||
```yaml
|
||||
internal:
|
||||
admins:
|
||||
# - 1580559962386440
|
||||
admins:
|
||||
# - 1580559962386440
|
||||
```
|
||||
|
||||
@@ -7,72 +7,78 @@ description: Installing and setting up Ente standalone without docker.
|
||||
|
||||
## Running Museum (Ente's server) without Docker
|
||||
|
||||
First, start by installing all the dependencies to get your machine ready for development.
|
||||
First, start by installing all the dependencies to get your machine ready for
|
||||
development.
|
||||
|
||||
```sh
|
||||
```sh
|
||||
# For MacOS
|
||||
brew tap homebrew/core
|
||||
brew update
|
||||
brew install go
|
||||
brew tap homebrew/core
|
||||
brew update
|
||||
brew install go
|
||||
|
||||
# For Ubuntu based distros
|
||||
sudo apt update && sudo apt upgrade
|
||||
sudo apt update && sudo apt upgrade
|
||||
sudo apt install golang-go
|
||||
```
|
||||
|
||||
Alternatively, you can also download the latest binaries from ['All Release'](https://go.dev/dl/) page from the official website.
|
||||
Alternatively, you can also download the latest binaries from
|
||||
['All Release'](https://go.dev/dl/) page from the official website.
|
||||
|
||||
```sh
|
||||
brew install postgres@15
|
||||
# Link the postgres keg
|
||||
brew link postgresql@15
|
||||
```sh
|
||||
brew install postgres@15
|
||||
# Link the postgres keg
|
||||
brew link postgresql@15
|
||||
|
||||
brew install libsodium
|
||||
brew install libsodium
|
||||
|
||||
# For Ubuntu based distros
|
||||
# For Ubuntu based distros
|
||||
sudo apt install postgresql
|
||||
sudo apt install libsodium23 libsodium-dev
|
||||
sudo apt install libsodium23 libsodium-dev
|
||||
```
|
||||
|
||||
The package `libsodium23` might be installed already in some cases.
|
||||
|
||||
Installing pkg-config
|
||||
|
||||
```sh
|
||||
brew install pkg-config
|
||||
```sh
|
||||
brew install pkg-config
|
||||
|
||||
# For Ubuntu based distros
|
||||
# For Ubuntu based distros
|
||||
sudo apt install pkg-config
|
||||
```
|
||||
|
||||
## Starting Postgres
|
||||
## Starting Postgres
|
||||
|
||||
### With pg_ctl
|
||||
### With pg_ctl
|
||||
|
||||
```sh
|
||||
pg_ctl -D /usr/local/var/postgres -l logfile start
|
||||
```sh
|
||||
pg_ctl -D /usr/local/var/postgres -l logfile start
|
||||
```
|
||||
|
||||
Dependeing on the Operating System type the path for postgres binary or configuration file might be different, please check if the command keeps failing for you.
|
||||
Dependeing on the Operating System type the path for postgres binary or
|
||||
configuration file might be different, please check if the command keeps failing
|
||||
for you.
|
||||
|
||||
Ideally, if you are on a Linux system with systemd as the init. You can also start postgres as a systemd service. After Installation execute the following commands:
|
||||
Ideally, if you are on a Linux system with systemd as the init. You can also
|
||||
start postgres as a systemd service. After Installation execute the following
|
||||
commands:
|
||||
|
||||
```sh
|
||||
sudo systemctl enable postgresql
|
||||
```sh
|
||||
sudo systemctl enable postgresql
|
||||
sudo systemctl daemon-reload && sudo systemctl start postgresql
|
||||
```
|
||||
|
||||
### Create user
|
||||
### Create user
|
||||
|
||||
```sh
|
||||
```sh
|
||||
createuser -s postgres
|
||||
```
|
||||
|
||||
## Start Museum
|
||||
## Start Museum
|
||||
|
||||
Start by cloning ente to your system.
|
||||
Start by cloning ente to your system.
|
||||
|
||||
```sh
|
||||
```sh
|
||||
git clone https://github.com/ente-io/ente
|
||||
```
|
||||
|
||||
@@ -82,23 +88,29 @@ cd ente/server
|
||||
go run cmd/museum/main.go
|
||||
```
|
||||
|
||||
You can also add the export line to your shell's RC file, to avoid exporting the environment variable every time.
|
||||
You can also add the export line to your shell's RC file, to avoid exporting the
|
||||
environment variable every time.
|
||||
|
||||
For live reloads, install [air](https://github.com/air-verse/air#installation). Then you can just call air after declaring the required environment variables. For example,
|
||||
For live reloads, install [air](https://github.com/air-verse/air#installation).
|
||||
Then you can just call air after declaring the required environment variables.
|
||||
For example,
|
||||
|
||||
```sh
|
||||
ENTE_DB_USER=postgres
|
||||
air
|
||||
```
|
||||
|
||||
## Museum as a background service
|
||||
## Museum as a background service
|
||||
|
||||
Please check the below links if you want to run Museum as a service, both of them are battle tested.
|
||||
Please check the below links if you want to run Museum as a service, both of
|
||||
them are battle tested.
|
||||
|
||||
1. [How to run museum as a systemd service](https://gist.github.com/mngshm/a0edb097c91d1dc45aeed755af310323)
|
||||
2. [Museum.service](https://github.com/ente-io/ente/blob/23e678889189157ecc389c258267685934b83631/server/scripts/deploy/museum.service#L4)
|
||||
|
||||
Once you are done with setting and running Museum, all you are left to do is run the web app and reverse_proxy it with a webserver. You can check the following resources for Deploying your web app.
|
||||
Once you are done with setting and running Museum, all you are left to do is run
|
||||
the web app and reverse_proxy it with a webserver. You can check the following
|
||||
resources for Deploying your web app.
|
||||
|
||||
1. [Hosting the Web App](https://help.ente.io/self-hosting/guides/web-app).
|
||||
2. [Running Ente Web app as a systemd Service](https://gist.github.com/mngshm/72e32bd483c2129621ed0d74412492fd)
|
||||
|
||||
@@ -17,20 +17,21 @@ yarn install
|
||||
NEXT_PUBLIC_ENTE_ENDPOINT=http://localhost:8080 yarn dev:photos
|
||||
```
|
||||
|
||||
This is fine for trying the web app and verifying that your self-hosted server is
|
||||
working as expected etc. But if you would like to use the web app for a longer term,
|
||||
then it is recommended to follow the Docker approach.
|
||||
This is fine for trying the web app and verifying that your self-hosted server
|
||||
is working as expected etc. But if you would like to use the web app for a
|
||||
longer term, then it is recommended to follow the Docker approach.
|
||||
|
||||
## With Docker/Docker Compose (Recommended)
|
||||
|
||||
> [!IMPORTANT]
|
||||
>
|
||||
> This docker image is still in testing stage and it might show up with some
|
||||
> variables in different scenarios. But this image has been tested on a production
|
||||
> ente site.
|
||||
>
|
||||
> unknown variables in different scenarios. But this image has been tested on a
|
||||
> production Ente site.
|
||||
>
|
||||
> Recurring changes might be made by the team or from community if more
|
||||
> improvements can be made.
|
||||
> improvements can be made so that we are able to build a full-fledged docker
|
||||
> image.
|
||||
|
||||
```dockerfile
|
||||
FROM node:20-bookworm-slim as builder
|
||||
@@ -43,9 +44,13 @@ COPY apps/ .
|
||||
# Will help default to yarn versoin 1.22.22
|
||||
RUN corepack enable
|
||||
|
||||
# Endpoint for Ente Server
|
||||
NEXT_PUBLIC_ENTE_ENDPOINT=https://your-ente-endpoint.com
|
||||
NEXT_PUBLIC_ENTE_ALBUMS_ENDPOINT=https://your-albums-endpoint.com
|
||||
|
||||
RUN yarn cache clean
|
||||
RUN yarn install --network-timeout 1000000000
|
||||
RUN yarn build:photos && yarn build:auth && yarn build:accounts && yarn build:cast
|
||||
RUN yarn build:photos && yarn build:accounts && yarn build:auth && yarn build:cast
|
||||
|
||||
FROM node:20-bookworm-slim
|
||||
|
||||
@@ -70,77 +75,89 @@ EXPOSE ${AUTH}
|
||||
ENV CAST=3003
|
||||
EXPOSE ${CAST}
|
||||
|
||||
CMD ["sh", "-c", "serve /app/photos -l tcp://0.0.0.0:${PHOTOS} & serve tcp://0.0.0.0:${ACCOUNTS} -l /app/accounts & server tcp://0.0.0.0:${AUTH} -l /app/auth & server -l tcp://0.0.0.0:${CAST} & serve /app/cast]
|
||||
# The albums app does not have navigable pages on it, but the
|
||||
# port will be exposed in-order to self up the albums endpoint
|
||||
# `apps.public-albums` in museum.yaml configuration file.
|
||||
ENV ALBUMS=3004
|
||||
EXPOSE ${ALBUMS}
|
||||
|
||||
CMD ["sh", "-c", "serve /app/photos -l tcp://0.0.0.0:${PHOTOS} & serve /app/accounts -l tcp://0.0.0.0:${ACCOUNTS} & serve /app/auth -l tcp://0.0.0.0:${AUTH} & serve /app/cast -l tcp://0.0.0.0:${CAST}"]
|
||||
```
|
||||
|
||||
The above is a multi-stage Dockerfile which creates a production ready static output
|
||||
of the 4 apps (Photos, Accounts, Auth and Cast) and serves the static content with
|
||||
Caddy.
|
||||
The above is a multi-stage Dockerfile which creates a production ready static
|
||||
output of the 4 apps (Photos, Accounts, Auth and Cast) and serves the static
|
||||
content with Caddy.
|
||||
|
||||
Looking at 2 different node base-images doing different tasks in the same Dockerfile
|
||||
would not make sense, but the Dockerfile is divided into two just to improve the build
|
||||
efficiency as building this Dockerfile will arguably take more time.
|
||||
Looking at 2 different node base-images doing different tasks in the same
|
||||
Dockerfile would not make sense, but the Dockerfile is divided into two just to
|
||||
improve the build efficiency as building this Dockerfile will arguably take more
|
||||
time.
|
||||
|
||||
Lets build a Docker image from the above Dockerfile. Copy and paste the above Dockerfile
|
||||
contents in the root of your web directory which is inside `ente/web`. Execute the
|
||||
below command to create an image from this Dockerfile.
|
||||
|
||||
You can always edit the Dockerfile and remove the steps for apps which you do not
|
||||
intend to install on your system (like auth or cast) and opt out of it.
|
||||
Lets build a Docker image from the above Dockerfile. Copy and paste the above
|
||||
Dockerfile contents in the root of your web directory which is inside
|
||||
`ente/web`. Execute the below command to create an image from this Dockerfile.
|
||||
|
||||
```sh
|
||||
# Build the image
|
||||
docker build -t <image-name>:<tag> --no-cache --progress plain .
|
||||
docker build -t <image-name>:<tag> --no-cache --progress plain .
|
||||
```
|
||||
|
||||
You can always edit the Dockerfile and remove the steps for apps which you do
|
||||
not intend to install on your system (like auth or cast) and opt out of those.
|
||||
|
||||
Regarding Albums App, please take a note that they are not web pages with
|
||||
navigable pages, if accessed on the web-browser they will simply redirect to
|
||||
ente.web.io.
|
||||
|
||||
## compose.yaml
|
||||
|
||||
Moving ahead, we need to paste the below contents into the compose.yaml inside
|
||||
`ente/server/compose.yaml` under the services section.
|
||||
`ente/server/compose.yaml` under the services section.
|
||||
|
||||
```yaml
|
||||
ente-web:
|
||||
ente-web:
|
||||
image: <image-name> # name of the image you used while building
|
||||
ports:
|
||||
- 3000:3000
|
||||
- 3001:3001
|
||||
- 3002:3002
|
||||
- 3003:3003
|
||||
- 3000:3000
|
||||
- 3001:3001
|
||||
- 3002:3002
|
||||
- 3003:3003
|
||||
- 3004:3004
|
||||
environment:
|
||||
- NODE_ENV=development
|
||||
- NODE_ENV=development
|
||||
restart: always
|
||||
```
|
||||
|
||||
Now, we're good to go. All we are left to do is start the containers.
|
||||
Now, we're good to go. All we are left to do now is start the containers.
|
||||
|
||||
```sh
|
||||
docker compose up -d # --build
|
||||
```sh
|
||||
docker compose up -d # --build
|
||||
|
||||
# Accessing the logs
|
||||
docker compose logs <container-name>
|
||||
```
|
||||
|
||||
Next part is to configure a [web server](#web-server-configuration).
|
||||
|
||||
## Without Docker / Docker compose
|
||||
|
||||
One way to run all the apps together without Docker is by using [PM2](https://pm2.keymetrics.io/)
|
||||
in this setup. The configuration and usage is very simple and just needs one
|
||||
configuration file for it. You can run the apps both in dev server mode as
|
||||
well as static files.
|
||||
One way to run all the apps together without Docker is by using
|
||||
[PM2](https://pm2.keymetrics.io/) in this setup. The configuration and usage is
|
||||
very simple and just needs one configuration file for it. You can run the apps
|
||||
both in dev server mode as well as static files.
|
||||
|
||||
The below configuration will run the apps in dev server mode.
|
||||
|
||||
|
||||
|
||||
### Install PM2
|
||||
|
||||
```sh
|
||||
npm install pm2@latest
|
||||
```sh
|
||||
npm install pm2@latest
|
||||
```
|
||||
|
||||
Copy the below contents to a file called `ecosystem.config.js` inside the `ente/web`
|
||||
directory.
|
||||
Copy the below contents to a file called `ecosystem.config.js` inside the
|
||||
`ente/web` directory.
|
||||
|
||||
```js
|
||||
```js
|
||||
module.exports = {
|
||||
apps: [
|
||||
{
|
||||
@@ -179,26 +196,44 @@ directory.
|
||||
|
||||
```
|
||||
|
||||
Finally, start pm2.
|
||||
Finally, start pm2.
|
||||
|
||||
```sh
|
||||
pm2 start
|
||||
```sh
|
||||
pm2 start
|
||||
|
||||
# for logs
|
||||
pm2 logs all
|
||||
```
|
||||
|
||||
# Web server configuration
|
||||
## Configure App Endpoints
|
||||
|
||||
The last step ahead is configuring reverse_proxy for the ports on which the
|
||||
apps are being served (you will have to make changes, if you have cusotmized the ports).
|
||||
The web server of choice in this guide is [Caddy](https://caddyserver.com) because
|
||||
with caddy you don't have to manually configure/setup SSL ceritifcates as caddy
|
||||
will take care of that.
|
||||
> [!NOTE]
|
||||
> Previously, this was dependent on the env variables `NEXT_ENTE_PUBLIC_ACCOUNTS_ENDPOINT`
|
||||
> and etc. Please check the below documentation to update your setup configurations
|
||||
|
||||
You can configure the web endpoints for the other apps including Accounts, Albums
|
||||
Family and Cast in your `museum.yaml`` configuration file. Checkout
|
||||
[`local.yaml`](https://github.com/ente-io/ente/blob/543411254b2bb55bd00a0e515dcafa12d12d3b35/server/configurations/local.yaml#L76-L89)
|
||||
to configure the endpoints. Make sure to setup up your DNS Records accordingly to the
|
||||
similar URL's you set up in `museum.yaml``
|
||||
|
||||
Next part is to configure the web server.
|
||||
|
||||
# Web server configuration
|
||||
|
||||
The last step ahead is configuring reverse_proxy for the ports on which the apps
|
||||
are being served (you will have to make changes, if you have cusotmized the
|
||||
ports). The web server of choice in this guide is
|
||||
[Caddy](https://caddyserver.com) because with caddy you don't have to manually
|
||||
configure/setup SSL ceritifcates as caddy will take care of that.
|
||||
|
||||
```sh
|
||||
photos.yourdomain.com {
|
||||
reverse_proxy http://localhost:3001
|
||||
# for logging
|
||||
log {
|
||||
level error
|
||||
}
|
||||
}
|
||||
|
||||
auth.yourdomain.com {
|
||||
@@ -207,17 +242,17 @@ auth.yourdomain.com {
|
||||
# and so on ...
|
||||
```
|
||||
|
||||
Next, start the caddy server :).
|
||||
Next, start the caddy server :).
|
||||
|
||||
```sh
|
||||
```sh
|
||||
# If caddy service is not enabled
|
||||
sudo systemctl enable caddy
|
||||
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl start caddy
|
||||
```
|
||||
|
||||
## Contributing
|
||||
## Contributing
|
||||
|
||||
Please start a discussion on the Github Repo if you have any suggestions for the Dockerfile,
|
||||
You can also share your setups on Github Discussions.
|
||||
Please start a discussion on the Github Repo if you have any suggestions for the
|
||||
Dockerfile, You can also share your setups on Github Discussions.
|
||||
|
||||
@@ -16,9 +16,11 @@ the same code we use for our own cloud service.
|
||||
|
||||
## Getting started
|
||||
|
||||
#### Installing Docker
|
||||
#### Installing Docker
|
||||
|
||||
Refer to [How to install Docker from the APT repository](https://docs.docker.com/engine/install/ubuntu/#install-using-the-repository) for detailed instructions.
|
||||
Refer to
|
||||
[How to install Docker from the APT repository](https://docs.docker.com/engine/install/ubuntu/#install-using-the-repository)
|
||||
for detailed instructions.
|
||||
|
||||
#### Start the server
|
||||
|
||||
@@ -33,12 +35,12 @@ docker compose up --build
|
||||
> You can also use a pre-built Docker image from `ghcr.io/ente-io/server`
|
||||
> ([More info](https://github.com/ente-io/ente/blob/main/server/docs/docker.md))
|
||||
|
||||
Install the necessary dependencies for running the web client
|
||||
Install the necessary dependencies for running the web client
|
||||
|
||||
```sh
|
||||
# installing npm and yarn
|
||||
```sh
|
||||
# installing npm and yarn
|
||||
|
||||
sudo apt update
|
||||
sudo apt update
|
||||
sudo apt install nodejs npm
|
||||
sudo npm install -g yarn // to install yarn globally
|
||||
```
|
||||
@@ -66,24 +68,19 @@ apps and configure them to use your
|
||||
|
||||
## Next steps
|
||||
|
||||
- More details about the server are in its
|
||||
[README](https://github.com/ente-io/ente/tree/main/server#readme)
|
||||
- More details about the server are in its
|
||||
[README](https://github.com/ente-io/ente/tree/main/server#readme)
|
||||
|
||||
- More details about running the server (with or without Docker) are in
|
||||
[RUNNING](https://github.com/ente-io/ente/blob/main/server/RUNNING.md)
|
||||
- More details about running the server (with or without Docker) are in
|
||||
[RUNNING](https://github.com/ente-io/ente/blob/main/server/RUNNING.md)
|
||||
|
||||
- If you have questions around self-hosting that are not answered in any of
|
||||
the existing documentation, you can ask in our
|
||||
[GitHub Discussions](https://github.com/ente-io/ente/discussions). **Please
|
||||
remember to search first if the query has been already asked and answered.**
|
||||
- If you have questions around self-hosting that are not answered in any of the
|
||||
existing documentation, you can ask in our
|
||||
[GitHub Discussions](https://github.com/ente-io/ente/discussions). **Please
|
||||
remember to search first if the query has been already asked and answered.**
|
||||
|
||||
## Contributing!
|
||||
|
||||
While we would love to provide a completely seamless self-hosting experience,
|
||||
right now we do not have the engineering bandwidth to answer all queries,
|
||||
document everything exactly etc. We will try (that's why we're writing this!),
|
||||
but we also hope that community members will step up to fill any gaps.
|
||||
|
||||
One particular way in which you can help is by adding new [guides](guides/) on
|
||||
this help site. The documentation is written in Markdown and adding new pages is
|
||||
[easy](https://github.com/ente-io/ente/tree/main/docs#readme). Editing existing
|
||||
|
||||
@@ -1,35 +1,39 @@
|
||||
---
|
||||
title: Ente CLI Secrets
|
||||
description: A quick hotfix for keyring errors while running Ente CLI.
|
||||
title: Ente CLI Secrets
|
||||
description: A quick hotfix for keyring errors while running Ente CLI.
|
||||
---
|
||||
|
||||
# Ente CLI Secrets
|
||||
# Ente CLI Secrets
|
||||
|
||||
Ente CLI makes use of keyring for storing sensitive information
|
||||
like your passwords. And running the cli straight out of the
|
||||
box might give you some errors related to keyrings in some case.
|
||||
Ente CLI makes use of keyring for storing sensitive information like your
|
||||
passwords. And running the cli straight out of the box might give you some
|
||||
errors related to keyrings in some case.
|
||||
|
||||
Follow the below steps to run Ente CLI and also avoid keyrings errors.
|
||||
Follow the below steps to run Ente CLI and also avoid keyrings errors.
|
||||
|
||||
Run:
|
||||
|
||||
```sh
|
||||
```sh
|
||||
# export the secrets path
|
||||
|
||||
export ENTE_CLI_SECRETS_PATH=./<path-to-secrets.txt>
|
||||
|
||||
./ente-cli
|
||||
```
|
||||
You can also add the above line to your shell's rc file, to prevent the need to export manually every time.
|
||||
|
||||
You can also add the above line to your shell's rc file, to prevent the need to
|
||||
export manually every time.
|
||||
|
||||
Then one of the following:
|
||||
|
||||
1. If the file doesn't exist, Ente CLI will create it and fill it with a random 32 character encryption key.
|
||||
2. If you do create the file, please fill it with a cryptographically generated 32 byte string.
|
||||
1. If the file doesn't exist, Ente CLI will create it and fill it with a random
|
||||
32 character encryption key.
|
||||
2. If you do create the file, please fill it with a cryptographically generated
|
||||
32 byte string.
|
||||
|
||||
And you are good to go.
|
||||
|
||||
## Ref
|
||||
## Ref
|
||||
|
||||
- [Ente CLI Secrets Path](https://www.reddit.com/r/selfhosted/comments/1gc09il/comment/lu2hox2/?utm_source=share&utm_medium=web3x&utm_name=web3xcss&utm_term=1&utm_content=share_button)
|
||||
- [Keyrings](https://man7.org/linux/man-pages/man7/keyrings.7.html)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user