Merge branch 'main' into remote_db
34
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@@ -1,24 +1,21 @@
|
||||
name: Report a bug
|
||||
description: Let us know if something's not working the way you expected.
|
||||
description: For regressions only (things that were working earlier)
|
||||
labels: []
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Before opening a new bug report, please ensure
|
||||
1. you are on the latest version (it might've already been fixed),
|
||||
2. you've searched for existing issues (please add your observations as a comment there instead of creating a duplicate).
|
||||
|
||||
If you are self hosting, please create a community [Q&A](https://github.com/ente-io/ente/discussions/categories/q-a) instead.
|
||||
Before opening a new issue, **please** ensure
|
||||
1. You are on the latest version,
|
||||
2. You've searched for existing issues,
|
||||
3. It was working earlier (otherwise use [this](https://github.com/ente-io/ente/discussions/categories/enhancements))
|
||||
4. It is not about self hosting (otherwise use [this](https://github.com/ente-io/ente/discussions/categories/q-a))
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Description
|
||||
description: >
|
||||
Please describe the bug. If possible, also include the steps to
|
||||
reproduce the behaviour, and the expected behaviour (sometimes
|
||||
bugs are just expectation mismatches, in which case this would be
|
||||
a good fit for
|
||||
[enhancements](https://github.com/ente-io/ente/discussions/categories/enhancements)).
|
||||
Describe the bug and steps to reproduce the behaviour, and how it
|
||||
differs from the previously working behaviour.
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
@@ -30,15 +27,12 @@ body:
|
||||
attributes:
|
||||
label: Last working version
|
||||
description: >
|
||||
The version where the feature was last known to be working. It is
|
||||
fine if you don't remember the exact version (mention roughly
|
||||
then), but if there just isn't a last known working version, then
|
||||
it is likely that what is being reported is not an issue
|
||||
(regression) but an enhancement. The difference between the two
|
||||
categories is not just semantic - **enhancements use GitHub
|
||||
discussions and so can be [upvoted by the
|
||||
community](https://github.com/ente-io/ente/discussions/categories/enhancements)**
|
||||
(while issues cannot be).
|
||||
The version where things were last known to be working. It is fine
|
||||
if you don't remember the exact version (mention roughly then),
|
||||
but **if there just isn't a last working version, then please file
|
||||
it as an
|
||||
[enhancement](https://github.com/ente-io/ente/discussions/categories/enhancements))**
|
||||
(where the community upvotes can be used to help prioritize).
|
||||
placeholder: e.g. v1.2.3
|
||||
- type: dropdown
|
||||
attributes:
|
||||
|
||||
@@ -475,6 +475,16 @@
|
||||
"title": "FreeTaxUSA",
|
||||
"slug": "freetaxusa"
|
||||
},
|
||||
{
|
||||
"title": "FZJ",
|
||||
"slug": "fzj",
|
||||
"hex": "023d6b",
|
||||
"altNames": [
|
||||
"Forschungszentrum Jülich",
|
||||
"FZJ IdP",
|
||||
"iffLogin"
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "G2A"
|
||||
},
|
||||
@@ -739,8 +749,8 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Mercado Livre",
|
||||
"slug": "mercado_livre",
|
||||
"title": "Mercado Libre",
|
||||
"slug": "mercado_libre",
|
||||
"altNames": [
|
||||
"Mercado Libre",
|
||||
"MercadoLibre",
|
||||
@@ -1020,6 +1030,14 @@
|
||||
"qiniu"
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "R10.net",
|
||||
"slug": "r10",
|
||||
"altNames": [
|
||||
"R10",
|
||||
"r10.net"
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Raindrop.io",
|
||||
"slug": "raindrop_io",
|
||||
@@ -1399,6 +1417,25 @@
|
||||
},
|
||||
{
|
||||
"title": "CoinSpot"
|
||||
},
|
||||
{
|
||||
"title": "Aternos",
|
||||
"slug": "aternos"
|
||||
},
|
||||
{
|
||||
"title": "Toshl Finance",
|
||||
"slug": "toshl_finance",
|
||||
"altNames": [
|
||||
"Toshl"
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "xAI",
|
||||
"slug": "xai"
|
||||
},
|
||||
{
|
||||
"title": "Cronometer",
|
||||
"slug": "cronometer"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
13
auth/assets/custom-icons/icons/aternos.svg
Normal file
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
|
||||
<svg version="1.0" shape-rendering="geometricPrecision" text-rendering="geometricPrecision" image-rendering="optimizeQuality" fill-rule="evenodd" xml:space="preserve"
|
||||
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="300mm" height="300mm" viewBox="0 0 16000 16000" preserveAspectRatio="xMidYMid meet">
|
||||
<g>
|
||||
<path fill="#2b87d3" d="M0 8000 l0 -8000 8000 0 8000 0 0 8000 0 8000 -8000 0 -8000 0 0 -8000z m13990 0 l0 -5990 -5990 0 -5990 0 0 5990 0 5990 5990 0 5990 0 0 -5990z"/>
|
||||
<path fill="#2b87d3" d="M2995 12998 c-3 -7 -4 -911 -3 -2008 l3 -1995 1005 0 1005 0 3 997 2 998 998 2 997 3 0 1005 0 1005 -2003 3 c-1597 2 -2004 0 -2007 -10z"/>
|
||||
<path fill="#2b87d3" d="M8995 12998 c-3 -7 -4 -461 -3 -1008 l3 -995 997 -3 998 -2 2 -998 3 -997 1005 0 1005 0 0 2005 0 2005 -2003 3 c-1597 2 -2004 0 -2007 -10z"/>
|
||||
<path fill="#2b87d3" d="M5995 9998 c-3 -7 -4 -911 -3 -2008 l3 -1995 2005 0 2005 0 0 2005 0 2005 -2003 3 c-1597 2 -2004 0 -2007 -10z"/>
|
||||
<path fill="#2b87d3" d="M2995 6998 c-3 -7 -4 -911 -3 -2008 l3 -1995 2005 0 2005 0 0 1005 0 1005 -997 3 -998 2 -2 998 -3 997 -1003 3 c-797 2 -1004 0 -1007 -10z"/>
|
||||
<path fill="#2b87d3" d="M10997 7003 c-4 -3 -7 -453 -7 -1000 l0 -993 -997 -2 -998 -3 0 -1005 0 -1005 2005 0 2005 0 0 2005 0 2005 -1001 3 c-550 1 -1004 -1 -1007 -5z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.4 KiB |
25
auth/assets/custom-icons/icons/cronometer.svg
Normal file
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
width="107.51429"
|
||||
height="102.75398"
|
||||
viewBox="0 0 107.51429 102.75398"
|
||||
fill="none"
|
||||
version="1.1"
|
||||
id="svg12"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs12" />
|
||||
<g
|
||||
id="g12"
|
||||
transform="translate(34.950067,-215.99315)">
|
||||
<path
|
||||
d="m 57.85843,271.77769 c -0.774,-0.1257 -1.5665,0.0595 -2.2048,0.5152 -0.6382,0.4557 -1.0704,1.145 -1.2028,1.9179 -0.1447,0.8786 -0.3109,1.7775 -0.496,2.6697 -1.7799,8.5172 -5.1174,16.6325 -9.8446,23.9376 -5.0162,7.5169 -10.8489,12.0047 -15.6015,12.0047 -2.2725,0.0492 -4.5367,-0.2938 -6.6926,-1.0138 -5.6912,-1.775 -11.7884,-1.7717 -17.4777,0.009 -2.1479,0.7139 -4.4023,1.0536 -6.6652,1.0044 -4.7486,0 -10.58,-4.4851 -15.5963,-11.9979 -4.727,-7.3046 -8.0652,-15.4188 -9.84715,-23.935 -1.97756,-9.485 -1.60717,-17.8346 1.06924,-24.1485 1.09829,-2.7795 2.74951,-5.307 4.85381,-7.4292 2.1042,-2.1223 4.6176,-3.7952 7.3876,-4.9171 2.77,-1.122 5.7387,-1.6698 8.7268,-1.6101 2.988,0.0597 5.9328,0.7255 8.6558,1.9572 l 0.1663,0.0635 c 3.1372,1.3741 6.5201,2.0997 9.9449,2.1331 h 0.127 c 3.4272,-0.0346 6.8117,-0.763 9.9498,-2.1412 l 0.1502,-0.0581 c 2.981,-1.3116 6.2053,-1.979 9.462,-1.9586 1.8593,0.0219 3.7051,0.317 5.4785,0.8759 1.02,0.3144 2.0172,0.6982 2.9846,1.1489 0.7121,0.333 1.5269,0.3705 2.2665,0.1042 0.7397,-0.2662 1.3439,-0.8144 1.6805,-1.5248 0.1645,-0.3511 0.2583,-0.7312 0.2755,-1.1185 0.0172,-0.3873 -0.0421,-0.7742 -0.1749,-1.1385 -0.1328,-0.3643 -0.3362,-0.6987 -0.5986,-0.9841 -0.2625,-0.2854 -0.5788,-0.5161 -0.9307,-0.6789 -1.2159,-0.5667 -2.4693,-1.0495 -3.7512,-1.445 -2.3402,-0.7366 -4.7769,-1.1202 -7.2302,-1.1381 -3.9898,-0.0245 -7.9413,0.7777 -11.6058,2.356 l -0.1514,0.0581 c -1.5551,0.6563 -3.1723,1.1544 -4.8271,1.4869 -0.2018,-1.6639 -0.5606,-3.305 -1.0719,-4.9013 11.4383,-2.0749 11.0342,-15.88816 11.0342,-15.88816 -9.3133,1.40309 -13.3294,4.93919 -14.9623,8.33877 -1.5519,-2.01717 -3.4478,-3.74459 -5.6002,-5.10275 -0.3906,-0.24958 -0.8265,-0.41979 -1.2828,-0.50093 -0.4563,-0.0811 -0.9238,-0.0716 -1.3765,0.0281 -0.4526,0.0997 -0.8812,0.28749 -1.2613,0.55278 -0.38,0.26529 -0.7041,0.60283 -0.9537,0.99335 -0.2496,0.39052 -0.4198,0.82638 -0.5009,1.28269 -0.0812,0.45631 -0.0717,0.92412 0.028,1.37675 0.0997,0.45262 0.2875,0.88118 0.5528,1.2612 0.2653,0.38003 0.6028,0.70409 0.9933,0.95367 1.9269,1.29176 3.5632,2.97116 4.8046,4.93076 1.2415,1.9597 2.0607,4.1567 2.4055,6.4507 -1.2634,-0.3369 -2.5038,-0.7536 -3.7143,-1.2476 l -0.1759,-0.0676 c -3.6617,-1.5742 -7.6092,-2.3745 -11.5949,-2.3506 -9.0309,0 -20.73562,6.0327 -25.63155,17.5723 -3.97541,9.3756 -2.962867,20.2042 -1.41244,27.6387 1.94038,9.2532 5.57254,18.0686 10.71379,26.003 6.3017,9.4378 13.5982,14.6369 20.5461,14.6369 2.8438,0.049 5.6759,-0.375 8.3806,-1.255 4.5889,-1.454 9.515,-1.454 14.1039,0 2.6964,0.878 5.5198,1.3 8.3549,1.251 6.8478,0 14.3376,-5.3384 20.5461,-14.645 5.1404,-7.9344 8.7713,-16.75 10.7098,-26.0031 0.2041,-0.9746 0.3851,-1.9559 0.5406,-2.917 0.062,-0.3835 0.0481,-0.7755 -0.0416,-1.1535 -0.0897,-0.3779 -0.2534,-0.7345 -0.4812,-1.0492 -0.2278,-0.3147 -0.5154,-0.5813 -0.8464,-0.7846 -0.3311,-0.2033 -0.6991,-0.3393 -1.0828,-0.4001"
|
||||
fill="#ff6733"
|
||||
id="path11" />
|
||||
<path
|
||||
d="m 71.33493,256.39499 v 0.0121 l -8.2649,-5.8475 -0.4271,-0.2298 0.0512,-0.5177 0.2393,-10.0798 h 0.0095 c 0.0046,-0.5208 -0.1263,-1.0339 -0.3802,-1.4887 -0.2538,-0.4548 -0.6219,-0.8357 -1.0675,-1.1053 -0.4471,-0.2723 -0.9569,-0.4242 -1.4801,-0.441 -0.5233,-0.0169 -1.0422,0.102 -1.5059,0.3451 l -8.7538,4.3593 c -1.2619,0.6789 -2.3372,1.6578 -3.1318,2.8502 -0.7946,1.1925 -1.2839,2.5621 -1.4247,3.9881 l -0.7408,7.7913 -6.3059,3.3658 c -2.4638,-3.7027 -5.7171,-6.8136 -9.5264,-9.1092 -3.8093,-2.2956 -8.0799,-3.7189 -12.5047,-4.1675 -4.4249,-0.4486 -8.894,0.0886 -13.0866,1.573 -4.1925,1.4843 -8.0041,3.879 -11.1609,7.0119 -2.7859,2.7623 -4.9974,6.0489 -6.5065,9.6702 -1.509,3.6213 -2.286,7.5057 -2.286,11.4288 0,3.9232 0.777,7.8075 2.286,11.4288 1.5091,3.6214 3.7206,6.908 6.5065,9.6702 4.197,4.1711 9.5317,7.0104 15.3356,8.1623 5.8039,1.1518 11.8188,0.5648 17.2905,-1.6873 5.4718,-2.2522 10.157,-6.0694 13.4684,-10.9731 3.3114,-4.9037 5.1017,-10.6758 5.1465,-16.5928 0.0013,-3.8327 -0.7435,-7.6291 -2.1926,-11.1774 l 6.2181,-3.3117 -0.0109,0.0311 6.7206,4.0741 c 1.2315,0.7427 2.6257,1.1736 4.0615,1.2554 1.4357,0.0817 2.8695,-0.1882 4.1772,-0.7863 l 8.7534,-4.3593 c 0.472,-0.2216 0.877,-0.5622 1.177,-0.9882 0.3,-0.426 0.483,-0.9228 0.532,-1.4413 0.049,-0.5185 -0.038,-1.0409 -0.252,-1.5156 -0.214,-0.4747 -0.548,-0.8853 -0.97,-1.1915 m -34.1485,19.4107 c -0.0347,4.7475 -1.47,9.3791 -4.1262,13.3141 -2.6561,3.9351 -6.4148,6.9984 -10.8048,8.806 -4.39,1.8076 -9.2158,2.2789 -13.8727,1.355 -4.6568,-0.924 -8.9373,-3.2021 -12.3047,-6.5488 -2.2347,-2.2161 -4.0086,-4.8527 -5.2191,-7.7579 -1.2105,-2.9051 -1.8335,-6.0211 -1.8335,-9.1684 0,-3.1472 0.623,-6.2632 1.8335,-9.1684 1.2105,-2.9051 2.9844,-5.5417 5.2191,-7.7578 2.5007,-2.4815 5.514,-4.3861 8.8284,-5.5801 3.3145,-1.194 6.85,-1.6486 10.3587,-1.3319 3.5087,0.3167 6.9057,1.397 9.9528,3.1652 3.0471,1.7682 5.6703,4.1815 7.6862,7.0707 l -8.1614,4.3552 c -1.3138,-1.6306 -2.9557,-2.9671 -4.8188,-3.9229 -1.8632,-0.9559 -3.9062,-1.5098 -5.997,-1.6259 -2.0908,-0.1161 -4.1826,0.2082 -6.1401,0.952 -1.9576,0.7437 -3.7372,1.8903 -5.2234,3.3654 -1.3826,1.3719 -2.4797,3.0038 -3.2285,4.8018 -0.7489,1.798 -1.1343,3.7264 -1.1343,5.674 0,1.9477 0.3854,3.8761 1.1343,5.6741 0.7488,1.7979 1.8459,3.4299 3.2285,4.8018 2.317,2.3457 5.3482,3.8548 8.6165,4.2898 3.2684,0.4351 6.5886,-0.2286 9.4386,-1.8865 2.85,-1.6579 5.0682,-4.2161 6.3055,-7.2723 1.2374,-3.0562 1.4238,-6.437 0.53,-9.6107 l 8.2064,-4.3687 c 1.0104,2.6766 1.5273,5.5142 1.526,8.3752 z m -26.0801,1.2734 c 0.3553,0.6991 0.9725,1.2295 1.7171,1.4759 0.7445,0.2463 1.5564,0.1885 2.2586,-0.1607 l 6.9193,-3.6848 c 0.2696,2.1001 -0.213,4.2278 -1.3623,6.006 -1.1493,1.7782 -2.891,3.0921 -4.9165,3.7087 -2.0255,0.6167 -4.2042,0.4963 -6.1494,-0.3399 -1.9452,-0.8361 -3.5316,-2.334 -4.4779,-4.228 -0.9463,-1.8941 -1.1912,-4.0621 -0.6917,-6.1196 0.4995,-2.0576 1.7111,-3.8718 3.4205,-5.1212 1.7094,-1.2494 3.806,-1.8532 5.9181,-1.7044 2.1121,0.1487 4.1034,1.0405 5.6207,2.5172 l -6.9345,3.6997 c -0.3472,0.1714 -0.6571,0.4099 -0.9118,0.7018 -0.2546,0.2918 -0.449,0.6311 -0.5719,0.9984 -0.1229,0.3673 -0.172,0.7553 -0.1442,1.1416 0.0278,0.3863 0.1317,0.7633 0.3059,1.1093 z m 39.7718,-27.0764 c 0.219,-1.157 0.3879,-2.1708 1.4557,-2.7467 l 4.5109,-2.2438 -0.6085,5.5191 -5.7029,2.8386 z m 8.0467,10.3339 c -0.5151,0.173 -1.0642,0.2192 -1.6009,0.1347 -0.5367,-0.0845 -1.0453,-0.2971 -1.4824,-0.6199 l -2.9222,-1.7424 5.7042,-2.8386 4.8109,2.8224 z"
|
||||
fill="#ff6733"
|
||||
id="path12" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 6.6 KiB |
7
auth/assets/custom-icons/icons/fzj.svg
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
<svg width="21.087mm" height="21.735mm" version="1.1" viewBox="0 0 21.087 21.735" xmlns="http://www.w3.org/2000/svg">
|
||||
<g transform="translate(34.396 -25.136)">
|
||||
<path d="m-26.575 34.404 3.5438-9.2136c-0.38165-0.0363-0.76329-0.0545-1.1631-0.0545-1.9082 0-3.7983 0.49067-5.452 1.4538-1.6538 0.96316-3.035 2.3261-3.9982 3.998-0.09087 0.14538-0.16356 0.30893-0.25443 0.47249v0.0545l-0.14538 0.39981c-1.0904 2.7804 0.56337 4.834 2.1626 5.4337 0.45433 0.16355 0.92685 0.25441 1.3994 0.25441 0.72694 0 1.4175-0.18172 2.0536-0.54517 0.6179-0.36347 1.1449-0.8723 1.5084-1.4902 0.14539-0.23624 0.25443-0.49067 0.34529-0.76326m6.4334 2.3625c-2.1081 5.5246-7.2149 7.5962-11.885 6.7966 0.70877 0.72692 1.5084 1.3448 2.3807 1.8536 1.6538 0.96316 3.5257 1.4538 5.452 1.4538 1.9082 0 3.7619-0.49067 5.4339-1.4538 1.6538-0.96316 3.035-2.3261 3.9982-3.9798 0.94502-1.6537 1.4539-3.5437 1.4539-5.4337 0-1.9082-0.50886-3.8163-1.4539-5.4518-0.5452-0.94499-1.1994-1.7628-1.9809-2.4897l-3.3984 8.7048" fill="#023d6b" fill-rule="evenodd" stroke-width=".26458"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 8.0 KiB After Width: | Height: | Size: 8.0 KiB |
96
auth/assets/custom-icons/icons/r10.svg
Normal file
@@ -0,0 +1,96 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 25.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 280.6 100" style="enable-background:new 0 0 280.6 100;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{enable-background:new ;}
|
||||
.st1{fill:#FFFFFF;}
|
||||
.st2{fill:#3F4257;}
|
||||
.st3{fill-rule:evenodd;clip-rule:evenodd;fill:#3F4257;}
|
||||
.st4{fill-rule:evenodd;clip-rule:evenodd;fill:#EA4335;}
|
||||
.st5{fill:#EA4335;}
|
||||
.st6{fill:#FBBC05;}
|
||||
.st7{fill:#4285F4;}
|
||||
.st8{fill:#34A853;}
|
||||
</style>
|
||||
<g>
|
||||
<g class="st0">
|
||||
<path class="st1" d="M114.5,57.9h-6.3L97.9,46.2h-7.2v11.7h-5.4V24.1c5.3,0,10.5,0,15.8,0c7.8,0,12,5.4,12,11
|
||||
c0,4.8-2.5,9.5-9.2,10.5L114,57L114.5,57.9z M90.7,29.1v12.2H101c4.5,0,6.5-2.8,6.5-6c0-3-2-6.2-6.4-6.2H90.7z"/>
|
||||
<polygon class="st1" points="124.5,57.9 129.9,57.9 129.9,24.2 118.7,27.7 118.7,32.4 124.5,30.8 "/>
|
||||
<path class="st1" d="M139.7,38.1c0-19.6,28.4-19.5,28.4,0V44c0,19.5-28.4,19.6-28.4,0V38.1z M145.2,44c0,12.8,17.5,12.8,17.5,0
|
||||
v-5.9c0-12.6-17.5-12.8-17.5,0V44z"/>
|
||||
</g>
|
||||
<g class="st0">
|
||||
<path class="st1" d="M188.8,24.2l22.8,27.9V24.2h2.6v33.8h-1L190.3,30v27.9h-2.6V24.2H188.8z"/>
|
||||
<path class="st1" d="M226.3,39.7h19.8v2.4h-19.8v13.3h21.4v2.5h-24V24.2h23.4v2.5h-20.8V39.7z"/>
|
||||
<path class="st1" d="M263.3,26.5h-12.2v-2.3h27.1v2.3h-12.2v31.4h-2.6V26.5z"/>
|
||||
</g>
|
||||
<g id="Group_174_3_" transform="translate(-5071.999 -1624)">
|
||||
<path class="st1" d="M5106.8,1722c-5.8,0-11.4-1.2-16.4-3.6c-4.9-2.3-9.1-5.7-12-9.8c-5-7.1-6.1-16-3-25l0-0.1
|
||||
c7.8-22.5,13-25.7,18.7-27.4l0.5-0.1l0,0.2l0.8-0.1c0.5,0,0.9-0.1,1.4-0.1c0.6,0,1.2,0,1.8,0.1l0.8,0.1l0.4,0.1
|
||||
c1.9,0.3,3.8,0.8,5.7,1.5l0,0l0,0c0.4,0.1,0.9,0.2,1.3,0.2c0,0,0,0,0,0c5.2,0,12.8-10.1,18.8-28.9c-0.3,1.7-1.1,6.5-1.4,8.1
|
||||
c-1.2,6.5-2.3,12.7-3.2,17.7l-0.1,0.5l0.5,0.2c2.8,1.2,5,3.8,6.5,7.6l0.1,0.3l0.3,0.1c5.2,1.9,9.3,4.6,12.1,8
|
||||
c2.5,3,4.2,6.5,4.8,10.5c0.9,5.3,0,11.6-2.5,17.6c-2.2,5.2-5.3,9.8-8.5,12.3C5126,1718.6,5116.6,1722,5106.8,1722L5106.8,1722z
|
||||
M5094.2,1635.7l0.5,2.5l-0.2,16.8L5094.2,1635.7z M5099.2,1654.4c-0.2-8.7,5.1-17.6,12.8-21.7c-0.7,0.9-1.4,1.8-2,2.7
|
||||
C5103.8,1639,5100.3,1645.3,5099.2,1654.4z"/>
|
||||
<g>
|
||||
<path class="st1" d="M5128.3,1663.1c-1.7-4.1-4-6.7-6.9-8c1.5-8.3,3.6-20,5.7-31.1c-0.4,1.7-1.1,3.4-1.7,5
|
||||
c-1.7,9.3-4.2,20.4-5.5,27.4c3.2,1.5,5.6,4.2,6.9,7.6c27.3,9.9,16.5,38.3,6.9,46.1c-28,22.7-67.7,4-57.3-26.9
|
||||
c6.8-20.3,12.9-24.2,18.7-26v0c2.6-0.5,6.9,0.4,9.2,0.9c1.4,0.4,2.2,0.5,2.5,0.5c8,0.5,15.6-18.5,18.5-29.8
|
||||
c-2.1,5.3-11.8,30.7-19.9,28.3c-1.9-0.7-3.8-1.2-5.8-1.6c0.8-8.8,4-15.8,10.7-19.6c1.2-1.8,2.7-3.6,4.2-5.1
|
||||
c-9.9,3.5-16.8,14.4-16.1,24.6c-1.1-0.1-2.2-0.1-3.3,0l0.2-17.2l-2.1-9.6l0.5,26.8c-6.3,1.9-11.6,5.9-19.1,27.8l0,0
|
||||
c-7.8,22.6,10.4,39.4,32.1,39.4c9.2,0,19-3.1,27.7-10C5144.6,1704.6,5157.1,1673.7,5128.3,1663.1z"/>
|
||||
<polygon class="st2" points="5114.7,1630.8 5114.7,1630.8 5114.7,1630.8 "/>
|
||||
</g>
|
||||
<g id="Group_1_3_" transform="translate(5072 1624)">
|
||||
<path id="Path_839_2_" class="st3" d="M33.1,41.9c1.8-4.6,5.7-7.7,10.2-7.7c6.2,0,11.3,6.1,11.3,13.6s-5.1,13.6-11.3,13.6
|
||||
c-4.5,0-8.4-3.2-10.2-7.8c0.1-0.2,0.2-0.3,0.3-0.5c1.7,4.2,5.2,7.2,9.4,7.2c5.7,0,10.4-5.6,10.4-12.4s-4.6-12.4-10.4-12.4
|
||||
c-4.1,0-7.7,2.9-9.4,7.1C33.3,42.2,33.2,42.1,33.1,41.9z M25.1,36.4c2.9,0,5.5,1.9,7.1,4.8c-1.2-2.3-3.6-3.7-6.2-3.8
|
||||
c-4.4,0-7.9,4.6-7.9,10.3S22.5,58,26,58s4.7-1.9,6.1-4.2c-1.6,2.8-3.2,5.1-7,5.1c-3.8,0-8.7-5-8.7-11.2
|
||||
C16.4,41.5,20.3,36.4,25.1,36.4L25.1,36.4z"/>
|
||||
<path id="Path_840_2_" class="st3" d="M27.8,45.5c0.9,0,1.6-0.7,1.6-1.5c0-0.9-0.7-1.6-1.5-1.6c-0.9,0-1.6,0.7-1.6,1.5
|
||||
c0,0,0,0,0,0C26.3,44.8,27,45.4,27.8,45.5z"/>
|
||||
<path id="Path_842_2_" class="st3" d="M46.9,46.4c0.9,0,1.6-0.6,1.6-1.5c0-0.9-0.6-1.6-1.5-1.6s-1.6,0.6-1.6,1.5c0,0,0,0,0,0.1
|
||||
C45.4,45.7,46.1,46.4,46.9,46.4z"/>
|
||||
<path id="Path_843_2_" class="st3" d="M26.1,62.8l0.6,0.1l-2.3,23.4l-0.6-0.1L26.1,62.8z"/>
|
||||
<path id="Path_844_2_" class="st3" d="M38.6,65.3l0.6,0l1.5,23.5l-0.6,0L38.6,65.3z"/>
|
||||
<path id="Path_845_2_" class="st3" d="M51.6,64.2l0.5-0.1l3.1,19.7L54.6,84L51.6,64.2z"/>
|
||||
<g>
|
||||
<polygon class="st2" points="8.1,57.5 8.1,57.5 8.1,57.5 8.1,57.5 "/>
|
||||
<path class="st2" d="M8.1,57.5c-4.3,39.6,64.1,47.3,56.7-0.1c0,0,0,0,0,0c0,0,0,0,0,0s0,0,0,0c-0.3,0.2-0.6,0.4-0.9,0.6
|
||||
c-0.3,0.2-0.6,0.5-1,0.7c-0.9,0.6-2.2,1.2-3.8,1.9C41.4,66.9,17.2,62.2,8.1,57.5 M9.3,58.9c7.6,7,37.3,10.1,53,2.1
|
||||
c0,0,0.3-0.1,0.5-0.3C67.3,101.9,5.8,94.4,9.3,58.9z"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<circle class="st1" cx="177.1" cy="53.6" r="4"/>
|
||||
<path id="Forma_1_3_" class="st4" d="M153,74.7c-1,0-2.1,0.3-2.9,1c-0.7,0.6-1.3,1.3-1.7,2c-0.4-0.8-1-1.5-1.7-2
|
||||
c-0.8-0.7-1.8-1-2.9-1c-2.9,0-5.2,2.4-5.2,5.6c0,3.5,2.8,5.8,7,9.4c0.7,0.6,1.5,1.3,2.4,2c0.2,0.2,0.6,0.2,0.8,0
|
||||
c0.8-0.7,1.6-1.4,2.4-2c4.2-3.6,7-6,7-9.4C158.1,77.1,155.9,74.7,153,74.7z"/>
|
||||
<g>
|
||||
<path class="st1" d="M86.6,71.9l5.2,15.7l5.3-15.7h1.5l5.3,15.7l5.2-15.7h2.7l-6.6,19h-2.4l-4.9-14.2L93,90.9h-2.4l-6.6-19H86.6z"
|
||||
/>
|
||||
<path class="st1" d="M125.1,88.7c-1.4,1.6-3.7,2.4-5.8,2.4c-4.1,0-7-2.7-7-7c0-4,2.9-6.9,6.9-6.9c4.1,0,7.2,2.5,6.7,7.9h-11.4
|
||||
c0.2,2.5,2.3,4,4.9,4c1.5,0,3.4-0.6,4.3-1.7L125.1,88.7L125.1,88.7z M123.8,83.2c-0.1-2.6-1.9-4-4.5-4c-2.3,0-4.4,1.4-4.7,4
|
||||
L123.8,83.2L123.8,83.2z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path class="st5" d="M214.6,84.2c0,4.8-3.7,8.3-8.3,8.3s-8.3-3.5-8.3-8.3c0-4.8,3.7-8.3,8.3-8.3S214.6,79.4,214.6,84.2z M211,84.2
|
||||
c0-3-2.2-5-4.7-5s-4.7,2-4.7,5c0,3,2.2,5,4.7,5S211,87.2,211,84.2z"/>
|
||||
<path class="st6" d="M232.6,84.2c0,4.8-3.7,8.3-8.3,8.3s-8.3-3.5-8.3-8.3c0-4.8,3.7-8.3,8.3-8.3S232.6,79.4,232.6,84.2z M229,84.2
|
||||
c0-3-2.2-5-4.7-5s-4.7,2-4.7,5c0,3,2.2,5,4.7,5S229,87.2,229,84.2z"/>
|
||||
<path class="st7" d="M249.9,76.4v14.9c0,6.1-3.6,8.7-7.9,8.7c-4,0-6.5-2.7-7.4-4.9l3.2-1.3c0.6,1.4,2,3,4.2,3
|
||||
c2.7,0,4.4-1.7,4.4-4.9v-1.2h-0.1c-0.8,1-2.4,1.9-4.4,1.9c-4.2,0-8-3.6-8-8.3c0-4.7,3.8-8.3,8-8.3c2,0,3.6,0.9,4.4,1.9h0.1v-1.4
|
||||
L249.9,76.4L249.9,76.4z M246.7,84.3c0-2.9-2-5.1-4.4-5.1c-2.5,0-4.6,2.1-4.6,5.1c0,2.9,2.1,5,4.6,5
|
||||
C244.7,89.3,246.7,87.2,246.7,84.3z"/>
|
||||
<path class="st8" d="M255.6,67.7V92H252V67.7H255.6z"/>
|
||||
<path class="st5" d="M269.5,87l2.8,1.9c-0.9,1.4-3.1,3.7-6.9,3.7c-4.7,0-8.3-3.7-8.3-8.3c0-4.9,3.6-8.3,7.8-8.3
|
||||
c4.3,0,6.4,3.4,7.1,5.3l0.4,0.9l-11.1,4.6c0.9,1.7,2.2,2.5,4,2.5C267.3,89.3,268.6,88.4,269.5,87L269.5,87z M260.8,84l7.4-3.1
|
||||
c-0.4-1-1.6-1.8-3.1-1.8C263.3,79.1,260.7,80.8,260.8,84z"/>
|
||||
<path class="st7" d="M184.5,82.1v-3.5h11.9c0.1,0.6,0.2,1.3,0.2,2.1c0,2.6-0.7,5.9-3.1,8.3c-2.3,2.4-5.2,3.6-9,3.6
|
||||
c-7.1,0-13.1-5.8-13.1-12.9c0-7.1,6-12.9,13.1-12.9c3.9,0,6.7,1.5,8.9,3.6l-2.5,2.5c-1.5-1.4-3.6-2.5-6.4-2.5
|
||||
c-5.2,0-9.3,4.2-9.3,9.4c0,5.2,4.1,9.4,9.3,9.4c3.4,0,5.3-1.4,6.5-2.6c1-1,1.7-2.4,1.9-4.4L184.5,82.1z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 6.8 KiB |
103
auth/assets/custom-icons/icons/toshl_finance.svg
Normal file
|
After Width: | Height: | Size: 16 KiB |
35
auth/assets/custom-icons/icons/xai.svg
Normal file
@@ -0,0 +1,35 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Generator: Adobe Illustrator 27.5.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="katman_1"
|
||||
x="0px"
|
||||
y="0px"
|
||||
viewBox="0 0 841.89 595.28"
|
||||
style="enable-background:new 0 0 841.89 595.28;"
|
||||
xml:space="preserve"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs id="defs4" />
|
||||
<g
|
||||
id="g4"
|
||||
style="fill:currentColor">
|
||||
<polygon
|
||||
points="557.09,211.99 565.4,538.36 631.96,538.36 640.28,93.18"
|
||||
id="polygon1"
|
||||
style="fill:currentColor" />
|
||||
<polygon
|
||||
points="640.28,56.91 538.72,56.91 379.35,284.53 430.13,357.05"
|
||||
id="polygon2"
|
||||
style="fill:currentColor" />
|
||||
<polygon
|
||||
points="201.61,538.36 303.17,538.36 353.96,465.84 303.17,393.31"
|
||||
id="polygon3"
|
||||
style="fill:currentColor" />
|
||||
<polygon
|
||||
points="201.61,211.99 430.13,538.36 531.69,538.36 303.17,211.99"
|
||||
id="polygon4"
|
||||
style="fill:currentColor" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.0 KiB |
@@ -8,7 +8,7 @@
|
||||
},
|
||||
"onBoardingBody": "Бяспечна зрабіць рэзервовую копію кодаў 2ФА",
|
||||
"onBoardingGetStarted": "Пачаць",
|
||||
"setupFirstAccount": "Наладзіць ваш першы ўліковы запіс",
|
||||
"setupFirstAccount": "Наладзіць свой першы ўліковы запіс",
|
||||
"importScanQrCode": "Сканіраваць код QR-код",
|
||||
"qrCode": "QR-код",
|
||||
"importEnterSetupKey": "Увесці ключ наладжвання",
|
||||
@@ -45,19 +45,38 @@
|
||||
"timeBasedKeyType": "Заснаваныя на часе (TOTP)",
|
||||
"counterBasedKeyType": "Заснаваныя на лічыльніку (HOTP)",
|
||||
"saveAction": "Захаваць",
|
||||
"nextTotpTitle": "наступны",
|
||||
"nextTotpTitle": "далей",
|
||||
"deleteCodeTitle": "Выдаліць код?",
|
||||
"deleteCodeMessage": "Вы сапраўды хочаце выдаліць гэты код? Гэта дзеянне з'яўляецца незваротным.",
|
||||
"trashCode": "Выдаліць код?",
|
||||
"trashCodeMessage": "Вы сапраўды хочаце выдаліць код для {account}?",
|
||||
"trash": "Сметніца",
|
||||
"viewLogsAction": "Паглядзець журнал",
|
||||
"preparingLogsTitle": "Падрыхтоўка журнала...",
|
||||
"viewLogsAction": "Паглядзець журналы",
|
||||
"preparingLogsTitle": "Падрыхтоўка журналаў...",
|
||||
"emailLogsTitle": "Адправіць журнал па электроннай пошце",
|
||||
"exportLogsAction": "Экспартаваць журнал",
|
||||
"reportABug": "Паведаміць пра памылку",
|
||||
"reportBug": "Паведаміць пра памылку",
|
||||
"emailLogsMessage": "Адпраўце журналы на {email}",
|
||||
"@emailLogsMessage": {
|
||||
"placeholders": {
|
||||
"email": {
|
||||
"type": "String"
|
||||
}
|
||||
}
|
||||
},
|
||||
"copyEmailAction": "Скапіяваць электронную пошту",
|
||||
"exportLogsAction": "Экспартаваць журналы",
|
||||
"reportABug": "Паведаміць аб памылцы",
|
||||
"crashAndErrorReporting": "Справаздачы аб збоях і памылках",
|
||||
"reportBug": "Паведаміць аб памылцы",
|
||||
"emailUsMessage": "Адпраўце нам ліст на {email}",
|
||||
"@emailUsMessage": {
|
||||
"placeholders": {
|
||||
"email": {
|
||||
"type": "String"
|
||||
}
|
||||
}
|
||||
},
|
||||
"contactSupport": "Звярнуцца ў службу падтрымкі",
|
||||
"rateUsOnStore": "Ацаніць нас у {storeName}",
|
||||
"blog": "Блог",
|
||||
"verifyPassword": "Праверыць пароль",
|
||||
"pleaseWait": "Пачакайце...",
|
||||
@@ -66,32 +85,128 @@
|
||||
"useRecoveryKey": "Выкарыстоўваць ключ аднаўлення",
|
||||
"incorrectPasswordTitle": "Няправільны пароль",
|
||||
"welcomeBack": "З вяртаннем!",
|
||||
"changeEmail": "Змяніць адрас электроннай пошты",
|
||||
"changePassword": "Змяніць пароль",
|
||||
"data": "Даныя",
|
||||
"importCodes": "Імпартаваць коды",
|
||||
"importTypePlainText": "Звычайны тэкст",
|
||||
"importTypeEnteEncrypted": "Шыфраванне экспартавання з Ente",
|
||||
"passwordForDecryptingExport": "Пароль для дэшыфроўкі экспартавання",
|
||||
"passwordEmptyError": "Пароль не можа быць пустым",
|
||||
"importFromApp": "Імпартаваць коды з {appName}",
|
||||
"exportCodes": "Экспартаваць коды",
|
||||
"importLabel": "Імпарт",
|
||||
"selectFile": "Выбраць файл",
|
||||
"ok": "OK",
|
||||
"cancel": "Скасаваць",
|
||||
"yes": "Так",
|
||||
"no": "Не",
|
||||
"email": "Электронная пошта",
|
||||
"support": "Падтрымка",
|
||||
"general": "Агульныя",
|
||||
"settings": "Налады",
|
||||
"copied": "Скапіявана",
|
||||
"pleaseTryAgain": "Калі ласка, паспрабуйце яшчэ раз",
|
||||
"delete": "Выдаліць",
|
||||
"enterYourPasswordHint": "Увядзіце ваш пароль",
|
||||
"forgotPassword": "Забылі пароль",
|
||||
"oops": "Вой",
|
||||
"faq": "Частыя пытанні",
|
||||
"scan": "Сканіраваць",
|
||||
"verify": "Праверыць",
|
||||
"verifyPasskey": "Праверыць ключ доступу",
|
||||
"loginWithTOTP": "Увайсці з TOTP",
|
||||
"recoverAccount": "Аднавіць уліковы запіс",
|
||||
"recover": "Аднавіць",
|
||||
"invalidQRCode": "Памылковы QR-код",
|
||||
"deleteAccount": "Выдаліць уліковы запіс",
|
||||
"noDeleteAccountAction": "Не, выдаліць уліковы запіс",
|
||||
"sendEmail": "Адправіць ліст",
|
||||
"createNewAccount": "Стварыць новы ўліковы запіс",
|
||||
"weakStrength": "Ненадзейны",
|
||||
"strongStrength": "Надзейны",
|
||||
"moderateStrength": "Умераная",
|
||||
"confirmPassword": "Пацвердзіць пароль",
|
||||
"close": "Закрыць",
|
||||
"oopsSomethingWentWrong": "Штосьці пайшло не так.",
|
||||
"selectLanguage": "Выберыце мову",
|
||||
"language": "Мова",
|
||||
"social": "Сацыяльныя сеткі",
|
||||
"security": "Бяспека",
|
||||
"searchHint": "Пошук...",
|
||||
"search": "Пошук"
|
||||
"search": "Пошук",
|
||||
"addCode": "Дадаць код",
|
||||
"scanAQrCode": "Сканіраваць QR-код",
|
||||
"edit": "Рэдагаваць",
|
||||
"share": "Абагуліць",
|
||||
"restore": "Аднавіць",
|
||||
"error": "Памылка",
|
||||
"saveKey": "Захаваць ключ",
|
||||
"save": "Захаваць",
|
||||
"send": "Адправіць",
|
||||
"back": "Назад",
|
||||
"createAccount": "Стварыць уліковы запіс",
|
||||
"password": "Пароль",
|
||||
"privacyPolicyTitle": "Палітыка прыватнасці",
|
||||
"termsOfServicesTitle": "Умовы",
|
||||
"changePasswordTitle": "Змяніць пароль",
|
||||
"resetPasswordTitle": "Скінуць пароль",
|
||||
"encryptionKeys": "Ключы шыфравання",
|
||||
"continueLabel": "Працягнуць",
|
||||
"insecureDevice": "Небяспечная прылада",
|
||||
"logInLabel": "Увайсці",
|
||||
"logout": "Выйсці",
|
||||
"exit": "Выхад",
|
||||
"theme": "Тема",
|
||||
"lightTheme": "Светлая",
|
||||
"darkTheme": "Цёмная",
|
||||
"systemTheme": "Сістэманая",
|
||||
"confirm": "Пацвердзіць",
|
||||
"emailYourLogs": "Адправіць журналы",
|
||||
"about": "Аб праграме",
|
||||
"privacy": "Прыватнасць",
|
||||
"terms": "Умовы",
|
||||
"downloadUpdate": "Спампаваць",
|
||||
"update": "Абнавіць",
|
||||
"warning": "Папярэджанне",
|
||||
"importSuccessTitle": "Ура!",
|
||||
"sorry": "Прабачце",
|
||||
"pendingSyncs": "Папярэджанне",
|
||||
"manualSort": "Карыстальніцкая",
|
||||
"incorrectCode": "Няправільны код",
|
||||
"enterPassword": "Увядзіце пароль",
|
||||
"export": "Экспартаваць",
|
||||
"singIn": "Увайсці",
|
||||
"androidBiometricSuccess": "Паспяхова",
|
||||
"@androidBiometricSuccess": {
|
||||
"description": "Message to let the user know that authentication was successful. It is used on Android side. Maximum 60 characters."
|
||||
},
|
||||
"androidCancelButton": "Скасаваць",
|
||||
"@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."
|
||||
},
|
||||
"goToSettings": "Перайсці ў налады",
|
||||
"@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."
|
||||
},
|
||||
"passkey": "Ключ доступу",
|
||||
"pinText": "Замацаваць",
|
||||
"unpinText": "Адмацаваць",
|
||||
"pinned": "Замацавана",
|
||||
"tags": "Тэгі",
|
||||
"createNewTag": "Стварыць новы тэг",
|
||||
"tag": "Тэг",
|
||||
"create": "Стварыць",
|
||||
"viewRawCodes": "Паглядзець неапрацаваныя коды",
|
||||
"rawCodeData": "Неапрацаваныя даныя кода",
|
||||
"appLock": "Блакіроўка праграмы",
|
||||
"next": "Далей",
|
||||
"tapToUnlock": "Націсніце для разблакіроўкі",
|
||||
"type": "Тып",
|
||||
"period": "Перыяд",
|
||||
"digits": "Лічбы"
|
||||
}
|
||||
@@ -173,6 +173,7 @@
|
||||
"invalidQRCode": "Ogiltig QR-kod",
|
||||
"noRecoveryKeyTitle": "Ingen återställningsnyckel?",
|
||||
"enterEmailHint": "Ange din e-postadress",
|
||||
"enterNewEmailHint": "Ange din nya e-postadress",
|
||||
"invalidEmailTitle": "Ogiltig e-postadress",
|
||||
"invalidEmailMessage": "Ange en giltig e-postadress.",
|
||||
"deleteAccount": "Radera konto",
|
||||
@@ -368,16 +369,19 @@
|
||||
"signInToBackup": "Logga in för att säkerhetskopiera dina koder",
|
||||
"singIn": "Logga in",
|
||||
"sigInBackupReminder": "Vänligen exportera dina koder för att säkerställa att du har en säkerhetskopia som du kan återställa från.",
|
||||
"offlineModeWarning": "Du har valt att fortsätta utan säkerhetskopior. Vänligen ta manuella säkerhetskopior för att se till att dina koder är säkra.",
|
||||
"showLargeIcons": "Visa stora ikoner",
|
||||
"compactMode": "Kompakt läge",
|
||||
"shouldHideCode": "Dölj koder",
|
||||
"doubleTapToViewHiddenCode": "Du kan dubbeltrycka på en post för att visa koden",
|
||||
"focusOnSearchBar": "Fokusera på sök vid appstart",
|
||||
"confirmUpdatingkey": "Är du säker på att du vill uppdatera den hemliga nyckeln?",
|
||||
"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",
|
||||
"confirmAccountDeleteMessage": "Detta konto är kopplat till andra Ente apps, om du använder någon.\n\nDina uppladdade data, över alla Ente appar, kommer att schemaläggas för radering och ditt konto kommer att raderas permanent.",
|
||||
"androidBiometricHint": "Verifiera identitet",
|
||||
"@androidBiometricHint": {
|
||||
"description": "Hint message advising the user how to authenticate with biometrics. It is used on Android side. Maximum 60 characters."
|
||||
@@ -414,6 +418,18 @@
|
||||
"@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."
|
||||
},
|
||||
"androidGoToSettingsDescription": "Biometrisk autentisering är inte konfigurerad på din enhet. Gå till \"Inställningar > Säkerhet\" för att lägga till biometrisk autentisering.",
|
||||
"@androidGoToSettingsDescription": {
|
||||
"description": "Message advising the user to go to the settings and configure biometric on their device. It shows in a dialog on Android side."
|
||||
},
|
||||
"iOSLockOut": "Biometrisk autentisering är inaktiverat. Lås och lås upp din skärm för att aktivera den.",
|
||||
"@iOSLockOut": {
|
||||
"description": "Message advising the user to re-enable biometrics on their device. It shows in a dialog on iOS side."
|
||||
},
|
||||
"iOSGoToSettingsDescription": "Biometrisk autentisering är inte konfigurerad på din enhet. Aktivera antingen Touch ID eller Face ID på din telefon.",
|
||||
"@iOSGoToSettingsDescription": {
|
||||
"description": "Message advising the user to go to the settings and configure Biometrics for their device. It shows in a dialog on iOS side."
|
||||
},
|
||||
"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."
|
||||
@@ -421,6 +437,7 @@
|
||||
"noInternetConnection": "Ingen internetanslutning",
|
||||
"pleaseCheckYourInternetConnectionAndTryAgain": "Kontrollera din internetanslutning och försök igen.",
|
||||
"signOutFromOtherDevices": "Logga ut från andra enheter",
|
||||
"signOutOtherBody": "Om du tror att någon kanske känner till ditt lösenord kan du tvinga alla andra enheter med ditt konto att logga ut.",
|
||||
"signOutOtherDevices": "Logga ut andra enheter",
|
||||
"doNotSignOut": "Logga inte ut",
|
||||
"hearUsWhereTitle": "Hur hörde du talas om Ente? (valfritt)",
|
||||
@@ -450,6 +467,7 @@
|
||||
"create": "Skapa",
|
||||
"editTag": "Redigera tagg",
|
||||
"deleteTagTitle": "Radera tagg?",
|
||||
"deleteTagMessage": "Vill du ta bort den här koden? Det går inte att ångra den här åtgärden.",
|
||||
"somethingWentWrongParsingCode": "Vi kunde inte tolka {x} koder.",
|
||||
"updateNotAvailable": "Uppdateringen är inte tillgänglig",
|
||||
"viewRawCodes": "Visa råa koder",
|
||||
|
||||
@@ -173,6 +173,7 @@
|
||||
"invalidQRCode": "QR 碼無效",
|
||||
"noRecoveryKeyTitle": "沒有復原密鑰嗎?",
|
||||
"enterEmailHint": "請輸入您的電子郵件地址",
|
||||
"enterNewEmailHint": "輸入你的新電子郵件地址",
|
||||
"invalidEmailTitle": "無效的電子郵件地址",
|
||||
"invalidEmailMessage": "請輸入一個有效的電子郵件地址。",
|
||||
"deleteAccount": "刪除帳戶",
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
"next-electron-server": "^1.0.0",
|
||||
"node-stream-zip": "^1.15.0",
|
||||
"onnxruntime-node": "^1.20.1",
|
||||
"zod": "^3.25.48"
|
||||
"zod": "^3.25.51"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^9.28.0",
|
||||
@@ -49,7 +49,7 @@
|
||||
"ajv": "^8.17.1",
|
||||
"concurrently": "^9.1.2",
|
||||
"cross-env": "^7.0.3",
|
||||
"electron": "^36.3.2",
|
||||
"electron": "^36.4.0",
|
||||
"electron-builder": "^26.0.14",
|
||||
"eslint": "^9",
|
||||
"prettier": "3.5.3",
|
||||
@@ -57,7 +57,7 @@
|
||||
"prettier-plugin-packagejson": "^2.5.15",
|
||||
"shx": "^0.4.0",
|
||||
"typescript": "^5.8.3",
|
||||
"typescript-eslint": "^8.33.0"
|
||||
"typescript-eslint": "^8.33.1"
|
||||
},
|
||||
"packageManager": "yarn@1.22.22",
|
||||
"productName": "ente"
|
||||
|
||||
@@ -50,8 +50,8 @@ import { convertToJPEG, generateImageThumbnail } from "./services/image";
|
||||
import { logout } from "./services/logout";
|
||||
import {
|
||||
lastShownChangelogVersion,
|
||||
masterKeyB64,
|
||||
saveMasterKeyB64,
|
||||
masterKeyFromSafeStorage,
|
||||
saveMasterKeyInSafeStorage,
|
||||
setLastShownChangelogVersion,
|
||||
} from "./services/store";
|
||||
import {
|
||||
@@ -108,10 +108,12 @@ export const attachIPCHandlers = () => {
|
||||
|
||||
ipcMain.handle("selectDirectory", () => selectDirectory());
|
||||
|
||||
ipcMain.handle("masterKeyB64", () => masterKeyB64());
|
||||
ipcMain.handle("masterKeyFromSafeStorage", () =>
|
||||
masterKeyFromSafeStorage(),
|
||||
);
|
||||
|
||||
ipcMain.handle("saveMasterKeyB64", (_, masterKeyB64: string) =>
|
||||
saveMasterKeyB64(masterKeyB64),
|
||||
ipcMain.handle("saveMasterKeyInSafeStorage", (_, masterKey: string) =>
|
||||
saveMasterKeyInSafeStorage(masterKey),
|
||||
);
|
||||
|
||||
ipcMain.handle("lastShownChangelogVersion", () =>
|
||||
|
||||
@@ -12,7 +12,7 @@ import fs_ from "node:fs";
|
||||
import fs from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import { Readable } from "node:stream";
|
||||
import { z } from "zod";
|
||||
import { z } from "zod/v4";
|
||||
import type { FFmpegCommand } from "../../types/ipc";
|
||||
import log from "../log-worker";
|
||||
import { messagePortMainEndpoint } from "../utils/comlink";
|
||||
|
||||
@@ -15,7 +15,7 @@ import { existsSync } from "fs";
|
||||
import fs from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import * as ort from "onnxruntime-node";
|
||||
import { z } from "zod";
|
||||
import { z } from "zod/v4";
|
||||
import log from "../log-worker";
|
||||
import { messagePortMainEndpoint } from "../utils/comlink";
|
||||
import { wait } from "../utils/common";
|
||||
|
||||
@@ -24,17 +24,17 @@ export const clearStores = () => {
|
||||
* On macOS, `safeStorage` stores our data under a Keychain entry named
|
||||
* "<app-name> Safe Storage". In our case, "ente Safe Storage".
|
||||
*/
|
||||
export const saveMasterKeyB64 = (masterKeyB64: string) => {
|
||||
const encryptedKey = safeStorage.encryptString(masterKeyB64);
|
||||
const b64EncryptedKey = Buffer.from(encryptedKey).toString("base64");
|
||||
safeStorageStore.set("encryptionKey", b64EncryptedKey);
|
||||
export const saveMasterKeyInSafeStorage = (masterKey: string) => {
|
||||
const encryptedKeyBuffer = safeStorage.encryptString(masterKey);
|
||||
const encryptedKey = Buffer.from(encryptedKeyBuffer).toString("base64");
|
||||
safeStorageStore.set("encryptionKey", encryptedKey);
|
||||
};
|
||||
|
||||
export const masterKeyB64 = (): string | undefined => {
|
||||
const b64EncryptedKey = safeStorageStore.get("encryptionKey");
|
||||
if (!b64EncryptedKey) return undefined;
|
||||
const keyBuffer = Buffer.from(b64EncryptedKey, "base64");
|
||||
return safeStorage.decryptString(keyBuffer);
|
||||
export const masterKeyFromSafeStorage = (): string | undefined => {
|
||||
const encryptedKey = safeStorageStore.get("encryptionKey");
|
||||
if (!encryptedKey) return undefined;
|
||||
const encryptedKeyBuffer = Buffer.from(encryptedKey, "base64");
|
||||
return safeStorage.decryptString(encryptedKeyBuffer);
|
||||
};
|
||||
|
||||
export const lastShownChangelogVersion = (): number | undefined =>
|
||||
|
||||
@@ -28,6 +28,13 @@ export const createWatcher = (mainWindow: BrowserWindow) => {
|
||||
// Ask the watcher to wait for a the file size to stabilize before
|
||||
// telling us about a new file. By default, it waits for 2 seconds.
|
||||
awaitWriteFinish: true,
|
||||
// On macOS we start getting "EMFILE: too many open files" when watching
|
||||
// large folders. This is a known regression in Chokidar v4:
|
||||
// https://github.com/paulmillr/chokidar/issues/1385
|
||||
//
|
||||
// The recommended workaround for now is to enable usePolling. Since it
|
||||
// comes at a performance cost, we only do it where needed (macOS).
|
||||
...(process.platform == "darwin" ? { usePolling: true } : {}),
|
||||
});
|
||||
|
||||
watcher
|
||||
|
||||
@@ -113,10 +113,11 @@ const logout = () => {
|
||||
return ipcRenderer.invoke("logout");
|
||||
};
|
||||
|
||||
const masterKeyB64 = () => ipcRenderer.invoke("masterKeyB64");
|
||||
const masterKeyFromSafeStorage = () =>
|
||||
ipcRenderer.invoke("masterKeyFromSafeStorage");
|
||||
|
||||
const saveMasterKeyB64 = (masterKeyB64: string) =>
|
||||
ipcRenderer.invoke("saveMasterKeyB64", masterKeyB64);
|
||||
const saveMasterKeyInSafeStorage = (masterKey: string) =>
|
||||
ipcRenderer.invoke("saveMasterKeyInSafeStorage", masterKey);
|
||||
|
||||
const lastShownChangelogVersion = () =>
|
||||
ipcRenderer.invoke("lastShownChangelogVersion");
|
||||
@@ -358,8 +359,8 @@ contextBridge.exposeInMainWorld("electron", {
|
||||
selectDirectory,
|
||||
pathForFile,
|
||||
logout,
|
||||
masterKeyB64,
|
||||
saveMasterKeyB64,
|
||||
masterKeyFromSafeStorage,
|
||||
saveMasterKeyInSafeStorage,
|
||||
lastShownChangelogVersion,
|
||||
setLastShownChangelogVersion,
|
||||
isAutoLaunchEnabled,
|
||||
|
||||
@@ -392,78 +392,78 @@
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
"@typescript-eslint/eslint-plugin@8.33.0":
|
||||
version "8.33.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.33.0.tgz#51ed03649575ba51bcee7efdbfd85283249b5447"
|
||||
integrity sha512-CACyQuqSHt7ma3Ns601xykeBK/rDeZa3w6IS6UtMQbixO5DWy+8TilKkviGDH6jtWCo8FGRKEK5cLLkPvEammQ==
|
||||
"@typescript-eslint/eslint-plugin@8.33.1":
|
||||
version "8.33.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.33.1.tgz#532641b416ed2afd5be893cddb2a58e9cd1f7a3e"
|
||||
integrity sha512-TDCXj+YxLgtvxvFlAvpoRv9MAncDLBV2oT9Bd7YBGC/b/sEURoOYuIwLI99rjWOfY3QtDzO+mk0n4AmdFExW8A==
|
||||
dependencies:
|
||||
"@eslint-community/regexpp" "^4.10.0"
|
||||
"@typescript-eslint/scope-manager" "8.33.0"
|
||||
"@typescript-eslint/type-utils" "8.33.0"
|
||||
"@typescript-eslint/utils" "8.33.0"
|
||||
"@typescript-eslint/visitor-keys" "8.33.0"
|
||||
"@typescript-eslint/scope-manager" "8.33.1"
|
||||
"@typescript-eslint/type-utils" "8.33.1"
|
||||
"@typescript-eslint/utils" "8.33.1"
|
||||
"@typescript-eslint/visitor-keys" "8.33.1"
|
||||
graphemer "^1.4.0"
|
||||
ignore "^7.0.0"
|
||||
natural-compare "^1.4.0"
|
||||
ts-api-utils "^2.1.0"
|
||||
|
||||
"@typescript-eslint/parser@8.33.0":
|
||||
version "8.33.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.33.0.tgz#8e523c2b447ad7cd6ac91b719d8b37449481784d"
|
||||
integrity sha512-JaehZvf6m0yqYp34+RVnihBAChkqeH+tqqhS0GuX1qgPpwLvmTPheKEs6OeCK6hVJgXZHJ2vbjnC9j119auStQ==
|
||||
"@typescript-eslint/parser@8.33.1":
|
||||
version "8.33.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.33.1.tgz#ef9a5ee6aa37a6b4f46cc36d08a14f828238afe2"
|
||||
integrity sha512-qwxv6dq682yVvgKKp2qWwLgRbscDAYktPptK4JPojCwwi3R9cwrvIxS4lvBpzmcqzR4bdn54Z0IG1uHFskW4dA==
|
||||
dependencies:
|
||||
"@typescript-eslint/scope-manager" "8.33.0"
|
||||
"@typescript-eslint/types" "8.33.0"
|
||||
"@typescript-eslint/typescript-estree" "8.33.0"
|
||||
"@typescript-eslint/visitor-keys" "8.33.0"
|
||||
"@typescript-eslint/scope-manager" "8.33.1"
|
||||
"@typescript-eslint/types" "8.33.1"
|
||||
"@typescript-eslint/typescript-estree" "8.33.1"
|
||||
"@typescript-eslint/visitor-keys" "8.33.1"
|
||||
debug "^4.3.4"
|
||||
|
||||
"@typescript-eslint/project-service@8.33.0":
|
||||
version "8.33.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/project-service/-/project-service-8.33.0.tgz#71f37ef9010de47bf20963914743c5cbef851e08"
|
||||
integrity sha512-d1hz0u9l6N+u/gcrk6s6gYdl7/+pp8yHheRTqP6X5hVDKALEaTn8WfGiit7G511yueBEL3OpOEpD+3/MBdoN+A==
|
||||
"@typescript-eslint/project-service@8.33.1":
|
||||
version "8.33.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/project-service/-/project-service-8.33.1.tgz#c85e7d9a44d6a11fe64e73ac1ed47de55dc2bf9f"
|
||||
integrity sha512-DZR0efeNklDIHHGRpMpR5gJITQpu6tLr9lDJnKdONTC7vvzOlLAG/wcfxcdxEWrbiZApcoBCzXqU/Z458Za5Iw==
|
||||
dependencies:
|
||||
"@typescript-eslint/tsconfig-utils" "^8.33.0"
|
||||
"@typescript-eslint/types" "^8.33.0"
|
||||
"@typescript-eslint/tsconfig-utils" "^8.33.1"
|
||||
"@typescript-eslint/types" "^8.33.1"
|
||||
debug "^4.3.4"
|
||||
|
||||
"@typescript-eslint/scope-manager@8.33.0":
|
||||
version "8.33.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.33.0.tgz#459cf0c49d410800b1a023b973c62d699b09bf4c"
|
||||
integrity sha512-LMi/oqrzpqxyO72ltP+dBSP6V0xiUb4saY7WLtxSfiNEBI8m321LLVFU9/QDJxjDQG9/tjSqKz/E3380TEqSTw==
|
||||
"@typescript-eslint/scope-manager@8.33.1":
|
||||
version "8.33.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.33.1.tgz#d1e0efb296da5097d054bc9972e69878a2afea73"
|
||||
integrity sha512-dM4UBtgmzHR9bS0Rv09JST0RcHYearoEoo3pG5B6GoTR9XcyeqX87FEhPo+5kTvVfKCvfHaHrcgeJQc6mrDKrA==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "8.33.0"
|
||||
"@typescript-eslint/visitor-keys" "8.33.0"
|
||||
"@typescript-eslint/types" "8.33.1"
|
||||
"@typescript-eslint/visitor-keys" "8.33.1"
|
||||
|
||||
"@typescript-eslint/tsconfig-utils@8.33.0", "@typescript-eslint/tsconfig-utils@^8.33.0":
|
||||
version "8.33.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.33.0.tgz#316adab038bbdc43e448781d5a816c2973eab73e"
|
||||
integrity sha512-sTkETlbqhEoiFmGr1gsdq5HyVbSOF0145SYDJ/EQmXHtKViCaGvnyLqWFFHtEXoS0J1yU8Wyou2UGmgW88fEug==
|
||||
"@typescript-eslint/tsconfig-utils@8.33.1", "@typescript-eslint/tsconfig-utils@^8.33.1":
|
||||
version "8.33.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.33.1.tgz#7836afcc097a4657a5ed56670851a450d8b70ab8"
|
||||
integrity sha512-STAQsGYbHCF0/e+ShUQ4EatXQ7ceh3fBCXkNU7/MZVKulrlq1usH7t2FhxvCpuCi5O5oi1vmVaAjrGeL71OK1g==
|
||||
|
||||
"@typescript-eslint/type-utils@8.33.0":
|
||||
version "8.33.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.33.0.tgz#f06124b2d6db8a51b24990cb123c9543af93fef5"
|
||||
integrity sha512-lScnHNCBqL1QayuSrWeqAL5GmqNdVUQAAMTaCwdYEdWfIrSrOGzyLGRCHXcCixa5NK6i5l0AfSO2oBSjCjf4XQ==
|
||||
"@typescript-eslint/type-utils@8.33.1":
|
||||
version "8.33.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.33.1.tgz#d73ee1a29d8a0abe60d4abbff4f1d040f0de15fa"
|
||||
integrity sha512-1cG37d9xOkhlykom55WVwG2QRNC7YXlxMaMzqw2uPeJixBFfKWZgaP/hjAObqMN/u3fr5BrTwTnc31/L9jQ2ww==
|
||||
dependencies:
|
||||
"@typescript-eslint/typescript-estree" "8.33.0"
|
||||
"@typescript-eslint/utils" "8.33.0"
|
||||
"@typescript-eslint/typescript-estree" "8.33.1"
|
||||
"@typescript-eslint/utils" "8.33.1"
|
||||
debug "^4.3.4"
|
||||
ts-api-utils "^2.1.0"
|
||||
|
||||
"@typescript-eslint/types@8.33.0", "@typescript-eslint/types@^8.33.0":
|
||||
version "8.33.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.33.0.tgz#02a7dbba611a8abf1ad2a9e00f72f7b94b5ab0ee"
|
||||
integrity sha512-DKuXOKpM5IDT1FA2g9x9x1Ug81YuKrzf4mYX8FAVSNu5Wo/LELHWQyM1pQaDkI42bX15PWl0vNPt1uGiIFUOpg==
|
||||
"@typescript-eslint/types@8.33.1", "@typescript-eslint/types@^8.33.1":
|
||||
version "8.33.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.33.1.tgz#b693111bc2180f8098b68e9958cf63761657a55f"
|
||||
integrity sha512-xid1WfizGhy/TKMTwhtVOgalHwPtV8T32MS9MaH50Cwvz6x6YqRIPdD2WvW0XaqOzTV9p5xdLY0h/ZusU5Lokg==
|
||||
|
||||
"@typescript-eslint/typescript-estree@8.33.0":
|
||||
version "8.33.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.33.0.tgz#abcc1d3db75a8e9fd2e274ee8c4099fa2399abfd"
|
||||
integrity sha512-vegY4FQoB6jL97Tu/lWRsAiUUp8qJTqzAmENH2k59SJhw0Th1oszb9Idq/FyyONLuNqT1OADJPXfyUNOR8SzAQ==
|
||||
"@typescript-eslint/typescript-estree@8.33.1":
|
||||
version "8.33.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.33.1.tgz#d271beed470bc915b8764e22365d4925c2ea265d"
|
||||
integrity sha512-+s9LYcT8LWjdYWu7IWs7FvUxpQ/DGkdjZeE/GGulHvv8rvYwQvVaUZ6DE+j5x/prADUgSbbCWZ2nPI3usuVeOA==
|
||||
dependencies:
|
||||
"@typescript-eslint/project-service" "8.33.0"
|
||||
"@typescript-eslint/tsconfig-utils" "8.33.0"
|
||||
"@typescript-eslint/types" "8.33.0"
|
||||
"@typescript-eslint/visitor-keys" "8.33.0"
|
||||
"@typescript-eslint/project-service" "8.33.1"
|
||||
"@typescript-eslint/tsconfig-utils" "8.33.1"
|
||||
"@typescript-eslint/types" "8.33.1"
|
||||
"@typescript-eslint/visitor-keys" "8.33.1"
|
||||
debug "^4.3.4"
|
||||
fast-glob "^3.3.2"
|
||||
is-glob "^4.0.3"
|
||||
@@ -471,22 +471,22 @@
|
||||
semver "^7.6.0"
|
||||
ts-api-utils "^2.1.0"
|
||||
|
||||
"@typescript-eslint/utils@8.33.0":
|
||||
version "8.33.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.33.0.tgz#574ad5edee371077b9e28ca6fb804f2440f447c1"
|
||||
integrity sha512-lPFuQaLA9aSNa7D5u2EpRiqdAUhzShwGg/nhpBlc4GR6kcTABttCuyjFs8BcEZ8VWrjCBof/bePhP3Q3fS+Yrw==
|
||||
"@typescript-eslint/utils@8.33.1":
|
||||
version "8.33.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.33.1.tgz#ea22f40d3553da090f928cf17907e963643d4b96"
|
||||
integrity sha512-52HaBiEQUaRYqAXpfzWSR2U3gxk92Kw006+xZpElaPMg3C4PgM+A5LqwoQI1f9E5aZ/qlxAZxzm42WX+vn92SQ==
|
||||
dependencies:
|
||||
"@eslint-community/eslint-utils" "^4.7.0"
|
||||
"@typescript-eslint/scope-manager" "8.33.0"
|
||||
"@typescript-eslint/types" "8.33.0"
|
||||
"@typescript-eslint/typescript-estree" "8.33.0"
|
||||
"@typescript-eslint/scope-manager" "8.33.1"
|
||||
"@typescript-eslint/types" "8.33.1"
|
||||
"@typescript-eslint/typescript-estree" "8.33.1"
|
||||
|
||||
"@typescript-eslint/visitor-keys@8.33.0":
|
||||
version "8.33.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.33.0.tgz#fbae16fd3594531f8cad95d421125d634e9974fe"
|
||||
integrity sha512-7RW7CMYoskiz5OOGAWjJFxgb7c5UNjTG292gYhWeOAcFmYCtVCSqjqSBj5zMhxbXo2JOW95YYrUWJfU0zrpaGQ==
|
||||
"@typescript-eslint/visitor-keys@8.33.1":
|
||||
version "8.33.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.33.1.tgz#6c6e002c24d13211df3df851767f24dfdb4f42bc"
|
||||
integrity sha512-3i8NrFcZeeDHJ+7ZUuDkGT+UHq+XoFGsymNK2jZCOHcfEzRQ0BdpRtdpSx/Iyf3MHLWIcLS0COuOPibKQboIiQ==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "8.33.0"
|
||||
"@typescript-eslint/types" "8.33.1"
|
||||
eslint-visitor-keys "^4.2.0"
|
||||
|
||||
"@xmldom/xmldom@^0.8.8":
|
||||
@@ -1250,10 +1250,10 @@ electron-updater@^6.6.3:
|
||||
semver "^7.6.3"
|
||||
tiny-typed-emitter "^2.1.0"
|
||||
|
||||
electron@^36.3.2:
|
||||
version "36.3.2"
|
||||
resolved "https://registry.yarnpkg.com/electron/-/electron-36.3.2.tgz#4a60f95e8d3858d01570c03b58dc2fb2f17ee8b6"
|
||||
integrity sha512-v0/j7n22CL3OYv9BIhq6JJz2+e1HmY9H4bjTk8/WzVT9JwVX/T/21YNdR7xuQ6XDSEo9gP5JnqmjOamE+CUY8Q==
|
||||
electron@^36.4.0:
|
||||
version "36.4.0"
|
||||
resolved "https://registry.yarnpkg.com/electron/-/electron-36.4.0.tgz#9463bf5fa7565ae7be3a274f7f6a46359bcfe74d"
|
||||
integrity sha512-LLOOZEuW5oqvnjC7HBQhIqjIIJAZCIFjQxltQGLfEC7XFsBoZgQ3u3iFj+Kzw68Xj97u1n57Jdt7P98qLvUibQ==
|
||||
dependencies:
|
||||
"@electron/get" "^2.0.0"
|
||||
"@types/node" "^22.7.7"
|
||||
@@ -3251,14 +3251,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.33.0:
|
||||
version "8.33.0"
|
||||
resolved "https://registry.yarnpkg.com/typescript-eslint/-/typescript-eslint-8.33.0.tgz#89f733a90edc6abe0994b6130b964e781a1ba82f"
|
||||
integrity sha512-5YmNhF24ylCsvdNW2oJwMzTbaeO4bg90KeGtMjUw0AGtHksgEPLRTUil+coHwCfiu4QjVJFnjp94DmU6zV7DhQ==
|
||||
typescript-eslint@^8.33.1:
|
||||
version "8.33.1"
|
||||
resolved "https://registry.yarnpkg.com/typescript-eslint/-/typescript-eslint-8.33.1.tgz#d2d59c9b24afe1f903a855b02145802e4ae930ff"
|
||||
integrity sha512-AgRnV4sKkWOiZ0Kjbnf5ytTJXMUZQ0qhSVdQtDNYLPLnjsATEYhaO94GlRQwi4t4gO8FfjM6NnikHeKjUm8D7A==
|
||||
dependencies:
|
||||
"@typescript-eslint/eslint-plugin" "8.33.0"
|
||||
"@typescript-eslint/parser" "8.33.0"
|
||||
"@typescript-eslint/utils" "8.33.0"
|
||||
"@typescript-eslint/eslint-plugin" "8.33.1"
|
||||
"@typescript-eslint/parser" "8.33.1"
|
||||
"@typescript-eslint/utils" "8.33.1"
|
||||
|
||||
typescript@^5.4.3, typescript@^5.8.3:
|
||||
version "5.8.3"
|
||||
@@ -3421,7 +3421,7 @@ yocto-queue@^0.1.0:
|
||||
resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"
|
||||
integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==
|
||||
|
||||
zod@^3.25.48:
|
||||
version "3.25.48"
|
||||
resolved "https://registry.yarnpkg.com/zod/-/zod-3.25.48.tgz#6c2b536fbb519905e8f4a4ac58743de4d5331bb2"
|
||||
integrity sha512-0X1mz8FtgEIvaxGjdIImYpZEaZMrund9pGXm3M6vM7Reba0e2eI71KPjSCGXBfwKDPwPoywf6waUKc3/tFvX2Q==
|
||||
zod@^3.25.51:
|
||||
version "3.25.51"
|
||||
resolved "https://registry.yarnpkg.com/zod/-/zod-3.25.51.tgz#aa2cf648e54f6f060f139cf77b694819f63c9f3a"
|
||||
integrity sha512-TQSnBldh+XSGL+opiSIq0575wvDPqu09AqWe1F7JhUMKY+M91/aGlK4MhpVNO7MgYfHcVCB1ffwAUTJzllKJqg==
|
||||
|
||||
@@ -6,15 +6,16 @@ description: >
|
||||
|
||||
# Community
|
||||
|
||||
We are building Ente in the open with our community on
|
||||
[GitHub](https://github.com/ente-io/ente) and [Discord](https://ente.io/discord)
|
||||
|
||||
## Blog
|
||||
|
||||
To stay up to date with new product launches, and behind the scenes details of
|
||||
how we're building Ente, you can read our [blog](https://ente.io/blog) (or
|
||||
subscribe to it via [RSS](https://ente.io/blog/rss.xml))
|
||||
|
||||
## Community
|
||||
## Socials
|
||||
|
||||
Or if you'd just like to hang out, join our
|
||||
[Discord](https://discord.gg/z2YVKkycX3), follow us on
|
||||
[Twitter](https://twitter.com/enteio) or give us a shout out on
|
||||
You can also follow us on [Twitter](https://twitter.com/enteio) or toot to us on
|
||||
[Mastodon](https://mstdn.social/@ente)
|
||||
|
||||
@@ -5,7 +5,13 @@ description: Details about how to contribute to Ente
|
||||
|
||||
# Contributing
|
||||
|
||||
## Suggest a feature
|
||||
There are many ways to contribute to Ente. By spreading the word, engaging with
|
||||
our community, helping us with translations or documentation.
|
||||
|
||||
You can find our contribution guidelines
|
||||
[here](https://github.com/ente-io/ente/blob/main/CONTRIBUTING.md).
|
||||
|
||||
## Suggesting features
|
||||
|
||||
To suggest new features and/or offer your perspective on how we should design
|
||||
(planned and upcoming features), use our
|
||||
|
||||
@@ -6,8 +6,8 @@ description: Get help from Ente via customer support and community
|
||||
# Help
|
||||
|
||||
If you encounter any issues with any of the products that's not answered by our
|
||||
[documentation](/), please reach out to our Customer Support by sending an email
|
||||
to [support@ente.io](mailto:support@ente.io)
|
||||
[docs](/), please reach out to our team by sending an email to
|
||||
[support@ente.io](mailto:support@ente.io)
|
||||
|
||||
For community support, please post your queries on
|
||||
[Discord](https://discord.gg/z2YVKkycX3)
|
||||
|
||||
@@ -103,43 +103,19 @@ clicking on "Your map" under "Locations" on the search screen.
|
||||
On the login page, enter your email and click on Forgot Password. Then, enter
|
||||
your recovery key and create a new password.
|
||||
|
||||
# iOS Album Backup and Organization in Ente
|
||||
|
||||
### How does Ente handle photos that are part of multiple iOS albums?
|
||||
|
||||
When you select multiple albums for backup, Ente prioritizes uploading each
|
||||
photo to the album with the fewest photos. This means a photo will only be
|
||||
uploaded once, even if it exists in multiple albums on your device. If you
|
||||
create new albums on your device after the initial backup, those photos may not
|
||||
appear in the corresponding Ente album if they were already uploaded to a
|
||||
different album.
|
||||
|
||||
### Why don’t all photos from a new iOS album appear in the corresponding Ente album?
|
||||
|
||||
If you create a new album on your device after the initial backup, the photos in
|
||||
that album may have already been uploaded to another album in Ente. To fix this,
|
||||
go to the "On Device" album in Ente, select all photos, and manually add them to
|
||||
the corresponding album in Ente.
|
||||
|
||||
### What happens if I reorganize my photos in the iOS Photos app after backing up?
|
||||
|
||||
Reorganizing photos in the iOS Photos app (e.g., moving photos to new albums)
|
||||
won’t automatically reflect in Ente. You’ll need to manually add those photos to
|
||||
the corresponding albums in Ente to maintain consistency.
|
||||
|
||||
### Can I search for photos using the descriptions I’ve added?
|
||||
## Can I search for photos using the descriptions I’ve added?
|
||||
|
||||
Yes, descriptions are searchable, making it easier to find specific photos
|
||||
later. To do this, open the photo, tap the (i) button, and enter your
|
||||
description.
|
||||
|
||||
### How does the deduplication feature work on the desktop app?
|
||||
## How does the deduplication feature work on the desktop app?
|
||||
|
||||
If the app finds exact duplicates, it will show them in the deduplication. When
|
||||
you delete a duplicate, the app keeps one copy and creates a symlink for the
|
||||
other duplicate. This helps save storage space.
|
||||
|
||||
### What happens if I lose access to my email address? Can I use my recovery key to bypass email verification?
|
||||
## What happens if I lose access to my email address? Can I use my recovery key to bypass email verification?
|
||||
|
||||
No, the recovery key does not bypass email verification. For security reasons,
|
||||
we do not disable or bypass email verification unless the account owner reaches
|
||||
@@ -148,3 +124,29 @@ their account.
|
||||
|
||||
If you lose access to your email, please contact our support team at
|
||||
support@ente.io
|
||||
|
||||
---
|
||||
|
||||
# iOS Album Backup and Organization in Ente
|
||||
|
||||
## How does Ente handle photos that are part of multiple iOS albums?
|
||||
|
||||
When you select multiple albums for backup, Ente prioritizes uploading each
|
||||
photo to the album with the fewest photos. This means a photo will only be
|
||||
uploaded once, even if it exists in multiple albums on your device. If you
|
||||
create new albums on your device after the initial backup, those photos may not
|
||||
appear in the corresponding Ente album if they were already uploaded to a
|
||||
different album.
|
||||
|
||||
## Why don’t all photos from a new iOS album appear in the corresponding Ente album?
|
||||
|
||||
If you create a new album on your device after the initial backup, the photos in
|
||||
that album may have already been uploaded to another album in Ente. To fix this,
|
||||
go to the "On Device" album in Ente, select all photos, and manually add them to
|
||||
the corresponding album in Ente.
|
||||
|
||||
## What happens if I reorganize my photos in the iOS Photos app after backing up?
|
||||
|
||||
Reorganizing photos in the iOS Photos app (e.g., moving photos to new albums)
|
||||
won’t automatically reflect in Ente. You’ll need to manually add those photos to
|
||||
the corresponding albums in Ente to maintain consistency.
|
||||
|
||||
@@ -52,6 +52,11 @@ Ente also provides a tool for manual de-duplication in _Settings → Backup →
|
||||
Remove duplicates_. This is useful if you have an existing library with
|
||||
duplicates across different albums, but wish to keep only one copy.
|
||||
|
||||
During this operation, Ente will discard duplicates across all albums, retain a
|
||||
single copy, and add symlinks to this copy within all existing albums. So your
|
||||
existing album structure remains unchanged, while the space consumed by the
|
||||
duplicate data is freed up.
|
||||
|
||||
## Adding to Ente album creates symlinks
|
||||
|
||||
Note that once a file is in Ente, adding it to another Ente album will create a
|
||||
|
||||
@@ -53,7 +53,7 @@ analyzer:
|
||||
sort_child_properties_last: warning
|
||||
sort_pub_dependencies: warning
|
||||
library_private_types_in_public_api: warning
|
||||
constant_identifier_names: warning
|
||||
constant_identifier_names: ignore
|
||||
prefer_const_constructors: warning
|
||||
prefer_const_declarations: warning
|
||||
prefer_const_constructors_in_immutables: warning
|
||||
|
||||
@@ -153,6 +153,20 @@
|
||||
<meta-data android:name="android.appwidget.provider"
|
||||
android:resource="@xml/memory_widget" />
|
||||
</receiver>
|
||||
<receiver android:name="EnteAlbumsWidgetProvider" android:label="Albums" android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
||||
</intent-filter>
|
||||
<meta-data android:name="android.appwidget.provider"
|
||||
android:resource="@xml/albums_widget" />
|
||||
</receiver>
|
||||
<receiver android:name="EntePeopleWidgetProvider" android:label="People" android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
||||
</intent-filter>
|
||||
<meta-data android:name="android.appwidget.provider"
|
||||
android:resource="@xml/people_widget" />
|
||||
</receiver>
|
||||
<receiver android:exported="false" android:name="com.dexterous.flutterlocalnotifications.ScheduledNotificationReceiver" /> <!-- Needed for scheduling notifications -->
|
||||
<receiver android:exported="false" android:name="com.dexterous.flutterlocalnotifications.ScheduledNotificationBootReceiver"> <!-- Needed for scheduling notifications -->
|
||||
<intent-filter>
|
||||
|
||||
@@ -0,0 +1,195 @@
|
||||
package io.ente.photos
|
||||
|
||||
import android.appwidget.AppWidgetManager
|
||||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.BitmapFactory
|
||||
import android.graphics.drawable.BitmapDrawable
|
||||
import android.net.Uri
|
||||
import android.util.Log
|
||||
import android.view.View
|
||||
import android.widget.RemoteViews
|
||||
import androidx.core.content.ContextCompat
|
||||
import es.antonborri.home_widget.HomeWidgetLaunchIntent
|
||||
import es.antonborri.home_widget.HomeWidgetProvider
|
||||
import java.io.File
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.decodeFromString
|
||||
import kotlinx.serialization.json.Json
|
||||
|
||||
@Serializable
|
||||
data class AlbumsFileData(
|
||||
val title: String?,
|
||||
val subText: String?,
|
||||
val generatedId: Int?,
|
||||
val mainKey: String?
|
||||
)
|
||||
|
||||
class EnteAlbumsWidgetProvider : HomeWidgetProvider() {
|
||||
override fun onUpdate(
|
||||
context: Context,
|
||||
appWidgetManager: AppWidgetManager,
|
||||
appWidgetIds: IntArray,
|
||||
widgetData: SharedPreferences
|
||||
) {
|
||||
appWidgetIds.forEach { widgetId ->
|
||||
val views =
|
||||
RemoteViews(context.packageName, R.layout.albums_widget_layout)
|
||||
.apply {
|
||||
val totalAlbums =
|
||||
widgetData.getInt("totalAlbums", 0)
|
||||
var randomNumber = -1
|
||||
var imagePath: String? = null
|
||||
if (totalAlbums > 0) {
|
||||
randomNumber =
|
||||
(0 until totalAlbums!!).random()
|
||||
imagePath =
|
||||
widgetData.getString(
|
||||
"albums_widget_" +
|
||||
randomNumber,
|
||||
null
|
||||
)
|
||||
}
|
||||
var imageExists: Boolean = false
|
||||
if (imagePath != null) {
|
||||
val imageFile = File(imagePath)
|
||||
imageExists = imageFile.exists()
|
||||
}
|
||||
if (imageExists) {
|
||||
val data =
|
||||
widgetData.getString(
|
||||
"albums_widget_${randomNumber}_data",
|
||||
null
|
||||
)
|
||||
val decoded: AlbumsFileData? =
|
||||
data?.let {
|
||||
Json.decodeFromString<
|
||||
AlbumsFileData>(it)
|
||||
}
|
||||
val title = decoded?.title
|
||||
val subText = decoded?.subText
|
||||
val generatedId = decoded?.generatedId
|
||||
val mainKey = decoded?.mainKey
|
||||
|
||||
val deepLinkUri =
|
||||
Uri.parse(
|
||||
"albumwidget://message?generatedId=${generatedId}&mainKey=${mainKey}&homeWidget"
|
||||
)
|
||||
|
||||
val pendingIntent =
|
||||
HomeWidgetLaunchIntent.getActivity(
|
||||
context,
|
||||
MainActivity::class.java,
|
||||
deepLinkUri
|
||||
)
|
||||
|
||||
setOnClickPendingIntent(
|
||||
R.id.widget_container,
|
||||
pendingIntent
|
||||
)
|
||||
|
||||
Log.d(
|
||||
"EnteAlbumsWidgetProvider",
|
||||
"Image exists: $imagePath"
|
||||
)
|
||||
setViewVisibility(
|
||||
R.id.widget_img,
|
||||
View.VISIBLE
|
||||
)
|
||||
setViewVisibility(
|
||||
R.id.widget_subtitle,
|
||||
View.VISIBLE
|
||||
)
|
||||
setViewVisibility(
|
||||
R.id.widget_title,
|
||||
View.VISIBLE
|
||||
)
|
||||
setViewVisibility(
|
||||
R.id.widget_overlay,
|
||||
View.VISIBLE
|
||||
)
|
||||
setViewVisibility(
|
||||
R.id.widget_placeholder,
|
||||
View.GONE
|
||||
)
|
||||
setViewVisibility(
|
||||
R.id.widget_placeholder_text,
|
||||
View.GONE
|
||||
)
|
||||
setViewVisibility(
|
||||
R.id.widget_placeholder_container,
|
||||
View.GONE
|
||||
)
|
||||
|
||||
val bitmap: Bitmap =
|
||||
BitmapFactory.decodeFile(imagePath)
|
||||
setImageViewBitmap(R.id.widget_img, bitmap)
|
||||
setTextViewText(R.id.widget_title, title)
|
||||
setTextViewText(
|
||||
R.id.widget_subtitle,
|
||||
subText
|
||||
)
|
||||
} else {
|
||||
// Open App on Widget Click
|
||||
val pendingIntent =
|
||||
HomeWidgetLaunchIntent.getActivity(
|
||||
context,
|
||||
MainActivity::class.java
|
||||
)
|
||||
setOnClickPendingIntent(
|
||||
R.id.widget_container,
|
||||
pendingIntent
|
||||
)
|
||||
|
||||
Log.d(
|
||||
"EnteAlbumsWidgetProvider",
|
||||
"Image doesn't exists"
|
||||
)
|
||||
setViewVisibility(
|
||||
R.id.widget_img,
|
||||
View.GONE
|
||||
)
|
||||
setViewVisibility(
|
||||
R.id.widget_subtitle,
|
||||
View.GONE
|
||||
)
|
||||
setViewVisibility(
|
||||
R.id.widget_title,
|
||||
View.GONE
|
||||
)
|
||||
setViewVisibility(
|
||||
R.id.widget_overlay,
|
||||
View.GONE
|
||||
)
|
||||
setViewVisibility(
|
||||
R.id.widget_placeholder,
|
||||
View.VISIBLE
|
||||
)
|
||||
setViewVisibility(
|
||||
R.id.widget_placeholder_text,
|
||||
View.VISIBLE
|
||||
)
|
||||
setViewVisibility(
|
||||
R.id.widget_placeholder_container,
|
||||
View.VISIBLE
|
||||
)
|
||||
|
||||
val drawable =
|
||||
ContextCompat.getDrawable(
|
||||
context,
|
||||
R.drawable.ic_albums_widget
|
||||
)
|
||||
val bitmap =
|
||||
(drawable as BitmapDrawable).bitmap
|
||||
setImageViewBitmap(
|
||||
R.id.widget_placeholder,
|
||||
bitmap
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
appWidgetManager.updateAppWidget(widgetId, views)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -91,10 +91,6 @@ class EnteMemoryWidgetProvider : HomeWidgetProvider() {
|
||||
R.id.widget_img,
|
||||
View.VISIBLE
|
||||
)
|
||||
setViewVisibility(
|
||||
R.id.widget_placeholder_container,
|
||||
View.VISIBLE
|
||||
)
|
||||
setViewVisibility(
|
||||
R.id.widget_subtitle,
|
||||
View.VISIBLE
|
||||
@@ -148,10 +144,6 @@ class EnteMemoryWidgetProvider : HomeWidgetProvider() {
|
||||
R.id.widget_img,
|
||||
View.GONE
|
||||
)
|
||||
setViewVisibility(
|
||||
R.id.widget_placeholder_container,
|
||||
View.GONE
|
||||
)
|
||||
setViewVisibility(
|
||||
R.id.widget_subtitle,
|
||||
View.GONE
|
||||
@@ -181,7 +173,7 @@ class EnteMemoryWidgetProvider : HomeWidgetProvider() {
|
||||
ContextCompat.getDrawable(
|
||||
context,
|
||||
R.drawable
|
||||
.ic_home_widget_default
|
||||
.ic_memories_widget
|
||||
)
|
||||
val bitmap =
|
||||
(drawable as BitmapDrawable).bitmap
|
||||
|
||||
@@ -0,0 +1,195 @@
|
||||
package io.ente.photos
|
||||
|
||||
import android.appwidget.AppWidgetManager
|
||||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.BitmapFactory
|
||||
import android.graphics.drawable.BitmapDrawable
|
||||
import android.net.Uri
|
||||
import android.util.Log
|
||||
import android.view.View
|
||||
import android.widget.RemoteViews
|
||||
import androidx.core.content.ContextCompat
|
||||
import es.antonborri.home_widget.HomeWidgetLaunchIntent
|
||||
import es.antonborri.home_widget.HomeWidgetProvider
|
||||
import java.io.File
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.decodeFromString
|
||||
import kotlinx.serialization.json.Json
|
||||
|
||||
@Serializable
|
||||
data class PeopleFileData(
|
||||
val title: String?,
|
||||
val subText: String?,
|
||||
val generatedId: Int?,
|
||||
val mainKey: String?
|
||||
)
|
||||
|
||||
class EntePeopleWidgetProvider : HomeWidgetProvider() {
|
||||
override fun onUpdate(
|
||||
context: Context,
|
||||
appWidgetManager: AppWidgetManager,
|
||||
appWidgetIds: IntArray,
|
||||
widgetData: SharedPreferences
|
||||
) {
|
||||
appWidgetIds.forEach { widgetId ->
|
||||
val views =
|
||||
RemoteViews(context.packageName, R.layout.people_widget_layout)
|
||||
.apply {
|
||||
val totalPeople =
|
||||
widgetData.getInt("totalPeople", 0)
|
||||
var randomNumber = -1
|
||||
var imagePath: String? = null
|
||||
if (totalPeople > 0) {
|
||||
randomNumber =
|
||||
(0 until totalPeople!!).random()
|
||||
imagePath =
|
||||
widgetData.getString(
|
||||
"people_widget_" +
|
||||
randomNumber,
|
||||
null
|
||||
)
|
||||
}
|
||||
var imageExists: Boolean = false
|
||||
if (imagePath != null) {
|
||||
val imageFile = File(imagePath)
|
||||
imageExists = imageFile.exists()
|
||||
}
|
||||
if (imageExists) {
|
||||
val data =
|
||||
widgetData.getString(
|
||||
"people_widget_${randomNumber}_data",
|
||||
null
|
||||
)
|
||||
val decoded: PeopleFileData? =
|
||||
data?.let {
|
||||
Json.decodeFromString<
|
||||
PeopleFileData>(it)
|
||||
}
|
||||
val title = decoded?.title
|
||||
val subText = decoded?.subText
|
||||
val generatedId = decoded?.generatedId
|
||||
val mainKey = decoded?.mainKey
|
||||
|
||||
val deepLinkUri =
|
||||
Uri.parse(
|
||||
"peoplewidget://message?generatedId=${generatedId}&mainKey=${mainKey}&homeWidget"
|
||||
)
|
||||
|
||||
val pendingIntent =
|
||||
HomeWidgetLaunchIntent.getActivity(
|
||||
context,
|
||||
MainActivity::class.java,
|
||||
deepLinkUri
|
||||
)
|
||||
|
||||
setOnClickPendingIntent(
|
||||
R.id.widget_container,
|
||||
pendingIntent
|
||||
)
|
||||
|
||||
Log.d(
|
||||
"EntePeopleWidgetProvider",
|
||||
"Image exists: $imagePath"
|
||||
)
|
||||
setViewVisibility(
|
||||
R.id.widget_img,
|
||||
View.VISIBLE
|
||||
)
|
||||
setViewVisibility(
|
||||
R.id.widget_subtitle,
|
||||
View.VISIBLE
|
||||
)
|
||||
setViewVisibility(
|
||||
R.id.widget_title,
|
||||
View.VISIBLE
|
||||
)
|
||||
setViewVisibility(
|
||||
R.id.widget_overlay,
|
||||
View.VISIBLE
|
||||
)
|
||||
setViewVisibility(
|
||||
R.id.widget_placeholder,
|
||||
View.GONE
|
||||
)
|
||||
setViewVisibility(
|
||||
R.id.widget_placeholder_text,
|
||||
View.GONE
|
||||
)
|
||||
setViewVisibility(
|
||||
R.id.widget_placeholder_container,
|
||||
View.GONE
|
||||
)
|
||||
|
||||
val bitmap: Bitmap =
|
||||
BitmapFactory.decodeFile(imagePath)
|
||||
setImageViewBitmap(R.id.widget_img, bitmap)
|
||||
setTextViewText(R.id.widget_title, title)
|
||||
setTextViewText(
|
||||
R.id.widget_subtitle,
|
||||
subText
|
||||
)
|
||||
} else {
|
||||
// Open App on Widget Click
|
||||
val pendingIntent =
|
||||
HomeWidgetLaunchIntent.getActivity(
|
||||
context,
|
||||
MainActivity::class.java
|
||||
)
|
||||
setOnClickPendingIntent(
|
||||
R.id.widget_container,
|
||||
pendingIntent
|
||||
)
|
||||
|
||||
Log.d(
|
||||
"EntePeopleWidgetProvider",
|
||||
"Image doesn't exists"
|
||||
)
|
||||
setViewVisibility(
|
||||
R.id.widget_img,
|
||||
View.GONE
|
||||
)
|
||||
setViewVisibility(
|
||||
R.id.widget_subtitle,
|
||||
View.GONE
|
||||
)
|
||||
setViewVisibility(
|
||||
R.id.widget_title,
|
||||
View.GONE
|
||||
)
|
||||
setViewVisibility(
|
||||
R.id.widget_overlay,
|
||||
View.GONE
|
||||
)
|
||||
setViewVisibility(
|
||||
R.id.widget_placeholder,
|
||||
View.VISIBLE
|
||||
)
|
||||
setViewVisibility(
|
||||
R.id.widget_placeholder_text,
|
||||
View.VISIBLE
|
||||
)
|
||||
setViewVisibility(
|
||||
R.id.widget_placeholder_container,
|
||||
View.VISIBLE
|
||||
)
|
||||
|
||||
val drawable =
|
||||
ContextCompat.getDrawable(
|
||||
context,
|
||||
R.drawable.ic_people_widget
|
||||
)
|
||||
val bitmap =
|
||||
(drawable as BitmapDrawable).bitmap
|
||||
setImageViewBitmap(
|
||||
R.id.widget_placeholder,
|
||||
bitmap
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
appWidgetManager.updateAppWidget(widgetId, views)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 50 KiB |
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 31 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 25 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 82 KiB |
|
After Width: | Height: | Size: 33 KiB |
|
After Width: | Height: | Size: 46 KiB |
|
After Width: | Height: | Size: 57 KiB |
|
Before Width: | Height: | Size: 164 KiB |
|
After Width: | Height: | Size: 56 KiB |
|
After Width: | Height: | Size: 80 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 202 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 170 KiB |
|
After Width: | Height: | Size: 145 KiB |
@@ -0,0 +1,84 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:id="@+id/widget_container">
|
||||
|
||||
<!-- Main Image (if available) -->
|
||||
<ImageView
|
||||
android:id="@+id/widget_img"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:scaleType="centerCrop"
|
||||
android:visibility="gone" /> <!-- Initially hidden -->
|
||||
|
||||
<!-- Gradient Overlay for Text Readability -->
|
||||
<LinearLayout
|
||||
android:id="@+id/widget_overlay"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom"
|
||||
android:orientation="vertical"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:paddingBottom="16dp"
|
||||
android:paddingTop="4dp"
|
||||
android:background="@layout/gradient_overlay"
|
||||
android:visibility="gone"> <!-- Initially hidden, shown when image is available -->
|
||||
|
||||
<!-- Title -->
|
||||
<TextView
|
||||
android:id="@+id/widget_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text=""
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold"
|
||||
android:maxLines="1"
|
||||
android:ellipsize="end"
|
||||
android:visibility="gone"/>
|
||||
|
||||
<!-- Subtitle -->
|
||||
<TextView
|
||||
android:id="@+id/widget_subtitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text=""
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="12sp"
|
||||
android:maxLines="1"
|
||||
android:ellipsize="end"
|
||||
android:visibility="gone"/>
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Placeholder View (when no image available) -->
|
||||
<LinearLayout
|
||||
android:id="@+id/widget_placeholder_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:background="@color/widget_placeholder_bg">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/widget_placeholder"
|
||||
android:layout_width="120dp"
|
||||
android:layout_height="120dp"
|
||||
android:src="@drawable/ic_albums_widget"
|
||||
android:scaleType="fitCenter" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/widget_placeholder_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Go to Settings -> General to customise the widget"
|
||||
android:textSize="12sp"
|
||||
android:gravity="center_horizontal"
|
||||
android:textColor="@color/widget_text_color"
|
||||
android:paddingStart="8dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:layout_marginTop="12dp"/>
|
||||
</LinearLayout>
|
||||
|
||||
</FrameLayout>
|
||||
@@ -65,15 +65,15 @@
|
||||
android:id="@+id/widget_placeholder"
|
||||
android:layout_width="120dp"
|
||||
android:layout_height="120dp"
|
||||
android:src="@drawable/ic_home_widget_default"
|
||||
android:src="@drawable/ic_memories_widget"
|
||||
android:scaleType="fitCenter" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/widget_placeholder_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Your memories will appear here"
|
||||
android:textSize="14sp"
|
||||
android:text="Go to Settings -> General to customise the widget"
|
||||
android:textSize="12sp"
|
||||
android:gravity="center_horizontal"
|
||||
android:textColor="@color/widget_text_color"
|
||||
android:paddingStart="8dp"
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:id="@+id/widget_container">
|
||||
|
||||
<!-- Main Image (if available) -->
|
||||
<ImageView
|
||||
android:id="@+id/widget_img"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:scaleType="centerCrop"
|
||||
android:visibility="gone" /> <!-- Initially hidden -->
|
||||
|
||||
<!-- Gradient Overlay for Text Readability -->
|
||||
<LinearLayout
|
||||
android:id="@+id/widget_overlay"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom"
|
||||
android:orientation="vertical"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:paddingBottom="16dp"
|
||||
android:paddingTop="4dp"
|
||||
android:background="@layout/gradient_overlay"
|
||||
android:visibility="gone"> <!-- Initially hidden, shown when image is available -->
|
||||
|
||||
<!-- Title -->
|
||||
<TextView
|
||||
android:id="@+id/widget_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text=""
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold"
|
||||
android:maxLines="1"
|
||||
android:ellipsize="end"
|
||||
android:visibility="gone"/>
|
||||
|
||||
<!-- Subtitle -->
|
||||
<TextView
|
||||
android:id="@+id/widget_subtitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text=""
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="12sp"
|
||||
android:maxLines="1"
|
||||
android:ellipsize="end"
|
||||
android:visibility="gone"/>
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Placeholder View (when no image available) -->
|
||||
<LinearLayout
|
||||
android:id="@+id/widget_placeholder_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:background="@color/widget_placeholder_bg">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/widget_placeholder"
|
||||
android:layout_width="120dp"
|
||||
android:layout_height="120dp"
|
||||
android:src="@drawable/ic_people_widget"
|
||||
android:scaleType="fitCenter" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/widget_placeholder_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Go to Settings -> General to customise the widget"
|
||||
android:textSize="12sp"
|
||||
android:gravity="center_horizontal"
|
||||
android:textColor="@color/widget_text_color"
|
||||
android:paddingStart="8dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:layout_marginTop="12dp"/>
|
||||
</LinearLayout>
|
||||
|
||||
</FrameLayout>
|
||||
10
mobile/android/app/src/main/res/xml/albums_widget.xml
Normal file
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:minWidth="100dp"
|
||||
android:minHeight="100dp"
|
||||
android:updatePeriodMillis="900000"
|
||||
android:initialLayout="@layout/albums_widget_layout"
|
||||
android:previewImage="@drawable/albums_widget_preview"
|
||||
android:resizeMode="horizontal|vertical"
|
||||
android:widgetCategory="home_screen">
|
||||
</appwidget-provider>
|
||||
@@ -1,5 +1,5 @@
|
||||
<network-security-config>
|
||||
<base-config>
|
||||
<base-config cleartextTrafficPermitted="true">
|
||||
<trust-anchors>
|
||||
<certificates src="system" />
|
||||
<certificates src="user" />
|
||||
|
||||
10
mobile/android/app/src/main/res/xml/people_widget.xml
Normal file
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:minWidth="100dp"
|
||||
android:minHeight="100dp"
|
||||
android:updatePeriodMillis="900000"
|
||||
android:initialLayout="@layout/people_widget_layout"
|
||||
android:previewImage="@drawable/people_widget_preview"
|
||||
android:resizeMode="horizontal|vertical"
|
||||
android:widgetCategory="home_screen">
|
||||
</appwidget-provider>
|
||||
BIN
mobile/assets/2.0x/albums-widget-static.png
Normal file
|
After Width: | Height: | Size: 25 KiB |
BIN
mobile/assets/2.0x/memories-widget-static.png
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
mobile/assets/2.0x/people-widget-static.png
Normal file
|
After Width: | Height: | Size: 34 KiB |
BIN
mobile/assets/3.0x/albums-widget-static.png
Normal file
|
After Width: | Height: | Size: 38 KiB |
BIN
mobile/assets/3.0x/memories-widget-static.png
Normal file
|
After Width: | Height: | Size: 36 KiB |
BIN
mobile/assets/3.0x/people-widget-static.png
Normal file
|
After Width: | Height: | Size: 52 KiB |
BIN
mobile/assets/albums-widget-static.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
3
mobile/assets/icons/albums-widget-icon.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M16.668 3.33073V13.3307H6.66797V3.33073H16.668ZM16.668 1.66406H6.66797C5.7513 1.66406 5.0013 2.41406 5.0013 3.33073V13.3307C5.0013 14.2474 5.7513 14.9974 6.66797 14.9974H16.668C17.5846 14.9974 18.3346 14.2474 18.3346 13.3307V3.33073C18.3346 2.41406 17.5846 1.66406 16.668 1.66406ZM9.58464 9.7224L10.993 11.6057L13.0596 9.0224L15.8346 12.4974H7.5013L9.58464 9.7224ZM1.66797 4.9974V16.6641C1.66797 17.5807 2.41797 18.3307 3.33464 18.3307H15.0013V16.6641H3.33464V4.9974H1.66797Z" fill="black"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 604 B |
4
mobile/assets/icons/memories-widget-icon.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x="2" y="1" width="15" height="18" rx="1.4" stroke="black" stroke-width="1.4"/>
|
||||
<path d="M11.773 16.5745C11.5071 16.8091 11.0978 16.8091 10.8319 16.5711L10.7934 16.5371C8.95659 14.9221 7.75655 13.8646 7.80203 12.5454C7.82302 11.9674 8.12741 11.4132 8.62072 11.0868C9.54436 10.4748 10.6849 10.7604 11.3007 11.4608C11.9164 10.7604 13.057 10.4714 13.9807 11.0868C14.474 11.4132 14.7783 11.9674 14.7993 12.5454C14.8483 13.8646 13.6448 14.9221 11.808 16.5439L11.773 16.5745Z" fill="black"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 595 B |
3
mobile/assets/icons/past-year-memory-icon.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg width="21" height="20" viewBox="0 0 21 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M16.3333 3.33073H15.5V1.66406H13.8333V3.33073H7.16667V1.66406H5.5V3.33073H4.66667C3.74167 3.33073 3 4.08073 3 4.9974V16.6641C3 17.5807 3.74167 18.3307 4.66667 18.3307H16.3333C17.25 18.3307 18 17.5807 18 16.6641V4.9974C18 4.08073 17.25 3.33073 16.3333 3.33073ZM16.3333 16.6641H4.66667V8.33073H16.3333V16.6641ZM16.3333 6.66406H4.66667V4.9974H16.3333V6.66406ZM6.33333 9.9974H10.5V14.1641H6.33333V9.9974Z" fill="black"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 529 B |
3
mobile/assets/icons/people-widget-icon.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M9.9987 5.0026C10.9154 5.0026 11.6654 5.7526 11.6654 6.66927C11.6654 7.58594 10.9154 8.33594 9.9987 8.33594C9.08203 8.33594 8.33203 7.58594 8.33203 6.66927C8.33203 5.7526 9.08203 5.0026 9.9987 5.0026ZM9.9987 13.3359C12.2487 13.3359 14.832 14.4109 14.9987 15.0026H4.9987C5.19036 14.4026 7.75703 13.3359 9.9987 13.3359ZM9.9987 3.33594C8.15703 3.33594 6.66536 4.8276 6.66536 6.66927C6.66536 8.51094 8.15703 10.0026 9.9987 10.0026C11.8404 10.0026 13.332 8.51094 13.332 6.66927C13.332 4.8276 11.8404 3.33594 9.9987 3.33594ZM9.9987 11.6693C7.7737 11.6693 3.33203 12.7859 3.33203 15.0026V16.6693H16.6654V15.0026C16.6654 12.7859 12.2237 11.6693 9.9987 11.6693Z" fill="black"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 781 B |
11
mobile/assets/icons/smart-memory-icon.svg
Normal file
@@ -0,0 +1,11 @@
|
||||
<svg width="21" height="20" viewBox="0 0 21 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_38630_146929)">
|
||||
<path d="M11.1613 17.0685C10.5815 17.5949 9.68898 17.5949 9.10919 17.0609L9.02528 16.9846C5.0202 13.3609 2.40355 10.9884 2.50272 8.02846C2.5485 6.73158 3.2122 5.4881 4.28784 4.75574C6.30183 3.38257 8.78879 4.02339 10.1314 5.5949C11.4741 4.02339 13.9611 3.37494 15.975 4.75574C17.0507 5.4881 17.7144 6.73158 17.7602 8.02846C17.867 10.9884 15.2427 13.3609 11.2376 16.9998L11.1613 17.0685Z" stroke="black" stroke-width="1.5"/>
|
||||
<path d="M14.5938 0.34668C14.9459 -0.282495 15.8744 -0.282502 16.2266 0.34668L16.293 0.491211L16.9727 2.34277L18.8252 3.02344L18.9697 3.08984C19.5989 3.44199 19.5989 4.37051 18.9697 4.72266L18.8252 4.78906L16.9727 5.46875L16.293 7.32129C16.01 8.09135 14.971 8.13983 14.5938 7.46582L14.5273 7.32129L13.8467 5.46875L11.9951 4.78906C11.1738 4.4873 11.1738 3.3252 11.9951 3.02344L13.8467 2.34277L14.5273 0.491211L14.5938 0.34668Z" fill="black" stroke="#F5F5F5" stroke-width="1.25366"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_38630_146929">
|
||||
<rect width="20" height="20" fill="white" transform="translate(0.5)"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
BIN
mobile/assets/memories-widget-static.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
mobile/assets/people-widget-static.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
36
mobile/fastlane/metadata/android/sr/full_description.txt
Normal file
@@ -0,0 +1,36 @@
|
||||
ente is a simple app to backup and share your photos and videos.
|
||||
|
||||
If you've been looking for a privacy-friendly alternative to Google Photos, you've come to the right place. With ente, they are stored end-to-end encrypted (e2ee). This means that only you can view them.
|
||||
|
||||
We have open-source apps across Android, iOS, web and desktop, and your photos will seamlessly sync between all of them in an end-to-end encrypted (e2ee) manner.
|
||||
|
||||
ente also makes it simple to share your albums with your loved ones, even if they aren't on ente. You can share publicly viewable links, where they can view your album and collaborate by adding photos to it, even without an account or app.
|
||||
|
||||
Your encrypted data is replicated to 3 different locations, including a fall-out shelter in Paris. We take posterity seriously and make it easy to ensure that your memories outlive you.
|
||||
|
||||
We are here to make the safest photos app ever, come join our journey!
|
||||
|
||||
FEATURES
|
||||
- Original quality backups, because every pixel is important
|
||||
- Family plans, so you can share storage with your family
|
||||
- Collaborative albums, so you can pool together photos after a trip
|
||||
- Shared folders, in case you want your partner to enjoy your "Camera" clicks
|
||||
- Album links, that can be protected with a password
|
||||
- Ability to free up space, by removing files that have been safely backed up
|
||||
- Human support, because you're worth it
|
||||
- Descriptions, so you can caption your memories and find them easily
|
||||
- Image editor, to add finishing touches
|
||||
- Favorite, hide and relive your memories, for they are precious
|
||||
- One-click import from Google, Apple, your hard drive and more
|
||||
- Dark theme, because your photos look good in it
|
||||
- 2FA, 3FA, biometric auth
|
||||
- and a LOT more!
|
||||
|
||||
PERMISSIONS
|
||||
ente requests for certain permissions to serve the purpose of a photo storage provider, which can be reviewed here: https://github.com/ente-io/ente/blob/f-droid/mobile/android/permissions.md
|
||||
|
||||
PRICING
|
||||
We don't offer forever free plans, because it is important to us that we remain sustainable and withstand the test of time. Instead we offer affordable plans that you can freely share with your family. You can find more information at ente.io.
|
||||
|
||||
SUPPORT
|
||||
We take pride in offering human support. If you are our paid customer, you can reach out to team@ente.io and expect a response from our team within 24 hours.
|
||||
@@ -0,0 +1 @@
|
||||
ente is an end-to-end encrypted photo storage app
|
||||
1
mobile/fastlane/metadata/android/sr/title.txt
Normal file
@@ -0,0 +1 @@
|
||||
ente - encrypted photo storage
|
||||
33
mobile/fastlane/metadata/ios/sr/description.txt
Normal file
@@ -0,0 +1,33 @@
|
||||
Ente is a simple app to automatically backup and organize your photos and videos.
|
||||
|
||||
If you've been looking for a privacy-friendly alternative to preserve your memories, you've come to the right place. With Ente, they are stored end-to-end encrypted (e2ee). This means that only you can view them.
|
||||
|
||||
We have apps across all platforms, and your photos will seamlessly sync between all your devices in an end-to-end encrypted (e2ee) manner.
|
||||
|
||||
Ente also makes it simple to share your albums with your loved ones. You can either share them directly with other Ente users, end-to-end encrypted; or with publicly viewable links.
|
||||
|
||||
Your encrypted data is stored across multiple locations, including a fall-out shelter in Paris. We take posterity seriously and make it easy to ensure that your memories outlive you.
|
||||
|
||||
We are here to make the safest photos app ever, come join our journey!
|
||||
|
||||
FEATURES
|
||||
- Original quality backups, because every pixel is important
|
||||
- Family plans, so you can share storage with your family
|
||||
- Shared folders, in case you want your partner to enjoy your "Camera" clicks
|
||||
- Album links, that can be protected with a password and set to expire
|
||||
- Ability to free up space, by removing files that have been safely backed up
|
||||
- Image editor, to add finishing touches
|
||||
- Favorite, hide and relive your memories, for they are precious
|
||||
- One-click import from all major storage providers
|
||||
- Dark theme, because your photos look good in it
|
||||
- 2FA, 3FA, biometric auth
|
||||
- and a LOT more!
|
||||
|
||||
PRICING
|
||||
We don't offer forever free plans, because it is important to us that we remain sustainable and withstand the test of time. Instead we offer affordable plans that you can freely share with your family. You can find more information at ente.io.
|
||||
|
||||
SUPPORT
|
||||
We take pride in offering human support. If you are our paid customer, you can reach out to team@ente.io and expect a response from our team within 24 hours.
|
||||
|
||||
TERMS
|
||||
https://ente.io/terms
|
||||
1
mobile/fastlane/metadata/ios/sr/keywords.txt
Normal file
@@ -0,0 +1 @@
|
||||
photos,photography,family,privacy,cloud,backup,videos,photo,encryption,storage,album,alternative
|
||||
1
mobile/fastlane/metadata/ios/sr/name.txt
Normal file
@@ -0,0 +1 @@
|
||||
Ente Photos
|
||||
1
mobile/fastlane/metadata/ios/sr/subtitle.txt
Normal file
@@ -0,0 +1 @@
|
||||
Encrypted photo storage
|
||||
30
mobile/fastlane/metadata/playstore/sr/full_description.txt
Normal file
@@ -0,0 +1,30 @@
|
||||
Ente is a simple app to automatically backup and organize your photos and videos.
|
||||
|
||||
If you've been looking for a privacy-friendly alternative to preserve your memories, you've come to the right place. With Ente, they are stored end-to-end encrypted (e2ee). This means that only you can view them.
|
||||
|
||||
We have apps across Android, iOS, web and Desktop, and your photos will seamlessly sync between all your devices in an end-to-end encrypted (e2ee) manner.
|
||||
|
||||
Ente also makes it simple to share your albums with your loved ones. You can either share them directly with other Ente users, end-to-end encrypted; or with publicly viewable links.
|
||||
|
||||
Your encrypted data is stored across multiple locations, including a fall-out shelter in Paris. We take posterity seriously and make it easy to ensure that your memories outlive you.
|
||||
|
||||
We are here to make the safest photos app ever, come join our journey!
|
||||
|
||||
✨ FEATURES
|
||||
- Original quality backups, because every pixel is important
|
||||
- Family plans, so you can share storage with your family
|
||||
- Shared folders, in case you want your partner to enjoy your "Camera" clicks
|
||||
- Album links, that can be protected with a password and set to expire
|
||||
- Ability to free up space, by removing files that have been safely backed up
|
||||
- Image editor, to add finishing touches
|
||||
- Favorite, hide and relive your memories, for they are precious
|
||||
- One-click import from Google, Apple, your hard drive and more
|
||||
- Dark theme, because your photos look good in it
|
||||
- 2FA, 3FA, biometric auth
|
||||
- and a LOT more!
|
||||
|
||||
💲 PRICING
|
||||
We don't offer forever free plans, because it is important to us that we remain sustainable and withstand the test of time. Instead we offer affordable plans that you can freely share with your family. You can find more information at ente.io.
|
||||
|
||||
🙋 SUPPORT
|
||||
We take pride in offering human support. If you are our paid customer, you can reach out to team@ente.io and expect a response from our team within 24 hours.
|
||||
@@ -0,0 +1 @@
|
||||
Encrypted photo storage - backup, organize and share your photos and videos
|
||||
1
mobile/fastlane/metadata/playstore/sr/title.txt
Normal file
@@ -0,0 +1 @@
|
||||
Ente Photos
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
BIN
mobile/ios/EnteAlbumWidget/Assets.xcassets/AlbumsWidgetDefault.imageset/AlbumsWidgetDefault.png
vendored
Normal file
|
After Width: | Height: | Size: 20 KiB |
21
mobile/ios/EnteAlbumWidget/Assets.xcassets/AlbumsWidgetDefault.imageset/Contents.json
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "AlbumsWidgetDefault.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
BIN
mobile/ios/EnteAlbumWidget/Assets.xcassets/AlbumsWidgetPreview.imageset/AlbumsWidgetPreview.png
vendored
Normal file
|
After Width: | Height: | Size: 186 KiB |
21
mobile/ios/EnteAlbumWidget/Assets.xcassets/AlbumsWidgetPreview.imageset/Contents.json
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "AlbumsWidgetPreview.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
6
mobile/ios/EnteAlbumWidget/Assets.xcassets/Contents.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"platform" : "ios",
|
||||
"size" : "1024x1024"
|
||||
},
|
||||
{
|
||||
"appearances" : [
|
||||
{
|
||||
"appearance" : "luminosity",
|
||||
"value" : "dark"
|
||||
}
|
||||
],
|
||||
"idiom" : "universal",
|
||||
"platform" : "ios",
|
||||
"size" : "1024x1024"
|
||||
},
|
||||
{
|
||||
"appearances" : [
|
||||
{
|
||||
"appearance" : "luminosity",
|
||||
"value" : "tinted"
|
||||
}
|
||||
],
|
||||
"idiom" : "universal",
|
||||
"platform" : "ios",
|
||||
"size" : "1024x1024"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"info": {
|
||||
"author": "xcode",
|
||||
"version": 1
|
||||
}
|
||||
}
|
||||
261
mobile/ios/EnteAlbumWidget/EnteAlbumWidget.swift
Normal file
@@ -0,0 +1,261 @@
|
||||
//
|
||||
// EnteAlbumWidget.swift
|
||||
// EnteAlbumWidget
|
||||
|
||||
import SwiftUI
|
||||
import UIKit
|
||||
import WidgetKit
|
||||
|
||||
private let widgetGroupId = "group.io.ente.frame.EnteMemoryWidget"
|
||||
|
||||
struct Provider: TimelineProvider {
|
||||
let minutes = 15
|
||||
let data = UserDefaults(suiteName: widgetGroupId)
|
||||
|
||||
func placeholder(in _: Context) -> FileEntry {
|
||||
FileEntry(
|
||||
date: Date(), index: nil, imageData: nil, title: "Title", subTitle: "Sub Title",
|
||||
generatedId: nil, mainKey: nil)
|
||||
}
|
||||
|
||||
func getSnapshot(in _: Context, completion: @escaping (FileEntry) -> Void) {
|
||||
let entry = FileEntry(
|
||||
date: Date(), index: -2, imageData: nil, title: "Favorites",
|
||||
subTitle: "May 3, 2021",
|
||||
generatedId: nil, mainKey: nil)
|
||||
completion(entry)
|
||||
}
|
||||
|
||||
func getTimeline(in _: Context, completion: @escaping (Timeline<Entry>) -> Void) {
|
||||
var entries: [FileEntry] = []
|
||||
|
||||
// Generate a timeline consisting of five entries an hour apart, starting from the current date.
|
||||
let currentDate = Calendar.current.nextDate(
|
||||
after: Date(), matching: DateComponents(second: 0), matchingPolicy: .nextTime,
|
||||
direction: .backward
|
||||
)!
|
||||
|
||||
var totalAlbums =
|
||||
data?.integer(forKey: "totalAlbums")
|
||||
|
||||
if totalAlbums != nil && totalAlbums! > 0 {
|
||||
let count = totalAlbums! > 5 ? 5 : totalAlbums
|
||||
for offset in 0..<count! {
|
||||
let randomInt = Int.random(in: 0..<totalAlbums!)
|
||||
let entryDate = Calendar.current.date(
|
||||
byAdding: .minute, value: minutes * offset, to: currentDate
|
||||
)!
|
||||
let imageData =
|
||||
data?.string(forKey: "albums_widget_" + String(randomInt))
|
||||
let dictionary = data?.dictionary(
|
||||
forKey: "albums_widget_" + String(randomInt) + "_data")
|
||||
let generatedId = dictionary?["generatedId"] as? Int
|
||||
let subTitle = dictionary?["subText"] as? String
|
||||
let title = dictionary?["title"] as? String
|
||||
let mainKey = dictionary?["mainKey"] as? String
|
||||
|
||||
let entry = FileEntry(
|
||||
date: entryDate, index: randomInt, imageData: imageData, title: title,
|
||||
subTitle: subTitle, generatedId: generatedId, mainKey: mainKey)
|
||||
entries.append(entry)
|
||||
}
|
||||
} else {
|
||||
let entry = FileEntry(
|
||||
date: Date(), index: -1, imageData: nil, title: nil, subTitle: nil,
|
||||
generatedId: nil, mainKey: nil
|
||||
)
|
||||
entries.append(entry)
|
||||
}
|
||||
|
||||
let timeline = Timeline(entries: entries, policy: .atEnd)
|
||||
completion(timeline)
|
||||
}
|
||||
|
||||
// func relevances() async -> WidgetRelevances<Void> {
|
||||
// // Generate a list containing the contexts this widget is relevant in.
|
||||
// }
|
||||
}
|
||||
|
||||
struct FileEntry: TimelineEntry {
|
||||
let date: Date
|
||||
let index: Int?
|
||||
let imageData: String?
|
||||
let title: String?
|
||||
let subTitle: String?
|
||||
var generatedId: Int?
|
||||
var mainKey: String?
|
||||
}
|
||||
|
||||
struct EnteAlbumWidgetEntryView: View {
|
||||
var entry: Provider.Entry
|
||||
let data = UserDefaults.init(suiteName: widgetGroupId)
|
||||
|
||||
var body: some View {
|
||||
GeometryReader { geometry in
|
||||
ZStack {
|
||||
if let imageData = entry.imageData,
|
||||
let uiImage = UIImage(contentsOfFile: imageData)
|
||||
{
|
||||
Image(uiImage: uiImage)
|
||||
.resizable()
|
||||
.backwardWidgetFullColorRenderingMode()
|
||||
.aspectRatio(contentMode: .fill)
|
||||
.frame(width: geometry.size.width, height: geometry.size.height)
|
||||
.overlay(
|
||||
LinearGradient(
|
||||
gradient: Gradient(colors: [Color.black.opacity(0.7), Color.clear]),
|
||||
startPoint: .bottom,
|
||||
endPoint: .top
|
||||
)
|
||||
|
||||
.frame(height: geometry.size.height * 0.4)
|
||||
.frame(maxHeight: .infinity, alignment: .bottom)
|
||||
.backwardWidgetAccentable(true)
|
||||
)
|
||||
.overlay(
|
||||
VStack(alignment: .leading, spacing: 2) {
|
||||
Text(entry.title ?? "").font(
|
||||
.custom("Inter", size: 14, relativeTo: .caption)
|
||||
) // Custom with fallback
|
||||
.bold()
|
||||
.foregroundStyle(.white)
|
||||
.shadow(radius: 20)
|
||||
Text(entry.subTitle ?? "")
|
||||
.font(.custom("Inter", size: 12, relativeTo: .caption2))
|
||||
.foregroundStyle(.white)
|
||||
.shadow(radius: 20)
|
||||
}
|
||||
.padding(.leading, geometry.size.width * 0.05)
|
||||
.padding(.bottom, geometry.size.height * 0.05),
|
||||
alignment: .bottomLeading
|
||||
)
|
||||
} else if entry.index == -2 {
|
||||
if let uiImage = UIImage(named: "AlbumsWidgetPreview") {
|
||||
Image(uiImage: uiImage)
|
||||
.resizable()
|
||||
.backwardWidgetFullColorRenderingMode()
|
||||
.aspectRatio(contentMode: .fill)
|
||||
.frame(width: geometry.size.width, height: geometry.size.height)
|
||||
.overlay(
|
||||
LinearGradient(
|
||||
gradient: Gradient(colors: [
|
||||
Color.black.opacity(0.7), Color.clear,
|
||||
]),
|
||||
startPoint: .bottom,
|
||||
endPoint: .top
|
||||
)
|
||||
|
||||
.frame(height: geometry.size.height * 0.4)
|
||||
.frame(maxHeight: .infinity, alignment: .bottom)
|
||||
.backwardWidgetAccentable(true)
|
||||
)
|
||||
.overlay(
|
||||
VStack(alignment: .leading, spacing: 2) {
|
||||
Text(entry.title ?? "").font(
|
||||
.custom("Inter", size: 14, relativeTo: .caption)
|
||||
) // Custom with fallback
|
||||
.bold()
|
||||
.foregroundStyle(.white)
|
||||
.shadow(radius: 20)
|
||||
Text(entry.subTitle ?? "")
|
||||
.font(.custom("Inter", size: 12, relativeTo: .caption2))
|
||||
.foregroundStyle(.white)
|
||||
.shadow(radius: 20)
|
||||
}
|
||||
.padding(.leading, geometry.size.width * 0.05)
|
||||
.padding(.bottom, geometry.size.height * 0.05),
|
||||
alignment: .bottomLeading
|
||||
)
|
||||
}
|
||||
} else if let uiImage = UIImage(named: "AlbumsWidgetDefault") {
|
||||
VStack(spacing: 8) {
|
||||
Spacer()
|
||||
Image(uiImage: uiImage)
|
||||
.resizable()
|
||||
.backwardWidgetFullColorRenderingMode()
|
||||
.aspectRatio(contentMode: .fit)
|
||||
.padding(8)
|
||||
|
||||
Text("Go to Settings -> General to customise the widget")
|
||||
.font(.custom("Inter", size: 12, relativeTo: .caption))
|
||||
.foregroundStyle(.white) // Tint-aware color
|
||||
.multilineTextAlignment(.center)
|
||||
.padding(.bottom, 12)
|
||||
.padding(.horizontal, 8)
|
||||
.backwardWidgetAccentable(true)
|
||||
Spacer()
|
||||
}
|
||||
.frame(width: geometry.size.width, height: geometry.size.height)
|
||||
} else {
|
||||
Color.gray
|
||||
}
|
||||
}
|
||||
.clipped()
|
||||
.edgesIgnoringSafeArea(.all)
|
||||
.widgetURL(
|
||||
URL(
|
||||
string:
|
||||
"albumwidget://message?generatedId=\(entry.generatedId != nil ? String(entry.generatedId!) : "nan")&mainKey=\(entry.mainKey != nil ? entry.mainKey! : "nan")&homeWidget"
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct EnteAlbumWidget: Widget {
|
||||
let kind: String = "EnteAlbumWidget"
|
||||
|
||||
var body: some WidgetConfiguration {
|
||||
StaticConfiguration(kind: kind, provider: Provider()) { entry in
|
||||
if #available(iOS 17.0, *) {
|
||||
EnteAlbumWidgetEntryView(entry: entry)
|
||||
.containerBackground(.fill.tertiary, for: .widget)
|
||||
} else {
|
||||
EnteAlbumWidgetEntryView(entry: entry)
|
||||
.padding()
|
||||
.background()
|
||||
}
|
||||
}
|
||||
.configurationDisplayName("Albums")
|
||||
.description("See photos from selected albums including your favorites")
|
||||
.contentMarginsDisabled()
|
||||
}
|
||||
}
|
||||
|
||||
#Preview(as: .systemSmall) {
|
||||
EnteAlbumWidget()
|
||||
} timeline: {
|
||||
FileEntry(
|
||||
date: .now, index: -2, imageData: nil, title: nil, subTitle: nil, generatedId: nil,
|
||||
mainKey: nil)
|
||||
FileEntry(
|
||||
date: .now, index: -2, imageData: nil, title: nil, subTitle: nil, generatedId: nil,
|
||||
mainKey: nil)
|
||||
}
|
||||
|
||||
extension View {
|
||||
@ViewBuilder
|
||||
func backwardWidgetAccentable(_ accentable: Bool = true) -> some View {
|
||||
if #available(iOS 16.0, *) {
|
||||
self.widgetAccentable(accentable)
|
||||
} else {
|
||||
self
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension Image {
|
||||
@ViewBuilder
|
||||
func backwardWidgetAccentedRenderingMode(_ isAccentedRenderingMode: Bool = true) -> some View {
|
||||
if #available(iOS 18.0, *) {
|
||||
self.widgetAccentedRenderingMode(isAccentedRenderingMode ? .accented : .fullColor)
|
||||
} else {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
func backwardWidgetFullColorRenderingMode() -> some View {
|
||||
backwardWidgetAccentedRenderingMode(false)
|
||||
}
|
||||
}
|
||||
17
mobile/ios/EnteAlbumWidget/EnteAlbumWidgetBundle.swift
Normal file
@@ -0,0 +1,17 @@
|
||||
//
|
||||
// EnteAlbumWidgetBundle.swift
|
||||
// EnteAlbumWidget
|
||||
//
|
||||
// Created by Prateek Sunal on 5/15/25.
|
||||
// Copyright © 2025 The Chromium Authors. All rights reserved.
|
||||
//
|
||||
|
||||
import WidgetKit
|
||||
import SwiftUI
|
||||
|
||||
@main
|
||||
struct EnteAlbumWidgetBundle: WidgetBundle {
|
||||
var body: some Widget {
|
||||
EnteAlbumWidget()
|
||||
}
|
||||
}
|
||||
11
mobile/ios/EnteAlbumWidget/Info.plist
Normal file
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>NSExtension</key>
|
||||
<dict>
|
||||
<key>NSExtensionPointIdentifier</key>
|
||||
<string>com.apple.widgetkit-extension</string>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
||||
10
mobile/ios/EnteAlbumWidgetExtension.entitlements
Normal file
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.security.application-groups</key>
|
||||
<array>
|
||||
<string>group.io.ente.frame.EnteMemoryWidget</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
21
mobile/ios/EnteMemoryWidget/Assets.xcassets/MemoriesWidgetDefault.imageset/Contents.json
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "MemoriesWidgetDefault.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
BIN
mobile/ios/EnteMemoryWidget/Assets.xcassets/MemoriesWidgetDefault.imageset/MemoriesWidgetDefault.png
vendored
Normal file
|
After Width: | Height: | Size: 20 KiB |
21
mobile/ios/EnteMemoryWidget/Assets.xcassets/MemoriesWidgetPreview.imageset/Contents.json
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "MemoriesWidgetPreview.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
BIN
mobile/ios/EnteMemoryWidget/Assets.xcassets/MemoriesWidgetPreview.imageset/MemoriesWidgetPreview.png
vendored
Normal file
|
After Width: | Height: | Size: 132 KiB |
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||