Merge remote-tracking branch 'origin' into auth-deskicons
This commit is contained in:
commit
3d91b548db
6
.gitignore
vendored
6
.gitignore
vendored
|
@ -1,8 +1,6 @@
|
||||||
# Let folks use their custom .vscode settings
|
# Let folks use their custom editor settings
|
||||||
.vscode
|
.vscode
|
||||||
|
.idea
|
||||||
|
|
||||||
# macOS
|
# macOS
|
||||||
.DS_Store
|
.DS_Store
|
||||||
.idea
|
|
||||||
.ente.authenticator.db
|
|
||||||
.ente.offline_authenticator.db
|
|
||||||
|
|
|
@ -85,20 +85,16 @@ PODS:
|
||||||
- SDWebImage (5.19.2):
|
- SDWebImage (5.19.2):
|
||||||
- SDWebImage/Core (= 5.19.2)
|
- SDWebImage/Core (= 5.19.2)
|
||||||
- SDWebImage/Core (5.19.2)
|
- SDWebImage/Core (5.19.2)
|
||||||
- Sentry/HybridSDK (8.21.0):
|
- Sentry/HybridSDK (8.25.0)
|
||||||
- SentryPrivate (= 8.21.0)
|
- sentry_flutter (7.20.1):
|
||||||
- sentry_flutter (0.0.1):
|
|
||||||
- Flutter
|
- Flutter
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
- Sentry/HybridSDK (= 8.21.0)
|
- Sentry/HybridSDK (= 8.25.0)
|
||||||
- SentryPrivate (8.21.0)
|
|
||||||
- share_plus (0.0.1):
|
- share_plus (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- shared_preferences_foundation (0.0.1):
|
- shared_preferences_foundation (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
- smart_auth (0.0.1):
|
|
||||||
- Flutter
|
|
||||||
- sodium_libs (2.2.1):
|
- sodium_libs (2.2.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- sqflite (0.0.3):
|
- sqflite (0.0.3):
|
||||||
|
@ -115,7 +111,7 @@ PODS:
|
||||||
- sqlite3/common
|
- sqlite3/common
|
||||||
- sqlite3_flutter_libs (0.0.1):
|
- sqlite3_flutter_libs (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- sqlite3 (~> 3.45.1)
|
- "sqlite3 (~> 3.45.3+1)"
|
||||||
- sqlite3/fts5
|
- sqlite3/fts5
|
||||||
- sqlite3/perf-threadsafe
|
- sqlite3/perf-threadsafe
|
||||||
- sqlite3/rtree
|
- sqlite3/rtree
|
||||||
|
@ -148,7 +144,6 @@ DEPENDENCIES:
|
||||||
- sentry_flutter (from `.symlinks/plugins/sentry_flutter/ios`)
|
- sentry_flutter (from `.symlinks/plugins/sentry_flutter/ios`)
|
||||||
- share_plus (from `.symlinks/plugins/share_plus/ios`)
|
- share_plus (from `.symlinks/plugins/share_plus/ios`)
|
||||||
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
|
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
|
||||||
- smart_auth (from `.symlinks/plugins/smart_auth/ios`)
|
|
||||||
- sodium_libs (from `.symlinks/plugins/sodium_libs/ios`)
|
- sodium_libs (from `.symlinks/plugins/sodium_libs/ios`)
|
||||||
- sqflite (from `.symlinks/plugins/sqflite/darwin`)
|
- sqflite (from `.symlinks/plugins/sqflite/darwin`)
|
||||||
- sqlite3_flutter_libs (from `.symlinks/plugins/sqlite3_flutter_libs/ios`)
|
- sqlite3_flutter_libs (from `.symlinks/plugins/sqlite3_flutter_libs/ios`)
|
||||||
|
@ -163,7 +158,6 @@ SPEC REPOS:
|
||||||
- ReachabilitySwift
|
- ReachabilitySwift
|
||||||
- SDWebImage
|
- SDWebImage
|
||||||
- Sentry
|
- Sentry
|
||||||
- SentryPrivate
|
|
||||||
- sqlite3
|
- sqlite3
|
||||||
- SwiftyGif
|
- SwiftyGif
|
||||||
- Toast
|
- Toast
|
||||||
|
@ -215,8 +209,6 @@ EXTERNAL SOURCES:
|
||||||
:path: ".symlinks/plugins/share_plus/ios"
|
:path: ".symlinks/plugins/share_plus/ios"
|
||||||
shared_preferences_foundation:
|
shared_preferences_foundation:
|
||||||
:path: ".symlinks/plugins/shared_preferences_foundation/darwin"
|
:path: ".symlinks/plugins/shared_preferences_foundation/darwin"
|
||||||
smart_auth:
|
|
||||||
:path: ".symlinks/plugins/smart_auth/ios"
|
|
||||||
sodium_libs:
|
sodium_libs:
|
||||||
:path: ".symlinks/plugins/sodium_libs/ios"
|
:path: ".symlinks/plugins/sodium_libs/ios"
|
||||||
sqflite:
|
sqflite:
|
||||||
|
@ -236,13 +228,13 @@ SPEC CHECKSUMS:
|
||||||
file_saver: 503e386464dbe118f630e17b4c2e1190fa0cf808
|
file_saver: 503e386464dbe118f630e17b4c2e1190fa0cf808
|
||||||
fk_user_agent: 1f47ec39291e8372b1d692b50084b0d54103c545
|
fk_user_agent: 1f47ec39291e8372b1d692b50084b0d54103c545
|
||||||
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
|
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
|
||||||
flutter_email_sender: 02d7443217d8c41483223627972bfdc09f74276b
|
flutter_email_sender: 10a22605f92809a11ef52b2f412db806c6082d40
|
||||||
flutter_inappwebview_ios: 97215cf7d4677db55df76782dbd2930c5e1c1ea0
|
flutter_inappwebview_ios: 97215cf7d4677db55df76782dbd2930c5e1c1ea0
|
||||||
flutter_local_authentication: 1172a4dd88f6306dadce067454e2c4caf07977bb
|
flutter_local_authentication: 1172a4dd88f6306dadce067454e2c4caf07977bb
|
||||||
flutter_local_notifications: 4cde75091f6327eb8517fa068a0a5950212d2086
|
flutter_local_notifications: 4cde75091f6327eb8517fa068a0a5950212d2086
|
||||||
flutter_native_splash: edf599c81f74d093a4daf8e17bd7a018854bc778
|
flutter_native_splash: edf599c81f74d093a4daf8e17bd7a018854bc778
|
||||||
flutter_secure_storage: 23fc622d89d073675f2eaa109381aefbcf5a49be
|
flutter_secure_storage: 23fc622d89d073675f2eaa109381aefbcf5a49be
|
||||||
fluttertoast: 31b00dabfa7fb7bacd9e7dbee580d7a2ff4bf265
|
fluttertoast: 9f2f8e81bb5ce18facb9748d7855bf5a756fe3db
|
||||||
local_auth_darwin: c7e464000a6a89e952235699e32b329457608d98
|
local_auth_darwin: c7e464000a6a89e952235699e32b329457608d98
|
||||||
move_to_background: 39a5b79b26d577b0372cbe8a8c55e7aa9fcd3a2d
|
move_to_background: 39a5b79b26d577b0372cbe8a8c55e7aa9fcd3a2d
|
||||||
MTBBarcodeScanner: f453b33c4b7dfe545d8c6484ed744d55671788cb
|
MTBBarcodeScanner: f453b33c4b7dfe545d8c6484ed744d55671788cb
|
||||||
|
@ -253,16 +245,14 @@ SPEC CHECKSUMS:
|
||||||
qr_code_scanner: bb67d64904c3b9658ada8c402e8b4d406d5d796e
|
qr_code_scanner: bb67d64904c3b9658ada8c402e8b4d406d5d796e
|
||||||
ReachabilitySwift: 2128f3a8c9107e1ad33574c6e58e8285d460b149
|
ReachabilitySwift: 2128f3a8c9107e1ad33574c6e58e8285d460b149
|
||||||
SDWebImage: dfe95b2466a9823cf9f0c6d01217c06550d7b29a
|
SDWebImage: dfe95b2466a9823cf9f0c6d01217c06550d7b29a
|
||||||
Sentry: ebc12276bd17613a114ab359074096b6b3725203
|
Sentry: cd86fc55628f5b7c572cabe66cc8f95a9d2f165a
|
||||||
sentry_flutter: dff1df05dc39c83d04f9330b36360fc374574c5e
|
sentry_flutter: 4cb24c1055c556d7b27262ab2e179d1e5a0b9b0c
|
||||||
SentryPrivate: d651efb234cf385ec9a1cdd3eff94b5e78a0e0fe
|
|
||||||
share_plus: c3fef564749587fc939ef86ffb283ceac0baf9f5
|
share_plus: c3fef564749587fc939ef86ffb283ceac0baf9f5
|
||||||
shared_preferences_foundation: b4c3b4cddf1c21f02770737f147a3f5da9d39695
|
shared_preferences_foundation: b4c3b4cddf1c21f02770737f147a3f5da9d39695
|
||||||
smart_auth: 4bedbc118723912d0e45a07e8ab34039c19e04f2
|
|
||||||
sodium_libs: 1faae17af662384acbd13e41867a0008cd2e2318
|
sodium_libs: 1faae17af662384acbd13e41867a0008cd2e2318
|
||||||
sqflite: 673a0e54cc04b7d6dba8d24fb8095b31c3a99eec
|
sqflite: 673a0e54cc04b7d6dba8d24fb8095b31c3a99eec
|
||||||
sqlite3: 02d1f07eaaa01f80a1c16b4b31dfcbb3345ee01a
|
sqlite3: 02d1f07eaaa01f80a1c16b4b31dfcbb3345ee01a
|
||||||
sqlite3_flutter_libs: af0e8fe9bce48abddd1ffdbbf839db0302d72d80
|
sqlite3_flutter_libs: 9bfe005308998aeca155330bbc2ea6dddf834a3b
|
||||||
SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4
|
SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4
|
||||||
Toast: 1f5ea13423a1e6674c4abdac5be53587ae481c4e
|
Toast: 1f5ea13423a1e6674c4abdac5be53587ae481c4e
|
||||||
url_launcher_ios: 6116280ddcfe98ab8820085d8d76ae7449447586
|
url_launcher_ios: 6116280ddcfe98ab8820085d8d76ae7449447586
|
||||||
|
|
|
@ -188,6 +188,8 @@
|
||||||
"recoveryKeySaveDescription": "Мы не храним этот ключ, пожалуйста, сохраните этот ключ в безопасном месте.",
|
"recoveryKeySaveDescription": "Мы не храним этот ключ, пожалуйста, сохраните этот ключ в безопасном месте.",
|
||||||
"doThisLater": "Сделать позже",
|
"doThisLater": "Сделать позже",
|
||||||
"saveKey": "Сохранить ключ",
|
"saveKey": "Сохранить ключ",
|
||||||
|
"save": "Сохранить",
|
||||||
|
"send": "Отправить",
|
||||||
"back": "Вернуться",
|
"back": "Вернуться",
|
||||||
"createAccount": "Создать аккаунт",
|
"createAccount": "Создать аккаунт",
|
||||||
"passwordStrength": "Мощность пароля: {passwordStrengthValue}",
|
"passwordStrength": "Мощность пароля: {passwordStrengthValue}",
|
||||||
|
@ -394,5 +396,13 @@
|
||||||
"signOutOtherDevices": "Выйти из других устройств",
|
"signOutOtherDevices": "Выйти из других устройств",
|
||||||
"doNotSignOut": "Не выходить",
|
"doNotSignOut": "Не выходить",
|
||||||
"hearUsWhereTitle": "Как вы узнали о Ente? (необязательно)",
|
"hearUsWhereTitle": "Как вы узнали о Ente? (необязательно)",
|
||||||
"hearUsExplanation": "Будет полезно, если вы укажете, где нашли нас, так как мы не отслеживаем установки приложения"
|
"hearUsExplanation": "Будет полезно, если вы укажете, где нашли нас, так как мы не отслеживаем установки приложения",
|
||||||
|
"waitingForVerification": "Ожидание подтверждения...",
|
||||||
|
"developerSettingsWarning": "Вы уверены, что хотите изменить настройки разработчика?",
|
||||||
|
"developerSettings": "Настройки разработчика",
|
||||||
|
"serverEndpoint": "Конечная точка сервера",
|
||||||
|
"invalidEndpoint": "Неверная конечная точка",
|
||||||
|
"invalidEndpointMessage": "Извините, введенная вами конечная точка неверна. Пожалуйста, введите корректную конечную точку и повторите попытку.",
|
||||||
|
"endpointUpdatedMessage": "Конечная точка успешно обновлена",
|
||||||
|
"customEndpoint": "Подключено к {endpoint}"
|
||||||
}
|
}
|
|
@ -29,20 +29,16 @@ PODS:
|
||||||
- ReachabilitySwift (5.2.2)
|
- ReachabilitySwift (5.2.2)
|
||||||
- screen_retriever (0.0.1):
|
- screen_retriever (0.0.1):
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
- Sentry/HybridSDK (8.21.0):
|
- Sentry/HybridSDK (8.25.0)
|
||||||
- SentryPrivate (= 8.21.0)
|
- sentry_flutter (7.20.1):
|
||||||
- sentry_flutter (0.0.1):
|
|
||||||
- Flutter
|
- Flutter
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
- Sentry/HybridSDK (= 8.21.0)
|
- Sentry/HybridSDK (= 8.25.0)
|
||||||
- SentryPrivate (8.21.0)
|
|
||||||
- share_plus (0.0.1):
|
- share_plus (0.0.1):
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
- shared_preferences_foundation (0.0.1):
|
- shared_preferences_foundation (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
- smart_auth (0.0.1):
|
|
||||||
- FlutterMacOS
|
|
||||||
- sodium_libs (2.2.1):
|
- sodium_libs (2.2.1):
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
- sqflite (0.0.3):
|
- sqflite (0.0.3):
|
||||||
|
@ -59,7 +55,7 @@ PODS:
|
||||||
- sqlite3/common
|
- sqlite3/common
|
||||||
- sqlite3_flutter_libs (0.0.1):
|
- sqlite3_flutter_libs (0.0.1):
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
- sqlite3 (~> 3.45.1)
|
- "sqlite3 (~> 3.45.3+1)"
|
||||||
- sqlite3/fts5
|
- sqlite3/fts5
|
||||||
- sqlite3/perf-threadsafe
|
- sqlite3/perf-threadsafe
|
||||||
- sqlite3/rtree
|
- sqlite3/rtree
|
||||||
|
@ -87,7 +83,6 @@ DEPENDENCIES:
|
||||||
- sentry_flutter (from `Flutter/ephemeral/.symlinks/plugins/sentry_flutter/macos`)
|
- sentry_flutter (from `Flutter/ephemeral/.symlinks/plugins/sentry_flutter/macos`)
|
||||||
- share_plus (from `Flutter/ephemeral/.symlinks/plugins/share_plus/macos`)
|
- share_plus (from `Flutter/ephemeral/.symlinks/plugins/share_plus/macos`)
|
||||||
- shared_preferences_foundation (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin`)
|
- shared_preferences_foundation (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin`)
|
||||||
- smart_auth (from `Flutter/ephemeral/.symlinks/plugins/smart_auth/macos`)
|
|
||||||
- sodium_libs (from `Flutter/ephemeral/.symlinks/plugins/sodium_libs/macos`)
|
- sodium_libs (from `Flutter/ephemeral/.symlinks/plugins/sodium_libs/macos`)
|
||||||
- sqflite (from `Flutter/ephemeral/.symlinks/plugins/sqflite/darwin`)
|
- sqflite (from `Flutter/ephemeral/.symlinks/plugins/sqflite/darwin`)
|
||||||
- sqlite3_flutter_libs (from `Flutter/ephemeral/.symlinks/plugins/sqlite3_flutter_libs/macos`)
|
- sqlite3_flutter_libs (from `Flutter/ephemeral/.symlinks/plugins/sqlite3_flutter_libs/macos`)
|
||||||
|
@ -100,7 +95,6 @@ SPEC REPOS:
|
||||||
- OrderedSet
|
- OrderedSet
|
||||||
- ReachabilitySwift
|
- ReachabilitySwift
|
||||||
- Sentry
|
- Sentry
|
||||||
- SentryPrivate
|
|
||||||
- sqlite3
|
- sqlite3
|
||||||
|
|
||||||
EXTERNAL SOURCES:
|
EXTERNAL SOURCES:
|
||||||
|
@ -136,8 +130,6 @@ EXTERNAL SOURCES:
|
||||||
:path: Flutter/ephemeral/.symlinks/plugins/share_plus/macos
|
:path: Flutter/ephemeral/.symlinks/plugins/share_plus/macos
|
||||||
shared_preferences_foundation:
|
shared_preferences_foundation:
|
||||||
:path: Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin
|
:path: Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin
|
||||||
smart_auth:
|
|
||||||
:path: Flutter/ephemeral/.symlinks/plugins/smart_auth/macos
|
|
||||||
sodium_libs:
|
sodium_libs:
|
||||||
:path: Flutter/ephemeral/.symlinks/plugins/sodium_libs/macos
|
:path: Flutter/ephemeral/.symlinks/plugins/sodium_libs/macos
|
||||||
sqflite:
|
sqflite:
|
||||||
|
@ -167,16 +159,14 @@ SPEC CHECKSUMS:
|
||||||
path_provider_foundation: 3784922295ac71e43754bd15e0653ccfd36a147c
|
path_provider_foundation: 3784922295ac71e43754bd15e0653ccfd36a147c
|
||||||
ReachabilitySwift: 2128f3a8c9107e1ad33574c6e58e8285d460b149
|
ReachabilitySwift: 2128f3a8c9107e1ad33574c6e58e8285d460b149
|
||||||
screen_retriever: 59634572a57080243dd1bf715e55b6c54f241a38
|
screen_retriever: 59634572a57080243dd1bf715e55b6c54f241a38
|
||||||
Sentry: ebc12276bd17613a114ab359074096b6b3725203
|
Sentry: cd86fc55628f5b7c572cabe66cc8f95a9d2f165a
|
||||||
sentry_flutter: dff1df05dc39c83d04f9330b36360fc374574c5e
|
sentry_flutter: 4cb24c1055c556d7b27262ab2e179d1e5a0b9b0c
|
||||||
SentryPrivate: d651efb234cf385ec9a1cdd3eff94b5e78a0e0fe
|
|
||||||
share_plus: 76dd39142738f7a68dd57b05093b5e8193f220f7
|
share_plus: 76dd39142738f7a68dd57b05093b5e8193f220f7
|
||||||
shared_preferences_foundation: b4c3b4cddf1c21f02770737f147a3f5da9d39695
|
shared_preferences_foundation: b4c3b4cddf1c21f02770737f147a3f5da9d39695
|
||||||
smart_auth: b38e3ab4bfe089eacb1e233aca1a2340f96c28e9
|
|
||||||
sodium_libs: d39bd76697736cb11ce4a0be73b9b4bc64466d6f
|
sodium_libs: d39bd76697736cb11ce4a0be73b9b4bc64466d6f
|
||||||
sqflite: 673a0e54cc04b7d6dba8d24fb8095b31c3a99eec
|
sqflite: 673a0e54cc04b7d6dba8d24fb8095b31c3a99eec
|
||||||
sqlite3: 02d1f07eaaa01f80a1c16b4b31dfcbb3345ee01a
|
sqlite3: 02d1f07eaaa01f80a1c16b4b31dfcbb3345ee01a
|
||||||
sqlite3_flutter_libs: 06a05802529659a272beac4ee1350bfec294f386
|
sqlite3_flutter_libs: 8d204ef443cf0d5c1c8b058044eab53f3943a9c5
|
||||||
tray_manager: 9064e219c56d75c476e46b9a21182087930baf90
|
tray_manager: 9064e219c56d75c476e46b9a21182087930baf90
|
||||||
url_launcher_macos: d2691c7dd33ed713bf3544850a623080ec693d95
|
url_launcher_macos: d2691c7dd33ed713bf3544850a623080ec693d95
|
||||||
window_manager: 3a1844359a6295ab1e47659b1a777e36773cd6e8
|
window_manager: 3a1844359a6295ab1e47659b1a777e36773cd6e8
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
name: ente_auth
|
name: ente_auth
|
||||||
description: ente two-factor authenticator
|
description: ente two-factor authenticator
|
||||||
version: 2.0.58+258
|
version: 3.0.2+302
|
||||||
publish_to: none
|
publish_to: none
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
"build:ci": "yarn build-renderer && tsc",
|
"build:ci": "yarn build-renderer && tsc",
|
||||||
"build:quick": "yarn build-renderer && yarn build-main:quick",
|
"build:quick": "yarn build-renderer && yarn build-main:quick",
|
||||||
"dev": "concurrently --kill-others --success first --names 'main,rndr' \"yarn dev-main\" \"yarn dev-renderer\"",
|
"dev": "concurrently --kill-others --success first --names 'main,rndr' \"yarn dev-main\" \"yarn dev-renderer\"",
|
||||||
"dev-main": "tsc && electron app/main.js",
|
"dev-main": "tsc && electron .",
|
||||||
"dev-renderer": "cd ../web && yarn install && yarn dev:photos",
|
"dev-renderer": "cd ../web && yarn install && yarn dev:photos",
|
||||||
"postinstall": "electron-builder install-app-deps",
|
"postinstall": "electron-builder install-app-deps",
|
||||||
"lint": "yarn prettier --check --log-level warn . && eslint --ext .ts src && yarn tsc",
|
"lint": "yarn prettier --check --log-level warn . && eslint --ext .ts src && yarn tsc",
|
||||||
|
|
|
@ -241,7 +241,7 @@ const uniqueSavePath = (dirPath: string, fileName: string) => {
|
||||||
*
|
*
|
||||||
* @param webContents The renderer to configure.
|
* @param webContents The renderer to configure.
|
||||||
*/
|
*/
|
||||||
export const allowExternalLinks = (webContents: WebContents) => {
|
export const allowExternalLinks = (webContents: WebContents) =>
|
||||||
// By default, if the user were open a link, say
|
// By default, if the user were open a link, say
|
||||||
// https://github.com/ente-io/ente/discussions, then it would open a _new_
|
// https://github.com/ente-io/ente/discussions, then it would open a _new_
|
||||||
// BrowserWindow within our app.
|
// BrowserWindow within our app.
|
||||||
|
@ -253,13 +253,37 @@ export const allowExternalLinks = (webContents: WebContents) => {
|
||||||
// Returning `action` "deny" accomplishes this.
|
// Returning `action` "deny" accomplishes this.
|
||||||
webContents.setWindowOpenHandler(({ url }) => {
|
webContents.setWindowOpenHandler(({ url }) => {
|
||||||
if (!url.startsWith(rendererURL)) {
|
if (!url.startsWith(rendererURL)) {
|
||||||
|
// This does not work in Ubuntu currently: mailto links seem to just
|
||||||
|
// get ignored, and HTTP links open in the text editor instead of in
|
||||||
|
// the browser.
|
||||||
|
// https://github.com/electron/electron/issues/31485
|
||||||
void shell.openExternal(url);
|
void shell.openExternal(url);
|
||||||
return { action: "deny" };
|
return { action: "deny" };
|
||||||
} else {
|
} else {
|
||||||
return { action: "allow" };
|
return { action: "allow" };
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
|
||||||
|
/**
|
||||||
|
* Allow uploading to arbitrary S3 buckets.
|
||||||
|
*
|
||||||
|
* The files in the desktop app are served over the ente:// protocol. During
|
||||||
|
* testing or self-hosting, we might be using a S3 bucket that does not allow
|
||||||
|
* whitelisting a custom URI scheme. To avoid requiring the bucket to set an
|
||||||
|
* "Access-Control-Allow-Origin: *" or do a echo-back of `Origin`, we add a
|
||||||
|
* workaround here instead, intercepting the ACAO header and allowing `*`.
|
||||||
|
*/
|
||||||
|
export const allowAllCORSOrigins = (webContents: WebContents) =>
|
||||||
|
webContents.session.webRequest.onHeadersReceived(
|
||||||
|
({ responseHeaders }, callback) => {
|
||||||
|
const headers: NonNullable<typeof responseHeaders> = {};
|
||||||
|
for (const [key, value] of Object.entries(responseHeaders ?? {}))
|
||||||
|
if (key.toLowerCase() != "access-control-allow-origin")
|
||||||
|
headers[key] = value;
|
||||||
|
headers["Access-Control-Allow-Origin"] = ["*"];
|
||||||
|
callback({ responseHeaders: headers });
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add an icon for our app in the system tray.
|
* Add an icon for our app in the system tray.
|
||||||
|
@ -291,32 +315,18 @@ const setupTrayItem = (mainWindow: BrowserWindow) => {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Older versions of our app used to maintain a cache dir using the main
|
* Older versions of our app used to maintain a cache dir using the main
|
||||||
* process. This has been removed in favor of cache on the web layer.
|
* process. This has been removed in favor of cache on the web layer. Delete the
|
||||||
|
* old cache dir if it exists.
|
||||||
*
|
*
|
||||||
* Delete the old cache dir if it exists.
|
* Added May 2024, v1.7.0. This migration code can be removed after some time
|
||||||
*
|
* once most people have upgraded to newer versions.
|
||||||
* This will happen in two phases. The cache had three subdirectories:
|
|
||||||
*
|
|
||||||
* - Two of them, "thumbs" and "files", will be removed now (v1.7.0, May 2024).
|
|
||||||
*
|
|
||||||
* - The third one, "face-crops" will be removed once we finish the face search
|
|
||||||
* changes. See: [Note: Legacy face crops].
|
|
||||||
*
|
|
||||||
* This migration code can be removed after some time once most people have
|
|
||||||
* upgraded to newer versions.
|
|
||||||
*/
|
*/
|
||||||
const deleteLegacyDiskCacheDirIfExists = async () => {
|
const deleteLegacyDiskCacheDirIfExists = async () => {
|
||||||
const removeIfExists = async (dirPath: string) => {
|
|
||||||
if (existsSync(dirPath)) {
|
|
||||||
log.info(`Removing legacy disk cache from ${dirPath}`);
|
|
||||||
await fs.rm(dirPath, { recursive: true });
|
|
||||||
}
|
|
||||||
};
|
|
||||||
// [Note: Getting the cache path]
|
// [Note: Getting the cache path]
|
||||||
//
|
//
|
||||||
// The existing code was passing "cache" as a parameter to getPath.
|
// The existing code was passing "cache" as a parameter to getPath.
|
||||||
//
|
//
|
||||||
// However, "cache" is not a valid parameter to getPath. It works! (for
|
// However, "cache" is not a valid parameter to getPath. It works (for
|
||||||
// example, on macOS I get `~/Library/Caches`), but it is intentionally not
|
// example, on macOS I get `~/Library/Caches`), but it is intentionally not
|
||||||
// documented as part of the public API:
|
// documented as part of the public API:
|
||||||
//
|
//
|
||||||
|
@ -329,8 +339,8 @@ const deleteLegacyDiskCacheDirIfExists = async () => {
|
||||||
// @ts-expect-error "cache" works but is not part of the public API.
|
// @ts-expect-error "cache" works but is not part of the public API.
|
||||||
const cacheDir = path.join(app.getPath("cache"), "ente");
|
const cacheDir = path.join(app.getPath("cache"), "ente");
|
||||||
if (existsSync(cacheDir)) {
|
if (existsSync(cacheDir)) {
|
||||||
await removeIfExists(path.join(cacheDir, "thumbs"));
|
log.info(`Removing legacy disk cache from ${cacheDir}`);
|
||||||
await removeIfExists(path.join(cacheDir, "files"));
|
await fs.rm(cacheDir, { recursive: true });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -390,8 +400,10 @@ const main = () => {
|
||||||
registerStreamProtocol();
|
registerStreamProtocol();
|
||||||
|
|
||||||
// Configure the renderer's environment.
|
// Configure the renderer's environment.
|
||||||
setDownloadPath(mainWindow.webContents);
|
const webContents = mainWindow.webContents;
|
||||||
allowExternalLinks(mainWindow.webContents);
|
setDownloadPath(webContents);
|
||||||
|
allowExternalLinks(webContents);
|
||||||
|
allowAllCORSOrigins(webContents);
|
||||||
|
|
||||||
// Start loading the renderer.
|
// Start loading the renderer.
|
||||||
void mainWindow.loadURL(rendererURL);
|
void mainWindow.loadURL(rendererURL);
|
||||||
|
|
|
@ -24,7 +24,6 @@ import {
|
||||||
updateOnNextRestart,
|
updateOnNextRestart,
|
||||||
} from "./services/app-update";
|
} from "./services/app-update";
|
||||||
import {
|
import {
|
||||||
legacyFaceCrop,
|
|
||||||
openDirectory,
|
openDirectory,
|
||||||
openLogDirectory,
|
openLogDirectory,
|
||||||
selectDirectory,
|
selectDirectory,
|
||||||
|
@ -43,10 +42,10 @@ import {
|
||||||
import { convertToJPEG, generateImageThumbnail } from "./services/image";
|
import { convertToJPEG, generateImageThumbnail } from "./services/image";
|
||||||
import { logout } from "./services/logout";
|
import { logout } from "./services/logout";
|
||||||
import {
|
import {
|
||||||
clipImageEmbedding,
|
computeCLIPImageEmbedding,
|
||||||
clipTextEmbeddingIfAvailable,
|
computeCLIPTextEmbeddingIfAvailable,
|
||||||
} from "./services/ml-clip";
|
} from "./services/ml-clip";
|
||||||
import { detectFaces, faceEmbeddings } from "./services/ml-face";
|
import { computeFaceEmbeddings, detectFaces } from "./services/ml-face";
|
||||||
import { encryptionKey, saveEncryptionKey } from "./services/store";
|
import { encryptionKey, saveEncryptionKey } from "./services/store";
|
||||||
import {
|
import {
|
||||||
clearPendingUploads,
|
clearPendingUploads,
|
||||||
|
@ -170,24 +169,22 @@ export const attachIPCHandlers = () => {
|
||||||
|
|
||||||
// - ML
|
// - ML
|
||||||
|
|
||||||
ipcMain.handle("clipImageEmbedding", (_, jpegImageData: Uint8Array) =>
|
ipcMain.handle(
|
||||||
clipImageEmbedding(jpegImageData),
|
"computeCLIPImageEmbedding",
|
||||||
|
(_, jpegImageData: Uint8Array) =>
|
||||||
|
computeCLIPImageEmbedding(jpegImageData),
|
||||||
);
|
);
|
||||||
|
|
||||||
ipcMain.handle("clipTextEmbeddingIfAvailable", (_, text: string) =>
|
ipcMain.handle("computeCLIPTextEmbeddingIfAvailable", (_, text: string) =>
|
||||||
clipTextEmbeddingIfAvailable(text),
|
computeCLIPTextEmbeddingIfAvailable(text),
|
||||||
);
|
);
|
||||||
|
|
||||||
ipcMain.handle("detectFaces", (_, input: Float32Array) =>
|
ipcMain.handle("detectFaces", (_, input: Float32Array) =>
|
||||||
detectFaces(input),
|
detectFaces(input),
|
||||||
);
|
);
|
||||||
|
|
||||||
ipcMain.handle("faceEmbeddings", (_, input: Float32Array) =>
|
ipcMain.handle("computeFaceEmbeddings", (_, input: Float32Array) =>
|
||||||
faceEmbeddings(input),
|
computeFaceEmbeddings(input),
|
||||||
);
|
|
||||||
|
|
||||||
ipcMain.handle("legacyFaceCrop", (_, faceID: string) =>
|
|
||||||
legacyFaceCrop(faceID),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// - Upload
|
// - Upload
|
||||||
|
|
|
@ -70,8 +70,9 @@ const logInfo = (...params: unknown[]) => {
|
||||||
const message = params
|
const message = params
|
||||||
.map((p) => (typeof p == "string" ? p : util.inspect(p)))
|
.map((p) => (typeof p == "string" ? p : util.inspect(p)))
|
||||||
.join(" ");
|
.join(" ");
|
||||||
log.info(`[main] ${message}`);
|
const m = `[info] ${message}`;
|
||||||
if (isDev) console.log(`[info] ${message}`);
|
if (isDev) console.log(m);
|
||||||
|
log.info(`[main] ${m}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
const logDebug = (param: () => unknown) => {
|
const logDebug = (param: () => unknown) => {
|
||||||
|
|
|
@ -163,7 +163,7 @@ const checkForUpdatesAndNotify = async (mainWindow: BrowserWindow) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the version of the desktop app
|
* Return the version of the desktop app.
|
||||||
*
|
*
|
||||||
* The return value is of the form `v1.2.3`.
|
* The return value is of the form `v1.2.3`.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
import { shell } from "electron/common";
|
import { shell } from "electron/common";
|
||||||
import { app, dialog } from "electron/main";
|
import { app, dialog } from "electron/main";
|
||||||
import { existsSync } from "fs";
|
|
||||||
import fs from "node:fs/promises";
|
|
||||||
import path from "node:path";
|
import path from "node:path";
|
||||||
import { posixPath } from "../utils/electron";
|
import { posixPath } from "../utils/electron";
|
||||||
|
|
||||||
|
@ -53,14 +51,6 @@ export const openLogDirectory = () => openDirectory(logDirectoryPath());
|
||||||
* "userData" directory. This is the **primary** place applications are meant to
|
* "userData" directory. This is the **primary** place applications are meant to
|
||||||
* store user's data, e.g. various configuration files and saved state.
|
* store user's data, e.g. various configuration files and saved state.
|
||||||
*
|
*
|
||||||
* During development, our app name is "Electron", so this'd be, for example,
|
|
||||||
* `~/Library/Application Support/Electron` if we run using `yarn dev`. For the
|
|
||||||
* packaged production app, our app name is "ente", so this would be:
|
|
||||||
*
|
|
||||||
* - Windows: `%APPDATA%\ente`, e.g. `C:\Users\<username>\AppData\Local\ente`
|
|
||||||
* - Linux: `~/.config/ente`
|
|
||||||
* - macOS: `~/Library/Application Support/ente`
|
|
||||||
*
|
|
||||||
* Note that Chromium also stores the browser state, e.g. localStorage or disk
|
* Note that Chromium also stores the browser state, e.g. localStorage or disk
|
||||||
* caches, in userData.
|
* caches, in userData.
|
||||||
*
|
*
|
||||||
|
@ -73,21 +63,7 @@ export const openLogDirectory = () => openDirectory(logDirectoryPath());
|
||||||
* "ente.log", it can be found at:
|
* "ente.log", it can be found at:
|
||||||
*
|
*
|
||||||
* - macOS: ~/Library/Logs/ente/ente.log (production)
|
* - macOS: ~/Library/Logs/ente/ente.log (production)
|
||||||
* - macOS: ~/Library/Logs/Electron/ente.log (dev)
|
|
||||||
* - Linux: ~/.config/ente/logs/ente.log
|
* - Linux: ~/.config/ente/logs/ente.log
|
||||||
* - Windows: %USERPROFILE%\AppData\Roaming\ente\logs\ente.log
|
* - Windows: %USERPROFILE%\AppData\Roaming\ente\logs\ente.log
|
||||||
*/
|
*/
|
||||||
const logDirectoryPath = () => app.getPath("logs");
|
const logDirectoryPath = () => app.getPath("logs");
|
||||||
|
|
||||||
/**
|
|
||||||
* See: [Note: Legacy face crops]
|
|
||||||
*/
|
|
||||||
export const legacyFaceCrop = async (
|
|
||||||
faceID: string,
|
|
||||||
): Promise<Uint8Array | undefined> => {
|
|
||||||
// See: [Note: Getting the cache path]
|
|
||||||
// @ts-expect-error "cache" works but is not part of the public API.
|
|
||||||
const cacheDir = path.join(app.getPath("cache"), "ente");
|
|
||||||
const filePath = path.join(cacheDir, "face-crops", faceID);
|
|
||||||
return existsSync(filePath) ? await fs.readFile(filePath) : undefined;
|
|
||||||
};
|
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
import fs from "node:fs/promises";
|
import fs from "node:fs/promises";
|
||||||
import path from "node:path";
|
import path from "node:path";
|
||||||
import { CustomErrorMessage, type ZipItem } from "../../types/ipc";
|
import { CustomErrorMessage, type ZipItem } from "../../types/ipc";
|
||||||
import log from "../log";
|
|
||||||
import { execAsync, isDev } from "../utils/electron";
|
import { execAsync, isDev } from "../utils/electron";
|
||||||
import {
|
import {
|
||||||
deleteTempFileIgnoringErrors,
|
deleteTempFileIgnoringErrors,
|
||||||
|
@ -93,9 +92,6 @@ export const generateImageThumbnail = async (
|
||||||
let thumbnail: Uint8Array;
|
let thumbnail: Uint8Array;
|
||||||
do {
|
do {
|
||||||
await execAsync(command);
|
await execAsync(command);
|
||||||
// TODO(MR): release 1.7
|
|
||||||
// TODO(MR): imagemagick debugging. Remove me after verifying logs.
|
|
||||||
log.info(`Generated thumbnail using ${command.join(" ")}`);
|
|
||||||
thumbnail = new Uint8Array(await fs.readFile(outputFilePath));
|
thumbnail = new Uint8Array(await fs.readFile(outputFilePath));
|
||||||
quality -= 10;
|
quality -= 10;
|
||||||
command = generateImageThumbnailCommand(
|
command = generateImageThumbnailCommand(
|
||||||
|
|
|
@ -11,7 +11,7 @@ import * as ort from "onnxruntime-node";
|
||||||
import Tokenizer from "../../thirdparty/clip-bpe-ts/mod";
|
import Tokenizer from "../../thirdparty/clip-bpe-ts/mod";
|
||||||
import log from "../log";
|
import log from "../log";
|
||||||
import { writeStream } from "../stream";
|
import { writeStream } from "../stream";
|
||||||
import { ensure } from "../utils/common";
|
import { ensure, wait } from "../utils/common";
|
||||||
import { deleteTempFile, makeTempFilePath } from "../utils/temp";
|
import { deleteTempFile, makeTempFilePath } from "../utils/temp";
|
||||||
import { makeCachedInferenceSession } from "./ml";
|
import { makeCachedInferenceSession } from "./ml";
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ const cachedCLIPImageSession = makeCachedInferenceSession(
|
||||||
351468764 /* 335.2 MB */,
|
351468764 /* 335.2 MB */,
|
||||||
);
|
);
|
||||||
|
|
||||||
export const clipImageEmbedding = async (jpegImageData: Uint8Array) => {
|
export const computeCLIPImageEmbedding = async (jpegImageData: Uint8Array) => {
|
||||||
const tempFilePath = await makeTempFilePath();
|
const tempFilePath = await makeTempFilePath();
|
||||||
const imageStream = new Response(jpegImageData.buffer).body;
|
const imageStream = new Response(jpegImageData.buffer).body;
|
||||||
await writeStream(tempFilePath, ensure(imageStream));
|
await writeStream(tempFilePath, ensure(imageStream));
|
||||||
|
@ -42,7 +42,7 @@ const clipImageEmbedding_ = async (jpegFilePath: string) => {
|
||||||
const results = await session.run(feeds);
|
const results = await session.run(feeds);
|
||||||
log.debug(
|
log.debug(
|
||||||
() =>
|
() =>
|
||||||
`onnx/clip image embedding took ${Date.now() - t1} ms (prep: ${t2 - t1} ms, inference: ${Date.now() - t2} ms)`,
|
`ONNX/CLIP image embedding took ${Date.now() - t1} ms (prep: ${t2 - t1} ms, inference: ${Date.now() - t2} ms)`,
|
||||||
);
|
);
|
||||||
/* Need these model specific casts to type the result */
|
/* Need these model specific casts to type the result */
|
||||||
const imageEmbedding = ensure(results.output).data as Float32Array;
|
const imageEmbedding = ensure(results.output).data as Float32Array;
|
||||||
|
@ -140,21 +140,23 @@ const getTokenizer = () => {
|
||||||
return _tokenizer;
|
return _tokenizer;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const clipTextEmbeddingIfAvailable = async (text: string) => {
|
export const computeCLIPTextEmbeddingIfAvailable = async (text: string) => {
|
||||||
const sessionOrStatus = await Promise.race([
|
const sessionOrSkip = await Promise.race([
|
||||||
cachedCLIPTextSession(),
|
cachedCLIPTextSession(),
|
||||||
"downloading-model",
|
// Wait for a tick to get the session promise to resolved the first time
|
||||||
|
// this code runs on each app start (and the model has been downloaded).
|
||||||
|
wait(0).then(() => 1),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Don't wait for the download to complete
|
// Don't wait for the download to complete.
|
||||||
if (typeof sessionOrStatus == "string") {
|
if (typeof sessionOrSkip == "number") {
|
||||||
log.info(
|
log.info(
|
||||||
"Ignoring CLIP text embedding request because model download is pending",
|
"Ignoring CLIP text embedding request because model download is pending",
|
||||||
);
|
);
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
const session = sessionOrStatus;
|
const session = sessionOrSkip;
|
||||||
const t1 = Date.now();
|
const t1 = Date.now();
|
||||||
const tokenizer = getTokenizer();
|
const tokenizer = getTokenizer();
|
||||||
const tokenizedText = Int32Array.from(tokenizer.encodeForCLIP(text));
|
const tokenizedText = Int32Array.from(tokenizer.encodeForCLIP(text));
|
||||||
|
@ -165,7 +167,7 @@ export const clipTextEmbeddingIfAvailable = async (text: string) => {
|
||||||
const results = await session.run(feeds);
|
const results = await session.run(feeds);
|
||||||
log.debug(
|
log.debug(
|
||||||
() =>
|
() =>
|
||||||
`onnx/clip text embedding took ${Date.now() - t1} ms (prep: ${t2 - t1} ms, inference: ${Date.now() - t2} ms)`,
|
`ONNX/CLIP text embedding took ${Date.now() - t1} ms (prep: ${t2 - t1} ms, inference: ${Date.now() - t2} ms)`,
|
||||||
);
|
);
|
||||||
const textEmbedding = ensure(results.output).data as Float32Array;
|
const textEmbedding = ensure(results.output).data as Float32Array;
|
||||||
return normalizeEmbedding(textEmbedding);
|
return normalizeEmbedding(textEmbedding);
|
||||||
|
|
|
@ -23,7 +23,7 @@ export const detectFaces = async (input: Float32Array) => {
|
||||||
input: new ort.Tensor("float32", input, [1, 3, 640, 640]),
|
input: new ort.Tensor("float32", input, [1, 3, 640, 640]),
|
||||||
};
|
};
|
||||||
const results = await session.run(feeds);
|
const results = await session.run(feeds);
|
||||||
log.debug(() => `onnx/yolo face detection took ${Date.now() - t} ms`);
|
log.debug(() => `ONNX/YOLO face detection took ${Date.now() - t} ms`);
|
||||||
return ensure(results.output).data;
|
return ensure(results.output).data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ const cachedFaceEmbeddingSession = makeCachedInferenceSession(
|
||||||
5286998 /* 5 MB */,
|
5286998 /* 5 MB */,
|
||||||
);
|
);
|
||||||
|
|
||||||
export const faceEmbeddings = async (input: Float32Array) => {
|
export const computeFaceEmbeddings = async (input: Float32Array) => {
|
||||||
// Dimension of each face (alias)
|
// Dimension of each face (alias)
|
||||||
const mobileFaceNetFaceSize = 112;
|
const mobileFaceNetFaceSize = 112;
|
||||||
// Smaller alias
|
// Smaller alias
|
||||||
|
@ -45,7 +45,7 @@ export const faceEmbeddings = async (input: Float32Array) => {
|
||||||
const t = Date.now();
|
const t = Date.now();
|
||||||
const feeds = { img_inputs: inputTensor };
|
const feeds = { img_inputs: inputTensor };
|
||||||
const results = await session.run(feeds);
|
const results = await session.run(feeds);
|
||||||
log.debug(() => `onnx/yolo face embedding took ${Date.now() - t} ms`);
|
log.debug(() => `ONNX/MFNT face embedding took ${Date.now() - t} ms`);
|
||||||
/* Need these model specific casts to extract and type the result */
|
/* Need these model specific casts to extract and type the result */
|
||||||
return (results.embeddings as unknown as Record<string, unknown>)
|
return (results.embeddings as unknown as Record<string, unknown>)
|
||||||
.cpuData as Float32Array;
|
.cpuData as Float32Array;
|
||||||
|
|
|
@ -18,10 +18,7 @@ export const clearStores = () => {
|
||||||
* [Note: Safe storage keys]
|
* [Note: Safe storage keys]
|
||||||
*
|
*
|
||||||
* On macOS, `safeStorage` stores our data under a Keychain entry named
|
* On macOS, `safeStorage` stores our data under a Keychain entry named
|
||||||
* "<app-name> Safe Storage". Which resolves to:
|
* "<app-name> Safe Storage". In our case, "ente Safe Storage".
|
||||||
*
|
|
||||||
* - Electron Safe Storage (dev)
|
|
||||||
* - ente Safe Storage (prod)
|
|
||||||
*/
|
*/
|
||||||
export const saveEncryptionKey = (encryptionKey: string) => {
|
export const saveEncryptionKey = (encryptionKey: string) => {
|
||||||
const encryptedKey = safeStorage.encryptString(encryptionKey);
|
const encryptedKey = safeStorage.encryptString(encryptionKey);
|
||||||
|
|
|
@ -13,3 +13,12 @@ export const ensure = <T>(v: T | null | undefined): T => {
|
||||||
if (v === undefined) throw new Error("Required value was not found");
|
if (v === undefined) throw new Error("Required value was not found");
|
||||||
return v;
|
return v;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wait for {@link ms} milliseconds
|
||||||
|
*
|
||||||
|
* This function is a promisified `setTimeout`. It returns a promise that
|
||||||
|
* resolves after {@link ms} milliseconds.
|
||||||
|
*/
|
||||||
|
export const wait = (ms: number) =>
|
||||||
|
new Promise((resolve) => setTimeout(resolve, ms));
|
||||||
|
|
|
@ -55,9 +55,7 @@ export const execAsync = async (command: string | string[]) => {
|
||||||
: command;
|
: command;
|
||||||
const startTime = Date.now();
|
const startTime = Date.now();
|
||||||
const result = await execAsync_(escapedCommand);
|
const result = await execAsync_(escapedCommand);
|
||||||
log.debug(
|
log.debug(() => `${escapedCommand} (${Date.now() - startTime} ms)`);
|
||||||
() => `${escapedCommand} (${Math.round(Date.now() - startTime)} ms)`,
|
|
||||||
);
|
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -65,7 +65,7 @@ const selectDirectory = () => ipcRenderer.invoke("selectDirectory");
|
||||||
|
|
||||||
const logout = () => {
|
const logout = () => {
|
||||||
watchRemoveListeners();
|
watchRemoveListeners();
|
||||||
ipcRenderer.send("logout");
|
return ipcRenderer.invoke("logout");
|
||||||
};
|
};
|
||||||
|
|
||||||
const encryptionKey = () => ipcRenderer.invoke("encryptionKey");
|
const encryptionKey = () => ipcRenderer.invoke("encryptionKey");
|
||||||
|
@ -153,20 +153,17 @@ const ffmpegExec = (
|
||||||
|
|
||||||
// - ML
|
// - ML
|
||||||
|
|
||||||
const clipImageEmbedding = (jpegImageData: Uint8Array) =>
|
const computeCLIPImageEmbedding = (jpegImageData: Uint8Array) =>
|
||||||
ipcRenderer.invoke("clipImageEmbedding", jpegImageData);
|
ipcRenderer.invoke("computeCLIPImageEmbedding", jpegImageData);
|
||||||
|
|
||||||
const clipTextEmbeddingIfAvailable = (text: string) =>
|
const computeCLIPTextEmbeddingIfAvailable = (text: string) =>
|
||||||
ipcRenderer.invoke("clipTextEmbeddingIfAvailable", text);
|
ipcRenderer.invoke("computeCLIPTextEmbeddingIfAvailable", text);
|
||||||
|
|
||||||
const detectFaces = (input: Float32Array) =>
|
const detectFaces = (input: Float32Array) =>
|
||||||
ipcRenderer.invoke("detectFaces", input);
|
ipcRenderer.invoke("detectFaces", input);
|
||||||
|
|
||||||
const faceEmbeddings = (input: Float32Array) =>
|
const computeFaceEmbeddings = (input: Float32Array) =>
|
||||||
ipcRenderer.invoke("faceEmbeddings", input);
|
ipcRenderer.invoke("computeFaceEmbeddings", input);
|
||||||
|
|
||||||
const legacyFaceCrop = (faceID: string) =>
|
|
||||||
ipcRenderer.invoke("legacyFaceCrop", faceID);
|
|
||||||
|
|
||||||
// - Watch
|
// - Watch
|
||||||
|
|
||||||
|
@ -340,11 +337,10 @@ contextBridge.exposeInMainWorld("electron", {
|
||||||
|
|
||||||
// - ML
|
// - ML
|
||||||
|
|
||||||
clipImageEmbedding,
|
computeCLIPImageEmbedding,
|
||||||
clipTextEmbeddingIfAvailable,
|
computeCLIPTextEmbeddingIfAvailable,
|
||||||
detectFaces,
|
detectFaces,
|
||||||
faceEmbeddings,
|
computeFaceEmbeddings,
|
||||||
legacyFaceCrop,
|
|
||||||
|
|
||||||
// - Watch
|
// - Watch
|
||||||
|
|
||||||
|
|
|
@ -43,7 +43,7 @@ android {
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId "io.ente.photos"
|
applicationId "io.ente.photos"
|
||||||
minSdkVersion 21
|
minSdkVersion 26
|
||||||
targetSdkVersion 33
|
targetSdkVersion 33
|
||||||
versionCode flutterVersionCode.toInteger()
|
versionCode flutterVersionCode.toInteger()
|
||||||
versionName flutterVersionName
|
versionName flutterVersionName
|
||||||
|
@ -70,6 +70,10 @@ android {
|
||||||
dimension "default"
|
dimension "default"
|
||||||
applicationIdSuffix ".dev"
|
applicationIdSuffix ".dev"
|
||||||
}
|
}
|
||||||
|
face {
|
||||||
|
dimension "default"
|
||||||
|
applicationIdSuffix ".face"
|
||||||
|
}
|
||||||
playstore {
|
playstore {
|
||||||
dimension "default"
|
dimension "default"
|
||||||
}
|
}
|
||||||
|
|
10
mobile/android/app/src/face/AndroidManifest.xml
Normal file
10
mobile/android/app/src/face/AndroidManifest.xml
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
package="io.ente.photos">
|
||||||
|
<!-- Flutter needs it to communicate with the running application
|
||||||
|
to allow setting breakpoints, to provide hot reload, etc.
|
||||||
|
-->
|
||||||
|
<uses-permission android:name="android.permission.INTERNET"/>
|
||||||
|
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||||
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||||
|
</manifest>
|
4
mobile/android/app/src/face/res/values/strings.xml
Normal file
4
mobile/android/app/src/face/res/values/strings.xml
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
<resources>
|
||||||
|
<string name="app_name">ente face</string>
|
||||||
|
<string name="backup">backup face</string>
|
||||||
|
</resources>
|
|
@ -1,91 +0,0 @@
|
||||||
unknown
|
|
||||||
person
|
|
||||||
bicycle
|
|
||||||
car
|
|
||||||
motorcycle
|
|
||||||
airplane
|
|
||||||
bus
|
|
||||||
train
|
|
||||||
truck
|
|
||||||
boat
|
|
||||||
traffic light
|
|
||||||
fire hydrant
|
|
||||||
unknown
|
|
||||||
stop sign
|
|
||||||
parking meter
|
|
||||||
bench
|
|
||||||
bird
|
|
||||||
cat
|
|
||||||
dog
|
|
||||||
horse
|
|
||||||
sheep
|
|
||||||
cow
|
|
||||||
elephant
|
|
||||||
bear
|
|
||||||
zebra
|
|
||||||
giraffe
|
|
||||||
unknown
|
|
||||||
backpack
|
|
||||||
umbrella
|
|
||||||
unknown
|
|
||||||
unknown
|
|
||||||
handbag
|
|
||||||
tie
|
|
||||||
suitcase
|
|
||||||
frisbee
|
|
||||||
skis
|
|
||||||
snowboard
|
|
||||||
sports ball
|
|
||||||
kite
|
|
||||||
baseball bat
|
|
||||||
baseball glove
|
|
||||||
skateboard
|
|
||||||
surfboard
|
|
||||||
tennis racket
|
|
||||||
bottle
|
|
||||||
unknown
|
|
||||||
wine glass
|
|
||||||
cup
|
|
||||||
fork
|
|
||||||
knife
|
|
||||||
spoon
|
|
||||||
bowl
|
|
||||||
banana
|
|
||||||
apple
|
|
||||||
sandwich
|
|
||||||
orange
|
|
||||||
broccoli
|
|
||||||
carrot
|
|
||||||
hot dog
|
|
||||||
pizza
|
|
||||||
donut
|
|
||||||
cake
|
|
||||||
chair
|
|
||||||
couch
|
|
||||||
potted plant
|
|
||||||
bed
|
|
||||||
unknown
|
|
||||||
dining table
|
|
||||||
unknown
|
|
||||||
unknown
|
|
||||||
toilet
|
|
||||||
unknown
|
|
||||||
tv
|
|
||||||
laptop
|
|
||||||
mouse
|
|
||||||
remote
|
|
||||||
keyboard
|
|
||||||
cell phone
|
|
||||||
microwave
|
|
||||||
oven
|
|
||||||
toaster
|
|
||||||
sink
|
|
||||||
refrigerator
|
|
||||||
unknown
|
|
||||||
book
|
|
||||||
clock
|
|
||||||
vase
|
|
||||||
scissors
|
|
||||||
teddy bear
|
|
||||||
hair drier
|
|
||||||
toothbrush
|
|
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
|
@ -1,30 +0,0 @@
|
||||||
waterfall
|
|
||||||
snow
|
|
||||||
landscape
|
|
||||||
underwater
|
|
||||||
architecture
|
|
||||||
sunset / sunrise
|
|
||||||
blue sky
|
|
||||||
cloudy sky
|
|
||||||
greenery
|
|
||||||
autumn leaves
|
|
||||||
portrait
|
|
||||||
flower
|
|
||||||
night shot
|
|
||||||
stage concert
|
|
||||||
fireworks
|
|
||||||
candle light
|
|
||||||
neon lights
|
|
||||||
indoor
|
|
||||||
backlight
|
|
||||||
text documents
|
|
||||||
qr images
|
|
||||||
group portrait
|
|
||||||
computer screens
|
|
||||||
kids
|
|
||||||
dog
|
|
||||||
cat
|
|
||||||
macro
|
|
||||||
food
|
|
||||||
beach
|
|
||||||
mountain
|
|
Binary file not shown.
|
@ -6,6 +6,8 @@ PODS:
|
||||||
- connectivity_plus (0.0.1):
|
- connectivity_plus (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
|
- dart_ui_isolate (0.0.1):
|
||||||
|
- Flutter
|
||||||
- device_info_plus (0.0.1):
|
- device_info_plus (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- file_saver (0.0.1):
|
- file_saver (0.0.1):
|
||||||
|
@ -226,6 +228,7 @@ DEPENDENCIES:
|
||||||
- background_fetch (from `.symlinks/plugins/background_fetch/ios`)
|
- background_fetch (from `.symlinks/plugins/background_fetch/ios`)
|
||||||
- battery_info (from `.symlinks/plugins/battery_info/ios`)
|
- battery_info (from `.symlinks/plugins/battery_info/ios`)
|
||||||
- connectivity_plus (from `.symlinks/plugins/connectivity_plus/darwin`)
|
- connectivity_plus (from `.symlinks/plugins/connectivity_plus/darwin`)
|
||||||
|
- dart_ui_isolate (from `.symlinks/plugins/dart_ui_isolate/ios`)
|
||||||
- device_info_plus (from `.symlinks/plugins/device_info_plus/ios`)
|
- device_info_plus (from `.symlinks/plugins/device_info_plus/ios`)
|
||||||
- file_saver (from `.symlinks/plugins/file_saver/ios`)
|
- file_saver (from `.symlinks/plugins/file_saver/ios`)
|
||||||
- firebase_core (from `.symlinks/plugins/firebase_core/ios`)
|
- firebase_core (from `.symlinks/plugins/firebase_core/ios`)
|
||||||
|
@ -302,6 +305,8 @@ EXTERNAL SOURCES:
|
||||||
:path: ".symlinks/plugins/battery_info/ios"
|
:path: ".symlinks/plugins/battery_info/ios"
|
||||||
connectivity_plus:
|
connectivity_plus:
|
||||||
:path: ".symlinks/plugins/connectivity_plus/darwin"
|
:path: ".symlinks/plugins/connectivity_plus/darwin"
|
||||||
|
dart_ui_isolate:
|
||||||
|
:path: ".symlinks/plugins/dart_ui_isolate/ios"
|
||||||
device_info_plus:
|
device_info_plus:
|
||||||
:path: ".symlinks/plugins/device_info_plus/ios"
|
:path: ".symlinks/plugins/device_info_plus/ios"
|
||||||
file_saver:
|
file_saver:
|
||||||
|
@ -397,6 +402,7 @@ SPEC CHECKSUMS:
|
||||||
background_fetch: 2319bf7e18237b4b269430b7f14d177c0df09c5a
|
background_fetch: 2319bf7e18237b4b269430b7f14d177c0df09c5a
|
||||||
battery_info: 09f5c9ee65394f2291c8c6227bedff345b8a730c
|
battery_info: 09f5c9ee65394f2291c8c6227bedff345b8a730c
|
||||||
connectivity_plus: ddd7f30999e1faaef5967c23d5b6d503d10434db
|
connectivity_plus: ddd7f30999e1faaef5967c23d5b6d503d10434db
|
||||||
|
dart_ui_isolate: d5bcda83ca4b04f129d70eb90110b7a567aece14
|
||||||
device_info_plus: c6fb39579d0f423935b0c9ce7ee2f44b71b9fce6
|
device_info_plus: c6fb39579d0f423935b0c9ce7ee2f44b71b9fce6
|
||||||
file_saver: 503e386464dbe118f630e17b4c2e1190fa0cf808
|
file_saver: 503e386464dbe118f630e17b4c2e1190fa0cf808
|
||||||
Firebase: 91fefd38712feb9186ea8996af6cbdef41473442
|
Firebase: 91fefd38712feb9186ea8996af6cbdef41473442
|
||||||
|
|
|
@ -293,6 +293,7 @@
|
||||||
"${BUILT_PRODUCTS_DIR}/background_fetch/background_fetch.framework",
|
"${BUILT_PRODUCTS_DIR}/background_fetch/background_fetch.framework",
|
||||||
"${BUILT_PRODUCTS_DIR}/battery_info/battery_info.framework",
|
"${BUILT_PRODUCTS_DIR}/battery_info/battery_info.framework",
|
||||||
"${BUILT_PRODUCTS_DIR}/connectivity_plus/connectivity_plus.framework",
|
"${BUILT_PRODUCTS_DIR}/connectivity_plus/connectivity_plus.framework",
|
||||||
|
"${BUILT_PRODUCTS_DIR}/dart_ui_isolate/dart_ui_isolate.framework",
|
||||||
"${BUILT_PRODUCTS_DIR}/device_info_plus/device_info_plus.framework",
|
"${BUILT_PRODUCTS_DIR}/device_info_plus/device_info_plus.framework",
|
||||||
"${BUILT_PRODUCTS_DIR}/file_saver/file_saver.framework",
|
"${BUILT_PRODUCTS_DIR}/file_saver/file_saver.framework",
|
||||||
"${BUILT_PRODUCTS_DIR}/fk_user_agent/fk_user_agent.framework",
|
"${BUILT_PRODUCTS_DIR}/fk_user_agent/fk_user_agent.framework",
|
||||||
|
@ -374,6 +375,7 @@
|
||||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/background_fetch.framework",
|
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/background_fetch.framework",
|
||||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/battery_info.framework",
|
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/battery_info.framework",
|
||||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/connectivity_plus.framework",
|
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/connectivity_plus.framework",
|
||||||
|
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/dart_ui_isolate.framework",
|
||||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/device_info_plus.framework",
|
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/device_info_plus.framework",
|
||||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/file_saver.framework",
|
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/file_saver.framework",
|
||||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/fk_user_agent.framework",
|
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/fk_user_agent.framework",
|
||||||
|
|
|
@ -65,9 +65,9 @@
|
||||||
<key>ITSAppUsesNonExemptEncryption</key>
|
<key>ITSAppUsesNonExemptEncryption</key>
|
||||||
<false/>
|
<false/>
|
||||||
<key>FLTEnableImpeller</key>
|
<key>FLTEnableImpeller</key>
|
||||||
<false />
|
<true />
|
||||||
<key>FLTEnableWideGamut</key>
|
<key>FLTEnableWideGamut</key>
|
||||||
<false/>
|
<true/>
|
||||||
<key>NSFaceIDUsageDescription</key>
|
<key>NSFaceIDUsageDescription</key>
|
||||||
<string>Please allow ente to lock itself with FaceID or TouchID</string>
|
<string>Please allow ente to lock itself with FaceID or TouchID</string>
|
||||||
<key>NSCameraUsageDescription</key>
|
<key>NSCameraUsageDescription</key>
|
||||||
|
|
|
@ -19,6 +19,7 @@ import 'package:photos/db/upload_locks_db.dart';
|
||||||
import "package:photos/events/endpoint_updated_event.dart";
|
import "package:photos/events/endpoint_updated_event.dart";
|
||||||
import 'package:photos/events/signed_in_event.dart';
|
import 'package:photos/events/signed_in_event.dart';
|
||||||
import 'package:photos/events/user_logged_out_event.dart';
|
import 'package:photos/events/user_logged_out_event.dart';
|
||||||
|
import "package:photos/face/db.dart";
|
||||||
import 'package:photos/models/key_attributes.dart';
|
import 'package:photos/models/key_attributes.dart';
|
||||||
import 'package:photos/models/key_gen_result.dart';
|
import 'package:photos/models/key_gen_result.dart';
|
||||||
import 'package:photos/models/private_key_attributes.dart';
|
import 'package:photos/models/private_key_attributes.dart';
|
||||||
|
@ -187,6 +188,7 @@ class Configuration {
|
||||||
: null;
|
: null;
|
||||||
await CollectionsDB.instance.clearTable();
|
await CollectionsDB.instance.clearTable();
|
||||||
await MemoriesDB.instance.clearTable();
|
await MemoriesDB.instance.clearTable();
|
||||||
|
await FaceMLDataDB.instance.clearTable();
|
||||||
|
|
||||||
await UploadLocksDB.instance.clearTable();
|
await UploadLocksDB.instance.clearTable();
|
||||||
await IgnoredFilesService.instance.reset();
|
await IgnoredFilesService.instance.reset();
|
||||||
|
|
|
@ -99,6 +99,9 @@ const blackThumbnailBase64 = '/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAEBAQEBAQEB'
|
||||||
'AKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAo' +
|
'AKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAo' +
|
||||||
'AKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgD/9k=';
|
'AKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgD/9k=';
|
||||||
|
|
||||||
|
const localFileServer =
|
||||||
|
String.fromEnvironment("localFileServer", defaultValue: "");
|
||||||
|
|
||||||
const uploadTempFilePrefix = "upload_file_";
|
const uploadTempFilePrefix = "upload_file_";
|
||||||
final tempDirCleanUpInterval = kDebugMode
|
final tempDirCleanUpInterval = kDebugMode
|
||||||
? const Duration(seconds: 30).inMicroseconds
|
? const Duration(seconds: 30).inMicroseconds
|
||||||
|
|
|
@ -9,7 +9,7 @@ extension EntitiesDB on FilesDB {
|
||||||
List<LocalEntityData> data, {
|
List<LocalEntityData> data, {
|
||||||
ConflictAlgorithm conflictAlgorithm = ConflictAlgorithm.replace,
|
ConflictAlgorithm conflictAlgorithm = ConflictAlgorithm.replace,
|
||||||
}) async {
|
}) async {
|
||||||
debugPrint("Inserting missing PathIDToLocalIDMapping");
|
debugPrint("entitiesDB: upsertEntities ${data.length} entities");
|
||||||
final db = await database;
|
final db = await database;
|
||||||
var batch = db.batch();
|
var batch = db.batch();
|
||||||
int batchCounter = 0;
|
int batchCounter = 0;
|
||||||
|
@ -62,4 +62,17 @@ extension EntitiesDB on FilesDB {
|
||||||
return LocalEntityData.fromJson(maps[i]);
|
return LocalEntityData.fromJson(maps[i]);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<LocalEntityData?> getEntity(EntityType type, String id) async {
|
||||||
|
final db = await database;
|
||||||
|
final List<Map<String, dynamic>> maps = await db.query(
|
||||||
|
"entities",
|
||||||
|
where: "type = ? AND id = ?",
|
||||||
|
whereArgs: [type.typeToString(), id],
|
||||||
|
);
|
||||||
|
if (maps.isEmpty) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return LocalEntityData.fromJson(maps.first);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -491,6 +491,18 @@ class FilesDB {
|
||||||
return convertToFiles(results)[0];
|
return convertToFiles(results)[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<EnteFile?> getAnyUploadedFile(int uploadedID) async {
|
||||||
|
final db = await instance.sqliteAsyncDB;
|
||||||
|
final results = await db.getAll(
|
||||||
|
'SELECT * FROM $filesTable WHERE $columnUploadedFileID = ?',
|
||||||
|
[uploadedID],
|
||||||
|
);
|
||||||
|
if (results.isEmpty) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return convertToFiles(results)[0];
|
||||||
|
}
|
||||||
|
|
||||||
Future<Set<int>> getUploadedFileIDs(int collectionID) async {
|
Future<Set<int>> getUploadedFileIDs(int collectionID) async {
|
||||||
final db = await instance.sqliteAsyncDB;
|
final db = await instance.sqliteAsyncDB;
|
||||||
final results = await db.getAll(
|
final results = await db.getAll(
|
||||||
|
@ -683,6 +695,17 @@ class FilesDB {
|
||||||
return files;
|
return files;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<List<EnteFile>> getAllFilesFromCollections(
|
||||||
|
Iterable<int> collectionID,
|
||||||
|
) async {
|
||||||
|
final db = await instance.sqliteAsyncDB;
|
||||||
|
final String sql =
|
||||||
|
'SELECT * FROM $filesTable WHERE $columnCollectionID IN (${collectionID.join(',')})';
|
||||||
|
final results = await db.getAll(sql);
|
||||||
|
final files = convertToFiles(results);
|
||||||
|
return files;
|
||||||
|
}
|
||||||
|
|
||||||
Future<List<EnteFile>> getNewFilesInCollection(
|
Future<List<EnteFile>> getNewFilesInCollection(
|
||||||
int collectionID,
|
int collectionID,
|
||||||
int addedTime,
|
int addedTime,
|
||||||
|
@ -1304,6 +1327,23 @@ class FilesDB {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<Map<int, int>> getFileIDToCreationTime() async {
|
||||||
|
final db = await instance.sqliteAsyncDB;
|
||||||
|
final rows = await db.getAll(
|
||||||
|
'''
|
||||||
|
SELECT $columnUploadedFileID, $columnCreationTime
|
||||||
|
FROM $filesTable
|
||||||
|
WHERE
|
||||||
|
($columnUploadedFileID IS NOT NULL AND $columnUploadedFileID IS NOT -1);
|
||||||
|
''',
|
||||||
|
);
|
||||||
|
final result = <int, int>{};
|
||||||
|
for (final row in rows) {
|
||||||
|
result[row[columnUploadedFileID] as int] = row[columnCreationTime] as int;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
// getCollectionFileFirstOrLast returns the first or last uploaded file in
|
// getCollectionFileFirstOrLast returns the first or last uploaded file in
|
||||||
// the collection based on the given collectionID and the order.
|
// the collection based on the given collectionID and the order.
|
||||||
Future<EnteFile?> getCollectionFileFirstOrLast(
|
Future<EnteFile?> getCollectionFileFirstOrLast(
|
||||||
|
@ -1643,13 +1683,14 @@ class FilesDB {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<int>> getOwnedFileIDs(int ownerID) async {
|
Future<List<int>> getOwnedFileIDs(int ownerID) async {
|
||||||
final db = await instance.database;
|
final db = await instance.sqliteAsyncDB;
|
||||||
final results = await db.query(
|
final results = await db.getAll(
|
||||||
filesTable,
|
'''
|
||||||
columns: [columnUploadedFileID],
|
SELECT DISTINCT $columnUploadedFileID FROM $filesTable
|
||||||
where:
|
WHERE ($columnOwnerID = ? AND $columnUploadedFileID IS NOT NULL AND
|
||||||
'($columnOwnerID = $ownerID AND $columnUploadedFileID IS NOT NULL AND $columnUploadedFileID IS NOT -1)',
|
$columnUploadedFileID IS NOT -1)
|
||||||
distinct: true,
|
''',
|
||||||
|
[ownerID],
|
||||||
);
|
);
|
||||||
final ids = <int>[];
|
final ids = <int>[];
|
||||||
for (final result in results) {
|
for (final result in results) {
|
||||||
|
@ -1659,16 +1700,17 @@ class FilesDB {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<EnteFile>> getUploadedFiles(List<int> uploadedIDs) async {
|
Future<List<EnteFile>> getUploadedFiles(List<int> uploadedIDs) async {
|
||||||
final db = await instance.database;
|
final db = await instance.sqliteAsyncDB;
|
||||||
String inParam = "";
|
String inParam = "";
|
||||||
for (final id in uploadedIDs) {
|
for (final id in uploadedIDs) {
|
||||||
inParam += "'" + id.toString() + "',";
|
inParam += "'" + id.toString() + "',";
|
||||||
}
|
}
|
||||||
inParam = inParam.substring(0, inParam.length - 1);
|
inParam = inParam.substring(0, inParam.length - 1);
|
||||||
final results = await db.query(
|
final results = await db.getAll(
|
||||||
filesTable,
|
'''
|
||||||
where: '$columnUploadedFileID IN ($inParam)',
|
SELECT * FROM $filesTable WHERE $columnUploadedFileID IN ($inParam)
|
||||||
groupBy: columnUploadedFileID,
|
GROUP BY $columnUploadedFileID
|
||||||
|
''',
|
||||||
);
|
);
|
||||||
if (results.isEmpty) {
|
if (results.isEmpty) {
|
||||||
return <EnteFile>[];
|
return <EnteFile>[];
|
||||||
|
|
|
@ -26,4 +26,6 @@ enum EventType {
|
||||||
hide,
|
hide,
|
||||||
unhide,
|
unhide,
|
||||||
coverChanged,
|
coverChanged,
|
||||||
|
peopleChanged,
|
||||||
|
peopleClusterChanged,
|
||||||
}
|
}
|
||||||
|
|
22
mobile/lib/events/people_changed_event.dart
Normal file
22
mobile/lib/events/people_changed_event.dart
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
import "package:photos/events/event.dart";
|
||||||
|
import "package:photos/models/file/file.dart";
|
||||||
|
|
||||||
|
class PeopleChangedEvent extends Event {
|
||||||
|
final List<EnteFile>? relevantFiles;
|
||||||
|
final PeopleEventType type;
|
||||||
|
final String source;
|
||||||
|
|
||||||
|
PeopleChangedEvent({
|
||||||
|
this.relevantFiles,
|
||||||
|
this.type = PeopleEventType.defaultType,
|
||||||
|
this.source = "",
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get reason => '$runtimeType{type: ${type.name}, "via": $source}';
|
||||||
|
}
|
||||||
|
|
||||||
|
enum PeopleEventType {
|
||||||
|
defaultType,
|
||||||
|
removedFilesFromCluster,
|
||||||
|
}
|
193
mobile/lib/extensions/ml_linalg_extensions.dart
Normal file
193
mobile/lib/extensions/ml_linalg_extensions.dart
Normal file
|
@ -0,0 +1,193 @@
|
||||||
|
import 'dart:math' as math show sin, cos, atan2, sqrt, pow;
|
||||||
|
import 'package:ml_linalg/linalg.dart';
|
||||||
|
|
||||||
|
extension SetVectorValues on Vector {
|
||||||
|
Vector setValues(int start, int end, Iterable<double> values) {
|
||||||
|
if (values.length > length) {
|
||||||
|
throw Exception('Values cannot be larger than vector');
|
||||||
|
} else if (end - start != values.length) {
|
||||||
|
throw Exception('Values must be same length as range');
|
||||||
|
} else if (start < 0 || end > length) {
|
||||||
|
throw Exception('Range must be within vector');
|
||||||
|
}
|
||||||
|
final tempList = toList();
|
||||||
|
tempList.replaceRange(start, end, values);
|
||||||
|
final newVector = Vector.fromList(tempList);
|
||||||
|
return newVector;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension SetMatrixValues on Matrix {
|
||||||
|
Matrix setSubMatrix(
|
||||||
|
int startRow,
|
||||||
|
int endRow,
|
||||||
|
int startColumn,
|
||||||
|
int endColumn,
|
||||||
|
Iterable<Iterable<double>> values,
|
||||||
|
) {
|
||||||
|
if (values.length > rowCount) {
|
||||||
|
throw Exception('New values cannot have more rows than original matrix');
|
||||||
|
} else if (values.elementAt(0).length > columnCount) {
|
||||||
|
throw Exception(
|
||||||
|
'New values cannot have more columns than original matrix',
|
||||||
|
);
|
||||||
|
} else if (endRow - startRow != values.length) {
|
||||||
|
throw Exception('Values (number of rows) must be same length as range');
|
||||||
|
} else if (endColumn - startColumn != values.elementAt(0).length) {
|
||||||
|
throw Exception(
|
||||||
|
'Values (number of columns) must be same length as range',
|
||||||
|
);
|
||||||
|
} else if (startRow < 0 ||
|
||||||
|
endRow > rowCount ||
|
||||||
|
startColumn < 0 ||
|
||||||
|
endColumn > columnCount) {
|
||||||
|
throw Exception('Range must be within matrix');
|
||||||
|
}
|
||||||
|
final tempList = asFlattenedList
|
||||||
|
.toList(); // You need `.toList()` here to make sure the list is growable, otherwise `replaceRange` will throw an error
|
||||||
|
for (var i = startRow; i < endRow; i++) {
|
||||||
|
tempList.replaceRange(
|
||||||
|
i * columnCount + startColumn,
|
||||||
|
i * columnCount + endColumn,
|
||||||
|
values.elementAt(i).toList(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
final newMatrix = Matrix.fromFlattenedList(tempList, rowCount, columnCount);
|
||||||
|
return newMatrix;
|
||||||
|
}
|
||||||
|
|
||||||
|
Matrix setValues(
|
||||||
|
int startRow,
|
||||||
|
int endRow,
|
||||||
|
int startColumn,
|
||||||
|
int endColumn,
|
||||||
|
Iterable<double> values,
|
||||||
|
) {
|
||||||
|
if ((startRow - endRow) * (startColumn - endColumn) != values.length) {
|
||||||
|
throw Exception('Values must be same length as range');
|
||||||
|
} else if (startRow < 0 ||
|
||||||
|
endRow > rowCount ||
|
||||||
|
startColumn < 0 ||
|
||||||
|
endColumn > columnCount) {
|
||||||
|
throw Exception('Range must be within matrix');
|
||||||
|
}
|
||||||
|
|
||||||
|
final tempList = asFlattenedList
|
||||||
|
.toList(); // You need `.toList()` here to make sure the list is growable, otherwise `replaceRange` will throw an error
|
||||||
|
var index = 0;
|
||||||
|
for (var i = startRow; i < endRow; i++) {
|
||||||
|
for (var j = startColumn; j < endColumn; j++) {
|
||||||
|
tempList[i * columnCount + j] = values.elementAt(index);
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
final newMatrix = Matrix.fromFlattenedList(tempList, rowCount, columnCount);
|
||||||
|
return newMatrix;
|
||||||
|
}
|
||||||
|
|
||||||
|
Matrix setValue(int row, int column, double value) {
|
||||||
|
if (row < 0 || row > rowCount || column < 0 || column > columnCount) {
|
||||||
|
throw Exception('Index must be within range of matrix');
|
||||||
|
}
|
||||||
|
final tempList = asFlattenedList;
|
||||||
|
tempList[row * columnCount + column] = value;
|
||||||
|
final newMatrix = Matrix.fromFlattenedList(tempList, rowCount, columnCount);
|
||||||
|
return newMatrix;
|
||||||
|
}
|
||||||
|
|
||||||
|
Matrix appendRow(List<double> row) {
|
||||||
|
final oldNumberOfRows = rowCount;
|
||||||
|
final oldNumberOfColumns = columnCount;
|
||||||
|
if (row.length != oldNumberOfColumns) {
|
||||||
|
throw Exception('Row must have same number of columns as matrix');
|
||||||
|
}
|
||||||
|
final flatListMatrix = asFlattenedList;
|
||||||
|
flatListMatrix.addAll(row);
|
||||||
|
return Matrix.fromFlattenedList(
|
||||||
|
flatListMatrix,
|
||||||
|
oldNumberOfRows + 1,
|
||||||
|
oldNumberOfColumns,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension MatrixCalculations on Matrix {
|
||||||
|
double determinant() {
|
||||||
|
final int length = rowCount;
|
||||||
|
if (length != columnCount) {
|
||||||
|
throw Exception('Matrix must be square');
|
||||||
|
}
|
||||||
|
if (length == 1) {
|
||||||
|
return this[0][0];
|
||||||
|
} else if (length == 2) {
|
||||||
|
return this[0][0] * this[1][1] - this[0][1] * this[1][0];
|
||||||
|
} else {
|
||||||
|
throw Exception('Determinant for Matrix larger than 2x2 not implemented');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Computes the singular value decomposition of a matrix, using https://lucidar.me/en/mathematics/singular-value-decomposition-of-a-2x2-matrix/ as reference, but with slightly different signs for the second columns of U and V
|
||||||
|
Map<String, dynamic> svd() {
|
||||||
|
if (rowCount != 2 || columnCount != 2) {
|
||||||
|
throw Exception('Matrix must be 2x2');
|
||||||
|
}
|
||||||
|
final a = this[0][0];
|
||||||
|
final b = this[0][1];
|
||||||
|
final c = this[1][0];
|
||||||
|
final d = this[1][1];
|
||||||
|
|
||||||
|
// Computation of U matrix
|
||||||
|
final tempCalc = a * a + b * b - c * c - d * d;
|
||||||
|
final theta = 0.5 * math.atan2(2 * a * c + 2 * b * d, tempCalc);
|
||||||
|
final U = Matrix.fromList([
|
||||||
|
[math.cos(theta), math.sin(theta)],
|
||||||
|
[math.sin(theta), -math.cos(theta)],
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Computation of S matrix
|
||||||
|
// ignore: non_constant_identifier_names
|
||||||
|
final S1 = a * a + b * b + c * c + d * d;
|
||||||
|
// ignore: non_constant_identifier_names
|
||||||
|
final S2 =
|
||||||
|
math.sqrt(math.pow(tempCalc, 2) + 4 * math.pow(a * c + b * d, 2));
|
||||||
|
final sigma1 = math.sqrt((S1 + S2) / 2);
|
||||||
|
final sigma2 = math.sqrt((S1 - S2) / 2);
|
||||||
|
final S = Vector.fromList([sigma1, sigma2]);
|
||||||
|
|
||||||
|
// Computation of V matrix
|
||||||
|
final tempCalc2 = a * a - b * b + c * c - d * d;
|
||||||
|
final phi = 0.5 * math.atan2(2 * a * b + 2 * c * d, tempCalc2);
|
||||||
|
final s11 = (a * math.cos(theta) + c * math.sin(theta)) * math.cos(phi) +
|
||||||
|
(b * math.cos(theta) + d * math.sin(theta)) * math.sin(phi);
|
||||||
|
final s22 = (a * math.sin(theta) - c * math.cos(theta)) * math.sin(phi) +
|
||||||
|
(-b * math.sin(theta) + d * math.cos(theta)) * math.cos(phi);
|
||||||
|
final V = Matrix.fromList([
|
||||||
|
[s11.sign * math.cos(phi), s22.sign * math.sin(phi)],
|
||||||
|
[s11.sign * math.sin(phi), -s22.sign * math.cos(phi)],
|
||||||
|
]);
|
||||||
|
|
||||||
|
return {
|
||||||
|
'U': U,
|
||||||
|
'S': S,
|
||||||
|
'V': V,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
int matrixRank() {
|
||||||
|
final svdResult = svd();
|
||||||
|
final Vector S = svdResult['S']!;
|
||||||
|
final rank = S.toList().where((element) => element > 1e-10).length;
|
||||||
|
return rank;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension TransformMatrix on Matrix {
|
||||||
|
List<List<double>> to2DList() {
|
||||||
|
final List<List<double>> outerList = [];
|
||||||
|
for (var i = 0; i < rowCount; i++) {
|
||||||
|
final innerList = this[i].toList();
|
||||||
|
outerList.add(innerList);
|
||||||
|
}
|
||||||
|
return outerList;
|
||||||
|
}
|
||||||
|
}
|
|
@ -23,4 +23,9 @@ class EnteWatch extends Stopwatch {
|
||||||
reset();
|
reset();
|
||||||
previousElapsed = 0;
|
previousElapsed = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void stopWithLog(String msg) {
|
||||||
|
log(msg);
|
||||||
|
stop();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
1018
mobile/lib/face/db.dart
Normal file
1018
mobile/lib/face/db.dart
Normal file
File diff suppressed because it is too large
Load diff
103
mobile/lib/face/db_fields.dart
Normal file
103
mobile/lib/face/db_fields.dart
Normal file
|
@ -0,0 +1,103 @@
|
||||||
|
// Faces Table Fields & Schema Queries
|
||||||
|
import 'package:photos/services/machine_learning/face_ml/face_filtering/face_filtering_constants.dart';
|
||||||
|
|
||||||
|
const facesTable = 'faces';
|
||||||
|
const fileIDColumn = 'file_id';
|
||||||
|
const faceIDColumn = 'face_id';
|
||||||
|
const faceDetectionColumn = 'detection';
|
||||||
|
const faceEmbeddingBlob = 'eBlob';
|
||||||
|
const faceScore = 'score';
|
||||||
|
const faceBlur = 'blur';
|
||||||
|
const isSideways = 'is_sideways';
|
||||||
|
const imageWidth = 'width';
|
||||||
|
const imageHeight = 'height';
|
||||||
|
const faceClusterId = 'cluster_id';
|
||||||
|
const mlVersionColumn = 'ml_version';
|
||||||
|
|
||||||
|
const createFacesTable = '''CREATE TABLE IF NOT EXISTS $facesTable (
|
||||||
|
$fileIDColumn INTEGER NOT NULL,
|
||||||
|
$faceIDColumn TEXT NOT NULL UNIQUE,
|
||||||
|
$faceDetectionColumn TEXT NOT NULL,
|
||||||
|
$faceEmbeddingBlob BLOB NOT NULL,
|
||||||
|
$faceScore REAL NOT NULL,
|
||||||
|
$faceBlur REAL NOT NULL DEFAULT $kLapacianDefault,
|
||||||
|
$isSideways INTEGER NOT NULL DEFAULT 0,
|
||||||
|
$imageHeight INTEGER NOT NULL DEFAULT 0,
|
||||||
|
$imageWidth INTEGER NOT NULL DEFAULT 0,
|
||||||
|
$mlVersionColumn INTEGER NOT NULL DEFAULT -1,
|
||||||
|
PRIMARY KEY($fileIDColumn, $faceIDColumn)
|
||||||
|
);
|
||||||
|
''';
|
||||||
|
|
||||||
|
const deleteFacesTable = 'DROP TABLE IF EXISTS $facesTable';
|
||||||
|
// End of Faces Table Fields & Schema Queries
|
||||||
|
|
||||||
|
//##region Face Clusters Table Fields & Schema Queries
|
||||||
|
const faceClustersTable = 'face_clusters';
|
||||||
|
const fcClusterID = 'cluster_id';
|
||||||
|
const fcFaceId = 'face_id';
|
||||||
|
|
||||||
|
// fcClusterId & fcFaceId are the primary keys and fcClusterId is a foreign key to faces table
|
||||||
|
const createFaceClustersTable = '''
|
||||||
|
CREATE TABLE IF NOT EXISTS $faceClustersTable (
|
||||||
|
$fcFaceId TEXT NOT NULL,
|
||||||
|
$fcClusterID INTEGER NOT NULL,
|
||||||
|
PRIMARY KEY($fcFaceId)
|
||||||
|
);
|
||||||
|
''';
|
||||||
|
// -- Creating a non-unique index on clusterID for query optimization
|
||||||
|
const fcClusterIDIndex =
|
||||||
|
'''CREATE INDEX IF NOT EXISTS idx_fcClusterID ON $faceClustersTable($fcClusterID);''';
|
||||||
|
const dropFaceClustersTable = 'DROP TABLE IF EXISTS $faceClustersTable';
|
||||||
|
//##endregion
|
||||||
|
|
||||||
|
// People Table Fields & Schema Queries
|
||||||
|
const personTable = 'person';
|
||||||
|
|
||||||
|
const deletePersonTable = 'DROP TABLE IF EXISTS $personTable';
|
||||||
|
//End People Table Fields & Schema Queries
|
||||||
|
|
||||||
|
// Clusters Table Fields & Schema Queries
|
||||||
|
const clusterPersonTable = 'cluster_person';
|
||||||
|
const personIdColumn = 'person_id';
|
||||||
|
const clusterIDColumn = 'cluster_id';
|
||||||
|
|
||||||
|
const createClusterPersonTable = '''
|
||||||
|
CREATE TABLE IF NOT EXISTS $clusterPersonTable (
|
||||||
|
$personIdColumn TEXT NOT NULL,
|
||||||
|
$clusterIDColumn INTEGER NOT NULL,
|
||||||
|
PRIMARY KEY($personIdColumn, $clusterIDColumn)
|
||||||
|
);
|
||||||
|
''';
|
||||||
|
const dropClusterPersonTable = 'DROP TABLE IF EXISTS $clusterPersonTable';
|
||||||
|
// End Clusters Table Fields & Schema Queries
|
||||||
|
|
||||||
|
/// Cluster Summary Table Fields & Schema Queries
|
||||||
|
const clusterSummaryTable = 'cluster_summary';
|
||||||
|
const avgColumn = 'avg';
|
||||||
|
const countColumn = 'count';
|
||||||
|
const createClusterSummaryTable = '''
|
||||||
|
CREATE TABLE IF NOT EXISTS $clusterSummaryTable (
|
||||||
|
$clusterIDColumn INTEGER NOT NULL,
|
||||||
|
$avgColumn BLOB NOT NULL,
|
||||||
|
$countColumn INTEGER NOT NULL,
|
||||||
|
PRIMARY KEY($clusterIDColumn)
|
||||||
|
);
|
||||||
|
''';
|
||||||
|
|
||||||
|
const dropClusterSummaryTable = 'DROP TABLE IF EXISTS $clusterSummaryTable';
|
||||||
|
|
||||||
|
/// End Cluster Summary Table Fields & Schema Queries
|
||||||
|
|
||||||
|
/// notPersonFeedback Table Fields & Schema Queries
|
||||||
|
const notPersonFeedback = 'not_person_feedback';
|
||||||
|
|
||||||
|
const createNotPersonFeedbackTable = '''
|
||||||
|
CREATE TABLE IF NOT EXISTS $notPersonFeedback (
|
||||||
|
$personIdColumn TEXT NOT NULL,
|
||||||
|
$clusterIDColumn INTEGER NOT NULL,
|
||||||
|
PRIMARY KEY($personIdColumn, $clusterIDColumn)
|
||||||
|
);
|
||||||
|
''';
|
||||||
|
const dropNotPersonFeedbackTable = 'DROP TABLE IF EXISTS $notPersonFeedback';
|
||||||
|
// End Clusters Table Fields & Schema Queries
|
57
mobile/lib/face/db_model_mappers.dart
Normal file
57
mobile/lib/face/db_model_mappers.dart
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
import "dart:convert";
|
||||||
|
|
||||||
|
import 'package:photos/face/db_fields.dart';
|
||||||
|
import "package:photos/face/model/detection.dart";
|
||||||
|
import "package:photos/face/model/face.dart";
|
||||||
|
import "package:photos/generated/protos/ente/common/vector.pb.dart";
|
||||||
|
import "package:photos/models/ml/ml_versions.dart";
|
||||||
|
|
||||||
|
int boolToSQLInt(bool? value, {bool defaultValue = false}) {
|
||||||
|
final bool v = value ?? defaultValue;
|
||||||
|
if (v == false) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool sqlIntToBool(int? value, {bool defaultValue = false}) {
|
||||||
|
final int v = value ?? (defaultValue ? 1 : 0);
|
||||||
|
if (v == 0) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> mapRemoteToFaceDB(Face face) {
|
||||||
|
return {
|
||||||
|
faceIDColumn: face.faceID,
|
||||||
|
fileIDColumn: face.fileID,
|
||||||
|
faceDetectionColumn: json.encode(face.detection.toJson()),
|
||||||
|
faceEmbeddingBlob: EVector(
|
||||||
|
values: face.embedding,
|
||||||
|
).writeToBuffer(),
|
||||||
|
faceScore: face.score,
|
||||||
|
faceBlur: face.blur,
|
||||||
|
isSideways: face.detection.faceIsSideways() ? 1 : 0,
|
||||||
|
mlVersionColumn: faceMlVersion,
|
||||||
|
imageWidth: face.fileInfo?.imageWidth ?? 0,
|
||||||
|
imageHeight: face.fileInfo?.imageHeight ?? 0,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
Face mapRowToFace(Map<String, dynamic> row) {
|
||||||
|
return Face(
|
||||||
|
row[faceIDColumn] as String,
|
||||||
|
row[fileIDColumn] as int,
|
||||||
|
EVector.fromBuffer(row[faceEmbeddingBlob] as List<int>).values,
|
||||||
|
row[faceScore] as double,
|
||||||
|
Detection.fromJson(json.decode(row[faceDetectionColumn] as String)),
|
||||||
|
row[faceBlur] as double,
|
||||||
|
fileInfo: FileInfo(
|
||||||
|
imageWidth: row[imageWidth] as int,
|
||||||
|
imageHeight: row[imageHeight] as int,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
43
mobile/lib/face/model/box.dart
Normal file
43
mobile/lib/face/model/box.dart
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
/// Bounding box of a face.
|
||||||
|
///
|
||||||
|
/// [xMin] and [yMin] are the coordinates of the top left corner of the box, and
|
||||||
|
/// [width] and [height] are the width and height of the box.
|
||||||
|
///
|
||||||
|
/// WARNING: All values are relative to the original image size, so in the range [0, 1].
|
||||||
|
class FaceBox {
|
||||||
|
final double xMin;
|
||||||
|
final double yMin;
|
||||||
|
final double width;
|
||||||
|
final double height;
|
||||||
|
|
||||||
|
FaceBox({
|
||||||
|
required this.xMin,
|
||||||
|
required this.yMin,
|
||||||
|
required this.width,
|
||||||
|
required this.height,
|
||||||
|
});
|
||||||
|
|
||||||
|
factory FaceBox.fromJson(Map<String, dynamic> json) {
|
||||||
|
return FaceBox(
|
||||||
|
xMin: (json['xMin'] is int
|
||||||
|
? (json['xMin'] as int).toDouble()
|
||||||
|
: json['xMin'] as double),
|
||||||
|
yMin: (json['yMin'] is int
|
||||||
|
? (json['yMin'] as int).toDouble()
|
||||||
|
: json['yMin'] as double),
|
||||||
|
width: (json['width'] is int
|
||||||
|
? (json['width'] as int).toDouble()
|
||||||
|
: json['width'] as double),
|
||||||
|
height: (json['height'] is int
|
||||||
|
? (json['height'] as int).toDouble()
|
||||||
|
: json['height'] as double),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() => {
|
||||||
|
'xMin': xMin,
|
||||||
|
'yMin': yMin,
|
||||||
|
'width': width,
|
||||||
|
'height': height,
|
||||||
|
};
|
||||||
|
}
|
120
mobile/lib/face/model/detection.dart
Normal file
120
mobile/lib/face/model/detection.dart
Normal file
|
@ -0,0 +1,120 @@
|
||||||
|
import "dart:math" show min, max;
|
||||||
|
|
||||||
|
import "package:photos/face/model/box.dart";
|
||||||
|
import "package:photos/face/model/landmark.dart";
|
||||||
|
import "package:photos/services/machine_learning/face_ml/face_detection/detection.dart";
|
||||||
|
|
||||||
|
/// Stores the face detection data, notably the bounding box and landmarks.
|
||||||
|
///
|
||||||
|
/// - Bounding box: [FaceBox] with xMin, yMin (so top left corner), width, height
|
||||||
|
/// - Landmarks: list of [Landmark]s, namely leftEye, rightEye, nose, leftMouth, rightMouth
|
||||||
|
///
|
||||||
|
/// WARNING: All coordinates are relative to the image size, so in the range [0, 1]!
|
||||||
|
class Detection {
|
||||||
|
FaceBox box;
|
||||||
|
List<Landmark> landmarks;
|
||||||
|
|
||||||
|
Detection({
|
||||||
|
required this.box,
|
||||||
|
required this.landmarks,
|
||||||
|
});
|
||||||
|
|
||||||
|
bool get isEmpty => box.width == 0 && box.height == 0 && landmarks.isEmpty;
|
||||||
|
|
||||||
|
// empty box
|
||||||
|
Detection.empty()
|
||||||
|
: box = FaceBox(
|
||||||
|
xMin: 0,
|
||||||
|
yMin: 0,
|
||||||
|
width: 0,
|
||||||
|
height: 0,
|
||||||
|
),
|
||||||
|
landmarks = [];
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() => {
|
||||||
|
'box': box.toJson(),
|
||||||
|
'landmarks': landmarks.map((x) => x.toJson()).toList(),
|
||||||
|
};
|
||||||
|
|
||||||
|
factory Detection.fromJson(Map<String, dynamic> json) {
|
||||||
|
return Detection(
|
||||||
|
box: FaceBox.fromJson(json['box'] as Map<String, dynamic>),
|
||||||
|
landmarks: List<Landmark>.from(
|
||||||
|
json['landmarks']
|
||||||
|
.map((x) => Landmark.fromJson(x as Map<String, dynamic>)),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
int getFaceArea(int imageWidth, int imageHeight) {
|
||||||
|
return (box.width * imageWidth * box.height * imageHeight).toInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
FaceDirection getFaceDirection() {
|
||||||
|
if (isEmpty) {
|
||||||
|
return FaceDirection.straight;
|
||||||
|
}
|
||||||
|
final leftEye = [landmarks[0].x, landmarks[0].y];
|
||||||
|
final rightEye = [landmarks[1].x, landmarks[1].y];
|
||||||
|
final nose = [landmarks[2].x, landmarks[2].y];
|
||||||
|
final leftMouth = [landmarks[3].x, landmarks[3].y];
|
||||||
|
final rightMouth = [landmarks[4].x, landmarks[4].y];
|
||||||
|
|
||||||
|
final double eyeDistanceX = (rightEye[0] - leftEye[0]).abs();
|
||||||
|
final double eyeDistanceY = (rightEye[1] - leftEye[1]).abs();
|
||||||
|
final double mouthDistanceY = (rightMouth[1] - leftMouth[1]).abs();
|
||||||
|
|
||||||
|
final bool faceIsUpright =
|
||||||
|
(max(leftEye[1], rightEye[1]) + 0.5 * eyeDistanceY < nose[1]) &&
|
||||||
|
(nose[1] + 0.5 * mouthDistanceY < min(leftMouth[1], rightMouth[1]));
|
||||||
|
|
||||||
|
final bool noseStickingOutLeft = (nose[0] < min(leftEye[0], rightEye[0])) &&
|
||||||
|
(nose[0] < min(leftMouth[0], rightMouth[0]));
|
||||||
|
final bool noseStickingOutRight =
|
||||||
|
(nose[0] > max(leftEye[0], rightEye[0])) &&
|
||||||
|
(nose[0] > max(leftMouth[0], rightMouth[0]));
|
||||||
|
|
||||||
|
final bool noseCloseToLeftEye =
|
||||||
|
(nose[0] - leftEye[0]).abs() < 0.2 * eyeDistanceX;
|
||||||
|
final bool noseCloseToRightEye =
|
||||||
|
(nose[0] - rightEye[0]).abs() < 0.2 * eyeDistanceX;
|
||||||
|
|
||||||
|
// if (faceIsUpright && (noseStickingOutLeft || noseCloseToLeftEye)) {
|
||||||
|
if (noseStickingOutLeft || (faceIsUpright && noseCloseToLeftEye)) {
|
||||||
|
return FaceDirection.left;
|
||||||
|
// } else if (faceIsUpright && (noseStickingOutRight || noseCloseToRightEye)) {
|
||||||
|
} else if (noseStickingOutRight || (faceIsUpright && noseCloseToRightEye)) {
|
||||||
|
return FaceDirection.right;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FaceDirection.straight;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool faceIsSideways() {
|
||||||
|
if (isEmpty) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
final leftEye = [landmarks[0].x, landmarks[0].y];
|
||||||
|
final rightEye = [landmarks[1].x, landmarks[1].y];
|
||||||
|
final nose = [landmarks[2].x, landmarks[2].y];
|
||||||
|
final leftMouth = [landmarks[3].x, landmarks[3].y];
|
||||||
|
final rightMouth = [landmarks[4].x, landmarks[4].y];
|
||||||
|
|
||||||
|
final double eyeDistanceX = (rightEye[0] - leftEye[0]).abs();
|
||||||
|
final double eyeDistanceY = (rightEye[1] - leftEye[1]).abs();
|
||||||
|
final double mouthDistanceY = (rightMouth[1] - leftMouth[1]).abs();
|
||||||
|
|
||||||
|
final bool faceIsUpright =
|
||||||
|
(max(leftEye[1], rightEye[1]) + 0.5 * eyeDistanceY < nose[1]) &&
|
||||||
|
(nose[1] + 0.5 * mouthDistanceY < min(leftMouth[1], rightMouth[1]));
|
||||||
|
|
||||||
|
final bool noseStickingOutLeft =
|
||||||
|
(nose[0] < min(leftEye[0], rightEye[0]) - 0.5 * eyeDistanceX) &&
|
||||||
|
(nose[0] < min(leftMouth[0], rightMouth[0]));
|
||||||
|
final bool noseStickingOutRight =
|
||||||
|
(nose[0] > max(leftEye[0], rightEye[0]) + 0.5 * eyeDistanceX) &&
|
||||||
|
(nose[0] > max(leftMouth[0], rightMouth[0]));
|
||||||
|
|
||||||
|
return faceIsUpright && (noseStickingOutLeft || noseStickingOutRight);
|
||||||
|
}
|
||||||
|
}
|
25
mobile/lib/face/model/dimension.dart
Normal file
25
mobile/lib/face/model/dimension.dart
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
class Dimensions {
|
||||||
|
final int width;
|
||||||
|
final int height;
|
||||||
|
|
||||||
|
const Dimensions({required this.width, required this.height});
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'Dimensions(width: $width, height: $height})';
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, int> toJson() {
|
||||||
|
return {
|
||||||
|
'width': width,
|
||||||
|
'height': height,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
factory Dimensions.fromJson(Map<String, dynamic> json) {
|
||||||
|
return Dimensions(
|
||||||
|
width: json['width'] as int,
|
||||||
|
height: json['height'] as int,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
85
mobile/lib/face/model/face.dart
Normal file
85
mobile/lib/face/model/face.dart
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
import "package:photos/face/model/detection.dart";
|
||||||
|
import 'package:photos/services/machine_learning/face_ml/face_filtering/face_filtering_constants.dart';
|
||||||
|
import "package:photos/services/machine_learning/face_ml/face_ml_result.dart";
|
||||||
|
|
||||||
|
// FileInfo contains the image width and height of the image the face was detected in.
|
||||||
|
class FileInfo {
|
||||||
|
int? imageWidth;
|
||||||
|
int? imageHeight;
|
||||||
|
FileInfo({
|
||||||
|
this.imageWidth,
|
||||||
|
this.imageHeight,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
class Face {
|
||||||
|
final String faceID;
|
||||||
|
final List<double> embedding;
|
||||||
|
Detection detection;
|
||||||
|
final double score;
|
||||||
|
final double blur;
|
||||||
|
|
||||||
|
///#region Local DB fields
|
||||||
|
// This is not stored on the server, using it for local DB row
|
||||||
|
FileInfo? fileInfo;
|
||||||
|
final int fileID;
|
||||||
|
///#endregion
|
||||||
|
|
||||||
|
bool get isBlurry => blur < kLaplacianHardThreshold;
|
||||||
|
|
||||||
|
bool get hasHighScore => score > kMinimumQualityFaceScore;
|
||||||
|
|
||||||
|
bool get isHighQuality => (!isBlurry) && hasHighScore;
|
||||||
|
|
||||||
|
int area({int? w, int? h}) {
|
||||||
|
return detection.getFaceArea(
|
||||||
|
fileInfo?.imageWidth ?? w ?? 0,
|
||||||
|
fileInfo?.imageHeight ?? h ?? 0,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Face(
|
||||||
|
this.faceID,
|
||||||
|
this.fileID,
|
||||||
|
this.embedding,
|
||||||
|
this.score,
|
||||||
|
this.detection,
|
||||||
|
this.blur, {
|
||||||
|
this.fileInfo,
|
||||||
|
});
|
||||||
|
|
||||||
|
factory Face.empty(int fileID, {bool error = false}) {
|
||||||
|
return Face(
|
||||||
|
"$fileID-0",
|
||||||
|
fileID,
|
||||||
|
<double>[],
|
||||||
|
error ? -1.0 : 0.0,
|
||||||
|
Detection.empty(),
|
||||||
|
0.0,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
factory Face.fromJson(Map<String, dynamic> json) {
|
||||||
|
final String faceID = json['faceID'] as String;
|
||||||
|
final int fileID = getFileIdFromFaceId(faceID);
|
||||||
|
return Face(
|
||||||
|
faceID,
|
||||||
|
fileID,
|
||||||
|
List<double>.from((json['embedding'] ?? json['embeddings']) as List),
|
||||||
|
json['score'] as double,
|
||||||
|
Detection.fromJson(json['detection'] as Map<String, dynamic>),
|
||||||
|
// high value means t
|
||||||
|
(json['blur'] ?? kLapacianDefault) as double,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note: Keep the information in toJson minimum. Keep in sync with desktop.
|
||||||
|
// Derive fields like fileID from other values whenever possible
|
||||||
|
Map<String, dynamic> toJson() => {
|
||||||
|
'faceID': faceID,
|
||||||
|
'embedding': embedding,
|
||||||
|
'detection': detection.toJson(),
|
||||||
|
'score': score,
|
||||||
|
'blur': blur,
|
||||||
|
};
|
||||||
|
}
|
33
mobile/lib/face/model/landmark.dart
Normal file
33
mobile/lib/face/model/landmark.dart
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
/// Landmark coordinate data.
|
||||||
|
///
|
||||||
|
/// WARNING: All coordinates are relative to the image size, so in the range [0, 1]!
|
||||||
|
class Landmark {
|
||||||
|
double x;
|
||||||
|
double y;
|
||||||
|
|
||||||
|
Landmark({
|
||||||
|
required this.x,
|
||||||
|
required this.y,
|
||||||
|
});
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() => {
|
||||||
|
'x': x,
|
||||||
|
'y': y,
|
||||||
|
};
|
||||||
|
|
||||||
|
factory Landmark.fromJson(Map<String, dynamic> json) {
|
||||||
|
return Landmark(
|
||||||
|
x: (json['x'] is int
|
||||||
|
? (json['x'] as int).toDouble()
|
||||||
|
: json['x'] as double),
|
||||||
|
y: (json['y'] is int
|
||||||
|
? (json['y'] as int).toDouble()
|
||||||
|
: json['y'] as double),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
toString() {
|
||||||
|
return '(x: ${x.toStringAsFixed(4)}, y: ${y.toStringAsFixed(4)})';
|
||||||
|
}
|
||||||
|
}
|
139
mobile/lib/face/model/person.dart
Normal file
139
mobile/lib/face/model/person.dart
Normal file
|
@ -0,0 +1,139 @@
|
||||||
|
// PersonEntity represents information about a Person in the context of FaceClustering that is stored.
|
||||||
|
// On the remote server, the PersonEntity is stored as {Entity} with type person.
|
||||||
|
// On the device, this information is stored as [LocalEntityData] with type person.
|
||||||
|
import "package:flutter/foundation.dart";
|
||||||
|
|
||||||
|
class PersonEntity {
|
||||||
|
final String remoteID;
|
||||||
|
final PersonData data;
|
||||||
|
PersonEntity(
|
||||||
|
this.remoteID,
|
||||||
|
this.data,
|
||||||
|
);
|
||||||
|
|
||||||
|
// copyWith
|
||||||
|
PersonEntity copyWith({
|
||||||
|
String? remoteID,
|
||||||
|
PersonData? data,
|
||||||
|
}) {
|
||||||
|
return PersonEntity(
|
||||||
|
remoteID ?? this.remoteID,
|
||||||
|
data ?? this.data,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ClusterInfo {
|
||||||
|
final int id;
|
||||||
|
final Set<String> faces;
|
||||||
|
ClusterInfo({
|
||||||
|
required this.id,
|
||||||
|
required this.faces,
|
||||||
|
});
|
||||||
|
|
||||||
|
// toJson
|
||||||
|
Map<String, dynamic> toJson() => {
|
||||||
|
'id': id,
|
||||||
|
'faces': faces.toList(),
|
||||||
|
};
|
||||||
|
|
||||||
|
// from Json
|
||||||
|
factory ClusterInfo.fromJson(Map<String, dynamic> json) {
|
||||||
|
return ClusterInfo(
|
||||||
|
id: json['id'] as int,
|
||||||
|
faces: (json['faces'] as List<dynamic>).map((e) => e as String).toSet(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class PersonData {
|
||||||
|
final String name;
|
||||||
|
final bool isHidden;
|
||||||
|
String? avatarFaceId;
|
||||||
|
List<ClusterInfo>? assigned = List<ClusterInfo>.empty();
|
||||||
|
List<ClusterInfo>? rejected = List<ClusterInfo>.empty();
|
||||||
|
final String? birthDate;
|
||||||
|
|
||||||
|
bool hasAvatar() => avatarFaceId != null;
|
||||||
|
|
||||||
|
bool get isIgnored =>
|
||||||
|
(name.isEmpty || name == '(hidden)' || name == '(ignored)');
|
||||||
|
|
||||||
|
PersonData({
|
||||||
|
required this.name,
|
||||||
|
this.assigned,
|
||||||
|
this.rejected,
|
||||||
|
this.avatarFaceId,
|
||||||
|
this.isHidden = false,
|
||||||
|
this.birthDate,
|
||||||
|
});
|
||||||
|
// copyWith
|
||||||
|
PersonData copyWith({
|
||||||
|
String? name,
|
||||||
|
List<ClusterInfo>? assigned,
|
||||||
|
String? avatarFaceId,
|
||||||
|
bool? isHidden,
|
||||||
|
int? version,
|
||||||
|
String? birthDate,
|
||||||
|
}) {
|
||||||
|
return PersonData(
|
||||||
|
name: name ?? this.name,
|
||||||
|
assigned: assigned ?? this.assigned,
|
||||||
|
avatarFaceId: avatarFaceId ?? this.avatarFaceId,
|
||||||
|
isHidden: isHidden ?? this.isHidden,
|
||||||
|
birthDate: birthDate ?? this.birthDate,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void logStats() {
|
||||||
|
if (kDebugMode == false) return;
|
||||||
|
// log number of assigned and rejected clusters and total number of faces in each cluster
|
||||||
|
final StringBuffer sb = StringBuffer();
|
||||||
|
sb.writeln('Person: $name');
|
||||||
|
int assignedCount = 0;
|
||||||
|
for (final a in (assigned ?? <ClusterInfo>[])) {
|
||||||
|
assignedCount += a.faces.length;
|
||||||
|
}
|
||||||
|
sb.writeln('Assigned: ${assigned?.length} withFaces $assignedCount');
|
||||||
|
sb.writeln('Rejected: ${rejected?.length}');
|
||||||
|
if (assigned != null) {
|
||||||
|
for (var cluster in assigned!) {
|
||||||
|
sb.writeln('Cluster: ${cluster.id} - ${cluster.faces.length}');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
debugPrint(sb.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
// toJson
|
||||||
|
Map<String, dynamic> toJson() => {
|
||||||
|
'name': name,
|
||||||
|
'assigned': assigned?.map((e) => e.toJson()).toList(),
|
||||||
|
'rejected': rejected?.map((e) => e.toJson()).toList(),
|
||||||
|
'avatarFaceId': avatarFaceId,
|
||||||
|
'isHidden': isHidden,
|
||||||
|
'birthDate': birthDate,
|
||||||
|
};
|
||||||
|
|
||||||
|
// fromJson
|
||||||
|
factory PersonData.fromJson(Map<String, dynamic> json) {
|
||||||
|
final assigned = (json['assigned'] == null || json['assigned'].length == 0)
|
||||||
|
? <ClusterInfo>[]
|
||||||
|
: List<ClusterInfo>.from(
|
||||||
|
json['assigned'].map((x) => ClusterInfo.fromJson(x)),
|
||||||
|
);
|
||||||
|
|
||||||
|
final rejected = (json['rejected'] == null || json['rejected'].length == 0)
|
||||||
|
? <ClusterInfo>[]
|
||||||
|
: List<ClusterInfo>.from(
|
||||||
|
json['rejected'].map((x) => ClusterInfo.fromJson(x)),
|
||||||
|
);
|
||||||
|
return PersonData(
|
||||||
|
name: json['name'] as String,
|
||||||
|
assigned: assigned,
|
||||||
|
rejected: rejected,
|
||||||
|
avatarFaceId: json['avatarFaceId'] as String?,
|
||||||
|
isHidden: json['isHidden'] as bool? ?? false,
|
||||||
|
birthDate: json['birthDate'] as String?,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
11
mobile/lib/generated/intl/messages_cs.dart
generated
11
mobile/lib/generated/intl/messages_cs.dart
generated
|
@ -34,6 +34,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||||
"addViewers": m1,
|
"addViewers": m1,
|
||||||
"changeLocationOfSelectedItems": MessageLookupByLibrary.simpleMessage(
|
"changeLocationOfSelectedItems": MessageLookupByLibrary.simpleMessage(
|
||||||
"Change location of selected items?"),
|
"Change location of selected items?"),
|
||||||
|
"clusteringProgress":
|
||||||
|
MessageLookupByLibrary.simpleMessage("Clustering progress"),
|
||||||
"contacts": MessageLookupByLibrary.simpleMessage("Contacts"),
|
"contacts": MessageLookupByLibrary.simpleMessage("Contacts"),
|
||||||
"createCollaborativeLink":
|
"createCollaborativeLink":
|
||||||
MessageLookupByLibrary.simpleMessage("Create collaborative link"),
|
MessageLookupByLibrary.simpleMessage("Create collaborative link"),
|
||||||
|
@ -44,7 +46,14 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||||
"editsToLocationWillOnlyBeSeenWithinEnte":
|
"editsToLocationWillOnlyBeSeenWithinEnte":
|
||||||
MessageLookupByLibrary.simpleMessage(
|
MessageLookupByLibrary.simpleMessage(
|
||||||
"Edits to location will only be seen within Ente"),
|
"Edits to location will only be seen within Ente"),
|
||||||
|
"enterPersonName":
|
||||||
|
MessageLookupByLibrary.simpleMessage("Enter person name"),
|
||||||
|
"faceRecognition":
|
||||||
|
MessageLookupByLibrary.simpleMessage("Face recognition"),
|
||||||
|
"faceRecognitionIndexingDescription": MessageLookupByLibrary.simpleMessage(
|
||||||
|
"Please note that this will result in a higher bandwidth and battery usage until all items are indexed."),
|
||||||
"fileTypes": MessageLookupByLibrary.simpleMessage("File types"),
|
"fileTypes": MessageLookupByLibrary.simpleMessage("File types"),
|
||||||
|
"foundFaces": MessageLookupByLibrary.simpleMessage("Found faces"),
|
||||||
"joinDiscord": MessageLookupByLibrary.simpleMessage("Join Discord"),
|
"joinDiscord": MessageLookupByLibrary.simpleMessage("Join Discord"),
|
||||||
"locations": MessageLookupByLibrary.simpleMessage("Locations"),
|
"locations": MessageLookupByLibrary.simpleMessage("Locations"),
|
||||||
"longPressAnEmailToVerifyEndToEndEncryption":
|
"longPressAnEmailToVerifyEndToEndEncryption":
|
||||||
|
@ -55,6 +64,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||||
"Modify your query, or try searching for"),
|
"Modify your query, or try searching for"),
|
||||||
"moveToHiddenAlbum":
|
"moveToHiddenAlbum":
|
||||||
MessageLookupByLibrary.simpleMessage("Move to hidden album"),
|
MessageLookupByLibrary.simpleMessage("Move to hidden album"),
|
||||||
|
"removePersonLabel":
|
||||||
|
MessageLookupByLibrary.simpleMessage("Remove person label"),
|
||||||
"search": MessageLookupByLibrary.simpleMessage("Search"),
|
"search": MessageLookupByLibrary.simpleMessage("Search"),
|
||||||
"selectALocation":
|
"selectALocation":
|
||||||
MessageLookupByLibrary.simpleMessage("Select a location"),
|
MessageLookupByLibrary.simpleMessage("Select a location"),
|
||||||
|
|
14
mobile/lib/generated/intl/messages_de.dart
generated
14
mobile/lib/generated/intl/messages_de.dart
generated
|
@ -227,6 +227,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||||
"Ich verstehe, dass ich meine Daten verlieren kann, wenn ich mein Passwort vergesse, da meine Daten <underline>Ende-zu-Ende-verschlüsselt</underline> sind."),
|
"Ich verstehe, dass ich meine Daten verlieren kann, wenn ich mein Passwort vergesse, da meine Daten <underline>Ende-zu-Ende-verschlüsselt</underline> sind."),
|
||||||
"activeSessions":
|
"activeSessions":
|
||||||
MessageLookupByLibrary.simpleMessage("Aktive Sitzungen"),
|
MessageLookupByLibrary.simpleMessage("Aktive Sitzungen"),
|
||||||
|
"addAName": MessageLookupByLibrary.simpleMessage("Add a name"),
|
||||||
"addANewEmail": MessageLookupByLibrary.simpleMessage(
|
"addANewEmail": MessageLookupByLibrary.simpleMessage(
|
||||||
"Neue E-Mail-Adresse hinzufügen"),
|
"Neue E-Mail-Adresse hinzufügen"),
|
||||||
"addCollaborator":
|
"addCollaborator":
|
||||||
|
@ -435,6 +436,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||||
"Nach Aufnahmezeit gruppieren"),
|
"Nach Aufnahmezeit gruppieren"),
|
||||||
"clubByFileName":
|
"clubByFileName":
|
||||||
MessageLookupByLibrary.simpleMessage("Nach Dateiname gruppieren"),
|
MessageLookupByLibrary.simpleMessage("Nach Dateiname gruppieren"),
|
||||||
|
"clusteringProgress":
|
||||||
|
MessageLookupByLibrary.simpleMessage("Clustering progress"),
|
||||||
"codeAppliedPageTitle":
|
"codeAppliedPageTitle":
|
||||||
MessageLookupByLibrary.simpleMessage("Code eingelöst"),
|
MessageLookupByLibrary.simpleMessage("Code eingelöst"),
|
||||||
"codeCopiedToClipboard": MessageLookupByLibrary.simpleMessage(
|
"codeCopiedToClipboard": MessageLookupByLibrary.simpleMessage(
|
||||||
|
@ -675,6 +678,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||||
MessageLookupByLibrary.simpleMessage("Passwort eingeben"),
|
MessageLookupByLibrary.simpleMessage("Passwort eingeben"),
|
||||||
"enterPasswordToEncrypt": MessageLookupByLibrary.simpleMessage(
|
"enterPasswordToEncrypt": MessageLookupByLibrary.simpleMessage(
|
||||||
"Gib ein Passwort ein, mit dem wir deine Daten verschlüsseln können"),
|
"Gib ein Passwort ein, mit dem wir deine Daten verschlüsseln können"),
|
||||||
|
"enterPersonName":
|
||||||
|
MessageLookupByLibrary.simpleMessage("Enter person name"),
|
||||||
"enterReferralCode": MessageLookupByLibrary.simpleMessage(
|
"enterReferralCode": MessageLookupByLibrary.simpleMessage(
|
||||||
"Gib den Weiterempfehlungs-Code ein"),
|
"Gib den Weiterempfehlungs-Code ein"),
|
||||||
"enterThe6digitCodeFromnyourAuthenticatorApp":
|
"enterThe6digitCodeFromnyourAuthenticatorApp":
|
||||||
|
@ -699,6 +704,10 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||||
MessageLookupByLibrary.simpleMessage("Protokolle exportieren"),
|
MessageLookupByLibrary.simpleMessage("Protokolle exportieren"),
|
||||||
"exportYourData":
|
"exportYourData":
|
||||||
MessageLookupByLibrary.simpleMessage("Daten exportieren"),
|
MessageLookupByLibrary.simpleMessage("Daten exportieren"),
|
||||||
|
"faceRecognition":
|
||||||
|
MessageLookupByLibrary.simpleMessage("Face recognition"),
|
||||||
|
"faceRecognitionIndexingDescription": MessageLookupByLibrary.simpleMessage(
|
||||||
|
"Please note that this will result in a higher bandwidth and battery usage until all items are indexed."),
|
||||||
"faces": MessageLookupByLibrary.simpleMessage("Gesichter"),
|
"faces": MessageLookupByLibrary.simpleMessage("Gesichter"),
|
||||||
"failedToApplyCode": MessageLookupByLibrary.simpleMessage(
|
"failedToApplyCode": MessageLookupByLibrary.simpleMessage(
|
||||||
"Der Code konnte nicht aktiviert werden"),
|
"Der Code konnte nicht aktiviert werden"),
|
||||||
|
@ -738,11 +747,14 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||||
"filesBackedUpInAlbum": m23,
|
"filesBackedUpInAlbum": m23,
|
||||||
"filesDeleted":
|
"filesDeleted":
|
||||||
MessageLookupByLibrary.simpleMessage("Dateien gelöscht"),
|
MessageLookupByLibrary.simpleMessage("Dateien gelöscht"),
|
||||||
|
"findPeopleByName": MessageLookupByLibrary.simpleMessage(
|
||||||
|
"Find people quickly by searching by name"),
|
||||||
"flip": MessageLookupByLibrary.simpleMessage("Spiegeln"),
|
"flip": MessageLookupByLibrary.simpleMessage("Spiegeln"),
|
||||||
"forYourMemories":
|
"forYourMemories":
|
||||||
MessageLookupByLibrary.simpleMessage("Als Erinnerung"),
|
MessageLookupByLibrary.simpleMessage("Als Erinnerung"),
|
||||||
"forgotPassword":
|
"forgotPassword":
|
||||||
MessageLookupByLibrary.simpleMessage("Passwort vergessen"),
|
MessageLookupByLibrary.simpleMessage("Passwort vergessen"),
|
||||||
|
"foundFaces": MessageLookupByLibrary.simpleMessage("Found faces"),
|
||||||
"freeStorageClaimed": MessageLookupByLibrary.simpleMessage(
|
"freeStorageClaimed": MessageLookupByLibrary.simpleMessage(
|
||||||
"Kostenlos hinzugefügter Speicherplatz"),
|
"Kostenlos hinzugefügter Speicherplatz"),
|
||||||
"freeStorageOnReferralSuccess": m24,
|
"freeStorageOnReferralSuccess": m24,
|
||||||
|
@ -1164,6 +1176,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||||
"removeParticipant":
|
"removeParticipant":
|
||||||
MessageLookupByLibrary.simpleMessage("Teilnehmer entfernen"),
|
MessageLookupByLibrary.simpleMessage("Teilnehmer entfernen"),
|
||||||
"removeParticipantBody": m43,
|
"removeParticipantBody": m43,
|
||||||
|
"removePersonLabel":
|
||||||
|
MessageLookupByLibrary.simpleMessage("Remove person label"),
|
||||||
"removePublicLink":
|
"removePublicLink":
|
||||||
MessageLookupByLibrary.simpleMessage("Öffentlichen Link entfernen"),
|
MessageLookupByLibrary.simpleMessage("Öffentlichen Link entfernen"),
|
||||||
"removeShareItemsWarning": MessageLookupByLibrary.simpleMessage(
|
"removeShareItemsWarning": MessageLookupByLibrary.simpleMessage(
|
||||||
|
|
21
mobile/lib/generated/intl/messages_en.dart
generated
21
mobile/lib/generated/intl/messages_en.dart
generated
|
@ -132,7 +132,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||||
"Please talk to ${providerName} support if you were charged";
|
"Please talk to ${providerName} support if you were charged";
|
||||||
|
|
||||||
static String m38(endDate) =>
|
static String m38(endDate) =>
|
||||||
"Free trial valid till ${endDate}.\nYou can purchase a paid plan afterwards.";
|
"Free trial valid till ${endDate}.\nYou can choose a paid plan afterwards.";
|
||||||
|
|
||||||
static String m39(toEmail) => "Please email us at ${toEmail}";
|
static String m39(toEmail) => "Please email us at ${toEmail}";
|
||||||
|
|
||||||
|
@ -225,6 +225,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||||
"I understand that if I lose my password, I may lose my data since my data is <underline>end-to-end encrypted</underline>."),
|
"I understand that if I lose my password, I may lose my data since my data is <underline>end-to-end encrypted</underline>."),
|
||||||
"activeSessions":
|
"activeSessions":
|
||||||
MessageLookupByLibrary.simpleMessage("Active sessions"),
|
MessageLookupByLibrary.simpleMessage("Active sessions"),
|
||||||
|
"addAName": MessageLookupByLibrary.simpleMessage("Add a name"),
|
||||||
"addANewEmail": MessageLookupByLibrary.simpleMessage("Add a new email"),
|
"addANewEmail": MessageLookupByLibrary.simpleMessage("Add a new email"),
|
||||||
"addCollaborator":
|
"addCollaborator":
|
||||||
MessageLookupByLibrary.simpleMessage("Add collaborator"),
|
MessageLookupByLibrary.simpleMessage("Add collaborator"),
|
||||||
|
@ -434,6 +435,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||||
MessageLookupByLibrary.simpleMessage("Club by capture time"),
|
MessageLookupByLibrary.simpleMessage("Club by capture time"),
|
||||||
"clubByFileName":
|
"clubByFileName":
|
||||||
MessageLookupByLibrary.simpleMessage("Club by file name"),
|
MessageLookupByLibrary.simpleMessage("Club by file name"),
|
||||||
|
"clusteringProgress":
|
||||||
|
MessageLookupByLibrary.simpleMessage("Clustering progress"),
|
||||||
"codeAppliedPageTitle":
|
"codeAppliedPageTitle":
|
||||||
MessageLookupByLibrary.simpleMessage("Code applied"),
|
MessageLookupByLibrary.simpleMessage("Code applied"),
|
||||||
"codeCopiedToClipboard":
|
"codeCopiedToClipboard":
|
||||||
|
@ -675,6 +678,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||||
"enterPassword": MessageLookupByLibrary.simpleMessage("Enter password"),
|
"enterPassword": MessageLookupByLibrary.simpleMessage("Enter password"),
|
||||||
"enterPasswordToEncrypt": MessageLookupByLibrary.simpleMessage(
|
"enterPasswordToEncrypt": MessageLookupByLibrary.simpleMessage(
|
||||||
"Enter a password we can use to encrypt your data"),
|
"Enter a password we can use to encrypt your data"),
|
||||||
|
"enterPersonName":
|
||||||
|
MessageLookupByLibrary.simpleMessage("Enter person name"),
|
||||||
"enterReferralCode":
|
"enterReferralCode":
|
||||||
MessageLookupByLibrary.simpleMessage("Enter referral code"),
|
MessageLookupByLibrary.simpleMessage("Enter referral code"),
|
||||||
"enterThe6digitCodeFromnyourAuthenticatorApp":
|
"enterThe6digitCodeFromnyourAuthenticatorApp":
|
||||||
|
@ -697,6 +702,10 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||||
"exportLogs": MessageLookupByLibrary.simpleMessage("Export logs"),
|
"exportLogs": MessageLookupByLibrary.simpleMessage("Export logs"),
|
||||||
"exportYourData":
|
"exportYourData":
|
||||||
MessageLookupByLibrary.simpleMessage("Export your data"),
|
MessageLookupByLibrary.simpleMessage("Export your data"),
|
||||||
|
"faceRecognition":
|
||||||
|
MessageLookupByLibrary.simpleMessage("Face recognition"),
|
||||||
|
"faceRecognitionIndexingDescription": MessageLookupByLibrary.simpleMessage(
|
||||||
|
"Please note that this will result in a higher bandwidth and battery usage until all items are indexed."),
|
||||||
"faces": MessageLookupByLibrary.simpleMessage("Faces"),
|
"faces": MessageLookupByLibrary.simpleMessage("Faces"),
|
||||||
"failedToApplyCode":
|
"failedToApplyCode":
|
||||||
MessageLookupByLibrary.simpleMessage("Failed to apply code"),
|
MessageLookupByLibrary.simpleMessage("Failed to apply code"),
|
||||||
|
@ -736,11 +745,14 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||||
"filesDeleted": MessageLookupByLibrary.simpleMessage("Files deleted"),
|
"filesDeleted": MessageLookupByLibrary.simpleMessage("Files deleted"),
|
||||||
"filesSavedToGallery":
|
"filesSavedToGallery":
|
||||||
MessageLookupByLibrary.simpleMessage("Files saved to gallery"),
|
MessageLookupByLibrary.simpleMessage("Files saved to gallery"),
|
||||||
|
"findPeopleByName":
|
||||||
|
MessageLookupByLibrary.simpleMessage("Find people quickly by name"),
|
||||||
"flip": MessageLookupByLibrary.simpleMessage("Flip"),
|
"flip": MessageLookupByLibrary.simpleMessage("Flip"),
|
||||||
"forYourMemories":
|
"forYourMemories":
|
||||||
MessageLookupByLibrary.simpleMessage("for your memories"),
|
MessageLookupByLibrary.simpleMessage("for your memories"),
|
||||||
"forgotPassword":
|
"forgotPassword":
|
||||||
MessageLookupByLibrary.simpleMessage("Forgot password"),
|
MessageLookupByLibrary.simpleMessage("Forgot password"),
|
||||||
|
"foundFaces": MessageLookupByLibrary.simpleMessage("Found faces"),
|
||||||
"freeStorageClaimed":
|
"freeStorageClaimed":
|
||||||
MessageLookupByLibrary.simpleMessage("Free storage claimed"),
|
MessageLookupByLibrary.simpleMessage("Free storage claimed"),
|
||||||
"freeStorageOnReferralSuccess": m24,
|
"freeStorageOnReferralSuccess": m24,
|
||||||
|
@ -1022,6 +1034,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||||
"paymentFailedTalkToProvider": m37,
|
"paymentFailedTalkToProvider": m37,
|
||||||
"pendingItems": MessageLookupByLibrary.simpleMessage("Pending items"),
|
"pendingItems": MessageLookupByLibrary.simpleMessage("Pending items"),
|
||||||
"pendingSync": MessageLookupByLibrary.simpleMessage("Pending sync"),
|
"pendingSync": MessageLookupByLibrary.simpleMessage("Pending sync"),
|
||||||
|
"people": MessageLookupByLibrary.simpleMessage("People"),
|
||||||
"peopleUsingYourCode":
|
"peopleUsingYourCode":
|
||||||
MessageLookupByLibrary.simpleMessage("People using your code"),
|
MessageLookupByLibrary.simpleMessage("People using your code"),
|
||||||
"permDeleteWarning": MessageLookupByLibrary.simpleMessage(
|
"permDeleteWarning": MessageLookupByLibrary.simpleMessage(
|
||||||
|
@ -1151,6 +1164,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||||
"removeParticipant":
|
"removeParticipant":
|
||||||
MessageLookupByLibrary.simpleMessage("Remove participant"),
|
MessageLookupByLibrary.simpleMessage("Remove participant"),
|
||||||
"removeParticipantBody": m43,
|
"removeParticipantBody": m43,
|
||||||
|
"removePersonLabel":
|
||||||
|
MessageLookupByLibrary.simpleMessage("Remove person label"),
|
||||||
"removePublicLink":
|
"removePublicLink":
|
||||||
MessageLookupByLibrary.simpleMessage("Remove public link"),
|
MessageLookupByLibrary.simpleMessage("Remove public link"),
|
||||||
"removeShareItemsWarning": MessageLookupByLibrary.simpleMessage(
|
"removeShareItemsWarning": MessageLookupByLibrary.simpleMessage(
|
||||||
|
@ -1208,8 +1223,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||||
"Add descriptions like \"#trip\" in photo info to quickly find them here"),
|
"Add descriptions like \"#trip\" in photo info to quickly find them here"),
|
||||||
"searchDatesEmptySection": MessageLookupByLibrary.simpleMessage(
|
"searchDatesEmptySection": MessageLookupByLibrary.simpleMessage(
|
||||||
"Search by a date, month or year"),
|
"Search by a date, month or year"),
|
||||||
"searchFaceEmptySection":
|
"searchFaceEmptySection": MessageLookupByLibrary.simpleMessage(
|
||||||
MessageLookupByLibrary.simpleMessage("Find all photos of a person"),
|
"Persons will be shown here once indexing is done"),
|
||||||
"searchFileTypesAndNamesEmptySection":
|
"searchFileTypesAndNamesEmptySection":
|
||||||
MessageLookupByLibrary.simpleMessage("File types and names"),
|
MessageLookupByLibrary.simpleMessage("File types and names"),
|
||||||
"searchHint1":
|
"searchHint1":
|
||||||
|
|
11
mobile/lib/generated/intl/messages_es.dart
generated
11
mobile/lib/generated/intl/messages_es.dart
generated
|
@ -367,6 +367,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||||
"close": MessageLookupByLibrary.simpleMessage("Cerrar"),
|
"close": MessageLookupByLibrary.simpleMessage("Cerrar"),
|
||||||
"clubByCaptureTime": MessageLookupByLibrary.simpleMessage(
|
"clubByCaptureTime": MessageLookupByLibrary.simpleMessage(
|
||||||
"Agrupar por tiempo de captura"),
|
"Agrupar por tiempo de captura"),
|
||||||
|
"clusteringProgress":
|
||||||
|
MessageLookupByLibrary.simpleMessage("Clustering progress"),
|
||||||
"codeAppliedPageTitle":
|
"codeAppliedPageTitle":
|
||||||
MessageLookupByLibrary.simpleMessage("Código aplicado"),
|
MessageLookupByLibrary.simpleMessage("Código aplicado"),
|
||||||
"codeCopiedToClipboard": MessageLookupByLibrary.simpleMessage(
|
"codeCopiedToClipboard": MessageLookupByLibrary.simpleMessage(
|
||||||
|
@ -585,6 +587,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||||
MessageLookupByLibrary.simpleMessage("Introduzca contraseña"),
|
MessageLookupByLibrary.simpleMessage("Introduzca contraseña"),
|
||||||
"enterPasswordToEncrypt": MessageLookupByLibrary.simpleMessage(
|
"enterPasswordToEncrypt": MessageLookupByLibrary.simpleMessage(
|
||||||
"Introduzca una contraseña que podamos usar para cifrar sus datos"),
|
"Introduzca una contraseña que podamos usar para cifrar sus datos"),
|
||||||
|
"enterPersonName":
|
||||||
|
MessageLookupByLibrary.simpleMessage("Enter person name"),
|
||||||
"enterReferralCode": MessageLookupByLibrary.simpleMessage(
|
"enterReferralCode": MessageLookupByLibrary.simpleMessage(
|
||||||
"Ingresar código de referencia"),
|
"Ingresar código de referencia"),
|
||||||
"enterThe6digitCodeFromnyourAuthenticatorApp":
|
"enterThe6digitCodeFromnyourAuthenticatorApp":
|
||||||
|
@ -609,6 +613,10 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||||
MessageLookupByLibrary.simpleMessage("Exportar registros"),
|
MessageLookupByLibrary.simpleMessage("Exportar registros"),
|
||||||
"exportYourData":
|
"exportYourData":
|
||||||
MessageLookupByLibrary.simpleMessage("Exportar tus datos"),
|
MessageLookupByLibrary.simpleMessage("Exportar tus datos"),
|
||||||
|
"faceRecognition":
|
||||||
|
MessageLookupByLibrary.simpleMessage("Face recognition"),
|
||||||
|
"faceRecognitionIndexingDescription": MessageLookupByLibrary.simpleMessage(
|
||||||
|
"Please note that this will result in a higher bandwidth and battery usage until all items are indexed."),
|
||||||
"failedToApplyCode":
|
"failedToApplyCode":
|
||||||
MessageLookupByLibrary.simpleMessage("Error al aplicar el código"),
|
MessageLookupByLibrary.simpleMessage("Error al aplicar el código"),
|
||||||
"failedToCancel":
|
"failedToCancel":
|
||||||
|
@ -647,6 +655,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||||
MessageLookupByLibrary.simpleMessage("para tus recuerdos"),
|
MessageLookupByLibrary.simpleMessage("para tus recuerdos"),
|
||||||
"forgotPassword":
|
"forgotPassword":
|
||||||
MessageLookupByLibrary.simpleMessage("Olvidé mi contraseña"),
|
MessageLookupByLibrary.simpleMessage("Olvidé mi contraseña"),
|
||||||
|
"foundFaces": MessageLookupByLibrary.simpleMessage("Found faces"),
|
||||||
"freeStorageClaimed": MessageLookupByLibrary.simpleMessage(
|
"freeStorageClaimed": MessageLookupByLibrary.simpleMessage(
|
||||||
"Almacenamiento gratuito reclamado"),
|
"Almacenamiento gratuito reclamado"),
|
||||||
"freeStorageOnReferralSuccess": m24,
|
"freeStorageOnReferralSuccess": m24,
|
||||||
|
@ -997,6 +1006,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||||
"removeParticipant":
|
"removeParticipant":
|
||||||
MessageLookupByLibrary.simpleMessage("Quitar participante"),
|
MessageLookupByLibrary.simpleMessage("Quitar participante"),
|
||||||
"removeParticipantBody": m43,
|
"removeParticipantBody": m43,
|
||||||
|
"removePersonLabel":
|
||||||
|
MessageLookupByLibrary.simpleMessage("Remove person label"),
|
||||||
"removePublicLink":
|
"removePublicLink":
|
||||||
MessageLookupByLibrary.simpleMessage("Quitar enlace público"),
|
MessageLookupByLibrary.simpleMessage("Quitar enlace público"),
|
||||||
"removeShareItemsWarning": MessageLookupByLibrary.simpleMessage(
|
"removeShareItemsWarning": MessageLookupByLibrary.simpleMessage(
|
||||||
|
|
11
mobile/lib/generated/intl/messages_fr.dart
generated
11
mobile/lib/generated/intl/messages_fr.dart
generated
|
@ -425,6 +425,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||||
MessageLookupByLibrary.simpleMessage("Grouper par durée"),
|
MessageLookupByLibrary.simpleMessage("Grouper par durée"),
|
||||||
"clubByFileName":
|
"clubByFileName":
|
||||||
MessageLookupByLibrary.simpleMessage("Grouper par nom de fichier"),
|
MessageLookupByLibrary.simpleMessage("Grouper par nom de fichier"),
|
||||||
|
"clusteringProgress":
|
||||||
|
MessageLookupByLibrary.simpleMessage("Clustering progress"),
|
||||||
"codeAppliedPageTitle":
|
"codeAppliedPageTitle":
|
||||||
MessageLookupByLibrary.simpleMessage("Code appliqué"),
|
MessageLookupByLibrary.simpleMessage("Code appliqué"),
|
||||||
"codeCopiedToClipboard": MessageLookupByLibrary.simpleMessage(
|
"codeCopiedToClipboard": MessageLookupByLibrary.simpleMessage(
|
||||||
|
@ -665,6 +667,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||||
MessageLookupByLibrary.simpleMessage("Saisissez le mot de passe"),
|
MessageLookupByLibrary.simpleMessage("Saisissez le mot de passe"),
|
||||||
"enterPasswordToEncrypt": MessageLookupByLibrary.simpleMessage(
|
"enterPasswordToEncrypt": MessageLookupByLibrary.simpleMessage(
|
||||||
"Entrez un mot de passe que nous pouvons utiliser pour chiffrer vos données"),
|
"Entrez un mot de passe que nous pouvons utiliser pour chiffrer vos données"),
|
||||||
|
"enterPersonName":
|
||||||
|
MessageLookupByLibrary.simpleMessage("Enter person name"),
|
||||||
"enterReferralCode": MessageLookupByLibrary.simpleMessage(
|
"enterReferralCode": MessageLookupByLibrary.simpleMessage(
|
||||||
"Entrez le code de parrainage"),
|
"Entrez le code de parrainage"),
|
||||||
"enterThe6digitCodeFromnyourAuthenticatorApp":
|
"enterThe6digitCodeFromnyourAuthenticatorApp":
|
||||||
|
@ -688,6 +692,10 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||||
"exportLogs": MessageLookupByLibrary.simpleMessage("Exporter les logs"),
|
"exportLogs": MessageLookupByLibrary.simpleMessage("Exporter les logs"),
|
||||||
"exportYourData":
|
"exportYourData":
|
||||||
MessageLookupByLibrary.simpleMessage("Exportez vos données"),
|
MessageLookupByLibrary.simpleMessage("Exportez vos données"),
|
||||||
|
"faceRecognition":
|
||||||
|
MessageLookupByLibrary.simpleMessage("Face recognition"),
|
||||||
|
"faceRecognitionIndexingDescription": MessageLookupByLibrary.simpleMessage(
|
||||||
|
"Please note that this will result in a higher bandwidth and battery usage until all items are indexed."),
|
||||||
"faces": MessageLookupByLibrary.simpleMessage("Visages"),
|
"faces": MessageLookupByLibrary.simpleMessage("Visages"),
|
||||||
"failedToApplyCode": MessageLookupByLibrary.simpleMessage(
|
"failedToApplyCode": MessageLookupByLibrary.simpleMessage(
|
||||||
"Impossible d\'appliquer le code"),
|
"Impossible d\'appliquer le code"),
|
||||||
|
@ -732,6 +740,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||||
MessageLookupByLibrary.simpleMessage("pour vos souvenirs"),
|
MessageLookupByLibrary.simpleMessage("pour vos souvenirs"),
|
||||||
"forgotPassword":
|
"forgotPassword":
|
||||||
MessageLookupByLibrary.simpleMessage("Mot de passe oublié"),
|
MessageLookupByLibrary.simpleMessage("Mot de passe oublié"),
|
||||||
|
"foundFaces": MessageLookupByLibrary.simpleMessage("Found faces"),
|
||||||
"freeStorageClaimed":
|
"freeStorageClaimed":
|
||||||
MessageLookupByLibrary.simpleMessage("Stockage gratuit réclamé"),
|
MessageLookupByLibrary.simpleMessage("Stockage gratuit réclamé"),
|
||||||
"freeStorageOnReferralSuccess": m24,
|
"freeStorageOnReferralSuccess": m24,
|
||||||
|
@ -1129,6 +1138,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||||
"removeParticipant":
|
"removeParticipant":
|
||||||
MessageLookupByLibrary.simpleMessage("Supprimer le participant"),
|
MessageLookupByLibrary.simpleMessage("Supprimer le participant"),
|
||||||
"removeParticipantBody": m43,
|
"removeParticipantBody": m43,
|
||||||
|
"removePersonLabel":
|
||||||
|
MessageLookupByLibrary.simpleMessage("Remove person label"),
|
||||||
"removePublicLink":
|
"removePublicLink":
|
||||||
MessageLookupByLibrary.simpleMessage("Supprimer le lien public"),
|
MessageLookupByLibrary.simpleMessage("Supprimer le lien public"),
|
||||||
"removeShareItemsWarning": MessageLookupByLibrary.simpleMessage(
|
"removeShareItemsWarning": MessageLookupByLibrary.simpleMessage(
|
||||||
|
|
11
mobile/lib/generated/intl/messages_it.dart
generated
11
mobile/lib/generated/intl/messages_it.dart
generated
|
@ -411,6 +411,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||||
MessageLookupByLibrary.simpleMessage("Club per tempo di cattura"),
|
MessageLookupByLibrary.simpleMessage("Club per tempo di cattura"),
|
||||||
"clubByFileName":
|
"clubByFileName":
|
||||||
MessageLookupByLibrary.simpleMessage("Unisci per nome file"),
|
MessageLookupByLibrary.simpleMessage("Unisci per nome file"),
|
||||||
|
"clusteringProgress":
|
||||||
|
MessageLookupByLibrary.simpleMessage("Clustering progress"),
|
||||||
"codeAppliedPageTitle":
|
"codeAppliedPageTitle":
|
||||||
MessageLookupByLibrary.simpleMessage("Codice applicato"),
|
MessageLookupByLibrary.simpleMessage("Codice applicato"),
|
||||||
"codeCopiedToClipboard": MessageLookupByLibrary.simpleMessage(
|
"codeCopiedToClipboard": MessageLookupByLibrary.simpleMessage(
|
||||||
|
@ -644,6 +646,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||||
MessageLookupByLibrary.simpleMessage("Inserisci password"),
|
MessageLookupByLibrary.simpleMessage("Inserisci password"),
|
||||||
"enterPasswordToEncrypt": MessageLookupByLibrary.simpleMessage(
|
"enterPasswordToEncrypt": MessageLookupByLibrary.simpleMessage(
|
||||||
"Inserisci una password per criptare i tuoi dati"),
|
"Inserisci una password per criptare i tuoi dati"),
|
||||||
|
"enterPersonName":
|
||||||
|
MessageLookupByLibrary.simpleMessage("Enter person name"),
|
||||||
"enterReferralCode": MessageLookupByLibrary.simpleMessage(
|
"enterReferralCode": MessageLookupByLibrary.simpleMessage(
|
||||||
"Inserisci il codice di invito"),
|
"Inserisci il codice di invito"),
|
||||||
"enterThe6digitCodeFromnyourAuthenticatorApp":
|
"enterThe6digitCodeFromnyourAuthenticatorApp":
|
||||||
|
@ -665,6 +669,10 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||||
"Questo link è scaduto. Si prega di selezionare un nuovo orario di scadenza o disabilitare la scadenza del link."),
|
"Questo link è scaduto. Si prega di selezionare un nuovo orario di scadenza o disabilitare la scadenza del link."),
|
||||||
"exportLogs": MessageLookupByLibrary.simpleMessage("Esporta log"),
|
"exportLogs": MessageLookupByLibrary.simpleMessage("Esporta log"),
|
||||||
"exportYourData": MessageLookupByLibrary.simpleMessage("Esporta dati"),
|
"exportYourData": MessageLookupByLibrary.simpleMessage("Esporta dati"),
|
||||||
|
"faceRecognition":
|
||||||
|
MessageLookupByLibrary.simpleMessage("Face recognition"),
|
||||||
|
"faceRecognitionIndexingDescription": MessageLookupByLibrary.simpleMessage(
|
||||||
|
"Please note that this will result in a higher bandwidth and battery usage until all items are indexed."),
|
||||||
"failedToApplyCode": MessageLookupByLibrary.simpleMessage(
|
"failedToApplyCode": MessageLookupByLibrary.simpleMessage(
|
||||||
"Impossibile applicare il codice"),
|
"Impossibile applicare il codice"),
|
||||||
"failedToCancel":
|
"failedToCancel":
|
||||||
|
@ -704,6 +712,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||||
MessageLookupByLibrary.simpleMessage("per i tuoi ricordi"),
|
MessageLookupByLibrary.simpleMessage("per i tuoi ricordi"),
|
||||||
"forgotPassword":
|
"forgotPassword":
|
||||||
MessageLookupByLibrary.simpleMessage("Password dimenticata"),
|
MessageLookupByLibrary.simpleMessage("Password dimenticata"),
|
||||||
|
"foundFaces": MessageLookupByLibrary.simpleMessage("Found faces"),
|
||||||
"freeStorageClaimed":
|
"freeStorageClaimed":
|
||||||
MessageLookupByLibrary.simpleMessage("Spazio gratuito richiesto"),
|
MessageLookupByLibrary.simpleMessage("Spazio gratuito richiesto"),
|
||||||
"freeStorageOnReferralSuccess": m24,
|
"freeStorageOnReferralSuccess": m24,
|
||||||
|
@ -1090,6 +1099,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||||
"removeParticipant":
|
"removeParticipant":
|
||||||
MessageLookupByLibrary.simpleMessage("Rimuovi partecipante"),
|
MessageLookupByLibrary.simpleMessage("Rimuovi partecipante"),
|
||||||
"removeParticipantBody": m43,
|
"removeParticipantBody": m43,
|
||||||
|
"removePersonLabel":
|
||||||
|
MessageLookupByLibrary.simpleMessage("Remove person label"),
|
||||||
"removePublicLink":
|
"removePublicLink":
|
||||||
MessageLookupByLibrary.simpleMessage("Rimuovi link pubblico"),
|
MessageLookupByLibrary.simpleMessage("Rimuovi link pubblico"),
|
||||||
"removeShareItemsWarning": MessageLookupByLibrary.simpleMessage(
|
"removeShareItemsWarning": MessageLookupByLibrary.simpleMessage(
|
||||||
|
|
11
mobile/lib/generated/intl/messages_ko.dart
generated
11
mobile/lib/generated/intl/messages_ko.dart
generated
|
@ -34,6 +34,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||||
"addViewers": m1,
|
"addViewers": m1,
|
||||||
"changeLocationOfSelectedItems": MessageLookupByLibrary.simpleMessage(
|
"changeLocationOfSelectedItems": MessageLookupByLibrary.simpleMessage(
|
||||||
"Change location of selected items?"),
|
"Change location of selected items?"),
|
||||||
|
"clusteringProgress":
|
||||||
|
MessageLookupByLibrary.simpleMessage("Clustering progress"),
|
||||||
"contacts": MessageLookupByLibrary.simpleMessage("Contacts"),
|
"contacts": MessageLookupByLibrary.simpleMessage("Contacts"),
|
||||||
"createCollaborativeLink":
|
"createCollaborativeLink":
|
||||||
MessageLookupByLibrary.simpleMessage("Create collaborative link"),
|
MessageLookupByLibrary.simpleMessage("Create collaborative link"),
|
||||||
|
@ -44,7 +46,14 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||||
"editsToLocationWillOnlyBeSeenWithinEnte":
|
"editsToLocationWillOnlyBeSeenWithinEnte":
|
||||||
MessageLookupByLibrary.simpleMessage(
|
MessageLookupByLibrary.simpleMessage(
|
||||||
"Edits to location will only be seen within Ente"),
|
"Edits to location will only be seen within Ente"),
|
||||||
|
"enterPersonName":
|
||||||
|
MessageLookupByLibrary.simpleMessage("Enter person name"),
|
||||||
|
"faceRecognition":
|
||||||
|
MessageLookupByLibrary.simpleMessage("Face recognition"),
|
||||||
|
"faceRecognitionIndexingDescription": MessageLookupByLibrary.simpleMessage(
|
||||||
|
"Please note that this will result in a higher bandwidth and battery usage until all items are indexed."),
|
||||||
"fileTypes": MessageLookupByLibrary.simpleMessage("File types"),
|
"fileTypes": MessageLookupByLibrary.simpleMessage("File types"),
|
||||||
|
"foundFaces": MessageLookupByLibrary.simpleMessage("Found faces"),
|
||||||
"joinDiscord": MessageLookupByLibrary.simpleMessage("Join Discord"),
|
"joinDiscord": MessageLookupByLibrary.simpleMessage("Join Discord"),
|
||||||
"locations": MessageLookupByLibrary.simpleMessage("Locations"),
|
"locations": MessageLookupByLibrary.simpleMessage("Locations"),
|
||||||
"longPressAnEmailToVerifyEndToEndEncryption":
|
"longPressAnEmailToVerifyEndToEndEncryption":
|
||||||
|
@ -55,6 +64,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||||
"Modify your query, or try searching for"),
|
"Modify your query, or try searching for"),
|
||||||
"moveToHiddenAlbum":
|
"moveToHiddenAlbum":
|
||||||
MessageLookupByLibrary.simpleMessage("Move to hidden album"),
|
MessageLookupByLibrary.simpleMessage("Move to hidden album"),
|
||||||
|
"removePersonLabel":
|
||||||
|
MessageLookupByLibrary.simpleMessage("Remove person label"),
|
||||||
"search": MessageLookupByLibrary.simpleMessage("Search"),
|
"search": MessageLookupByLibrary.simpleMessage("Search"),
|
||||||
"selectALocation":
|
"selectALocation":
|
||||||
MessageLookupByLibrary.simpleMessage("Select a location"),
|
MessageLookupByLibrary.simpleMessage("Select a location"),
|
||||||
|
|
7
mobile/lib/generated/intl/messages_nl.dart
generated
7
mobile/lib/generated/intl/messages_nl.dart
generated
|
@ -447,6 +447,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||||
MessageLookupByLibrary.simpleMessage("Samenvoegen op tijd"),
|
MessageLookupByLibrary.simpleMessage("Samenvoegen op tijd"),
|
||||||
"clubByFileName":
|
"clubByFileName":
|
||||||
MessageLookupByLibrary.simpleMessage("Samenvoegen op bestandsnaam"),
|
MessageLookupByLibrary.simpleMessage("Samenvoegen op bestandsnaam"),
|
||||||
|
"clusteringProgress":
|
||||||
|
MessageLookupByLibrary.simpleMessage("Clustering progress"),
|
||||||
"codeAppliedPageTitle":
|
"codeAppliedPageTitle":
|
||||||
MessageLookupByLibrary.simpleMessage("Code toegepast"),
|
MessageLookupByLibrary.simpleMessage("Code toegepast"),
|
||||||
"codeCopiedToClipboard": MessageLookupByLibrary.simpleMessage(
|
"codeCopiedToClipboard": MessageLookupByLibrary.simpleMessage(
|
||||||
|
@ -723,6 +725,10 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||||
MessageLookupByLibrary.simpleMessage("Logboek exporteren"),
|
MessageLookupByLibrary.simpleMessage("Logboek exporteren"),
|
||||||
"exportYourData":
|
"exportYourData":
|
||||||
MessageLookupByLibrary.simpleMessage("Exporteer je gegevens"),
|
MessageLookupByLibrary.simpleMessage("Exporteer je gegevens"),
|
||||||
|
"faceRecognition":
|
||||||
|
MessageLookupByLibrary.simpleMessage("Face recognition"),
|
||||||
|
"faceRecognitionIndexingDescription": MessageLookupByLibrary.simpleMessage(
|
||||||
|
"Please note that this will result in a higher bandwidth and battery usage until all items are indexed."),
|
||||||
"faces": MessageLookupByLibrary.simpleMessage("Gezichten"),
|
"faces": MessageLookupByLibrary.simpleMessage("Gezichten"),
|
||||||
"failedToApplyCode":
|
"failedToApplyCode":
|
||||||
MessageLookupByLibrary.simpleMessage("Code toepassen mislukt"),
|
MessageLookupByLibrary.simpleMessage("Code toepassen mislukt"),
|
||||||
|
@ -771,6 +777,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||||
MessageLookupByLibrary.simpleMessage("voor uw herinneringen"),
|
MessageLookupByLibrary.simpleMessage("voor uw herinneringen"),
|
||||||
"forgotPassword":
|
"forgotPassword":
|
||||||
MessageLookupByLibrary.simpleMessage("Wachtwoord vergeten"),
|
MessageLookupByLibrary.simpleMessage("Wachtwoord vergeten"),
|
||||||
|
"foundFaces": MessageLookupByLibrary.simpleMessage("Found faces"),
|
||||||
"freeStorageClaimed":
|
"freeStorageClaimed":
|
||||||
MessageLookupByLibrary.simpleMessage("Gratis opslag geclaimd"),
|
MessageLookupByLibrary.simpleMessage("Gratis opslag geclaimd"),
|
||||||
"freeStorageOnReferralSuccess": m24,
|
"freeStorageOnReferralSuccess": m24,
|
||||||
|
|
11
mobile/lib/generated/intl/messages_no.dart
generated
11
mobile/lib/generated/intl/messages_no.dart
generated
|
@ -39,6 +39,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||||
"cancel": MessageLookupByLibrary.simpleMessage("Avbryt"),
|
"cancel": MessageLookupByLibrary.simpleMessage("Avbryt"),
|
||||||
"changeLocationOfSelectedItems": MessageLookupByLibrary.simpleMessage(
|
"changeLocationOfSelectedItems": MessageLookupByLibrary.simpleMessage(
|
||||||
"Change location of selected items?"),
|
"Change location of selected items?"),
|
||||||
|
"clusteringProgress":
|
||||||
|
MessageLookupByLibrary.simpleMessage("Clustering progress"),
|
||||||
"confirmAccountDeletion":
|
"confirmAccountDeletion":
|
||||||
MessageLookupByLibrary.simpleMessage("Bekreft sletting av konto"),
|
MessageLookupByLibrary.simpleMessage("Bekreft sletting av konto"),
|
||||||
"confirmDeletePrompt": MessageLookupByLibrary.simpleMessage(
|
"confirmDeletePrompt": MessageLookupByLibrary.simpleMessage(
|
||||||
|
@ -57,12 +59,19 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||||
MessageLookupByLibrary.simpleMessage(
|
MessageLookupByLibrary.simpleMessage(
|
||||||
"Edits to location will only be seen within Ente"),
|
"Edits to location will only be seen within Ente"),
|
||||||
"email": MessageLookupByLibrary.simpleMessage("E-post"),
|
"email": MessageLookupByLibrary.simpleMessage("E-post"),
|
||||||
|
"enterPersonName":
|
||||||
|
MessageLookupByLibrary.simpleMessage("Enter person name"),
|
||||||
"enterValidEmail": MessageLookupByLibrary.simpleMessage(
|
"enterValidEmail": MessageLookupByLibrary.simpleMessage(
|
||||||
"Vennligst skriv inn en gyldig e-postadresse."),
|
"Vennligst skriv inn en gyldig e-postadresse."),
|
||||||
"enterYourEmailAddress": MessageLookupByLibrary.simpleMessage(
|
"enterYourEmailAddress": MessageLookupByLibrary.simpleMessage(
|
||||||
"Skriv inn e-postadressen din"),
|
"Skriv inn e-postadressen din"),
|
||||||
|
"faceRecognition":
|
||||||
|
MessageLookupByLibrary.simpleMessage("Face recognition"),
|
||||||
|
"faceRecognitionIndexingDescription": MessageLookupByLibrary.simpleMessage(
|
||||||
|
"Please note that this will result in a higher bandwidth and battery usage until all items are indexed."),
|
||||||
"feedback": MessageLookupByLibrary.simpleMessage("Tilbakemelding"),
|
"feedback": MessageLookupByLibrary.simpleMessage("Tilbakemelding"),
|
||||||
"fileTypes": MessageLookupByLibrary.simpleMessage("File types"),
|
"fileTypes": MessageLookupByLibrary.simpleMessage("File types"),
|
||||||
|
"foundFaces": MessageLookupByLibrary.simpleMessage("Found faces"),
|
||||||
"invalidEmailAddress":
|
"invalidEmailAddress":
|
||||||
MessageLookupByLibrary.simpleMessage("Ugyldig e-postadresse"),
|
MessageLookupByLibrary.simpleMessage("Ugyldig e-postadresse"),
|
||||||
"joinDiscord": MessageLookupByLibrary.simpleMessage("Join Discord"),
|
"joinDiscord": MessageLookupByLibrary.simpleMessage("Join Discord"),
|
||||||
|
@ -77,6 +86,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||||
"Modify your query, or try searching for"),
|
"Modify your query, or try searching for"),
|
||||||
"moveToHiddenAlbum":
|
"moveToHiddenAlbum":
|
||||||
MessageLookupByLibrary.simpleMessage("Move to hidden album"),
|
MessageLookupByLibrary.simpleMessage("Move to hidden album"),
|
||||||
|
"removePersonLabel":
|
||||||
|
MessageLookupByLibrary.simpleMessage("Remove person label"),
|
||||||
"search": MessageLookupByLibrary.simpleMessage("Search"),
|
"search": MessageLookupByLibrary.simpleMessage("Search"),
|
||||||
"selectALocation":
|
"selectALocation":
|
||||||
MessageLookupByLibrary.simpleMessage("Select a location"),
|
MessageLookupByLibrary.simpleMessage("Select a location"),
|
||||||
|
|
11
mobile/lib/generated/intl/messages_pl.dart
generated
11
mobile/lib/generated/intl/messages_pl.dart
generated
|
@ -49,6 +49,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||||
MessageLookupByLibrary.simpleMessage("Zmień hasło"),
|
MessageLookupByLibrary.simpleMessage("Zmień hasło"),
|
||||||
"checkInboxAndSpamFolder": MessageLookupByLibrary.simpleMessage(
|
"checkInboxAndSpamFolder": MessageLookupByLibrary.simpleMessage(
|
||||||
"Sprawdź swoją skrzynkę odbiorczą (i spam), aby zakończyć weryfikację"),
|
"Sprawdź swoją skrzynkę odbiorczą (i spam), aby zakończyć weryfikację"),
|
||||||
|
"clusteringProgress":
|
||||||
|
MessageLookupByLibrary.simpleMessage("Clustering progress"),
|
||||||
"codeCopiedToClipboard": MessageLookupByLibrary.simpleMessage(
|
"codeCopiedToClipboard": MessageLookupByLibrary.simpleMessage(
|
||||||
"Kod został skopiowany do schowka"),
|
"Kod został skopiowany do schowka"),
|
||||||
"confirm": MessageLookupByLibrary.simpleMessage("Potwierdź"),
|
"confirm": MessageLookupByLibrary.simpleMessage("Potwierdź"),
|
||||||
|
@ -101,6 +103,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||||
"Wprowadź nowe hasło, którego możemy użyć do zaszyfrowania Twoich danych"),
|
"Wprowadź nowe hasło, którego możemy użyć do zaszyfrowania Twoich danych"),
|
||||||
"enterPasswordToEncrypt": MessageLookupByLibrary.simpleMessage(
|
"enterPasswordToEncrypt": MessageLookupByLibrary.simpleMessage(
|
||||||
"Wprowadź hasło, którego możemy użyć do zaszyfrowania Twoich danych"),
|
"Wprowadź hasło, którego możemy użyć do zaszyfrowania Twoich danych"),
|
||||||
|
"enterPersonName":
|
||||||
|
MessageLookupByLibrary.simpleMessage("Enter person name"),
|
||||||
"enterValidEmail": MessageLookupByLibrary.simpleMessage(
|
"enterValidEmail": MessageLookupByLibrary.simpleMessage(
|
||||||
"Podaj poprawny adres e-mail."),
|
"Podaj poprawny adres e-mail."),
|
||||||
"enterYourEmailAddress":
|
"enterYourEmailAddress":
|
||||||
|
@ -109,10 +113,15 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||||
MessageLookupByLibrary.simpleMessage("Wprowadź hasło"),
|
MessageLookupByLibrary.simpleMessage("Wprowadź hasło"),
|
||||||
"enterYourRecoveryKey": MessageLookupByLibrary.simpleMessage(
|
"enterYourRecoveryKey": MessageLookupByLibrary.simpleMessage(
|
||||||
"Wprowadź swój klucz odzyskiwania"),
|
"Wprowadź swój klucz odzyskiwania"),
|
||||||
|
"faceRecognition":
|
||||||
|
MessageLookupByLibrary.simpleMessage("Face recognition"),
|
||||||
|
"faceRecognitionIndexingDescription": MessageLookupByLibrary.simpleMessage(
|
||||||
|
"Please note that this will result in a higher bandwidth and battery usage until all items are indexed."),
|
||||||
"feedback": MessageLookupByLibrary.simpleMessage("Informacja zwrotna"),
|
"feedback": MessageLookupByLibrary.simpleMessage("Informacja zwrotna"),
|
||||||
"fileTypes": MessageLookupByLibrary.simpleMessage("File types"),
|
"fileTypes": MessageLookupByLibrary.simpleMessage("File types"),
|
||||||
"forgotPassword":
|
"forgotPassword":
|
||||||
MessageLookupByLibrary.simpleMessage("Nie pamiętam hasła"),
|
MessageLookupByLibrary.simpleMessage("Nie pamiętam hasła"),
|
||||||
|
"foundFaces": MessageLookupByLibrary.simpleMessage("Found faces"),
|
||||||
"generatingEncryptionKeys": MessageLookupByLibrary.simpleMessage(
|
"generatingEncryptionKeys": MessageLookupByLibrary.simpleMessage(
|
||||||
"Generowanie kluczy szyfrujących..."),
|
"Generowanie kluczy szyfrujących..."),
|
||||||
"howItWorks": MessageLookupByLibrary.simpleMessage("Jak to działa"),
|
"howItWorks": MessageLookupByLibrary.simpleMessage("Jak to działa"),
|
||||||
|
@ -166,6 +175,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||||
"Jeśli zapomnisz hasła, jedynym sposobem odzyskania danych jest ten klucz."),
|
"Jeśli zapomnisz hasła, jedynym sposobem odzyskania danych jest ten klucz."),
|
||||||
"recoverySuccessful":
|
"recoverySuccessful":
|
||||||
MessageLookupByLibrary.simpleMessage("Odzyskano pomyślnie!"),
|
MessageLookupByLibrary.simpleMessage("Odzyskano pomyślnie!"),
|
||||||
|
"removePersonLabel":
|
||||||
|
MessageLookupByLibrary.simpleMessage("Remove person label"),
|
||||||
"resendEmail":
|
"resendEmail":
|
||||||
MessageLookupByLibrary.simpleMessage("Wyślij e-mail ponownie"),
|
MessageLookupByLibrary.simpleMessage("Wyślij e-mail ponownie"),
|
||||||
"resetPasswordTitle":
|
"resetPasswordTitle":
|
||||||
|
|
9
mobile/lib/generated/intl/messages_pt.dart
generated
9
mobile/lib/generated/intl/messages_pt.dart
generated
|
@ -445,6 +445,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||||
"Agrupar por tempo de captura"),
|
"Agrupar por tempo de captura"),
|
||||||
"clubByFileName": MessageLookupByLibrary.simpleMessage(
|
"clubByFileName": MessageLookupByLibrary.simpleMessage(
|
||||||
"Agrupar pelo nome de arquivo"),
|
"Agrupar pelo nome de arquivo"),
|
||||||
|
"clusteringProgress":
|
||||||
|
MessageLookupByLibrary.simpleMessage("Clustering progress"),
|
||||||
"codeAppliedPageTitle":
|
"codeAppliedPageTitle":
|
||||||
MessageLookupByLibrary.simpleMessage("Código aplicado"),
|
MessageLookupByLibrary.simpleMessage("Código aplicado"),
|
||||||
"codeCopiedToClipboard": MessageLookupByLibrary.simpleMessage(
|
"codeCopiedToClipboard": MessageLookupByLibrary.simpleMessage(
|
||||||
|
@ -587,7 +589,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||||
"descriptions": MessageLookupByLibrary.simpleMessage("Descrições"),
|
"descriptions": MessageLookupByLibrary.simpleMessage("Descrições"),
|
||||||
"deselectAll": MessageLookupByLibrary.simpleMessage("Desmarcar todos"),
|
"deselectAll": MessageLookupByLibrary.simpleMessage("Desmarcar todos"),
|
||||||
"designedToOutlive":
|
"designedToOutlive":
|
||||||
MessageLookupByLibrary.simpleMessage("Feito para ter logenvidade"),
|
MessageLookupByLibrary.simpleMessage("Feito para ter longevidade"),
|
||||||
"details": MessageLookupByLibrary.simpleMessage("Detalhes"),
|
"details": MessageLookupByLibrary.simpleMessage("Detalhes"),
|
||||||
"devAccountChanged": MessageLookupByLibrary.simpleMessage(
|
"devAccountChanged": MessageLookupByLibrary.simpleMessage(
|
||||||
"A conta de desenvolvedor que usamos para publicar o Ente na App Store foi alterada. Por esse motivo, você precisará fazer entrar novamente.\n\nPedimos desculpas pelo inconveniente, mas isso era inevitável."),
|
"A conta de desenvolvedor que usamos para publicar o Ente na App Store foi alterada. Por esse motivo, você precisará fazer entrar novamente.\n\nPedimos desculpas pelo inconveniente, mas isso era inevitável."),
|
||||||
|
@ -714,6 +716,10 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||||
"exportLogs": MessageLookupByLibrary.simpleMessage("Exportar logs"),
|
"exportLogs": MessageLookupByLibrary.simpleMessage("Exportar logs"),
|
||||||
"exportYourData":
|
"exportYourData":
|
||||||
MessageLookupByLibrary.simpleMessage("Exportar seus dados"),
|
MessageLookupByLibrary.simpleMessage("Exportar seus dados"),
|
||||||
|
"faceRecognition":
|
||||||
|
MessageLookupByLibrary.simpleMessage("Face recognition"),
|
||||||
|
"faceRecognitionIndexingDescription": MessageLookupByLibrary.simpleMessage(
|
||||||
|
"Please note that this will result in a higher bandwidth and battery usage until all items are indexed."),
|
||||||
"faces": MessageLookupByLibrary.simpleMessage("Rostos"),
|
"faces": MessageLookupByLibrary.simpleMessage("Rostos"),
|
||||||
"failedToApplyCode":
|
"failedToApplyCode":
|
||||||
MessageLookupByLibrary.simpleMessage("Falha ao aplicar o código"),
|
MessageLookupByLibrary.simpleMessage("Falha ao aplicar o código"),
|
||||||
|
@ -760,6 +766,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||||
MessageLookupByLibrary.simpleMessage("para suas memórias"),
|
MessageLookupByLibrary.simpleMessage("para suas memórias"),
|
||||||
"forgotPassword":
|
"forgotPassword":
|
||||||
MessageLookupByLibrary.simpleMessage("Esqueceu sua senha"),
|
MessageLookupByLibrary.simpleMessage("Esqueceu sua senha"),
|
||||||
|
"foundFaces": MessageLookupByLibrary.simpleMessage("Found faces"),
|
||||||
"freeStorageClaimed": MessageLookupByLibrary.simpleMessage(
|
"freeStorageClaimed": MessageLookupByLibrary.simpleMessage(
|
||||||
"Armazenamento gratuito reivindicado"),
|
"Armazenamento gratuito reivindicado"),
|
||||||
"freeStorageOnReferralSuccess": m24,
|
"freeStorageOnReferralSuccess": m24,
|
||||||
|
|
9
mobile/lib/generated/intl/messages_zh.dart
generated
9
mobile/lib/generated/intl/messages_zh.dart
generated
|
@ -382,6 +382,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||||
"close": MessageLookupByLibrary.simpleMessage("关闭"),
|
"close": MessageLookupByLibrary.simpleMessage("关闭"),
|
||||||
"clubByCaptureTime": MessageLookupByLibrary.simpleMessage("按拍摄时间分组"),
|
"clubByCaptureTime": MessageLookupByLibrary.simpleMessage("按拍摄时间分组"),
|
||||||
"clubByFileName": MessageLookupByLibrary.simpleMessage("按文件名排序"),
|
"clubByFileName": MessageLookupByLibrary.simpleMessage("按文件名排序"),
|
||||||
|
"clusteringProgress":
|
||||||
|
MessageLookupByLibrary.simpleMessage("Clustering progress"),
|
||||||
"codeAppliedPageTitle": MessageLookupByLibrary.simpleMessage("代码已应用"),
|
"codeAppliedPageTitle": MessageLookupByLibrary.simpleMessage("代码已应用"),
|
||||||
"codeCopiedToClipboard":
|
"codeCopiedToClipboard":
|
||||||
MessageLookupByLibrary.simpleMessage("代码已复制到剪贴板"),
|
MessageLookupByLibrary.simpleMessage("代码已复制到剪贴板"),
|
||||||
|
@ -543,7 +545,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||||
"emailVerificationToggle":
|
"emailVerificationToggle":
|
||||||
MessageLookupByLibrary.simpleMessage("电子邮件验证"),
|
MessageLookupByLibrary.simpleMessage("电子邮件验证"),
|
||||||
"emailYourLogs": MessageLookupByLibrary.simpleMessage("通过电子邮件发送您的日志"),
|
"emailYourLogs": MessageLookupByLibrary.simpleMessage("通过电子邮件发送您的日志"),
|
||||||
"empty": MessageLookupByLibrary.simpleMessage("空的"),
|
"empty": MessageLookupByLibrary.simpleMessage("清空"),
|
||||||
"emptyTrash": MessageLookupByLibrary.simpleMessage("要清空回收站吗?"),
|
"emptyTrash": MessageLookupByLibrary.simpleMessage("要清空回收站吗?"),
|
||||||
"enableMaps": MessageLookupByLibrary.simpleMessage("启用地图"),
|
"enableMaps": MessageLookupByLibrary.simpleMessage("启用地图"),
|
||||||
"enableMapsDesc": MessageLookupByLibrary.simpleMessage(
|
"enableMapsDesc": MessageLookupByLibrary.simpleMessage(
|
||||||
|
@ -592,6 +594,10 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||||
MessageLookupByLibrary.simpleMessage("此链接已过期。请选择新的过期时间或禁用链接有效期。"),
|
MessageLookupByLibrary.simpleMessage("此链接已过期。请选择新的过期时间或禁用链接有效期。"),
|
||||||
"exportLogs": MessageLookupByLibrary.simpleMessage("导出日志"),
|
"exportLogs": MessageLookupByLibrary.simpleMessage("导出日志"),
|
||||||
"exportYourData": MessageLookupByLibrary.simpleMessage("导出您的数据"),
|
"exportYourData": MessageLookupByLibrary.simpleMessage("导出您的数据"),
|
||||||
|
"faceRecognition":
|
||||||
|
MessageLookupByLibrary.simpleMessage("Face recognition"),
|
||||||
|
"faceRecognitionIndexingDescription": MessageLookupByLibrary.simpleMessage(
|
||||||
|
"Please note that this will result in a higher bandwidth and battery usage until all items are indexed."),
|
||||||
"faces": MessageLookupByLibrary.simpleMessage("人脸"),
|
"faces": MessageLookupByLibrary.simpleMessage("人脸"),
|
||||||
"failedToApplyCode": MessageLookupByLibrary.simpleMessage("无法使用此代码"),
|
"failedToApplyCode": MessageLookupByLibrary.simpleMessage("无法使用此代码"),
|
||||||
"failedToCancel": MessageLookupByLibrary.simpleMessage("取消失败"),
|
"failedToCancel": MessageLookupByLibrary.simpleMessage("取消失败"),
|
||||||
|
@ -626,6 +632,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||||
"flip": MessageLookupByLibrary.simpleMessage("上下翻转"),
|
"flip": MessageLookupByLibrary.simpleMessage("上下翻转"),
|
||||||
"forYourMemories": MessageLookupByLibrary.simpleMessage("为您的回忆"),
|
"forYourMemories": MessageLookupByLibrary.simpleMessage("为您的回忆"),
|
||||||
"forgotPassword": MessageLookupByLibrary.simpleMessage("忘记密码"),
|
"forgotPassword": MessageLookupByLibrary.simpleMessage("忘记密码"),
|
||||||
|
"foundFaces": MessageLookupByLibrary.simpleMessage("Found faces"),
|
||||||
"freeStorageClaimed": MessageLookupByLibrary.simpleMessage("已领取的免费存储"),
|
"freeStorageClaimed": MessageLookupByLibrary.simpleMessage("已领取的免费存储"),
|
||||||
"freeStorageOnReferralSuccess": m24,
|
"freeStorageOnReferralSuccess": m24,
|
||||||
"freeStorageSpace": m25,
|
"freeStorageSpace": m25,
|
||||||
|
|
138
mobile/lib/generated/l10n.dart
generated
138
mobile/lib/generated/l10n.dart
generated
|
@ -4034,10 +4034,10 @@ class S {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `Free trial valid till {endDate}.\nYou can purchase a paid plan afterwards.`
|
/// `Free trial valid till {endDate}.\nYou can choose a paid plan afterwards.`
|
||||||
String playStoreFreeTrialValidTill(Object endDate) {
|
String playStoreFreeTrialValidTill(Object endDate) {
|
||||||
return Intl.message(
|
return Intl.message(
|
||||||
'Free trial valid till $endDate.\nYou can purchase a paid plan afterwards.',
|
'Free trial valid till $endDate.\nYou can choose a paid plan afterwards.',
|
||||||
name: 'playStoreFreeTrialValidTill',
|
name: 'playStoreFreeTrialValidTill',
|
||||||
desc: '',
|
desc: '',
|
||||||
args: [endDate],
|
args: [endDate],
|
||||||
|
@ -6969,10 +6969,10 @@ class S {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `Find all photos of a person`
|
/// `Persons will be shown here once indexing is done`
|
||||||
String get searchFaceEmptySection {
|
String get searchFaceEmptySection {
|
||||||
return Intl.message(
|
return Intl.message(
|
||||||
'Find all photos of a person',
|
'Persons will be shown here once indexing is done',
|
||||||
name: 'searchFaceEmptySection',
|
name: 'searchFaceEmptySection',
|
||||||
desc: '',
|
desc: '',
|
||||||
args: [],
|
args: [],
|
||||||
|
@ -8168,6 +8168,16 @@ class S {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// `People`
|
||||||
|
String get people {
|
||||||
|
return Intl.message(
|
||||||
|
'People',
|
||||||
|
name: 'people',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/// `Contents`
|
/// `Contents`
|
||||||
String get contents {
|
String get contents {
|
||||||
return Intl.message(
|
return Intl.message(
|
||||||
|
@ -8388,26 +8398,6 @@ class S {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `Auto pair`
|
|
||||||
String get autoPair {
|
|
||||||
return Intl.message(
|
|
||||||
'Auto pair',
|
|
||||||
name: 'autoPair',
|
|
||||||
desc: '',
|
|
||||||
args: [],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// `Pair with PIN`
|
|
||||||
String get pairWithPin {
|
|
||||||
return Intl.message(
|
|
||||||
'Pair with PIN',
|
|
||||||
name: 'pairWithPin',
|
|
||||||
desc: '',
|
|
||||||
args: [],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// `Device not found`
|
/// `Device not found`
|
||||||
String get deviceNotFound {
|
String get deviceNotFound {
|
||||||
return Intl.message(
|
return Intl.message(
|
||||||
|
@ -8468,6 +8458,26 @@ class S {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// `Add a name`
|
||||||
|
String get addAName {
|
||||||
|
return Intl.message(
|
||||||
|
'Add a name',
|
||||||
|
name: 'addAName',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Find people quickly by name`
|
||||||
|
String get findPeopleByName {
|
||||||
|
return Intl.message(
|
||||||
|
'Find people quickly by name',
|
||||||
|
name: 'findPeopleByName',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/// `{count, plural, zero {Add viewer} one {Add viewer} other {Add viewers}}`
|
/// `{count, plural, zero {Add viewer} one {Add viewer} other {Add viewers}}`
|
||||||
String addViewers(num count) {
|
String addViewers(num count) {
|
||||||
return Intl.plural(
|
return Intl.plural(
|
||||||
|
@ -8594,6 +8604,26 @@ class S {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// `Enter person name`
|
||||||
|
String get enterPersonName {
|
||||||
|
return Intl.message(
|
||||||
|
'Enter person name',
|
||||||
|
name: 'enterPersonName',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Remove person label`
|
||||||
|
String get removePersonLabel {
|
||||||
|
return Intl.message(
|
||||||
|
'Remove person label',
|
||||||
|
name: 'removePersonLabel',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/// `Auto pair works only with devices that support Chromecast.`
|
/// `Auto pair works only with devices that support Chromecast.`
|
||||||
String get autoPairDesc {
|
String get autoPairDesc {
|
||||||
return Intl.message(
|
return Intl.message(
|
||||||
|
@ -8703,6 +8733,66 @@ class S {
|
||||||
args: [],
|
args: [],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// `Auto pair`
|
||||||
|
String get autoPair {
|
||||||
|
return Intl.message(
|
||||||
|
'Auto pair',
|
||||||
|
name: 'autoPair',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Pair with PIN`
|
||||||
|
String get pairWithPin {
|
||||||
|
return Intl.message(
|
||||||
|
'Pair with PIN',
|
||||||
|
name: 'pairWithPin',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Face recognition`
|
||||||
|
String get faceRecognition {
|
||||||
|
return Intl.message(
|
||||||
|
'Face recognition',
|
||||||
|
name: 'faceRecognition',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Please note that this will result in a higher bandwidth and battery usage until all items are indexed.`
|
||||||
|
String get faceRecognitionIndexingDescription {
|
||||||
|
return Intl.message(
|
||||||
|
'Please note that this will result in a higher bandwidth and battery usage until all items are indexed.',
|
||||||
|
name: 'faceRecognitionIndexingDescription',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Found faces`
|
||||||
|
String get foundFaces {
|
||||||
|
return Intl.message(
|
||||||
|
'Found faces',
|
||||||
|
name: 'foundFaces',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Clustering progress`
|
||||||
|
String get clusteringProgress {
|
||||||
|
return Intl.message(
|
||||||
|
'Clustering progress',
|
||||||
|
name: 'clusteringProgress',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class AppLocalizationDelegate extends LocalizationsDelegate<S> {
|
class AppLocalizationDelegate extends LocalizationsDelegate<S> {
|
||||||
|
|
111
mobile/lib/generated/protos/ente/common/box.pb.dart
Normal file
111
mobile/lib/generated/protos/ente/common/box.pb.dart
Normal file
|
@ -0,0 +1,111 @@
|
||||||
|
//
|
||||||
|
// Generated code. Do not modify.
|
||||||
|
// source: ente/common/box.proto
|
||||||
|
//
|
||||||
|
// @dart = 2.12
|
||||||
|
|
||||||
|
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
|
||||||
|
// ignore_for_file: constant_identifier_names, library_prefixes
|
||||||
|
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
|
||||||
|
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import
|
||||||
|
|
||||||
|
import 'dart:core' as $core;
|
||||||
|
|
||||||
|
import 'package:protobuf/protobuf.dart' as $pb;
|
||||||
|
|
||||||
|
/// CenterBox is a box where x,y is the center of the box
|
||||||
|
class CenterBox extends $pb.GeneratedMessage {
|
||||||
|
factory CenterBox({
|
||||||
|
$core.double? x,
|
||||||
|
$core.double? y,
|
||||||
|
$core.double? height,
|
||||||
|
$core.double? width,
|
||||||
|
}) {
|
||||||
|
final $result = create();
|
||||||
|
if (x != null) {
|
||||||
|
$result.x = x;
|
||||||
|
}
|
||||||
|
if (y != null) {
|
||||||
|
$result.y = y;
|
||||||
|
}
|
||||||
|
if (height != null) {
|
||||||
|
$result.height = height;
|
||||||
|
}
|
||||||
|
if (width != null) {
|
||||||
|
$result.width = width;
|
||||||
|
}
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
CenterBox._() : super();
|
||||||
|
factory CenterBox.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
|
||||||
|
factory CenterBox.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
|
||||||
|
|
||||||
|
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'CenterBox', package: const $pb.PackageName(_omitMessageNames ? '' : 'ente.common'), createEmptyInstance: create)
|
||||||
|
..a<$core.double>(1, _omitFieldNames ? '' : 'x', $pb.PbFieldType.OF)
|
||||||
|
..a<$core.double>(2, _omitFieldNames ? '' : 'y', $pb.PbFieldType.OF)
|
||||||
|
..a<$core.double>(3, _omitFieldNames ? '' : 'height', $pb.PbFieldType.OF)
|
||||||
|
..a<$core.double>(4, _omitFieldNames ? '' : 'width', $pb.PbFieldType.OF)
|
||||||
|
..hasRequiredFields = false
|
||||||
|
;
|
||||||
|
|
||||||
|
@$core.Deprecated(
|
||||||
|
'Using this can add significant overhead to your binary. '
|
||||||
|
'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
|
||||||
|
'Will be removed in next major version')
|
||||||
|
CenterBox clone() => CenterBox()..mergeFromMessage(this);
|
||||||
|
@$core.Deprecated(
|
||||||
|
'Using this can add significant overhead to your binary. '
|
||||||
|
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
|
||||||
|
'Will be removed in next major version')
|
||||||
|
CenterBox copyWith(void Function(CenterBox) updates) => super.copyWith((message) => updates(message as CenterBox)) as CenterBox;
|
||||||
|
|
||||||
|
$pb.BuilderInfo get info_ => _i;
|
||||||
|
|
||||||
|
@$core.pragma('dart2js:noInline')
|
||||||
|
static CenterBox create() => CenterBox._();
|
||||||
|
CenterBox createEmptyInstance() => create();
|
||||||
|
static $pb.PbList<CenterBox> createRepeated() => $pb.PbList<CenterBox>();
|
||||||
|
@$core.pragma('dart2js:noInline')
|
||||||
|
static CenterBox getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<CenterBox>(create);
|
||||||
|
static CenterBox? _defaultInstance;
|
||||||
|
|
||||||
|
@$pb.TagNumber(1)
|
||||||
|
$core.double get x => $_getN(0);
|
||||||
|
@$pb.TagNumber(1)
|
||||||
|
set x($core.double v) { $_setFloat(0, v); }
|
||||||
|
@$pb.TagNumber(1)
|
||||||
|
$core.bool hasX() => $_has(0);
|
||||||
|
@$pb.TagNumber(1)
|
||||||
|
void clearX() => clearField(1);
|
||||||
|
|
||||||
|
@$pb.TagNumber(2)
|
||||||
|
$core.double get y => $_getN(1);
|
||||||
|
@$pb.TagNumber(2)
|
||||||
|
set y($core.double v) { $_setFloat(1, v); }
|
||||||
|
@$pb.TagNumber(2)
|
||||||
|
$core.bool hasY() => $_has(1);
|
||||||
|
@$pb.TagNumber(2)
|
||||||
|
void clearY() => clearField(2);
|
||||||
|
|
||||||
|
@$pb.TagNumber(3)
|
||||||
|
$core.double get height => $_getN(2);
|
||||||
|
@$pb.TagNumber(3)
|
||||||
|
set height($core.double v) { $_setFloat(2, v); }
|
||||||
|
@$pb.TagNumber(3)
|
||||||
|
$core.bool hasHeight() => $_has(2);
|
||||||
|
@$pb.TagNumber(3)
|
||||||
|
void clearHeight() => clearField(3);
|
||||||
|
|
||||||
|
@$pb.TagNumber(4)
|
||||||
|
$core.double get width => $_getN(3);
|
||||||
|
@$pb.TagNumber(4)
|
||||||
|
set width($core.double v) { $_setFloat(3, v); }
|
||||||
|
@$pb.TagNumber(4)
|
||||||
|
$core.bool hasWidth() => $_has(3);
|
||||||
|
@$pb.TagNumber(4)
|
||||||
|
void clearWidth() => clearField(4);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const _omitFieldNames = $core.bool.fromEnvironment('protobuf.omit_field_names');
|
||||||
|
const _omitMessageNames = $core.bool.fromEnvironment('protobuf.omit_message_names');
|
11
mobile/lib/generated/protos/ente/common/box.pbenum.dart
Normal file
11
mobile/lib/generated/protos/ente/common/box.pbenum.dart
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
//
|
||||||
|
// Generated code. Do not modify.
|
||||||
|
// source: ente/common/box.proto
|
||||||
|
//
|
||||||
|
// @dart = 2.12
|
||||||
|
|
||||||
|
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
|
||||||
|
// ignore_for_file: constant_identifier_names, library_prefixes
|
||||||
|
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
|
||||||
|
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import
|
||||||
|
|
38
mobile/lib/generated/protos/ente/common/box.pbjson.dart
Normal file
38
mobile/lib/generated/protos/ente/common/box.pbjson.dart
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
//
|
||||||
|
// Generated code. Do not modify.
|
||||||
|
// source: ente/common/box.proto
|
||||||
|
//
|
||||||
|
// @dart = 2.12
|
||||||
|
|
||||||
|
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
|
||||||
|
// ignore_for_file: constant_identifier_names, library_prefixes
|
||||||
|
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
|
||||||
|
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import
|
||||||
|
|
||||||
|
import 'dart:convert' as $convert;
|
||||||
|
import 'dart:core' as $core;
|
||||||
|
import 'dart:typed_data' as $typed_data;
|
||||||
|
|
||||||
|
@$core.Deprecated('Use centerBoxDescriptor instead')
|
||||||
|
const CenterBox$json = {
|
||||||
|
'1': 'CenterBox',
|
||||||
|
'2': [
|
||||||
|
{'1': 'x', '3': 1, '4': 1, '5': 2, '9': 0, '10': 'x', '17': true},
|
||||||
|
{'1': 'y', '3': 2, '4': 1, '5': 2, '9': 1, '10': 'y', '17': true},
|
||||||
|
{'1': 'height', '3': 3, '4': 1, '5': 2, '9': 2, '10': 'height', '17': true},
|
||||||
|
{'1': 'width', '3': 4, '4': 1, '5': 2, '9': 3, '10': 'width', '17': true},
|
||||||
|
],
|
||||||
|
'8': [
|
||||||
|
{'1': '_x'},
|
||||||
|
{'1': '_y'},
|
||||||
|
{'1': '_height'},
|
||||||
|
{'1': '_width'},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Descriptor for `CenterBox`. Decode as a `google.protobuf.DescriptorProto`.
|
||||||
|
final $typed_data.Uint8List centerBoxDescriptor = $convert.base64Decode(
|
||||||
|
'CglDZW50ZXJCb3gSEQoBeBgBIAEoAkgAUgF4iAEBEhEKAXkYAiABKAJIAVIBeYgBARIbCgZoZW'
|
||||||
|
'lnaHQYAyABKAJIAlIGaGVpZ2h0iAEBEhkKBXdpZHRoGAQgASgCSANSBXdpZHRoiAEBQgQKAl94'
|
||||||
|
'QgQKAl95QgkKB19oZWlnaHRCCAoGX3dpZHRo');
|
||||||
|
|
14
mobile/lib/generated/protos/ente/common/box.pbserver.dart
Normal file
14
mobile/lib/generated/protos/ente/common/box.pbserver.dart
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
//
|
||||||
|
// Generated code. Do not modify.
|
||||||
|
// source: ente/common/box.proto
|
||||||
|
//
|
||||||
|
// @dart = 2.12
|
||||||
|
|
||||||
|
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
|
||||||
|
// ignore_for_file: constant_identifier_names
|
||||||
|
// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes
|
||||||
|
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
|
||||||
|
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import
|
||||||
|
|
||||||
|
export 'box.pb.dart';
|
||||||
|
|
83
mobile/lib/generated/protos/ente/common/point.pb.dart
Normal file
83
mobile/lib/generated/protos/ente/common/point.pb.dart
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
//
|
||||||
|
// Generated code. Do not modify.
|
||||||
|
// source: ente/common/point.proto
|
||||||
|
//
|
||||||
|
// @dart = 2.12
|
||||||
|
|
||||||
|
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
|
||||||
|
// ignore_for_file: constant_identifier_names, library_prefixes
|
||||||
|
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
|
||||||
|
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import
|
||||||
|
|
||||||
|
import 'dart:core' as $core;
|
||||||
|
|
||||||
|
import 'package:protobuf/protobuf.dart' as $pb;
|
||||||
|
|
||||||
|
/// EPoint is a point in 2D space
|
||||||
|
class EPoint extends $pb.GeneratedMessage {
|
||||||
|
factory EPoint({
|
||||||
|
$core.double? x,
|
||||||
|
$core.double? y,
|
||||||
|
}) {
|
||||||
|
final $result = create();
|
||||||
|
if (x != null) {
|
||||||
|
$result.x = x;
|
||||||
|
}
|
||||||
|
if (y != null) {
|
||||||
|
$result.y = y;
|
||||||
|
}
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
EPoint._() : super();
|
||||||
|
factory EPoint.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
|
||||||
|
factory EPoint.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
|
||||||
|
|
||||||
|
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'EPoint', package: const $pb.PackageName(_omitMessageNames ? '' : 'ente.common'), createEmptyInstance: create)
|
||||||
|
..a<$core.double>(1, _omitFieldNames ? '' : 'x', $pb.PbFieldType.OF)
|
||||||
|
..a<$core.double>(2, _omitFieldNames ? '' : 'y', $pb.PbFieldType.OF)
|
||||||
|
..hasRequiredFields = false
|
||||||
|
;
|
||||||
|
|
||||||
|
@$core.Deprecated(
|
||||||
|
'Using this can add significant overhead to your binary. '
|
||||||
|
'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
|
||||||
|
'Will be removed in next major version')
|
||||||
|
EPoint clone() => EPoint()..mergeFromMessage(this);
|
||||||
|
@$core.Deprecated(
|
||||||
|
'Using this can add significant overhead to your binary. '
|
||||||
|
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
|
||||||
|
'Will be removed in next major version')
|
||||||
|
EPoint copyWith(void Function(EPoint) updates) => super.copyWith((message) => updates(message as EPoint)) as EPoint;
|
||||||
|
|
||||||
|
$pb.BuilderInfo get info_ => _i;
|
||||||
|
|
||||||
|
@$core.pragma('dart2js:noInline')
|
||||||
|
static EPoint create() => EPoint._();
|
||||||
|
EPoint createEmptyInstance() => create();
|
||||||
|
static $pb.PbList<EPoint> createRepeated() => $pb.PbList<EPoint>();
|
||||||
|
@$core.pragma('dart2js:noInline')
|
||||||
|
static EPoint getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<EPoint>(create);
|
||||||
|
static EPoint? _defaultInstance;
|
||||||
|
|
||||||
|
@$pb.TagNumber(1)
|
||||||
|
$core.double get x => $_getN(0);
|
||||||
|
@$pb.TagNumber(1)
|
||||||
|
set x($core.double v) { $_setFloat(0, v); }
|
||||||
|
@$pb.TagNumber(1)
|
||||||
|
$core.bool hasX() => $_has(0);
|
||||||
|
@$pb.TagNumber(1)
|
||||||
|
void clearX() => clearField(1);
|
||||||
|
|
||||||
|
@$pb.TagNumber(2)
|
||||||
|
$core.double get y => $_getN(1);
|
||||||
|
@$pb.TagNumber(2)
|
||||||
|
set y($core.double v) { $_setFloat(1, v); }
|
||||||
|
@$pb.TagNumber(2)
|
||||||
|
$core.bool hasY() => $_has(1);
|
||||||
|
@$pb.TagNumber(2)
|
||||||
|
void clearY() => clearField(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const _omitFieldNames = $core.bool.fromEnvironment('protobuf.omit_field_names');
|
||||||
|
const _omitMessageNames = $core.bool.fromEnvironment('protobuf.omit_message_names');
|
11
mobile/lib/generated/protos/ente/common/point.pbenum.dart
Normal file
11
mobile/lib/generated/protos/ente/common/point.pbenum.dart
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
//
|
||||||
|
// Generated code. Do not modify.
|
||||||
|
// source: ente/common/point.proto
|
||||||
|
//
|
||||||
|
// @dart = 2.12
|
||||||
|
|
||||||
|
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
|
||||||
|
// ignore_for_file: constant_identifier_names, library_prefixes
|
||||||
|
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
|
||||||
|
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import
|
||||||
|
|
33
mobile/lib/generated/protos/ente/common/point.pbjson.dart
Normal file
33
mobile/lib/generated/protos/ente/common/point.pbjson.dart
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
//
|
||||||
|
// Generated code. Do not modify.
|
||||||
|
// source: ente/common/point.proto
|
||||||
|
//
|
||||||
|
// @dart = 2.12
|
||||||
|
|
||||||
|
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
|
||||||
|
// ignore_for_file: constant_identifier_names, library_prefixes
|
||||||
|
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
|
||||||
|
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import
|
||||||
|
|
||||||
|
import 'dart:convert' as $convert;
|
||||||
|
import 'dart:core' as $core;
|
||||||
|
import 'dart:typed_data' as $typed_data;
|
||||||
|
|
||||||
|
@$core.Deprecated('Use ePointDescriptor instead')
|
||||||
|
const EPoint$json = {
|
||||||
|
'1': 'EPoint',
|
||||||
|
'2': [
|
||||||
|
{'1': 'x', '3': 1, '4': 1, '5': 2, '9': 0, '10': 'x', '17': true},
|
||||||
|
{'1': 'y', '3': 2, '4': 1, '5': 2, '9': 1, '10': 'y', '17': true},
|
||||||
|
],
|
||||||
|
'8': [
|
||||||
|
{'1': '_x'},
|
||||||
|
{'1': '_y'},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Descriptor for `EPoint`. Decode as a `google.protobuf.DescriptorProto`.
|
||||||
|
final $typed_data.Uint8List ePointDescriptor = $convert.base64Decode(
|
||||||
|
'CgZFUG9pbnQSEQoBeBgBIAEoAkgAUgF4iAEBEhEKAXkYAiABKAJIAVIBeYgBAUIECgJfeEIECg'
|
||||||
|
'JfeQ==');
|
||||||
|
|
14
mobile/lib/generated/protos/ente/common/point.pbserver.dart
Normal file
14
mobile/lib/generated/protos/ente/common/point.pbserver.dart
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
//
|
||||||
|
// Generated code. Do not modify.
|
||||||
|
// source: ente/common/point.proto
|
||||||
|
//
|
||||||
|
// @dart = 2.12
|
||||||
|
|
||||||
|
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
|
||||||
|
// ignore_for_file: constant_identifier_names
|
||||||
|
// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes
|
||||||
|
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
|
||||||
|
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import
|
||||||
|
|
||||||
|
export 'point.pb.dart';
|
||||||
|
|
64
mobile/lib/generated/protos/ente/common/vector.pb.dart
Normal file
64
mobile/lib/generated/protos/ente/common/vector.pb.dart
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
//
|
||||||
|
// Generated code. Do not modify.
|
||||||
|
// source: ente/common/vector.proto
|
||||||
|
//
|
||||||
|
// @dart = 2.12
|
||||||
|
|
||||||
|
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
|
||||||
|
// ignore_for_file: constant_identifier_names, library_prefixes
|
||||||
|
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
|
||||||
|
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import
|
||||||
|
|
||||||
|
import 'dart:core' as $core;
|
||||||
|
|
||||||
|
import 'package:protobuf/protobuf.dart' as $pb;
|
||||||
|
|
||||||
|
/// Vector is generic message for dealing with lists of doubles
|
||||||
|
/// It should ideally be used independently and not as a submessage
|
||||||
|
class EVector extends $pb.GeneratedMessage {
|
||||||
|
factory EVector({
|
||||||
|
$core.Iterable<$core.double>? values,
|
||||||
|
}) {
|
||||||
|
final $result = create();
|
||||||
|
if (values != null) {
|
||||||
|
$result.values.addAll(values);
|
||||||
|
}
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
EVector._() : super();
|
||||||
|
factory EVector.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
|
||||||
|
factory EVector.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
|
||||||
|
|
||||||
|
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'EVector', package: const $pb.PackageName(_omitMessageNames ? '' : 'ente.common'), createEmptyInstance: create)
|
||||||
|
..p<$core.double>(1, _omitFieldNames ? '' : 'values', $pb.PbFieldType.KD)
|
||||||
|
..hasRequiredFields = false
|
||||||
|
;
|
||||||
|
|
||||||
|
@$core.Deprecated(
|
||||||
|
'Using this can add significant overhead to your binary. '
|
||||||
|
'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
|
||||||
|
'Will be removed in next major version')
|
||||||
|
EVector clone() => EVector()..mergeFromMessage(this);
|
||||||
|
@$core.Deprecated(
|
||||||
|
'Using this can add significant overhead to your binary. '
|
||||||
|
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
|
||||||
|
'Will be removed in next major version')
|
||||||
|
EVector copyWith(void Function(EVector) updates) => super.copyWith((message) => updates(message as EVector)) as EVector;
|
||||||
|
|
||||||
|
$pb.BuilderInfo get info_ => _i;
|
||||||
|
|
||||||
|
@$core.pragma('dart2js:noInline')
|
||||||
|
static EVector create() => EVector._();
|
||||||
|
EVector createEmptyInstance() => create();
|
||||||
|
static $pb.PbList<EVector> createRepeated() => $pb.PbList<EVector>();
|
||||||
|
@$core.pragma('dart2js:noInline')
|
||||||
|
static EVector getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<EVector>(create);
|
||||||
|
static EVector? _defaultInstance;
|
||||||
|
|
||||||
|
@$pb.TagNumber(1)
|
||||||
|
$core.List<$core.double> get values => $_getList(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const _omitFieldNames = $core.bool.fromEnvironment('protobuf.omit_field_names');
|
||||||
|
const _omitMessageNames = $core.bool.fromEnvironment('protobuf.omit_message_names');
|
11
mobile/lib/generated/protos/ente/common/vector.pbenum.dart
Normal file
11
mobile/lib/generated/protos/ente/common/vector.pbenum.dart
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
//
|
||||||
|
// Generated code. Do not modify.
|
||||||
|
// source: ente/common/vector.proto
|
||||||
|
//
|
||||||
|
// @dart = 2.12
|
||||||
|
|
||||||
|
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
|
||||||
|
// ignore_for_file: constant_identifier_names, library_prefixes
|
||||||
|
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
|
||||||
|
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import
|
||||||
|
|
27
mobile/lib/generated/protos/ente/common/vector.pbjson.dart
Normal file
27
mobile/lib/generated/protos/ente/common/vector.pbjson.dart
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
//
|
||||||
|
// Generated code. Do not modify.
|
||||||
|
// source: ente/common/vector.proto
|
||||||
|
//
|
||||||
|
// @dart = 2.12
|
||||||
|
|
||||||
|
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
|
||||||
|
// ignore_for_file: constant_identifier_names, library_prefixes
|
||||||
|
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
|
||||||
|
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import
|
||||||
|
|
||||||
|
import 'dart:convert' as $convert;
|
||||||
|
import 'dart:core' as $core;
|
||||||
|
import 'dart:typed_data' as $typed_data;
|
||||||
|
|
||||||
|
@$core.Deprecated('Use eVectorDescriptor instead')
|
||||||
|
const EVector$json = {
|
||||||
|
'1': 'EVector',
|
||||||
|
'2': [
|
||||||
|
{'1': 'values', '3': 1, '4': 3, '5': 1, '10': 'values'},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Descriptor for `EVector`. Decode as a `google.protobuf.DescriptorProto`.
|
||||||
|
final $typed_data.Uint8List eVectorDescriptor = $convert.base64Decode(
|
||||||
|
'CgdFVmVjdG9yEhYKBnZhbHVlcxgBIAMoAVIGdmFsdWVz');
|
||||||
|
|
14
mobile/lib/generated/protos/ente/common/vector.pbserver.dart
Normal file
14
mobile/lib/generated/protos/ente/common/vector.pbserver.dart
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
//
|
||||||
|
// Generated code. Do not modify.
|
||||||
|
// source: ente/common/vector.proto
|
||||||
|
//
|
||||||
|
// @dart = 2.12
|
||||||
|
|
||||||
|
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
|
||||||
|
// ignore_for_file: constant_identifier_names
|
||||||
|
// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes
|
||||||
|
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
|
||||||
|
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import
|
||||||
|
|
||||||
|
export 'vector.pb.dart';
|
||||||
|
|
169
mobile/lib/generated/protos/ente/ml/face.pb.dart
Normal file
169
mobile/lib/generated/protos/ente/ml/face.pb.dart
Normal file
|
@ -0,0 +1,169 @@
|
||||||
|
//
|
||||||
|
// Generated code. Do not modify.
|
||||||
|
// source: ente/ml/face.proto
|
||||||
|
//
|
||||||
|
// @dart = 2.12
|
||||||
|
|
||||||
|
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
|
||||||
|
// ignore_for_file: constant_identifier_names, library_prefixes
|
||||||
|
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
|
||||||
|
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import
|
||||||
|
|
||||||
|
import 'dart:core' as $core;
|
||||||
|
|
||||||
|
import 'package:protobuf/protobuf.dart' as $pb;
|
||||||
|
|
||||||
|
import '../common/box.pb.dart' as $0;
|
||||||
|
import '../common/point.pb.dart' as $1;
|
||||||
|
|
||||||
|
class Detection extends $pb.GeneratedMessage {
|
||||||
|
factory Detection({
|
||||||
|
$0.CenterBox? box,
|
||||||
|
$1.EPoint? landmarks,
|
||||||
|
}) {
|
||||||
|
final $result = create();
|
||||||
|
if (box != null) {
|
||||||
|
$result.box = box;
|
||||||
|
}
|
||||||
|
if (landmarks != null) {
|
||||||
|
$result.landmarks = landmarks;
|
||||||
|
}
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
Detection._() : super();
|
||||||
|
factory Detection.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
|
||||||
|
factory Detection.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
|
||||||
|
|
||||||
|
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'Detection', package: const $pb.PackageName(_omitMessageNames ? '' : 'ente.ml'), createEmptyInstance: create)
|
||||||
|
..aOM<$0.CenterBox>(1, _omitFieldNames ? '' : 'box', subBuilder: $0.CenterBox.create)
|
||||||
|
..aOM<$1.EPoint>(2, _omitFieldNames ? '' : 'landmarks', subBuilder: $1.EPoint.create)
|
||||||
|
..hasRequiredFields = false
|
||||||
|
;
|
||||||
|
|
||||||
|
@$core.Deprecated(
|
||||||
|
'Using this can add significant overhead to your binary. '
|
||||||
|
'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
|
||||||
|
'Will be removed in next major version')
|
||||||
|
Detection clone() => Detection()..mergeFromMessage(this);
|
||||||
|
@$core.Deprecated(
|
||||||
|
'Using this can add significant overhead to your binary. '
|
||||||
|
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
|
||||||
|
'Will be removed in next major version')
|
||||||
|
Detection copyWith(void Function(Detection) updates) => super.copyWith((message) => updates(message as Detection)) as Detection;
|
||||||
|
|
||||||
|
$pb.BuilderInfo get info_ => _i;
|
||||||
|
|
||||||
|
@$core.pragma('dart2js:noInline')
|
||||||
|
static Detection create() => Detection._();
|
||||||
|
Detection createEmptyInstance() => create();
|
||||||
|
static $pb.PbList<Detection> createRepeated() => $pb.PbList<Detection>();
|
||||||
|
@$core.pragma('dart2js:noInline')
|
||||||
|
static Detection getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<Detection>(create);
|
||||||
|
static Detection? _defaultInstance;
|
||||||
|
|
||||||
|
@$pb.TagNumber(1)
|
||||||
|
$0.CenterBox get box => $_getN(0);
|
||||||
|
@$pb.TagNumber(1)
|
||||||
|
set box($0.CenterBox v) { setField(1, v); }
|
||||||
|
@$pb.TagNumber(1)
|
||||||
|
$core.bool hasBox() => $_has(0);
|
||||||
|
@$pb.TagNumber(1)
|
||||||
|
void clearBox() => clearField(1);
|
||||||
|
@$pb.TagNumber(1)
|
||||||
|
$0.CenterBox ensureBox() => $_ensure(0);
|
||||||
|
|
||||||
|
@$pb.TagNumber(2)
|
||||||
|
$1.EPoint get landmarks => $_getN(1);
|
||||||
|
@$pb.TagNumber(2)
|
||||||
|
set landmarks($1.EPoint v) { setField(2, v); }
|
||||||
|
@$pb.TagNumber(2)
|
||||||
|
$core.bool hasLandmarks() => $_has(1);
|
||||||
|
@$pb.TagNumber(2)
|
||||||
|
void clearLandmarks() => clearField(2);
|
||||||
|
@$pb.TagNumber(2)
|
||||||
|
$1.EPoint ensureLandmarks() => $_ensure(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
class Face extends $pb.GeneratedMessage {
|
||||||
|
factory Face({
|
||||||
|
$core.String? id,
|
||||||
|
Detection? detection,
|
||||||
|
$core.double? confidence,
|
||||||
|
}) {
|
||||||
|
final $result = create();
|
||||||
|
if (id != null) {
|
||||||
|
$result.id = id;
|
||||||
|
}
|
||||||
|
if (detection != null) {
|
||||||
|
$result.detection = detection;
|
||||||
|
}
|
||||||
|
if (confidence != null) {
|
||||||
|
$result.confidence = confidence;
|
||||||
|
}
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
Face._() : super();
|
||||||
|
factory Face.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
|
||||||
|
factory Face.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
|
||||||
|
|
||||||
|
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'Face', package: const $pb.PackageName(_omitMessageNames ? '' : 'ente.ml'), createEmptyInstance: create)
|
||||||
|
..aOS(1, _omitFieldNames ? '' : 'id')
|
||||||
|
..aOM<Detection>(2, _omitFieldNames ? '' : 'detection', subBuilder: Detection.create)
|
||||||
|
..a<$core.double>(3, _omitFieldNames ? '' : 'confidence', $pb.PbFieldType.OF)
|
||||||
|
..hasRequiredFields = false
|
||||||
|
;
|
||||||
|
|
||||||
|
@$core.Deprecated(
|
||||||
|
'Using this can add significant overhead to your binary. '
|
||||||
|
'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
|
||||||
|
'Will be removed in next major version')
|
||||||
|
Face clone() => Face()..mergeFromMessage(this);
|
||||||
|
@$core.Deprecated(
|
||||||
|
'Using this can add significant overhead to your binary. '
|
||||||
|
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
|
||||||
|
'Will be removed in next major version')
|
||||||
|
Face copyWith(void Function(Face) updates) => super.copyWith((message) => updates(message as Face)) as Face;
|
||||||
|
|
||||||
|
$pb.BuilderInfo get info_ => _i;
|
||||||
|
|
||||||
|
@$core.pragma('dart2js:noInline')
|
||||||
|
static Face create() => Face._();
|
||||||
|
Face createEmptyInstance() => create();
|
||||||
|
static $pb.PbList<Face> createRepeated() => $pb.PbList<Face>();
|
||||||
|
@$core.pragma('dart2js:noInline')
|
||||||
|
static Face getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<Face>(create);
|
||||||
|
static Face? _defaultInstance;
|
||||||
|
|
||||||
|
@$pb.TagNumber(1)
|
||||||
|
$core.String get id => $_getSZ(0);
|
||||||
|
@$pb.TagNumber(1)
|
||||||
|
set id($core.String v) { $_setString(0, v); }
|
||||||
|
@$pb.TagNumber(1)
|
||||||
|
$core.bool hasId() => $_has(0);
|
||||||
|
@$pb.TagNumber(1)
|
||||||
|
void clearId() => clearField(1);
|
||||||
|
|
||||||
|
@$pb.TagNumber(2)
|
||||||
|
Detection get detection => $_getN(1);
|
||||||
|
@$pb.TagNumber(2)
|
||||||
|
set detection(Detection v) { setField(2, v); }
|
||||||
|
@$pb.TagNumber(2)
|
||||||
|
$core.bool hasDetection() => $_has(1);
|
||||||
|
@$pb.TagNumber(2)
|
||||||
|
void clearDetection() => clearField(2);
|
||||||
|
@$pb.TagNumber(2)
|
||||||
|
Detection ensureDetection() => $_ensure(1);
|
||||||
|
|
||||||
|
@$pb.TagNumber(3)
|
||||||
|
$core.double get confidence => $_getN(2);
|
||||||
|
@$pb.TagNumber(3)
|
||||||
|
set confidence($core.double v) { $_setFloat(2, v); }
|
||||||
|
@$pb.TagNumber(3)
|
||||||
|
$core.bool hasConfidence() => $_has(2);
|
||||||
|
@$pb.TagNumber(3)
|
||||||
|
void clearConfidence() => clearField(3);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const _omitFieldNames = $core.bool.fromEnvironment('protobuf.omit_field_names');
|
||||||
|
const _omitMessageNames = $core.bool.fromEnvironment('protobuf.omit_message_names');
|
11
mobile/lib/generated/protos/ente/ml/face.pbenum.dart
Normal file
11
mobile/lib/generated/protos/ente/ml/face.pbenum.dart
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
//
|
||||||
|
// Generated code. Do not modify.
|
||||||
|
// source: ente/ml/face.proto
|
||||||
|
//
|
||||||
|
// @dart = 2.12
|
||||||
|
|
||||||
|
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
|
||||||
|
// ignore_for_file: constant_identifier_names, library_prefixes
|
||||||
|
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
|
||||||
|
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import
|
||||||
|
|
55
mobile/lib/generated/protos/ente/ml/face.pbjson.dart
Normal file
55
mobile/lib/generated/protos/ente/ml/face.pbjson.dart
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
//
|
||||||
|
// Generated code. Do not modify.
|
||||||
|
// source: ente/ml/face.proto
|
||||||
|
//
|
||||||
|
// @dart = 2.12
|
||||||
|
|
||||||
|
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
|
||||||
|
// ignore_for_file: constant_identifier_names, library_prefixes
|
||||||
|
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
|
||||||
|
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import
|
||||||
|
|
||||||
|
import 'dart:convert' as $convert;
|
||||||
|
import 'dart:core' as $core;
|
||||||
|
import 'dart:typed_data' as $typed_data;
|
||||||
|
|
||||||
|
@$core.Deprecated('Use detectionDescriptor instead')
|
||||||
|
const Detection$json = {
|
||||||
|
'1': 'Detection',
|
||||||
|
'2': [
|
||||||
|
{'1': 'box', '3': 1, '4': 1, '5': 11, '6': '.ente.common.CenterBox', '9': 0, '10': 'box', '17': true},
|
||||||
|
{'1': 'landmarks', '3': 2, '4': 1, '5': 11, '6': '.ente.common.EPoint', '9': 1, '10': 'landmarks', '17': true},
|
||||||
|
],
|
||||||
|
'8': [
|
||||||
|
{'1': '_box'},
|
||||||
|
{'1': '_landmarks'},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Descriptor for `Detection`. Decode as a `google.protobuf.DescriptorProto`.
|
||||||
|
final $typed_data.Uint8List detectionDescriptor = $convert.base64Decode(
|
||||||
|
'CglEZXRlY3Rpb24SLQoDYm94GAEgASgLMhYuZW50ZS5jb21tb24uQ2VudGVyQm94SABSA2JveI'
|
||||||
|
'gBARI2CglsYW5kbWFya3MYAiABKAsyEy5lbnRlLmNvbW1vbi5FUG9pbnRIAVIJbGFuZG1hcmtz'
|
||||||
|
'iAEBQgYKBF9ib3hCDAoKX2xhbmRtYXJrcw==');
|
||||||
|
|
||||||
|
@$core.Deprecated('Use faceDescriptor instead')
|
||||||
|
const Face$json = {
|
||||||
|
'1': 'Face',
|
||||||
|
'2': [
|
||||||
|
{'1': 'id', '3': 1, '4': 1, '5': 9, '9': 0, '10': 'id', '17': true},
|
||||||
|
{'1': 'detection', '3': 2, '4': 1, '5': 11, '6': '.ente.ml.Detection', '9': 1, '10': 'detection', '17': true},
|
||||||
|
{'1': 'confidence', '3': 3, '4': 1, '5': 2, '9': 2, '10': 'confidence', '17': true},
|
||||||
|
],
|
||||||
|
'8': [
|
||||||
|
{'1': '_id'},
|
||||||
|
{'1': '_detection'},
|
||||||
|
{'1': '_confidence'},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Descriptor for `Face`. Decode as a `google.protobuf.DescriptorProto`.
|
||||||
|
final $typed_data.Uint8List faceDescriptor = $convert.base64Decode(
|
||||||
|
'CgRGYWNlEhMKAmlkGAEgASgJSABSAmlkiAEBEjUKCWRldGVjdGlvbhgCIAEoCzISLmVudGUubW'
|
||||||
|
'wuRGV0ZWN0aW9uSAFSCWRldGVjdGlvbogBARIjCgpjb25maWRlbmNlGAMgASgCSAJSCmNvbmZp'
|
||||||
|
'ZGVuY2WIAQFCBQoDX2lkQgwKCl9kZXRlY3Rpb25CDQoLX2NvbmZpZGVuY2U=');
|
||||||
|
|
14
mobile/lib/generated/protos/ente/ml/face.pbserver.dart
Normal file
14
mobile/lib/generated/protos/ente/ml/face.pbserver.dart
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
//
|
||||||
|
// Generated code. Do not modify.
|
||||||
|
// source: ente/ml/face.proto
|
||||||
|
//
|
||||||
|
// @dart = 2.12
|
||||||
|
|
||||||
|
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
|
||||||
|
// ignore_for_file: constant_identifier_names
|
||||||
|
// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes
|
||||||
|
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
|
||||||
|
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import
|
||||||
|
|
||||||
|
export 'face.pb.dart';
|
||||||
|
|
179
mobile/lib/generated/protos/ente/ml/fileml.pb.dart
Normal file
179
mobile/lib/generated/protos/ente/ml/fileml.pb.dart
Normal file
|
@ -0,0 +1,179 @@
|
||||||
|
//
|
||||||
|
// Generated code. Do not modify.
|
||||||
|
// source: ente/ml/fileml.proto
|
||||||
|
//
|
||||||
|
// @dart = 2.12
|
||||||
|
|
||||||
|
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
|
||||||
|
// ignore_for_file: constant_identifier_names, library_prefixes
|
||||||
|
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
|
||||||
|
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import
|
||||||
|
|
||||||
|
import 'dart:core' as $core;
|
||||||
|
|
||||||
|
import 'package:fixnum/fixnum.dart' as $fixnum;
|
||||||
|
import 'package:protobuf/protobuf.dart' as $pb;
|
||||||
|
|
||||||
|
import 'face.pb.dart' as $2;
|
||||||
|
|
||||||
|
class FileML extends $pb.GeneratedMessage {
|
||||||
|
factory FileML({
|
||||||
|
$fixnum.Int64? id,
|
||||||
|
$core.Iterable<$core.double>? clip,
|
||||||
|
}) {
|
||||||
|
final $result = create();
|
||||||
|
if (id != null) {
|
||||||
|
$result.id = id;
|
||||||
|
}
|
||||||
|
if (clip != null) {
|
||||||
|
$result.clip.addAll(clip);
|
||||||
|
}
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
FileML._() : super();
|
||||||
|
factory FileML.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
|
||||||
|
factory FileML.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
|
||||||
|
|
||||||
|
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'FileML', package: const $pb.PackageName(_omitMessageNames ? '' : 'ente.ml'), createEmptyInstance: create)
|
||||||
|
..aInt64(1, _omitFieldNames ? '' : 'id')
|
||||||
|
..p<$core.double>(2, _omitFieldNames ? '' : 'clip', $pb.PbFieldType.KD)
|
||||||
|
..hasRequiredFields = false
|
||||||
|
;
|
||||||
|
|
||||||
|
@$core.Deprecated(
|
||||||
|
'Using this can add significant overhead to your binary. '
|
||||||
|
'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
|
||||||
|
'Will be removed in next major version')
|
||||||
|
FileML clone() => FileML()..mergeFromMessage(this);
|
||||||
|
@$core.Deprecated(
|
||||||
|
'Using this can add significant overhead to your binary. '
|
||||||
|
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
|
||||||
|
'Will be removed in next major version')
|
||||||
|
FileML copyWith(void Function(FileML) updates) => super.copyWith((message) => updates(message as FileML)) as FileML;
|
||||||
|
|
||||||
|
$pb.BuilderInfo get info_ => _i;
|
||||||
|
|
||||||
|
@$core.pragma('dart2js:noInline')
|
||||||
|
static FileML create() => FileML._();
|
||||||
|
FileML createEmptyInstance() => create();
|
||||||
|
static $pb.PbList<FileML> createRepeated() => $pb.PbList<FileML>();
|
||||||
|
@$core.pragma('dart2js:noInline')
|
||||||
|
static FileML getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<FileML>(create);
|
||||||
|
static FileML? _defaultInstance;
|
||||||
|
|
||||||
|
@$pb.TagNumber(1)
|
||||||
|
$fixnum.Int64 get id => $_getI64(0);
|
||||||
|
@$pb.TagNumber(1)
|
||||||
|
set id($fixnum.Int64 v) { $_setInt64(0, v); }
|
||||||
|
@$pb.TagNumber(1)
|
||||||
|
$core.bool hasId() => $_has(0);
|
||||||
|
@$pb.TagNumber(1)
|
||||||
|
void clearId() => clearField(1);
|
||||||
|
|
||||||
|
@$pb.TagNumber(2)
|
||||||
|
$core.List<$core.double> get clip => $_getList(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
class FileFaces extends $pb.GeneratedMessage {
|
||||||
|
factory FileFaces({
|
||||||
|
$core.Iterable<$2.Face>? faces,
|
||||||
|
$core.int? height,
|
||||||
|
$core.int? width,
|
||||||
|
$core.int? version,
|
||||||
|
$core.String? error,
|
||||||
|
}) {
|
||||||
|
final $result = create();
|
||||||
|
if (faces != null) {
|
||||||
|
$result.faces.addAll(faces);
|
||||||
|
}
|
||||||
|
if (height != null) {
|
||||||
|
$result.height = height;
|
||||||
|
}
|
||||||
|
if (width != null) {
|
||||||
|
$result.width = width;
|
||||||
|
}
|
||||||
|
if (version != null) {
|
||||||
|
$result.version = version;
|
||||||
|
}
|
||||||
|
if (error != null) {
|
||||||
|
$result.error = error;
|
||||||
|
}
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
FileFaces._() : super();
|
||||||
|
factory FileFaces.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
|
||||||
|
factory FileFaces.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
|
||||||
|
|
||||||
|
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'FileFaces', package: const $pb.PackageName(_omitMessageNames ? '' : 'ente.ml'), createEmptyInstance: create)
|
||||||
|
..pc<$2.Face>(1, _omitFieldNames ? '' : 'faces', $pb.PbFieldType.PM, subBuilder: $2.Face.create)
|
||||||
|
..a<$core.int>(2, _omitFieldNames ? '' : 'height', $pb.PbFieldType.O3)
|
||||||
|
..a<$core.int>(3, _omitFieldNames ? '' : 'width', $pb.PbFieldType.O3)
|
||||||
|
..a<$core.int>(4, _omitFieldNames ? '' : 'version', $pb.PbFieldType.O3)
|
||||||
|
..aOS(5, _omitFieldNames ? '' : 'error')
|
||||||
|
..hasRequiredFields = false
|
||||||
|
;
|
||||||
|
|
||||||
|
@$core.Deprecated(
|
||||||
|
'Using this can add significant overhead to your binary. '
|
||||||
|
'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
|
||||||
|
'Will be removed in next major version')
|
||||||
|
FileFaces clone() => FileFaces()..mergeFromMessage(this);
|
||||||
|
@$core.Deprecated(
|
||||||
|
'Using this can add significant overhead to your binary. '
|
||||||
|
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
|
||||||
|
'Will be removed in next major version')
|
||||||
|
FileFaces copyWith(void Function(FileFaces) updates) => super.copyWith((message) => updates(message as FileFaces)) as FileFaces;
|
||||||
|
|
||||||
|
$pb.BuilderInfo get info_ => _i;
|
||||||
|
|
||||||
|
@$core.pragma('dart2js:noInline')
|
||||||
|
static FileFaces create() => FileFaces._();
|
||||||
|
FileFaces createEmptyInstance() => create();
|
||||||
|
static $pb.PbList<FileFaces> createRepeated() => $pb.PbList<FileFaces>();
|
||||||
|
@$core.pragma('dart2js:noInline')
|
||||||
|
static FileFaces getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<FileFaces>(create);
|
||||||
|
static FileFaces? _defaultInstance;
|
||||||
|
|
||||||
|
@$pb.TagNumber(1)
|
||||||
|
$core.List<$2.Face> get faces => $_getList(0);
|
||||||
|
|
||||||
|
@$pb.TagNumber(2)
|
||||||
|
$core.int get height => $_getIZ(1);
|
||||||
|
@$pb.TagNumber(2)
|
||||||
|
set height($core.int v) { $_setSignedInt32(1, v); }
|
||||||
|
@$pb.TagNumber(2)
|
||||||
|
$core.bool hasHeight() => $_has(1);
|
||||||
|
@$pb.TagNumber(2)
|
||||||
|
void clearHeight() => clearField(2);
|
||||||
|
|
||||||
|
@$pb.TagNumber(3)
|
||||||
|
$core.int get width => $_getIZ(2);
|
||||||
|
@$pb.TagNumber(3)
|
||||||
|
set width($core.int v) { $_setSignedInt32(2, v); }
|
||||||
|
@$pb.TagNumber(3)
|
||||||
|
$core.bool hasWidth() => $_has(2);
|
||||||
|
@$pb.TagNumber(3)
|
||||||
|
void clearWidth() => clearField(3);
|
||||||
|
|
||||||
|
@$pb.TagNumber(4)
|
||||||
|
$core.int get version => $_getIZ(3);
|
||||||
|
@$pb.TagNumber(4)
|
||||||
|
set version($core.int v) { $_setSignedInt32(3, v); }
|
||||||
|
@$pb.TagNumber(4)
|
||||||
|
$core.bool hasVersion() => $_has(3);
|
||||||
|
@$pb.TagNumber(4)
|
||||||
|
void clearVersion() => clearField(4);
|
||||||
|
|
||||||
|
@$pb.TagNumber(5)
|
||||||
|
$core.String get error => $_getSZ(4);
|
||||||
|
@$pb.TagNumber(5)
|
||||||
|
set error($core.String v) { $_setString(4, v); }
|
||||||
|
@$pb.TagNumber(5)
|
||||||
|
$core.bool hasError() => $_has(4);
|
||||||
|
@$pb.TagNumber(5)
|
||||||
|
void clearError() => clearField(5);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const _omitFieldNames = $core.bool.fromEnvironment('protobuf.omit_field_names');
|
||||||
|
const _omitMessageNames = $core.bool.fromEnvironment('protobuf.omit_message_names');
|
11
mobile/lib/generated/protos/ente/ml/fileml.pbenum.dart
Normal file
11
mobile/lib/generated/protos/ente/ml/fileml.pbenum.dart
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
//
|
||||||
|
// Generated code. Do not modify.
|
||||||
|
// source: ente/ml/fileml.proto
|
||||||
|
//
|
||||||
|
// @dart = 2.12
|
||||||
|
|
||||||
|
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
|
||||||
|
// ignore_for_file: constant_identifier_names, library_prefixes
|
||||||
|
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
|
||||||
|
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import
|
||||||
|
|
57
mobile/lib/generated/protos/ente/ml/fileml.pbjson.dart
Normal file
57
mobile/lib/generated/protos/ente/ml/fileml.pbjson.dart
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
//
|
||||||
|
// Generated code. Do not modify.
|
||||||
|
// source: ente/ml/fileml.proto
|
||||||
|
//
|
||||||
|
// @dart = 2.12
|
||||||
|
|
||||||
|
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
|
||||||
|
// ignore_for_file: constant_identifier_names, library_prefixes
|
||||||
|
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
|
||||||
|
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import
|
||||||
|
|
||||||
|
import 'dart:convert' as $convert;
|
||||||
|
import 'dart:core' as $core;
|
||||||
|
import 'dart:typed_data' as $typed_data;
|
||||||
|
|
||||||
|
@$core.Deprecated('Use fileMLDescriptor instead')
|
||||||
|
const FileML$json = {
|
||||||
|
'1': 'FileML',
|
||||||
|
'2': [
|
||||||
|
{'1': 'id', '3': 1, '4': 1, '5': 3, '9': 0, '10': 'id', '17': true},
|
||||||
|
{'1': 'clip', '3': 2, '4': 3, '5': 1, '10': 'clip'},
|
||||||
|
],
|
||||||
|
'8': [
|
||||||
|
{'1': '_id'},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Descriptor for `FileML`. Decode as a `google.protobuf.DescriptorProto`.
|
||||||
|
final $typed_data.Uint8List fileMLDescriptor = $convert.base64Decode(
|
||||||
|
'CgZGaWxlTUwSEwoCaWQYASABKANIAFICaWSIAQESEgoEY2xpcBgCIAMoAVIEY2xpcEIFCgNfaW'
|
||||||
|
'Q=');
|
||||||
|
|
||||||
|
@$core.Deprecated('Use fileFacesDescriptor instead')
|
||||||
|
const FileFaces$json = {
|
||||||
|
'1': 'FileFaces',
|
||||||
|
'2': [
|
||||||
|
{'1': 'faces', '3': 1, '4': 3, '5': 11, '6': '.ente.ml.Face', '10': 'faces'},
|
||||||
|
{'1': 'height', '3': 2, '4': 1, '5': 5, '9': 0, '10': 'height', '17': true},
|
||||||
|
{'1': 'width', '3': 3, '4': 1, '5': 5, '9': 1, '10': 'width', '17': true},
|
||||||
|
{'1': 'version', '3': 4, '4': 1, '5': 5, '9': 2, '10': 'version', '17': true},
|
||||||
|
{'1': 'error', '3': 5, '4': 1, '5': 9, '9': 3, '10': 'error', '17': true},
|
||||||
|
],
|
||||||
|
'8': [
|
||||||
|
{'1': '_height'},
|
||||||
|
{'1': '_width'},
|
||||||
|
{'1': '_version'},
|
||||||
|
{'1': '_error'},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Descriptor for `FileFaces`. Decode as a `google.protobuf.DescriptorProto`.
|
||||||
|
final $typed_data.Uint8List fileFacesDescriptor = $convert.base64Decode(
|
||||||
|
'CglGaWxlRmFjZXMSIwoFZmFjZXMYASADKAsyDS5lbnRlLm1sLkZhY2VSBWZhY2VzEhsKBmhlaW'
|
||||||
|
'dodBgCIAEoBUgAUgZoZWlnaHSIAQESGQoFd2lkdGgYAyABKAVIAVIFd2lkdGiIAQESHQoHdmVy'
|
||||||
|
'c2lvbhgEIAEoBUgCUgd2ZXJzaW9uiAEBEhkKBWVycm9yGAUgASgJSANSBWVycm9yiAEBQgkKB1'
|
||||||
|
'9oZWlnaHRCCAoGX3dpZHRoQgoKCF92ZXJzaW9uQggKBl9lcnJvcg==');
|
||||||
|
|
14
mobile/lib/generated/protos/ente/ml/fileml.pbserver.dart
Normal file
14
mobile/lib/generated/protos/ente/ml/fileml.pbserver.dart
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
//
|
||||||
|
// Generated code. Do not modify.
|
||||||
|
// source: ente/ml/fileml.proto
|
||||||
|
//
|
||||||
|
// @dart = 2.12
|
||||||
|
|
||||||
|
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
|
||||||
|
// ignore_for_file: constant_identifier_names
|
||||||
|
// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes
|
||||||
|
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
|
||||||
|
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import
|
||||||
|
|
||||||
|
export 'fileml.pb.dart';
|
||||||
|
|
|
@ -18,5 +18,11 @@
|
||||||
"addCollaborators": "{count, plural, zero {Add collaborator} one {Add collaborator} other {Add collaborators}}",
|
"addCollaborators": "{count, plural, zero {Add collaborator} one {Add collaborator} other {Add collaborators}}",
|
||||||
"longPressAnEmailToVerifyEndToEndEncryption": "Long press an email to verify end to end encryption.",
|
"longPressAnEmailToVerifyEndToEndEncryption": "Long press an email to verify end to end encryption.",
|
||||||
"createCollaborativeLink": "Create collaborative link",
|
"createCollaborativeLink": "Create collaborative link",
|
||||||
"search": "Search"
|
"search": "Search",
|
||||||
|
"enterPersonName": "Enter person name",
|
||||||
|
"removePersonLabel": "Remove person label",
|
||||||
|
"faceRecognition": "Face recognition",
|
||||||
|
"faceRecognitionIndexingDescription": "Please note that this will result in a higher bandwidth and battery usage until all items are indexed.",
|
||||||
|
"foundFaces": "Found faces",
|
||||||
|
"clusteringProgress": "Clustering progress"
|
||||||
}
|
}
|
|
@ -1187,6 +1187,8 @@
|
||||||
"changeLocationOfSelectedItems": "Standort der gewählten Elemente ändern?",
|
"changeLocationOfSelectedItems": "Standort der gewählten Elemente ändern?",
|
||||||
"editsToLocationWillOnlyBeSeenWithinEnte": "Änderungen des Standorts werden nur in ente sichtbar sein",
|
"editsToLocationWillOnlyBeSeenWithinEnte": "Änderungen des Standorts werden nur in ente sichtbar sein",
|
||||||
"cleanUncategorized": "Unkategorisiert leeren",
|
"cleanUncategorized": "Unkategorisiert leeren",
|
||||||
|
"addAName": "Add a name",
|
||||||
|
"findPeopleByName": "Find people quickly by searching by name",
|
||||||
"cleanUncategorizedDescription": "Entferne alle Dateien von \"Unkategorisiert\" die in anderen Alben vorhanden sind",
|
"cleanUncategorizedDescription": "Entferne alle Dateien von \"Unkategorisiert\" die in anderen Alben vorhanden sind",
|
||||||
"waitingForVerification": "Warte auf Bestätigung...",
|
"waitingForVerification": "Warte auf Bestätigung...",
|
||||||
"passkey": "Passkey",
|
"passkey": "Passkey",
|
||||||
|
@ -1204,5 +1206,11 @@
|
||||||
"addCollaborators": "{count, plural, zero {Add collaborator} one {Add collaborator} other {Add collaborators}}",
|
"addCollaborators": "{count, plural, zero {Add collaborator} one {Add collaborator} other {Add collaborators}}",
|
||||||
"longPressAnEmailToVerifyEndToEndEncryption": "Long press an email to verify end to end encryption.",
|
"longPressAnEmailToVerifyEndToEndEncryption": "Long press an email to verify end to end encryption.",
|
||||||
"createCollaborativeLink": "Create collaborative link",
|
"createCollaborativeLink": "Create collaborative link",
|
||||||
"search": "Search"
|
"search": "Search",
|
||||||
|
"enterPersonName": "Enter person name",
|
||||||
|
"removePersonLabel": "Remove person label",
|
||||||
|
"faceRecognition": "Face recognition",
|
||||||
|
"faceRecognitionIndexingDescription": "Please note that this will result in a higher bandwidth and battery usage until all items are indexed.",
|
||||||
|
"foundFaces": "Found faces",
|
||||||
|
"clusteringProgress": "Clustering progress"
|
||||||
}
|
}
|
|
@ -569,7 +569,7 @@
|
||||||
"freeTrialValidTill": "Free trial valid till {endDate}",
|
"freeTrialValidTill": "Free trial valid till {endDate}",
|
||||||
"validTill": "Valid till {endDate}",
|
"validTill": "Valid till {endDate}",
|
||||||
"addOnValidTill": "Your {storageAmount} add-on is valid till {endDate}",
|
"addOnValidTill": "Your {storageAmount} add-on is valid till {endDate}",
|
||||||
"playStoreFreeTrialValidTill": "Free trial valid till {endDate}.\nYou can purchase a paid plan afterwards.",
|
"playStoreFreeTrialValidTill": "Free trial valid till {endDate}.\nYou can choose a paid plan afterwards.",
|
||||||
"subWillBeCancelledOn": "Your subscription will be cancelled on {endDate}",
|
"subWillBeCancelledOn": "Your subscription will be cancelled on {endDate}",
|
||||||
"subscription": "Subscription",
|
"subscription": "Subscription",
|
||||||
"paymentDetails": "Payment details",
|
"paymentDetails": "Payment details",
|
||||||
|
@ -987,7 +987,7 @@
|
||||||
"fileTypesAndNames": "File types and names",
|
"fileTypesAndNames": "File types and names",
|
||||||
"location": "Location",
|
"location": "Location",
|
||||||
"moments": "Moments",
|
"moments": "Moments",
|
||||||
"searchFaceEmptySection": "Find all photos of a person",
|
"searchFaceEmptySection": "Persons will be shown here once indexing is done",
|
||||||
"searchDatesEmptySection": "Search by a date, month or year",
|
"searchDatesEmptySection": "Search by a date, month or year",
|
||||||
"searchLocationEmptySection": "Group photos that are taken within some radius of a photo",
|
"searchLocationEmptySection": "Group photos that are taken within some radius of a photo",
|
||||||
"searchPeopleEmptySection": "Invite people, and you'll see all photos shared by them here",
|
"searchPeopleEmptySection": "Invite people, and you'll see all photos shared by them here",
|
||||||
|
@ -1171,6 +1171,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"faces": "Faces",
|
"faces": "Faces",
|
||||||
|
"people": "People",
|
||||||
"contents": "Contents",
|
"contents": "Contents",
|
||||||
"addNew": "Add new",
|
"addNew": "Add new",
|
||||||
"@addNew": {
|
"@addNew": {
|
||||||
|
@ -1196,14 +1197,14 @@
|
||||||
"verifyPasskey": "Verify passkey",
|
"verifyPasskey": "Verify passkey",
|
||||||
"playOnTv": "Play album on TV",
|
"playOnTv": "Play album on TV",
|
||||||
"pair": "Pair",
|
"pair": "Pair",
|
||||||
"autoPair": "Auto pair",
|
|
||||||
"pairWithPin": "Pair with PIN",
|
|
||||||
"deviceNotFound": "Device not found",
|
"deviceNotFound": "Device not found",
|
||||||
"castInstruction": "Visit cast.ente.io on the device you want to pair.\n\nEnter the code below to play the album on your TV.",
|
"castInstruction": "Visit cast.ente.io on the device you want to pair.\n\nEnter the code below to play the album on your TV.",
|
||||||
"deviceCodeHint": "Enter the code",
|
"deviceCodeHint": "Enter the code",
|
||||||
"joinDiscord": "Join Discord",
|
"joinDiscord": "Join Discord",
|
||||||
"locations": "Locations",
|
"locations": "Locations",
|
||||||
"descriptions": "Descriptions",
|
"descriptions": "Descriptions",
|
||||||
|
"addAName": "Add a name",
|
||||||
|
"findPeopleByName": "Find people quickly by name",
|
||||||
"addViewers": "{count, plural, zero {Add viewer} one {Add viewer} other {Add viewers}}",
|
"addViewers": "{count, plural, zero {Add viewer} one {Add viewer} other {Add viewers}}",
|
||||||
"addCollaborators": "{count, plural, zero {Add collaborator} one {Add collaborator} other {Add collaborators}}",
|
"addCollaborators": "{count, plural, zero {Add collaborator} one {Add collaborator} other {Add collaborators}}",
|
||||||
"longPressAnEmailToVerifyEndToEndEncryption": "Long press an email to verify end to end encryption.",
|
"longPressAnEmailToVerifyEndToEndEncryption": "Long press an email to verify end to end encryption.",
|
||||||
|
@ -1216,6 +1217,8 @@
|
||||||
"customEndpoint": "Connected to {endpoint}",
|
"customEndpoint": "Connected to {endpoint}",
|
||||||
"createCollaborativeLink": "Create collaborative link",
|
"createCollaborativeLink": "Create collaborative link",
|
||||||
"search": "Search",
|
"search": "Search",
|
||||||
|
"enterPersonName": "Enter person name",
|
||||||
|
"removePersonLabel": "Remove person label",
|
||||||
"autoPairDesc": "Auto pair works only with devices that support Chromecast.",
|
"autoPairDesc": "Auto pair works only with devices that support Chromecast.",
|
||||||
"manualPairDesc": "Pair with PIN works with any screen you wish to view your album on.",
|
"manualPairDesc": "Pair with PIN works with any screen you wish to view your album on.",
|
||||||
"connectToDevice": "Connect to device",
|
"connectToDevice": "Connect to device",
|
||||||
|
@ -1226,5 +1229,11 @@
|
||||||
"stopCastingBody": "Do you want to stop casting?",
|
"stopCastingBody": "Do you want to stop casting?",
|
||||||
"castIPMismatchTitle": "Failed to cast album",
|
"castIPMismatchTitle": "Failed to cast album",
|
||||||
"castIPMismatchBody": "Please make sure you are on the same network as the TV.",
|
"castIPMismatchBody": "Please make sure you are on the same network as the TV.",
|
||||||
"pairingComplete": "Pairing complete"
|
"pairingComplete": "Pairing complete",
|
||||||
|
"autoPair": "Auto pair",
|
||||||
|
"pairWithPin": "Pair with PIN",
|
||||||
|
"faceRecognition": "Face recognition",
|
||||||
|
"faceRecognitionIndexingDescription": "Please note that this will result in a higher bandwidth and battery usage until all items are indexed.",
|
||||||
|
"foundFaces": "Found faces",
|
||||||
|
"clusteringProgress": "Clustering progress"
|
||||||
}
|
}
|
|
@ -980,5 +980,11 @@
|
||||||
"addCollaborators": "{count, plural, zero {Add collaborator} one {Add collaborator} other {Add collaborators}}",
|
"addCollaborators": "{count, plural, zero {Add collaborator} one {Add collaborator} other {Add collaborators}}",
|
||||||
"longPressAnEmailToVerifyEndToEndEncryption": "Long press an email to verify end to end encryption.",
|
"longPressAnEmailToVerifyEndToEndEncryption": "Long press an email to verify end to end encryption.",
|
||||||
"createCollaborativeLink": "Create collaborative link",
|
"createCollaborativeLink": "Create collaborative link",
|
||||||
"search": "Search"
|
"search": "Search",
|
||||||
|
"enterPersonName": "Enter person name",
|
||||||
|
"removePersonLabel": "Remove person label",
|
||||||
|
"faceRecognition": "Face recognition",
|
||||||
|
"faceRecognitionIndexingDescription": "Please note that this will result in a higher bandwidth and battery usage until all items are indexed.",
|
||||||
|
"foundFaces": "Found faces",
|
||||||
|
"clusteringProgress": "Clustering progress"
|
||||||
}
|
}
|
|
@ -1161,5 +1161,11 @@
|
||||||
"addCollaborators": "{count, plural, zero {Add collaborator} one {Add collaborator} other {Add collaborators}}",
|
"addCollaborators": "{count, plural, zero {Add collaborator} one {Add collaborator} other {Add collaborators}}",
|
||||||
"longPressAnEmailToVerifyEndToEndEncryption": "Long press an email to verify end to end encryption.",
|
"longPressAnEmailToVerifyEndToEndEncryption": "Long press an email to verify end to end encryption.",
|
||||||
"createCollaborativeLink": "Create collaborative link",
|
"createCollaborativeLink": "Create collaborative link",
|
||||||
"search": "Search"
|
"search": "Search",
|
||||||
|
"enterPersonName": "Enter person name",
|
||||||
|
"removePersonLabel": "Remove person label",
|
||||||
|
"faceRecognition": "Face recognition",
|
||||||
|
"faceRecognitionIndexingDescription": "Please note that this will result in a higher bandwidth and battery usage until all items are indexed.",
|
||||||
|
"foundFaces": "Found faces",
|
||||||
|
"clusteringProgress": "Clustering progress"
|
||||||
}
|
}
|
|
@ -1123,5 +1123,11 @@
|
||||||
"addCollaborators": "{count, plural, zero {Add collaborator} one {Add collaborator} other {Add collaborators}}",
|
"addCollaborators": "{count, plural, zero {Add collaborator} one {Add collaborator} other {Add collaborators}}",
|
||||||
"longPressAnEmailToVerifyEndToEndEncryption": "Long press an email to verify end to end encryption.",
|
"longPressAnEmailToVerifyEndToEndEncryption": "Long press an email to verify end to end encryption.",
|
||||||
"createCollaborativeLink": "Create collaborative link",
|
"createCollaborativeLink": "Create collaborative link",
|
||||||
"search": "Search"
|
"search": "Search",
|
||||||
|
"enterPersonName": "Enter person name",
|
||||||
|
"removePersonLabel": "Remove person label",
|
||||||
|
"faceRecognition": "Face recognition",
|
||||||
|
"faceRecognitionIndexingDescription": "Please note that this will result in a higher bandwidth and battery usage until all items are indexed.",
|
||||||
|
"foundFaces": "Found faces",
|
||||||
|
"clusteringProgress": "Clustering progress"
|
||||||
}
|
}
|
|
@ -18,5 +18,11 @@
|
||||||
"addCollaborators": "{count, plural, zero {Add collaborator} one {Add collaborator} other {Add collaborators}}",
|
"addCollaborators": "{count, plural, zero {Add collaborator} one {Add collaborator} other {Add collaborators}}",
|
||||||
"longPressAnEmailToVerifyEndToEndEncryption": "Long press an email to verify end to end encryption.",
|
"longPressAnEmailToVerifyEndToEndEncryption": "Long press an email to verify end to end encryption.",
|
||||||
"createCollaborativeLink": "Create collaborative link",
|
"createCollaborativeLink": "Create collaborative link",
|
||||||
"search": "Search"
|
"search": "Search",
|
||||||
|
"enterPersonName": "Enter person name",
|
||||||
|
"removePersonLabel": "Remove person label",
|
||||||
|
"faceRecognition": "Face recognition",
|
||||||
|
"faceRecognitionIndexingDescription": "Please note that this will result in a higher bandwidth and battery usage until all items are indexed.",
|
||||||
|
"foundFaces": "Found faces",
|
||||||
|
"clusteringProgress": "Clustering progress"
|
||||||
}
|
}
|
|
@ -1226,5 +1226,9 @@
|
||||||
"stopCastingBody": "Wil je stoppen met casten?",
|
"stopCastingBody": "Wil je stoppen met casten?",
|
||||||
"castIPMismatchTitle": "Album casten mislukt",
|
"castIPMismatchTitle": "Album casten mislukt",
|
||||||
"castIPMismatchBody": "Zorg ervoor dat je op hetzelfde netwerk zit als de tv.",
|
"castIPMismatchBody": "Zorg ervoor dat je op hetzelfde netwerk zit als de tv.",
|
||||||
"pairingComplete": "Koppeling voltooid"
|
"pairingComplete": "Koppeling voltooid",
|
||||||
|
"faceRecognition": "Face recognition",
|
||||||
|
"faceRecognitionIndexingDescription": "Please note that this will result in a higher bandwidth and battery usage until all items are indexed.",
|
||||||
|
"foundFaces": "Found faces",
|
||||||
|
"clusteringProgress": "Clustering progress"
|
||||||
}
|
}
|
|
@ -32,5 +32,11 @@
|
||||||
"addCollaborators": "{count, plural, zero {Add collaborator} one {Add collaborator} other {Add collaborators}}",
|
"addCollaborators": "{count, plural, zero {Add collaborator} one {Add collaborator} other {Add collaborators}}",
|
||||||
"longPressAnEmailToVerifyEndToEndEncryption": "Long press an email to verify end to end encryption.",
|
"longPressAnEmailToVerifyEndToEndEncryption": "Long press an email to verify end to end encryption.",
|
||||||
"createCollaborativeLink": "Create collaborative link",
|
"createCollaborativeLink": "Create collaborative link",
|
||||||
"search": "Search"
|
"search": "Search",
|
||||||
|
"enterPersonName": "Enter person name",
|
||||||
|
"removePersonLabel": "Remove person label",
|
||||||
|
"faceRecognition": "Face recognition",
|
||||||
|
"faceRecognitionIndexingDescription": "Please note that this will result in a higher bandwidth and battery usage until all items are indexed.",
|
||||||
|
"foundFaces": "Found faces",
|
||||||
|
"clusteringProgress": "Clustering progress"
|
||||||
}
|
}
|
|
@ -119,5 +119,11 @@
|
||||||
"addCollaborators": "{count, plural, zero {Add collaborator} one {Add collaborator} other {Add collaborators}}",
|
"addCollaborators": "{count, plural, zero {Add collaborator} one {Add collaborator} other {Add collaborators}}",
|
||||||
"longPressAnEmailToVerifyEndToEndEncryption": "Long press an email to verify end to end encryption.",
|
"longPressAnEmailToVerifyEndToEndEncryption": "Long press an email to verify end to end encryption.",
|
||||||
"createCollaborativeLink": "Create collaborative link",
|
"createCollaborativeLink": "Create collaborative link",
|
||||||
"search": "Search"
|
"search": "Search",
|
||||||
|
"enterPersonName": "Enter person name",
|
||||||
|
"removePersonLabel": "Remove person label",
|
||||||
|
"faceRecognition": "Face recognition",
|
||||||
|
"faceRecognitionIndexingDescription": "Please note that this will result in a higher bandwidth and battery usage until all items are indexed.",
|
||||||
|
"foundFaces": "Found faces",
|
||||||
|
"clusteringProgress": "Clustering progress"
|
||||||
}
|
}
|
|
@ -1226,5 +1226,9 @@
|
||||||
"stopCastingBody": "Você quer parar a transmissão?",
|
"stopCastingBody": "Você quer parar a transmissão?",
|
||||||
"castIPMismatchTitle": "Falha ao transmitir álbum",
|
"castIPMismatchTitle": "Falha ao transmitir álbum",
|
||||||
"castIPMismatchBody": "Certifique-se de estar na mesma rede que a TV.",
|
"castIPMismatchBody": "Certifique-se de estar na mesma rede que a TV.",
|
||||||
"pairingComplete": "Pareamento concluído"
|
"pairingComplete": "Pareamento concluído",
|
||||||
|
"faceRecognition": "Face recognition",
|
||||||
|
"faceRecognitionIndexingDescription": "Please note that this will result in a higher bandwidth and battery usage until all items are indexed.",
|
||||||
|
"foundFaces": "Found faces",
|
||||||
|
"clusteringProgress": "Clustering progress"
|
||||||
}
|
}
|
|
@ -1226,5 +1226,9 @@
|
||||||
"stopCastingBody": "您想停止投放吗?",
|
"stopCastingBody": "您想停止投放吗?",
|
||||||
"castIPMismatchTitle": "投放相册失败",
|
"castIPMismatchTitle": "投放相册失败",
|
||||||
"castIPMismatchBody": "请确保您的设备与电视处于同一网络。",
|
"castIPMismatchBody": "请确保您的设备与电视处于同一网络。",
|
||||||
"pairingComplete": "配对完成"
|
"pairingComplete": "配对完成",
|
||||||
|
"faceRecognition": "Face recognition",
|
||||||
|
"faceRecognitionIndexingDescription": "Please note that this will result in a higher bandwidth and battery usage until all items are indexed.",
|
||||||
|
"foundFaces": "Found faces",
|
||||||
|
"clusteringProgress": "Clustering progress"
|
||||||
}
|
}
|
|
@ -21,6 +21,7 @@ import 'package:photos/core/errors.dart';
|
||||||
import 'package:photos/core/network/network.dart';
|
import 'package:photos/core/network/network.dart';
|
||||||
import 'package:photos/db/upload_locks_db.dart';
|
import 'package:photos/db/upload_locks_db.dart';
|
||||||
import 'package:photos/ente_theme_data.dart';
|
import 'package:photos/ente_theme_data.dart';
|
||||||
|
import "package:photos/face/db.dart";
|
||||||
import "package:photos/l10n/l10n.dart";
|
import "package:photos/l10n/l10n.dart";
|
||||||
import "package:photos/service_locator.dart";
|
import "package:photos/service_locator.dart";
|
||||||
import 'package:photos/services/app_lifecycle_service.dart';
|
import 'package:photos/services/app_lifecycle_service.dart';
|
||||||
|
@ -32,6 +33,9 @@ import 'package:photos/services/home_widget_service.dart';
|
||||||
import 'package:photos/services/local_file_update_service.dart';
|
import 'package:photos/services/local_file_update_service.dart';
|
||||||
import 'package:photos/services/local_sync_service.dart';
|
import 'package:photos/services/local_sync_service.dart';
|
||||||
import "package:photos/services/location_service.dart";
|
import "package:photos/services/location_service.dart";
|
||||||
|
import 'package:photos/services/machine_learning/face_ml/face_ml_service.dart';
|
||||||
|
import "package:photos/services/machine_learning/face_ml/person/person_service.dart";
|
||||||
|
import 'package:photos/services/machine_learning/file_ml/remote_fileml_service.dart';
|
||||||
import "package:photos/services/machine_learning/machine_learning_controller.dart";
|
import "package:photos/services/machine_learning/machine_learning_controller.dart";
|
||||||
import 'package:photos/services/machine_learning/semantic_search/semantic_search_service.dart';
|
import 'package:photos/services/machine_learning/semantic_search/semantic_search_service.dart';
|
||||||
import 'package:photos/services/memories_service.dart';
|
import 'package:photos/services/memories_service.dart';
|
||||||
|
@ -213,6 +217,7 @@ Future<void> _init(bool isBackground, {String via = ''}) async {
|
||||||
LocalFileUpdateService.instance.init(preferences);
|
LocalFileUpdateService.instance.init(preferences);
|
||||||
SearchService.instance.init();
|
SearchService.instance.init();
|
||||||
StorageBonusService.instance.init(preferences);
|
StorageBonusService.instance.init(preferences);
|
||||||
|
RemoteFileMLService.instance.init(preferences);
|
||||||
if (!isBackground &&
|
if (!isBackground &&
|
||||||
Platform.isAndroid &&
|
Platform.isAndroid &&
|
||||||
await HomeWidgetService.instance.countHomeWidgets() == 0) {
|
await HomeWidgetService.instance.countHomeWidgets() == 0) {
|
||||||
|
@ -233,9 +238,23 @@ Future<void> _init(bool isBackground, {String via = ''}) async {
|
||||||
// Can not including existing tf/ml binaries as they are not being built
|
// Can not including existing tf/ml binaries as they are not being built
|
||||||
// from source.
|
// from source.
|
||||||
// See https://gitlab.com/fdroid/fdroiddata/-/merge_requests/12671#note_1294346819
|
// See https://gitlab.com/fdroid/fdroiddata/-/merge_requests/12671#note_1294346819
|
||||||
// if (!UpdateService.instance.isFdroidFlavor()) {
|
if (!UpdateService.instance.isFdroidFlavor()) {
|
||||||
// unawaited(ObjectDetectionService.instance.init());
|
// unawaited(ObjectDetectionService.instance.init());
|
||||||
// }
|
if (flagService.faceSearchEnabled) {
|
||||||
|
unawaited(FaceMlService.instance.init());
|
||||||
|
FaceMlService.instance.listenIndexOnDiffSync();
|
||||||
|
FaceMlService.instance.listenOnPeopleChangedSync();
|
||||||
|
} else {
|
||||||
|
if (LocalSettings.instance.isFaceIndexingEnabled) {
|
||||||
|
unawaited(LocalSettings.instance.toggleFaceIndexing());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PersonService.init(
|
||||||
|
EntityService.instance,
|
||||||
|
FaceMLDataDB.instance,
|
||||||
|
preferences,
|
||||||
|
);
|
||||||
|
|
||||||
_logger.info("Initialization done");
|
_logger.info("Initialization done");
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ import "package:flutter/foundation.dart";
|
||||||
|
|
||||||
enum EntityType {
|
enum EntityType {
|
||||||
location,
|
location,
|
||||||
|
person,
|
||||||
unknown,
|
unknown,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,6 +10,8 @@ EntityType typeFromString(String type) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case "location":
|
case "location":
|
||||||
return EntityType.location;
|
return EntityType.location;
|
||||||
|
case "person":
|
||||||
|
return EntityType.location;
|
||||||
}
|
}
|
||||||
debugPrint("unexpected collection type $type");
|
debugPrint("unexpected collection type $type");
|
||||||
return EntityType.unknown;
|
return EntityType.unknown;
|
||||||
|
@ -19,6 +22,8 @@ extension EntityTypeExtn on EntityType {
|
||||||
switch (this) {
|
switch (this) {
|
||||||
case EntityType.location:
|
case EntityType.location:
|
||||||
return "location";
|
return "location";
|
||||||
|
case EntityType.person:
|
||||||
|
return "person";
|
||||||
case EntityType.unknown:
|
case EntityType.unknown:
|
||||||
return "unknown";
|
return "unknown";
|
||||||
}
|
}
|
||||||
|
|
|
@ -243,6 +243,9 @@ class EnteFile {
|
||||||
}
|
}
|
||||||
|
|
||||||
String get downloadUrl {
|
String get downloadUrl {
|
||||||
|
if (localFileServer.isNotEmpty) {
|
||||||
|
return "$localFileServer/$uploadedFileID";
|
||||||
|
}
|
||||||
final endpoint = Configuration.instance.getHttpEndpoint();
|
final endpoint = Configuration.instance.getHttpEndpoint();
|
||||||
if (endpoint != kDefaultProductionEndpoint || flagService.disableCFWorker) {
|
if (endpoint != kDefaultProductionEndpoint || flagService.disableCFWorker) {
|
||||||
return endpoint + "/files/download/" + uploadedFileID.toString();
|
return endpoint + "/files/download/" + uploadedFileID.toString();
|
||||||
|
@ -256,6 +259,9 @@ class EnteFile {
|
||||||
}
|
}
|
||||||
|
|
||||||
String get thumbnailUrl {
|
String get thumbnailUrl {
|
||||||
|
if (localFileServer.isNotEmpty) {
|
||||||
|
return "$localFileServer/thumb/$uploadedFileID";
|
||||||
|
}
|
||||||
final endpoint = Configuration.instance.getHttpEndpoint();
|
final endpoint = Configuration.instance.getHttpEndpoint();
|
||||||
if (endpoint != kDefaultProductionEndpoint || flagService.disableCFWorker) {
|
if (endpoint != kDefaultProductionEndpoint || flagService.disableCFWorker) {
|
||||||
return endpoint + "/files/preview/" + uploadedFileID.toString();
|
return endpoint + "/files/preview/" + uploadedFileID.toString();
|
||||||
|
|
|
@ -18,6 +18,8 @@ enum GalleryType {
|
||||||
searchResults,
|
searchResults,
|
||||||
locationTag,
|
locationTag,
|
||||||
quickLink,
|
quickLink,
|
||||||
|
peopleTag,
|
||||||
|
cluster,
|
||||||
}
|
}
|
||||||
|
|
||||||
extension GalleyTypeExtension on GalleryType {
|
extension GalleyTypeExtension on GalleryType {
|
||||||
|
@ -32,12 +34,14 @@ extension GalleyTypeExtension on GalleryType {
|
||||||
case GalleryType.locationTag:
|
case GalleryType.locationTag:
|
||||||
case GalleryType.quickLink:
|
case GalleryType.quickLink:
|
||||||
case GalleryType.uncategorized:
|
case GalleryType.uncategorized:
|
||||||
|
case GalleryType.peopleTag:
|
||||||
case GalleryType.sharedCollection:
|
case GalleryType.sharedCollection:
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case GalleryType.hiddenSection:
|
case GalleryType.hiddenSection:
|
||||||
case GalleryType.hiddenOwnedCollection:
|
case GalleryType.hiddenOwnedCollection:
|
||||||
case GalleryType.trash:
|
case GalleryType.trash:
|
||||||
|
case GalleryType.cluster:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -50,6 +54,7 @@ extension GalleyTypeExtension on GalleryType {
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case GalleryType.hiddenSection:
|
case GalleryType.hiddenSection:
|
||||||
|
case GalleryType.peopleTag:
|
||||||
case GalleryType.hiddenOwnedCollection:
|
case GalleryType.hiddenOwnedCollection:
|
||||||
case GalleryType.favorite:
|
case GalleryType.favorite:
|
||||||
case GalleryType.searchResults:
|
case GalleryType.searchResults:
|
||||||
|
@ -59,6 +64,7 @@ extension GalleyTypeExtension on GalleryType {
|
||||||
case GalleryType.trash:
|
case GalleryType.trash:
|
||||||
case GalleryType.sharedCollection:
|
case GalleryType.sharedCollection:
|
||||||
case GalleryType.locationTag:
|
case GalleryType.locationTag:
|
||||||
|
case GalleryType.cluster:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -75,12 +81,14 @@ extension GalleyTypeExtension on GalleryType {
|
||||||
case GalleryType.uncategorized:
|
case GalleryType.uncategorized:
|
||||||
case GalleryType.locationTag:
|
case GalleryType.locationTag:
|
||||||
case GalleryType.quickLink:
|
case GalleryType.quickLink:
|
||||||
|
case GalleryType.peopleTag:
|
||||||
return true;
|
return true;
|
||||||
case GalleryType.trash:
|
case GalleryType.trash:
|
||||||
case GalleryType.archive:
|
case GalleryType.archive:
|
||||||
case GalleryType.hiddenSection:
|
case GalleryType.hiddenSection:
|
||||||
case GalleryType.hiddenOwnedCollection:
|
case GalleryType.hiddenOwnedCollection:
|
||||||
case GalleryType.sharedCollection:
|
case GalleryType.sharedCollection:
|
||||||
|
case GalleryType.cluster:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -98,8 +106,10 @@ extension GalleyTypeExtension on GalleryType {
|
||||||
case GalleryType.localFolder:
|
case GalleryType.localFolder:
|
||||||
case GalleryType.locationTag:
|
case GalleryType.locationTag:
|
||||||
case GalleryType.quickLink:
|
case GalleryType.quickLink:
|
||||||
|
case GalleryType.peopleTag:
|
||||||
return true;
|
return true;
|
||||||
case GalleryType.trash:
|
case GalleryType.trash:
|
||||||
|
case GalleryType.cluster:
|
||||||
case GalleryType.sharedCollection:
|
case GalleryType.sharedCollection:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -114,8 +124,10 @@ extension GalleyTypeExtension on GalleryType {
|
||||||
case GalleryType.archive:
|
case GalleryType.archive:
|
||||||
case GalleryType.uncategorized:
|
case GalleryType.uncategorized:
|
||||||
case GalleryType.locationTag:
|
case GalleryType.locationTag:
|
||||||
|
case GalleryType.peopleTag:
|
||||||
return true;
|
return true;
|
||||||
case GalleryType.hiddenSection:
|
case GalleryType.hiddenSection:
|
||||||
|
case GalleryType.cluster:
|
||||||
case GalleryType.hiddenOwnedCollection:
|
case GalleryType.hiddenOwnedCollection:
|
||||||
case GalleryType.localFolder:
|
case GalleryType.localFolder:
|
||||||
case GalleryType.trash:
|
case GalleryType.trash:
|
||||||
|
@ -132,6 +144,7 @@ extension GalleyTypeExtension on GalleryType {
|
||||||
case GalleryType.quickLink:
|
case GalleryType.quickLink:
|
||||||
return true;
|
return true;
|
||||||
case GalleryType.hiddenSection:
|
case GalleryType.hiddenSection:
|
||||||
|
case GalleryType.peopleTag:
|
||||||
case GalleryType.hiddenOwnedCollection:
|
case GalleryType.hiddenOwnedCollection:
|
||||||
case GalleryType.uncategorized:
|
case GalleryType.uncategorized:
|
||||||
case GalleryType.favorite:
|
case GalleryType.favorite:
|
||||||
|
@ -139,6 +152,7 @@ extension GalleyTypeExtension on GalleryType {
|
||||||
case GalleryType.homepage:
|
case GalleryType.homepage:
|
||||||
case GalleryType.archive:
|
case GalleryType.archive:
|
||||||
case GalleryType.localFolder:
|
case GalleryType.localFolder:
|
||||||
|
case GalleryType.cluster:
|
||||||
case GalleryType.trash:
|
case GalleryType.trash:
|
||||||
case GalleryType.locationTag:
|
case GalleryType.locationTag:
|
||||||
return false;
|
return false;
|
||||||
|
@ -154,6 +168,7 @@ extension GalleyTypeExtension on GalleryType {
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case GalleryType.hiddenSection:
|
case GalleryType.hiddenSection:
|
||||||
|
case GalleryType.peopleTag:
|
||||||
case GalleryType.hiddenOwnedCollection:
|
case GalleryType.hiddenOwnedCollection:
|
||||||
case GalleryType.favorite:
|
case GalleryType.favorite:
|
||||||
case GalleryType.searchResults:
|
case GalleryType.searchResults:
|
||||||
|
@ -162,6 +177,7 @@ extension GalleyTypeExtension on GalleryType {
|
||||||
case GalleryType.trash:
|
case GalleryType.trash:
|
||||||
case GalleryType.sharedCollection:
|
case GalleryType.sharedCollection:
|
||||||
case GalleryType.locationTag:
|
case GalleryType.locationTag:
|
||||||
|
case GalleryType.cluster:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -182,10 +198,12 @@ extension GalleyTypeExtension on GalleryType {
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case GalleryType.hiddenSection:
|
case GalleryType.hiddenSection:
|
||||||
|
case GalleryType.peopleTag:
|
||||||
case GalleryType.hiddenOwnedCollection:
|
case GalleryType.hiddenOwnedCollection:
|
||||||
case GalleryType.localFolder:
|
case GalleryType.localFolder:
|
||||||
case GalleryType.trash:
|
case GalleryType.trash:
|
||||||
case GalleryType.favorite:
|
case GalleryType.favorite:
|
||||||
|
case GalleryType.cluster:
|
||||||
case GalleryType.sharedCollection:
|
case GalleryType.sharedCollection:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -203,12 +221,14 @@ extension GalleyTypeExtension on GalleryType {
|
||||||
case GalleryType.searchResults:
|
case GalleryType.searchResults:
|
||||||
case GalleryType.uncategorized:
|
case GalleryType.uncategorized:
|
||||||
case GalleryType.locationTag:
|
case GalleryType.locationTag:
|
||||||
|
case GalleryType.peopleTag:
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case GalleryType.hiddenSection:
|
case GalleryType.hiddenSection:
|
||||||
case GalleryType.hiddenOwnedCollection:
|
case GalleryType.hiddenOwnedCollection:
|
||||||
case GalleryType.quickLink:
|
case GalleryType.quickLink:
|
||||||
case GalleryType.favorite:
|
case GalleryType.favorite:
|
||||||
|
case GalleryType.cluster:
|
||||||
case GalleryType.archive:
|
case GalleryType.archive:
|
||||||
case GalleryType.localFolder:
|
case GalleryType.localFolder:
|
||||||
case GalleryType.trash:
|
case GalleryType.trash:
|
||||||
|
@ -244,7 +264,7 @@ extension GalleyTypeExtension on GalleryType {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool showEditLocation() {
|
bool showEditLocation() {
|
||||||
return this != GalleryType.sharedCollection;
|
return this != GalleryType.sharedCollection && this != GalleryType.cluster;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -334,7 +354,9 @@ extension GalleryAppBarExtn on GalleryType {
|
||||||
case GalleryType.locationTag:
|
case GalleryType.locationTag:
|
||||||
case GalleryType.searchResults:
|
case GalleryType.searchResults:
|
||||||
return false;
|
return false;
|
||||||
|
case GalleryType.cluster:
|
||||||
case GalleryType.uncategorized:
|
case GalleryType.uncategorized:
|
||||||
|
case GalleryType.peopleTag:
|
||||||
case GalleryType.ownedCollection:
|
case GalleryType.ownedCollection:
|
||||||
case GalleryType.sharedCollection:
|
case GalleryType.sharedCollection:
|
||||||
case GalleryType.quickLink:
|
case GalleryType.quickLink:
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import "package:equatable/equatable.dart";
|
import "package:equatable/equatable.dart";
|
||||||
import "package:photos/models/api/entity/type.dart";
|
import "package:photos/models/api/entity/type.dart";
|
||||||
|
|
||||||
|
// LocalEntityData is a class that represents the data of an entity stored locally.
|
||||||
class LocalEntityData {
|
class LocalEntityData {
|
||||||
final String id;
|
final String id;
|
||||||
final EntityType type;
|
final EntityType type;
|
||||||
|
|
7
mobile/lib/models/ml/ml_typedefs.dart
Normal file
7
mobile/lib/models/ml/ml_typedefs.dart
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
typedef Embedding = List<double>;
|
||||||
|
|
||||||
|
typedef Num3DInputMatrix = List<List<List<num>>>;
|
||||||
|
|
||||||
|
typedef Int3DInputMatrix = List<List<List<int>>>;
|
||||||
|
|
||||||
|
typedef Double3DInputMatrix = List<List<List<double>>>;
|
3
mobile/lib/models/ml/ml_versions.dart
Normal file
3
mobile/lib/models/ml/ml_versions.dart
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
const faceMlVersion = 1;
|
||||||
|
const clusterMlVersion = 1;
|
||||||
|
const minimumClusterSize = 2;
|
|
@ -8,8 +8,15 @@ class GenericSearchResult extends SearchResult {
|
||||||
final List<EnteFile> _files;
|
final List<EnteFile> _files;
|
||||||
final ResultType _type;
|
final ResultType _type;
|
||||||
final Function(BuildContext context)? onResultTap;
|
final Function(BuildContext context)? onResultTap;
|
||||||
|
final Map<String, dynamic> params;
|
||||||
|
|
||||||
GenericSearchResult(this._type, this._name, this._files, {this.onResultTap});
|
GenericSearchResult(
|
||||||
|
this._type,
|
||||||
|
this._name,
|
||||||
|
this._files, {
|
||||||
|
this.onResultTap,
|
||||||
|
this.params = const {},
|
||||||
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String name() {
|
String name() {
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue