Compare commits

...

335 Commits

Author SHA1 Message Date
Neeraj
d95df66b9c [auth] Fix deeplink issue (#4818)
## Description
Also
- Remove logo from privacy screen
- Fix bug while deleting items from trash
## Tests
2025-01-22 14:45:21 +05:30
Neeraj Gupta
58cb9f480f Clean up 2025-01-22 14:42:23 +05:30
Neeraj Gupta
14e413effa [auth] Bump version 2025-01-22 14:41:36 +05:30
Neeraj Gupta
728a8c4976 Merge remote-tracking branch 'origin/main' into auth_fixes 2025-01-22 14:41:22 +05:30
Neeraj Gupta
dc779ae53f [auth] Opt out of flutter default deeplinking 2025-01-22 14:40:28 +05:30
Neeraj Gupta
ab5bda8074 [auth] Remove privacy screen image 2025-01-22 14:39:33 +05:30
Neeraj Gupta
2fc8d6e0c4 [auth] Handle multiple invokation of same deeplink 2025-01-22 14:35:03 +05:30
Neeraj Gupta
3fa18b3560 [auth] Handle deeplink in offline mode 2025-01-22 14:30:04 +05:30
Neeraj Gupta
a15556264a [auth]Skip wait for online sync while parsing otpauth deeplink 2025-01-22 14:23:31 +05:30
Manav Rathi
267f54d943 [web] Fix link default prop for the (WIP) light mode (#4817)
This was causing an exception when opening screens with the <Link>
2025-01-22 14:20:13 +05:30
Manav Rathi
1015c87dd2 Fix link default prop 2025-01-22 14:14:18 +05:30
Neeraj Gupta
a71c284708 [auth] Fix bug in trash deletion 2025-01-22 13:55:22 +05:30
Neeraj Gupta
89e1efbde4 [auth] Opt out of flutter deeplink for ios 2025-01-22 13:54:57 +05:30
Manav Rathi
5e317b9f37 Increase hover opacity for light mode 2025-01-22 13:37:55 +05:30
Manav Rathi
6a4e992843 [desktop] Attempt to fix macOS universal build after electron builder update (#4816)
CI failures since updating Electron building (and Electron):

• packaging platform=darwin arch=arm64 electron=34.0.0
appOutDir=dist/mac-universal-arm64-temp
• packaging platform=darwin arch=universal electron=34.0.0
appOutDir=dist/mac-universal
⨯ pattern is too long failedTask=build stackTrace=TypeError: pattern is
too long
2025-01-22 13:18:02 +05:30
Manav Rathi
6e5e28d2bd [desktop] Attempt to fix macOS universal build after electron builder update
CI failures since updating Electron building (and Electron):

 • packaging       platform=darwin arch=arm64 electron=34.0.0 appOutDir=dist/mac-universal-arm64-temp
  • packaging       platform=darwin arch=universal electron=34.0.0 appOutDir=dist/mac-universal
  ⨯ pattern is too long  failedTask=build stackTrace=TypeError: pattern is too long
2025-01-22 13:16:30 +05:30
Manav Rathi
fcb7221820 [desktop] Fix incomplete build being generated - Take 2 (#4815)
These issues only surface when running on the CI, hence the PR splurge.
2025-01-22 13:01:55 +05:30
Manav Rathi
4abfb5b8bd Don't return falsey 2025-01-22 12:59:54 +05:30
Manav Rathi
09b15d8645 [desktop] Fix incomplete build being generated (#4813)
...because of returning false from our build hook.

Also update the MetaInfo to avoid duplicating.
2025-01-22 12:43:17 +05:30
Manav Rathi
e0eae10007 Use URL instead of repeating contents 2025-01-22 12:41:39 +05:30
Manav Rathi
47ec5e78c0 [desktop] Fix incomplete build being generated
...because of returning false from our build hook.
2025-01-22 12:39:33 +05:30
Neeraj
07f55020df [auth] Bump version v4.3.0 (#4812)
## Description

## Tests
2025-01-22 11:40:50 +05:30
Neeraj Gupta
d345de9ff3 [auth] Bump version v4.3.0 2025-01-22 11:36:23 +05:30
Neeraj
3bbb3c5767 [auth] Revert Notification banner (#4806) 2025-01-22 11:29:51 +05:30
Manav Rathi
7ac322b799 [desktop] Update build for latest electron builder (#4811)
Since the eb update, the CI job fails with errors like

unable to copy, file is symlinked outside the package
source=out/404.html
realPathFile=/Users/runner/work/photos-desktop/photos-desktop/web/apps/photos/out/404.html

Error: Cannot copy file (xxx.js) symlinked to file (xxx.js) outside the
package as that violates asar security integrity
at writeFileOrProcessSymlink
(/Users/runner/work/photos-desktop/photos-desktop/desktop/node_modules/app-builder-lib/src/asar/asarUtil.ts:126:15)
2025-01-22 09:43:55 +05:30
Manav Rathi
1e8750c330 [desktop] Update build for latest electron builder
Since the eb update, the CI job fails with errors like

    unable to copy, file is symlinked outside the package  source=out/404.html realPathFile=/Users/runner/work/photos-desktop/photos-desktop/web/apps/photos/out/404.html

    Error: Cannot copy file (xxx.js) symlinked to file (xxx.js) outside the package as that violates asar security integrity
      at writeFileOrProcessSymlink (/Users/runner/work/photos-desktop/photos-desktop/desktop/node_modules/app-builder-lib/src/asar/asarUtil.ts:126:15)
2025-01-22 09:42:08 +05:30
Manav Rathi
07786e3162 [desktop] Depedencies upgrade (#4809)
In particular,

* Electron 34 is needed to fix the Flatpak file picker issue -
  "Fixed file chooser dialogs for flaptak applications. #44681"
  https://github.com/electron/electron/pull/44681

* Electron builder 26 is needed for the FPM app armour profiles

https://github.com/electron-userland/electron-builder/issues/8635#issuecomment-2462586534
2025-01-22 08:17:33 +05:30
Manav Rathi
d413c1d8dc LF 2025-01-22 08:16:23 +05:30
Manav Rathi
0466067c55 [desktop] Depedencies upgrade
In particular,

* Electron 34 is needed to fix the Flatpak file picker issue -
  "Fixed file chooser dialogs for flaptak applications. #44681"
  https://github.com/electron/electron/pull/44681

* Electron builder 26 is needed for the FPM app armour profiles
  https://github.com/electron-userland/electron-builder/issues/8635#issuecomment-2462586534
2025-01-22 08:08:30 +05:30
Manav Rathi
d8b7d76d55 [desktop] IM 7 - Handle CI rebuilds, and add windows extension (#4808)
- CI builds both arch binaries in one go, so the singular yarn install
hook is not enough
- Without the extension windows doesn't run it
2025-01-22 07:54:34 +05:30
Manav Rathi
b1c62f6c93 [desktop] IM 7 - Handle CI rebuilds, and add windows extension
- CI builds both arch binaries in one go, so the singular yarn install hook is not enough
- Without the extension windows doesn't run it
2025-01-22 07:49:18 +05:30
Aman Raj Singh Mourya
5620be6c15 [auth] revert commit 2bf58aff45 2025-01-21 22:12:40 +05:30
Aman Raj Singh Mourya
91462bcb3c Revert "[auth] Implemeted banner widget"
This reverts commit 2bf58aff45.
2025-01-21 22:09:19 +05:30
Neeraj
c040935c52 [auth] Update crypto dependency + bump version (#4805)
## Description

## Tests
2025-01-21 20:15:40 +05:30
Neeraj Gupta
ffe7535cd2 Lint fix 2025-01-21 20:09:05 +05:30
Neeraj Gupta
219e5590bc [auth] Ensure sortKey is always passed 2025-01-21 19:58:41 +05:30
Neeraj Gupta
7c7ce15177 [auth] Bump version 2025-01-21 19:53:20 +05:30
Neeraj Gupta
b2e164af75 [auth] Upgrade dependency 2025-01-21 19:52:57 +05:30
Neeraj
d495d6f281 [auth] Remove scan package (#4804) 2025-01-21 19:32:21 +05:30
Aman Raj Singh Mourya
1e45ae5bbc [auth] Remove scan package 2025-01-21 19:27:33 +05:30
mangesh
636d493dfe [docs] fix web app docs, sibling to #4800 (#4802) 2025-01-21 16:39:06 +05:30
Manav Rathi
1684192dc0 [desktop] Update to ImageMagick 7, and also make it available on Linux ARM + Windows x64/ARM (#4803) 2025-01-21 16:38:38 +05:30
Manav Rathi
e7d6362eaa Make prettier happy 2025-01-21 16:32:03 +05:30
Manav Rathi
85cf1de12c All current os/arch combinations are handled 2025-01-21 16:28:35 +05:30
mngshm
19135a0dfc resolve merge conflict o.O 2025-01-21 16:26:33 +05:30
Manav Rathi
3d2b8974df Temporary tracing 2025-01-21 16:24:03 +05:30
Manav Rathi
d836e190e3 Use the updated im 7 2025-01-21 16:21:49 +05:30
mngshm
5e54b0af36 fix[web-app docs]: fix syntax issue & add note related to yarn version 2025-01-21 16:05:19 +05:30
Manav Rathi
75509ff339 exec 2025-01-21 15:56:04 +05:30
Neeraj
adf8542301 [mob] Bump version (#4801)
## Description

## Tests
2025-01-21 15:55:09 +05:30
Neeraj Gupta
eca1ff6bb6 [mob] Bump version 2025-01-21 15:54:49 +05:30
Manav Rathi
c731833863 Use a node script to avoid dealing with Windows nonsense 2025-01-21 15:36:00 +05:30
Manav Rathi
cf27dd5889 Outline 2025-01-21 14:54:24 +05:30
Neeraj
45e8006652 [mob][auth] Flutter upgrade to 3.27.2 (#4799)
## Description

## Tests
2025-01-21 14:50:32 +05:30
Neeraj Gupta
39a54a08c0 [auth] Lint fix 2025-01-21 14:29:11 +05:30
Neeraj Gupta
d3fecf3831 [auth] Lint fix 2025-01-21 14:24:12 +05:30
Neeraj Gupta
e9ed423094 Lint fixes 2025-01-21 14:21:13 +05:30
Neeraj Gupta
6eb381b64a [auth][photos] Upgrade flutter 2025-01-21 14:02:13 +05:30
Neeraj Gupta
9f67d06844 [auth] Upgrade flutter submodule to 3.27.2 2025-01-21 13:31:05 +05:30
Neeraj
17ab295983 [auth] Minor fixes (#4797)
## Description

## Tests
2025-01-21 12:49:59 +05:30
Laurens Priem
dd600c05cd [docs] Add FAQ question on export (#4798)
## Description

Added a question on export size.
2025-01-21 11:47:47 +05:30
laurenspriem
ed8ce66ce5 [docs] Add FAQ question on export 2025-01-21 11:45:50 +05:30
Neeraj Gupta
6c68052a55 Lint fix 2025-01-21 11:04:24 +05:30
Neeraj
305c63f921 [auth] Notification banner (#4789)
## Description
![SmartSelect_20250120_211733
1](https://github.com/user-attachments/assets/bc996a00-eaeb-4a87-8ea4-feceb9efeeb1)
2025-01-21 10:53:54 +05:30
Neeraj Gupta
bb4e42331b [auth] Update window min size/height 2025-01-21 10:53:38 +05:30
Neeraj Gupta
4243a331a3 [auth] Log error during init 2025-01-21 10:35:26 +05:30
Aman Raj Singh Mourya
2bf58aff45 [auth] Implemeted banner widget 2025-01-20 21:21:08 +05:30
Aman Raj Singh Mourya
85c5ccd218 [auth] added assets for banner widget 2025-01-20 21:20:25 +05:30
Manav Rathi
0f63930e52 [meta] Update issue template (#4788) 2025-01-20 19:57:49 +05:30
Manav Rathi
4826fdc999 [meta] Update issue template 2025-01-20 19:57:29 +05:30
Manav Rathi
6621944a66 [web] Update mem & ops limits (#4785)
Sibling of https://github.com/ente-io/ente/pull/4771
2025-01-20 19:45:59 +05:30
Neeraj
969a9c554f [server] Fix error type for bad request (#4787)
## Description

## Tests
2025-01-20 16:44:40 +05:30
Neeraj Gupta
e6e4540671 [server] Fix error type for bad request 2025-01-20 16:42:08 +05:30
Neeraj
e2ccfe5f48 [mob] Lower Mem & increase ops limit for key derivation (#4771)
## Description

## Tests
2025-01-20 16:40:09 +05:30
Manav Rathi
4c518f6b13 [web] Update mem & ops limits
Sibling of https://github.com/ente-io/ente/pull/4771
2025-01-20 14:48:25 +05:30
Neeraj Gupta
ff3da665a3 [server] Add server side validation 2025-01-20 14:17:22 +05:30
Neeraj Gupta
2b8c6494cd [mob] Remove unused value 2025-01-20 14:16:39 +05:30
Neeraj Gupta
ff81711043 Merge branch 'lowerMemRequirement' of https://github.com/ente-io/auth into lowerMemRequirement 2025-01-20 14:13:43 +05:30
Manav Rathi
96605d7702 [desktop] Include branding colors in Flathub MetaInfo (#4784)
https://docs.flathub.org/blog/introducing-app-brand-colors/#adding-brand-colors
2025-01-20 14:13:10 +05:30
Neeraj Gupta
02fb6888ab [mob] Remove client side strength check 2025-01-20 14:12:59 +05:30
Manav Rathi
0309db9466 [desktop] Include branding colors in Flathub MetaInfo
https://docs.flathub.org/blog/introducing-app-brand-colors/#adding-brand-colors
2025-01-20 14:04:21 +05:30
Neeraj Gupta
ffde143247 [mob] Fixed typo and lint 2025-01-20 14:01:56 +05:30
Neeraj Gupta
8e26433dd2 [mob] LowerMem & increase ops limit for key derivation 2025-01-20 14:01:56 +05:30
Trekky12
e92b5c3397 [cli] sync deleted files before syncing new/updates files (#4776)
## Description
The CLI sorts deleted photos to the bottom of the sync queue. 
When an album is synced, a photo is removed from the album and later
re-added to the album (same name) and doing another sync the new file is
added first and a new name is generated since the original filename is
(still) taken. Afterwards the initial photo is deleted and the filename
would be available.
This leads to having a file, e.g. IMG_0001_1.JPG instead of the original
filename IMG_0001.JPG despite the initial filename is no longer on disk
and could have been used.

This PR changes the sort order so that deleted files are first removed
and afterwards new files are created. In this case all files where the
filename is now available, but were taken, are named like they were
uploaded.
2025-01-20 11:16:37 +05:30
github-actions[bot]
77db220327 [mobile] New translations (#4781)
New translations from
[Crowdin](https://crowdin.com/project/ente-photos-app)

Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2025-01-20 11:09:50 +05:30
Neeraj
7e320693a1 [server] Remove unused endpoint (#4772)
## Description

No logs for request in last 30 days and client code also don't refer to
this endpoint.

## Tests
2025-01-20 11:09:31 +05:30
Jonathan Beliën
714a37d461 [auth] Update icons (#4777)
## Description

- Remove "forced" color for Fastmail logo (colors are already defined in
SVG file)
- Add [CSAM ](https://www.csam.be/en/index.html) logo
- Add [reMarkable](https://remarkable.com/) logo

I was planning to add LinkedIn logo but noticed #4742 so I've removed
it.

## Tests
2025-01-20 11:07:56 +05:30
github-actions[bot]
db7f38a926 [auth] New translations (#4782)
New translations from
[Crowdin](https://crowdin.com/project/ente-authenticator-app)

Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2025-01-20 11:06:41 +05:30
Manav Rathi
a7232d7401 [web] New translations (#4779)
New translations from
[Crowdin](https://crowdin.com/project/ente-photos-web)
2025-01-20 09:59:54 +05:30
Crowdin Bot
dbc7861cee New Crowdin translations by GitHub Action 2025-01-20 00:34:13 +00:00
Neeraj Gupta
43adef8899 [mob] Fixed typo and lint 2025-01-18 16:14:00 +05:30
Neeraj Gupta
73af752f52 [mob] LowerMem & increase ops limit for key derivation 2025-01-18 16:10:30 +05:30
Manav Rathi
b6d267e0cd [web] UI color related improvements (#4765)
Continuation of https://github.com/ente-io/ente/pull/4759.
2025-01-17 20:39:38 +05:30
Manav Rathi
aaeab874d8 Rename 2025-01-17 20:35:10 +05:30
Manav Rathi
8cd2267f5d Fix imports 2025-01-17 20:31:54 +05:30
Manav Rathi
67398ea9e4 Fix the button to work in light mode 2025-01-17 20:26:02 +05:30
Manav Rathi
8705d878f4 Tweak 2025-01-17 20:06:09 +05:30
Manav Rathi
a37bd085d6 Color text 2025-01-17 20:02:22 +05:30
Manav Rathi
9a01518200 Prune 2025-01-17 19:50:27 +05:30
Manav Rathi
f1e1939983 Swap 2025-01-17 19:46:03 +05:30
Manav Rathi
60de6018a1 Swap 2025-01-17 19:39:30 +05:30
Manav Rathi
14ff82da27 hover opacity 2025-01-17 19:36:08 +05:30
Manav Rathi
0e34b92398 Better match 2025-01-17 19:05:44 +05:30
Manav Rathi
929f749ad9 Fill 2025-01-17 18:50:58 +05:30
Manav Rathi
1dd831e72d Lowercase for consistency with the others 2025-01-17 18:35:57 +05:30
Manav Rathi
9e4ad1280f Mergability 2025-01-17 17:57:28 +05:30
Manav Rathi
3970724ade Fix logo 2025-01-17 17:50:13 +05:30
Manav Rathi
0f5d921ddb Comment out the fields we're not currently using 2025-01-17 17:41:04 +05:30
Manav Rathi
ef55e2dc23 Tweak 2025-01-17 17:37:17 +05:30
Manav Rathi
a17fb4e2fb landing page 2025-01-17 17:31:20 +05:30
Manav Rathi
210e055d9c LM tweaks 2025-01-17 17:16:21 +05:30
Manav Rathi
1788d07cdd [server] Make SMTP sender name configurable (#4677)
## Description

## Tests
2025-01-17 16:32:36 +05:30
Tobias Genannt
ae68998069 [server] Make SMTP sender name configurable 2025-01-17 12:00:15 +01:00
Manav Rathi
9041269af7 Shadow 2025-01-17 16:13:25 +05:30
Manav Rathi
b5fd289ae9 Theme aware 2025-01-17 16:02:32 +05:30
Manav Rathi
2cdc14aed3 light 2025-01-17 15:55:34 +05:30
Laurens Priem
4bb9c3b290 [mob][photos] Sort merge persons (#4761)
## Description

When assigning or merging an unnamed cluster, order the possible
existing persons to merge with in order from most similar to least
similar.

## Tests

Tested in debug mode on my pixel phone.
2025-01-17 15:54:25 +05:30
Manav Rathi
ccb07a45d9 Shorten 2025-01-17 15:51:45 +05:30
laurenspriem
0f03545929 [mob][photos] Cleanup 2025-01-17 15:44:50 +05:30
Manav Rathi
4f1659f7b7 Palette 2025-01-17 15:43:25 +05:30
laurenspriem
703277fc1d [mob][photos] Run once 2025-01-17 15:18:38 +05:30
laurenspriem
7de379580a [mob][photos] imports 2025-01-17 15:02:27 +05:30
laurenspriem
e224609e7d [mob][photos] First sort attempt 2025-01-17 15:01:20 +05:30
Manav Rathi
1bb04f2650 [web] Deploy only on weekdays (#4760) 2025-01-17 14:50:29 +05:30
Manav Rathi
a164f1b839 [web] Deploy only on weekdays 2025-01-17 14:48:12 +05:30
Manav Rathi
c69eb1dc52 [web] UI color related improvements (#4759)
Continuation of https://github.com/ente-io/ente/pull/4751. Now that dark
theme colors have been (mostly) isolated, next up will be introducing
the light one.
2025-01-17 14:43:59 +05:30
Manav Rathi
371960d479 gray 2025-01-17 14:21:25 +05:30
LivioZ
fd50eb9c13 Add Starbreeze icon (#4743)
Source:
[https://corporate.starbreeze.com/en/press/media/](https://corporate.starbreeze.com/en/press/media/)
2025-01-17 14:16:15 +05:30
Neeraj
f1bd625585 [auth][mob] Add padding during SRP authn (#4758)
## Description

## Tests
2025-01-17 14:13:29 +05:30
mangesh
de253865ac [draft] staff (#4611) 2025-01-17 14:06:02 +05:30
Laurens Priem
776fdc6d03 Cluster trigger (#4750)
## Description

Trigger clustering when user presses on unclustered face from file info.
2025-01-17 14:05:22 +05:30
Bl4ckspell
58d2f740a5 [Auth] Add more custom icons (#4753)
## Description
Added more icons:

| Name | Icon | Source |

|---------------|-------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------|
| Finanzfluss | <img
src="https://github.com/user-attachments/assets/f3c9ca30-0202-490b-8339-83970b8b8e1e"
width="100"><br> |
[https://www.finanzfluss.de/presse/](https://www.finanzfluss.de/presse/)
|
| LabyMod | <img
src="https://github.com/user-attachments/assets/1bb8f37d-e3df-4370-a414-de5057ab5324"
width="100"><br> |
[https://labymod.net/en/branding](https://labymod.net/en/branding) |
| Nextcloud | <img
src="https://github.com/user-attachments/assets/bc907f08-ce94-41d1-a12e-63cf5f8c5a40"
width="100"><br> |
[https://nextcloud.com/press/#logo-resources](https://nextcloud.com/press/#logo-resources)
|
| Parqet | <img
src="https://github.com/user-attachments/assets/6059e0b7-9a36-44cb-ba1f-ce7af89a7a13"
width="100"><br> |
[https://parqet.notion.site/Parqet-in-der-Presse-314ee4e9cf4648e99371821f072acc58](https://parqet.notion.site/Parqet-in-der-Presse-314ee4e9cf4648e99371821f072acc58)
|
| CSGORoll | <img
src="https://github.com/user-attachments/assets/9c738583-fbf3-44aa-8058-441d5ce8ef71"
width="100"><br> |
[https://www.csgoroll.com/assets/favicons/android-icon-192x192.png](https://www.csgoroll.com/assets/favicons/android-icon-192x192.png)
|
| GommeHD.net | <img
src="https://github.com/user-attachments/assets/c472be83-362e-4c59-b245-bd99bc229934"
width="100"><br> |
[https://img.gommehd.net/128x128/logo.png](https://img.gommehd.net/128x128/logo.png)
|
## Note
For `CSGORoll` and `GommeHD.net`, I couldn't find official .svg files.
As a result, I converted the low-resolution .png sources to .svg, which
may not look perfect. Feel free to search for better-quality assets if
needed.
2025-01-17 14:04:41 +05:30
Manav Rathi
df04d0ec2e [desktop] Add MetaInfo (#4757)
## Description

Add AppStream MetaInfo for https://github.com/flathub/flathub/pull/6032,
similar to
[enteauth.appdata.xml](https://github.com/ente-io/ente/blob/main/auth/linux/packaging/enteauth.appdata.xml).
2025-01-17 14:04:37 +05:30
Neeraj
4de573190b [server] Switch to forked version of go-srp (#4748)
## Description

The custom forks fixes couple of padding related issues in the original
library.
Changes can be reviewed here
https://github.com/Kong/go-srp/compare/master...ente-io:go-srp:master
## Tests
2025-01-17 14:01:08 +05:30
Manav Rathi
8e044f4f50 Fix font 2025-01-17 13:51:37 +05:30
Manav Rathi
2ef78be038 fainter 2025-01-17 13:39:17 +05:30
Manav Rathi
cb90e064ab Remove unnecessary customization 2025-01-17 13:06:04 +05:30
Manav Rathi
18d091ea4e Extract 2025-01-17 12:59:49 +05:30
Manav Rathi
82a2c6e12b For now 2025-01-17 12:50:56 +05:30
Manav Rathi
cb085ba0f3 Use channel style 2025-01-17 12:48:58 +05:30
Manav Rathi
491e446454 Remove hardcoded 2025-01-17 12:42:04 +05:30
Manav Rathi
bfe62d2209 LF 2025-01-17 12:07:48 +05:30
Manav Rathi
0a359b0835 Remove hardcoded 2025-01-17 12:05:21 +05:30
Manav Rathi
1a1b5cac3b Remove prop from styled LinkButton 2025-01-17 11:40:10 +05:30
Manav Rathi
0b95e84143 Tweak spacing 2025-01-17 10:39:46 +05:30
Manav Rathi
c5ab6e7c66 Improve 2025-01-17 10:29:00 +05:30
Manav Rathi
6fe6233664 Swap 2025-01-17 10:10:55 +05:30
Manav Rathi
38895eaf56 Unprop 2025-01-17 10:03:33 +05:30
Manav Rathi
9e91029105 dedup 2025-01-17 10:00:20 +05:30
Manav Rathi
169af1628d Ditto 2025-01-17 09:55:23 +05:30
Manav Rathi
634aa10aff in css 2025-01-17 09:43:52 +05:30
NN708
03903ae605 [desktop] Add MetaInfo 2025-01-17 11:08:18 +08:00
Manav Rathi
8961939d37 Theme 2025-01-17 08:02:45 +05:30
Manav Rathi
870cb61adb Theme 2025-01-17 07:58:26 +05:30
Manav Rathi
786b0bac4f Smoother animation 2025-01-17 07:38:41 +05:30
Manav Rathi
03deaa9b8e Use 2025-01-17 07:35:15 +05:30
Manav Rathi
2117a5b6e8 Conv 2025-01-17 07:34:13 +05:30
Manav Rathi
a002733d3f [web] UI color related improvements (#4751)
Prep for light mode (continuation of
https://github.com/ente-io/ente/pull/4741)
2025-01-16 19:34:04 +05:30
Manav Rathi
3008fac19c Const 2025-01-16 19:28:09 +05:30
Manav Rathi
3f324a599c Prep 2025-01-16 19:21:36 +05:30
Manav Rathi
67acabf7c7 Fix 2025-01-16 19:17:45 +05:30
Manav Rathi
03c1ff366f Fix 2025-01-16 19:15:25 +05:30
Manav Rathi
94eef9b596 Prep for merge 2025-01-16 18:52:02 +05:30
Manav Rathi
fb70460ec5 Sel 2025-01-16 18:08:32 +05:30
laurenspriem
57e8eb7c03 [mob][photos] Force clustering on unclustered face 2025-01-16 17:55:39 +05:30
Manav Rathi
d8443c5f6f Match Figma (better, but still not exactly) 2025-01-16 17:46:53 +05:30
Neeraj Gupta
5c7127cba9 Fix lint 2025-01-16 17:38:52 +05:30
Neeraj Gupta
b871f00150 Fix pkg version 2025-01-16 17:35:12 +05:30
Neeraj Gupta
bc8ebab531 clean up 2025-01-16 17:32:11 +05:30
Neeraj Gupta
b70b00cda4 Add dependency on fork to track changes 2025-01-16 17:10:51 +05:30
Neeraj Gupta
52653b6fe4 Clean up logs 2025-01-16 16:52:00 +05:30
Neeraj Gupta
0b26d9abc5 Add missing padding 2025-01-16 16:06:09 +05:30
Manav Rathi
d2defe4d27 Use 2025-01-16 16:06:03 +05:30
Manav Rathi
926e179d57 Rename to disambiguate from Overlay 2025-01-16 15:52:32 +05:30
Manav Rathi
b7841e2aee Use theme color 2025-01-16 15:47:18 +05:30
Neeraj Gupta
77fdfe84ec [server] Add missing padding 2025-01-16 15:34:42 +05:30
laurenspriem
d9fc53137d [mob][photos] Dont double run clustering 2025-01-16 15:32:36 +05:30
laurenspriem
470d14d81f [mob][photos] Rename 2025-01-16 15:24:52 +05:30
laurenspriem
5611f2f9d9 [mob][photos] Rename function 2025-01-16 15:22:57 +05:30
Neeraj Gupta
5302f67679 [server] Update srp validation 2025-01-16 15:20:50 +05:30
Manav Rathi
4ed620db28 Fix default hidden collection download 2025-01-16 15:17:44 +05:30
Manav Rathi
c4f2e9e319 Overrides 2025-01-16 15:17:44 +05:30
Manav Rathi
b7dd90158b Fix font weights
normal is the CSS keyword which resolves to 400, which is not what we want (500).
2025-01-16 15:17:44 +05:30
Manav Rathi
ba6418fcf2 Fix 2025-01-16 15:17:44 +05:30
Manav Rathi
806839d5ab Fix 2025-01-16 15:17:44 +05:30
Manav Rathi
f324e5e11c Switching theme reveals more 2025-01-16 15:17:43 +05:30
Manav Rathi
d24f9aff72 Temp fix 2025-01-16 15:17:43 +05:30
Manav Rathi
20bbd61fce Dropdown revert 2025-01-16 15:17:43 +05:30
Manav Rathi
24aff9268a Remove hardcoded 2025-01-16 15:17:43 +05:30
Manav Rathi
588236dcb4 Fix 2025-01-16 15:17:43 +05:30
Manav Rathi
e4b26e7e74 Crop 2025-01-16 15:17:43 +05:30
Manav Rathi
61cd5de725 Remove hardcoded black 2025-01-16 15:17:43 +05:30
Manav Rathi
7310d4da03 const 2025-01-16 15:17:43 +05:30
Manav Rathi
804b91b825 Fix + TODO 2025-01-16 15:17:43 +05:30
Manav Rathi
c7fab49d68 Rename 2025-01-16 15:17:43 +05:30
Manav Rathi
75c3c54a5a Shift 2025-01-16 15:17:43 +05:30
Manav Rathi
59e3f864ce why? 2025-01-16 15:17:43 +05:30
Manav Rathi
1322739707 Move 2025-01-16 15:17:43 +05:30
Manav Rathi
c72b4a428a unlints 2025-01-16 15:17:43 +05:30
Manav Rathi
59f6bb5f48 Cleanup 2025-01-16 15:17:43 +05:30
Manav Rathi
1915fa0bb6 Prune 2025-01-16 15:17:43 +05:30
Manav Rathi
5f5de6b640 ts 2025-01-16 15:17:43 +05:30
Manav Rathi
944caafe76 Fix 2025-01-16 15:17:43 +05:30
Manav Rathi
6171488375 Take 1 2025-01-16 15:17:43 +05:30
Manav Rathi
5328e6cfee wip checkpoint 2025-01-16 15:17:43 +05:30
laurenspriem
429fcbf062 [mob][photos] Better logging 2025-01-16 15:16:10 +05:30
Bl4ckspell
8366a8fe4d [Auth] Add Badlion logo (#4746)
## Description
Source:
[https://www.badlion.net/wiki/resources](https://www.badlion.net/wiki/resources)
2025-01-16 11:20:11 +05:30
Manav Rathi
9e8e2af51d [web] UI color related improvements (#4741)
Prep for light mode.
2025-01-15 19:32:16 +05:30
Manav Rathi
b0318e4ec3 Trim 2025-01-15 19:22:18 +05:30
Manav Rathi
78dc93f6d7 wip rework 2025-01-15 19:05:05 +05:30
Manav Rathi
12793858d0 Doc and move 2025-01-15 18:54:11 +05:30
Manav Rathi
c7896d0e68 USe 2025-01-15 18:44:47 +05:30
Manav Rathi
038a08f583 Use 2025-01-15 18:39:54 +05:30
Manav Rathi
b316947548 Extract 2025-01-15 18:33:50 +05:30
Manav Rathi
2db54bc1ce Conv 2025-01-15 18:18:49 +05:30
Manav Rathi
d2bdec909d Conv 2025-01-15 18:12:57 +05:30
Manav Rathi
5477d09155 Conv 2025-01-15 18:10:35 +05:30
Manav Rathi
bd0b3aadf8 Rework 2025-01-15 18:03:17 +05:30
Manav Rathi
dea20345da Rework 2025-01-15 17:44:07 +05:30
Manav Rathi
ba0ea26e93 Conv 2025-01-15 17:24:48 +05:30
Manav Rathi
d34cb01a07 Conv 2025-01-15 17:12:46 +05:30
Manav Rathi
d3b1f0f5ab Conv 2025-01-15 16:48:31 +05:30
Manav Rathi
7913debe8c No chevron there anymore 2025-01-15 16:39:56 +05:30
Manav Rathi
f282761ad2 Conv 2025-01-15 16:36:21 +05:30
Manav Rathi
351883c002 Conv 2025-01-15 16:36:21 +05:30
Manav Rathi
fc81dd9df3 Conv 2025-01-15 16:36:21 +05:30
Manav Rathi
f61ba74797 Update 2025-01-15 16:36:21 +05:30
Manav Rathi
9602d70a14 Conv 2025-01-15 16:36:21 +05:30
Manav Rathi
e620116371 pigmentize 2025-01-15 16:36:21 +05:30
Manav Rathi
ed6ea753a2 Scope 2025-01-15 16:36:21 +05:30
Manav Rathi
dd01a4aaa5 Hover and use 2025-01-15 16:36:21 +05:30
Manav Rathi
16747b48b0 fp 2025-01-15 16:36:21 +05:30
Manav Rathi
4cf3302cff Tweak 2025-01-15 16:36:21 +05:30
Manav Rathi
51597ed48d prep for pigment 2025-01-15 16:36:21 +05:30
Manav Rathi
131cf43f73 Tweak API 2025-01-15 16:36:21 +05:30
Manav Rathi
ad4716256e Tweak 2025-01-15 16:36:21 +05:30
Manav Rathi
4c1e434b96 Visual fix 2025-01-15 16:36:21 +05:30
Manav Rathi
7417bb6830 Conv 2025-01-15 16:36:21 +05:30
Manav Rathi
e475c0d507 Reduce prop scope 2025-01-15 16:36:21 +05:30
Manav Rathi
f3f7d67fb3 Simplify 2025-01-15 16:36:21 +05:30
Manav Rathi
c44e558259 Update 2025-01-15 16:36:21 +05:30
Manav Rathi
038b47ebeb Tweak 2025-01-15 16:36:21 +05:30
Manav Rathi
e996664b57 Conv 2025-01-15 16:36:21 +05:30
Manav Rathi
8b9830fe79 Improve focus visible and add active state for switch 2025-01-15 16:36:21 +05:30
Manav Rathi
75149a4a70 m 2025-01-15 16:36:21 +05:30
Manav Rathi
66e85567a6 Conv 2025-01-15 16:36:21 +05:30
Manav Rathi
36f7bb5364 Tweak 2025-01-15 16:36:21 +05:30
Manav Rathi
58db7e8a91 Conv 2025-01-15 16:36:21 +05:30
Manav Rathi
d7e62f2b26 Seeing blue 2025-01-15 16:36:21 +05:30
Manav Rathi
a1117da632 Conv 2025-01-15 16:36:21 +05:30
Manav Rathi
003f1ec0e8 Conv 2025-01-15 16:36:21 +05:30
Manav Rathi
a0078dd966 In palette 2025-01-15 16:36:21 +05:30
Manav Rathi
6a71d6359a Inline 2025-01-15 16:36:20 +05:30
Manav Rathi
04ea4ac027 [desktop] Fix regression causing people suggestions not to appear in empty state (#4739)
When the search bar was empty, previously we would show people
suggestions. This
was accidentally circumvented; fix it.
2025-01-15 16:34:06 +05:30
Manav Rathi
5074f7d9f4 [desktop] Fix regression causing people suggestions not to appear in empty state
When the search bar was empty, previously we would show people suggestions. This
was accidentally circumvented; fix it.
2025-01-15 16:28:33 +05:30
Neeraj Gupta
125f386df1 [auth] Bump version 2025-01-15 15:55:45 +05:30
Neeraj Gupta
41ed5dd17e [auth] Fix manual code setup 2025-01-15 15:55:45 +05:30
Neeraj
6031101600 [server] Legacy email reminder (#4737)
## Description
- Sends email when account is ready to be recovered
- Keep sending reminder email every 7 days, till T-2 day when a recovery
attempt is in waiting.

## Tests
Did monkey testing locally by modifying the DB time
2025-01-15 15:48:45 +05:30
Neeraj Gupta
73a8550844 [server] Add remaining mails for legacy 2025-01-15 15:41:13 +05:30
mngshm
2c6022186c remove token print 2025-01-15 15:22:52 +05:30
mngshm
1713be30b7 reset Sidebar/index.ts 2025-01-15 15:20:41 +05:30
mngshm
629cbe6887 fix lint issue specifically for Sidebar/index.ts 2025-01-15 14:06:13 +05:30
mngshm
c2306ed4e9 reorganize getToken import line 2025-01-15 13:52:16 +05:30
mngshm
7d1670d210 condition for instanceof HTMLInputElement 2025-01-15 13:33:14 +05:30
mngshm
1638b7584f reorganize getToken import line 2025-01-15 12:41:30 +05:30
Laurens Priem
bf256863b9 [mob][photos] Bump for release (#4735)
## Description

## Tests
2025-01-15 07:50:15 +01:00
laurenspriem
e7aeef6e2e [mob][photos] Bump for release 2025-01-15 12:18:42 +05:30
Laurens Priem
3a77db9ff6 [mob][photos] Fix regression with Persons (#4734)
## Description

Fix regression causing the Person entities to not load properly on
mobile.
2025-01-15 07:43:56 +01:00
laurenspriem
00c279096d [mob][photos] Format 2025-01-15 12:00:44 +05:30
laurenspriem
a913e2c6e7 [mob][photos] Fix person issue 2025-01-15 11:54:27 +05:30
Neeraj Gupta
05f86b8951 [auth] Potential fix for segfault on Linux due to bad window size 2025-01-15 11:12:17 +05:30
Manav Rathi
2396cc8d30 [web] Switch to CSS vars based color schemes (#4730) 2025-01-15 10:56:04 +05:30
Manav Rathi
52f3e7a293 lf 2025-01-15 10:53:08 +05:30
Manav Rathi
a15c9620ec Static 2025-01-15 10:45:27 +05:30
Manav Rathi
626b403657 T 2025-01-15 10:28:52 +05:30
Manav Rathi
20310d2ef5 Update 2025-01-15 10:20:38 +05:30
Manav Rathi
75e146e23b Fix lints 2025-01-15 09:53:52 +05:30
Manav Rathi
bfabeaefb9 Move 2025-01-15 09:52:50 +05:30
Manav Rathi
882d66ee52 Remove old state 2025-01-15 09:48:04 +05:30
Manav Rathi
16a804c329 Selector 2025-01-15 09:28:49 +05:30
Manav Rathi
db77e45aab Enable css vars based color schemes
https://mui.com/blog/material-ui-v6-is-out/
2025-01-15 08:57:20 +05:30
Manav Rathi
9e1570032a [web] Translation improvements (#4728) 2025-01-15 08:43:59 +05:30
Manav Rathi
cb88e1662b Simplify 2025-01-15 08:37:49 +05:30
Manav Rathi
80bea2b31b R 2025-01-15 08:31:51 +05:30
Manav Rathi
b63d6ad859 Fix casing 2025-01-15 08:28:15 +05:30
Manav Rathi
d13e9bc11a [web] Color related code improvements (#4720) 2025-01-14 21:29:27 +05:30
Manav Rathi
8bfb5fcba5 Conv 2025-01-14 21:22:33 +05:30
Manav Rathi
794fe3cad6 2fa 2025-01-14 21:10:11 +05:30
Manav Rathi
1b9ad83653 2f 2025-01-14 20:44:57 +05:30
Manav Rathi
7236b24d96 Swap danger 2025-01-14 20:36:59 +05:30
Manav Rathi
7757409976 active 2025-01-14 20:31:29 +05:30
Manav Rathi
58150319f0 Light 2025-01-14 20:19:32 +05:30
Manav Rathi
b4b719ffc4 Use 2025-01-14 20:09:03 +05:30
Manav Rathi
4fc82e2b98 Patch 2025-01-14 19:55:38 +05:30
Manav Rathi
6b55e8598f crs 2025-01-14 19:52:58 +05:30
Manav Rathi
f50c88fd15 Backdrop 2025-01-14 19:50:16 +05:30
Neeraj Gupta
d968310f73 [mob] Update moments section for internal users 2025-01-14 17:38:10 +05:30
Laurens Priem
4a27596a2e [mob][photos] Fix hidden file for face (#4718)
## Description

## Tests
2025-01-14 13:04:35 +01:00
Manav Rathi
8fef83adaf Fix 2025-01-14 17:05:49 +05:30
Manav Rathi
baa081510e Remove other uses of text.secondary 2025-01-14 17:02:53 +05:30
Manav Rathi
77248175c2 Default is standard, but I don't see how it is different
We're anyways overriding the bg and color of the buttons in this toggle group.
2025-01-14 16:57:58 +05:30
Manav Rathi
c506346c2a Remove unnecessary primary 2025-01-14 16:40:15 +05:30
Manav Rathi
4c75253e0a To misc 2025-01-14 16:32:36 +05:30
mngshm
e81b6acbdd fix lint? 2025-01-14 16:32:21 +05:30
mngshm
08278fb169 fix: formatting ;-; 2025-01-14 16:30:26 +05:30
mngshm
09d2158ca4 add basic functionality for 'update-token' feature 2025-01-14 16:28:53 +05:30
laurenspriem
25d66dd238 [mob][photos] Fix hidden file for face 2025-01-14 15:20:44 +05:30
Manav Rathi
52cbd024f7 Document why 2025-01-14 15:14:35 +05:30
Manav Rathi
fdd7f20518 Disable ripple on checkboxes 2025-01-14 15:07:41 +05:30
Manav Rathi
44566d7e64 Inline to avoid text.secondary 2025-01-14 14:38:20 +05:30
Manav Rathi
397248557b Inline to avoid text.secondary 2025-01-14 14:29:41 +05:30
Manav Rathi
2a532cf1d2 Doc 2025-01-14 14:24:38 +05:30
Manav Rathi
62edaa62d8 Doc 2025-01-14 14:16:05 +05:30
Manav Rathi
b41909477e Doc 2025-01-14 14:15:07 +05:30
Manav Rathi
4926783905 Fin 2025-01-14 14:00:26 +05:30
Manav Rathi
e593274fec Paper 2025-01-14 13:32:14 +05:30
Manav Rathi
085e11302c ts 2025-01-14 12:51:56 +05:30
Manav Rathi
f925d98686 Fixed 2025-01-14 12:48:54 +05:30
Manav Rathi
8b038e7439 Clean 2025-01-14 12:21:30 +05:30
Manav Rathi
3db0b73648 Rearrange 2025-01-14 12:09:28 +05:30
Manav Rathi
474f9b8433 Reduce interface 2025-01-14 12:08:48 +05:30
Manav Rathi
e8f11effe7 Cleanup 2025-01-14 11:57:51 +05:30
Manav Rathi
8560304b1d Palette var 2025-01-14 11:51:57 +05:30
Manav Rathi
4a6910ce46 Gen and inline 2025-01-14 11:13:24 +05:30
Manav Rathi
3f38ed4611 Doc 2025-01-14 10:55:30 +05:30
Manav Rathi
537f1c3d0c Split 2025-01-14 10:40:30 +05:30
Manav Rathi
07944d9ac0 Doc 2025-01-14 10:26:05 +05:30
Manav Rathi
db8270987b doc 2025-01-14 10:26:05 +05:30
mngshm
c750f2ea7e add: dashboard redirection button in photos app
while this is temporary. The baseURL hardcoding will be removed in the near future.

pushing this to keep a track of changes happening
2025-01-13 16:59:37 +05:30
mngshm
57a2650e8d fix: useEffect() syntax and formatting 2025-01-13 16:57:26 +05:30
mngshm
cfe86b00aa auto-fill search bar for token and wrap input fields in single div 2025-01-13 16:21:33 +05:30
Neeraj Gupta
9fe58e44b0 [server] Improve recovery initialization validation 2025-01-11 15:22:42 +05:30
mngshm
f0789b1fca pushing staged changes 2025-01-07 17:41:55 +05:30
mngshm
cf6cd23ea4 fix: formatting 2025-01-07 10:11:06 +05:30
mngshm
079a84fc82 refactor: reomve unnecessary stylesheet 2025-01-06 19:13:01 +05:30
264 changed files with 4979 additions and 3356 deletions

View File

@@ -1,6 +1,6 @@
name: Report a bug
description: Let us know if something's not working the way you expected.
labels: ["triage"]
labels: []
body:
- type: markdown
attributes:

View File

@@ -4,7 +4,7 @@ on:
workflow_dispatch: # Allow manually running the action
env:
FLUTTER_VERSION: "3.24.3"
FLUTTER_VERSION: "3.27.2"
jobs:
build:

View File

@@ -8,7 +8,7 @@ on:
- ".github/workflows/auth-lint.yml"
env:
FLUTTER_VERSION: "3.24.3"
FLUTTER_VERSION: "3.27.2"
jobs:
lint:

View File

@@ -29,7 +29,7 @@ on:
- "auth-v*"
env:
FLUTTER_VERSION: "3.24.3"
FLUTTER_VERSION: "3.27.2"
jobs:
build-ubuntu:

View File

@@ -4,7 +4,7 @@ on:
workflow_dispatch: # Allow manually running the action
env:
FLUTTER_VERSION: "3.24.3"
FLUTTER_VERSION: "3.27.2"
jobs:
build:

View File

@@ -9,7 +9,7 @@ on:
env:
FLUTTER_VERSION: "3.24.3"
FLUTTER_VERSION: "3.27.2"
jobs:
lint:

View File

@@ -9,7 +9,7 @@ on:
- "photos-v*"
env:
FLUTTER_VERSION: "3.24.3"
FLUTTER_VERSION: "3.27.2"
jobs:
build:

View File

@@ -4,7 +4,7 @@ on:
schedule:
# [Note: Run workflow every 24 hours]
#
# Run everyday at ~8:00 AM IST (except Sundays).
# Run every weekday at ~8:00 AM IST.
#
# First field is minute, second is hour of the day. Last is day of week,
# 0 being Sunday.
@@ -15,7 +15,7 @@ on:
# https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#schedule
# https://crontab.guru/
#
- cron: "25 2 * * 1-6"
- cron: "25 2 * * 1-5"
# Also allow manually running the workflow
workflow_dispatch:

View File

@@ -46,6 +46,7 @@
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data android:name="flutterEmbedding" android:value="2"/>
<meta-data android:name="flutter_deeplinking_enabled" android:value="false" />
<meta-data android:name="io.sentry.dsn"
android:value="https://ed4ddd6309b847ba8849935e26e9b648@sentry.ente.io/9"/>

View File

@@ -55,6 +55,14 @@
"title": "AzurWare",
"slug": "azuware"
},
{
"title": "Badlion",
"slug": "badlion",
"altNames": [
"Badlion Client",
"BadlionClient"
]
},
{
"title": "BaiduCloud",
"slug": "baidu_cloud",
@@ -249,9 +257,16 @@
"Crypto com"
]
},
{
"title": "CSAM"
},
{
"title": "CSFloat"
},
{
"title": "CSGORoll",
"slug": "csgoroll"
},
{
"title": "DCS",
"altNames": [
@@ -330,8 +345,7 @@
"title": "Estateguru"
},
{
"title": "Fastmail",
"hex": "0067B9"
"title": "Fastmail"
},
{
"title": "Fidelity",
@@ -343,6 +357,10 @@
{
"title": "Filen"
},
{
"title": "Finanzfluss",
"slug": "finanzfluss"
},
{
"title": "Firefox",
"slug": "mozilla"
@@ -362,6 +380,14 @@
{
"title": "GMX"
},
{
"title": "GommeHD.net",
"slug": "gommehd",
"altNames": [
"GommeHD",
"GommeHDnet"
]
},
{
"title": "Google"
},
@@ -507,6 +533,10 @@
"title": "La Poste",
"slug": "laposte"
},
{
"title": "LabyMod",
"slug": "labymod"
},
{
"title": "Lark",
"slug": "lark",
@@ -622,6 +652,10 @@
"title": "Name.com",
"slug": "name_com"
},
{
"title": "Nextcloud",
"slug": "nextcloud"
},
{
"title": "NeteaseMail",
"slug": "netease_mail",
@@ -697,6 +731,10 @@
"欧易"
]
},
{
"title": "Parqet",
"slug": "parqet"
},
{
"title": "Parsec"
},
@@ -798,6 +836,9 @@
"Registro.br"
]
},
{
"title": "reMarkable"
},
{
"title": "Restorecord"
},
@@ -880,6 +921,15 @@
"title": "Standard Notes",
"slug": "standardnotes"
},
{
"title": "Starbreeze",
"altNames": [
"Starbreeze Nebula",
"Starbreeze Account",
"PAYDAY",
"PAYDAY 3"
]
},
{
"title": "Surfshark"
},

View File

@@ -0,0 +1,47 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 400 400">
<defs>
<style>
.cls-1 {
fill: #030303;
}
.cls-1, .cls-2, .cls-3, .cls-4 {
stroke-width: 0px;
}
.cls-2 {
fill: #71470d;
}
.cls-3 {
fill: #feb730;
}
.cls-4 {
fill: #2caddc;
}
</style>
</defs>
<path class="cls-4" d="M356.2,275.9V124.1c0-9.6-5.1-18.4-13.3-23.2L213.6,25.2c-8.4-4.9-18.8-4.9-27.2,0L57.1,100.8c-8.3,4.8-13.3,13.7-13.3,23.2v151.8c0,9.6,5.1,18.4,13.3,23.2l129.3,75.6c8.4,4.9,18.8,4.9,27.2,0l129.3-75.6c8.3-4.8,13.3-13.7,13.3-23.2Z"/>
<g>
<path class="cls-1" d="M208.8,327.5c-.4-.8-1.7-4.2-2.8-7.4-1.8-5.3-2-5.6-2.3-3.1-.1,1.5-.6,2.7-1,2.7s-.8,1.6-.8,3.5c0,4-1,3.5-2.5-1.3l-1-3.3-1.3,2.8-1.3,2.8-.5-5c-.6-6.7-2.2-6.6-4.7.3-2.3,6.3-3.4,7.7-4.1,5.2-.4-1.3-1.3-1.8-3-1.8s-2.6-.4-3.4-3.3c-1.2-3.9-2-4.2-3.1-1l-.8,2.3v-2.9c-.2-2.6-.3-2.7-1.2-1.3-1,1.5-2.1,2.9-3.2,4.2l-2.2,2.6-.9-2.4c-.5-1.3-.8-2.8-.9-4.2,0-1.7-.3-3.4-.5-5l-.5-3.2-4.4,4.3-4.4,4.4-.6-3.9c-.6-4.3-1.5-4.7-5.5-2.6-1.4.7-2.7,1.2-2.8,1s-.6-1.6-1-3.2c-.7-2.8-.9-3-5.8-3.7s-5.1-.9-5.5-3.5c-.8-5-3.1-8.7-5.3-8.7s-1.8-.4-1.5-.8c.7-1.1-.9-1.1-3.1,0-1.7.9-1.7.8-1.2-3,.4-3,.3-4-.7-4.4-.7-.3-3.4-3.2-6-6.5l-5.3-6.6c-.3-.3-2.5,0-4.9.7-2.4.7-4.5,1.2-4.7,1s.6-3.1,1.7-6.5c2-6.4,2-7.6,0-7.6s-1.2-1.2-1.2-5,0-5-2.9-5.9l-2.9-.9,1.2-3c1.7-4.1,1-5.3-3-5.3s-3.4-.3-3.4-.7,1.3-2.4,2.9-4.6,2.9-4,2.9-4.2-1.2-.7-2.7-1c-1.5-.3-2.9-.8-4.3-1.4-1.4-.8-1.3-1.1,1.6-4.1l3.2-3.3-2.7.5c-2.7.5-3.9-.7-1.4-1.6,1.9-.7,1.5-1.8-1.3-2.8-2-.8-2.5-1.4-2.5-3.5s-.6-2.9-1.3-3.3c-1.1-.6-1.1-.9.6-2,1.2-.8,2.5-1.4,3.8-1.9,1.2-.3,2-1.4,1.9-2.6,0-1.7-.5-2-3.1-2.3l-3.1-.3,2.3-1.2c2.7-1.4,2.9-2.3.6-3-2.2-.7-2.2-2.1,0-2.1s2.1-3.8-1.3-5.9c-2.5-1.6-2.8-2-1.7-2.6.7-.4,1.3-1.7,1.3-2.8,0-1.3.4-2.5,1-3.6.8-1.3.6-2.1-.8-4.6-2.5-4.2-2.6-11.8-.2-12.6,2.6-.8,2.5-3.9-.3-6.9l-2.5-2.7,2.6-.9c2.6-.9,4.1-3.3,3.1-5-.3-.5-.1-1.9.4-3.1.6-1.5,1-3.1,1.2-4.8.1-1.3.4-2.5.8-3.8,2.5-6.8,3.2-10.3,2.4-12.4s-.6-2.5,2.9-4.7c2.2-1.4,3.7-2.9,3.7-3.9s1-2.8,2.3-4.3,3.4-4.2,4.6-5.9c1.9-2.5,2.9-3.1,5.1-3.1s5.5-2,5.5-3.9,1.8-1,4-1.3,5.1-1.1,6.4-1.9,4-1.6,6-1.7,4.2-.6,4.9-1.2,1.7-.9,2.3-.8c3.8.5,6.5-.2,7-1.8s.7-1.6,2-.4c2.2,2,6.2,1.6,8.5-.8l2-2.1,1.1,2.1c1.4,2.6,4.4,2.8,7.7.4,2-1.5,2.8-1.6,5.6-.9,1.8.5,4.3,1.1,5.6,1.3,1.3.3,2.3,1.1,2.3,1.8,0,1.1,3.1,2.9,4.9,2.9.3,0,1.3-1.1,2.2-2.5l1.7-2.5,2.6,3.1,2.6,3.1,4.3-2.7,4.3-2.7,1.9,1.7c1.8,1.7,2.1,1.7,11.9.6,5.5-.7,11.9-1.2,14.2-1.2,2.9-.1,5.9-.5,8.7-1.3,4.7-1.3,5.9-1.1,5.9.8s2.4,2.1,6.3,0l3.8-2.1-.2,2.8c-.2,2.7-.1,2.8,3.1,3.1,1.8.1,4.4,1,5.7,2,1.5,1.1,4.4,1.9,7.7,2.3,5.3.5,8.7,2.4,8.7,4.8s1.6,2.3,3.6,3.7,4.1,3.6,4.7,4.8,3,4.2,5.3,6.5c3.9,4,4.1,4.3,2.4,4.9-2.9.9-2,2.9,2.2,4.6,3.7,1.5,4,2.3,1.8,4.7-1.8,1.9-1.8,2.1-.4,3.1,1.2.9,1.3,1.5.6,2.7-1.3,2.4-.2,6.2,2.2,8.3,2,1.7,2.1,1.9.7,3.8-1.8,2.6-1.8,3.7.5,6.7l1.9,2.5-1.8,1.4c-2.6,2-1.8,7.5,1.5,10.7,3,2.9,3,3.7,0,3.7s-2.5.4-2.8,2.5c-.2,1.4,0,3,.3,3.6s.7,2.1.7,3.3.7,2.6,1.5,3.1c1.3.7,1.1,1-1.3,2.3-1.5.8-2.7,2-2.7,2.5,0,.8-.2,1.5-.5,2.2-.3.9.2,1.3,1.9,1.6l2.4.3-2.3,1.1c-1.3.6-2.3,1.4-2.3,1.7s1,1.1,2.3,1.7l2.3,1.2-2.7.3c-3.7.4-3.9,3.7-.2,5.2,3.4,1.4,4.8,3.2,3,3.9-.8.3-1.3,1.5-1.3,3s-.5,2.7-2.3,3.4c-1.3.5-2.4,1.1-2.6,1.2s.6,1,1.7,2l2,1.7-3.3-.4-3.3-.5,3.2,2.9c3.6,3.3,3.4,4-2,5.6l-3.6,1,3,3.9c1.6,2.2,3,4.3,3,4.8s-1.5.9-3.3.9c-4.1,0-4.6.8-3,4.7.7,1.7,1.3,3.2,1.3,3.3s-1.3.7-2.9,1.2c-2.9,1-2.9,1-2.9,5.9s-.3,5-1.1,5-1.8.5-2.6,1.1c-1.4,1-1.4,1.4.4,7.5,1,3.5,1.6,6.7,1.4,7s-2.9,0-5.8-.8l-5.3-1.3-4.8,4.8-4.8,4.8,1.1,5.2c.6,2.9.9,5.2.6,5.2s-1.5-.6-2.6-1.2c-5.2-2.9-8.2-1-10.1,6.3l-1,4-4.9.5c-4.8.5-4.9.6-5.8,3.9-.5,1.8-1.1,3.3-1.2,3.3s-1.7-.6-3.3-1.4-3.2-1.2-3.5-.9-.7,3.2-1,6.4-.7,5.9-1,5.9-2.4-1.9-4.6-4.1c-2.2-2.3-4.4-3.9-4.8-3.7s-.7,1.7-.7,3.2-.5,3.4-1.1,4.3c-1,1.4-1.3,1.3-3.5-1.7-3.9-5.3-4-5.3-3.4.5.5,5,.4,5.3-.7,3.8-.7-.9-1.3-1.9-1.3-2.3,0-2-1.5-.3-2.2,2.5-.6,2.6-1.2,3.2-3.1,3.4-1.3.1-2.8,1-3.5,2-1.1,1.6-1.2,1.6-2,.2h0Z"/>
<path class="cls-3" d="M197.3,280c-1.3-4.3-2.3-4.9-4.4-2.3-.9,1.2-2.4,2.2-3.3,2.2-1.6,0-2.3-1.2-5.1-8.3l-.8-2.1-1.3,3.1c-1.6,4-3.3,3.3-4.1-1.6l-.6-3.8-1.8,2.3-1.8,2.3-17.8-10.3c-17.1-9.9-17.8-10.4-19.4-14.1-1.7-3.9-6.9-10.1-8.6-10.1s-1.8-.8-2.7-1.9l-1.8-1.9,4.1-5.4,4.1-5.4-3.9-.8-3.9-.8,4.1-2.2,4.1-2.2-4.4-2.3c-4.7-2.5-5.6-4.8-2.9-7.5,1.3-1.3,1.3-1.5-.2-3-1.4-1.6-1.4-1.7,0-3.3,1.3-1.5,1.3-1.8.2-3-2.4-2.4-1.6-4.5,2.9-7.3l4.3-2.7-4-2.1-4-2.1,3.9-.8,3.9-.7-4.2-5.4-4.2-5.4,1.9-2,1.9-2,11.1,11.1,11.1,11.1v12.8l1.8-.3c1.1-.2,8.9-1.4,17.4-2.8,21-3.4,19.2-2.7,19.2-6.7v-3.3h25.9v3.3c0,3.9-1.9,3.3,19.2,6.8,8.5,1.4,16,2.5,17,2.7.7.2,2,.3,2,.3,0,0,.2-2.3.2-6.2v-6.6l10-10c7.7-7.7,10.3-9.8,11-9,1.1,1.1,1.2.9-4.5,7.9l-3.2,3.9,4.3.6,4.3.6-4.4,2.3-4.4,2.3,4.7,2.7c2.6,1.4,4.7,3.2,4.7,3.8s-.7,2.1-1.8,3.3l-1.8,2.2,2.2,1c2,.9,2.9,2.3,1.5,2.4-.3,0-1.3.6-2.2,1.2-1.5,1.1-1.4,1.3.3,2.9,2.6,2.6,1.8,4.3-3.3,7l-4.5,2.4,4.4,2.3,4.4,2.3-3.9.6c-2.2.3-3.9.8-3.9,1s1.7,2.6,3.7,5.3c2.1,2.7,3.8,5.2,3.7,5.6,0,.4-2.7,2.9-5.9,5.6-4.1,3.5-6.5,6.3-8.2,9.7l-2.4,4.8-17.7,10.2-17.7,10.2-2-2.3-2-2.3v2.9c0,5.6-1.3,5.6-3.3,0-1-2.8-2-5.1-2.1-5.1s-1.4,3.1-2.9,6.9c-1.5,3.8-3,7.2-3.3,7.6s-1.7-.3-2.9-1.5c-1.3-1.3-2.3-2.1-2.4-2s-.8,1.3-1.4,2.6l-1.3,2.3-.8-3.6ZM189.4,257.6l9.7-2.7,11.2,2.7c5.8,1.5,10.7,2,10.9,1.8.9-.9-1.2-2-6.5-3.3-3-.8-7.4-1.9-9.9-2.7l-4.4-1.7.3-8.8.2-9.3,12.4-7.8c6.8-4.3,12.6-7.9,12.9-8.2s-11.6-.5-26.4-.5-26.8.3-26.8.7,5.6,4,12.4,8.2l12.3,7.6v18.2l-9.5,3.4c-5.3,1.4-9.7,3-9.9,3.6-.5,1.3-.7,1.8,11.2-1.3h0ZM188,182.7v-5.3l-18.6-3.1c-10.3-1.7-19.5-2.9-19.8-3.1v9.5l-8.7-8.7c-4.8-4.8-8.6-9.2-8.5-9.8s.8-1.8,1.4-2.6,2.7-3.7,4.3-6.3c2.5-3.9,3.6-4.8,6.1-5.3,1.7-.3,4.5-1.8,6.4-3.4,2.6-2.1,3.9-2.7,5.4-2.4,1.9.5,3.2-.5,8.3-6.9l1.5-1.9,5.4,4.3,5.4,4.3.9-4.1.9-4.1,2,4c1.1,2.2,2.2,4,2.5,4s1.4-1.9,2.5-4.2c2.2-4.6,4-5.3,6.9-2.7,1.6,1.4,1.7,1.3,3.6-1.1,1.1-1.3,2-2.1,2-1.6s.5,1.6,1.1,2.3c1,1.4,1.3,1.4,4.1-.3l3-1.8,2.7,5,2.7,5,2.2-4.3,2.2-4.3.6,4c.3,2.2.8,4,.9,4s2.7-1.8,5.7-4.2l5.3-4.2,3.8,4.5c3.3,3.8,4.3,4.5,6.7,4.4,2.1,0,3.5.6,5.4,2.5,1.6,1.6,3.8,2.8,5.8,3.1,2.8.5,3.6,1.2,6.7,6.1,1.9,3.1,5,6.7,6.8,7.9s3.3,2.6,3.3,2.9-3.4,3.9-7.5,8.1l-7.5,7.5v-4.7c0-2.7-.3-4.8-.7-4.8s-8.9,1.3-19.1,3l-18.8,3.3v4.8l-12.4.3c-6.7.3-11.8,0-13.3,0h0Z"/>
<g>
<circle class="cls-2" cx="188.4" cy="236.7" r="1.7"/>
<circle class="cls-2" cx="181.7" cy="236.7" r="1.7"/>
<circle class="cls-2" cx="175" cy="236.7" r="1.7"/>
<circle class="cls-2" cx="181.7" cy="243.4" r="1.7"/>
<circle class="cls-2" cx="188.4" cy="243.4" r="1.7"/>
<circle class="cls-2" cx="175" cy="243.4" r="1.7"/>
<circle class="cls-2" cx="181.7" cy="250.1" r="1.7"/>
<circle class="cls-2" cx="208.5" cy="236.7" r="1.7"/>
<circle class="cls-2" cx="215.1" cy="236.7" r="1.7"/>
<circle class="cls-2" cx="221.8" cy="236.7" r="1.7"/>
<circle class="cls-2" cx="208.5" cy="243.4" r="1.7"/>
<circle class="cls-2" cx="215.1" cy="243.4" r="1.7"/>
<circle class="cls-2" cx="221.8" cy="243.4" r="1.7"/>
<circle class="cls-2" cx="215.1" cy="250.1" r="1.7"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 7.0 KiB

View File

@@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024">
<circle cx="512" cy="512" r="512" fill="#9a2857"/>
<path d="M727 278.6q-99 37.09-197.74 74.76a27.83 27.83 0 0 1-20.85.41q-102.54-36.2-205.09-72.35c-4.45-1.57-9-2.82-14.22-4.56v469.89c3.42-1.16 5.67-1.83 7.84-2.7 69-28.07 138.13-55.9 206.95-84.41a34.06 34.06 0 0 1 29.52.36c66.62 29.54 133.53 58.41 201.5 88V276c-3.35 1.09-5.67 1.74-7.91 2.6Zm-208 339-.57-225.6c18.21-6.66 36.44-13.21 54.6-20 42.69-15.8 85.34-31.83 129.09-48.23v373.44C640.57 671 579.79 644.3 519 617.63Zm162.1-107a14 14 0 0 1-12.86 13.31 14.34 14.34 0 0 1-13.66-12.66c-.32-5.93 6.92-13.46 13-13.53a14.58 14.58 0 0 1 13.51 12.88Z" fill="#fff"/>
</svg>

After

Width:  |  Height:  |  Size: 683 B

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 9.4 KiB

View File

@@ -0,0 +1,44 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: $$$/GeneralStr/196=Adobe Illustrator 27.6.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 518.4 476.9" style="enable-background:new 0 0 518.4 476.9;" xml:space="preserve">
<style type="text/css">
.st0{fill:#4D6BDD;}
.st1{fill:#FFFFFF;}
.st2{fill:#FFD749;}
.st3{fill:#FF6B4A;}
.st4{fill:#89A3F4;}
.st5{fill:#FCE088;}
.st6{fill:#FC9381;}
.st7{fill:#C2D3FF;}
.st8{fill:#FCECC0;}
.st9{fill:#F9BEB7;}
</style>
<g>
<g>
<ellipse transform="matrix(0.7071 -0.7071 0.7071 0.7071 -94.1312 252.3384)" class="st0" cx="257.5" cy="239.8" rx="237.1" ry="237.1"/>
<g>
<g>
<g>
<path class="st1" d="M350.6,211.4c-8.9-9.6-12.2-30.5-12.2-30.5l-2.6-12c0,0-3.1-11.3-5.4-14.6c-1-2.6-2.8-9.7,3.5-16.9
c0,0,6.3-8.1-2.8-14.6c0,0-10-8.3-17.2,1.2c0,0-6.7,12.3-16.4,10.4c-2.6-0.7-4.3-1-4.3-1s-21.7-4.2-35.7-4.3
c-14,0-35.7,4.3-35.7,4.3s-1.6,0.3-4.3,1c-9.6,1.8-16.4-10.4-16.4-10.4c-7.2-9.6-17.2-1.2-17.2-1.2c-9.2,6.6-2.8,14.6-2.8,14.6
c6.3,7.2,4.5,14.4,3.5,16.9c-2.3,3.4-5.4,14.6-5.4,14.6l-2.6,12c0,0-3.3,20.8-12.2,30.5c0,0-60.2,54.1-19.4,109.4
c0,0,26.8,31.8,71,7.2c0,0,20.6-11.4,41.5-11.5c20.8,0,41.5,11.5,41.5,11.5c44.2,24.6,70.9-7.2,70.9-7.2
C410.8,265.5,350.6,211.4,350.6,211.4z M217.8,257.2c-4.2,5.6-14.6,5-23.2-1.4c-8.6-6.4-12.2-16.2-8-21.8
c4.2-5.6,14.6-5,23.2,1.4C218.4,241.8,222,251.6,217.8,257.2z M224.8,196.7c-7.6,0-13.8-7.1-13.8-12.4h11.4
c1.3,0,1.7-2.2,0.9-3.3l-7.2-9.6c2.4-1.9,5.4-3.4,8.7-3.4c7.6,0,13.8,6.7,13.8,14.3C238.7,190,232.5,196.7,224.8,196.7z
M276.4,184.3h11.4c1.3,0,1.7-2.2,0.9-3.3l-7.2-9.6c2.4-1.9,5.4-3.4,8.7-3.4c7.6,0,13.8,6,13.8,13.6c0,7.6-6.2,15.2-13.8,15.2
C282.6,196.8,276.4,189.6,276.4,184.3z M320.5,254.4c-8.6,6.4-19,7-23.2,1.4c-4.2-5.7-0.6-15.4,8-21.8c8.6-6.4,19-7,23.2-1.4
C332.7,238.2,329.2,248,320.5,254.4z"/>
</g>
<g>
<path class="st1" d="M257.6,331.6c-27.6,0-39.9,15.3-39.9,15.3s-12.4,13.4,39.9,13.4c52.3,0,39.9-13.4,39.9-13.4
S285.2,331.6,257.6,331.6z"/>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@@ -0,0 +1,243 @@
<svg width="86" height="79" version="1.1" viewBox="0 0 86 79" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><image width="86" height="79" preserveAspectRatio="none" xlink:href="data:image/png;base64,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
AAvYWZcFHibQAAAAAElFTkSuQmCC
"/></svg>

After

Width:  |  Height:  |  Size: 18 KiB

View File

@@ -0,0 +1,163 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
version="1.1"
id="svg1"
width="533.33331"
height="533.33331"
viewBox="0 0 533.33331 533.33331"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs1">
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath6">
<path
d="M 0,400 H 400 V 0 H 0 Z"
transform="translate(-199.8565,-316.05771)"
id="path6" />
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath8">
<path
d="M 0,400 H 400 V 0 H 0 Z"
transform="translate(-154.47981,-66.407704)"
id="path8" />
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath10">
<path
d="M 0,400 H 400 V 0 H 0 Z"
transform="translate(-173.84721,-187.2259)"
id="path10" />
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath12">
<path
d="M 0,400 H 400 V 0 H 0 Z"
transform="translate(-224.58621,-187.2259)"
id="path12" />
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath14">
<path
d="M 0,400 H 400 V 0 H 0 Z"
transform="translate(-116.893,-254.432)"
id="path14" />
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath16">
<path
d="M 0,400 H 400 V 0 H 0 Z"
transform="translate(-245.23801,-66.407704)"
id="path16" />
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath18">
<path
d="M 0,400 H 400 V 0 H 0 Z"
transform="translate(-282.99751,-254.432)"
id="path18" />
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath20">
<path
d="M 0,400 H 400 V 0 H 0 Z"
transform="translate(-179.5,-68.443902)"
id="path20" />
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath22">
<path
d="M 0,400 H 400 V 0 H 0 Z"
id="path22" />
</clipPath>
</defs>
<g
id="layer-MC1">
<path
id="path1"
d="m 0,0 -45.38,24.103 -5.988,3.182 -2.203,6.628 -11.87,35.716 -20.153,16.347 -62.304,50.532 -10.044,8.146 5.074,11.876 35.049,82.011 -4.269,75.046 -2.054,36.132 29.25,-21.284 49.904,-36.312 48.547,13.344 4.5,1.236 4.498,-1.236 48.548,-13.344 49.903,36.312 29.251,21.284 -2.054,-36.132 -4.269,-75.046 35.048,-82.011 5.074,-11.876 -10.043,-8.146 L 101.711,85.976 81.557,69.629 69.687,33.913 67.484,27.285 61.497,24.103 16.117,0 8.059,-4.281 Z M -23.274,51.29 8.059,34.649 39.39,51.29 l 15.394,46.323 0.941,2.35 21.632,42.862 32.587,64.568 -9.139,21.384 -1.57,3.673 0.227,3.987 2.44,42.897 -27.26,-19.837 -6.61,-4.809 -7.964,2.189 -52.009,14.297 -52.012,-14.297 -7.962,-2.189 -6.609,4.809 -27.262,19.837 2.44,-42.897 0.227,-3.987 -1.57,-3.673 -9.138,-21.382 32.588,-64.57 21.631,-42.862 0.94,-2.35 z m -70.522,85.48 -3.125,63.385 -19.311,-45.188 z m 226.146,18.197 -19.311,45.184 -3.128,-63.381 z"
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
transform="matrix(1.3333333,0,0,-1.3333333,255.73453,496.95893)" />
<path
id="path2"
d="m 0,0 -45.38,24.104 -17.597,52.95 -21.632,42.862 1.767,-35.821 -62.304,50.532 36.618,85.685 -4.495,79.032 56.513,-41.123 56.51,15.534 56.51,-15.534 56.513,41.123 -4.496,-79.032 36.618,-85.685 L 82.841,84.095 84.608,119.916 62.976,77.054 45.379,24.104 Z"
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none"
transform="matrix(1.3333333,0,0,-1.3333333,266.47933,476.71373)" />
<path
id="path3"
d="m 0,0 -45.379,24.104 -3.421,1.818 -1.26,3.787 -17.324,52.131 -0.561,1.11 0.572,-11.603 -17.042,13.823 -62.303,50.532 -5.739,4.654 2.899,6.787 35.721,83.585 -4.365,76.755 -1.174,20.647 16.714,-12.163 52.736,-38.374 51.96,14.283 2.571,0.706 2.57,-0.706 51.961,-14.283 52.735,38.374 16.715,12.163 -1.174,-20.647 -4.365,-76.755 35.721,-83.585 2.898,-6.787 -5.739,-4.654 L 93.625,85.17 76.583,71.347 77.155,82.95 76.594,81.84 59.269,29.709 58.01,25.922 54.588,24.104 9.21,0 4.605,-2.446 Z m -32.748,39.639 37.353,-19.84 37.352,19.84 16.338,49.163 0.538,1.344 21.633,42.861 20.806,41.226 -2.274,-46.102 -0.688,-13.936 39.523,32.055 -33.717,78.899 -0.898,2.099 0.129,2.277 3.323,58.385 -39.799,-28.96 -3.777,-2.748 -4.55,1.251 -53.939,14.827 -53.939,-14.827 -4.55,-1.251 -3.777,2.748 -39.798,28.96 3.32,-58.385 0.131,-2.277 -0.898,-2.099 -33.718,-78.899 39.523,-32.056 -0.687,13.937 -2.274,46.101 20.807,-41.225 21.632,-42.861 0.537,-1.344 z"
style="fill:#000d26;fill-opacity:1;fill-rule:nonzero;stroke:none"
transform="matrix(1.3333333,0,0,-1.3333333,260.33933,488.498)" />
<path
id="path4"
d="m 0,0 -45.38,24.104 -17.597,52.95 -21.632,42.862 1.767,-35.821 -62.304,50.532 36.618,85.685 -4.495,79.032 56.513,-41.123 56.51,15.534 56.51,-15.534 56.513,41.123 -4.496,-79.032 36.618,-85.685 L 82.841,84.095 84.608,119.916 62.976,77.054 45.379,24.104 Z"
style="fill:#008fe8;fill-opacity:1;fill-rule:evenodd;stroke:none"
transform="matrix(1.3333333,0,0,-1.3333333,266.47933,476.92973)" />
<path
id="path5"
d="m 0,0 56.511,-15.533 56.513,41.122 -4.496,-79.032 36.62,-85.685 -62.306,-50.532 1.767,35.821 L 62.013,-196.22 45.378,-249.65 0,-273.754 l -0.665,0.353 c 0,0 -3.805,-0.865 -0.53,26.953 3.274,27.818 -1.05,78.74 -2.395,121.674 v -0.001 l -9.525,-8.658 8.842,43.362 -20.08,-8.665 19.549,35.619 -24.589,-4.137 17.15,23.546 -27.686,-9.391 29.551,40.46 -46.132,-2.894 55.845,15.351 z"
style="fill:#3bb4ff;fill-opacity:1;fill-rule:evenodd;stroke:none"
transform="matrix(1.3333333,0,0,-1.3333333,266.47533,111.92307)"
clip-path="url(#clipPath6)" />
<path
id="path7"
d="m 0,0 -17.596,52.949 -21.633,42.862 1.766,-35.821 -62.303,50.532 36.618,85.685 -4.464,78.475 41.419,-97.788 -27.817,11.282 -5.738,-35.7 -7.627,16.399 -3.771,-32.944 -4.781,12.116 -13.554,-35.107 26.294,-23.118 0.958,21.19 14.583,-29.362 0.109,44.478 33.394,-60.557 2.569,14.938 L 4.8,3.564 l 36.833,-19.011 -1.88,-5.67 z"
style="fill:#00619e;fill-opacity:1;fill-rule:evenodd;stroke:none"
transform="matrix(1.3333333,0,0,-1.3333333,205.97307,444.78973)"
clip-path="url(#clipPath8)" />
<path
id="path9"
d="M 0,0 -50.69,20.972 -39.263,-3.23 -3.426,-14.233 8.692,-27.173 Z"
style="fill:#000d26;fill-opacity:1;fill-rule:evenodd;stroke:none"
transform="matrix(1.3333333,0,0,-1.3333333,231.79627,283.6988)"
clip-path="url(#clipPath10)" />
<path
id="path11"
d="M 0,0 50.691,20.972 39.263,-3.23 3.427,-14.233 -8.692,-27.173 Z"
style="fill:#000d26;fill-opacity:1;fill-rule:evenodd;stroke:none"
transform="matrix(1.3333333,0,0,-1.3333333,299.44827,283.6988)"
clip-path="url(#clipPath12)" />
<path
id="path13"
d="m 0,0 -35.476,9.923 5.419,77.292 14.697,-70.121 z"
style="fill:#000d26;fill-opacity:1;fill-rule:evenodd;stroke:none"
transform="matrix(1.3333333,0,0,-1.3333333,155.85733,194.09067)"
clip-path="url(#clipPath14)" />
<path
id="path15"
d="M 0,0 17.597,52.949 39.23,95.811 37.463,59.99 l 62.304,50.532 -36.619,85.685 4.464,78.475 -41.418,-97.788 27.817,11.282 5.738,-35.7 7.626,16.399 3.771,-32.944 4.783,12.116 L 89.481,112.94 62.061,88.694 61.666,119.06 48.773,79.076 47.538,126.128 14.144,65.571 11.575,80.509 -4.799,3.564 l -36.834,-19.011 1.881,-5.67 z"
style="fill:#d6efff;fill-opacity:1;fill-rule:evenodd;stroke:none"
transform="matrix(1.3333333,0,0,-1.3333333,326.984,444.78973)"
clip-path="url(#clipPath16)" />
<path
id="path17"
d="M 0,0 35.304,9.923 30.056,87.215 15.36,17.094 Z"
style="fill:#000d26;fill-opacity:1;fill-rule:evenodd;stroke:none"
transform="matrix(1.3333333,0,0,-1.3333333,377.33,194.09067)"
clip-path="url(#clipPath18)" />
<path
id="path19"
d="M 0,0 20.501,-11.245 41,0 v 7.634 9.868 L 29.715,22.437 20.462,26.512 11.197,22.437 0,17.502 V 7.634 Z"
style="fill:#000d26;fill-opacity:1;fill-rule:evenodd;stroke:none"
transform="matrix(1.3333333,0,0,-1.3333333,239.33333,442.0748)"
clip-path="url(#clipPath20)" />
<path
id="path21"
d="m 194.5,66.895 h 11 v -28 h -11 z"
style="fill:#000d26;fill-opacity:1;fill-rule:evenodd;stroke:none"
transform="matrix(1.3333333,0,0,-1.3333333,0,533.33333)"
clip-path="url(#clipPath22)" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 8.5 KiB

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
id="Layer_1"
width="121.48518"
height="55.305733"
x="0"
y="0"
enable-background="new 0 0 196.6 72"
version="1.1"
viewBox="0 0 113.89219 51.848675"
xml:space="preserve"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><metadata
id="metadata20" /><defs
id="defs18" /><path
id="path1052"
d="M 57.032896,-3.3856248e-4 C 45.227625,-3.3856248e-4 35.221679,8.0028574 32.120504,18.846282 29.425259,13.094765 23.58457,9.0653444 16.85711,9.0653444 7.60526,9.0653444 0,16.670607 0,25.922452 c 0,9.251833 7.60526,16.860567 16.85711,16.860567 6.72746,0 12.568149,-4.031885 15.263395,-9.784412 3.101175,10.84425 13.10712,18.850106 24.912391,18.850106 11.717964,0 21.67289,-7.885111 24.853382,-18.607048 2.745036,5.621934 8.513436,9.541354 15.145342,9.541354 9.25185,0 16.86057,-7.608734 16.86057,-16.860567 0,-9.251845 -7.60872,-16.8571076 -16.86057,-16.8571076 -6.631906,0 -12.400306,3.9169646 -15.145342,9.5378906 C 78.705786,7.8821364 68.75086,-3.3856248e-4 57.032896,-3.3856248e-4 Z m 0,9.89551796248 c 8.911648,0 16.030748,7.1156526 16.030748,16.0272726 0,8.911605 -7.1191,16.030737 -16.030748,16.030737 -8.911593,0 -16.027247,-7.119132 -16.027247,-16.030737 0,-8.91162 7.115653,-16.0272706 16.027247,-16.0272726 z M 16.85711,18.960863 c 3.90438,0 6.96505,3.057188 6.96505,6.961589 0,3.904386 -3.06067,6.965049 -6.96505,6.965049 -3.90439,0 -6.96161,-3.060663 -6.96161,-6.965049 0,-3.904401 3.05722,-6.961589 6.96161,-6.961589 z m 80.17451,0 c 3.90442,0 6.96506,3.057188 6.96506,6.961589 0,3.904386 -3.06066,6.965049 -6.96506,6.965049 -3.90436,0 -6.961576,-3.060663 -6.961576,-6.965049 0,-3.904401 3.057226,-6.961589 6.961576,-6.961589 z"
style="color:#000000;font-style:normal;font-variant:normal;font-weight:400;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#0082c9;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:5.5659;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" /></svg>

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="550.00049"
height="398.08325"
viewBox="0 0 550.00049 398.08325"
fill="none"
version="1.1"
id="svg1"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs1" />
<path
d="m 141.11125,269.62825 133.889,-77.073 223.151,128.456 -133.892,77.072 z m -104.137,-59.944 c -49.299,-28.379 -49.299,-74.387 0,-102.763 l 44.63,-25.693 133.889,77.073 -133.889,77.073 z m 297.533,-51.383 133.889,-77.073 44.63,25.693 c 49.299,28.376 49.299,74.384 0,102.763 l -44.63,25.69 z m -193.396,-111.327 44.63,-25.69 c 49.296,-28.379 129.222,-28.379 178.518,0 l 44.63,25.69 -133.889,77.073 z"
fill="#ffffff"
id="path1"
style="fill:#009991;fill-opacity:1" />
</svg>

After

Width:  |  Height:  |  Size: 794 B

View File

@@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 960 960">
<path fill="#000000" d="M494.86,409.59l-37.52-83.51h-35.35v1.44c2.89,2.52,4.69,9.56,4.69,17.31v80.63c0,12.8-1.62,19.12-4.33,21.83v1.44h20.56s0-1.44,0-1.44c-2.71-2.71-5.41-7.22-5.41-21.83v-80.99s46.18,104.26,46.18,104.26h5.23l46.19-104.61v84.05c0,10.1-1.62,16.42-4.33,19.12v1.44h34.81s0-1.44,0-1.44c-2.71-2.71-4.33-9.01-4.33-19.12v-83.34c0-7.76,1.81-14.79,4.69-17.31v-1.44h-34.09l-36.98,83.51h0ZM378.21,373.87v-20.2h-.73l-31.03,11.19v1.27c3.79,3.25,6.49,10.28,6.49,20.92v41.12c0,10.1-1.62,16.42-4.33,19.12v1.44h35.71s0-1.44,0-1.44c-3.06-2.35-6.14-6.68-6.14-19.12v-47.98c3.79-3.6,9.56-5.6,16.96-5.6,6.14,0,11.9,1.08,16.23,3.25h1.44s0-22.54,0-22.54c-1.62-.36-3.97-.54-6.49-.54-12.44,0-22.37,8.66-28.14,19.12h.01Z"/>
</svg>

After

Width:  |  Height:  |  Size: 784 B

View File

@@ -0,0 +1 @@
<svg id="Lager_1" data-name="Lager 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 189.11 188.93"><defs><style>.cls-1{fill:#fff;}</style></defs><path d="M515.5,279.22a94.56,94.56,0,1,1-94.56-94.47A94.51,94.51,0,0,1,515.5,279.22Z" transform="translate(-326.39 -184.75)"/><path class="cls-1" d="M388.45,300.05c-1.94,8.41-12.59,1.73-15.15,12-2.42,9.71,7.54,19.77,1.62,19.42-8.11-.48-18-2.84-12.78,11.64-2.5-16.77,14.88-4.2,18.93-9.7s-5.92-19.23,2.81-19.12,11.89,2,15.58-3.46C395.14,308,392.36,305.21,388.45,300.05Z" transform="translate(-326.39 -184.75)"/><path class="cls-1" d="M412.37,239.33c11.71-12.4-2.75-9.08-2.75-18.16.07-5.18,15.13-6.72,17.07-12s-20.14-9.51-5.84-18.11c-8.05,11.07,10.86,9.87,10.43,18.11-.36,6.62-11.08,9-11.08,12.07-.21,5.56,15.66,5.72,9.2,18.3A39.57,39.57,0,0,0,412.37,239.33Z" transform="translate(-326.39 -184.75)"/><path class="cls-1" d="M442.81,245.1c1.86-4.54,6-10.44,14.59-8,14.41,4.09,1.48-9.39,10.51-14.21,7.66-4.11,11.06,6.13,20.79,3.31-6.61,7.84-14.16-4.16-18.5,2.24-3.85,5.66,3.15,11.12.91,15.22-3.51,6.36-10.36.78-13.8,3.33s-3,6.88-3,10.37C451.87,252.48,447.08,248.24,442.81,245.1Z" transform="translate(-326.39 -184.75)"/><path class="cls-1" d="M459.71,270.1c10.31,9.5,11-3.49,17.62-3.5,5.78,0,8.12,17.32,14.11,17.51,6.79.2,10.64-15.69,18.73-5-9.61-5.29-11.14,9.84-18.53,10-10.84.18-11.22-12.56-14.53-12.56-4.54.22-4.5,17.44-17.9,10.43A36.93,36.93,0,0,0,459.71,270.1Z" transform="translate(-326.39 -184.75)"/><path class="cls-1" d="M441.56,311.37c8.81,5.91.67,11.88,5.51,16.58,3.45,3.31,13.88-4,18.59-2.52,3,1-2.63,9.82,1.92,13.41,3.83,3,11.91,2.08,15.82-.8-5.36.62-11.13,1.45-13.45-3.86s3.81-12.27,1.3-15.35c-2.19-2.67-16,5.2-15-4.28.43-3.77,3.15-12-2.92-14.27A40.5,40.5,0,0,1,441.56,311.37Z" transform="translate(-326.39 -184.75)"/><path class="cls-1" d="M412.93,316.48c-2.42,10.89,6.09,12.37,6.25,16.28.24,5.88-9.29,6.94-9.12,14.06.11,4.61,16.23,9.05,10.49,18.07,8.06-6.25-4-13.61-3.82-17.92.29-8,14.07-6.12,13.8-15.05-.21-7.85-6.11-5.67-.93-15.45A42.33,42.33,0,0,1,412.93,316.48Z" transform="translate(-326.39 -184.75)"/><path class="cls-1" d="M382.27,270.8c-13.19-4.74-16.29,11-20,10.81S354,266,349.36,270.07c-8.09,7.13-6.68,12.48-14.61,9.24,7.33,7.23,9.09-1.91,15-5.25,5-2.8,4.85,16.63,12.69,16.83,4.33.11,9.5-7,12.18-7a11.29,11.29,0,0,1,8.15,3.9A39,39,0,0,1,382.27,270.8Z" transform="translate(-326.39 -184.75)"/><path class="cls-1" d="M387.73,257.21c-8.38-2.34-6.54-10.82-5.79-16.22.72-5.23.37-8.75-8-3.9s-14.66-4.52-9.71-9.8c4.33-4.63-2-7.48-6.53-6.16,1.56-1.92,9.08-5.59,11.55,2,1.34,4.12-2.73,7.4-.53,9.09,4.09,3.13,9.78-8.44,16.32-6.12,5.79,2.06,3.4,6.33,5.69,13.72,1.09,3.47,3.89,5.43,7.74,5.77A38.31,38.31,0,0,0,387.73,257.21Z" transform="translate(-326.39 -184.75)"/><path class="cls-1" d="M409.85,272.86c-2.28-.32-1.89-2.08-1.89-2.08l-2.61-1s-.83,5.07,4.25,5.06c4.82,0,5.61-2.24,5.68-2.75a31,31,0,0,0-3.14-.53C411.75,272.16,411.73,273.13,409.85,272.86Z" transform="translate(-326.39 -184.75)"/><path class="cls-1" d="M434.69,270.35a1.63,1.63,0,0,1-1.34,2.51c-1.88.27-2.14-.57-2.41-1.42-1,.19-2.36.33-3.45.57.07.52,1.72,3.07,6.46,2.23,5.18-.92,3.34-5,3.34-5S435.55,270,434.69,270.35Z" transform="translate(-326.39 -184.75)"/><path class="cls-1" d="M420.74,293.72c-14.62.21-22.05-3.89-23.72-5.91-.63,2.23,7,17.47,24.38,17.32C440.23,305,445,287.89,445,285.06,442.31,288.11,439.06,293.44,420.74,293.72Z" transform="translate(-326.39 -184.75)"/><path class="cls-1" d="M420.91,241.27a36.51,36.51,0,1,0,36.51,36.51A36.5,36.5,0,0,0,420.91,241.27ZM422,267.54c1.51,3,.26,4.91,10.47,1.74,3.82-1.17,10.61-7.94,16.46-1.64-4.15-3.13-9.22-.58-8.93,1.15-.19.92.14,5-5.42,6.26-5.32,1.19-7.78-1.85-8.5-2.64C422.12,272.47,421.79,269.07,422,267.54Zm1.77,14.94c-1.27.94,1.15-2.3,2.81-1.6s-1,4.28-.31,2.09C426.83,281.18,425.19,281.39,423.74,282.48Zm-13-12.82c10,2.92,9.33.72,9.67-.19.11.66-.11,3-4.05,2.94-.71.79-.92,3.65-6.58,3.61-6.84,0-7.21-5.11-7.31-6.29-.21-2.68-5.71-2.67-8.31-2.09C400.29,264.68,406.86,268.54,410.7,269.66Zm6.4,14.28c.33,1.19-2.53-1.32-.3-2.14s3.53,1.73,3,1.33C418.21,282,416.5,281.71,417.1,283.94Zm29.71,0c-.65,7-5.71,21.68-25.34,21.87-16.91.16-25.79-11.3-26.29-18.11-1.12,1.22-1.7,3.22-1.68,5.77-.48-1.06-1.07-6,1.56-8a3.56,3.56,0,0,1,3.33-.23c-1.24.65-.88.25-1.34.72.66,1.63,8.88,7.06,23.49,7.05,16.14,0,22-5.63,24.36-10.67a4.44,4.44,0,0,0-2.6-1.14,5.06,5.06,0,0,1,4.78.25c1.65,1.14,2.74,4.23,2.6,7.56C449.46,287.4,448.4,284.46,446.81,284Z" transform="translate(-326.39 -184.75)"/></svg>

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

@@ -82,8 +82,6 @@ PODS:
- qr_code_scanner (0.2.0):
- Flutter
- MTBBarcodeScanner
- scan (0.0.1):
- Flutter
- SDWebImage (5.20.0):
- SDWebImage/Core (= 5.20.0)
- SDWebImage/Core (5.20.0)
@@ -146,7 +144,6 @@ DEPENDENCIES:
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
- privacy_screen (from `.symlinks/plugins/privacy_screen/ios`)
- qr_code_scanner (from `.symlinks/plugins/qr_code_scanner/ios`)
- scan (from `.symlinks/plugins/scan/ios`)
- sentry_flutter (from `.symlinks/plugins/sentry_flutter/ios`)
- share_plus (from `.symlinks/plugins/share_plus/ios`)
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
@@ -208,8 +205,6 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/privacy_screen/ios"
qr_code_scanner:
:path: ".symlinks/plugins/qr_code_scanner/ios"
scan:
:path: ".symlinks/plugins/scan/ios"
sentry_flutter:
:path: ".symlinks/plugins/sentry_flutter/ios"
share_plus:
@@ -250,7 +245,6 @@ SPEC CHECKSUMS:
path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46
privacy_screen: 1a131c052ceb3c3659934b003b0d397c2381a24e
qr_code_scanner: bb67d64904c3b9658ada8c402e8b4d406d5d796e
scan: aea35bb4aa59ccc8839c576a18cd57c7d492cc86
SDWebImage: 73c6079366fea25fa4bb9640d5fb58f0893facd8
Sentry: f8374b5415bc38dfb5645941b3ae31230fbeae57
sentry_flutter: 0eb93e5279eb41e2392212afe1ccd2fecb4f8cbe

View File

@@ -63,6 +63,8 @@
<string>Main</string>
<key>UIStatusBarHidden</key>
<false/>
<key>FlutterDeepLinkingEnabled</key>
<false/>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>

View File

@@ -88,6 +88,8 @@
"useRecoveryKey": "Utilizza un codice di recupero",
"incorrectPasswordTitle": "Password sbagliata",
"welcomeBack": "Bentornato!",
"emailAlreadyRegistered": "Email già registrata.",
"emailNotRegistered": "Email non registrata.",
"madeWithLoveAtPrefix": "realizzato con ❤️ a ",
"supportDevs": "Iscriviti a <bold-green>ente</bold-green> per supportare questo progetto.",
"supportDiscount": "Utilizzare il codice coupon \"AUTH\" per ottenere il 10% di sconto al primo anno",

View File

@@ -88,6 +88,8 @@
"useRecoveryKey": "Herstelsleutel gebruiken",
"incorrectPasswordTitle": "Onjuist wachtwoord",
"welcomeBack": "Welkom terug!",
"emailAlreadyRegistered": "E-mail is al geregistreerd.",
"emailNotRegistered": "E-mail niet geregistreerd.",
"madeWithLoveAtPrefix": "met ❤️ gemaakt door",
"supportDevs": "Abonneer u op <bold-green>ente</bold-green> om ons te steunen",
"supportDiscount": "Gebruik couponcode \"AUTH\" om het eerste jaar 10% korting te krijgen",

View File

@@ -88,6 +88,8 @@
"useRecoveryKey": "Använd återställningsnyckel",
"incorrectPasswordTitle": "Felaktigt lösenord",
"welcomeBack": "Välkommen tillbaka!",
"emailAlreadyRegistered": "E-postadress redan registrerad.",
"emailNotRegistered": "E-postadress ej registrerad.",
"madeWithLoveAtPrefix": "gjord med ❤️ av ",
"supportDevs": "Prenumerera på <bold-green>ente</bold-green> för att stödja oss",
"supportDiscount": "Använd kupongkoden \"AUTH\" för att få 10% rabatt första året",
@@ -321,7 +323,11 @@
"terminate": "Avsluta",
"thisDevice": "Den här enheten",
"thisEmailIsAlreadyInUse": "Denna e-postadress används redan",
"verificationFailedPleaseTryAgain": "Verifiering misslyckades, vänligen försök igen",
"yourVerificationCodeHasExpired": "Din verifieringskod har upphört att gälla",
"incorrectCode": "Felaktig kod",
"sorryTheCodeYouveEnteredIsIncorrect": "Tyvärr, den kod som du har angett är felaktig",
"authenticationFailedPleaseTryAgain": "Autentisering misslyckades, vänligen försök igen",
"authenticationSuccessful": "Autentisering lyckades!",
"twofactorAuthenticationSuccessfullyReset": "Tvåfaktorsautentisering återställd",
"incorrectRecoveryKey": "Felaktig återställningsnyckel",

View File

@@ -71,6 +71,7 @@ void main() async {
await WindowListenerService.instance.init();
WindowOptions windowOptions = WindowOptions(
size: WindowListenerService.instance.getWindowSize(),
maximumSize: const Size(8192, 8192),
);
await windowManager.waitUntilReadyToShow(windowOptions, () async {
await DirectoryUtils.migrateNamingChanges();
@@ -103,7 +104,12 @@ Future<void> _runInForeground() async {
final savedThemeMode = _themeMode(await AdaptiveTheme.getThemeMode());
return await _runWithLogs(() async {
_logger.info("Starting app in foreground");
await _init(false, via: 'mainMethod');
try {
await _init(false, via: 'mainMethod');
} catch (e, s) {
_logger.severe("Failed to init", e, s);
rethrow;
}
final Locale? locale = await getLocale(noFallback: true);
unawaited(UpdateService.instance.showUpdateNotification());
runApp(
@@ -155,7 +161,7 @@ void _registerWindowsProtocol() {
Future<void> _init(bool bool, {String? via}) async {
_registerWindowsProtocol();
await initCryptoUtil();
await CryptoUtil.init();
await PreferenceService.instance.init();
await CodeStore.instance.init();

View File

@@ -7,7 +7,5 @@ String twoFactorTypeToString(TwoFactorType type) {
return "totp";
case TwoFactorType.passkey:
return "passkey";
default:
return type.name;
}
}

View File

@@ -364,12 +364,13 @@ class _SetupEnterSecretKeyPageState extends State<SetupEnterSecretKeyPage> {
widget.code?.display.copyWith(tags: selectedTags) ??
CodeDisplay(tags: selectedTags);
display.note = notes;
if (widget.code!.issuer != issuer) {
display.iconID = issuer.toLowerCase();
}
if (widget.code!.display.iconID != _customIconID.toLowerCase()) {
display.iconID = _customIconID.toLowerCase();
if (widget.code != null) {
if (widget.code!.issuer != issuer) {
display.iconID = issuer.toLowerCase();
}
if (widget.code!.display.iconID != _customIconID.toLowerCase()) {
display.iconID = _customIconID.toLowerCase();
}
}
display.iconSrc =

View File

@@ -689,7 +689,7 @@ class UserService {
"${_config.getHttpEndpoint()}/users/srp/create-session",
data: {
"srpUserID": srpAttributes.srpUserID,
"srpA": base64Encode(SRP6Util.encodeBigInt(A!)),
"srpA": base64Encode(SRP6Util.getPadded(A!, 512)),
},
);
final String sessionID = createSessionResponse.data["sessionID"];
@@ -705,7 +705,7 @@ class UserService {
data: {
"sessionID": sessionID,
"srpUserID": srpAttributes.srpUserID,
"srpM1": base64Encode(SRP6Util.encodeBigInt(clientM!)),
"srpM1": base64Encode(SRP6Util.getPadded(clientM!, 32)),
},
);
if (response.statusCode == 200) {

View File

@@ -1,10 +1,15 @@
import 'dart:async';
import 'dart:ui';
import 'package:flutter/widgets.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:window_manager/window_manager.dart';
class WindowListenerService {
static const double minWindowHeight = 320.0;
static const double minWindowWidth = 800.0;
static const double maxWindowHeight = 8192.0;
static const double maxWindowWidth = 8192.0;
late SharedPreferences _preferences;
WindowListenerService._privateConstructor();
@@ -17,20 +22,20 @@ class WindowListenerService {
}
Size getWindowSize() {
final double windowWidth = _preferences.getDouble('windowWidth') ?? 450.0;
final double windowHeight = _preferences.getDouble('windowHeight') ?? 800.0;
return Size(windowWidth, windowHeight);
final double windowWidth =
_preferences.getDouble('windowWidth') ?? minWindowWidth;
final double windowHeight =
_preferences.getDouble('windowHeight') ?? minWindowHeight;
final w = windowWidth.clamp(200.0, maxWindowWidth);
final h = windowHeight.clamp(400.0, maxWindowHeight);
return Size(w, h);
}
Future<void> onWindowResize() async {
final width = (await windowManager.getSize()).width;
final height = (await windowManager.getSize()).height;
// Save the window size to shared preferences
await _preferences.setDouble(
'windowWidth',
(await windowManager.getSize()).width,
);
await _preferences.setDouble(
'windowHeight',
(await windowManager.getSize()).height,
);
await _preferences.setDouble('windowWidth', width);
await _preferences.setDouble('windowHeight', height);
}
}

View File

@@ -64,22 +64,6 @@ class CodeStore {
return true;
}
Future<void> updateCodeIndex(Code code) async {
final key = code.generatedID!;
_cacheCodes.remove(key);
int deletedIndex = code.display.position;
_cacheCodes.forEach((key, c) async {
if (c.display.position > deletedIndex) {
Code updatedCode = c.copyWith(
display: c.display.copyWith(position: c.display.position - 1),
);
await addCode(updatedCode);
}
});
}
Future<List<Code>> getAllCodes({
AccountMode? accountMode,
bool sortCodes = true,
@@ -179,7 +163,6 @@ class CodeStore {
Future<void> removeCode(Code code, {AccountMode? accountMode}) async {
final mode = accountMode ?? _authenticatorService.getAccountMode();
await _authenticatorService.deleteEntry(code.generatedID!, mode);
await updateCodeIndex(code);
Bus.instance.fire(CodesUpdatedEvent());
}

View File

@@ -100,7 +100,7 @@ class _CodeWidgetState extends State<CodeWidget> {
@override
Widget build(BuildContext context) {
ignorePin = widget.sortKey == null || widget.sortKey == CodeSortKey.manual;
ignorePin = widget.sortKey != null && widget.sortKey == CodeSortKey.manual;
final colorScheme = getEnteColorScheme(context);
if (isMaskingEnabled != PreferenceService.instance.shouldHideCodes()) {
isMaskingEnabled = PreferenceService.instance.shouldHideCodes();
@@ -645,7 +645,12 @@ class _CodeWidgetState extends State<CodeWidget> {
firstButtonLabel: l10n.delete,
isCritical: true,
firstButtonOnTap: () async {
await CodeStore.instance.removeCode(widget.code);
try {
await CodeStore.instance.removeCode(widget.code);
} catch (e,s) {
logger.severe('Failed to delete code',e,s);
showGenericErrorDialog(context: context, error: e).ignore();
}
},
);
}

View File

@@ -210,7 +210,7 @@ class _MenuItemWidgetState extends State<MenuItemWidget> {
Future<void> _onTap() async {
if (executionStateNotifier.value == ExecutionState.inProgress ||
executionStateNotifier.value == ExecutionState.successful) return;
executionStateNotifier.value == ExecutionState.successful) {return;}
_debouncer.run(
() => Future(
() {
@@ -247,7 +247,7 @@ class _MenuItemWidgetState extends State<MenuItemWidget> {
void _onTapDown(details) {
if (executionStateNotifier.value == ExecutionState.inProgress ||
executionStateNotifier.value == ExecutionState.successful) return;
executionStateNotifier.value == ExecutionState.successful) {return;}
setState(() {
if (widget.pressedColor == null) {
hasPassedGestureCallbacks()
@@ -265,7 +265,7 @@ class _MenuItemWidgetState extends State<MenuItemWidget> {
void _onTapUp(details) {
if (executionStateNotifier.value == ExecutionState.inProgress ||
executionStateNotifier.value == ExecutionState.successful) return;
executionStateNotifier.value == ExecutionState.successful) {return;}
Future.delayed(
const Duration(milliseconds: 100),
() => setState(() {
@@ -276,7 +276,7 @@ class _MenuItemWidgetState extends State<MenuItemWidget> {
void _onCancel() {
if (executionStateNotifier.value == ExecutionState.inProgress ||
executionStateNotifier.value == ExecutionState.successful) return;
executionStateNotifier.value == ExecutionState.successful) {return;}
setState(() {
menuItemColor = widget.menuItemColor;
});

View File

@@ -1,5 +1,4 @@
import 'package:ente_auth/l10n/l10n.dart';
import 'package:ente_auth/services/auth_feature_flag.dart';
import 'package:ente_auth/theme/ente_theme.dart';
import 'package:ente_auth/ui/settings/data/import_page.dart';
import 'package:ente_auth/utils/navigation_util.dart';
@@ -10,13 +9,11 @@ import 'package:logging/logging.dart';
class HomeEmptyStateWidget extends StatelessWidget {
final VoidCallback? onScanTap;
final VoidCallback? onManuallySetupTap;
final VoidCallback? onImportFromGallery;
const HomeEmptyStateWidget({
super.key,
required this.onScanTap,
required this.onManuallySetupTap,
this.onImportFromGallery,
});
@override
@@ -62,23 +59,6 @@ class HomeEmptyStateWidget extends StatelessWidget {
),
),
const SizedBox(height: 18),
if (PlatformUtil.isMobile() &&
FeatureFlagService.instance
.isInternalUserOrDebugBuild())
SizedBox(
width: 400,
child: OutlinedButton(
onPressed: onImportFromGallery,
style: OutlinedButton.styleFrom(
padding: const EdgeInsets.symmetric(vertical: 8),
),
child: const Text(
"Import from gallery",
textAlign: TextAlign.center,
),
),
),
const SizedBox(height: 18),
SizedBox(
width: 400,
child: OutlinedButton(

View File

@@ -14,7 +14,6 @@ import 'package:ente_auth/models/code.dart';
import 'package:ente_auth/onboarding/model/tag_enums.dart';
import 'package:ente_auth/onboarding/view/common/tag_chip.dart';
import 'package:ente_auth/onboarding/view/setup_enter_secret_key_page.dart';
import 'package:ente_auth/services/auth_feature_flag.dart';
import 'package:ente_auth/services/preference_service.dart';
import 'package:ente_auth/services/user_service.dart';
import 'package:ente_auth/store/code_display_store.dart';
@@ -40,7 +39,6 @@ import 'package:ente_auth/utils/dialog_util.dart';
import 'package:ente_auth/utils/lock_screen_settings.dart';
import 'package:ente_auth/utils/platform_util.dart';
import 'package:ente_auth/utils/totp_util.dart';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
@@ -48,7 +46,6 @@ import 'package:flutter_speed_dial/flutter_speed_dial.dart';
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
import 'package:logging/logging.dart';
import 'package:move_to_background/move_to_background.dart';
import 'package:scan/scan.dart';
class HomePage extends StatefulWidget {
const HomePage({super.key});
@@ -93,8 +90,8 @@ class _HomePageState extends State<HomePage> {
@override
void initState() {
super.initState();
_textController.addListener(_applyFilteringAndRefresh);
_codeSortKey = PreferenceService.instance.codeSortKey();
_textController.addListener(_applyFilteringAndRefresh);
_loadCodes();
_streamSubscription = Bus.instance.on<CodesUpdatedEvent>().listen((event) {
_loadCodes();
@@ -274,7 +271,6 @@ class _HomePageState extends State<HomePage> {
);
break;
case CodeSortKey.manual:
default:
codes.sort((a, b) => a.display.position.compareTo(b.display.position));
break;
}
@@ -483,7 +479,6 @@ class _HomePageState extends State<HomePage> {
return HomeEmptyStateWidget(
onScanTap: _redirectToScannerPage,
onManuallySetupTap: _redirectToManualEntryPage,
onImportFromGallery: _importFromGallery,
);
} else {
final anyCodeHasError =
@@ -585,7 +580,7 @@ class _HomePageState extends State<HomePage> {
return ClipRect(
child: CodeWidget(
key: ValueKey('${code.hashCode}_$newIndex'),
key: ValueKey('${code.hashCode}_${newIndex}_$_codeSortKey'),
code,
isCompactMode: isCompactMode,
sortKey: _codeSortKey,
@@ -621,6 +616,7 @@ class _HomePageState extends State<HomePage> {
key: ValueKey('${codeState.hashCode}_$index'),
codeState,
isCompactMode: isCompactMode,
sortKey: _codeSortKey,
);
}),
itemCount: _filteredCodes.length,
@@ -671,16 +667,24 @@ class _HomePageState extends State<HomePage> {
}
return false;
}
int lastScanTime = DateTime.now().millisecondsSinceEpoch - 1000;
void _handleDeeplink(BuildContext context, String? link) {
if (!Configuration.instance.hasConfiguredAccount() || link == null) {
bool isAccountConfigured = Configuration.instance.hasConfiguredAccount();
bool isOfflineModeEnabled = Configuration.instance.hasOptedForOfflineMode() &&
Configuration.instance.getOfflineSecretKey() != null;
if (!(isAccountConfigured || isOfflineModeEnabled) || link == null) {
return;
}
if (DateTime.now().millisecondsSinceEpoch - lastScanTime < 1000) {
_logger.info("Ignoring potential event for same deeplink");
return;
}
lastScanTime = DateTime.now().millisecondsSinceEpoch;
if (mounted && link.toLowerCase().startsWith("otpauth://")) {
try {
final newCode = Code.fromOTPAuthUrl(link);
getNextTotp(newCode);
CodeStore.instance.addCode(newCode);
CodeStore.instance.addCode(newCode, shouldSync: false);
_focusNewCode(newCode);
} catch (e, s) {
showGenericErrorDialog(
@@ -699,29 +703,6 @@ class _HomePageState extends State<HomePage> {
_applyFilteringAndRefresh();
}
Future<void> _importFromGallery() async {
try {
final FilePickerResult? result = await FilePicker.platform.pickFiles(
type: FileType.image,
allowMultiple: false,
);
if (result != null) {
final path = result.files.single.path!;
String? res = await Scan.parse(path);
final Code? code = res != null ? Code.fromOTPAuthUrl(res) : null;
if (code != null) {
await CodeStore.instance.addCode(code);
if ((_allCodes?.where((e) => !e.hasError).length ?? 0) > 2) {
_focusNewCode(code);
}
}
}
} catch (e, s) {
await showGenericErrorDialog(context: context, error: e);
_logger.severe("Error while importing from gallery", e, s);
}
}
Widget _getFab() {
if (PlatformUtil.isDesktop()) {
return FloatingActionButton(
@@ -752,15 +733,6 @@ class _HomePageState extends State<HomePage> {
labelWidget: SpeedDialLabelWidget(context.l10n.scanAQrCode),
onTap: _redirectToScannerPage,
),
if (PlatformUtil.isMobile() &&
FeatureFlagService.instance.isInternalUserOrDebugBuild())
SpeedDialChild(
child: const Icon(Icons.image),
foregroundColor: Theme.of(context).colorScheme.fabForegroundColor,
backgroundColor: Theme.of(context).colorScheme.fabBackgroundColor,
labelWidget: const SpeedDialLabelWidget("Import from gallery"),
onTap: _importFromGallery,
),
SpeedDialChild(
child: const Icon(Icons.keyboard),
foregroundColor: Theme.of(context).colorScheme.fabForegroundColor,

View File

@@ -90,7 +90,6 @@ class LockScreenSettings {
: await PrivacyScreen.instance.enable(
iosOptions: const PrivacyIosOptions(
enablePrivacy: true,
privacyImageName: 'LaunchImage',
),
androidOptions: const PrivacyAndroidOptions(
enableSecure: true,

View File

@@ -27,6 +27,8 @@ PODS:
- path_provider_foundation (0.0.1):
- Flutter
- FlutterMacOS
- rive_common (0.0.1):
- FlutterMacOS
- screen_retriever (0.0.1):
- FlutterMacOS
- Sentry/HybridSDK (8.36.0)
@@ -82,6 +84,7 @@ DEPENDENCIES:
- local_auth_darwin (from `Flutter/ephemeral/.symlinks/plugins/local_auth_darwin/darwin`)
- package_info_plus (from `Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos`)
- path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin`)
- rive_common (from `Flutter/ephemeral/.symlinks/plugins/rive_common/macos`)
- screen_retriever (from `Flutter/ephemeral/.symlinks/plugins/screen_retriever/macos`)
- sentry_flutter (from `Flutter/ephemeral/.symlinks/plugins/sentry_flutter/macos`)
- share_plus (from `Flutter/ephemeral/.symlinks/plugins/share_plus/macos`)
@@ -124,6 +127,8 @@ EXTERNAL SOURCES:
:path: Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos
path_provider_foundation:
:path: Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin
rive_common:
:path: Flutter/ephemeral/.symlinks/plugins/rive_common/macos
screen_retriever:
:path: Flutter/ephemeral/.symlinks/plugins/screen_retriever/macos
sentry_flutter:
@@ -159,6 +164,7 @@ SPEC CHECKSUMS:
OrderedSet: e539b66b644ff081c73a262d24ad552a69be3a94
package_info_plus: fa739dd842b393193c5ca93c26798dff6e3d0e0c
path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46
rive_common: 9580b9f1f08a8c85006083078e80479edf3db26a
screen_retriever: 59634572a57080243dd1bf715e55b6c54f241a38
Sentry: f8374b5415bc38dfb5645941b3ae31230fbeae57
sentry_flutter: 0eb93e5279eb41e2392212afe1ccd2fecb4f8cbe

View File

@@ -5,15 +5,15 @@ packages:
dependency: transitive
description:
name: _fe_analyzer_shared
sha256: f256b0c0ba6c7577c15e2e4e114755640a875e885099367bf6e012b19314c834
sha256: "16e298750b6d0af7ce8a3ba7c18c69c3785d11b15ec83f6dcd0ad2a0009b3cab"
url: "https://pub.dev"
source: hosted
version: "72.0.0"
version: "76.0.0"
_macros:
dependency: transitive
description: dart
source: sdk
version: "0.3.2"
version: "0.3.3"
adaptive_theme:
dependency: "direct main"
description:
@@ -26,10 +26,10 @@ packages:
dependency: transitive
description:
name: analyzer
sha256: b652861553cd3990d8ed361f7979dc6d7053a9ac8843fa73820ab68ce5410139
sha256: "1f14db053a8c23e260789e9b0980fa27f2680dd640932cae5e1137cce0e46e1e"
url: "https://pub.dev"
source: hosted
version: "6.7.0"
version: "6.11.0"
ansicolor:
dependency: transitive
description:
@@ -250,10 +250,10 @@ packages:
dependency: "direct main"
description:
name: collection
sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a
sha256: a1ace0a119f20aabc852d165077c036cd864315bd99b7eaa10a60100341941bf
url: "https://pub.dev"
source: hosted
version: "1.18.0"
version: "1.19.0"
confetti:
dependency: "direct main"
description:
@@ -387,7 +387,7 @@ packages:
description:
path: "."
ref: HEAD
resolved-ref: e2e66ffd03f23bef5e0bb138b5f01b32d8e9b7bb
resolved-ref: f91e1545f8263df127762240c4da54a0c42835b2
url: "https://github.com/ente-io/ente_crypto_dart.git"
source: git
version: "1.0.0"
@@ -434,11 +434,12 @@ packages:
figma_squircle:
dependency: "direct main"
description:
name: figma_squircle
sha256: "790b91a9505e90d246f6efe2fa065ff7fffe658c7b44fe9b5b20c7b0ad3818c0"
url: "https://pub.dev"
source: hosted
version: "0.5.3"
path: "."
ref: HEAD
resolved-ref: "5f1ad5aaccdf31fc398fc141979ea845a0f45383"
url: "https://github.com/Ax0elz/figma_squircle.git"
source: git
version: "0.5.5"
file:
dependency: transitive
description:
@@ -913,18 +914,18 @@ packages:
dependency: transitive
description:
name: leak_tracker
sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05"
sha256: "7bb2830ebd849694d1ec25bf1f44582d6ac531a57a365a803a6034ff751d2d06"
url: "https://pub.dev"
source: hosted
version: "10.0.5"
version: "10.0.7"
leak_tracker_flutter_testing:
dependency: transitive
description:
name: leak_tracker_flutter_testing
sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806"
sha256: "9491a714cca3667b60b5c420da8217e6de0d1ba7a5ec322fab01758f6998f379"
url: "https://pub.dev"
source: hosted
version: "3.0.5"
version: "3.0.8"
leak_tracker_testing:
dependency: transitive
description:
@@ -993,10 +994,10 @@ packages:
dependency: transitive
description:
name: macros
sha256: "0acaed5d6b7eab89f63350bccd82119e6c602df0f391260d0e32b5e23db79536"
sha256: "1d9e801cd66f7ea3663c45fc708450db1fa57f988142c64289142c9b7ee80656"
url: "https://pub.dev"
source: hosted
version: "0.1.2-main.4"
version: "0.1.3-main.0"
matcher:
dependency: transitive
description:
@@ -1301,14 +1302,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "4.1.0"
scan:
dependency: "direct main"
description:
name: scan
sha256: b343ec36f863a88d41eb4c174b810c055c6bd1f1822b2188ab31aab684fb7cdb
url: "https://pub.dev"
source: hosted
version: "1.6.0"
screen_retriever:
dependency: transitive
description:
@@ -1433,7 +1426,7 @@ packages:
dependency: transitive
description: flutter
source: sdk
version: "0.0.99"
version: "0.0.0"
sodium:
dependency: transitive
description:
@@ -1527,10 +1520,10 @@ packages:
dependency: transitive
description:
name: stack_trace
sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b"
sha256: "9f47fd3630d76be3ab26f0ee06d213679aa425996925ff3feffdec504931c377"
url: "https://pub.dev"
source: hosted
version: "1.11.1"
version: "1.12.0"
steam_totp:
dependency: "direct main"
description:
@@ -1567,10 +1560,10 @@ packages:
dependency: transitive
description:
name: string_scanner
sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde"
sha256: "688af5ed3402a4bde5b3a6c15fd768dbf2621a614950b17f04626c431ab3c4c3"
url: "https://pub.dev"
source: hosted
version: "1.2.0"
version: "1.3.0"
styled_text:
dependency: "direct main"
description:
@@ -1599,10 +1592,10 @@ packages:
dependency: transitive
description:
name: test_api
sha256: "5b8a98dafc4d5c4c9c72d8b31ab2b23fc13422348d2997120294d3bac86b4ddb"
sha256: "664d3a9a64782fcdeb83ce9c6b39e78fd2971d4e37827b9b06c3aa1edc5e760c"
url: "https://pub.dev"
source: hosted
version: "0.7.2"
version: "0.7.3"
timezone:
dependency: transitive
description:
@@ -1767,10 +1760,10 @@ packages:
dependency: transitive
description:
name: vm_service
sha256: "5c5f338a667b4c644744b661f309fb8080bb94b18a7e91ef1dbd343bed00ed6d"
sha256: f6be3ed8bd01289b34d679c2b62226f63c0e69f9fd2e50a6b3c1c729a961041b
url: "https://pub.dev"
source: hosted
version: "14.2.5"
version: "14.3.0"
watcher:
dependency: transitive
description:

View File

@@ -1,7 +1,7 @@
name: ente_auth
description: ente two-factor authenticator
version: 4.2.7+427
version: 4.3.1+431
publish_to: none
environment:
@@ -32,7 +32,9 @@ dependencies:
expandable: ^5.0.1
expansion_tile_card: ^3.0.0
ffi: ^2.1.0
figma_squircle: ^0.5.3
figma_squircle:
git:
url: https://github.com/Ax0elz/figma_squircle.git
file_picker: ^8.1.7
# https://github.com/incrediblezayed/file_saver/issues/86
file_saver: ^0.2.11
@@ -82,8 +84,7 @@ dependencies:
privacy_screen: ^0.0.6
protobuf: ^3.0.0
qr_code_scanner: ^1.0.1
qr_flutter: ^4.1.0
scan: ^1.6.0
qr_flutter: ^4.1.0
sentry: ^8.7.0
sentry_flutter: ^8.7.0
share_plus: ^10.0.2

View File

@@ -65,7 +65,7 @@ type AlbumFileEntry struct {
func SortAlbumFileEntry(entries []*AlbumFileEntry) {
sort.Slice(entries, func(i, j int) bool {
if entries[i].IsDeleted != entries[j].IsDeleted {
return !entries[i].IsDeleted && entries[j].IsDeleted
return entries[i].IsDeleted && !entries[j].IsDeleted
}
return entries[i].AlbumID < entries[j].AlbumID
})

View File

@@ -12,10 +12,10 @@ on:
description: "Branch (ente-io/ente) to build"
type: string
schedule:
# Run everyday at ~8:00 AM IST (except Sundays).
# Run every weekday at ~8:00 AM IST.
# See: [Note: Run workflow every 24 hours]
#
- cron: "45 2 * * 1-6"
- cron: "45 2 * * 1-5"
push:
# Run when a tag matching the pattern "vd.d.d" is pushed. In particular,
# this excludes the "-beta" tags.

3
desktop/.gitignore vendored
View File

@@ -20,3 +20,6 @@ out
# electron-builder
dist/
# We download it on demand, if needed for the particular OS/arch.
build/magick*

Binary file not shown.

View File

@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<component type="desktop-application">
<id>io.ente.photos</id>
<metadata_license>CC0-1.0</metadata_license>
<project_license>AGPL-3.0</project_license>
<name>Ente Photos</name>
<summary>Safe home for your photos</summary>
<developer id="io.github.ente-io.ente">
<name>Ente.io Developers</name>
</developer>
<description>
<p>
Ente is an open-source, end-to-end encrypted (E2EE) photo storage app, that provides a secure way to backup your photos.
</p>
</description>
<launchable type="desktop-id">ente.desktop</launchable>
<content_rating type="oars-1.0" />
<url type="bugtracker">https://github.com/ente-io/ente/issues</url>
<url type="homepage">https://ente.io</url>
<url type="vcs-browser">https://github.com/ente-io/ente</url>
<screenshots>
<screenshot type="default">
<image>https://raw.githubusercontent.com/ente-io/ente/main/.github/assets/photos.png</image>
</screenshot>
</screenshots>
<branding>
<color type="primary" scheme_preference="light">#1db954</color>
<color type="primary" scheme_preference="dark">#1db954</color>
</branding>
<releases>
<release version="1.7.8" date="2025-01-13">
<url type="details">https://github.com/ente-io/photos-desktop/releases/tag/v1.7.8</url>
</release>
</releases>
</component>

View File

@@ -103,7 +103,7 @@ Some extra ones specific to the code here are:
### Format conversion
The main tool we use is for arbitrary conversions is ffmpeg. To bundle a
For video conversions and metadata extraction, we use ffmpeg. To bundle a
(platform specific) static binary of ffmpeg with our app, we use
[ffmpeg-static](https://github.com/eugeneware/ffmpeg-static).
@@ -111,10 +111,12 @@ The main tool we use is for arbitrary conversions is ffmpeg. To bundle a
> ffmpeg binary and using the wasm one (that our renderer process already has).
> Which is why we bundle it to speed up operations on the desktop app.
In addition, we also bundle a static Linux binary of imagemagick in our extra
resources (`build`) folder. This is used for thumbnail generation on Linux.
On Linux and Windows, we use ImageMagick for thumbnail generation and JPEG
conversion of unpreviewable images. A static OS/architecture specific binary of
this is bundled in our extra resources (`build`) folder by `scripts/magick.sh`
and/or `scripts/beforeBuild.js`. See "[Note: ImageMagick]" for more details.
On macOS, we use the `sips` CLI tool for conversion, but that is already
On macOS, we use the `sips` CLI tool for these tasks, but that is already
available on the host machine, and is not bundled with our app.
### ML

View File

@@ -6,6 +6,7 @@ files:
extraFiles:
- from: build
to: resources
beforeBuild: scripts/beforeBuild.js
protocols:
- name: Ente
schemes: ["ente"]
@@ -33,3 +34,4 @@ mac:
arch: [universal]
category: public.app-category.photography
hardenedRuntime: true
mergeASARs: false

View File

@@ -19,7 +19,7 @@ export default ts.config(
{
// The list of (minimatch) globs to ignore. This needs to be the only
// key in this configuration object.
ignores: ["eslint.config.mjs", "app/", "out/", "dist/"],
ignores: ["eslint.config.mjs", "scripts/*.js", "app/", "out/", "dist/"],
},
{
// Rule customizations.

View File

@@ -8,17 +8,18 @@
"main": "app/main.js",
"scripts": {
"build": "yarn build-renderer && yarn build-main",
"build-main": "tsc && electron-builder",
"build-main:quick": "tsc && electron-builder --dir --config.compression=store --config.mac.identity=null",
"build-renderer": "cross-env-shell _ENTE_IS_DESKTOP=1 \"cd ../web && yarn install && yarn build:photos && cd ../desktop && shx rm -f out && shx ln -sf ../web/apps/photos/out out\"",
"build:ci": "yarn build-renderer && tsc",
"build:quick": "yarn build-renderer && yarn build-main:quick",
"build-main": "tsc && electron-builder",
"build-main:quick": "tsc && electron-builder --dir --config.compression=store --config.mac.identity=null",
"build-renderer": "cross-env-shell _ENTE_IS_DESKTOP=1 \"cd ../web && yarn install && yarn build:photos && cd ../desktop && shx rm -rf out && shx cp -r ../web/apps/photos/out out\"",
"dev": "concurrently --kill-others --success first --names 'main,rndr' \"yarn dev-main\" \"yarn dev-renderer\"",
"dev-main": "tsc && electron .",
"dev-renderer": "cross-env-shell _ENTE_IS_DESKTOP=1 \"cd ../web && yarn install && yarn workspace photos next dev -p 3008\"",
"postinstall": "electron-builder install-app-deps",
"lint": "yarn prettier --check --log-level warn . && yarn eslint && yarn tsc",
"lint-fix": "yarn prettier --write --log-level warn . && yarn eslint && yarn tsc"
"lint-fix": "yarn prettier --write --log-level warn . && yarn eslint && yarn tsc",
"prepare": "node scripts/magick.js"
},
"resolutions": {
"jackspeak": "2.1.1"
@@ -32,7 +33,7 @@
"compare-versions": "^6.1.1",
"electron-log": "^5.2.4",
"electron-store": "^8.2.0",
"electron-updater": "^6.3.9",
"electron-updater": "^6.4.0-alpha.3",
"ffmpeg-static": "^5.2.0",
"lru-cache": "^11.0.2",
"next-electron-server": "^1.0.0",
@@ -40,23 +41,23 @@
"onnxruntime-node": "^1.20.1"
},
"devDependencies": {
"@eslint/js": "^9.17.0",
"@eslint/js": "^9.18.0",
"@tsconfig/node20": "^20.1.4",
"@types/auto-launch": "^5.0.5",
"@types/eslint__js": "^8.42.3",
"@types/ffmpeg-static": "^3.0.3",
"ajv": "^8.17.1",
"concurrently": "^9.1.1",
"concurrently": "^9.1.2",
"cross-env": "^7.0.3",
"electron": "^33.2.1",
"electron-builder": "^25.1.8",
"electron": "^34.0.0",
"electron-builder": "^26.0.0-alpha.10",
"eslint": "^9",
"prettier": "3.4.2",
"prettier-plugin-organize-imports": "^4.1.0",
"prettier-plugin-packagejson": "^2.5.6",
"prettier-plugin-packagejson": "^2.5.8",
"shx": "^0.3.4",
"typescript": "^5.7.2",
"typescript-eslint": "^8.18.2"
"typescript-eslint": "^8.21.0"
},
"packageManager": "yarn@1.22.22",
"productName": "ente"

64
desktop/scripts/beforeBuild.js Executable file
View File

@@ -0,0 +1,64 @@
const fsp = require("fs/promises");
/**
* This hook is invoked during the initial build (e.g. when triggered by "yarn
* build"), and importantly, on each rebuild for a different architecture during
* the build. We use it to ensure that the magick binary is for the current
* architecture being built. See "[Note: ImageMagick]" for more details.
*
* The documentation for this hook is at:
* https://www.electron.build/app-builder-lib.interface.configuration#beforebuild
*
* > The function to be run before dependencies are installed or rebuilt.
*
* Here is an example of the context that it gets
* https://www.electron.build/app-builder-lib.interface.beforebuildcontext
*
* appDir: '/path/to/ente/desktop',
* platform: Platform {
* name: 'mac',
* buildConfigurationKey: 'mac',
* nodeName: 'darwin'
* },
* arch: 'arm64'
*
* Note that we must not return falsey from this function, because
* > Resolving to false will skip dependencies install or rebuild.
*/
module.exports = async (context) => {
const { appDir, platform, arch } = context;
// The arch used by Electron Builder is not the same as the arch used by
// Node's process, but for the two cases that we care about, "x64" and
// "arm64", both of them use the string constant and thus can be compared.
//
// https://github.com/electron-userland/electron-builder/blob/master/packages/builder-util/src/arch.ts#L9
// https://nodejs.org/api/process.html#processarch
if (arch == process.arch) {
// `magick.js` would've already downloaded the file, nothing to do.
return true;
}
const download = async (downloadName, outputName) => {
const out = `${appDir}/build/${outputName}`;
console.log(`Downloading ${downloadName}`);
const downloadPath = `https://github.com/ente-io/ImageMagick/releases/download/2025-01-21/${downloadName}`;
return fetch(downloadPath)
.then((res) => res.blob())
.then((blob) => fsp.writeFile(out, blob.stream()))
.then(() => fsp.chmod(out, "744"));
};
switch (`${platform.nodeName}-${arch}`) {
case "linux-x64":
await download("magick-x86_64", "magick");
case "linux-arm64":
await download("magick-aarch64", "magick");
case "win32-x64":
await download("magick-x64.exe", "magick.exe");
case "linux-arm64":
await download("magick-arm64.exe", "magick.exe");
}
return true;
};

78
desktop/scripts/magick.js Executable file
View File

@@ -0,0 +1,78 @@
/**
* [Note: ImageMagick]
*
* We need static builds for Linux and Windows for both x64 and ARM. For this,
* we need a custom workflow because (as of writing):
*
* 1. Upstream doesn't publish ARM64 binaries for Linux
*
* 2. The Windows portable releases are not part of the artifacts attached to
* the upstream GitHub release.
*
* Our custom workflow is an adaption of the upstream release.yml - its goal is
* to have 4 standalone binaries - Linux x64, Linux ARM, Win x64, Win ARM -
* attached to a GitHub release from which we can pull them when building the
* desktop app.
*
* This is our custom workflow, which runs on a fork of upstream:
* https://github.com/ente-io/ImageMagick/commit/df895cce13d6a3f874a716c05ff2babeb33351b9
* (For reference, we also include a copy of it in this repo - `magick.yml`).
*
* The binaries it creates are available at
* https://github.com/ente-io/ImageMagick/releases/tag/2025-01-21.
*
* To integrate this ImageMagick binary, we need to modify two places:
*
* 1. This script, `magick.js`, runs during "yarn install" (it is set as the
* "prepare" step in our `package.json`). It downloads the relevant binary
* for the current OS/arch combination and places it in the `build` folder,
* allowing it to be used during development.
*
* 2. The sibling script, `beforeBuild.js`, runs during "yarn build" (it is set
* as the beforeBuild script in `electrons-builder.yml`). It downloads the
* relevant binary for the OS/arch combination being built.
*
* Note that `magick.js` would've already run once `beforeBuild.js` is run, but
* on our CI we prepare builds for multiple architectures in one go, so we need
* to unconditonally replace the binary with the relevant one for the current
* architecture being built (which might be different from the one we're running
* on). `beforeBuild.js` runs for each architecture being built.
*
* On macOS, we don't need ImageMagick since there we use the native `sips`.
*/
const fs = require("fs");
const fsp = require("fs/promises");
const main = () => {
switch (`${process.platform}-${process.arch}`) {
case "linux-x64":
return downloadIfNeeded("magick-x86_64", "magick");
case "linux-arm64":
return downloadIfNeeded("magick-aarch64", "magick");
case "win32-x64":
return downloadIfNeeded("magick-x64.exe", "magick.exe");
case "linux-arm64":
return downloadIfNeeded("magick-arm64.exe", "magick.exe");
}
};
const downloadIfNeeded = (downloadName, outputName) => {
const out = `build/${outputName}`;
try {
// Making the file executable is the last step, so if the file exists at
// this path and is executable, we assume it is the correct one.
fs.accessSync(out, fs.constants.X_OK);
return;
} catch {}
console.log(`Downloading ${downloadName}`);
const downloadPath = `https://github.com/ente-io/ImageMagick/releases/download/2025-01-21/${downloadName}`;
return fetch(downloadPath)
.then((res) => res.blob())
.then((blob) => fsp.writeFile(out, blob.stream()))
.then(() => fsp.chmod(out, "744"));
};
main();

127
desktop/scripts/magick.yml Normal file
View File

@@ -0,0 +1,127 @@
on:
workflow_dispatch:
push: # Push a tag to build and create a draft release
tags:
- "*"
name: binaries-for-ente
jobs:
create_magick_binary:
name: Create magick binary (Linux)
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-24.04, ubuntu-24.04-arm]
compiler: [gcc]
include:
- os: ubuntu-24.04
arch: x86_64
- os: ubuntu-24.04-arm
arch: aarch64
- compiler: gcc
cxx_compiler: g++
packages: gcc g++
steps:
- name: Install dependencies
run: |
set -e
export DEBIAN_FRONTEND=noninteractive
sudo apt update -y
sudo apt install -y autoconf curl fuse git kmod libbz2-dev libdjvulibre-dev libfontconfig-dev libfreetype6-dev libfribidi-dev libharfbuzz-dev liblcms-dev libopenexr-dev libopenjp2-7-dev libturbojpeg0-dev liblqr-dev libraqm-dev libtiff-dev libwebp-dev libx11-dev libxml2-dev liblzma-dev make software-properties-common wget ${{ matrix.packages }}
sudo add-apt-repository ppa:git-core/ppa -y
sudo apt install -y git
sudo add-apt-repository ppa:strukturag/libheif -y
sudo add-apt-repository ppa:strukturag/libde265 -y
sudo apt install libheif-dev -y
- name: Checkout
uses: actions/checkout@v4
# Avoid fatal: detected dubious ownership in repository at '/__w/ImageMagick/ImageMagick'
# Possible workaround: https://github.com/actions/runner/issues/2033#issuecomment-1598547465
- name: Flag current workspace as safe for git
run: git config --global --add safe.directory ${GITHUB_WORKSPACE}
- name: Download AppImage
run: |
set -e
sudo apt install -y file
mkdir -p out/app-image
cd out/app-image
wget -c https://github.com/$(wget -q https://github.com/probonopd/go-appimage/releases/expanded_assets/continuous -O - | grep "appimagetool-.*-${{ matrix.arch }}.AppImage" | head -n 1 | cut -d '"' -f 2)
chmod +x appimagetool-*.AppImage
- name: Build ImageMagick
env:
CFLAGS:
-Wno-deprecated-declarations -Wdeclaration-after-statement
-Wno-error=unused-variable
CC: ${{ matrix.compiler }}
CXX: ${{ matrix.cxx_compiler }}
run: |
set -e
./configure --with-quantum-depth=16 --without-magick-plus-plus --without-perl --without-x --disable-docs --prefix=/usr
make
make install DESTDIR=$(readlink -f out/appdir)
- name: Create ImageMagick AppImage
run: |
set -e
mkdir -p out/appdir/usr/share/applications/
cp app-image/imagemagick.desktop out/appdir/usr/share/applications/
mkdir -p out/appdir/usr/share/icons/hicolor/256x256/apps/
cp app-image/icon.png out/appdir/usr/share/icons/hicolor/256x256/apps/imagemagick.png
unset QTDIR
unset QT_PLUGIN_PATH
unset LD_LIBRARY_PATH
export VERSION=7
cd out
./app-image/appimagetool-*.AppImage --appimage-extract-and-run -s deploy appdir/usr/share/applications/*.desktop
chmod +x appdir/usr/lib/ld-linux-aarch64.so.1 || true
./app-image/appimagetool-*.AppImage --appimage-extract-and-run appdir
mkdir artifacts
cp ImageMagick*.AppImage artifacts/magick-${{ matrix.arch }}
- name: Upload ImageMagick AppImage
uses: actions/upload-artifact@v4
with:
name: magick-${{ matrix.arch }}
path: out/artifacts
- name: Create a draft GitHub release
uses: ncipollo/release-action@v1
with:
artifacts: "out/artifacts/*"
draft: true
allowUpdates: true
updateOnlyUnreleased: true
download_and_keep_windows_binaries:
name: Download magick binary (Windows)
runs-on: ubuntu-24.04
steps:
- name: Download
run: |
mkdir -p out/artifacts
curl -LO https://imagemagick.org/archive/binaries/ImageMagick-7.1.1-43-portable-Q16-x64.zip
unzip ImageMagick-7.1.1-43-portable-Q16-x64.zip
cp ImageMagick-7.1.1-43-portable-Q16-x64/magick.exe out/artifacts/magick-x64.exe
curl -LO https://imagemagick.org/archive/binaries/ImageMagick-7.1.1-43-portable-Q16-arm64.zip
unzip ImageMagick-7.1.1-43-portable-Q16-arm64.zip
cp ImageMagick-7.1.1-43-portable-Q16-arm64/magick.exe out/artifacts/magick-arm64.exe
- name: Upload ImageMagick exes
uses: actions/upload-artifact@v4
with:
name: magick-${{ matrix.arch }}
path: out/artifacts
- name: Create a draft GitHub release
uses: ncipollo/release-action@v1
with:
artifacts: "out/artifacts/*"
draft: true
allowUpdates: true
updateOnlyUnreleased: true

View File

@@ -2,7 +2,7 @@
import fs from "node:fs/promises";
import path from "node:path";
import { CustomErrorMessage, type ZipItem } from "../../types/ipc";
import { type ZipItem } from "../../types/ipc";
import { execAsync, isDev } from "../utils/electron";
import {
deleteTempFileIgnoringErrors,
@@ -44,25 +44,29 @@ const convertToJPEGCommand = (
];
case "linux":
// The bundled binary is an ELF x86-64 executable.
if (process.arch != "x64")
throw new Error(CustomErrorMessage.NotAvailable);
case "win32":
return [
imageMagickPath(),
"convert",
inputFilePath,
"-quality",
"100%",
outputFilePath,
];
default: // "win32"
throw new Error(CustomErrorMessage.NotAvailable);
default:
throw new Error("Not available on the current OS/arch");
}
};
/** Path to the Linux image-magick executable bundled with our app */
/**
* Path to the magick executable bundled with our app on Linux and Windows.
*/
const imageMagickPath = () =>
path.join(isDev ? "build" : process.resourcesPath, "image-magick");
path.join(
isDev ? "build" : process.resourcesPath,
process.platform == "win32" ? "magick.exe" : "magick",
);
export const generateImageThumbnail = async (
dataOrPathOrZipItem: Uint8Array | string | ZipItem,
@@ -133,14 +137,13 @@ const generateImageThumbnailCommand = (
];
case "linux":
// The bundled binary is an ELF x86-64 executable.
if (process.arch != "x64")
throw new Error(CustomErrorMessage.NotAvailable);
case "win32":
return [
imageMagickPath(),
"convert",
inputFilePath,
"-define",
`jpeg:size=${2 * maxDimension}x${2 * maxDimension}`,
inputFilePath,
"-auto-orient",
"-thumbnail",
`${maxDimension}x${maxDimension}`,
@@ -151,7 +154,7 @@ const generateImageThumbnailCommand = (
outputFilePath,
];
default: // "win32"
throw new Error(CustomErrorMessage.NotAvailable);
default:
throw new Error("Not available on the current OS/arch");
}
};

View File

@@ -56,6 +56,8 @@ export const execAsync = async (command: string | string[]) => {
const startTime = Date.now();
const result = await execAsync_(escapedCommand);
log.debug(() => `${escapedCommand} (${Date.now() - startTime} ms)`);
// TODO(MR): Temp for debugging in nightlies; Remove before release.
log.info(`${escapedCommand} (${Date.now() - startTime} ms)`);
return result;
};

View File

@@ -32,13 +32,3 @@ export interface PendingUploads {
filePaths: string[];
zipItems: ZipItem[];
}
/**
* See: [Note: Custom errors across Electron/Renderer boundary]
*
* Note: this is not a type, and cannot be used in preload.js; it is only meant
* for use in the main process code.
*/
export const CustomErrorMessage = {
NotAvailable: "This feature in not available on the current OS/arch",
};

View File

@@ -25,6 +25,15 @@
ajv "^6.12.0"
ajv-keywords "^3.4.1"
"@electron/asar@3.2.18":
version "3.2.18"
resolved "https://registry.yarnpkg.com/@electron/asar/-/asar-3.2.18.tgz#fa607f829209bab8b9e0ce6658d3fe81b2cba517"
integrity sha512-2XyvMe3N3Nrs8cV39IKELRHTYUWFKrmqqSY1U+GMlc0jvqjIVnoxhNd2H4JolWQncbJi1DCvb5TNxZuI2fEjWg==
dependencies:
commander "^5.0.0"
glob "^7.1.6"
minimatch "^3.0.4"
"@electron/asar@^3.2.7":
version "3.2.10"
resolved "https://registry.yarnpkg.com/@electron/asar/-/asar-3.2.10.tgz#615cf346b734b23cafa4e0603551010bd0e50aa8"
@@ -34,6 +43,15 @@
glob "^7.1.6"
minimatch "^3.0.4"
"@electron/fuses@^1.8.0":
version "1.8.0"
resolved "https://registry.yarnpkg.com/@electron/fuses/-/fuses-1.8.0.tgz#ad34d3cc4703b1258b83f6989917052cfc1490a0"
integrity sha512-zx0EIq78WlY/lBb1uXlziZmDZI4ubcCXIMJ4uGjXzZW0nS19TjSPeXPAjzzTmKQlJUZm0SbmZhPKP7tuQ1SsEw==
dependencies:
chalk "^4.1.1"
fs-extra "^9.0.1"
minimist "^1.2.5"
"@electron/get@^2.0.0":
version "2.0.3"
resolved "https://registry.yarnpkg.com/@electron/get/-/get-2.0.3.tgz#fba552683d387aebd9f3fcadbcafc8e12ee4f960"
@@ -49,6 +67,21 @@
optionalDependencies:
global-agent "^3.0.0"
"@electron/node-gyp@https://github.com/electron/node-gyp#06b29aafb7708acef8b3669835c8a7857ebc92d2":
version "10.2.0-electron.1"
resolved "https://github.com/electron/node-gyp#06b29aafb7708acef8b3669835c8a7857ebc92d2"
dependencies:
env-paths "^2.2.0"
exponential-backoff "^3.1.1"
glob "^8.1.0"
graceful-fs "^4.2.6"
make-fetch-happen "^10.2.1"
nopt "^6.0.0"
proc-log "^2.0.1"
semver "^7.3.5"
tar "^6.2.1"
which "^2.0.2"
"@electron/notarize@2.5.0":
version "2.5.0"
resolved "https://registry.yarnpkg.com/@electron/notarize/-/notarize-2.5.0.tgz#d4d25356adfa29df4a76bd64a8bd347237cd251e"
@@ -70,11 +103,12 @@
minimist "^1.2.6"
plist "^3.0.5"
"@electron/rebuild@3.6.1":
version "3.6.1"
resolved "https://registry.yarnpkg.com/@electron/rebuild/-/rebuild-3.6.1.tgz#59e8e36c3f6e6b94a699425dfb61f0394c3dd4df"
integrity sha512-f6596ZHpEq/YskUd8emYvOUne89ij8mQgjYFA5ru25QwbrRO+t1SImofdDv7kKOuWCmVOuU5tvfkbgGxIl3E/w==
"@electron/rebuild@3.7.0":
version "3.7.0"
resolved "https://registry.yarnpkg.com/@electron/rebuild/-/rebuild-3.7.0.tgz#82e20c467ddedbb295d7f641592c52e68c141e9f"
integrity sha512-VW++CNSlZwMYP7MyXEbrKjpzEwhB5kDNbzGtiPEjwYysqyTCF+YbNJ210Dj3AjWsGSV4iEEwNkmJN9yGZmVvmw==
dependencies:
"@electron/node-gyp" "https://github.com/electron/node-gyp#06b29aafb7708acef8b3669835c8a7857ebc92d2"
"@malept/cross-spawn-promise" "^2.0.0"
chalk "^4.0.0"
debug "^4.1.1"
@@ -83,7 +117,6 @@
got "^11.7.0"
node-abi "^3.45.0"
node-api-version "^0.2.0"
node-gyp "^9.0.0"
ora "^5.1.0"
read-binary-file-arch "^1.0.6"
semver "^7.3.5"
@@ -144,10 +177,10 @@
resolved "https://registry.yarnpkg.com/@eslint/js/-/js-9.9.1.tgz#4a97e85e982099d6c7ee8410aacb55adaa576f06"
integrity sha512-xIDQRsfg5hNBqHz04H1R3scSVwmI+KUbqjsQKHKQ1DAUSaUjYPReZZmS/5PNiKu1fUvzDd6H7DEDKACSEhu+TQ==
"@eslint/js@^9.17.0":
version "9.17.0"
resolved "https://registry.yarnpkg.com/@eslint/js/-/js-9.17.0.tgz#1523e586791f80376a6f8398a3964455ecc651ec"
integrity sha512-Sxc4hqcs1kTu0iID3kcZDW3JHq2a77HO9P8CP6YEA/FpH3Ll8UXE2r/86Rz9YJLKme39S9vU5OWNjC6Xl0Cr3w==
"@eslint/js@^9.18.0":
version "9.18.0"
resolved "https://registry.yarnpkg.com/@eslint/js/-/js-9.18.0.tgz#3356f85d18ed3627ab107790b53caf7e1e3d1e84"
integrity sha512-fK6L7rxcq6/z+AaQMtiFTkvbHkBLNlwyRxHpKawP0x3u9+NC6MQTnFW+AdpwC6gfHTW0051cokQgtTN2FqlxQA==
"@eslint/object-schema@^2.1.4":
version "2.1.4"
@@ -384,85 +417,85 @@
dependencies:
"@types/node" "*"
"@typescript-eslint/eslint-plugin@8.18.2":
version "8.18.2"
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.18.2.tgz#c78e363ab5fe3b21dd1c90d8be9581534417f78e"
integrity sha512-adig4SzPLjeQ0Tm+jvsozSGiCliI2ajeURDGHjZ2llnA+A67HihCQ+a3amtPhUakd1GlwHxSRvzOZktbEvhPPg==
"@typescript-eslint/eslint-plugin@8.21.0":
version "8.21.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.21.0.tgz#395014a75112ecdb81142b866ab6bb62e3be0f2a"
integrity sha512-eTH+UOR4I7WbdQnG4Z48ebIA6Bgi7WO8HvFEneeYBxG8qCOYgTOFPSg6ek9ITIDvGjDQzWHcoWHCDO2biByNzA==
dependencies:
"@eslint-community/regexpp" "^4.10.0"
"@typescript-eslint/scope-manager" "8.18.2"
"@typescript-eslint/type-utils" "8.18.2"
"@typescript-eslint/utils" "8.18.2"
"@typescript-eslint/visitor-keys" "8.18.2"
"@typescript-eslint/scope-manager" "8.21.0"
"@typescript-eslint/type-utils" "8.21.0"
"@typescript-eslint/utils" "8.21.0"
"@typescript-eslint/visitor-keys" "8.21.0"
graphemer "^1.4.0"
ignore "^5.3.1"
natural-compare "^1.4.0"
ts-api-utils "^1.3.0"
ts-api-utils "^2.0.0"
"@typescript-eslint/parser@8.18.2":
version "8.18.2"
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.18.2.tgz#0379a2e881d51d8fcf7ebdfa0dd18eee79182ce2"
integrity sha512-y7tcq4StgxQD4mDr9+Jb26dZ+HTZ/SkfqpXSiqeUXZHxOUyjWDKsmwKhJ0/tApR08DgOhrFAoAhyB80/p3ViuA==
"@typescript-eslint/parser@8.21.0":
version "8.21.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.21.0.tgz#312c638aaba4f640d45bfde7c6795a9d75deb088"
integrity sha512-Wy+/sdEH9kI3w9civgACwabHbKl+qIOu0uFZ9IMKzX3Jpv9og0ZBJrZExGrPpFAY7rWsXuxs5e7CPPP17A4eYA==
dependencies:
"@typescript-eslint/scope-manager" "8.18.2"
"@typescript-eslint/types" "8.18.2"
"@typescript-eslint/typescript-estree" "8.18.2"
"@typescript-eslint/visitor-keys" "8.18.2"
"@typescript-eslint/scope-manager" "8.21.0"
"@typescript-eslint/types" "8.21.0"
"@typescript-eslint/typescript-estree" "8.21.0"
"@typescript-eslint/visitor-keys" "8.21.0"
debug "^4.3.4"
"@typescript-eslint/scope-manager@8.18.2":
version "8.18.2"
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.18.2.tgz#d193c200d61eb0ddec5987c8e48c9d4e1c0510bd"
integrity sha512-YJFSfbd0CJjy14r/EvWapYgV4R5CHzptssoag2M7y3Ra7XNta6GPAJPPP5KGB9j14viYXyrzRO5GkX7CRfo8/g==
"@typescript-eslint/scope-manager@8.21.0":
version "8.21.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.21.0.tgz#d08d94e2a34b4ccdcc975543c25bb62917437500"
integrity sha512-G3IBKz0/0IPfdeGRMbp+4rbjfSSdnGkXsM/pFZA8zM9t9klXDnB/YnKOBQ0GoPmoROa4bCq2NeHgJa5ydsQ4mA==
dependencies:
"@typescript-eslint/types" "8.18.2"
"@typescript-eslint/visitor-keys" "8.18.2"
"@typescript-eslint/types" "8.21.0"
"@typescript-eslint/visitor-keys" "8.21.0"
"@typescript-eslint/type-utils@8.18.2":
version "8.18.2"
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.18.2.tgz#5ad07e09002eee237591881df674c1c0c91ca52f"
integrity sha512-AB/Wr1Lz31bzHfGm/jgbFR0VB0SML/hd2P1yxzKDM48YmP7vbyJNHRExUE/wZsQj2wUCvbWH8poNHFuxLqCTnA==
"@typescript-eslint/type-utils@8.21.0":
version "8.21.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.21.0.tgz#2e69d1a93cdbedc73fe694cd6ae4dfedd00430a0"
integrity sha512-95OsL6J2BtzoBxHicoXHxgk3z+9P3BEcQTpBKriqiYzLKnM2DeSqs+sndMKdamU8FosiadQFT3D+BSL9EKnAJQ==
dependencies:
"@typescript-eslint/typescript-estree" "8.18.2"
"@typescript-eslint/utils" "8.18.2"
"@typescript-eslint/typescript-estree" "8.21.0"
"@typescript-eslint/utils" "8.21.0"
debug "^4.3.4"
ts-api-utils "^1.3.0"
ts-api-utils "^2.0.0"
"@typescript-eslint/types@8.18.2":
version "8.18.2"
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.18.2.tgz#5ebad5b384c8aa1c0f86cee1c61bcdbe7511f547"
integrity sha512-Z/zblEPp8cIvmEn6+tPDIHUbRu/0z5lqZ+NvolL5SvXWT5rQy7+Nch83M0++XzO0XrWRFWECgOAyE8bsJTl1GQ==
"@typescript-eslint/types@8.21.0":
version "8.21.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.21.0.tgz#58f30aec8db8212fd886835dc5969cdf47cb29f5"
integrity sha512-PAL6LUuQwotLW2a8VsySDBwYMm129vFm4tMVlylzdoTybTHaAi0oBp7Ac6LhSrHHOdLM3efH+nAR6hAWoMF89A==
"@typescript-eslint/typescript-estree@8.18.2":
version "8.18.2"
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.18.2.tgz#fffb85527f8304e29bfbbdc712f4515da9f8b47c"
integrity sha512-WXAVt595HjpmlfH4crSdM/1bcsqh+1weFRWIa9XMTx/XHZ9TCKMcr725tLYqWOgzKdeDrqVHxFotrvWcEsk2Tg==
"@typescript-eslint/typescript-estree@8.21.0":
version "8.21.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.21.0.tgz#5ce71acdbed3b97b959f6168afba5a03c88f69a9"
integrity sha512-x+aeKh/AjAArSauz0GiQZsjT8ciadNMHdkUSwBB9Z6PrKc/4knM4g3UfHml6oDJmKC88a6//cdxnO/+P2LkMcg==
dependencies:
"@typescript-eslint/types" "8.18.2"
"@typescript-eslint/visitor-keys" "8.18.2"
"@typescript-eslint/types" "8.21.0"
"@typescript-eslint/visitor-keys" "8.21.0"
debug "^4.3.4"
fast-glob "^3.3.2"
is-glob "^4.0.3"
minimatch "^9.0.4"
semver "^7.6.0"
ts-api-utils "^1.3.0"
ts-api-utils "^2.0.0"
"@typescript-eslint/utils@8.18.2":
version "8.18.2"
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.18.2.tgz#a2635f71904a84f9e47fe1b6f65a6d944ff1adf9"
integrity sha512-Cr4A0H7DtVIPkauj4sTSXVl+VBWewE9/o40KcF3TV9aqDEOWoXF3/+oRXNby3DYzZeCATvbdksYsGZzplwnK/Q==
"@typescript-eslint/utils@8.21.0":
version "8.21.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.21.0.tgz#bc4874fbc30feb3298b926e3b03d94570b3999c5"
integrity sha512-xcXBfcq0Kaxgj7dwejMbFyq7IOHgpNMtVuDveK7w3ZGwG9owKzhALVwKpTF2yrZmEwl9SWdetf3fxNzJQaVuxw==
dependencies:
"@eslint-community/eslint-utils" "^4.4.0"
"@typescript-eslint/scope-manager" "8.18.2"
"@typescript-eslint/types" "8.18.2"
"@typescript-eslint/typescript-estree" "8.18.2"
"@typescript-eslint/scope-manager" "8.21.0"
"@typescript-eslint/types" "8.21.0"
"@typescript-eslint/typescript-estree" "8.21.0"
"@typescript-eslint/visitor-keys@8.18.2":
version "8.18.2"
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.18.2.tgz#b3e434b701f086b10a7c82416ebc56899d27ef2f"
integrity sha512-zORcwn4C3trOWiCqFQP1x6G3xTRyZ1LYydnj51cRnJ6hxBlr/cKPckk+PKPUw/fXmvfKTcw7bwY3w9izgx5jZw==
"@typescript-eslint/visitor-keys@8.21.0":
version "8.21.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.21.0.tgz#a89744c4cdc83b5c761eb5878befe6c33d1481b2"
integrity sha512-BkLMNpdV6prozk8LlyK/SOoWLmUFi+ZD+pcqti9ILCbVvHGk1ui1g4jJOc2WDLaeExz2qWwojxlPce5PljcT3w==
dependencies:
"@typescript-eslint/types" "8.18.2"
"@typescript-eslint/types" "8.21.0"
eslint-visitor-keys "^4.2.0"
"@xmldom/xmldom@^0.8.8":
@@ -571,35 +604,36 @@ anymatch@~3.1.2:
normalize-path "^3.0.0"
picomatch "^2.0.4"
app-builder-bin@5.0.0-alpha.10:
version "5.0.0-alpha.10"
resolved "https://registry.yarnpkg.com/app-builder-bin/-/app-builder-bin-5.0.0-alpha.10.tgz#cf12e593b6b847fb9d04027fa755c6c6610d778b"
integrity sha512-Ev4jj3D7Bo+O0GPD2NMvJl+PGiBAfS7pUGawntBNpCbxtpncfUixqFj9z9Jme7V7s3LBGqsWZZP54fxBX3JKJw==
app-builder-bin@5.0.0-alpha.12:
version "5.0.0-alpha.12"
resolved "https://registry.yarnpkg.com/app-builder-bin/-/app-builder-bin-5.0.0-alpha.12.tgz#2daf82f8badc698e0adcc95ba36af4ff0650dc80"
integrity sha512-j87o0j6LqPL3QRr8yid6c+Tt5gC7xNfYo6uQIQkorAC6MpeayVMZrEDzKmJJ/Hlv7EnOQpaRm53k6ktDYZyB6w==
app-builder-lib@25.1.8:
version "25.1.8"
resolved "https://registry.yarnpkg.com/app-builder-lib/-/app-builder-lib-25.1.8.tgz#ae376039c5f269c7d562af494a087e5bc6310f1b"
integrity sha512-pCqe7dfsQFBABC1jeKZXQWhGcCPF3rPCXDdfqVKjIeWBcXzyC1iOWZdfFhGl+S9MyE/k//DFmC6FzuGAUudNDg==
app-builder-lib@26.0.0-alpha.10:
version "26.0.0-alpha.10"
resolved "https://registry.yarnpkg.com/app-builder-lib/-/app-builder-lib-26.0.0-alpha.10.tgz#3eb3f64ffa5e995595ad61497c5e7a0c2d64b817"
integrity sha512-9K3MulGK7j+En4KjH3aq7AzDqe8nn35x7O9l5kwl16nWFdBthcdy1IKsx9CgjMSF+eTNctOZlXwnYiPiGzY+GQ==
dependencies:
"@develar/schema-utils" "~2.6.5"
"@electron/asar" "3.2.18"
"@electron/fuses" "^1.8.0"
"@electron/notarize" "2.5.0"
"@electron/osx-sign" "1.3.1"
"@electron/rebuild" "3.6.1"
"@electron/rebuild" "3.7.0"
"@electron/universal" "2.0.1"
"@malept/flatpak-bundler" "^0.4.0"
"@types/fs-extra" "9.0.13"
async-exit-hook "^2.0.1"
bluebird-lst "^1.0.9"
builder-util "25.1.7"
builder-util-runtime "9.2.10"
builder-util "26.0.0-alpha.10"
builder-util-runtime "9.3.0-alpha.0"
chromium-pickle-js "^0.2.0"
config-file-ts "0.2.8-rc1"
debug "^4.3.4"
dotenv "^16.4.5"
dotenv-expand "^11.0.6"
ejs "^3.1.8"
electron-publish "25.1.7"
form-data "^4.0.0"
electron-publish "26.0.0-alpha.10"
fs-extra "^10.1.0"
hosted-git-info "^4.1.0"
is-ci "^3.0.0"
@@ -609,7 +643,6 @@ app-builder-lib@25.1.8:
lazy-val "^1.0.5"
minimatch "^10.0.0"
resedit "^1.7.0"
sanitize-filename "^1.6.3"
semver "^7.3.8"
tar "^6.1.12"
temp-file "^3.4.0"
@@ -619,19 +652,6 @@ applescript@^1.0.0:
resolved "https://registry.yarnpkg.com/applescript/-/applescript-1.0.0.tgz#bb87af568cad034a4e48c4bdaf6067a3a2701317"
integrity sha512-yvtNHdWvtbYEiIazXAdp/NY+BBb65/DAseqlNiJQjOx9DynuzOYDbVLBJvuc0ve0VL9x6B3OHF6eH52y9hCBtQ==
"aproba@^1.0.3 || ^2.0.0":
version "2.0.0"
resolved "https://registry.yarnpkg.com/aproba/-/aproba-2.0.0.tgz#52520b8ae5b569215b354efc0caa3fe1e45a8adc"
integrity sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==
are-we-there-yet@^3.0.0:
version "3.0.1"
resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz#679df222b278c64f2cdba1175cdc00b0d96164bd"
integrity sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==
dependencies:
delegates "^1.0.0"
readable-stream "^3.6.0"
argparse@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38"
@@ -764,32 +784,33 @@ buffer@^5.1.0, buffer@^5.5.0:
base64-js "^1.3.1"
ieee754 "^1.1.13"
builder-util-runtime@9.2.10:
version "9.2.10"
resolved "https://registry.yarnpkg.com/builder-util-runtime/-/builder-util-runtime-9.2.10.tgz#a0f7d9e214158402e78b74a745c8d9f870c604bc"
integrity sha512-6p/gfG1RJSQeIbz8TK5aPNkoztgY1q5TgmGFMAXcY8itsGW6Y2ld1ALsZ5UJn8rog7hKF3zHx5iQbNQ8uLcRlw==
builder-util-runtime@9.3.0-alpha.0:
version "9.3.0-alpha.0"
resolved "https://registry.yarnpkg.com/builder-util-runtime/-/builder-util-runtime-9.3.0-alpha.0.tgz#c4639ae24a74d2e0f4eb324100af3040300bae62"
integrity sha512-EriE6Uf15niqdkyjBOS09OrXlhEV0HKhnATlI9n63vCoisnvvRTQNgoR2MV9vnBmNGhavBPZXPWPItv4QMDVfw==
dependencies:
debug "^4.3.4"
sax "^1.2.4"
builder-util@25.1.7:
version "25.1.7"
resolved "https://registry.yarnpkg.com/builder-util/-/builder-util-25.1.7.tgz#a07b404f0cb1a635aa165902be65297d58932ff8"
integrity sha512-7jPjzBwEGRbwNcep0gGNpLXG9P94VA3CPAZQCzxkFXiV2GMQKlziMbY//rXPI7WKfhsvGgFXjTcXdBEwgXw9ww==
builder-util@26.0.0-alpha.10:
version "26.0.0-alpha.10"
resolved "https://registry.yarnpkg.com/builder-util/-/builder-util-26.0.0-alpha.10.tgz#f445a530c28da6e3650b93e92263c06c6f89a2cc"
integrity sha512-RMVOAgdd+tzwpyF5C8gx9KjzwdUvkUEubpsHTvb2JwlQnBcyBc6hyVCU2gt2MivQCLbjCOEgsUX1/zHrWDqGfg==
dependencies:
"7zip-bin" "~5.2.0"
"@types/debug" "^4.1.6"
app-builder-bin "5.0.0-alpha.10"
app-builder-bin "5.0.0-alpha.12"
bluebird-lst "^1.0.9"
builder-util-runtime "9.2.10"
builder-util-runtime "9.3.0-alpha.0"
chalk "^4.1.2"
cross-spawn "^7.0.3"
cross-spawn "^7.0.6"
debug "^4.3.4"
fs-extra "^10.1.0"
http-proxy-agent "^7.0.0"
https-proxy-agent "^7.0.0"
is-ci "^3.0.0"
js-yaml "^4.1.0"
sanitize-filename "^1.6.3"
source-map-support "^0.5.19"
stat-mode "^1.0.0"
temp-file "^3.4.0"
@@ -846,7 +867,7 @@ caseless@^0.12.0:
resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
integrity sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==
chalk@^4.0.0, chalk@^4.0.2, chalk@^4.1.0, chalk@^4.1.2:
chalk@^4.0.0, chalk@^4.0.2, chalk@^4.1.0, chalk@^4.1.1, chalk@^4.1.2:
version "4.1.2"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01"
integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==
@@ -952,11 +973,6 @@ color-name@~1.1.4:
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
color-support@^1.1.3:
version "1.1.3"
resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2"
integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==
combined-stream@^1.0.8:
version "1.0.8"
resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
@@ -999,10 +1015,10 @@ concat-stream@^2.0.0:
readable-stream "^3.0.2"
typedarray "^0.0.6"
concurrently@^9.1.1:
version "9.1.1"
resolved "https://registry.yarnpkg.com/concurrently/-/concurrently-9.1.1.tgz#609dde2ce12f4f12d6a5ea6eace4c38bb7ab2ead"
integrity sha512-6VX8lrBIycgZKTwBsWS+bLrmkGRkDmvtGsYylRN9b93CygN6CbK46HmnQ3rdSOR8HRjdahDrxb5MqD9cEFOg5Q==
concurrently@^9.1.2:
version "9.1.2"
resolved "https://registry.yarnpkg.com/concurrently/-/concurrently-9.1.2.tgz#22d9109296961eaee773e12bfb1ce9a66bc9836c"
integrity sha512-H9MWcoPsYddwbOGM6difjVwVZHl63nwMEwDJG/L7VGtuaJhb12h2caPG2tVPWs7emuYix252iGfqOyrz1GczTQ==
dependencies:
chalk "^4.1.2"
lodash "^4.17.21"
@@ -1036,11 +1052,6 @@ config-file-ts@0.2.8-rc1:
glob "^10.3.12"
typescript "^5.4.3"
console-control-strings@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e"
integrity sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==
core-util-is@1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
@@ -1060,7 +1071,7 @@ cross-env@^7.0.3:
dependencies:
cross-spawn "^7.0.1"
cross-spawn@^7.0.0, cross-spawn@^7.0.1, cross-spawn@^7.0.2, cross-spawn@^7.0.3:
cross-spawn@^7.0.0, cross-spawn@^7.0.1, cross-spawn@^7.0.2:
version "7.0.3"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6"
integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==
@@ -1069,6 +1080,15 @@ cross-spawn@^7.0.0, cross-spawn@^7.0.1, cross-spawn@^7.0.2, cross-spawn@^7.0.3:
shebang-command "^2.0.0"
which "^2.0.1"
cross-spawn@^7.0.6:
version "7.0.6"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f"
integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==
dependencies:
path-key "^3.1.0"
shebang-command "^2.0.0"
which "^2.0.1"
debounce-fn@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/debounce-fn/-/debounce-fn-4.0.0.tgz#ed76d206d8a50e60de0dd66d494d82835ffe61c7"
@@ -1130,11 +1150,6 @@ delayed-stream@~1.0.0:
resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==
delegates@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a"
integrity sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==
detect-indent@^7.0.1:
version "7.0.1"
resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-7.0.1.tgz#cbb060a12842b9c4d333f1cac4aa4da1bb66bc25"
@@ -1163,14 +1178,14 @@ dir-compare@^4.2.0:
minimatch "^3.0.5"
p-limit "^3.1.0 "
dmg-builder@25.1.8:
version "25.1.8"
resolved "https://registry.yarnpkg.com/dmg-builder/-/dmg-builder-25.1.8.tgz#41f3b725edd896156e891016a44129e1bd580430"
integrity sha512-NoXo6Liy2heSklTI5OIZbCgXC1RzrDQsZkeEwXhdOro3FT1VBOvbubvscdPnjVuQ4AMwwv61oaH96AbiYg9EnQ==
dmg-builder@26.0.0-alpha.10:
version "26.0.0-alpha.10"
resolved "https://registry.yarnpkg.com/dmg-builder/-/dmg-builder-26.0.0-alpha.10.tgz#d4d908922005a0c852d0919a7dd0b8f77d3c4bd0"
integrity sha512-RWzCNLLu4dGIvBf8kBzjF/zI5aMOSA149S1V2NgAA4La8f8ghdJAm/DI5crSb2zDijFLyTNmUGTtvU6eHgiZyQ==
dependencies:
app-builder-lib "25.1.8"
builder-util "25.1.7"
builder-util-runtime "9.2.10"
app-builder-lib "26.0.0-alpha.10"
builder-util "26.0.0-alpha.10"
builder-util-runtime "9.3.0-alpha.0"
fs-extra "^10.1.0"
iconv-lite "^0.6.2"
js-yaml "^4.1.0"
@@ -1217,16 +1232,16 @@ ejs@^3.1.8:
dependencies:
jake "^10.8.5"
electron-builder@^25.1.8:
version "25.1.8"
resolved "https://registry.yarnpkg.com/electron-builder/-/electron-builder-25.1.8.tgz#b0e310f1600787610bb84c3f39bc7aadb2548486"
integrity sha512-poRgAtUHHOnlzZnc9PK4nzG53xh74wj2Jy7jkTrqZ0MWPoHGh1M2+C//hGeYdA+4K8w4yiVCNYoLXF7ySj2Wig==
electron-builder@^26.0.0-alpha.10:
version "26.0.0-alpha.10"
resolved "https://registry.yarnpkg.com/electron-builder/-/electron-builder-26.0.0-alpha.10.tgz#6f629f5f1f3340286af71cabd12d94edc53f15ea"
integrity sha512-QTitqOlP5aZ/8zhnxqjRb6BxSR7Kvwv07PoBGeIXADwSPHQhKhZ+S+GRFzUSYQrMTTJLGzUHbnAes6fZ3uThEA==
dependencies:
app-builder-lib "25.1.8"
builder-util "25.1.7"
builder-util-runtime "9.2.10"
app-builder-lib "26.0.0-alpha.10"
builder-util "26.0.0-alpha.10"
builder-util-runtime "9.3.0-alpha.0"
chalk "^4.1.2"
dmg-builder "25.1.8"
dmg-builder "26.0.0-alpha.10"
fs-extra "^10.1.0"
is-ci "^3.0.0"
lazy-val "^1.0.5"
@@ -1238,15 +1253,16 @@ electron-log@^5.2.4:
resolved "https://registry.yarnpkg.com/electron-log/-/electron-log-5.2.4.tgz#6b488d9db80aa3c6f3dc39bcd635fc9d1f79c8af"
integrity sha512-iX12WXc5XAaKeHg2QpiFjVwL+S1NVHPFd3V5RXtCmKhpAzXsVQnR3UEc0LovM6p6NkUQxDWnkdkaam9FNUVmCA==
electron-publish@25.1.7:
version "25.1.7"
resolved "https://registry.yarnpkg.com/electron-publish/-/electron-publish-25.1.7.tgz#14e50c2a3fafdc1c454eadbbc47ead89a48bb554"
integrity sha512-+jbTkR9m39eDBMP4gfbqglDd6UvBC7RLh5Y0MhFSsc6UkGHj9Vj9TWobxevHYMMqmoujL11ZLjfPpMX+Pt6YEg==
electron-publish@26.0.0-alpha.10:
version "26.0.0-alpha.10"
resolved "https://registry.yarnpkg.com/electron-publish/-/electron-publish-26.0.0-alpha.10.tgz#16ac95acca2d796ca00c7a90ca27ebf31855f284"
integrity sha512-yUkCJD7MLN57d6PJ8PMcBCR35xytA+jHyrOiS/H0hlmTOWq1sXN+tIBylX4h0dD/C6mn75/y5eE156Pe2nccPw==
dependencies:
"@types/fs-extra" "^9.0.11"
builder-util "25.1.7"
builder-util-runtime "9.2.10"
builder-util "26.0.0-alpha.10"
builder-util-runtime "9.3.0-alpha.0"
chalk "^4.1.2"
form-data "^4.0.0"
fs-extra "^10.1.0"
lazy-val "^1.0.5"
mime "^2.5.2"
@@ -1259,12 +1275,12 @@ electron-store@^8.2.0:
conf "^10.2.0"
type-fest "^2.17.0"
electron-updater@^6.3.9:
version "6.3.9"
resolved "https://registry.yarnpkg.com/electron-updater/-/electron-updater-6.3.9.tgz#e1e7f155624c58e6f3760f376c3a584028165ec4"
integrity sha512-2PJNONi+iBidkoC5D1nzT9XqsE8Q1X28Fn6xRQhO3YX8qRRyJ3mkV4F1aQsuRnYPqq6Hw+E51y27W75WgDoofw==
electron-updater@^6.4.0-alpha.3:
version "6.4.0-alpha.3"
resolved "https://registry.yarnpkg.com/electron-updater/-/electron-updater-6.4.0-alpha.3.tgz#4c33647c79f7ea1bcd184aac8a0b15d5a2b37cf1"
integrity sha512-pqbEqfKVly49UO3QhnRnzghK75BW6v6ZrpW/2vs+ZVVxHmrdwEl1bTjJFQl1LSIBABpBEwT5W9uwf3cKfrD+Bg==
dependencies:
builder-util-runtime "9.2.10"
builder-util-runtime "9.3.0-alpha.0"
fs-extra "^10.1.0"
js-yaml "^4.1.0"
lazy-val "^1.0.5"
@@ -1273,10 +1289,10 @@ electron-updater@^6.3.9:
semver "^7.6.3"
tiny-typed-emitter "^2.1.0"
electron@^33.2.1:
version "33.2.1"
resolved "https://registry.yarnpkg.com/electron/-/electron-33.2.1.tgz#d0d7bba7a7abf4f14881d0a6e03c498b301a2d5f"
integrity sha512-SG/nmSsK9Qg1p6wAW+ZfqU+AV8cmXMTIklUL18NnOKfZLlum4ZsDoVdmmmlL39ZmeCaq27dr7CgslRPahfoVJg==
electron@^34.0.0:
version "34.0.0"
resolved "https://registry.yarnpkg.com/electron/-/electron-34.0.0.tgz#30ccedbc02d2f036868b8278960fd0e438ec0e52"
integrity sha512-fpaPb0lifoUJ6UJa4Lk8/0B2Ku/xDZWdc1Gkj67jbygTCrvSon0qquju6Ltx1Kz23GRqqlIHXiy9EvrjpY7/Wg==
dependencies:
"@electron/get" "^2.0.0"
"@types/node" "^20.9.0"
@@ -1640,20 +1656,6 @@ function-bind@^1.1.2:
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c"
integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==
gauge@^4.0.3:
version "4.0.4"
resolved "https://registry.yarnpkg.com/gauge/-/gauge-4.0.4.tgz#52ff0652f2bbf607a989793d53b751bef2328dce"
integrity sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==
dependencies:
aproba "^1.0.3 || ^2.0.0"
color-support "^1.1.3"
console-control-strings "^1.1.0"
has-unicode "^2.0.1"
signal-exit "^3.0.7"
string-width "^4.2.3"
strip-ansi "^6.0.1"
wide-align "^1.1.5"
get-caller-file@^2.0.5:
version "2.0.5"
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
@@ -1713,7 +1715,7 @@ glob@^10.3.12, glob@^10.3.7:
package-json-from-dist "^1.0.0"
path-scurry "^1.11.1"
glob@^7.0.0, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6:
glob@^7.0.0, glob@^7.1.3, glob@^7.1.6:
version "7.2.3"
resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b"
integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==
@@ -1725,7 +1727,7 @@ glob@^7.0.0, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6:
once "^1.3.0"
path-is-absolute "^1.0.0"
glob@^8.0.1:
glob@^8.0.1, glob@^8.1.0:
version "8.1.0"
resolved "https://registry.yarnpkg.com/glob/-/glob-8.1.0.tgz#d388f656593ef708ee3e34640fdfb99a9fd1c33e"
integrity sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==
@@ -1817,11 +1819,6 @@ has-symbols@^1.0.3:
resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8"
integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==
has-unicode@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9"
integrity sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==
hasown@^2.0.0, hasown@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003"
@@ -2230,7 +2227,7 @@ lru-cache@^7.7.1:
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-7.18.3.tgz#f793896e0fd0e954a59dfdd82f0773808df6aa89"
integrity sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==
make-fetch-happen@^10.0.3:
make-fetch-happen@^10.2.1:
version "10.2.1"
resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-10.2.1.tgz#f5e3835c5e9817b617f2770870d9492d28678164"
integrity sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==
@@ -2337,7 +2334,7 @@ minimatch@^9.0.3, minimatch@^9.0.4:
dependencies:
brace-expansion "^2.0.1"
minimist@^1.2.3, minimist@^1.2.6:
minimist@^1.2.3, minimist@^1.2.5, minimist@^1.2.6:
version "1.2.8"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c"
integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==
@@ -2475,23 +2472,6 @@ node-api-version@^0.2.0:
dependencies:
semver "^7.3.5"
node-gyp@^9.0.0:
version "9.4.1"
resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-9.4.1.tgz#8a1023e0d6766ecb52764cc3a734b36ff275e185"
integrity sha512-OQkWKbjQKbGkMf/xqI1jjy3oCTgMKJac58G2+bjZb3fza6gW2YrCSdMQYaoTb70crvE//Gngr4f0AgVHmqHvBQ==
dependencies:
env-paths "^2.2.0"
exponential-backoff "^3.1.1"
glob "^7.1.4"
graceful-fs "^4.2.6"
make-fetch-happen "^10.0.3"
nopt "^6.0.0"
npmlog "^6.0.0"
rimraf "^3.0.2"
semver "^7.3.5"
tar "^6.1.2"
which "^2.0.2"
node-stream-zip@^1.15.0:
version "1.15.0"
resolved "https://registry.yarnpkg.com/node-stream-zip/-/node-stream-zip-1.15.0.tgz#158adb88ed8004c6c49a396b50a6a5de3bca33ea"
@@ -2514,16 +2494,6 @@ normalize-url@^6.0.1:
resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-6.1.0.tgz#40d0885b535deffe3f3147bec877d05fe4c5668a"
integrity sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==
npmlog@^6.0.0:
version "6.0.2"
resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-6.0.2.tgz#c8166017a42f2dea92d6453168dd865186a70830"
integrity sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==
dependencies:
are-we-there-yet "^3.0.0"
console-control-strings "^1.1.0"
gauge "^4.0.3"
set-blocking "^2.0.0"
object-keys@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e"
@@ -2724,12 +2694,12 @@ prettier-plugin-organize-imports@^4.1.0:
resolved "https://registry.yarnpkg.com/prettier-plugin-organize-imports/-/prettier-plugin-organize-imports-4.1.0.tgz#f3d3764046a8e7ba6491431158b9be6ffd83b90f"
integrity sha512-5aWRdCgv645xaa58X8lOxzZoiHAldAPChljr/MT0crXVOWTZ+Svl4hIWlz+niYSlO6ikE5UXkN1JrRvIP2ut0A==
prettier-plugin-packagejson@^2.5.6:
version "2.5.6"
resolved "https://registry.yarnpkg.com/prettier-plugin-packagejson/-/prettier-plugin-packagejson-2.5.6.tgz#cd3cca60e1aa87ee3ce3b4032c1c999798d9f714"
integrity sha512-TY7KiLtyt6Tlf53BEbXUWkN0+TRdHKgIMmtXtDCyHH6yWnZ50Lwq6Vb6lyjapZrhDTXooC4EtlY5iLe1sCgi5w==
prettier-plugin-packagejson@^2.5.8:
version "2.5.8"
resolved "https://registry.yarnpkg.com/prettier-plugin-packagejson/-/prettier-plugin-packagejson-2.5.8.tgz#1b307fce044d0230ea8f3210f8a731c5cc1b288d"
integrity sha512-BaGOF63I0IJZoudxpuQe17naV93BRtK8b3byWktkJReKEMX9CC4qdGUzThPDVO/AUhPzlqDiAXbp18U6X8wLKA==
dependencies:
sort-package-json "2.12.0"
sort-package-json "2.14.0"
synckit "0.9.2"
prettier@3.4.2:
@@ -2737,6 +2707,11 @@ prettier@3.4.2:
resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.4.2.tgz#a5ce1fb522a588bf2b78ca44c6e6fe5aa5a2b13f"
integrity sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==
proc-log@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/proc-log/-/proc-log-2.0.1.tgz#8f3f69a1f608de27878f91f5c688b225391cb685"
integrity sha512-Kcmo2FhfDTXdcbfDH76N7uBYHINxc/8GW7UAVuVP9I+Va3uHSerrnKV6dLooga/gh7GlgzuCCr/eoldnL1muGw==
progress@^2.0.3:
version "2.0.3"
resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8"
@@ -2785,7 +2760,7 @@ read-binary-file-arch@^1.0.6:
dependencies:
debug "^4.3.4"
readable-stream@^3.0.2, readable-stream@^3.4.0, readable-stream@^3.6.0:
readable-stream@^3.0.2, readable-stream@^3.4.0:
version "3.6.2"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967"
integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==
@@ -2953,11 +2928,6 @@ serialize-error@^7.0.1:
dependencies:
type-fest "^0.13.1"
set-blocking@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7"
integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==
shebang-command@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea"
@@ -2992,7 +2962,7 @@ shx@^0.3.4:
minimist "^1.2.3"
shelljs "^0.8.5"
signal-exit@^3.0.2, signal-exit@^3.0.7:
signal-exit@^3.0.2:
version "3.0.7"
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9"
integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==
@@ -3045,10 +3015,10 @@ sort-object-keys@^1.1.3:
resolved "https://registry.yarnpkg.com/sort-object-keys/-/sort-object-keys-1.1.3.tgz#bff833fe85cab147b34742e45863453c1e190b45"
integrity sha512-855pvK+VkU7PaKYPc+Jjnmt4EzejQHyhhF33q31qG8x7maDzkeFhAAThdCYay11CISO+qAMwjOBP+fPZe0IPyg==
sort-package-json@2.12.0:
version "2.12.0"
resolved "https://registry.yarnpkg.com/sort-package-json/-/sort-package-json-2.12.0.tgz#4196a1ba82ba63c4a512add1d00ab39026bf8ab7"
integrity sha512-/HrPQAeeLaa+vbAH/znjuhwUluuiM/zL5XX9kop8UpDgjtyWKt43hGDk2vd/TBdDpzIyzIHVUgmYofzYrAQjew==
sort-package-json@2.14.0:
version "2.14.0"
resolved "https://registry.yarnpkg.com/sort-package-json/-/sort-package-json-2.14.0.tgz#ba0c7420dc6edea4b0eb7e9f502fda63f57586d8"
integrity sha512-xBRdmMjFB/KW3l51mP31dhlaiFmqkHLfWTfZAno8prb/wbDxwBPWFpxB16GZbiPbYr3wL41H8Kx22QIDWRe8WQ==
dependencies:
detect-indent "^7.0.1"
detect-newline "^4.0.0"
@@ -3089,7 +3059,7 @@ stat-mode@^1.0.0:
resolved "https://registry.yarnpkg.com/stat-mode/-/stat-mode-1.0.0.tgz#68b55cb61ea639ff57136f36b216a291800d1465"
integrity sha512-jH9EhtKIjuXZ2cWxmXS8ZP80XyC3iasQxMDV8jzhNJpfDb7VbQLVW4Wvsxz9QZvzV+G4YoSfBUVKDOyxLzi/sg==
"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
version "4.2.3"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
@@ -3151,7 +3121,7 @@ synckit@0.9.2:
"@pkgr/core" "^0.1.0"
tslib "^2.6.2"
tar@^6.0.5, tar@^6.1.11, tar@^6.1.12, tar@^6.1.2:
tar@^6.0.5, tar@^6.1.11, tar@^6.1.12, tar@^6.2.1:
version "6.2.1"
resolved "https://registry.yarnpkg.com/tar/-/tar-6.2.1.tgz#717549c541bc3c2af15751bea94b1dd068d4b03a"
integrity sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==
@@ -3232,10 +3202,10 @@ truncate-utf8-bytes@^1.0.0:
dependencies:
utf8-byte-length "^1.0.1"
ts-api-utils@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.3.0.tgz#4b490e27129f1e8e686b45cc4ab63714dc60eea1"
integrity sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==
ts-api-utils@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-2.0.0.tgz#b9d7d5f7ec9f736f4d0f09758b8607979044a900"
integrity sha512-xCt/TOAc+EOHS1XPnijD3/yzpH6qg2xppZO1YDqGoVsNXfQfzHpOdNuXwrwOU8u4ITXJyDCTyt8w5g1sZv9ynQ==
tslib@^2.1.0, tslib@^2.6.2:
version "2.7.0"
@@ -3264,14 +3234,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.18.2:
version "8.18.2"
resolved "https://registry.yarnpkg.com/typescript-eslint/-/typescript-eslint-8.18.2.tgz#71334dcf843adc3fbb771dce5ade7876aa0d62b7"
integrity sha512-KuXezG6jHkvC3MvizeXgupZzaG5wjhU3yE8E7e6viOvAvD9xAWYp8/vy0WULTGe9DYDWcQu7aW03YIV3mSitrQ==
typescript-eslint@^8.21.0:
version "8.21.0"
resolved "https://registry.yarnpkg.com/typescript-eslint/-/typescript-eslint-8.21.0.tgz#78bdb83a6d771f0312b128297d84a3111885fd08"
integrity sha512-txEKYY4XMKwPXxNkN8+AxAdX6iIJAPiJbHE/FpQccs/sxw8Lf26kqwC3cn0xkHlW8kEbLhkhCsjWuMveaY9Rxw==
dependencies:
"@typescript-eslint/eslint-plugin" "8.18.2"
"@typescript-eslint/parser" "8.18.2"
"@typescript-eslint/utils" "8.18.2"
"@typescript-eslint/eslint-plugin" "8.21.0"
"@typescript-eslint/parser" "8.21.0"
"@typescript-eslint/utils" "8.21.0"
typescript@^5.4.3:
version "5.5.4"
@@ -3357,13 +3327,6 @@ which@^2.0.1, which@^2.0.2:
dependencies:
isexe "^2.0.0"
wide-align@^1.1.5:
version "1.1.5"
resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.5.tgz#df1d4c206854369ecf3c9a4898f1b23fbd9d15d3"
integrity sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==
dependencies:
string-width "^1.0.2 || 2 || 3 || 4"
winreg@1.2.4:
version "1.2.4"
resolved "https://registry.yarnpkg.com/winreg/-/winreg-1.2.4.tgz#ba065629b7a925130e15779108cf540990e98d1b"

View File

@@ -38,3 +38,11 @@ that the original is not modified. For more details, see the
A two way sync is not currently supported. Attempting to export data to the same
folder that is also being watched by the Ente app will result in undefined
behaviour (e.g. duplicate files, export stalling etc).
## Why is my export size larger than my backed-up size in Ente?
One possible reason could be that you have files that are in multiple different
albums. Whenever a file is backed-up to Ente in multiple albums it will still
count only once towards the total storage in Ente. However, during export that
file will be downloaded multiple times to the different folders corresponding to
said albums, causing the total export size to be larger.

View File

@@ -10,6 +10,12 @@ description:
The getting started instructions mention using `yarn dev` (which is an alias of
`yarn dev:photos`) to serve your web app.
>[!IMPORTANT]
> Please note that Ente's Web App supports the Yarn version 1.22.xx or 1.22.22 specifically.
> Make sure to install the right version or modify your yarn installation to meet the requirements.
> The user might end up into unknown version and dependency related errors if yarn
> is on different version.
```sh
cd ente/web
git submodule update --init --recursive
@@ -157,8 +163,8 @@ npm install pm2@latest
Copy the below contents to a file called `ecosystem.config.js` inside the
`ente/web` directory.
```js
module.exports = {
```js
module.exports = {
apps: [
{
name: "photos",
@@ -174,7 +180,8 @@ Copy the below contents to a file called `ecosystem.config.js` inside the
env: {
NODE_ENV: "development",
PORT: "3001"
},
}
},
{
name: "auth",
script: "yarn workspace auth next dev",

View File

@@ -1,43 +1,20 @@
.container {
position: relative; /* Ensure the parent is relatively positioned */
height: 100vh; /* Full viewport height */
width: 100vw; /* Full viewport width */
display: flex;
justify-content: center;
max-width: 1200px;
height: auto;
align-items: center;
margin: 0 auto;
}
.center-table {
display: table;
}
.input-form {
display: flex;
flex-direction: column;
align-items: center;
}
.horizontal-group {
position: absolute; /* Use absolute positioning */
top: 32px; /* 32px below the top of the page */
left: 32px; /* 32px from the leftmost edge of the page */
right: 32px;
display: flex;
align-items: center; /* Align items vertically centered */
gap: 20px; /* Adjust the gap between elements as needed */
background-color: #fafafa;
height: 104px;
width: 1375px;
border-radius: 10px;
}
.fetch-button-container button {
background-color: #00b33c;
color: white;
border: none;
width: 199px;
height: 56px;
margin-left: 20px;
}
.fetch-button-container button:hover {
@@ -52,15 +29,9 @@
color: inherit; /* Inherit color from parent */
font-weight: bold; /* Make the text bold */
font-size: 40px;
margin-bottom: 25px;
}
.text-field-token {
margin-left: 70px !important; /* Adjust margin for Token field */
}
.text-field-email {
margin-left: 20px !important; /* Adjust margin for Email field */
}
.duckie-container {
position: absolute;
top: 50%;
@@ -85,32 +56,31 @@
justify-content: center;
align-items: center;
}
.container {
position: relative; /* Ensure the parent is relatively positioned */
height: 100vh; /* Full viewport height */
width: 100vw; /* Full viewport width */
display: flex;
flex-direction: column; /* Add this */
justify-content: center; /* Center vertically */
align-items: center; /* Center horizontally */
}
.input-form {
display: flex;
flex-direction: column;
align-items: center;
z-index: 1; /* Ensure form is on top */
justify-content: space-around;
marign: 20px;
}
.horizontal-group {
display: flex;
align-items: center;
gap: 20px; /* Adjust the gap between elements as needed */
background-color: #fafafa;
background-color: #fcfcfc;
padding: 20px; /* Add padding around content */
border-radius: 10px;
margin-top: 90px;
width: 1200px;
justify-content: space-around;
}
.text-fields {
display: flex;
justify-content: row;
gap: 20px;
}
.fetch-button-container button {
background-color: #00b33c;
color: white;
@@ -123,24 +93,6 @@
background-color: #007c6c;
}
.link-text {
display: flex;
align-items: center;
padding: 0 16px; /* Add padding for better appearance */
text-decoration: none; /* Remove underline */
color: inherit; /* Inherit color from parent */
font-weight: bold; /* Make the text bold */
font-size: 40px;
}
.text-field-token {
margin-left: 70px !important; /* Adjust margin for Token field */
}
.text-field-email {
margin-left: 50px !important; /* Adjust margin for Email field */
}
.center-content {
display: flex;
justify-content: center;
@@ -157,44 +109,11 @@
align-items: center;
}
/* Example CSS to maintain tabs fixed position */
.tabs-container {
position: sticky;
top: 20px; /* Adjust as needed */
z-index: 1000; /* Ensure tabs are above other content */
}
.container {
position: relative; /* Ensure the parent is relatively positioned */
height: 100vh; /* Full viewport height */
width: 100vw; /* Full viewport width */
display: flex;
flex-direction: column; /* Ensure children stack vertically */
justify-content: center; /* Center vertically */
align-items: center; /* Center horizontally */
}
.input-form {
display: flex;
flex-direction: column;
align-items: center;
z-index: 1; /* Ensure form is on top */
margin-bottom: 20px; /* Add space between form and tabs */
}
.horizontal-group {
display: flex;
align-items: center;
gap: 20px; /* Adjust the gap between elements as needed */
background-color: #fafafa;
padding: 20px; /* Add padding around content */
border-radius: 10px;
}
.fetch-button-container button {
background-color: #00b33c;
color: white;
border: none;
width: 199px;
width: 150px;
height: 56px;
}
@@ -202,24 +121,6 @@
background-color: #007c6c;
}
.link-text {
display: flex;
align-items: center;
padding: 0 16px; /* Add padding for better appearance */
text-decoration: none; /* Remove underline */
color: inherit; /* Inherit color from parent */
font-weight: bold; /* Make the text bold */
font-size: 40px;
}
.text-field-token {
margin-left: 70px !important; /* Adjust margin for Token field */
}
.text-field-email {
margin-left: 50px !important; /* Adjust margin for Email field */
}
.center-content {
display: flex;
justify-content: center;
@@ -236,14 +137,6 @@
align-items: center;
}
.tabs-container {
position: sticky; /* Make the tabs sticky */
top: 0; /* Stick to the top of the viewport */
z-index: 1000; /* Ensure tabs are above other content */
background-color: #fafafa; /* Optional: Add background color to tabs */
padding: 10px 20px; /* Optional: Add padding for better appearance */
border-bottom: 1px solid #ccc; /* Optional: Add bottom border */
}
.dialog-popup-container {
/* Styles for the overlay/background */
position: fixed;
@@ -313,21 +206,12 @@
min-height: 100vh;
}
.input-form {
margin-bottom: 16px;
}
.content-container {
display: flex;
flex-direction: column;
align-items: center;
gap: 25px;
width: 100%;
margin-top: 150px;
}
.horizontal-group {
display: flex;
align-items: center;
}
.fetch-button-container {
@@ -335,13 +219,52 @@
margin-left: 10px;
}
.text-field-token,
.text-field-email {
margin: 0 8px;
}
.error-message {
color: red;
font-weight: bold;
margin-top: 16px;
}
/* MUi Component Custom CSS */
css-1t8l2tu-MuiInputBase-input-MuiOutlinedInput-input {
padding: none;
margin: none;
}
/* Mobile */
@media screen and (max-width: 475px) {
.link-text {
font-size: 30px;
text-align: center;
}
.input-form {
max-width: 400px;
align-items: center;
gap: 20px;
flex-direction: row;
}
.horizontal-group {
width: 500px;
flex-direction: column;
gap: 25px;
}
.text-fields {
width: fit-content;
flex-direction: column;
gap: 20px;
justify-content: center;
}
.text-fields label {
padding: 0;
margin: none;
}
}
@media screen and (max-width: 576px) {
}
@media screen and (max-width: 900px) {
}
@media screen and (max-width: 1200px) {
}

View File

@@ -1,3 +1,4 @@
import { Link } from "@mui/material";
import Box from "@mui/material/Box";
import Button from "@mui/material/Button";
import CircularProgress from "@mui/material/CircularProgress";
@@ -227,68 +228,116 @@ const App: React.FC = () => {
const handleTabChange = (
_event: React.SyntheticEvent,
newValue: number,
) => {
setTabValue(newValue);
};
useEffect(() => {
const searchParam = new URLSearchParams(window.location.search);
const userToken = searchParam.get("token");
if (userToken) {
setLocalToken(userToken);
setToken(userToken);
const editToken = document.getElementById(":r1:");
if (editToken instanceof HTMLInputElement) {
editToken.readOnly = true;
}
}
}, []);
const updateToken = () => {
const editToken = document.getElementById(":r1:");
if (editToken instanceof HTMLInputElement) {
editToken.readOnly = false;
// Change focus to token field
editToken.focus();
}
};
return (
<div className="container">
<form className="input-form" onKeyPress={handleKeyPress}>
<div className="horizontal-group">
<a
href="https://staff.ente.sh"
target="_blank"
rel="noopener noreferrer"
className="link-text"
>
staff.ente.sh
</a>
<TextField
label="Token"
value={localToken}
onChange={(e) => {
setLocalToken(e.target.value);
setToken(e.target.value);
}}
size="medium"
className="text-field-token"
style={{ width: "350px" }}
/>
<TextField
label="Email"
value={localEmail}
onChange={(e) => {
setLocalEmail(e.target.value);
setEmail(e.target.value);
}}
size="medium"
className="text-field-email"
style={{ width: "350px" }}
/>
<div className="fetch-button-container">
<Button
variant="contained"
onClick={() => {
fetchData().catch((error: unknown) =>
console.error("Fetch data error:", error),
);
}}
className="fetch-button"
style={{
padding: "0 16px",
}}
<div>
<form className="input-form" onKeyPress={handleKeyPress}>
<div className="horizontal-group">
<a
href="https://staff.ente.sh"
target="_blank"
rel="noopener noreferrer"
className="link-text"
>
FETCH
</Button>
staff.ente.io
</a>
<div className="text-fields">
<div
style={{
display: "flex",
flexDirection: "column",
}}
>
<TextField
label="Token"
value={localToken}
onChange={(e) => {
setLocalToken(e.target.value);
setToken(e.target.value);
}}
size="medium"
className="text-field-token"
style={{ maxWidth: "parent" }}
/>
<Link
style={{ textAlign: "left" }}
onClick={updateToken}
>
Update Token?
</Link>
</div>
<TextField
label="Email"
value={localEmail}
onChange={(e) => {
setLocalEmail(e.target.value);
setEmail(e.target.value);
}}
size="medium"
className="text-field-email"
style={{ width: "parent" }}
/>
</div>
<div className="fetch-button-container">
<Button
variant="contained"
onClick={() => {
fetchData().catch((error: unknown) =>
console.error(
"Fetch data error:",
error,
),
);
}}
className="fetch-button"
style={{
padding: "0 16px",
}}
>
FETCH
</Button>
</div>
</div>
</div>
</form>
</form>
</div>
<div className="content-container">
{loading ? (
<CircularProgress
sx={{ color: "black", marginTop: "200px" }}
sx={{
color: "black",
top: "200px",
position: "fixed",
}}
/>
) : error ? (
<div className="error-message">{error}</div>

View File

@@ -46,7 +46,7 @@ You can alternatively install the build from PlayStore or F-Droid.
## 🧑‍💻 Building from source
1. [Install Flutter v3.24.3](https://flutter.dev/docs/get-started/install).
1. [Install Flutter v3.27.2](https://flutter.dev/docs/get-started/install).
2. Pull in all submodules with `git submodule update --init --recursive`

View File

@@ -61,6 +61,7 @@ analyzer:
unnecessary_const: error
cancel_subscriptions: error
unrelated_type_equality_checks: error
unnecessary_cast: info
unawaited_futures: warning # convert to warning after fixing existing issues

View File

@@ -0,0 +1,36 @@
ente este o aplicație simplă pentru a face copii de rezervă și a partaja fotografiile și videoclipurile.
Dacă ați căutat o alternativă la Google Photos care să respecte confidențialitatea, ați ajuns la locul potrivit. Cu ente, acestea sunt stocate criptat integral (e2ee). Asta înseamnă că numai dvs. le puteți vedea.
Avem aplicații open-source pentru Android, iOS, web și desktop, iar fotografiile dvs. se vor sincroniza perfect între toate acestea într-o manieră criptată integral (e2ee).
De asemenea, ente simplifică partajarea albumelor dvs. cu cei dragi, chiar dacă aceștia nu folosesc ente. Puteți partaja linkuri vizibile public, unde aceștia pot vizualiza albumul dvs. și pot colabora prin adăugarea de fotografii la acesta, chiar și fără un cont sau o aplicație.
Datele dvs. criptate sunt copiate în 3 locații diferite, inclusiv într-un adăpost antiatomic din Paris. Luăm posteritatea în serios și vă asigurăm că amintirile dvs. vor ajunge la următoarea generație.
Suntem aici pentru a crea cea mai sigură aplicație de fotografii, veniți alături de noi!
CARACTERISTICI
- Copii de rezervă în calitate originală, deoarece fiecare pixel contează
- Planuri de familie, astfel încât să puteți distribui spațiul cu familia dvs.
- Albume colaborative, astfel încât să puteți pune în comun fotografii după o excursie
- Dosare distribuite, în cazul în care doriți ca partenerul dvs. să se bucure și de fotografiile dvs.
- Linkuri pentru albume care pot fi protejate cu o parolă
- Abilitatea de a elibera spațiu, prin eliminarea fișierelor care au fost salvate în siguranță
- Asistență umană, pentru că meritați
- Descrieri, astfel încât să vă puteți subtitra amintirile și să le găsiți cu ușurință
- Editor de imagini, pentru a adăuga ultimele retușuri
- Evidențiați, ascundeți și retrăiți-vă amintirile, căci sunt prețioase
- Import cu o singură apăsare din Google, Apple, hard disk și multe altele
- Temă întunecată, deoarece fotografiile dvs. arată bine și cu ea
- 2FA, 3FA, autentificare biometrică
- și MULTE altele!
PERMISIUNI
ente solicită anumite permisiuni pentru a servi scopului unui furnizor de stocare a fotografiilor, care poate fi revizuit aici: https://github.com/ente-io/ente/blob/f-droid/mobile/android/permissions.md
PREȚURI
Nu oferim planuri gratuite pentru totdeauna, deoarece este important pentru noi să rămânem sustenabili și să trecem testul timpului. În schimb, oferim planuri accesibile pe care le puteți distribui liber familiei dvs. Puteți afla mai multe la ente.io.
ASISTENȚĂ
Suntem mândri să oferim asistență umană. Dacă sunteți clientul nostru plătit, vă puteți adresa la team@ente.io și așteptați un răspuns din partea echipei noastre în termen de 24 de ore.

View File

@@ -0,0 +1 @@
ente este o aplicație de stocare foto criptată integral

View File

@@ -0,0 +1 @@
ente - stocare foto criptată

View File

@@ -0,0 +1,33 @@
Ente este o aplicație simplă pentru a face automat copii de rezervă și a vă organiza fotografiile și videoclipurile.
Dacă erați în căutarea unei alternative care să respecte confidențialitatea pentru a vă păstra amintirile, ați ajuns la locul potrivit. Cu Ente, acestea sunt stocate criptate integral (e2ee). Asta înseamnă că numai dvs. le puteți vedea.
Avem aplicații pentru toate platformele, iar fotografiile dvs. se vor sincroniza perfect între toate dispozitivele dvs. într-un mod criptat integral (e2ee).
De asemenea, Ente simplifică distribuirea albumelor dvs. cu cei dragi. Puteți fie să le distribuiți direct altor utilizatori Ente, criptate integral, fie cu linkuri care pot fi vizualizate public.
Datele dvs. criptate sunt stocate în mai multe locații, inclusiv într-un adăpost antiatomic din Paris. Luăm posteritatea în serios și vă asigurăm că amintirile dvs. vor ajunge la următoarea generație.
Suntem aici pentru a crea cea mai sigură aplicație de fotografii, veniți alături de noi!
CARACTERISTICI
- Copii de rezervă în calitate originală, deoarece fiecare pixel contează
- Planuri de familie, astfel încât să puteți distribui spațiul cu familia dvs.
- Dosare distribuite, în cazul în care doriți ca partenerul dvs. să se bucure și de fotografiile dvs.
- Linkuri pentru albume, care pot fi protejate cu o parolă și setate să expire
- Abilitatea de a elibera spațiu, prin eliminarea fișierelor care au fost salvate în siguranță
- Editor de imagini, pentru a adăuga ultimele retușuri
- Evidențiați, ascundeți și retrăiți-vă amintirile, căci sunt prețioase
- Import cu un singur clic de la toți furnizorii majori de stocare
- Temă întunecată, deoarece fotografiile dvs. arată bine și cu ea
- 2FA, 3FA, autentificare biometrică
- și MULTE altele!
PREȚURI
Nu oferim planuri gratuite pentru totdeauna, deoarece este important pentru noi să rămânem sustenabili și să trecem testul timpului. În schimb, oferim planuri accesibile pe care le puteți distribui liber familiei dvs. Puteți afla mai multe la ente.io.
ASISTENȚĂ
Suntem mândri să oferim asistență umană. Dacă sunteți clientul nostru plătit, vă puteți adresa la team@ente.io și așteptați un răspuns din partea echipei noastre în termen de 24 de ore.
TERMENI
https://ente.io/terms

View File

@@ -0,0 +1 @@
fotografii,fotografie,familie,intimitate,cloud,backup,video,foto,criptare,stocare,album,alternative

View File

@@ -0,0 +1 @@
Ente Foto

View File

@@ -0,0 +1 @@
Stocare foto criptată

View File

@@ -1,4 +1,3 @@
import "dart:io";
import "dart:typed_data";
import "package:logging/logging.dart";
@@ -98,15 +97,4 @@ extension ClipDB on MLDataDB {
embedding.version,
];
}
Future<void> _clearDeprecatedStores(Directory dir) async {
final deprecatedObjectBox = Directory(dir.path + "/object-box-store");
if (await deprecatedObjectBox.exists()) {
await deprecatedObjectBox.delete(recursive: true);
}
final deprecatedIsar = File(dir.path + "/default.isar");
if (await deprecatedIsar.exists()) {
await deprecatedIsar.delete();
}
}
}

View File

@@ -2,6 +2,8 @@
"@@locale ": "en",
"enterYourEmailAddress": "Voer uw e-mailadres in",
"accountWelcomeBack": "Welkom terug!",
"emailAlreadyRegistered": "E-mail is al geregistreerd.",
"emailNotRegistered": "E-mail niet geregistreerd.",
"email": "E-mail",
"cancel": "Annuleer",
"verify": "Verifiëren",
@@ -185,6 +187,8 @@
},
"allowAddPhotosDescription": "Sta toe dat mensen met de link ook foto's kunnen toevoegen aan het gedeelde album.",
"passwordLock": "Wachtwoord slot",
"canNotOpenTitle": "Kan dit album niet openen",
"canNotOpenBody": "Sorry, dit album kan niet worden geopend in de app.",
"disableDownloadWarningTitle": "Let op",
"disableDownloadWarningBody": "Kijkers kunnen nog steeds screenshots maken of een kopie van je foto's opslaan met behulp van externe tools",
"allowDownloads": "Downloads toestaan",
@@ -1378,6 +1382,7 @@
"extraPhotosFound": "Extra foto's gevonden",
"configuration": "Configuratie",
"localIndexing": "Lokaal indexeren",
"processed": "Verwerkt",
"resetPerson": "Verwijderen",
"areYouSureYouWantToResetThisPerson": "Weet u zeker dat u deze persoon wilt resetten?",
"allPersonGroupingWillReset": "Alle groepen voor deze persoon worden gereset, en je verliest alle suggesties die voor deze persoon zijn gedaan",
@@ -1578,5 +1583,11 @@
},
"legacyInvite": "{email} heeft je uitgenodigd om een vertrouwd contact te zijn",
"authToManageLegacy": "Verifieer om je vertrouwde contacten te beheren",
"useDifferentPlayerInfo": "Problemen met het afspelen van deze video? Hier ingedrukt houden om een andere speler te proberen."
"useDifferentPlayerInfo": "Problemen met het afspelen van deze video? Hier ingedrukt houden om een andere speler te proberen.",
"hideSharedItemsFromHomeGallery": "Verberg gedeelde bestanden uit de galerij",
"gallery": "Galerij",
"joinAlbum": "Deelnemen aan album",
"joinAlbumSubtext": "om je foto's te bekijken en toe te voegen",
"joinAlbumSubtextViewer": "om dit aan gedeelde albums toe te voegen",
"join": "Deelnemen"
}

View File

@@ -2,6 +2,8 @@
"@@locale ": "en",
"enterYourEmailAddress": "Introduceți adresa de e-mail",
"accountWelcomeBack": "Bine ați revenit!",
"emailAlreadyRegistered": "E-mail deja înregistrat.",
"emailNotRegistered": "E-mailul nu este înregistrat.",
"email": "E-mail",
"cancel": "Anulare",
"verify": "Verificare",
@@ -185,6 +187,8 @@
},
"allowAddPhotosDescription": "Permiteți persoanelor care au linkul să adauge și fotografii la albumul distribuit.",
"passwordLock": "Blocare cu parolă",
"canNotOpenTitle": "Nu se poate deschide acest album",
"canNotOpenBody": "Ne pare rău, acest album nu poate fi deschis în aplicație.",
"disableDownloadWarningTitle": "Rețineți",
"disableDownloadWarningBody": "Observatorii pot să facă capturi de ecran sau să salveze o copie a fotografiilor dvs. folosind instrumente externe",
"allowDownloads": "Permiteți descărcările",
@@ -351,6 +355,7 @@
"failedToLoadAlbums": "Încărcarea albumelor nu a reușit",
"hidden": "Ascunse",
"authToViewYourHiddenFiles": "Vă rugăm să vă autentificați pentru a vedea fișierele ascunse",
"authToViewTrashedFiles": "Vă rugăm să vă autentificați pentru a vedea fișierele din coșul de gunoi",
"trash": "Coș de gunoi",
"uncategorized": "Necategorisite",
"videoSmallCase": "videoclip",
@@ -412,6 +417,7 @@
"description": "The text to display in the advanced settings section"
},
"photoGridSize": "Dimensiunea grilei foto",
"manageDeviceStorage": "Gestionați memoria cache a dispozitivului",
"manageDeviceStorageDesc": "Revizuiți și ștergeți spațiul din memoria cache locală.",
"machineLearning": "Învățare automată",
"mlConsent": "Activați învățarea automată",
@@ -688,6 +694,8 @@
"noPhotosAreBeingBackedUpRightNow": "Nicio fotografie nu este salvată în acest moment",
"preserveMore": "Păstrați mai multe",
"grantFullAccessPrompt": "Vă rugăm să permiteți accesul la toate fotografiile în aplicația Setări",
"allowPermTitle": "Permiteți accesul la fotografii",
"allowPermBody": "Vă rugăm să permiteți accesul la fotografiile dvs. din Setări, astfel încât Ente să vă poată afișa și salva biblioteca.",
"openSettings": "Deschideți Setări",
"selectMorePhotos": "Selectați mai multe fotografii",
"existingUser": "Utilizator existent",
@@ -1090,6 +1098,83 @@
"description": "Label of confirm button to add a new custom radius to the radius selector of a location tag"
},
"setRadius": "Setare rază",
"familyPlanPortalTitle": "Familie",
"familyPlanOverview": "Adăugați 5 membri ai familiei la planul dvs. existent fără a plăti suplimentar.\n\nFiecare membru primește propriul spațiu privat și nu poate vedea fișierele celuilalt decât dacă acestea sunt partajate.\n\nPlanurile de familie sunt disponibile pentru clienții care au un abonament Ente plătit.\n\nAbonați-vă acum pentru a începe!",
"androidBiometricHint": "Verificați-vă identitatea",
"@androidBiometricHint": {
"description": "Hint message advising the user how to authenticate with biometrics. It is used on Android side. Maximum 60 characters."
},
"androidBiometricNotRecognized": "Neidentificat. Încercați din nou.",
"@androidBiometricNotRecognized": {
"description": "Message to let the user know that authentication was failed. It is used on Android side. Maximum 60 characters."
},
"androidBiometricSuccess": "Succes",
"@androidBiometricSuccess": {
"description": "Message to let the user know that authentication was successful. It is used on Android side. Maximum 60 characters."
},
"androidCancelButton": "Anulare",
"@androidCancelButton": {
"description": "Message showed on a button that the user can click to leave the current dialog. It is used on Android side. Maximum 30 characters."
},
"androidSignInTitle": "Autentificare necesară",
"@androidSignInTitle": {
"description": "Message showed as a title in a dialog which indicates the user that they need to scan biometric to continue. It is used on Android side. Maximum 60 characters."
},
"androidBiometricRequiredTitle": "Biometrice necesare",
"@androidBiometricRequiredTitle": {
"description": "Message showed as a title in a dialog which indicates the user has not set up biometric authentication on their device. It is used on Android side. Maximum 60 characters."
},
"androidDeviceCredentialsRequiredTitle": "Sunt necesare acreditările dispozitivului",
"@androidDeviceCredentialsRequiredTitle": {
"description": "Message showed as a title in a dialog which indicates the user has not set up credentials authentication on their device. It is used on Android side. Maximum 60 characters."
},
"androidDeviceCredentialsSetupDescription": "Sunt necesare acreditările dispozitivului",
"@androidDeviceCredentialsSetupDescription": {
"description": "Message advising the user to go to the settings and configure device credentials on their device. It shows in a dialog on Android side."
},
"goToSettings": "Mergeți la setări",
"@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": "Autentificarea biometrică nu este configurată pe dispozitivul dvs. Mergeți la „Setări > Securitate” pentru a adăuga autentificarea biometrică.",
"@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": "Autentificarea biometrică este dezactivată. Vă rugăm să blocați și să deblocați ecranul pentru a o activa.",
"@iOSLockOut": {
"description": "Message advising the user to re-enable biometrics on their device. It shows in a dialog on iOS side."
},
"iOSGoToSettingsDescription": "Autentificarea biometrică nu este configurată pe dispozitivul dvs. Vă rugăm să activați Touch ID sau Face ID pe telefonul dvs.",
"@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."
},
"openstreetmapContributors": "Contribuitori OpenStreetMap",
"hostedAtOsmFrance": "Găzduit la OSM Franţa",
"map": "Hartă",
"@map": {
"description": "Label for the map view"
},
"maps": "Hărţi",
"enableMaps": "Activare hărți",
"enableMapsDesc": "Se va afișa fotografiile dvs. pe o hartă a lumii.\n\nAceastă hartă este găzduită de Open Street Map, iar locațiile exacte ale fotografiilor dvs. nu sunt niciodată partajate.\n\nPuteți dezactiva această funcție oricând din Setări.",
"quickLinks": "Link-uri rapide",
"selectItemsToAdd": "Selectați elementele de adăugat",
"addSelected": "Adăugați selectate",
"addFromDevice": "Adăugați de pe dispozitiv",
"addPhotos": "Adăugați fotografii",
"noPhotosFoundHere": "Nu s-au găsit fotografii aici",
"zoomOutToSeePhotos": "Micșorați pentru a vedea fotografiile",
"noImagesWithLocation": "Nicio imagine cu locație",
"unpinAlbum": "Anulați fixarea albumului",
"pinAlbum": "Fixați albumul",
"create": "Creare",
"viewAll": "Vizualizați tot",
"nothingSharedWithYouYet": "Nimic distribuit cu dvs. încă",
"noAlbumsSharedByYouYet": "Niciun album nu a fost distribuit de dvs. încă",
"sharedWithYou": "Distribuite cu dvs.",
"sharedByYou": "Distribuite de dvs.",
"inviteYourFriendsToEnte": "Invitați-vă prietenii la Ente",
@@ -1152,6 +1237,21 @@
"changeLocationOfSelectedItems": "Schimbați locația articolelor selectate?",
"editsToLocationWillOnlyBeSeenWithinEnte": "Editările locației vor fi vizibile doar pe Ente",
"cleanUncategorized": "Curățare Necategorisite",
"cleanUncategorizedDescription": "Eliminați toate fișierele din „Fără categorie” care sunt prezente în alte albume",
"waitingForVerification": "Se așteaptă verificarea...",
"passkey": "Cheie de acces",
"passkeyAuthTitle": "Verificare cheie de acces",
"loginWithTOTP": "Autentificare cu parolă unică (TOTP)",
"passKeyPendingVerification": "Verificarea este încă în așteptare",
"loginSessionExpired": "Sesiune expirată",
"loginSessionExpiredDetails": "Sesiunea a expirat. Vă rugăm să vă autentificați din nou.",
"verifyPasskey": "Verificați cheia de acces",
"playOnTv": "Redare album pe TV",
"pair": "Asociere",
"deviceNotFound": "Dispozitivul nu a fost găsit",
"castInstruction": "Accesați cast.ente.io de pe dispozitivul pe care doriți să îl asociați.\n\nIntroduceți codul de mai jos pentru a reda albumul pe TV.",
"deviceCodeHint": "Introduceți codul",
"joinDiscord": "Alăturați-vă pe Discord",
"locations": "Locații",
"addAName": "Adăugați un nume",
"findThemQuickly": "Găsiți rapid",
@@ -1225,5 +1325,269 @@
"panorama": "Panoramă",
"reenterPassword": "Reintroduceți parola",
"reenterPin": "Reintroduceți codul PIN",
"deviceLock": "Blocare dispozitiv"
"deviceLock": "Blocare dispozitiv",
"pinLock": "Blocare PIN",
"next": "Înainte",
"setNewPassword": "Setați parola noua",
"enterPin": "Introduceţi codul PIN",
"setNewPin": "Setați un cod nou PIN",
"appLock": "Blocare aplicație",
"noSystemLockFound": "Nu s-a găsit nicio blocare de sistem",
"tapToUnlock": "Atingeți pentru a debloca",
"tooManyIncorrectAttempts": "Prea multe încercări incorecte",
"videoInfo": "Informaţii video",
"autoLock": "Blocare automată",
"immediately": "Imediat",
"autoLockFeatureDescription": "Timpul după care aplicația se blochează după ce a fost pusă în fundal",
"hideContent": "Ascundeți conținutul",
"hideContentDescriptionAndroid": "Ascunde conținutul aplicației în comutatorul de aplicații și dezactivează capturile de ecran",
"hideContentDescriptionIos": "Ascunde conținutul aplicației în comutatorul de aplicații",
"passwordStrengthInfo": "Puterea parolei este calculată luând în considerare lungimea parolei, caracterele utilizate și dacă parola apare sau nu în top 10.000 cele mai utilizate parole",
"noQuickLinksSelected": "Nu au fost găsite linkuri rapide",
"pleaseSelectQuickLinksToRemove": "Vă rugăm să selectați linkurile rapide de eliminat",
"removePublicLinks": "Eliminați linkurile publice",
"thisWillRemovePublicLinksOfAllSelectedQuickLinks": "Se vor elimina linkurile publice ale linkurilor rapide selectate.",
"guestView": "Mod oaspete",
"guestViewEnablePreSteps": "Pentru a activa modul oaspete, vă rugăm să configurați codul de acces al dispozitivului sau blocarea ecranului în setările sistemului.",
"nameTheAlbum": "Denumiți albumul",
"collectPhotosDescription": "Creați un link unde prietenii dvs. pot încărca fotografii la calitatea originală.",
"collect": "Colectare",
"appLockDescriptions": "Alegeți între ecranul de blocare implicit al dispozitivului dvs. și un ecran de blocare personalizat cu PIN sau parolă.",
"toEnableAppLockPleaseSetupDevicePasscodeOrScreen": "Pentru a activa blocarea aplicației, vă rugăm să configurați codul de acces al dispozitivului sau blocarea ecranului în setările sistemului.",
"authToViewPasskey": "Vă rugăm să vă autentificați pentru a vizualiza cheia de acces",
"loopVideoOn": "Repetare video activată",
"loopVideoOff": "Repetare video dezactivată",
"localSyncErrorMessage": "Se pare că ceva nu a mers bine, deoarece sincronizarea fotografiilor locale durează mai mult decât ne așteptam. Vă rugăm să contactați echipa noastră de asistență",
"showPerson": "Afișare persoană",
"sort": "Sortare",
"mostRecent": "Cele mai recente",
"mostRelevant": "Cele mai relevante",
"loadingYourPhotos": "Se încarcă fotografiile dvs...",
"processingImport": "Se procesează {folderName}...",
"personName": "Numele persoanei",
"addNewPerson": "Adăugare persoană nouă",
"addNameOrMerge": "Adăugare nume sau îmbinare",
"mergeWithExisting": "Îmbinare cu unul existent",
"newPerson": "Persoană nouă",
"addName": "Adăugare nume",
"add": "Adăugare",
"extraPhotosFoundFor": "S-au găsit fotografii extra pentru {text}",
"@extraPhotosFoundFor": {
"placeholders": {
"text": {
"type": "String"
}
}
},
"extraPhotosFound": "S-au găsit fotografii extra",
"configuration": "Configurare",
"localIndexing": "Indexare locală",
"processed": "Procesate",
"resetPerson": "Eliminare",
"areYouSureYouWantToResetThisPerson": "Sunteți sigur că doriți să resetaţi această persoană?",
"allPersonGroupingWillReset": "Toate grupările pentru această persoană vor fi resetate și veți pierde toate sugestiile făcute pentru această persoană",
"yesResetPerson": "Da, resetează persoana",
"onlyThem": "Numai el/ea",
"checkingModels": "Se verifică modelele...",
"enableMachineLearningBanner": "Activați învățarea automată pentru a folosi căutarea magică și recunoașterea facială",
"searchDiscoverEmptySection": "Imaginile vor fi afișate aici odată ce procesarea și sincronizarea este completă",
"searchPersonsEmptySection": "Persoanele vor fi afișate aici odată ce procesarea și sincronizarea este completă",
"viewersSuccessfullyAdded": "{count, plural, one {} few {S-au adăugat {count} observatori}=0 {S-au adăugat 0 observatori} =1 {S-a adăugat 1 observator} other {S-au adăugat {count} de observatori}}",
"@viewersSuccessfullyAdded": {
"placeholders": {
"count": {
"type": "int",
"example": "2"
}
},
"description": "Number of viewers that were successfully added to an album."
},
"collaboratorsSuccessfullyAdded": "{count, plural, one {} few {S-au adăugat {count} colaboratori}=0 {S-au adăugat 0 colaboratori} =1 {S-a adăugat 1 colaborator} other {S-au adăugat {count} de colaboratori}}",
"@collaboratorsSuccessfullyAdded": {
"placeholders": {
"count": {
"type": "int",
"example": "2"
}
},
"description": "Number of collaborators that were successfully added to an album."
},
"accountIsAlreadyConfigured": "Contul este deja configurat.",
"sessionIdMismatch": "Nepotrivire ID sesiune",
"@sessionIdMismatch": {
"description": "In passkey page, deeplink is ignored because of session ID mismatch."
},
"failedToFetchActiveSessions": "Nu s-a reușit preluarea sesiunilor active",
"@failedToFetchActiveSessions": {
"description": "In session page, warn user (in toast) that active sessions could not be fetched."
},
"failedToRefreshStripeSubscription": "Nu s-a reușit reîmprospătarea abonamentului",
"failedToPlayVideo": "Eroare la redarea videoclipului",
"uploadIsIgnoredDueToIgnorereason": "Încărcare ignorată din motivul {ignoreReason}",
"@uploadIsIgnoredDueToIgnorereason": {
"placeholders": {
"ignoreReason": {
"type": "String",
"example": "no network"
}
}
},
"typeOfGallerGallerytypeIsNotSupportedForRename": "Tipul de galerie {galleryType} nu este acceptat pentru redenumire",
"@typeOfGallerGallerytypeIsNotSupportedForRename": {
"placeholders": {
"galleryType": {
"type": "String",
"example": "no network"
}
}
},
"tapToUploadIsIgnoredDue": "Atingeți pentru a încărca, încărcarea este ignorată în prezent datorită {ignoreReason}",
"@tapToUploadIsIgnoredDue": {
"description": "Shown in upload icon widet, inside a tooltip.",
"placeholders": {
"ignoreReason": {
"type": "String",
"example": "no network"
}
}
},
"tapToUpload": "Atingeți pentru a încărca",
"@tapToUpload": {
"description": "Shown in upload icon widet, inside a tooltip."
},
"info": "Informații",
"addFiles": "Adăugați fișiere",
"castAlbum": "Difuzați albumul",
"imageNotAnalyzed": "Imaginea nu a fost analizată",
"noFacesFound": "Nu au fost găsite fețe",
"fileNotUploadedYet": "Fișierul nu a fost încărcat încă",
"noSuggestionsForPerson": "Nicio sugestie pentru {personName}",
"@noSuggestionsForPerson": {
"placeholders": {
"personName": {
"type": "String",
"example": "Alice"
}
}
},
"month": "lună",
"yearShort": "an",
"@yearShort": {
"description": "Appears in pricing page (/yr)"
},
"currentlyRunning": "rulează în prezent",
"ignored": "ignorat",
"photosCount": "{count, plural, one {} few {{count} fotografii}=0 {0 fotografii} =1 {1 fotografie} other {{count} de fotografii}}",
"@photosCount": {
"placeholders": {
"count": {
"type": "int",
"example": "2"
}
}
},
"file": "Fișier",
"searchSectionsLengthMismatch": "Lungimea secțiunilor nu se potrivesc: {snapshotLength} != {searchLength}",
"@searchSectionsLengthMismatch": {
"description": "Appears in search tab page",
"placeholders": {
"snapshotLength": {
"type": "int",
"example": "1"
},
"searchLength": {
"type": "int",
"example": "2"
}
}
},
"selectMailApp": "Selectați aplicația de e-mail",
"selectAllShort": "Toate",
"@selectAllShort": {
"description": "Text that appears in bottom right when you start to select multiple photos. When clicked, it selects all photos."
},
"changeLogMagicSearchImprovementTitle": "Îmbunătățire a căutării magice",
"changeLogMagicSearchImprovementContent": "Am îmbunătățit căutarea magică pentru a deveni mult mai rapidă, astfel încât să nu trebuiască să așteptați pentru a găsi ceea ce căutați.",
"changeLogBackupStatusTitle": "Starea copiei de rezervă",
"changeLogBackupStatusContent": "Am adăugat un jurnal al tuturor fișierelor care au fost încărcate pe Ente, inclusiv eșecurile și coada de așteptare.",
"changeLogDiscoverTitle": "Descoperire",
"changeLogDiscoverContent": "Căutați fotografii ale cărților de identitate, notițe sau chiar meme-uri? Mergeți la fila de căutare și dați o privire la Descoperire. Bazat pe căutarea noastră semantică, este un loc în care puteți găsi fotografii care ar putea fi importante pentru dvs.\\n\\nEste disponibilă numai dacă ați activat învățarea automată.",
"selectCoverPhoto": "Selectați fotografia de copertă",
"newLocation": "Locație nouă",
"faceNotClusteredYet": "Fața nu este încă grupată, vă rugăm să reveniți mai târziu",
"theLinkYouAreTryingToAccessHasExpired": "Linkul pe care încercați să îl accesați a expirat.",
"openFile": "Deschidere fișier",
"backupFile": "Salvare fișier",
"openAlbumInBrowser": "Deschideți albumul în browser",
"openAlbumInBrowserTitle": "Vă rugăm să utilizați aplicația web pentru a adăuga fotografii la acest album",
"allow": "Permiteți",
"allowAppToOpenSharedAlbumLinks": "Permiteți aplicației să deschidă link-uri de album partajate",
"seePublicAlbumLinksInApp": "Vedeți linkurile albumelor publice în aplicație",
"emergencyContacts": "Contacte de urgență",
"acceptTrustInvite": "Acceptați invitația",
"declineTrustInvite": "Refuzați invitația",
"removeYourselfAsTrustedContact": "Eliminați-vă ca persoană de contact de încredere",
"legacy": "Moștenire",
"legacyPageDesc": "Moștenirea permite contactelor de încredere să vă acceseze contul în absența dvs.",
"legacyPageDesc2": "Persoanele de contact de încredere pot iniția recuperarea contului și, dacă nu este blocată în termen de 30 de zile, vă pot reseta parola și accesa contul.",
"legacyAccounts": "Conturi de moștenire",
"trustedContacts": "Contacte de încredere",
"addTrustedContact": "Adăugare contact de încredere",
"removeInvite": "Eliminare invitație",
"recoveryWarning": "Un contact de încredere încearcă să vă acceseze contul",
"rejectRecovery": "Respingeți recuperarea",
"recoveryInitiated": "Recuperare inițiată",
"recoveryInitiatedDesc": "Puteți accesa contul după {days} zile. O notificare va fi trimisă la {email}.",
"@recoveryInitiatedDesc": {
"placeholders": {
"days": {
"type": "int",
"example": "30"
},
"email": {
"type": "String",
"example": "me@example.com"
}
}
},
"cancelAccountRecovery": "Anulare recuperare",
"recoveryAccount": "Recuperare cont",
"cancelAccountRecoveryBody": "Sunteți sigur că doriți să anulați recuperarea?",
"startAccountRecoveryTitle": "Începeți recuperarea",
"whyAddTrustContact": "Contactul de încredere vă poate ajuta la recuperarea datelor.",
"recoveryReady": "Acum puteți recupera contul {email} setând o nouă parolă.",
"@recoveryReady": {
"placeholders": {
"email": {
"type": "String",
"example": "me@example.com"
}
}
},
"recoveryWarningBody": "{email} încearcă să vă recupereze contul.",
"trustedInviteBody": "Ați fost învitat să fiți un contact de moștenire de către {email}.",
"warning": "Atenție",
"proceed": "Continuați",
"confirmAddingTrustedContact": "Sunteți pe cale să adăugați {email} ca persoană de contact de încredere. Acesta va putea să vă recupereze contul dacă lipsiți timp de {numOfDays} de zile.",
"@confirmAddingTrustedContact": {
"placeholders": {
"email": {
"type": "String",
"example": "me@example.com"
},
"numOfDays": {
"type": "int",
"example": "30"
}
}
},
"legacyInvite": "{email} v-a invitat să fiți un contact de încredere",
"authToManageLegacy": "Vă rugăm să vă autentificați pentru a gestiona contactele de încredere",
"useDifferentPlayerInfo": "Aveți probleme cu redarea acestui videoclip? Apăsați lung aici pentru a încerca un alt player.",
"hideSharedItemsFromHomeGallery": "Ascundeți elementele distribuite din galeria principală",
"gallery": "Galerie",
"joinAlbum": "Alăturați-vă albumului",
"joinAlbumSubtext": "pentru a vedea și a adăuga fotografii",
"joinAlbumSubtextViewer": "pentru a adăuga la albumele distribuite",
"join": "Alăturare"
}

View File

@@ -7,7 +7,5 @@ String twoFactorTypeToString(TwoFactorType type) {
return "totp";
case TwoFactorType.passkey:
return "passkey";
default:
return type.name;
}
}

View File

@@ -93,8 +93,6 @@ enum SideDataType {
switch (this) {
case SideDataType.displayMatrix:
return 'Display Matrix';
default:
assert(false, 'Unknown side data type: $this');
}
}
}

View File

@@ -2,12 +2,10 @@
import "dart:developer";
import "package:collection/collection.dart";
import "package:intl/intl.dart";
import "package:photos/models/ffmpeg/channel_layouts.dart";
import "package:photos/models/ffmpeg/codecs.dart";
import "package:photos/models/ffmpeg/ffprobe_keys.dart";
import "package:photos/models/ffmpeg/language.dart";
import "package:photos/models/ffmpeg/mp4.dart";
import "package:photos/models/location/location.dart";
@@ -344,12 +342,6 @@ class FFProbeProps {
return value;
}
static String _formatLanguage(String value) {
final language = Language.living639_2
.firstWhereOrNull((language) => language.iso639_2 == value);
return language?.native ?? value;
}
static final _durationHmsmPattern = RegExp(r'(\d+):(\d+):(\d+)(.\d+)');
static final _durationSmPattern = RegExp(r'(\d+)(.\d+)');
static final _locationPattern = RegExp(r'([+-][.0-9]+)');

View File

@@ -128,12 +128,14 @@ class PersonData {
// fromJson
factory PersonData.fromJson(Map<String, dynamic> json) {
final assigned = (json['assigned'] == null || json['assigned'].length == 0 || json['assigned'] != Iterable)
final assigned = (json['assigned'] == null ||
json['assigned'].length == 0 ||
json['assigned'] is! Iterable)
? <ClusterInfo>[]
: List<ClusterInfo>.from(
json['assigned']
.where((x) => x is Map<String, dynamic>)
.map((x) => ClusterInfo.fromJson(x as Map<String, dynamic>)),
.where((x) => x is Map<String, dynamic>)
.map((x) => ClusterInfo.fromJson(x as Map<String, dynamic>)),
);
final List<String> rejectedFaceIDs =

View File

@@ -13,6 +13,7 @@ import "package:photos/models/collection/collection.dart";
import "package:photos/models/collection/collection_items.dart";
import "package:photos/models/search/search_result.dart";
import "package:photos/models/typedefs.dart";
import "package:photos/service_locator.dart";
import "package:photos/services/collections_service.dart";
import "package:photos/services/search_service.dart";
import "package:photos/ui/viewer/gallery/collection_page.dart";
@@ -240,6 +241,9 @@ extension SectionTypeExtensions on SectionType {
return SearchService.instance.getMagicSectionResults(context);
case SectionType.moment:
if (flagService.internalUser) {
return SearchService.instance.onThisDayOrWeekResults(context, limit);
}
return SearchService.instance.getRandomMomentsSearchResults(context);
case SectionType.location:

View File

@@ -267,7 +267,9 @@ Map<LocationTag, int> _getLocationTagsToOccurenceForIsolate(
for (EnteFile file in files) {
if (file.uploadedFileID == null ||
file.uploadedFileID == -1 ||
!file.hasLocation) continue;
!file.hasLocation) {
continue;
}
for (LocalEntity<LocationTag> locationTagEntity in locationTagEntities) {
final locationTag = locationTagEntity.item;
final fileCoordinates = file.location!;

View File

@@ -3,7 +3,6 @@ import "dart:developer";
import "dart:typed_data" show Uint8List;
import "package:computer/computer.dart";
import "package:flutter/foundation.dart" show kDebugMode;
import "package:logging/logging.dart";
import "package:ml_linalg/dtype.dart";
import "package:ml_linalg/vector.dart";
@@ -400,7 +399,8 @@ ClusteringResult runLinearClustering(Map args) {
} else {
thresholdValue = distanceThreshold;
}
final bool faceHasBeenRejectedBefore = sortedFaceInfos[i].rejectedClusterIds != null;
final bool faceHasBeenRejectedBefore =
sortedFaceInfos[i].rejectedClusterIds != null;
if (i % 250 == 0) {
_logger.info("Processed ${offset != null ? i + offset : i} faces");
}
@@ -416,8 +416,8 @@ ClusteringResult runLinearClustering(Map args) {
if (faceHasBeenRejectedBefore &&
sortedFaceInfos[j].clusterId != null &&
sortedFaceInfos[i].rejectedClusterIds!.contains(
sortedFaceInfos[j].clusterId!,
)) {
sortedFaceInfos[j].clusterId!,
)) {
continue;
}
closestDistance = distance;
@@ -736,62 +736,3 @@ Map<String, (Uint8List, int)> _updateClusterSummaries({
return newClusterSummaries;
}
void _analyzeClusterResults(List<FaceInfo> sortedFaceInfos) {
if (!kDebugMode) return;
final stopwatch = Stopwatch()..start();
final Map<String, String> faceIdToCluster = {};
for (final faceInfo in sortedFaceInfos) {
faceIdToCluster[faceInfo.faceID] = faceInfo.clusterId!;
}
// Find faceIDs that are part of a cluster which is larger than 5 and are new faceIDs
final Map<String, int> clusterIdToSize = {};
faceIdToCluster.forEach((key, value) {
if (clusterIdToSize.containsKey(value)) {
clusterIdToSize[value] = clusterIdToSize[value]! + 1;
} else {
clusterIdToSize[value] = 1;
}
});
// print top 10 cluster ids and their sizes based on the internal cluster id
final clusterIds = faceIdToCluster.values.toSet();
final clusterSizes = clusterIds.map((clusterId) {
return faceIdToCluster.values.where((id) => id == clusterId).length;
}).toList();
clusterSizes.sort();
// find clusters whose size is greater than 1
int oneClusterCount = 0;
int moreThan5Count = 0;
int moreThan10Count = 0;
int moreThan20Count = 0;
int moreThan50Count = 0;
int moreThan100Count = 0;
for (int i = 0; i < clusterSizes.length; i++) {
if (clusterSizes[i] > 100) {
moreThan100Count++;
} else if (clusterSizes[i] > 50) {
moreThan50Count++;
} else if (clusterSizes[i] > 20) {
moreThan20Count++;
} else if (clusterSizes[i] > 10) {
moreThan10Count++;
} else if (clusterSizes[i] > 5) {
moreThan5Count++;
} else if (clusterSizes[i] == 1) {
oneClusterCount++;
}
}
// print the metrics
log(
"[ClusterIsolate] Total clusters ${clusterIds.length}: \n oneClusterCount $oneClusterCount \n moreThan5Count $moreThan5Count \n moreThan10Count $moreThan10Count \n moreThan20Count $moreThan20Count \n moreThan50Count $moreThan50Count \n moreThan100Count $moreThan100Count",
);
stopwatch.stop();
log(
"[ClusterIsolate] Clustering additional analysis took ${stopwatch.elapsedMilliseconds} ms",
);
}

View File

@@ -13,8 +13,6 @@ extension FaceDirectionExtension on FaceDirection {
return 'Right';
case FaceDirection.straight:
return 'Straight';
default:
throw Exception('Unknown FaceDirection');
}
}
}

View File

@@ -9,8 +9,6 @@ import "package:photos/core/event_bus.dart";
import "package:photos/events/machine_learning_control_event.dart";
class MachineLearningController {
MachineLearningController._privateConstructor();
final _logger = Logger("MachineLearningController");
static const kMaximumTemperature = 42; // 42 degree celsius

View File

@@ -43,10 +43,10 @@ class MLService {
bool get isInitialized => _isInitialized;
bool get showClusteringIsHappening => _showClusteringIsHappening;
bool get showClusteringIsHappening => _clusteringIsHappening;
bool debugIndexingDisabled = false;
bool _showClusteringIsHappening = false;
bool _clusteringIsHappening = false;
bool _mlControllerStatus = false;
bool _isIndexingOrClusteringRunning = false;
bool _isRunningML = false;
@@ -58,7 +58,9 @@ class MLService {
Future<void> init() async {
if (_isInitialized) return;
if (!userRemoteFlagService
.getCachedBoolValue(UserRemoteFlagService.mlEnabled)) return;
.getCachedBoolValue(UserRemoteFlagService.mlEnabled)) {
return;
}
_logger.info("init called");
// Check if the device has enough RAM to run local indexing
@@ -72,7 +74,9 @@ class MLService {
// Listen on MachineLearningController
Bus.instance.on<MachineLearningControlEvent>().listen((event) {
if (!userRemoteFlagService
.getCachedBoolValue(UserRemoteFlagService.mlEnabled)) return;
.getCachedBoolValue(UserRemoteFlagService.mlEnabled)) {
return;
}
_mlControllerStatus = event.shouldRun;
if (_mlControllerStatus) {
@@ -123,7 +127,7 @@ class MLService {
if (force) {
_mlControllerStatus = true;
}
if (_cannotRunMLFunction() && !force) return;
if (!_canRunMLFunction(function: "AllML") && !force) return;
_isRunningML = true;
await sync();
@@ -182,7 +186,7 @@ class MLService {
/// This function first fetches from remote and checks if the image has already been analyzed
/// with the lastest faceMlVersion and stored on remote or local database. If so, it skips the image.
Future<void> fetchAndIndexAllImages() async {
if (_cannotRunMLFunction()) return;
if (!_canRunMLFunction(function: "Indexing")) return;
try {
_isIndexingOrClusteringRunning = true;
@@ -237,11 +241,19 @@ class MLService {
}
}
Future<void> clusterAllImages({bool clusterInBuckets = true}) async {
if (_cannotRunMLFunction()) return;
Future<void> clusterAllImages({
bool clusterInBuckets = true,
bool force = false,
}) async {
if (!_canRunMLFunction(function: "Clustering") && !force) return;
if (_clusteringIsHappening) {
_logger.info("clusterAllImages() is already running, returning");
return;
}
_logger.info("`clusterAllImages()` called");
_isIndexingOrClusteringRunning = true;
_clusteringIsHappening = true;
final clusterAllImagesTime = DateTime.now();
_logger.info('Pulling remote feedback before actually clustering');
@@ -261,11 +273,8 @@ class MLService {
}
try {
_showClusteringIsHappening = true;
// Get a sense of the total number of faces in the database
final int totalFaces =
await MLDataDB.instance.getTotalFaceCount();
final int totalFaces = await MLDataDB.instance.getTotalFaceCount();
final fileIDToCreationTime =
await FilesDB.instance.getFileIDToCreationTime();
final startEmbeddingFetch = DateTime.now();
@@ -414,7 +423,7 @@ class MLService {
} catch (e, s) {
_logger.severe("`clusterAllImages` failed", e, s);
} finally {
_showClusteringIsHappening = false;
_clusteringIsHappening = false;
_isIndexingOrClusteringRunning = false;
_cancelPauseIndexingAndClustering();
}
@@ -532,30 +541,30 @@ class MLService {
}
}
bool _cannotRunMLFunction({String function = ""}) {
bool _canRunMLFunction({required String function}) {
if (kDebugMode && Platform.isIOS && !_isIndexingOrClusteringRunning) {
return false;
return true;
}
if (_isIndexingOrClusteringRunning) {
_logger.info(
"Cannot run $function because indexing or clustering is already running",
);
_logStatus();
return true;
return false;
}
if (_mlControllerStatus == false) {
_logger.info(
"Cannot run $function because MLController does not allow it",
);
_logStatus();
return true;
return false;
}
if (debugIndexingDisabled) {
_logger.info(
"Cannot run $function because debugIndexingDisabled is true",
);
_logStatus();
return true;
return false;
}
if (_shouldPauseIndexingAndClustering) {
// This should ideally not be triggered, because one of the above should be triggered instead.
@@ -563,9 +572,9 @@ class MLService {
"Cannot run $function because indexing and clustering is being paused",
);
_logStatus();
return true;
return false;
}
return false;
return true;
}
void _logStatus() {

View File

@@ -908,7 +908,9 @@ class SearchService {
// This should not be possible since it should be handled in the above loop, logging just in case
_logger.severe(
"`getAllFace`: Something unexpected happened, Cluster $clusterId should not have person id $personID",
Exception('Some unexpected error occurred in getAllFace wrt cluster to person mapping'),
Exception(
'Some unexpected error occurred in getAllFace wrt cluster to person mapping',
),
);
} else {
// This should not happen, means a clusterID is still assigned to a personID of a person that no longer exists
@@ -1183,6 +1185,103 @@ class SearchService {
return searchResults;
}
Future<List<GenericSearchResult>> onThisDayOrWeekResults(
BuildContext context,
int? limit,
) async {
final List<GenericSearchResult> searchResults = [];
final allFiles = await getAllFilesForSearch();
if (allFiles.isEmpty) return [];
final currentTime = DateTime.now().toLocal();
final currentDayMonth = currentTime.month * 100 + currentTime.day;
final cutOffTime = currentTime.subtract(const Duration(days: 365));
final averageDailyPhotos = allFiles.length / 365;
final significanceThreshold = averageDailyPhotos * 0.25;
// Group files by day-month and year
final dayMonthYearGroups = <int, Map<int, List<EnteFile>>>{};
for (final file in allFiles) {
if (file.creationTime! > cutOffTime.microsecondsSinceEpoch) continue;
final creationTime =
DateTime.fromMicrosecondsSinceEpoch(file.creationTime!);
final dayMonth = creationTime.month * 100 + creationTime.day;
final year = creationTime.year;
dayMonthYearGroups
.putIfAbsent(dayMonth, () => {})
.putIfAbsent(year, () => [])
.add(file);
}
// Process each day-month
for (final dayMonth in dayMonthYearGroups.keys) {
final dayDiff = dayMonth - currentDayMonth;
if (dayDiff < 0 || dayDiff > 2) continue;
final yearGroups = dayMonthYearGroups[dayMonth]!;
final significantYears = yearGroups.entries
.where((e) => e.value.length > significanceThreshold)
.map((e) => e.key)
.toList();
if (significantYears.length >= 3) {
// Combine all years for this day-month
final date =
DateTime(currentTime.year, dayMonth ~/ 100, dayMonth % 100);
final allPhotos = yearGroups.values.expand((x) => x).toList();
searchResults.add(
GenericSearchResult(
ResultType.event,
'Memories of ${DateFormat('MMMM d').format(date)}',
allPhotos,
hierarchicalSearchFilter: TopLevelGenericFilter(
filterName: DateFormat('MMMM d').format(date),
occurrence: kMostRelevantFilter,
filterResultType: ResultType.event,
matchedUploadedIDs: filesToUploadedFileIDs(allPhotos),
filterIcon: Icons.event_outlined,
),
),
);
} else {
// Individual entries for significant years
for (final year in significantYears) {
final date = DateTime(year, dayMonth ~/ 100, dayMonth % 100);
final files = yearGroups[year]!;
String name =
DateFormat.yMMMd(Localizations.localeOf(context).languageCode)
.format(date);
if (date.day == currentTime.day && date.month == currentTime.month) {
name = 'This day, ${currentTime.year - date.year} years back';
}
searchResults.add(
GenericSearchResult(
ResultType.event,
name,
files,
hierarchicalSearchFilter: TopLevelGenericFilter(
filterName: name,
occurrence: kMostRelevantFilter,
filterResultType: ResultType.event,
matchedUploadedIDs: filesToUploadedFileIDs(files),
filterIcon: Icons.event_outlined,
),
),
);
}
}
if (limit != null && searchResults.length >= limit) break;
}
return searchResults;
}
Future<GenericSearchResult?> getRandomDateResults(
BuildContext context,
) async {

View File

@@ -718,7 +718,7 @@ class UserService {
_config.getHttpEndpoint() + "/users/srp/create-session",
data: {
"srpUserID": srpAttributes.srpUserID,
"srpA": base64Encode(SRP6Util.encodeBigInt(A!)),
"srpA": base64Encode(SRP6Util.getPadded(A!, 512)),
},
);
final String sessionID = createSessionResponse.data["sessionID"];
@@ -733,7 +733,7 @@ class UserService {
data: {
"sessionID": sessionID,
"srpUserID": srpAttributes.srpUserID,
"srpM1": base64Encode(SRP6Util.encodeBigInt(clientM!)),
"srpM1": base64Encode(SRP6Util.getPadded(clientM!, 32)),
},
);
if (response.statusCode == 200) {

View File

@@ -213,7 +213,9 @@ class _MenuItemWidgetState extends State<MenuItemWidget> {
Future<void> _onTap() async {
if (executionStateNotifier.value == ExecutionState.inProgress ||
executionStateNotifier.value == ExecutionState.successful) return;
executionStateNotifier.value == ExecutionState.successful) {
return;
}
_debouncer.run(
() => Future(
() {
@@ -250,7 +252,9 @@ class _MenuItemWidgetState extends State<MenuItemWidget> {
void _onTapDown(details) {
if (executionStateNotifier.value == ExecutionState.inProgress ||
executionStateNotifier.value == ExecutionState.successful) return;
executionStateNotifier.value == ExecutionState.successful) {
return;
}
setState(() {
if (widget.pressedColor == null) {
hasPassedGestureCallbacks()
@@ -270,7 +274,9 @@ class _MenuItemWidgetState extends State<MenuItemWidget> {
void _onTapUp(details) {
if (executionStateNotifier.value == ExecutionState.inProgress ||
executionStateNotifier.value == ExecutionState.successful) return;
executionStateNotifier.value == ExecutionState.successful) {
return;
}
Future.delayed(
const Duration(milliseconds: 100),
() => setState(() {
@@ -281,7 +287,9 @@ class _MenuItemWidgetState extends State<MenuItemWidget> {
void _onCancel() {
if (executionStateNotifier.value == ExecutionState.inProgress ||
executionStateNotifier.value == ExecutionState.successful) return;
executionStateNotifier.value == ExecutionState.successful) {
return;
}
setState(() {
menuItemColor = widget.menuItemColor;
});

View File

@@ -346,7 +346,6 @@ class _PageViewState extends State<ExtentsPageView> {
break;
case Axis.horizontal:
default:
cacheExtent = constraints.maxWidth * widget.extents;
break;
}

View File

@@ -123,8 +123,6 @@ class _DeduplicatePageState extends State<DeduplicatePage> {
return bSize - aSize;
case SortKey.count:
return second.files.length - first.files.length;
default:
throw Exception("Unexpected sort key $sortKey");
}
});
}

View File

@@ -25,8 +25,6 @@ enum CropValue {
return Fraction.fromString("3/4");
case CropValue.ratio_4_3:
return Fraction.fromString("4/3");
default:
return null;
}
}

View File

@@ -1,7 +1,6 @@
import "dart:async";
import "dart:io";
import "package:flutter/cupertino.dart";
import "package:flutter/material.dart";
import "package:logging/logging.dart";
import "package:media_kit/media_kit.dart";
@@ -17,7 +16,6 @@ import "package:photos/services/files_service.dart";
import "package:photos/theme/colors.dart";
import "package:photos/theme/ente_theme.dart";
import "package:photos/ui/actions/file/file_actions.dart";
import "package:photos/ui/viewer/file/thumbnail_widget.dart";
import "package:photos/utils/debouncer.dart";
import "package:photos/utils/dialog_util.dart";
import "package:photos/utils/file_util.dart";
@@ -226,17 +224,6 @@ class _VideoWidgetMediaKitNewState extends State<VideoWidgetMediaKitNew>
});
}
}
Widget _getThumbnail() {
return Container(
color: Colors.black,
constraints: const BoxConstraints.expand(),
child: ThumbnailWidget(
widget.file,
fit: BoxFit.contain,
),
);
}
}
class _VideoWidget extends StatefulWidget {

View File

@@ -1,3 +1,4 @@
import "dart:async";
import "dart:developer" show log;
import "dart:typed_data";
@@ -13,6 +14,7 @@ import "package:photos/models/ml/face/person.dart";
import "package:photos/services/machine_learning/face_ml/face_detection/detection.dart";
import "package:photos/services/machine_learning/face_ml/face_filtering/face_filtering_constants.dart";
import "package:photos/services/machine_learning/face_ml/feedback/cluster_feedback.dart";
import "package:photos/services/machine_learning/ml_service.dart";
import "package:photos/services/search_service.dart";
import "package:photos/theme/ente_theme.dart";
import "package:photos/ui/viewer/file/no_thumbnail_widget.dart";
@@ -121,6 +123,7 @@ class _FaceWidgetState extends State<FaceWidget> {
context,
S.of(context).faceNotClusteredYet,
);
unawaited(MLService.instance.clusterAllImages(force: true));
return;
}
if (widget.person != null) {

View File

@@ -38,16 +38,9 @@ class _FacesItemWidgetState extends State<FacesItemWidget> {
subtitleSection: _faceWidgets(context, widget.file, editMode),
hasChipButtons: true,
biggerSpinner: true,
// editOnTap: _toggleEditMode, // TODO: re-enable at later time when the UI is less ugly
);
}
void _toggleEditMode() {
setState(() {
editMode = !editMode;
});
}
Future<List<Widget>> _faceWidgets(
BuildContext context,
EnteFile file,

View File

@@ -1,13 +1,17 @@
import 'dart:async';
import "dart:developer";
import "dart:developer" as dev;
import "dart:math" show max;
import "package:flutter/foundation.dart";
import "package:flutter/material.dart";
import "package:logging/logging.dart";
import "package:ml_linalg/linalg.dart" as ml;
import "package:photos/core/event_bus.dart";
import "package:photos/db/ml/db.dart";
import "package:photos/ente_theme_data.dart";
import "package:photos/events/people_changed_event.dart";
import "package:photos/generated/l10n.dart";
import "package:photos/generated/protos/ente/common/vector.pb.dart";
import "package:photos/l10n/l10n.dart";
import "package:photos/models/file/file.dart";
import "package:photos/models/ml/face/person.dart";
@@ -57,6 +61,7 @@ class _SaveOrEditPersonState extends State<SaveOrEditPerson> {
late final Logger _logger = Logger("_SavePersonState");
Timer? _debounce;
List<(PersonEntity, EnteFile)> _cachedPersons = [];
Map<String, double> _personToMaxSimilarity = {};
PersonEntity? person;
@override
@@ -309,7 +314,7 @@ class _SaveOrEditPersonState extends State<SaveOrEditPerson> {
stream: _getPersonsWithRecentFileStream(),
builder: (context, snapshot) {
if (snapshot.hasError) {
log("Error: ${snapshot.error} ${snapshot.stackTrace}}");
dev.log("Error: ${snapshot.error} ${snapshot.stackTrace}}");
if (kDebugMode) {
return Column(
mainAxisSize: MainAxisSize.min,
@@ -338,6 +343,7 @@ class _SaveOrEditPersonState extends State<SaveOrEditPerson> {
if (searchResults.isEmpty) {
return const SizedBox.shrink();
}
final finalResults = _sortByCosine(searchResults);
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
@@ -360,9 +366,9 @@ class _SaveOrEditPersonState extends State<SaveOrEditPerson> {
child: ListView.separated(
scrollDirection: Axis.horizontal,
padding: const EdgeInsets.only(right: 8),
itemCount: searchResults.length,
itemCount: finalResults.length,
itemBuilder: (context, index) {
final person = searchResults[index];
final person = finalResults[index];
return PersonGridItem(
key: ValueKey(person.$1.remoteID),
person: person.$1,
@@ -403,9 +409,78 @@ class _SaveOrEditPersonState extends State<SaveOrEditPerson> {
if (_cachedPersons.isEmpty) {
_cachedPersons = await _getPersonsWithRecentFile();
}
if (widget.clusterID != null) {
if (_personToMaxSimilarity.isEmpty) {
_personToMaxSimilarity = await _calculateSimilarityWithPersons();
}
}
yield _cachedPersons;
}
Future<Map<String, double>> _calculateSimilarityWithPersons() async {
// Get all cluster summaries from DB
final allClusterSummary = await MLDataDB.instance.getAllClusterSummary();
// Get current cluster embedding
final currentClusterEmbeddingData =
allClusterSummary[widget.clusterID!]?.$1;
if (currentClusterEmbeddingData == null) return {};
final ml.Vector currentClusterEmbedding = ml.Vector.fromList(
EVector.fromBuffer(currentClusterEmbeddingData).values,
dtype: ml.DType.float32,
);
// Get all cluster embeddings
final persons = _cachedPersons.map((e) => e.$1).toList();
final clusterToPerson = <String, String>{};
for (final person in persons) {
if (person.data.assigned != null) {
for (final cluster in person.data.assigned!) {
clusterToPerson[cluster.id] = person.remoteID;
}
}
}
allClusterSummary
.removeWhere((key, value) => !clusterToPerson.containsKey(key));
final Map<String, ml.Vector> allClusterEmbeddings = allClusterSummary.map(
(key, value) => MapEntry(
key,
ml.Vector.fromList(
EVector.fromBuffer(value.$1).values,
dtype: ml.DType.float32,
),
),
);
// Calculate cosine similarity between current cluster and all clusters
for (final entry in allClusterEmbeddings.entries) {
final personId = clusterToPerson[entry.key]!;
final similarity = currentClusterEmbedding.dot(entry.value);
_personToMaxSimilarity[personId] = max(
_personToMaxSimilarity[personId] ?? double.negativeInfinity,
similarity,
);
}
return _personToMaxSimilarity;
}
List<(PersonEntity, EnteFile)> _sortByCosine(
List<(PersonEntity, EnteFile)> searchResults,
) {
if (widget.clusterID == null || _personToMaxSimilarity.isEmpty) {
return searchResults;
}
// Sort search results based on cosine similarity
searchResults.sort((a, b) {
final similarityA = _personToMaxSimilarity[a.$1.remoteID] ?? 0;
final similarityB = _personToMaxSimilarity[b.$1.remoteID] ?? 0;
return similarityB.compareTo(similarityA);
});
return searchResults;
}
Future<void> addNewPerson(
BuildContext context, {
String text = '',

View File

@@ -9,6 +9,7 @@ import "package:photos/models/ml/face/face.dart";
import "package:photos/models/ml/face/person.dart";
import "package:photos/services/machine_learning/face_ml/person/person_service.dart";
import "package:photos/services/machine_learning/ml_result.dart";
import "package:photos/services/search_service.dart";
import "package:photos/theme/ente_theme.dart";
import "package:photos/ui/common/loading_widget.dart";
import "package:photos/ui/viewer/file/thumbnail_widget.dart";
@@ -109,11 +110,15 @@ class _PersonFaceWidgetState extends State<PersonFaceWidget> {
await MLDataDB.instance.getFaceIDsForCluster(widget.clusterID!);
}
if (allFaces != null) {
final allFileIDs = allFaces.map((e) => getFileIdFromFaceId(e));
final allFileIDs = allFaces.map((e) => getFileIdFromFaceId(e)).toSet();
final hiddenFileIDs = await SearchService.instance
.getHiddenFiles()
.then((onValue) => onValue.map((e) => e.uploadedFileID));
final acceptableFileIDs = allFileIDs.difference(hiddenFileIDs.toSet());
final fileIDToCreationTime =
await FilesDB.instance.getFileIDToCreationTime();
// Get the file with the most recent creation time
final recentFileID = allFileIDs.reduce((a, b) {
final recentFileID = acceptableFileIDs.reduce((a, b) {
final aTime = fileIDToCreationTime[a];
final bTime = fileIDToCreationTime[b];
if (aTime == null) {

View File

@@ -145,8 +145,6 @@ class SearchResultWidget extends StatelessWidget {
return "Shared";
case ResultType.faces:
return "Person";
default:
return type.name.toUpperCase();
}
}
}

View File

@@ -159,8 +159,6 @@ class _AllSearchSectionsState extends State<AllSearchSections> {
snapshot.data!.elementAt(index)
as List<GenericSearchResult>,
);
default:
const SizedBox.shrink();
}
},
)

View File

@@ -8,7 +8,6 @@ import 'package:logging/logging.dart';
import "package:photos/core/errors.dart";
import 'package:photos/models/derived_key_result.dart';
import 'package:photos/models/encryption_result.dart';
import "package:photos/utils/device_info.dart";
const int encryptionChunkSize = 4 * 1024 * 1024;
final int decryptionChunkSize =
@@ -392,24 +391,27 @@ class CryptoUtil {
Uint8List salt,
) async {
final logger = Logger("pwhash");
int memLimit = Sodium.cryptoPwhashMemlimitSensitive;
int opsLimit = Sodium.cryptoPwhashOpslimitSensitive;
if (await isLowSpecDevice()) {
logger.info("low spec device detected");
// When sensitive memLimit (1 GB) is used, on low spec device the OS might
// kill the app with OOM. To avoid that, start with 256 MB and
// corresponding ops limit (16).
// This ensures that the product of these two variables
// (the area under the graph that determines the amount of work required)
// stays the same
// SODIUM_CRYPTO_PWHASH_MEMLIMIT_SENSITIVE: 1073741824
// SODIUM_CRYPTO_PWHASH_MEMLIMIT_MODERATE: 268435456
// SODIUM_CRYPTO_PWHASH_OPSLIMIT_SENSITIVE: 4
memLimit = Sodium.cryptoPwhashMemlimitModerate;
final factor = Sodium.cryptoPwhashMemlimitSensitive ~/
Sodium.cryptoPwhashMemlimitModerate; // = 4
opsLimit = opsLimit * factor; // = 16
final int desiredStrength = Sodium.cryptoPwhashMemlimitSensitive *
Sodium.cryptoPwhashOpslimitSensitive;
// When sensitive memLimit (1 GB) is used, on low spec device the OS might
// kill the app with OOM. To avoid that, start with 256 MB and
// corresponding ops limit (16).
// This ensures that the product of these two variables
// (the area under the graph that determines the amount of work required)
// stays the same
// SODIUM_CRYPTO_PWHASH_MEMLIMIT_SENSITIVE: 1073741824
// SODIUM_CRYPTO_PWHASH_MEMLIMIT_MODERATE: 268435456
// SODIUM_CRYPTO_PWHASH_OPSLIMIT_SENSITIVE: 4
int memLimit = Sodium.cryptoPwhashMemlimitModerate;
final factor = Sodium.cryptoPwhashMemlimitSensitive ~/
Sodium.cryptoPwhashMemlimitModerate; // = 4
int opsLimit = Sodium.cryptoPwhashOpslimitSensitive * factor; // = 16
if (memLimit * opsLimit != desiredStrength) {
throw UnsupportedError(
"unexpcted values for memLimit $memLimit and opsLimit: $opsLimit",
);
}
Uint8List key;
while (memLimit >= Sodium.cryptoPwhashMemlimitMin &&
opsLimit <= Sodium.cryptoPwhashOpslimitMax) {

View File

@@ -325,7 +325,9 @@ List<ContactsFilter> _curateContactsFilter(
if (file.ownerID == Configuration.instance.getUserID() ||
file.uploadedFileID == null ||
file.uploadedFileID == -1 ||
file.ownerID == null) continue;
file.ownerID == null) {
continue;
}
ownerIdToOccurrence[file.ownerID!] =
(ownerIdToOccurrence[file.ownerID] ?? 0) + 1;
}

View File

@@ -5,10 +5,10 @@ packages:
dependency: transitive
description:
name: _fe_analyzer_shared
sha256: f256b0c0ba6c7577c15e2e4e114755640a875e885099367bf6e012b19314c834
sha256: "16e298750b6d0af7ce8a3ba7c18c69c3785d11b15ec83f6dcd0ad2a0009b3cab"
url: "https://pub.dev"
source: hosted
version: "72.0.0"
version: "76.0.0"
_flutterfire_internals:
dependency: transitive
description:
@@ -21,7 +21,7 @@ packages:
dependency: transitive
description: dart
source: sdk
version: "0.3.2"
version: "0.3.3"
adaptive_theme:
dependency: "direct main"
description:
@@ -34,10 +34,10 @@ packages:
dependency: transitive
description:
name: analyzer
sha256: b652861553cd3990d8ed361f7979dc6d7053a9ac8843fa73820ab68ce5410139
sha256: "1f14db053a8c23e260789e9b0980fa27f2680dd640932cae5e1137cce0e46e1e"
url: "https://pub.dev"
source: hosted
version: "6.7.0"
version: "6.11.0"
android_intent_plus:
dependency: "direct main"
description:
@@ -284,10 +284,10 @@ packages:
dependency: "direct main"
description:
name: collection
sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a
sha256: a1ace0a119f20aabc852d165077c036cd864315bd99b7eaa10a60100341941bf
url: "https://pub.dev"
source: hosted
version: "1.18.0"
version: "1.19.0"
computer:
dependency: "direct main"
description:
@@ -585,11 +585,12 @@ packages:
figma_squircle:
dependency: "direct main"
description:
name: figma_squircle
sha256: "790b91a9505e90d246f6efe2fa065ff7fffe658c7b44fe9b5b20c7b0ad3818c0"
url: "https://pub.dev"
source: hosted
version: "0.5.3"
path: "."
ref: HEAD
resolved-ref: "5f1ad5aaccdf31fc398fc141979ea845a0f45383"
url: "https://github.com/Ax0elz/figma_squircle.git"
source: git
version: "0.5.5"
file:
dependency: transitive
description:
@@ -1358,18 +1359,18 @@ packages:
dependency: transitive
description:
name: leak_tracker
sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05"
sha256: "7bb2830ebd849694d1ec25bf1f44582d6ac531a57a365a803a6034ff751d2d06"
url: "https://pub.dev"
source: hosted
version: "10.0.5"
version: "10.0.7"
leak_tracker_flutter_testing:
dependency: transitive
description:
name: leak_tracker_flutter_testing
sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806"
sha256: "9491a714cca3667b60b5c420da8217e6de0d1ba7a5ec322fab01758f6998f379"
url: "https://pub.dev"
source: hosted
version: "3.0.5"
version: "3.0.8"
leak_tracker_testing:
dependency: transitive
description:
@@ -1486,10 +1487,10 @@ packages:
dependency: transitive
description:
name: macros
sha256: "0acaed5d6b7eab89f63350bccd82119e6c602df0f391260d0e32b5e23db79536"
sha256: "1d9e801cd66f7ea3663c45fc708450db1fa57f988142c64289142c9b7ee80656"
url: "https://pub.dev"
source: hosted
version: "0.1.2-main.4"
version: "0.1.3-main.0"
maps_launcher:
dependency: "direct main"
description:
@@ -2292,7 +2293,7 @@ packages:
dependency: transitive
description: flutter
source: sdk
version: "0.0.99"
version: "0.0.0"
source_gen:
dependency: transitive
description:
@@ -2417,10 +2418,10 @@ packages:
dependency: transitive
description:
name: stack_trace
sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b"
sha256: "9f47fd3630d76be3ab26f0ee06d213679aa425996925ff3feffdec504931c377"
url: "https://pub.dev"
source: hosted
version: "1.11.1"
version: "1.12.0"
step_progress_indicator:
dependency: "direct main"
description:
@@ -2449,10 +2450,10 @@ packages:
dependency: transitive
description:
name: string_scanner
sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde"
sha256: "688af5ed3402a4bde5b3a6c15fd768dbf2621a614950b17f04626c431ab3c4c3"
url: "https://pub.dev"
source: hosted
version: "1.2.0"
version: "1.3.0"
styled_text:
dependency: "direct main"
description:
@@ -2513,26 +2514,26 @@ packages:
dependency: "direct dev"
description:
name: test
sha256: "7ee44229615f8f642b68120165ae4c2a75fe77ae2065b1e55ae4711f6cf0899e"
sha256: "713a8789d62f3233c46b4a90b174737b2c04cb6ae4500f2aa8b1be8f03f5e67f"
url: "https://pub.dev"
source: hosted
version: "1.25.7"
version: "1.25.8"
test_api:
dependency: transitive
description:
name: test_api
sha256: "5b8a98dafc4d5c4c9c72d8b31ab2b23fc13422348d2997120294d3bac86b4ddb"
sha256: "664d3a9a64782fcdeb83ce9c6b39e78fd2971d4e37827b9b06c3aa1edc5e760c"
url: "https://pub.dev"
source: hosted
version: "0.7.2"
version: "0.7.3"
test_core:
dependency: transitive
description:
name: test_core
sha256: "55ea5a652e38a1dfb32943a7973f3681a60f872f8c3a05a14664ad54ef9c6696"
sha256: "12391302411737c176b0b5d6491f466b0dd56d4763e347b6714efbaa74d7953d"
url: "https://pub.dev"
source: hosted
version: "0.6.4"
version: "0.6.5"
timezone:
dependency: transitive
description:
@@ -2819,10 +2820,10 @@ packages:
dependency: transitive
description:
name: vm_service
sha256: "5c5f338a667b4c644744b661f309fb8080bb94b18a7e91ef1dbd343bed00ed6d"
sha256: f6be3ed8bd01289b34d679c2b62226f63c0e69f9fd2e50a6b3c1c729a961041b
url: "https://pub.dev"
source: hosted
version: "14.2.5"
version: "14.3.0"
volume_controller:
dependency: transitive
description:
@@ -2891,10 +2892,10 @@ packages:
dependency: transitive
description:
name: webdriver
sha256: "003d7da9519e1e5f329422b36c4dcdf18d7d2978d1ba099ea4e45ba490ed845e"
sha256: "3d773670966f02a646319410766d3b5e1037efb7f07cc68f844d5e06cd4d61c8"
url: "https://pub.dev"
source: hosted
version: "3.0.3"
version: "3.0.4"
webkit_inspection_protocol:
dependency: transitive
description:

View File

@@ -12,7 +12,7 @@ description: ente photos application
# Read more about iOS versioning at
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
version: 0.9.79+979
version: 0.9.82+982
publish_to: none
environment:
@@ -63,7 +63,9 @@ dependencies:
fade_indexed_stack: ^0.2.2
fast_base58: ^0.2.1
ffmpeg_kit_flutter_min: ^6.0.3
figma_squircle: ^0.5.3
figma_squircle:
git:
url: https://github.com/Ax0elz/figma_squircle.git
file_saver:
# Use forked version till this PR is merged: https://github.com/incrediblezayed/file_saver/pull/87
git: https://github.com/jesims/file_saver.git

View File

@@ -474,6 +474,7 @@ func main() {
UserRepo: userRepo,
UserCtrl: userController,
PasskeyController: passkeyCtrl,
LockCtrl: lockController,
}
userHandler := &api.UserHandler{
UserController: userController,
@@ -495,7 +496,6 @@ func main() {
privateAPI.POST("/users/two-factor/disable", userHandler.DisableTwoFactor)
privateAPI.PUT("/users/attributes", userHandler.SetAttributes)
privateAPI.PUT("/users/email-mfa", userHandler.UpdateEmailMFA)
privateAPI.PUT("/users/keys", userHandler.UpdateKeys)
privateAPI.POST("/users/srp/setup", userHandler.SetupSRP)
privateAPI.POST("/users/srp/complete", userHandler.CompleteSRPSetup)
privateAPI.POST("/users/srp/update", userHandler.UpdateSrpAndKeyAttributes)
@@ -766,7 +766,7 @@ func main() {
setupAndStartBackgroundJobs(objectCleanupController, replicationController3, fileDataCtrl)
setupAndStartCrons(
userAuthRepo, publicCollectionRepo, twoFactorRepo, passkeysRepo, fileController, taskLockingRepo, emailNotificationCtrl,
trashController, pushController, objectController, dataCleanupController, storageBonusCtrl,
trashController, pushController, objectController, dataCleanupController, storageBonusCtrl, emergencyCtrl,
embeddingController, healthCheckHandler, kexCtrl, castDb)
// Create a new collector, the name will be used as a label on the metrics
@@ -901,6 +901,7 @@ func setupAndStartCrons(userAuthRepo *repo.UserAuthRepository, publicCollectionR
objectController *controller.ObjectController,
dataCleanupCtrl *dataCleanupCtrl.DeleteUserCleanupController,
storageBonusCtrl *storagebonus.Controller,
emergencyCtrl *emergency.Controller,
embeddingCtrl *embeddingCtrl.Controller,
healthCheckHandler *api.HealthCheckHandler,
kexCtrl *kexCtrl.Controller,
@@ -994,6 +995,7 @@ func setupAndStartCrons(userAuthRepo *repo.UserAuthRepository, publicCollectionR
})
scheduleAndRun(c, "@every 60m", func() {
emergencyCtrl.SendRecoveryReminder()
kexCtrl.DeleteOldKeys()
})

Some files were not shown because too many files have changed in this diff Show More