Merge branch 'main' into smart_dedupe

This commit is contained in:
laurenspriem
2025-08-19 11:47:19 +05:30
555 changed files with 95742 additions and 1730 deletions

View File

@@ -8,6 +8,7 @@ on:
env:
FLUTTER_VERSION: "3.32.8"
RUST_VERSION: "1.85.1"
permissions:
contents: read

View File

@@ -5,6 +5,7 @@ on:
env:
FLUTTER_VERSION: "3.32.8"
RUST_VERSION: "1.85.1"
permissions:
contents: write

View File

@@ -2,11 +2,12 @@ package cmd
import (
"fmt"
"github.com/ente-io/cli/pkg"
"github.com/spf13/cobra/doc"
"os"
"runtime"
"github.com/ente-io/cli/pkg"
"github.com/spf13/cobra/doc"
"github.com/spf13/viper"
"github.com/spf13/cobra"
@@ -20,11 +21,6 @@ var ctrl *pkg.ClICtrl
var rootCmd = &cobra.Command{
Use: "ente",
Short: "CLI tool for exporting your photos from ente.io",
// Uncomment the following line if your bare application
// has an action associated with it:
Run: func(cmd *cobra.Command, args []string) {
fmt.Sprintf("Hello World")
},
}
func GenerateDocs() error {

0
docs/docs/cli/index.md Normal file
View File

View File

@@ -63,11 +63,20 @@ It has no relation to Backblaze, Wasabi or Scaleway.
Each bucket's endpoint, region, key and secret should be configured accordingly
if using an external bucket.
A sample configuration for `b2-eu-cen` is provided, which can be used for other
2 buckets as well:
If a bucket has SSL support enabled, set `s3.are_local_buckets` to `false`. Enable path-style URL by setting `s3.use_path_style_urls` to `true`.
::: note
You can configure this for individual buckets over defining top-level configuration if you are using the latest server image (August 2025)
:::
A sample configuration for `b2-eu-cen` is provided, which can be used for other 2 buckets as well:
```yaml
b2-eu-cen:
are_local_buckets: true
use_path_style_urls: true
key: <key>
secret: <secret>
endpoint: localhost:3200

View File

@@ -96,8 +96,8 @@ provide correct credentials for proper connectivity within Museum.
The `s3` section within `museum.yaml` is by default configured to use local
MinIO buckets when using `quickstart.sh` or Docker Compose.
If you wish to use an external S3 provider, you can edit the configuration with
your provider's credentials, and set `s3.are_local_buckets` to `false`.
If you wish to use an external S3 provider with SSL, you can edit the configuration with
your provider's credentials, and set `s3.are_local_buckets` to `false`. Additionally, you can configure this for specific buckets in the corresponding bucket sections in the Compose file.
If you are using default MinIO, it is accessible at port `3200`. Web Console can
be accessed by enabling port `3201` in the Compose file.
@@ -111,11 +111,11 @@ and [troubleshooting](/self-hosting/troubleshooting/uploads) sections.
| Variable | Description | Default |
| -------------------------------------- | -------------------------------------------- | ------- |
| `s3.b2-eu-cen` | Primary hot storage S3 config | |
| `s3.b2-eu-cen` | Primary hot storage bucket configuration | |
| `s3.wasabi-eu-central-2-v3.compliance` | Whether to disable compliance lock on delete | `true` |
| `s3.scw-eu-fr-v3` | Optional secondary S3 config | |
| `s3.wasabi-eu-central-2-derived` | Derived data storage | |
| `s3.are_local_buckets` | Use local MinIO-compatible storage | `false` |
| `s3.scw-eu-fr-v3` | Cold storage bucket configuration | |
| `s3.wasabi-eu-central-2-v3` | Secondary hot storage configuration | |
| `s3.are_local_buckets` | | `true` |
| `s3.use_path_style_urls` | Enable path-style URLs for MinIO | `false` |
### Encryption Keys

View File

@@ -34,6 +34,9 @@ android {
ndkVersion flutter.ndkVersion
compileOptions {
// Flag to enable support for the new language APIs
coreLibraryDesugaringEnabled true
// Sets Java compatibility to Java 8
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
@@ -56,7 +59,7 @@ android {
applicationId "io.ente.auth"
// You can update the following values to match your application needs.
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
minSdkVersion 21
minSdkVersion 22
targetSdkVersion 35
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
@@ -115,4 +118,7 @@ flutter {
source '../..'
}
dependencies {}
dependencies {
// For AGP 7.4+
coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.1.4")
}

View File

@@ -0,0 +1,6 @@
# Please add these rules to your existing keep rules in order to suppress warnings.
# This is generated automatically by the Android Gradle plugin.
-dontwarn com.google.errorprone.annotations.CanIgnoreReturnValue
-dontwarn com.google.errorprone.annotations.CheckReturnValue
-dontwarn com.google.errorprone.annotations.Immutable
-dontwarn com.google.errorprone.annotations.RestrictedApi

View File

@@ -6,6 +6,19 @@ allprojects {
}
rootProject.buildDir = '../build'
subprojects {
afterEvaluate { project ->
if (project.hasProperty('android')) {
project.android {
if (namespace == null) {
namespace project.group
}
}
}
}
}
subprojects {
project.buildDir = "${rootProject.buildDir}/${project.name}"
}

View File

@@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.3-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-all.zip

View File

@@ -19,8 +19,8 @@ pluginManagement {
plugins {
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
id "com.android.application" version "7.3.0" apply false
id "org.jetbrains.kotlin.android" version "1.8.22" apply false
id "com.android.application" version "8.6.0" apply false
id "org.jetbrains.kotlin.android" version "2.1.10" apply false
}
include ":app"

View File

@@ -6,14 +6,14 @@
"request": "launch",
"type": "dart",
"flutterMode": "debug",
"program": "auth/lib/main.dart",
"program": "mobile/apps/auth/lib/main.dart",
"args": ["--dart-define", "endpoint=http://localhost:8080"]
},
{
"name": "Auth Android Dev",
"request": "launch",
"type": "dart",
"program": "auth/lib/main.dart",
"program": "mobile/apps/auth/lib/main.dart",
"args": [
"--dart-define",
"endpoint=http://192.168.1.3:8080",
@@ -25,21 +25,21 @@
"name": "Auth iOS Dev",
"request": "launch",
"type": "dart",
"program": "auth/lib/main.dart",
"program": "mobile/apps/auth/lib/main.dart",
"args": ["--dart-define", "endpoint=http://192.168.1.30:8080"]
},
{
"name": "Auth iOS Prod",
"request": "launch",
"type": "dart",
"program": "auth/lib/main.dart",
"program": "mobile/apps/auth/lib/main.dart",
"args": ["--target", "lib/main.dart"]
},
{
"name": "Auth Android Prod",
"request": "launch",
"type": "dart",
"program": "auth/lib/main.dart",
"program": "mobile/apps/auth/lib/main.dart",
"args": ["--target", "lib/main.dart", "--flavor", "independent"]
}
]

View File

@@ -3,7 +3,6 @@ PODS:
- Flutter
- connectivity_plus (0.0.1):
- Flutter
- FlutterMacOS
- cupertino_http (0.0.1):
- Flutter
- FlutterMacOS
@@ -61,13 +60,12 @@ PODS:
- Flutter
- flutter_local_notifications (0.0.1):
- Flutter
- flutter_native_splash (0.0.1):
- flutter_native_splash (2.4.3):
- Flutter
- flutter_secure_storage (6.0.0):
- Flutter
- fluttertoast (0.0.2):
- Flutter
- Toast
- local_auth_darwin (0.0.1):
- Flutter
- FlutterMacOS
@@ -87,9 +85,9 @@ PODS:
- qr_code_scanner (0.2.0):
- Flutter
- MTBBarcodeScanner
- SDWebImage (5.21.0):
- SDWebImage/Core (= 5.21.0)
- SDWebImage/Core (5.21.0)
- SDWebImage (5.21.1):
- SDWebImage/Core (= 5.21.1)
- SDWebImage/Core (5.21.1)
- Sentry/HybridSDK (8.46.0)
- sentry_flutter (8.14.2):
- Flutter
@@ -102,35 +100,38 @@ PODS:
- FlutterMacOS
- sodium_libs (2.2.1):
- Flutter
- sqflite (0.0.3):
- sqflite_darwin (0.0.4):
- Flutter
- FlutterMacOS
- "sqlite3 (3.46.1+1)":
- "sqlite3/common (= 3.46.1+1)"
- "sqlite3/common (3.46.1+1)"
- "sqlite3/dbstatvtab (3.46.1+1)":
- sqlite3 (3.50.2):
- sqlite3/common (= 3.50.2)
- sqlite3/common (3.50.2)
- sqlite3/dbstatvtab (3.50.2):
- sqlite3/common
- "sqlite3/fts5 (3.46.1+1)":
- sqlite3/fts5 (3.50.2):
- sqlite3/common
- "sqlite3/perf-threadsafe (3.46.1+1)":
- sqlite3/math (3.50.2):
- sqlite3/common
- "sqlite3/rtree (3.46.1+1)":
- sqlite3/perf-threadsafe (3.50.2):
- sqlite3/common
- sqlite3/rtree (3.50.2):
- sqlite3/common
- sqlite3_flutter_libs (0.0.1):
- Flutter
- "sqlite3 (~> 3.46.0+1)"
- FlutterMacOS
- sqlite3 (~> 3.50.1)
- sqlite3/dbstatvtab
- sqlite3/fts5
- sqlite3/math
- sqlite3/perf-threadsafe
- sqlite3/rtree
- SwiftyGif (5.4.5)
- Toast (4.1.1)
- url_launcher_ios (0.0.1):
- Flutter
DEPENDENCIES:
- app_links (from `.symlinks/plugins/app_links/ios`)
- connectivity_plus (from `.symlinks/plugins/connectivity_plus/darwin`)
- connectivity_plus (from `.symlinks/plugins/connectivity_plus/ios`)
- cupertino_http (from `.symlinks/plugins/cupertino_http/darwin`)
- device_info_plus (from `.symlinks/plugins/device_info_plus/ios`)
- file_picker (from `.symlinks/plugins/file_picker/ios`)
@@ -155,8 +156,8 @@ DEPENDENCIES:
- share_plus (from `.symlinks/plugins/share_plus/ios`)
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
- sodium_libs (from `.symlinks/plugins/sodium_libs/ios`)
- sqflite (from `.symlinks/plugins/sqflite/darwin`)
- sqlite3_flutter_libs (from `.symlinks/plugins/sqlite3_flutter_libs/ios`)
- sqflite_darwin (from `.symlinks/plugins/sqflite_darwin/darwin`)
- sqlite3_flutter_libs (from `.symlinks/plugins/sqlite3_flutter_libs/darwin`)
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
SPEC REPOS:
@@ -169,13 +170,12 @@ SPEC REPOS:
- Sentry
- sqlite3
- SwiftyGif
- Toast
EXTERNAL SOURCES:
app_links:
:path: ".symlinks/plugins/app_links/ios"
connectivity_plus:
:path: ".symlinks/plugins/connectivity_plus/darwin"
:path: ".symlinks/plugins/connectivity_plus/ios"
cupertino_http:
:path: ".symlinks/plugins/cupertino_http/darwin"
device_info_plus:
@@ -224,51 +224,50 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/shared_preferences_foundation/darwin"
sodium_libs:
:path: ".symlinks/plugins/sodium_libs/ios"
sqflite:
:path: ".symlinks/plugins/sqflite/darwin"
sqflite_darwin:
:path: ".symlinks/plugins/sqflite_darwin/darwin"
sqlite3_flutter_libs:
:path: ".symlinks/plugins/sqlite3_flutter_libs/ios"
:path: ".symlinks/plugins/sqlite3_flutter_libs/darwin"
url_launcher_ios:
:path: ".symlinks/plugins/url_launcher_ios/ios"
SPEC CHECKSUMS:
app_links: e7a6750a915a9e161c58d91bc610e8cd1d4d0ad0
connectivity_plus: ddd7f30999e1faaef5967c23d5b6d503d10434db
app_links: f3e17e4ee5e357b39d8b95290a9b2c299fca71c6
connectivity_plus: 2a701ffec2c0ae28a48cf7540e279787e77c447d
cupertino_http: 947a233f40cfea55167a49f2facc18434ea117ba
device_info_plus: c6fb39579d0f423935b0c9ce7ee2f44b71b9fce6
DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c
DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60
file_picker: 09aa5ec1ab24135ccd7a1621c46c84134bfd6655
file_picker: b159e0c068aef54932bb15dc9fd1571818edaf49
file_saver: 503e386464dbe118f630e17b4c2e1190fa0cf808
fk_user_agent: 1f47ec39291e8372b1d692b50084b0d54103c545
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
flutter_email_sender: 10a22605f92809a11ef52b2f412db806c6082d40
flutter_email_sender: e03bdda7637bcd3539bfe718fddd980e9508efaa
flutter_inappwebview_ios: 6f63631e2c62a7c350263b13fa5427aedefe81d4
flutter_local_authentication: 1172a4dd88f6306dadce067454e2c4caf07977bb
flutter_local_notifications: 4cde75091f6327eb8517fa068a0a5950212d2086
flutter_native_splash: edf599c81f74d093a4daf8e17bd7a018854bc778
flutter_local_notifications: df98d66e515e1ca797af436137b4459b160ad8c9
flutter_native_splash: df59bb2e1421aa0282cb2e95618af4dcb0c56c29
flutter_secure_storage: d33dac7ae2ea08509be337e775f6b59f1ff45f12
fluttertoast: e9a18c7be5413da53898f660530c56f35edfba9c
local_auth_darwin: 66e40372f1c29f383a314c738c7446e2f7fdadc3
fluttertoast: 21eecd6935e7064cc1fcb733a4c5a428f3f24f0f
local_auth_darwin: fa4b06454df7df8e97c18d7ee55151c57e7af0de
move_to_background: 39a5b79b26d577b0372cbe8a8c55e7aa9fcd3a2d
MTBBarcodeScanner: f453b33c4b7dfe545d8c6484ed744d55671788cb
objective_c: 77e887b5ba1827970907e10e832eec1683f3431d
OrderedSet: e539b66b644ff081c73a262d24ad552a69be3a94
package_info_plus: 58f0028419748fad15bf008b270aaa8e54380b1c
package_info_plus: c0502532a26c7662a62a356cebe2692ec5fe4ec4
path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46
privacy_screen: 1a131c052ceb3c3659934b003b0d397c2381a24e
qr_code_scanner: bb67d64904c3b9658ada8c402e8b4d406d5d796e
SDWebImage: f84b0feeb08d2d11e6a9b843cb06d75ebf5b8868
SDWebImage: f29024626962457f3470184232766516dee8dfea
Sentry: da60d980b197a46db0b35ea12cb8f39af48d8854
sentry_flutter: 2df8b0aab7e4aba81261c230cbea31c82a62dd1b
share_plus: 8875f4f2500512ea181eef553c3e27dba5135aad
share_plus: 8b6f8b3447e494cca5317c8c3073de39b3600d1f
shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78
sodium_libs: 1faae17af662384acbd13e41867a0008cd2e2318
sqflite: 673a0e54cc04b7d6dba8d24fb8095b31c3a99eec
sqlite3: 0bb0e6389d824e40296f531b858a2a0b71c0d2fb
sqlite3_flutter_libs: c00457ebd31e59fa6bb830380ddba24d44fbcd3b
sqflite_darwin: 5a7236e3b501866c1c9befc6771dfd73ffb8702d
sqlite3: 3e82a2daae39ba3b41ae6ee84a130494585460fc
sqlite3_flutter_libs: 2c48c4ee7217fd653251975e43412250d5bcbbe2
SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4
Toast: 1f5ea13423a1e6674c4abdac5be53587ae481c4e
url_launcher_ios: 5334b05cef931de560670eeae103fd3e431ac3fe
PODFILE CHECKSUM: 78f002751f1a8f65042b8da97902ba4124271c5a

View File

@@ -2,20 +2,21 @@ import 'dart:async';
import 'dart:io';
import 'package:adaptive_theme/adaptive_theme.dart';
import 'package:ente_accounts/services/user_service.dart';
import 'package:ente_auth/core/configuration.dart';
import 'package:ente_auth/core/event_bus.dart';
import 'package:ente_auth/ente_theme_data.dart';
import 'package:ente_auth/events/signed_in_event.dart';
import 'package:ente_auth/events/signed_out_event.dart';
import "package:ente_auth/l10n/l10n.dart";
import 'package:ente_auth/l10n/l10n.dart';
import 'package:ente_auth/locale.dart';
import "package:ente_auth/onboarding/view/onboarding_page.dart";
import 'package:ente_auth/services/authenticator_service.dart';
import 'package:ente_auth/services/update_service.dart';
import 'package:ente_auth/services/user_service.dart';
import 'package:ente_auth/services/window_listener_service.dart';
import 'package:ente_auth/ui/home_page.dart';
import 'package:ente_auth/ui/settings/app_update_dialog.dart';
import 'package:ente_events/event_bus.dart';
import 'package:ente_events/models/signed_in_event.dart';
import 'package:ente_events/models/signed_out_event.dart';
import 'package:ente_strings/l10n/strings_localizations.dart';
import 'package:flutter/foundation.dart';
import "package:flutter/material.dart";
import 'package:flutter_localizations/flutter_localizations.dart';
@@ -131,6 +132,7 @@ class _AppState extends State<App>
localeListResolutionCallback: localResolutionCallBack,
localizationsDelegates: const [
AppLocalizations.delegate,
StringsLocalizations.delegate,
GlobalMaterialLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
@@ -150,6 +152,7 @@ class _AppState extends State<App>
localeListResolutionCallback: localResolutionCallBack,
localizationsDelegates: const [
AppLocalizations.delegate,
StringsLocalizations.delegate,
GlobalMaterialLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,

View File

@@ -1,95 +1,36 @@
import 'dart:async';
import 'dart:convert';
import 'dart:io' as io;
import 'dart:typed_data';
import 'package:bip39/bip39.dart' as bip39;
import 'package:ente_auth/core/constants.dart';
import 'package:ente_auth/core/event_bus.dart';
import 'package:ente_auth/events/endpoint_updated_event.dart';
import 'package:ente_auth/events/signed_in_event.dart';
import 'package:ente_auth/events/signed_out_event.dart';
import 'package:ente_auth/models/key_attributes.dart';
import 'package:ente_auth/models/key_gen_result.dart';
import 'package:ente_auth/models/private_key_attributes.dart';
import 'package:ente_auth/store/authenticator_db.dart';
import 'package:ente_auth/utils/directory_utils.dart';
import 'package:ente_base/models/database.dart';
import 'package:ente_configuration/base_configuration.dart';
import 'package:ente_crypto_dart/ente_crypto_dart.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:logging/logging.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:sqflite_common_ffi/sqflite_ffi.dart';
import 'package:tuple/tuple.dart';
class Configuration {
class Configuration extends BaseConfiguration {
Configuration._privateConstructor();
static final Configuration instance = Configuration._privateConstructor();
static const endpoint = String.fromEnvironment(
"endpoint",
defaultValue: kDefaultProductionEndpoint,
);
static const emailKey = "email";
static const keyAttributesKey = "key_attributes";
static const lastTempFolderClearTimeKey = "last_temp_folder_clear_time";
static const keyKey = "key";
static const secretKeyKey = "secret_key";
static const authSecretKeyKey = "auth_secret_key";
static const offlineAuthSecretKey = "offline_auth_secret_key";
static const tokenKey = "token";
static const encryptedTokenKey = "encrypted_token";
static const userIDKey = "user_id";
static const hasMigratedSecureStorageKey = "has_migrated_secure_storage";
static const hasOptedForOfflineModeKey = "has_opted_for_offline_mode";
static const endPointKey = "endpoint";
final List<String> onlineSecureKeys = [
keyKey,
secretKeyKey,
authSecretKeyKey,
];
final kTempFolderDeletionTimeBuffer = const Duration(days: 1).inMicroseconds;
static final _logger = Logger("Configuration");
String? _cachedToken;
late SharedPreferences _preferences;
String? _key;
String? _secretKey;
String? _authSecretKey;
String? _offlineAuthKey;
late FlutterSecureStorage _secureStorage;
late String _tempDirectory;
String? _volatilePassword;
Future<void> init() async {
@override
Future<void> init(List<EnteBaseDatabase> dbs) async {
await super.init(dbs);
_preferences = await SharedPreferences.getInstance();
sqfliteFfiInit();
_secureStorage = const FlutterSecureStorage(
iOptions: IOSOptions(
accessibility: KeychainAccessibility.first_unlock_this_device,
),
);
_tempDirectory = (await DirectoryUtils.getDirectoryForInit()).path;
final tempDirectory = io.Directory(_tempDirectory);
try {
final currentTime = DateTime.now().microsecondsSinceEpoch;
if (tempDirectory.existsSync() &&
(_preferences.getInt(lastTempFolderClearTimeKey) ?? 0) <
(currentTime - kTempFolderDeletionTimeBuffer)) {
await tempDirectory.delete(recursive: true);
await _preferences.setInt(lastTempFolderClearTimeKey, currentTime);
_logger.info("Cleared temp folder");
} else {
_logger.info("Skipping temp folder clear");
}
} catch (e) {
_logger.warning(e);
}
tempDirectory.createSync(recursive: true);
await _initOnlineAccount();
sqfliteFfiInit();
await _initOfflineAccount();
}
@@ -99,303 +40,10 @@ class Configuration {
);
}
Future<void> _initOnlineAccount() async {
if (!_preferences.containsKey(tokenKey)) {
for (final key in onlineSecureKeys) {
unawaited(
_secureStorage.delete(
key: key,
),
);
}
} else {
_key = await _secureStorage.read(
key: keyKey,
);
_secretKey = await _secureStorage.read(
key: secretKeyKey,
);
_authSecretKey = await _secureStorage.read(
key: authSecretKeyKey,
);
if (_key == null) {
await logout(autoLogout: true);
}
}
}
@override
Future<void> logout({bool autoLogout = false}) async {
await _preferences.clear();
for (String key in onlineSecureKeys) {
await _secureStorage.delete(
key: key,
);
}
await AuthenticatorDB.instance.clearTable();
_key = null;
_cachedToken = null;
_secretKey = null;
_authSecretKey = null;
Bus.instance.fire(SignedOutEvent());
}
Future<KeyGenResult> generateKey(String password) async {
// Create a master key
final masterKey = CryptoUtil.generateKey();
// Create a recovery key
final recoveryKey = CryptoUtil.generateKey();
// Encrypt master key and recovery key with each other
final encryptedMasterKey = CryptoUtil.encryptSync(masterKey, recoveryKey);
final encryptedRecoveryKey = CryptoUtil.encryptSync(recoveryKey, masterKey);
// Derive a key from the password that will be used to encrypt and
// decrypt the master key
final kekSalt = CryptoUtil.getSaltToDeriveKey();
final derivedKeyResult = await CryptoUtil.deriveSensitiveKey(
utf8.encode(password),
kekSalt,
);
final loginKey = await CryptoUtil.deriveLoginKey(derivedKeyResult.key);
// Encrypt the key with this derived key
final encryptedKeyData =
CryptoUtil.encryptSync(masterKey, derivedKeyResult.key);
// Generate a public-private keypair and encrypt the latter
final keyPair = CryptoUtil.generateKeyPair();
final encryptedSecretKeyData =
CryptoUtil.encryptSync(keyPair.secretKey.extractBytes(), masterKey);
final attributes = KeyAttributes(
CryptoUtil.bin2base64(kekSalt),
CryptoUtil.bin2base64(encryptedKeyData.encryptedData!),
CryptoUtil.bin2base64(encryptedKeyData.nonce!),
CryptoUtil.bin2base64(keyPair.publicKey),
CryptoUtil.bin2base64(encryptedSecretKeyData.encryptedData!),
CryptoUtil.bin2base64(encryptedSecretKeyData.nonce!),
derivedKeyResult.memLimit,
derivedKeyResult.opsLimit,
CryptoUtil.bin2base64(encryptedMasterKey.encryptedData!),
CryptoUtil.bin2base64(encryptedMasterKey.nonce!),
CryptoUtil.bin2base64(encryptedRecoveryKey.encryptedData!),
CryptoUtil.bin2base64(encryptedRecoveryKey.nonce!),
);
final privateAttributes = PrivateKeyAttributes(
CryptoUtil.bin2base64(masterKey),
CryptoUtil.bin2hex(recoveryKey),
CryptoUtil.bin2base64(keyPair.secretKey.extractBytes()),
);
return KeyGenResult(attributes, privateAttributes, loginKey);
}
Future<Tuple2<KeyAttributes, Uint8List>> getAttributesForNewPassword(
String password,
) async {
// Get master key
final masterKey = getKey();
// Derive a key from the password that will be used to encrypt and
// decrypt the master key
final kekSalt = CryptoUtil.getSaltToDeriveKey();
final derivedKeyResult = await CryptoUtil.deriveSensitiveKey(
utf8.encode(password),
kekSalt,
);
final loginKey = await CryptoUtil.deriveLoginKey(derivedKeyResult.key);
// Encrypt the key with this derived key
final encryptedKeyData =
CryptoUtil.encryptSync(masterKey!, derivedKeyResult.key);
final existingAttributes = getKeyAttributes();
final updatedAttributes = existingAttributes!.copyWith(
kekSalt: CryptoUtil.bin2base64(kekSalt),
encryptedKey: CryptoUtil.bin2base64(encryptedKeyData.encryptedData!),
keyDecryptionNonce: CryptoUtil.bin2base64(encryptedKeyData.nonce!),
memLimit: derivedKeyResult.memLimit,
opsLimit: derivedKeyResult.opsLimit,
);
return Tuple2(updatedAttributes, loginKey);
}
// decryptSecretsAndGetLoginKey decrypts the master key and recovery key
// with the given password and save them in local secure storage.
// This method also returns the keyEncKey that can be used for performing
// SRP setup for existing users.
Future<Uint8List> decryptSecretsAndGetKeyEncKey(
String password,
KeyAttributes attributes, {
Uint8List? keyEncryptionKey,
}) async {
_logger.info('Start decryptAndSaveSecrets');
keyEncryptionKey ??= await CryptoUtil.deriveKey(
utf8.encode(password),
CryptoUtil.base642bin(attributes.kekSalt),
attributes.memLimit,
attributes.opsLimit,
);
_logger.info('user-key done');
Uint8List key;
try {
key = CryptoUtil.decryptSync(
CryptoUtil.base642bin(attributes.encryptedKey),
keyEncryptionKey,
CryptoUtil.base642bin(attributes.keyDecryptionNonce),
);
} catch (e) {
_logger.severe('master-key failed, incorrect password?', e);
throw Exception("Incorrect password");
}
_logger.info("master-key done");
await setKey(CryptoUtil.bin2base64(key));
final secretKey = CryptoUtil.decryptSync(
CryptoUtil.base642bin(attributes.encryptedSecretKey),
key,
CryptoUtil.base642bin(attributes.secretKeyDecryptionNonce),
);
_logger.info("secret-key done");
await setSecretKey(CryptoUtil.bin2base64(secretKey));
final token = CryptoUtil.openSealSync(
CryptoUtil.base642bin(getEncryptedToken()!),
CryptoUtil.base642bin(attributes.publicKey),
secretKey,
);
_logger.info('appToken done');
await setToken(
CryptoUtil.bin2base64(token, urlSafe: true),
);
return keyEncryptionKey;
}
Future<void> recover(String recoveryKey) async {
// check if user has entered mnemonic code
if (recoveryKey.contains(' ')) {
final split = recoveryKey.split(' ');
if (split.length != mnemonicKeyWordCount) {
String wordThatIsFollowedByEmptySpaceInSplit = '';
for (int i = 0; i < split.length; i++) {
String word = split[i];
if (word.isEmpty) {
wordThatIsFollowedByEmptySpaceInSplit =
'\n\nExtra space after word at position $i';
break;
}
}
throw AssertionError(
'\nRecovery code should have $mnemonicKeyWordCount words, '
'found ${split.length} words instead.$wordThatIsFollowedByEmptySpaceInSplit',
);
}
recoveryKey = bip39.mnemonicToEntropy(recoveryKey);
}
final attributes = getKeyAttributes();
Uint8List masterKey;
try {
masterKey = await CryptoUtil.decrypt(
CryptoUtil.base642bin(attributes!.masterKeyEncryptedWithRecoveryKey),
CryptoUtil.hex2bin(recoveryKey),
CryptoUtil.base642bin(attributes.masterKeyDecryptionNonce),
);
} catch (e) {
_logger.severe(e);
rethrow;
}
await setKey(CryptoUtil.bin2base64(masterKey));
final secretKey = CryptoUtil.decryptSync(
CryptoUtil.base642bin(attributes.encryptedSecretKey),
masterKey,
CryptoUtil.base642bin(attributes.secretKeyDecryptionNonce),
);
await setSecretKey(CryptoUtil.bin2base64(secretKey));
final token = CryptoUtil.openSealSync(
CryptoUtil.base642bin(getEncryptedToken()!),
CryptoUtil.base642bin(attributes.publicKey),
secretKey,
);
await setToken(
CryptoUtil.bin2base64(token, urlSafe: true),
);
}
String getHttpEndpoint() {
return _preferences.getString(endPointKey) ?? endpoint;
}
Future<void> setHttpEndpoint(String endpoint) async {
await _preferences.setString(endPointKey, endpoint);
Bus.instance.fire(EndpointUpdatedEvent());
}
String? getToken() {
_cachedToken ??= _preferences.getString(tokenKey);
return _cachedToken;
}
bool isLoggedIn() {
return getToken() != null;
}
Future<void> setToken(String token) async {
_cachedToken = token;
await _preferences.setString(tokenKey, token);
Bus.instance.fire(SignedInEvent());
}
Future<void> setEncryptedToken(String encryptedToken) async {
await _preferences.setString(encryptedTokenKey, encryptedToken);
}
String? getEncryptedToken() {
return _preferences.getString(encryptedTokenKey);
}
String? getEmail() {
return _preferences.getString(emailKey);
}
Future<void> setEmail(String email) async {
await _preferences.setString(emailKey, email);
}
int? getUserID() {
return _preferences.getInt(userIDKey);
}
Future<void> setUserID(int userID) async {
await _preferences.setInt(userIDKey, userID);
}
Future<void> setKeyAttributes(KeyAttributes attributes) async {
await _preferences.setString(keyAttributesKey, attributes.toJson());
}
KeyAttributes? getKeyAttributes() {
final jsonValue = _preferences.getString(keyAttributesKey);
if (jsonValue == null) {
return null;
} else {
return KeyAttributes.fromJson(jsonValue);
}
}
Future<void> setKey(String key) async {
_key = key;
await _secureStorage.write(
key: keyKey,
value: key,
);
}
Future<void> setSecretKey(String? secretKey) async {
_secretKey = secretKey;
await _secureStorage.write(
key: secretKeyKey,
value: secretKey,
);
await super.logout();
}
Future<void> setAuthSecretKey(String? authSecretKey) async {
@@ -406,14 +54,6 @@ class Configuration {
);
}
Uint8List? getKey() {
return _key == null ? null : CryptoUtil.base642bin(_key!);
}
Uint8List? getSecretKey() {
return _secretKey == null ? null : CryptoUtil.base642bin(_secretKey!);
}
Uint8List? getAuthSecretKey() {
return _authSecretKey == null
? null
@@ -426,24 +66,6 @@ class Configuration {
: CryptoUtil.base642bin(_offlineAuthKey!);
}
Uint8List getRecoveryKey() {
final keyAttributes = getKeyAttributes()!;
return CryptoUtil.decryptSync(
CryptoUtil.base642bin(keyAttributes.recoveryKeyEncryptedWithMasterKey),
getKey()!,
CryptoUtil.base642bin(keyAttributes.recoveryKeyDecryptionNonce),
);
}
// Caution: This directory is cleared on app start
String getTempDirectory() {
return _tempDirectory;
}
bool hasConfiguredAccount() {
return getToken() != null && _key != null;
}
bool hasOptedForOfflineMode() {
return _preferences.getBool(hasOptedForOfflineModeKey) ?? false;
}
@@ -464,16 +86,4 @@ class Configuration {
}
await _preferences.setBool(hasOptedForOfflineModeKey, true);
}
void setVolatilePassword(String volatilePassword) {
_volatilePassword = volatilePassword;
}
void resetVolatilePassword() {
_volatilePassword = null;
}
String? getVolatilePassword() {
return _volatilePassword;
}
}

View File

@@ -1,3 +1,3 @@
import 'package:ente_auth/events/event.dart';
import 'package:ente_events/models/event.dart';
class CodesUpdatedEvent extends Event {}

View File

@@ -1,3 +0,0 @@
import 'package:ente_auth/events/event.dart';
class EndpointUpdatedEvent extends Event {}

View File

@@ -1,3 +1,3 @@
import 'package:ente_auth/events/event.dart';
import 'package:ente_events/models/event.dart';
class IconsChangedEvent extends Event {}

View File

@@ -1,5 +0,0 @@
import 'package:ente_auth/events/event.dart';
// NotificationEvent event is used to re-fresh the UI to show latest notification
// (if any)
class NotificationEvent extends Event {}

View File

@@ -1,3 +0,0 @@
import 'package:ente_auth/events/event.dart';
class SignedInEvent extends Event {}

View File

@@ -1,3 +1 @@
import 'package:ente_auth/events/event.dart';
class SignedOutEvent extends Event {}
// TODO Implement this library.

View File

@@ -1,3 +1,3 @@
import 'package:ente_auth/events/event.dart';
import 'package:ente_events/models/event.dart';
class TriggerLogoutEvent extends Event {}

View File

@@ -1,8 +1,8 @@
import 'package:dio/dio.dart';
import 'package:ente_auth/core/errors.dart';
import 'package:ente_auth/core/network.dart';
import 'package:ente_auth/models/authenticator/auth_entity.dart';
import 'package:ente_auth/models/authenticator/auth_key.dart';
import 'package:ente_network/network.dart';
class AuthenticatorGateway {
late Dio _enteDio;

View File

@@ -88,6 +88,8 @@
"useRecoveryKey": "Χρήση κλειδιού ανάκτησης",
"incorrectPasswordTitle": "Λάθος κωδικός πρόσβασης",
"welcomeBack": "Καλωσορίσατε και πάλι!",
"emailAlreadyRegistered": "Το email είναι ήδη καταχωρημένο.",
"emailNotRegistered": "Το email δεν έχει καταχωρηθεί.",
"madeWithLoveAtPrefix": "φτιαγμένη με ❤️ στο ",
"supportDevs": "Εγγραφείτε στο <bold-green>ente</bold-green> για να μας υποστηρίξετε",
"supportDiscount": "Χρησιμοποιήστε τον κωδικό κουπονιού \"AUTH\" για να λάβετε 10% έκπτωση για τον πρώτο χρόνο",
@@ -171,6 +173,7 @@
"invalidQRCode": "Μη έγκυρος κωδικός QR",
"noRecoveryKeyTitle": "Χωρίς κλειδί ανάκτησης;",
"enterEmailHint": "Εισάγετε τη διεύθυνση email σας",
"enterNewEmailHint": "Εισάγετε την διεύθυνση ηλ. ταχυδρομείου σας",
"invalidEmailTitle": "Μη έγκυρη διεύθυνση email",
"invalidEmailMessage": "Παρακαλούμε εισάγετε μια έγκυρη διεύθυνση email.",
"deleteAccount": "Διαγραφή λογαριασμού",
@@ -258,6 +261,10 @@
"areYouSureYouWantToLogout": "Είστε σίγουροι ότι θέλετε να αποσυνδεθείτε;",
"yesLogout": "Ναι, αποσύνδεση",
"exit": "Εξοδος",
"theme": "Θέμα",
"lightTheme": "Φωτεινό",
"darkTheme": "Σκοτεινό",
"systemTheme": "Σύστημα",
"verifyingRecoveryKey": "Επαλήθευση κλειδιού ανάκτησης...",
"recoveryKeyVerified": "Το κλειδί ανάκτησης επαληθεύτηκε",
"recoveryKeySuccessBody": "Τέλεια! Το κλειδί ανάκτησης σας είναι έγκυρο. Σας ευχαριστούμε για την επαλήθευση.\n\nΠαρακαλώ θυμηθείτε να κρατήσετε το κλειδί ανάκτησης σας και σε αντίγραφο ασφαλείας.",
@@ -490,5 +497,24 @@
"appLockNotEnabled": "Το κλείδωμα εφαρμογής δεν είναι ενεργοποιημένο",
"appLockNotEnabledDescription": "Παρακαλώ ενεργοποιήστε το κλείδωμα εφαρμογής μέσω της επιλογής Ασφάλεια > Κλείδωμα εφαρμογής",
"authToViewPasskey": "Παρακαλώ πιστοποιηθείτε για να δείτε το κλειδί πρόσβασης",
"appLockOfflineModeWarning": "Έχετε επιλέξει να προχωρήσετε χωρίς αντίγραφα ασφαλείας. Αν ξεχάσετε τον κωδικό της εφαρμογής, θα κλειδωθείτε από την πρόσβαση στα δεδομένα σας."
"appLockOfflineModeWarning": "Έχετε επιλέξει να προχωρήσετε χωρίς αντίγραφα ασφαλείας. Αν ξεχάσετε τον κωδικό της εφαρμογής, θα κλειδωθείτε από την πρόσβαση στα δεδομένα σας.",
"duplicateCodes": "Διπλότυποι κωδικοί",
"noDuplicates": "✨ Δεν υπάρχουν διπλότυπα",
"youveNoDuplicateCodesThatCanBeCleared": "Δεν υπάρχουν διπλότυπα αρχεία που μπορούν να εκκαθαριστούν",
"deduplicateCodes": "Διπλότυποι κωδικοί",
"deselectAll": "Αποεπιλογή όλων",
"selectAll": "Επιλογή όλων",
"deleteDuplicates": "Διαγραφή διπλότυπων",
"plainHTML": "Απλό HTML",
"dropReviewiOS": "Αφήστε μια κριτική στο App Store",
"dropReviewAndroid": "Αφήστε μια κριτική στο Play Store",
"giveUsAStarOnGithub": "Δώστε μας ένα αστέρι στο Github",
"free5GB": "5GB δωρεάν στο <bold-green>ente</bold-green> Photos",
"freeStorageOffer": "10% έκπτωση στο <bold-green>ente</bold-green> photos",
"freeStorageOfferDescription": "Χρησιμοποιήστε τον κωδικό \"AUTH\" για να λάβετε 10% έκπτωση για τον πρώτο χρόνο",
"advanced": "Για προχωρημένους",
"algorithm": "Αλγόριθμος",
"type": "Τύπος",
"period": "Περίοδος",
"digits": "Ψηφία"
}

View File

@@ -45,7 +45,7 @@
"timeBasedKeyType": "Oparte na czasie (TOTP)",
"counterBasedKeyType": "Oparte na liczniku (HOTP)",
"saveAction": "Zapisz",
"nextTotpTitle": "następny",
"nextTotpTitle": "dalej",
"deleteCodeTitle": "Usunąć kod?",
"deleteCodeMessage": "Czy na pewno chcesz usunąć ten kod? Ta akcja jest nieodwracalna.",
"trashCode": "Przenieść kod do kosza?",

View File

@@ -6,4 +6,4 @@ export "package:ente_auth/l10n/arb/app_localizations.dart"
extension AppLocalizationsX on BuildContext {
AppLocalizations get l10n => AppLocalizations.of(this);
}
}

View File

@@ -2,34 +2,38 @@ import 'dart:async';
import 'dart:io';
import 'package:adaptive_theme/adaptive_theme.dart';
import 'package:ente_accounts/services/user_service.dart';
import "package:ente_auth/app/view/app.dart";
import 'package:ente_auth/core/configuration.dart';
import 'package:ente_auth/core/constants.dart';
import 'package:ente_auth/core/logging/super_logging.dart';
import 'package:ente_auth/core/network.dart';
import 'package:ente_auth/ente_theme_data.dart';
import 'package:ente_auth/l10n/l10n.dart';
import 'package:ente_auth/locale.dart';
import 'package:ente_auth/services/authenticator_service.dart';
import 'package:ente_auth/services/billing_service.dart';
import 'package:ente_auth/services/notification_service.dart';
import 'package:ente_auth/services/preference_service.dart';
import 'package:ente_auth/services/update_service.dart';
import 'package:ente_auth/services/user_service.dart';
import 'package:ente_auth/services/window_listener_service.dart';
import 'package:ente_auth/store/authenticator_db.dart';
import 'package:ente_auth/store/code_display_store.dart';
import 'package:ente_auth/store/code_store.dart';
import 'package:ente_auth/ui/tools/app_lock.dart';
import 'package:ente_auth/ui/tools/lock_screen.dart';
import 'package:ente_auth/ui/home_page.dart';
import 'package:ente_auth/ui/utils/icon_utils.dart';
import 'package:ente_auth/utils/directory_utils.dart';
import 'package:ente_auth/utils/lock_screen_settings.dart';
import 'package:ente_auth/utils/platform_util.dart';
import 'package:ente_auth/utils/window_protocol_handler.dart';
import 'package:ente_crypto_dart/ente_crypto_dart.dart';
import 'package:ente_lock_screen/lock_screen_settings.dart';
import 'package:ente_lock_screen/ui/app_lock.dart';
import 'package:ente_lock_screen/ui/lock_screen.dart';
import 'package:ente_logging/logging.dart';
import 'package:ente_network/network.dart';
import 'package:ente_strings/l10n/strings_localizations.dart';
import 'package:ente_ui/theme/theme_config.dart';
import 'package:flutter/foundation.dart';
import "package:flutter/material.dart";
import 'package:flutter_displaymode/flutter_displaymode.dart';
import 'package:logging/logging.dart';
import 'package:path_provider/path_provider.dart';
import 'package:tray_manager/tray_manager.dart';
import 'package:window_manager/window_manager.dart';
@@ -89,7 +93,9 @@ void main() async {
}
Future<void> _runInForeground() async {
AppThemeConfig.initialize(EnteApp.auth);
final savedThemeMode = _themeMode(await AdaptiveTheme.getThemeMode());
final configuration = Configuration.instance;
return await _runWithLogs(() async {
_logger.info("Starting app in foreground");
try {
@@ -103,12 +109,19 @@ Future<void> _runInForeground() async {
runApp(
AppLock(
builder: (args) => App(locale: locale),
lockScreen: const LockScreen(),
lockScreen: LockScreen(configuration),
enabled: await LockScreenSettings.instance.shouldShowLockScreen(),
locale: locale,
lightTheme: lightThemeData,
darkTheme: darkThemeData,
savedThemeMode: savedThemeMode,
localeListResolutionCallback: localResolutionCallBack,
localizationsDelegates: const [
...StringsLocalizations.localizationsDelegates,
...AppLocalizations.localizationsDelegates,
],
supportedLocales: appSupportedLocales,
backgroundLockLatency: const Duration(seconds: 0),
),
);
});
@@ -154,13 +167,13 @@ Future<void> _init(bool bool, {String? via}) async {
await PreferenceService.instance.init();
await CodeStore.instance.init();
await CodeDisplayStore.instance.init();
await Configuration.instance.init();
await Network.instance.init();
await UserService.instance.init();
await Configuration.instance.init([AuthenticatorDB.instance]);
await Network.instance.init(Configuration.instance);
await UserService.instance.init(Configuration.instance, const HomePage());
await AuthenticatorService.instance.init();
await BillingService.instance.init();
await NotificationService.instance.init();
await UpdateService.instance.init();
await IconUtils.instance.init();
await LockScreenSettings.instance.init();
await LockScreenSettings.instance.init(Configuration.instance);
}

View File

@@ -1,65 +0,0 @@
const freeProductID = "free";
const stripe = "stripe";
const appStore = "appstore";
const playStore = "playstore";
class Subscription {
final String productID;
final int storage;
final String originalTransactionID;
final String paymentProvider;
final int expiryTime;
final String price;
final String period;
final Attributes? attributes;
Subscription({
required this.productID,
required this.storage,
required this.originalTransactionID,
required this.paymentProvider,
required this.expiryTime,
required this.price,
required this.period,
this.attributes,
});
bool isValid() {
return expiryTime > DateTime.now().microsecondsSinceEpoch;
}
bool isYearlyPlan() {
return 'year' == period;
}
static fromMap(Map<String, dynamic>? map) {
if (map == null) return null;
return Subscription(
productID: map['productID'],
storage: map['storage'],
originalTransactionID: map['originalTransactionID'],
paymentProvider: map['paymentProvider'],
expiryTime: map['expiryTime'],
price: map['price'],
period: map['period'],
attributes: map["attributes"] != null
? Attributes.fromJson(map["attributes"])
: null,
);
}
}
class Attributes {
bool? isCancelled;
String? customerID;
Attributes({
this.isCancelled,
this.customerID,
});
Attributes.fromJson(dynamic json) {
isCancelled = json["isCancelled"];
customerID = json["customerID"];
}
}

View File

@@ -1,146 +0,0 @@
import 'dart:convert';
import 'dart:math';
import 'package:collection/collection.dart';
import 'package:ente_auth/models/subscription.dart';
class UserDetails {
final String email;
final int usage;
final int fileCount;
final int sharedCollectionsCount;
final Subscription subscription;
final FamilyData? familyData;
final ProfileData? profileData;
UserDetails(
this.email,
this.usage,
this.fileCount,
this.sharedCollectionsCount,
this.subscription,
this.familyData,
this.profileData,
);
bool isPartOfFamily() {
return familyData?.members?.isNotEmpty ?? false;
}
bool isFamilyAdmin() {
assert(isPartOfFamily(), "verify user is part of family before calling");
final FamilyMember currentUserMember = familyData!.members!
.firstWhere((element) => element.email.trim() == email.trim());
return currentUserMember.isAdmin;
}
// getFamilyOrPersonalUsage will return total usage for family if user
// belong to family group. Otherwise, it will return storage consumed by
// current user
int getFamilyOrPersonalUsage() {
return isPartOfFamily() ? familyData!.getTotalUsage() : usage;
}
int getFreeStorage() {
return max(
isPartOfFamily()
? (familyData!.storage - familyData!.getTotalUsage())
: (subscription.storage - (usage)),
0,
);
}
int getTotalStorage() {
return isPartOfFamily() ? familyData!.storage : subscription.storage;
}
factory UserDetails.fromMap(Map<String, dynamic> map) {
return UserDetails(
map['email'] as String,
map['usage'] as int,
(map['fileCount'] ?? 0) as int,
(map['sharedCollectionsCount'] ?? 0) as int,
Subscription.fromMap(map['subscription']),
FamilyData.fromMap(map['familyData']),
ProfileData.fromJson(map['profileData']),
);
}
}
class FamilyMember {
final String email;
final int usage;
final String id;
final bool isAdmin;
FamilyMember(this.email, this.usage, this.id, this.isAdmin);
factory FamilyMember.fromMap(Map<String, dynamic> map) {
return FamilyMember(
(map['email'] ?? '') as String,
map['usage'] as int,
map['id'] as String,
map['isAdmin'] as bool,
);
}
}
class ProfileData {
bool canDisableEmailMFA;
bool isEmailMFAEnabled;
bool isTwoFactorEnabled;
// Constructor with default values
ProfileData({
this.canDisableEmailMFA = false,
this.isEmailMFAEnabled = false,
this.isTwoFactorEnabled = false,
});
// Factory method to create ProfileData instance from JSON
factory ProfileData.fromJson(Map<String, dynamic>? json) {
if (json == null) null;
return ProfileData(
canDisableEmailMFA: json!['canDisableEmailMFA'] ?? false,
isEmailMFAEnabled: json['isEmailMFAEnabled'] ?? false,
isTwoFactorEnabled: json['isTwoFactorEnabled'] ?? false,
);
}
// Method to convert ProfileData instance to JSON
Map<String, dynamic> toJson() {
return {
'canDisableEmailMFA': canDisableEmailMFA,
'isEmailMFAEnabled': isEmailMFAEnabled,
'isTwoFactorEnabled': isTwoFactorEnabled,
};
}
String toJsonString() => json.encode(toJson());
}
class FamilyData {
final List<FamilyMember>? members;
// Storage available based on the family plan
final int storage;
final int expiryTime;
FamilyData(this.members, this.storage, this.expiryTime);
int getTotalUsage() {
return members!.map((e) => e.usage).toList().sum;
}
static fromMap(Map<String, dynamic>? map) {
if (map == null) return null;
assert(map['members'] != null && map['members'].length >= 0);
final members = List<FamilyMember>.from(
map['members'].map((x) => FamilyMember.fromMap(x)),
);
return FamilyData(
members,
map['storage'] as int,
map['expiryTime'] as int,
);
}
}

View File

@@ -1,19 +1,18 @@
import 'dart:async';
import 'dart:io';
import 'package:ente_accounts/pages/email_entry_page.dart';
import 'package:ente_accounts/pages/login_page.dart';
import 'package:ente_accounts/pages/password_entry_page.dart';
import 'package:ente_accounts/pages/password_reentry_page.dart';
import 'package:ente_auth/app/view/app.dart';
import 'package:ente_auth/core/configuration.dart';
import 'package:ente_auth/core/event_bus.dart';
import 'package:ente_auth/ente_theme_data.dart';
import 'package:ente_auth/events/trigger_logout_event.dart';
import "package:ente_auth/l10n/l10n.dart";
import 'package:ente_auth/locale.dart';
import 'package:ente_auth/theme/text_style.dart';
import 'package:ente_auth/ui/account/email_entry_page.dart';
import 'package:ente_auth/ui/account/login_page.dart';
import 'package:ente_auth/ui/account/logout_dialog.dart';
import 'package:ente_auth/ui/account/password_entry_page.dart';
import 'package:ente_auth/ui/account/password_reentry_page.dart';
import 'package:ente_auth/ui/common/gradient_button.dart';
import 'package:ente_auth/ui/components/buttons/button_widget.dart';
import 'package:ente_auth/ui/components/models/button_result.dart';
@@ -24,6 +23,7 @@ import 'package:ente_auth/ui/settings/language_picker.dart';
import 'package:ente_auth/utils/dialog_util.dart';
import 'package:ente_auth/utils/navigation_util.dart';
import 'package:ente_auth/utils/toast_util.dart';
import 'package:ente_events/event_bus.dart';
import 'package:flutter/foundation.dart';
import "package:flutter/material.dart";
import 'package:local_auth/local_auth.dart';
@@ -260,17 +260,22 @@ class _OnboardingPageState extends State<OnboardingPage> {
void _navigateToSignUpPage() {
Widget page;
if (Configuration.instance.getEncryptedToken() == null) {
page = const EmailEntryPage();
page = EmailEntryPage(Configuration.instance);
} else {
// No key
if (Configuration.instance.getKeyAttributes() == null) {
// Never had a key
page = const PasswordEntryPage(
mode: PasswordEntryMode.set,
page = PasswordEntryPage(
Configuration.instance,
PasswordEntryMode.set,
const HomePage(),
);
} else if (Configuration.instance.getKey() == null) {
// Yet to decrypt the key
page = const PasswordReentryPage();
page = PasswordReentryPage(
Configuration.instance,
const HomePage(),
);
} else {
// All is well, user just has not subscribed
page = const HomePage();
@@ -288,17 +293,22 @@ class _OnboardingPageState extends State<OnboardingPage> {
void _navigateToSignInPage() {
Widget page;
if (Configuration.instance.getEncryptedToken() == null) {
page = const LoginPage();
page = LoginPage(Configuration.instance);
} else {
// No key
if (Configuration.instance.getKeyAttributes() == null) {
// Never had a key
page = const PasswordEntryPage(
mode: PasswordEntryMode.set,
page = PasswordEntryPage(
Configuration.instance,
PasswordEntryMode.set,
const HomePage(),
);
} else if (Configuration.instance.getKey() == null) {
// Yet to decrypt the key
page = const PasswordReentryPage();
page = PasswordReentryPage(
Configuration.instance,
const HomePage(),
);
} else {
// All is well, user just has not subscribed
// page = getSubscriptionPage(isOnBoarding: true);

View File

@@ -1,6 +1,5 @@
import 'dart:async';
import 'package:ente_auth/core/event_bus.dart';
import 'package:ente_auth/events/codes_updated_event.dart';
import "package:ente_auth/l10n/l10n.dart";
import 'package:ente_auth/models/all_icon_data.dart';
@@ -23,6 +22,7 @@ import 'package:ente_auth/ui/utils/icon_utils.dart';
import 'package:ente_auth/utils/dialog_util.dart';
import 'package:ente_auth/utils/toast_util.dart';
import 'package:ente_auth/utils/totp_util.dart';
import 'package:ente_events/event_bus.dart';
import "package:flutter/material.dart";
import 'package:logging/logging.dart';

View File

@@ -4,9 +4,7 @@ import 'dart:math';
import 'package:ente_auth/core/configuration.dart';
import 'package:ente_auth/core/errors.dart';
import 'package:ente_auth/core/event_bus.dart';
import 'package:ente_auth/events/codes_updated_event.dart';
import 'package:ente_auth/events/signed_in_event.dart';
import 'package:ente_auth/events/trigger_logout_event.dart';
import 'package:ente_auth/gateway/authenticator.dart';
import 'package:ente_auth/models/authenticator/auth_entity.dart';
@@ -17,6 +15,8 @@ import 'package:ente_auth/services/preference_service.dart';
import 'package:ente_auth/store/authenticator_db.dart';
import 'package:ente_auth/store/offline_authenticator_db.dart';
import 'package:ente_crypto_dart/ente_crypto_dart.dart';
import 'package:ente_events/event_bus.dart';
import 'package:ente_events/models/signed_in_event.dart';
import 'package:flutter/foundation.dart';
import 'package:logging/logging.dart';
import 'package:shared_preferences/shared_preferences.dart';

View File

@@ -1,11 +1,11 @@
import 'dart:io';
import 'package:dio/dio.dart';
import 'package:ente_accounts/ente_accounts.dart';
import 'package:ente_auth/core/configuration.dart';
import 'package:ente_auth/core/errors.dart';
import 'package:ente_auth/core/network.dart';
import 'package:ente_auth/models/billing_plan.dart';
import 'package:ente_auth/models/subscription.dart';
import 'package:ente_auth/models/billing_plan.dart';
import 'package:ente_network/network.dart';
import 'package:logging/logging.dart';
const kWebPaymentRedirectUrl = "https://payments.ente.io/frameRedirect";

View File

@@ -1,5 +1,5 @@
import 'package:ente_auth/core/event_bus.dart';
import 'package:ente_auth/events/icons_changed_event.dart';
import 'package:ente_events/event_bus.dart';
import 'package:shared_preferences/shared_preferences.dart';
enum CodeSortKey {

View File

@@ -2,9 +2,9 @@ import 'dart:async';
import 'dart:io';
import 'package:ente_auth/core/constants.dart';
import 'package:ente_auth/core/network.dart';
import 'package:ente_auth/services/notification_service.dart';
import 'package:ente_auth/utils/platform_util.dart';
import 'package:ente_network/network.dart';
import 'package:logging/logging.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:shared_preferences/shared_preferences.dart';

View File

@@ -4,13 +4,14 @@ import 'dart:io';
import 'package:ente_auth/models/authenticator/auth_entity.dart';
import 'package:ente_auth/models/authenticator/local_auth_entity.dart';
import 'package:ente_auth/utils/directory_utils.dart';
import 'package:ente_base/ente_base.dart';
import 'package:flutter/foundation.dart';
import 'package:path/path.dart';
import 'package:path_provider/path_provider.dart';
import 'package:sqflite/sqflite.dart';
import 'package:sqflite_common_ffi/sqflite_ffi.dart';
class AuthenticatorDB {
class AuthenticatorDB extends EnteBaseDatabase {
static const _databaseName = "ente.authenticator.db";
static const _databaseVersion = 1;

View File

@@ -3,12 +3,12 @@ import 'dart:convert';
import 'package:collection/collection.dart';
import 'package:ente_auth/core/configuration.dart';
import 'package:ente_auth/core/event_bus.dart';
import 'package:ente_auth/events/codes_updated_event.dart';
import 'package:ente_auth/models/authenticator/entity_result.dart';
import 'package:ente_auth/models/code.dart';
import 'package:ente_auth/services/authenticator_service.dart';
import 'package:ente_auth/store/offline_authenticator_db.dart';
import 'package:ente_events/event_bus.dart';
import 'package:logging/logging.dart';
class CodeStore {

View File

@@ -1,7 +1,7 @@
import 'package:ente_auth/core/configuration.dart';
import 'package:ente_auth/l10n/l10n.dart';
import 'package:ente_auth/store/authenticator_db.dart';
import 'package:ente_auth/utils/dialog_util.dart';
import 'package:ente_auth/utils/dialog_util.dart';
import 'package:flutter/material.dart';
import 'package:logging/logging.dart';

View File

@@ -9,7 +9,6 @@ import 'package:ente_auth/l10n/l10n.dart';
import 'package:ente_auth/models/code.dart';
import 'package:ente_auth/onboarding/view/setup_enter_secret_key_page.dart';
import 'package:ente_auth/onboarding/view/view_qr_page.dart';
import 'package:ente_auth/services/local_authentication_service.dart';
import 'package:ente_auth/services/preference_service.dart';
import 'package:ente_auth/store/code_store.dart';
import 'package:ente_auth/theme/ente_theme.dart';
@@ -22,6 +21,7 @@ import 'package:ente_auth/utils/dialog_util.dart';
import 'package:ente_auth/utils/platform_util.dart';
import 'package:ente_auth/utils/toast_util.dart';
import 'package:ente_auth/utils/totp_util.dart';
import 'package:ente_lock_screen/local_authentication_service.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_context_menu/flutter_context_menu.dart';

View File

@@ -1,9 +1,9 @@
import 'package:ente_auth/ente_theme_data.dart';
import 'package:ente_auth/models/typedefs.dart';
import 'package:ente_auth/ente_theme_data.dart';
import 'package:ente_auth/ui/components/buttons/button_widget.dart';
import 'package:ente_auth/ui/components/dialog_widget.dart';
import 'package:ente_auth/ui/components/models/button_result.dart';
import 'package:ente_auth/ui/components/models/button_type.dart';
import 'package:ente_base/typedefs.dart';
import 'package:flutter/material.dart';
enum DialogUserChoice { firstChoice, secondChoice }

View File

@@ -1,5 +1,4 @@
import 'package:ente_auth/models/execution_states.dart';
import 'package:ente_auth/models/typedefs.dart';
import 'package:ente_auth/models/execution_states.dart';
import 'package:ente_auth/theme/colors.dart';
import 'package:ente_auth/theme/ente_theme.dart';
import 'package:ente_auth/theme/text_style.dart';
@@ -9,6 +8,7 @@ import 'package:ente_auth/ui/components/models/button_type.dart';
import 'package:ente_auth/ui/components/models/custom_button_style.dart';
import 'package:ente_auth/utils/debouncer.dart';
import "package:ente_auth/utils/dialog_util.dart";
import 'package:ente_base/typedefs.dart';
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';

View File

@@ -1,7 +1,6 @@
import 'dart:math';
import 'package:ente_auth/l10n/l10n.dart';
import 'package:ente_auth/models/typedefs.dart';
import 'package:ente_auth/l10n/l10n.dart';
import 'package:ente_auth/theme/colors.dart';
import 'package:ente_auth/theme/effects.dart';
import 'package:ente_auth/theme/ente_theme.dart';
@@ -11,6 +10,7 @@ import 'package:ente_auth/ui/components/models/button_result.dart';
import 'package:ente_auth/ui/components/models/button_type.dart';
import 'package:ente_auth/ui/components/separators.dart';
import 'package:ente_auth/ui/components/text_input_widget.dart';
import 'package:ente_base/typedefs.dart';
import 'package:flutter/material.dart';
///Will return null if dismissed by tapping outside

View File

@@ -1,8 +1,8 @@
import 'package:ente_auth/models/execution_states.dart';
import 'package:ente_auth/models/typedefs.dart';
import 'package:ente_auth/models/execution_states.dart';
import 'package:ente_auth/theme/ente_theme.dart';
import 'package:ente_auth/ui/components/menu_item_child_widgets.dart';
import 'package:ente_auth/utils/debouncer.dart';
import 'package:ente_base/typedefs.dart';
import 'package:expandable/expandable.dart';
import 'package:flutter/material.dart';

View File

@@ -1,9 +1,9 @@
import 'package:ente_auth/models/execution_states.dart';
import 'package:ente_auth/models/typedefs.dart';
import 'package:ente_auth/models/execution_states.dart';
import 'package:ente_auth/theme/ente_theme.dart';
import 'package:ente_auth/ui/common/loading_widget.dart';
import 'package:ente_auth/ui/components/separators.dart';
import 'package:ente_auth/utils/debouncer.dart';
import 'package:ente_base/typedefs.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:logging/logging.dart';

View File

@@ -1,9 +1,9 @@
import 'package:ente_auth/ente_theme_data.dart';
import 'package:ente_auth/models/execution_states.dart';
import 'package:ente_auth/models/typedefs.dart';
import 'package:ente_auth/theme/colors.dart';
import 'package:ente_auth/models/execution_states.dart';
import 'package:ente_auth/theme/colors.dart';
import 'package:ente_auth/ui/common/loading_widget.dart';
import 'package:ente_auth/utils/debouncer.dart';
import 'package:ente_base/typedefs.dart';
import 'package:flutter/material.dart';
typedef OnChangedCallBack = void Function(bool);

View File

@@ -1,10 +1,10 @@
import 'dart:ui';
import 'package:ente_auth/core/event_bus.dart';
import 'package:ente_auth/events/codes_updated_event.dart';
import 'package:ente_auth/l10n/l10n.dart';
import 'package:ente_auth/services/preference_service.dart';
import 'package:ente_auth/utils/platform_util.dart';
import 'package:ente_events/event_bus.dart';
import 'package:flutter/material.dart';
class CoachMarkWidget extends StatelessWidget {

View File

@@ -3,8 +3,8 @@ import 'dart:io';
import 'package:app_links/app_links.dart';
import 'package:collection/collection.dart';
import 'package:ente_accounts/services/user_service.dart';
import 'package:ente_auth/core/configuration.dart';
import 'package:ente_auth/core/event_bus.dart';
import 'package:ente_auth/ente_theme_data.dart';
import 'package:ente_auth/events/codes_updated_event.dart';
import 'package:ente_auth/events/icons_changed_event.dart';
@@ -15,7 +15,6 @@ import 'package:ente_auth/onboarding/model/tag_enums.dart';
import 'package:ente_auth/onboarding/view/common/tag_chip.dart';
import 'package:ente_auth/onboarding/view/setup_enter_secret_key_page.dart';
import 'package:ente_auth/services/preference_service.dart';
import 'package:ente_auth/services/user_service.dart';
import 'package:ente_auth/store/code_display_store.dart';
import 'package:ente_auth/store/code_store.dart';
import 'package:ente_auth/theme/ente_theme.dart';
@@ -34,11 +33,13 @@ import 'package:ente_auth/ui/reorder_codes_page.dart';
import 'package:ente_auth/ui/scanner_page.dart';
import 'package:ente_auth/ui/settings_page.dart';
import 'package:ente_auth/ui/sort_option_menu.dart';
import 'package:ente_auth/ui/tools/app_lock.dart';
import 'package:ente_auth/utils/dialog_util.dart';
import 'package:ente_auth/utils/lock_screen_settings.dart';
import 'package:ente_auth/utils/platform_util.dart';
import 'package:ente_auth/utils/totp_util.dart';
import 'package:ente_events/event_bus.dart';
import 'package:ente_lock_screen/lock_screen_settings.dart';
import 'package:ente_lock_screen/ui/app_lock.dart';
import 'package:ente_ui/pages/base_home_page.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
@@ -47,7 +48,7 @@ import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
import 'package:logging/logging.dart';
import 'package:move_to_background/move_to_background.dart';
class HomePage extends StatefulWidget {
class HomePage extends BaseHomePage {
const HomePage({super.key});
@override

View File

@@ -4,7 +4,7 @@ import 'package:ente_auth/l10n/l10n.dart';
import 'package:ente_auth/models/code.dart';
import 'package:ente_auth/utils/toast_util.dart';
import 'package:flutter/material.dart';
import 'package:qr_code_scanner/qr_code_scanner.dart';
import 'package:qr_code_scanner/qr_code_scanner.dart';
class ScannerPage extends StatefulWidget {
const ScannerPage({super.key});

View File

@@ -1,20 +1,21 @@
import 'package:ente_accounts/pages/change_email_dialog.dart';
import 'package:ente_accounts/pages/delete_account_page.dart';
import 'package:ente_accounts/pages/password_entry_page.dart';
import 'package:ente_accounts/pages/recovery_key_page.dart';
import 'package:ente_accounts/services/user_service.dart';
import 'package:ente_auth/core/configuration.dart';
import 'package:ente_auth/l10n/l10n.dart';
import 'package:ente_auth/services/local_authentication_service.dart';
import 'package:ente_auth/services/user_service.dart';
import 'package:ente_auth/theme/ente_theme.dart';
import 'package:ente_auth/ui/account/change_email_dialog.dart';
import 'package:ente_auth/ui/account/delete_account_page.dart';
import 'package:ente_auth/ui/account/password_entry_page.dart';
import 'package:ente_auth/ui/account/recovery_key_page.dart';
import 'package:ente_auth/ui/components/captioned_text_widget.dart';
import 'package:ente_auth/ui/components/expandable_menu_item_widget.dart';
import 'package:ente_auth/ui/components/menu_item_widget.dart';
import 'package:ente_auth/ui/home_page.dart';
import 'package:ente_auth/ui/settings/common_settings.dart';
import 'package:ente_auth/utils/dialog_util.dart';
import 'package:ente_auth/utils/navigation_util.dart';
import 'package:ente_auth/utils/platform_util.dart';
import 'package:ente_crypto_dart/ente_crypto_dart.dart';
import 'package:ente_lock_screen/local_authentication_service.dart';
import 'package:flutter/material.dart';
class AccountSectionWidget extends StatelessWidget {
@@ -81,8 +82,10 @@ class AccountSectionWidget extends StatelessWidget {
Navigator.of(context).push(
MaterialPageRoute(
builder: (BuildContext context) {
return const PasswordEntryPage(
mode: PasswordEntryMode.update,
return PasswordEntryPage(
Configuration.instance,
PasswordEntryMode.update,
const HomePage(),
);
},
),
@@ -121,6 +124,7 @@ class AccountSectionWidget extends StatelessWidget {
routeToPage(
context,
RecoveryKeyPage(
Configuration.instance,
recoveryKey,
l10n.ok,
showAppBar: true,
@@ -151,8 +155,9 @@ class AccountSectionWidget extends StatelessWidget {
trailingIcon: Icons.chevron_right_outlined,
trailingIconIsMuted: true,
onTap: () async {
final config = Configuration.instance;
// ignore: unawaited_futures
routeToPage(context, const DeleteAccountPage());
routeToPage(context, DeleteAccountPage(config));
},
),
sectionOptionSpacing,

View File

@@ -1,11 +1,11 @@
import 'package:ente_auth/l10n/l10n.dart';
import 'package:ente_auth/models/code.dart';
import 'package:ente_auth/services/deduplication_service.dart';
import 'package:ente_auth/services/local_authentication_service.dart';
import 'package:ente_auth/store/code_store.dart';
import 'package:ente_auth/theme/ente_theme.dart';
import 'package:ente_auth/ui/code_widget.dart';
import 'package:ente_auth/utils/dialog_util.dart';
import 'package:ente_lock_screen/local_authentication_service.dart';
import 'package:flutter/material.dart';
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
import 'package:logging/logging.dart';

View File

@@ -2,8 +2,7 @@ import 'dart:convert';
import 'dart:io';
import 'package:ente_auth/core/configuration.dart';
import 'package:ente_auth/l10n/l10n.dart';
import 'package:ente_auth/models/export/ente.dart';
import 'package:ente_auth/services/local_authentication_service.dart';
import 'package:ente_auth/models/export/ente.dart';
import 'package:ente_auth/store/code_store.dart';
import 'package:ente_auth/ui/components/buttons/button_widget.dart';
import 'package:ente_auth/ui/components/dialog_widget.dart';
@@ -14,6 +13,7 @@ import 'package:ente_auth/utils/platform_util.dart';
import 'package:ente_auth/utils/share_utils.dart';
import 'package:ente_auth/utils/toast_util.dart';
import 'package:ente_crypto_dart/ente_crypto_dart.dart';
import 'package:ente_lock_screen/local_authentication_service.dart';
import 'package:file_saver/file_saver.dart';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';

View File

@@ -1,8 +1,6 @@
import 'dart:io';
import 'package:ente_auth/app/view/app.dart';
import 'package:ente_auth/core/event_bus.dart';
import 'package:ente_auth/core/logging/super_logging.dart';
import 'package:ente_auth/events/icons_changed_event.dart';
import 'package:ente_auth/l10n/l10n.dart';
import 'package:ente_auth/locale.dart';
@@ -16,6 +14,8 @@ import 'package:ente_auth/ui/settings/common_settings.dart';
import 'package:ente_auth/ui/settings/language_picker.dart';
import 'package:ente_auth/utils/navigation_util.dart';
import 'package:ente_auth/utils/toast_util.dart';
import 'package:ente_events/event_bus.dart';
import 'package:ente_logging/logging.dart';
import 'package:flutter/material.dart';
class AdvancedSectionWidget extends StatefulWidget {

View File

@@ -1,10 +1,10 @@
import 'dart:io';
import 'package:ente_accounts/models/user_details.dart';
import 'package:ente_accounts/services/user_service.dart';
import 'package:ente_auth/core/configuration.dart';
import 'package:ente_auth/l10n/l10n.dart';
import 'package:ente_auth/models/user_details.dart';
import 'package:ente_auth/services/preference_service.dart';
import 'package:ente_auth/services/user_service.dart';
import 'package:ente_auth/ui/components/banner_widget.dart';
import 'package:flutter/material.dart';

View File

@@ -1,15 +1,14 @@
import 'dart:async';
import 'dart:typed_data';
import 'package:ente_accounts/models/user_details.dart';
import 'package:ente_accounts/pages/request_pwd_verification_page.dart';
import 'package:ente_accounts/pages/sessions_page.dart';
import 'package:ente_accounts/services/passkey_service.dart';
import 'package:ente_accounts/services/user_service.dart';
import 'package:ente_auth/core/configuration.dart';
import 'package:ente_auth/l10n/l10n.dart';
import 'package:ente_auth/models/user_details.dart';
import 'package:ente_auth/services/local_authentication_service.dart';
import 'package:ente_auth/services/passkey_service.dart';
import 'package:ente_auth/services/user_service.dart';
import 'package:ente_auth/theme/ente_theme.dart';
import 'package:ente_auth/ui/account/request_pwd_verification_page.dart';
import 'package:ente_auth/ui/account/sessions_page.dart';
import 'package:ente_auth/ui/components/buttons/button_widget.dart';
import 'package:ente_auth/ui/components/captioned_text_widget.dart';
import 'package:ente_auth/ui/components/expandable_menu_item_widget.dart';
@@ -17,14 +16,15 @@ import 'package:ente_auth/ui/components/menu_item_widget.dart';
import 'package:ente_auth/ui/components/models/button_result.dart';
import 'package:ente_auth/ui/components/toggle_switch_widget.dart';
import 'package:ente_auth/ui/settings/common_settings.dart';
import 'package:ente_auth/ui/settings/lock_screen/lock_screen_options.dart';
import 'package:ente_auth/utils/auth_util.dart';
import 'package:ente_auth/utils/dialog_util.dart';
import 'package:ente_auth/utils/lock_screen_settings.dart';
import 'package:ente_auth/utils/navigation_util.dart';
import 'package:ente_auth/utils/platform_util.dart';
import 'package:ente_auth/utils/toast_util.dart';
import 'package:ente_crypto_dart/ente_crypto_dart.dart';
import 'package:ente_lock_screen/auth_util.dart';
import 'package:ente_lock_screen/local_authentication_service.dart';
import 'package:ente_lock_screen/lock_screen_settings.dart';
import 'package:ente_lock_screen/ui/lock_screen_options.dart';
import 'package:flutter/material.dart';
import 'package:logging/logging.dart';
@@ -128,7 +128,7 @@ class _SecuritySectionWidgetState extends State<SecuritySectionWidget> {
Navigator.of(context).push(
MaterialPageRoute(
builder: (BuildContext context) {
return const SessionsPage();
return SessionsPage(Configuration.instance);
},
),
);
@@ -243,6 +243,7 @@ class _SecuritySectionWidgetState extends State<SecuritySectionWidget> {
await routeToPage(
context,
RequestPasswordVerificationPage(
Configuration.instance,
onPasswordVerified: (Uint8List keyEncryptionKey) async {
final Uint8List loginKey =
await CryptoUtil.deriveLoginKey(keyEncryptionKey);

View File

@@ -1,10 +1,9 @@
import 'dart:io';
import 'package:ente_accounts/services/user_service.dart';
import 'package:ente_auth/core/configuration.dart';
import 'package:ente_auth/l10n/l10n.dart';
import 'package:ente_auth/onboarding/view/onboarding_page.dart';
import 'package:ente_auth/services/local_authentication_service.dart';
import 'package:ente_auth/services/user_service.dart';
import 'package:ente_auth/onboarding/view/onboarding_page.dart';
import 'package:ente_auth/store/code_store.dart';
import 'package:ente_auth/theme/colors.dart';
import 'package:ente_auth/theme/ente_theme.dart';
@@ -27,6 +26,7 @@ import 'package:ente_auth/ui/settings/title_bar_widget.dart';
import 'package:ente_auth/utils/dialog_util.dart';
import 'package:ente_auth/utils/navigation_util.dart';
import 'package:ente_auth/utils/platform_util.dart';
import 'package:ente_lock_screen/local_authentication_service.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';

View File

@@ -3,8 +3,7 @@ import 'dart:math';
import 'package:confetti/confetti.dart';
import "package:dio/dio.dart";
import 'package:ente_auth/l10n/l10n.dart';
import 'package:ente_auth/models/typedefs.dart';
import 'package:ente_auth/l10n/l10n.dart';
import 'package:ente_auth/theme/colors.dart';
import 'package:ente_auth/ui/common/loading_widget.dart';
import 'package:ente_auth/ui/common/progress_dialog.dart';
@@ -16,6 +15,7 @@ import 'package:ente_auth/ui/components/models/button_result.dart';
import 'package:ente_auth/ui/components/models/button_type.dart';
import 'package:ente_auth/utils/email_util.dart';
import 'package:ente_auth/utils/platform_util.dart';
import 'package:ente_base/typedefs.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';

View File

@@ -3,7 +3,6 @@ import 'dart:io';
import 'package:archive/archive_io.dart';
import 'package:email_validator/email_validator.dart';
import 'package:ente_auth/core/configuration.dart';
import 'package:ente_auth/core/logging/super_logging.dart';
import 'package:ente_auth/l10n/l10n.dart';
import 'package:ente_auth/ui/components/buttons/button_widget.dart';
import 'package:ente_auth/ui/components/dialog_widget.dart';
@@ -14,11 +13,11 @@ import 'package:ente_auth/utils/directory_utils.dart';
import 'package:ente_auth/utils/platform_util.dart';
import 'package:ente_auth/utils/share_utils.dart';
import 'package:ente_auth/utils/toast_util.dart';
import 'package:ente_logging/logging.dart';
import "package:file_saver/file_saver.dart";
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import "package:intl/intl.dart";
import 'package:logging/logging.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:path_provider/path_provider.dart';
import 'package:share_plus/share_plus.dart';

View File

@@ -59,14 +59,14 @@ class PlatformUtil {
if (Platform.isAndroid || Platform.isIOS) {
await FileSaver.instance.saveAs(
name: fileName,
ext: extension,
fileExtension: extension,
bytes: bytes,
mimeType: type,
);
} else {
await FileSaver.instance.saveFile(
name: fileName,
ext: extension,
fileExtension: extension,
bytes: bytes,
mimeType: type,
);

View File

@@ -393,6 +393,27 @@ packages:
url: "https://pub.dev"
source: hosted
version: "3.0.0"
ente_accounts:
dependency: "direct main"
description:
path: "../../packages/accounts"
relative: true
source: path
version: "1.0.0"
ente_base:
dependency: "direct main"
description:
path: "../../packages/base"
relative: true
source: path
version: "1.0.0"
ente_configuration:
dependency: "direct main"
description:
path: "../../packages/configuration"
relative: true
source: path
version: "1.0.0"
ente_crypto_dart:
dependency: "direct main"
description:
@@ -402,6 +423,55 @@ packages:
url: "https://github.com/ente-io/ente_crypto_dart.git"
source: git
version: "1.0.0"
ente_events:
dependency: "direct main"
description:
path: "../../packages/events"
relative: true
source: path
version: "1.0.0"
ente_lock_screen:
dependency: "direct main"
description:
path: "../../packages/lock_screen"
relative: true
source: path
version: "1.0.0"
ente_logging:
dependency: "direct main"
description:
path: "../../packages/logging"
relative: true
source: path
version: "1.0.0"
ente_network:
dependency: "direct main"
description:
path: "../../packages/network"
relative: true
source: path
version: "1.0.0"
ente_strings:
dependency: "direct main"
description:
path: "../../packages/strings"
relative: true
source: path
version: "1.0.0"
ente_ui:
dependency: "direct main"
description:
path: "../../packages/ui"
relative: true
source: path
version: "1.0.0"
ente_utils:
dependency: transitive
description:
path: "../../packages/utils"
relative: true
source: path
version: "1.0.0"
event_bus:
dependency: "direct main"
description:
@@ -470,10 +540,10 @@ packages:
dependency: "direct main"
description:
name: file_saver
sha256: "448b1e30142cffe52f37ee085ea9ca50670d5425bb09b649d193549b2dcf6e26"
sha256: "9d93db09bd4da9e43238f9dd485360fc51a5c138eea5ef5f407ec56e58079ac0"
url: "https://pub.dev"
source: hosted
version: "0.3.0"
version: "0.3.1"
fixnum:
dependency: "direct main"
description:
@@ -485,10 +555,11 @@ packages:
fk_user_agent:
dependency: "direct main"
description:
name: fk_user_agent
sha256: fd6c94e120786985a292d12f61422a581f4e851148d5940af38b819357b8ad0d
url: "https://pub.dev"
source: hosted
path: "."
ref: "458046cd9a88924e5074d96ba45397219d53b230"
resolved-ref: "458046cd9a88924e5074d96ba45397219d53b230"
url: "https://github.com/flutter-fast-kit/fk_user_agent"
source: git
version: "2.1.0"
flutter:
dependency: "direct main"
@@ -538,21 +609,19 @@ packages:
flutter_inappwebview:
dependency: "direct main"
description:
path: flutter_inappwebview
ref: "3e6c4c4a25340cd363af9d38891d88498b90be26"
resolved-ref: "3e6c4c4a25340cd363af9d38891d88498b90be26"
url: "https://github.com/pichillilorenzo/flutter_inappwebview.git"
source: git
version: "6.2.0-beta.3"
name: flutter_inappwebview
sha256: "80092d13d3e29b6227e25b67973c67c7210bd5e35c4b747ca908e31eb71a46d5"
url: "https://pub.dev"
source: hosted
version: "6.1.5"
flutter_inappwebview_android:
dependency: transitive
description:
path: flutter_inappwebview_android
ref: "3e6c4c4a25340cd363af9d38891d88498b90be26"
resolved-ref: "3e6c4c4a25340cd363af9d38891d88498b90be26"
url: "https://github.com/pichillilorenzo/flutter_inappwebview.git"
source: git
version: "1.2.0-beta.3"
name: flutter_inappwebview_android
sha256: "62557c15a5c2db5d195cb3892aab74fcaec266d7b86d59a6f0027abd672cddba"
url: "https://pub.dev"
source: hosted
version: "1.1.3"
flutter_inappwebview_internal_annotations:
dependency: transitive
description:
@@ -564,48 +633,43 @@ packages:
flutter_inappwebview_ios:
dependency: transitive
description:
path: flutter_inappwebview_ios
ref: "3e6c4c4a25340cd363af9d38891d88498b90be26"
resolved-ref: "3e6c4c4a25340cd363af9d38891d88498b90be26"
url: "https://github.com/pichillilorenzo/flutter_inappwebview.git"
source: git
version: "1.2.0-beta.3"
name: flutter_inappwebview_ios
sha256: "5818cf9b26cf0cbb0f62ff50772217d41ea8d3d9cc00279c45f8aabaa1b4025d"
url: "https://pub.dev"
source: hosted
version: "1.1.2"
flutter_inappwebview_macos:
dependency: transitive
description:
path: flutter_inappwebview_macos
ref: "3e6c4c4a25340cd363af9d38891d88498b90be26"
resolved-ref: "3e6c4c4a25340cd363af9d38891d88498b90be26"
url: "https://github.com/pichillilorenzo/flutter_inappwebview.git"
source: git
version: "1.2.0-beta.3"
name: flutter_inappwebview_macos
sha256: c1fbb86af1a3738e3541364d7d1866315ffb0468a1a77e34198c9be571287da1
url: "https://pub.dev"
source: hosted
version: "1.1.2"
flutter_inappwebview_platform_interface:
dependency: transitive
description:
path: flutter_inappwebview_platform_interface
ref: "3e6c4c4a25340cd363af9d38891d88498b90be26"
resolved-ref: "3e6c4c4a25340cd363af9d38891d88498b90be26"
url: "https://github.com/pichillilorenzo/flutter_inappwebview.git"
source: git
version: "1.4.0-beta.3"
name: flutter_inappwebview_platform_interface
sha256: cf5323e194096b6ede7a1ca808c3e0a078e4b33cc3f6338977d75b4024ba2500
url: "https://pub.dev"
source: hosted
version: "1.3.0+1"
flutter_inappwebview_web:
dependency: transitive
description:
path: flutter_inappwebview_web
ref: "3e6c4c4a25340cd363af9d38891d88498b90be26"
resolved-ref: "3e6c4c4a25340cd363af9d38891d88498b90be26"
url: "https://github.com/pichillilorenzo/flutter_inappwebview.git"
source: git
version: "1.2.0-beta.3"
name: flutter_inappwebview_web
sha256: "55f89c83b0a0d3b7893306b3bb545ba4770a4df018204917148ebb42dc14a598"
url: "https://pub.dev"
source: hosted
version: "1.1.2"
flutter_inappwebview_windows:
dependency: transitive
description:
path: flutter_inappwebview_windows
ref: "3e6c4c4a25340cd363af9d38891d88498b90be26"
resolved-ref: "3e6c4c4a25340cd363af9d38891d88498b90be26"
url: "https://github.com/pichillilorenzo/flutter_inappwebview.git"
source: git
version: "0.7.0-beta.3"
name: flutter_inappwebview_windows
sha256: "8b4d3a46078a2cdc636c4a3d10d10f2a16882f6be607962dbfff8874d1642055"
url: "https://pub.dev"
source: hosted
version: "0.6.0"
flutter_launcher_icons:
dependency: "direct main"
description:
@@ -1081,10 +1145,11 @@ packages:
move_to_background:
dependency: "direct main"
description:
name: move_to_background
sha256: "00caad17a6ce149910777131503f43f8ed80025681f94684e3a6a87d979b914c"
url: "https://pub.dev"
source: hosted
path: "."
ref: "91e4d1a9c55b28bf93425d1f12faf410efc1e48d"
resolved-ref: "91e4d1a9c55b28bf93425d1f12faf410efc1e48d"
url: "https://github.com/Sayegh7/move_to_background"
source: git
version: "1.0.2"
native_dio_adapter:
dependency: "direct main"
@@ -1329,11 +1394,12 @@ packages:
qr_code_scanner:
dependency: "direct main"
description:
name: qr_code_scanner
sha256: f23b68d893505a424f0bd2e324ebea71ed88465d572d26bb8d2e78a4749591fd
url: "https://pub.dev"
source: hosted
version: "1.0.1"
path: "."
ref: a2d31633d4744f72ada87cfa85d221358ab082af
resolved-ref: a2d31633d4744f72ada87cfa85d221358ab082af
url: "https://github.com/juliuscanute/qr_code_scanner"
source: git
version: "1.0.0"
qr_flutter:
dependency: "direct main"
description:
@@ -1731,6 +1797,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.4.0"
ua_client_hints:
dependency: transitive
description:
name: ua_client_hints
sha256: "1b8759a46bfeab355252881df27f2604c01bded86aa2b578869fb1b638b23118"
url: "https://pub.dev"
source: hosted
version: "1.4.1"
universal_io:
dependency: transitive
description:

View File

@@ -1,19 +1,18 @@
name: ente_auth
description: ente two-factor authenticator
version: 4.4.3+443
version: 4.4.6+446
publish_to: none
environment:
sdk: ">=3.0.0 <4.0.0"
dependencies:
adaptive_theme: ^3.1.0 # done
adaptive_theme: ^3.1.0
app_links: ^6.3.3
archive: ^4.0.7
auto_size_text: ^3.0.0
base32: ^2.1.3
bip39: ^1.0.6 #done
bip39: ^1.0.6
bloc: ^9.0.0
clipboard: ^0.1.3
collection: ^1.18.0 # dart
@@ -25,19 +24,39 @@ dependencies:
dotted_border: ^3.1.0
dropdown_button2: ^2.3.9
email_validator: ^3.0.0
ente_accounts:
path: ../../packages/accounts
ente_base:
path: ../../packages/base
ente_configuration:
path: ../../packages/configuration
ente_crypto_dart:
git:
url: https://github.com/ente-io/ente_crypto_dart.git
ente_events:
path: ../../packages/events
ente_lock_screen:
path: ../../packages/lock_screen
ente_logging:
path: ../../packages/logging
ente_network:
path: ../../packages/network
ente_strings:
path: ../../packages/strings
ente_ui:
path: ../../packages/ui
event_bus: ^2.0.0
expandable: ^5.0.1
expansion_tile_card: ^3.0.0
ffi: ^2.1.0
figma_squircle: ^0.6.3
file_picker: ^10.2.0
# https://github.com/incrediblezayed/file_saver/issues/86
file_saver: ^0.3.0
file_saver: ^0.3.1
fixnum: ^1.1.0
fk_user_agent: ^2.1.0
fk_user_agent: # no package updates on pub.dev
git:
url: https://github.com/flutter-fast-kit/fk_user_agent
ref: 458046cd9a88924e5074d96ba45397219d53b230
flutter:
sdk: flutter
flutter_animate: ^4.1.0
@@ -47,13 +66,9 @@ dependencies:
flutter_email_sender: ^7.0.0
# revert to pub.dev when merged
# https://github.com/pichillilorenzo/flutter_inappwebview/pull/2548
flutter_inappwebview:
git:
url: https://github.com/pichillilorenzo/flutter_inappwebview.git
path: flutter_inappwebview
ref: 3e6c4c4a25340cd363af9d38891d88498b90be26
flutter_inappwebview: ^6.1.4
flutter_launcher_icons: ^0.14.1
flutter_local_authentication:
flutter_local_authentication: # linux fprintd fix is not published on pub.dev
git:
url: https://github.com/eaceto/flutter_local_authentication
ref: 1ac346a04592a05fd75acccf2e01fa3c7e955d96
@@ -77,7 +92,10 @@ dependencies:
local_auth_darwin: ^1.2.2
logging: ^1.0.1
modal_bottom_sheet: ^3.0.0
move_to_background: ^1.0.2
move_to_background: # no package updates on pub.dev
git:
url: https://github.com/Sayegh7/move_to_background
ref: 91e4d1a9c55b28bf93425d1f12faf410efc1e48d
native_dio_adapter: ^1.4.0
otp: ^3.1.1
package_info_plus: ^8.0.2
@@ -88,8 +106,11 @@ dependencies:
pointycastle: ^3.7.3
privacy_screen: ^0.0.6
protobuf: ^4.1.0
qr_code_scanner: ^1.0.1
qr_flutter: ^4.1.0
qr_code_scanner: # no package updates on pub.dev
git:
url: https://github.com/juliuscanute/qr_code_scanner
ref: a2d31633d4744f72ada87cfa85d221358ab082af
qr_flutter: ^4.1.0
sentry: ^8.14.2
sentry_flutter: ^8.14.2
share_plus: ^11.0.0

54
mobile/apps/locker/.gitignore vendored Normal file
View File

@@ -0,0 +1,54 @@
# Let folks use their custom editor settings
.vscode
.idea
# macOS
.DS_Store
# Miscellaneous
*.class
*.log
*.pyc
*.swp
.DS_Store
.atom/
.buildlog/
.history
.svn/
# Editors
.vscode/
# IntelliJ related
*.iml
*.ipr
*.iws
.idea/
# Flutter/Dart/Pub related
**/doc/api/
.dart_tool/
.flutter-plugins
.flutter-plugins-dependencies
.packages
.pub-cache/
.pub/
/build/
# Web related
lib/generated_plugin_registrant.dart
# Exceptions to above rules.
!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
android/key.properties
android/app/.settings/*
android/.settings/
.env
fastlane/report.xml
# Android related
android/app/build/
devtools_options.yaml

View File

@@ -0,0 +1 @@
# soon.

View File

@@ -0,0 +1,72 @@
# For more linters, we can check https://dart-lang.github.io/linter/lints/index.html
# or https://pub.dev/packages/lint (Effective dart)
# use "flutter analyze ." or "dart analyze ." for running lint checks
include: package:flutter_lints/flutter.yaml
linter:
rules:
# Ref https://github.com/flutter/packages/blob/master/packages/flutter_lints/lib/flutter.yaml
# Ref https://dart-lang.github.io/linter/lints/
- avoid_print
- avoid_unnecessary_containers
- avoid_web_libraries_in_flutter
- no_logic_in_create_state
- prefer_const_constructors
- prefer_const_constructors_in_immutables
- prefer_const_declarations
- prefer_const_literals_to_create_immutables
- prefer_final_locals
- require_trailing_commas
- sized_box_for_whitespace
- use_full_hex_values_for_flutter_colors
- use_key_in_widget_constructors
- cancel_subscriptions
- avoid_empty_else
- exhaustive_cases
# just style suggestions
- sort_pub_dependencies
- use_rethrow_when_possible
- prefer_double_quotes
- directives_ordering
- always_use_package_imports
- sort_child_properties_last
- unawaited_futures
analyzer:
errors:
avoid_empty_else: error
exhaustive_cases: error
curly_braces_in_flow_control_structures: error
directives_ordering: error
require_trailing_commas: error
always_use_package_imports: warning
prefer_final_fields: error
unused_import: error
camel_case_types: error
prefer_is_empty: warning
use_rethrow_when_possible: info
unused_field: warning
use_key_in_widget_constructors: warning
sort_child_properties_last: warning
sort_pub_dependencies: warning
library_private_types_in_public_api: warning
constant_identifier_names: ignore
prefer_const_constructors: warning
prefer_const_declarations: warning
prefer_const_constructors_in_immutables: warning
prefer_final_locals: warning
unnecessary_const: error
cancel_subscriptions: error
unrelated_type_equality_checks: error
unnecessary_cast: info
unawaited_futures: warning # convert to warning after fixing existing issues
invalid_dependency: info
use_build_context_synchronously: ignore # experimental lint, requires many changes
prefer_interpolation_to_compose_strings: ignore # later too many warnings
prefer_double_quotes: ignore # too many warnings
avoid_renaming_method_parameters: ignore # incorrect warnings for `equals` overrides

13
mobile/apps/locker/android/.gitignore vendored Normal file
View File

@@ -0,0 +1,13 @@
gradle-wrapper.jar
/.gradle
/captures/
/gradlew
/gradlew.bat
/local.properties
GeneratedPluginRegistrant.java
# Remember to never publicly share your keystore.
# See https://flutter.dev/to/reference-keystore
key.properties
**/*.keystore
**/*.jks

View File

@@ -0,0 +1,44 @@
plugins {
id "com.android.application"
id "kotlin-android"
// The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
id "dev.flutter.flutter-gradle-plugin"
}
android {
namespace = "io.ente.locker"
compileSdk = 35
ndkVersion = flutter.ndkVersion
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = JavaVersion.VERSION_1_8
}
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId = "io.ente.locker"
// You can update the following values to match your application needs.
// For more information, see: https://flutter.dev/to/review-gradle-config.
minSdk = 26
targetSdk = flutter.targetSdkVersion
versionCode = flutter.versionCode
versionName = flutter.versionName
}
buildTypes {
release {
// TODO: Add your own signing config for the release build.
// Signing with the debug keys for now, so `flutter run --release` works.
signingConfig = signingConfigs.debug
}
}
}
flutter {
source = "../.."
}

View File

@@ -0,0 +1,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<!-- The INTERNET permission is required for development. Specifically,
the Flutter tool needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>

View File

@@ -0,0 +1,57 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Camera permissions for document scanner -->
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-feature android:name="android.hardware.camera" android:required="false" />
<uses-feature android:name="android.hardware.camera.autofocus" android:required="false" />
<application
android:label="Ente Locker"
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher">
<activity
android:name=".MainActivity"
android:exported="true"
android:launchMode="singleTop"
android:taskAffinity=""
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<!-- Specifies an Android theme to apply to this Activity as soon as
the Android process has started. This theme is visible to the user
while the Flutter UI initializes. After that, this theme continues
to determine the Window background behind the Flutter UI. -->
<meta-data
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme"
/>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="*/*" />
</intent-filter>
</activity>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data
android:name="flutterEmbedding"
android:value="2" />
</application>
<!-- Required to query activities that can process text, see:
https://developer.android.com/training/package-visibility and
https://developer.android.com/reference/android/content/Intent#ACTION_PROCESS_TEXT.
In particular, this is used by the Flutter engine in io.flutter.plugin.text.ProcessTextPlugin. -->
<queries>
<intent>
<action android:name="android.intent.action.PROCESS_TEXT"/>
<data android:mimeType="text/plain"/>
</intent>
</queries>
</manifest>

View File

@@ -0,0 +1,5 @@
package io.ente.locker
import io.flutter.embedding.android.FlutterActivity
class MainActivity: FlutterActivity()

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="?android:colorBackground" />
<!-- You can insert your own image assets here -->
<!-- <item>
<bitmap
android:gravity="center"
android:src="@mipmap/launch_image" />
</item> -->
</layer-list>

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@android:color/white" />
<!-- You can insert your own image assets here -->
<!-- <item>
<bitmap
android:gravity="center"
android:src="@mipmap/launch_image" />
</item> -->
</layer-list>

Binary file not shown.

After

Width:  |  Height:  |  Size: 544 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 442 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 721 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
the Flutter engine draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
</style>
<!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your
Flutter UI initializes, as well as behind your Flutter UI while its
running.
This Theme is only used starting with V2 of Flutter's Android embedding. -->
<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
<item name="android:windowBackground">?android:colorBackground</item>
</style>
</resources>

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
<style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
the Flutter engine draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
</style>
<!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your
Flutter UI initializes, as well as behind your Flutter UI while its
running.
This Theme is only used starting with V2 of Flutter's Android embedding. -->
<style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
<item name="android:windowBackground">?android:colorBackground</item>
</style>
</resources>

View File

@@ -0,0 +1,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<!-- The INTERNET permission is required for development. Specifically,
the Flutter tool needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>

View File

@@ -0,0 +1,18 @@
allprojects {
repositories {
google()
mavenCentral()
}
}
rootProject.buildDir = "../build"
subprojects {
project.buildDir = "${rootProject.buildDir}/${project.name}"
}
subprojects {
project.evaluationDependsOn(":app")
}
tasks.register("clean", Delete) {
delete rootProject.buildDir
}

View File

@@ -0,0 +1,3 @@
org.gradle.jvmargs=-Xmx4G -XX:MaxMetaspaceSize=2G -XX:+HeapDumpOnOutOfMemoryError
android.useAndroidX=true
android.enableJetifier=true

View File

@@ -0,0 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-all.zip

View File

@@ -0,0 +1,25 @@
pluginManagement {
def flutterSdkPath = {
def properties = new Properties()
file("local.properties").withInputStream { properties.load(it) }
def flutterSdkPath = properties.getProperty("flutter.sdk")
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
return flutterSdkPath
}()
includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")
repositories {
google()
mavenCentral()
gradlePluginPortal()
}
}
plugins {
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
id "com.android.application" version "8.1.0" apply false
id "org.jetbrains.kotlin.android" version "1.8.22" apply false
}
include ":app"

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 107 KiB

34
mobile/apps/locker/ios/.gitignore vendored Normal file
View File

@@ -0,0 +1,34 @@
**/dgph
*.mode1v3
*.mode2v3
*.moved-aside
*.pbxuser
*.perspectivev3
**/*sync/
.sconsign.dblite
.tags*
**/.vagrant/
**/DerivedData/
Icon?
**/Pods/
**/.symlinks/
profile
xcuserdata
**/.generated/
Flutter/App.framework
Flutter/Flutter.framework
Flutter/Flutter.podspec
Flutter/Generated.xcconfig
Flutter/ephemeral/
Flutter/app.flx
Flutter/app.zip
Flutter/flutter_assets/
Flutter/flutter_export_environment.sh
ServiceDefinitions.json
Runner/GeneratedPluginRegistrant.*
# Exceptions to above rules.
!default.mode1v3
!default.mode2v3
!default.pbxuser
!default.perspectivev3

View File

@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>App</string>
<key>CFBundleIdentifier</key>
<string>io.flutter.flutter.app</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>App</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>MinimumOSVersion</key>
<string>12.0</string>
</dict>
</plist>

View File

@@ -0,0 +1,2 @@
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
#include "Generated.xcconfig"

View File

@@ -0,0 +1,2 @@
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
#include "Generated.xcconfig"

View File

@@ -0,0 +1,59 @@
# Uncomment this line to define a global platform for your project
platform :ios, '13.0'
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
project 'Runner', {
'Debug' => :debug,
'Profile' => :release,
'Release' => :release,
}
def flutter_root
generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
unless File.exist?(generated_xcode_build_settings_path)
raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
end
File.foreach(generated_xcode_build_settings_path) do |line|
matches = line.match(/FLUTTER_ROOT\=(.*)/)
return matches[1].strip if matches
end
raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
end
require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
flutter_ios_podfile_setup
target 'Runner' do
use_frameworks!
use_modular_headers!
flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
target 'RunnerTests' do
inherit! :search_paths
end
target 'Share Extension' do
inherit! :search_paths
end
end
post_install do |installer|
installer.pods_project.targets.each do |target|
flutter_additional_ios_build_settings(target)
target.build_configurations.each do |config|
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '13.0'
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [
'$(inherited)',
## dart: PermissionGroup.camera
'PERMISSION_CAMERA=1',
## dart: PermissionGroup.photos
'PERMISSION_PHOTOS=1',
]
end
end
end

View File

@@ -0,0 +1,225 @@
PODS:
- app_links (0.0.2):
- Flutter
- cupertino_http (0.0.1):
- Flutter
- FlutterMacOS
- device_info_plus (0.0.1):
- Flutter
- DKImagePickerController/Core (4.3.9):
- DKImagePickerController/ImageDataManager
- DKImagePickerController/Resource
- DKImagePickerController/ImageDataManager (4.3.9)
- DKImagePickerController/PhotoGallery (4.3.9):
- DKImagePickerController/Core
- DKPhotoGallery
- DKImagePickerController/Resource (4.3.9)
- DKPhotoGallery (0.0.19):
- DKPhotoGallery/Core (= 0.0.19)
- DKPhotoGallery/Model (= 0.0.19)
- DKPhotoGallery/Preview (= 0.0.19)
- DKPhotoGallery/Resource (= 0.0.19)
- SDWebImage
- SwiftyGif
- DKPhotoGallery/Core (0.0.19):
- DKPhotoGallery/Model
- DKPhotoGallery/Preview
- SDWebImage
- SwiftyGif
- DKPhotoGallery/Model (0.0.19):
- SDWebImage
- SwiftyGif
- DKPhotoGallery/Preview (0.0.19):
- DKPhotoGallery/Model
- DKPhotoGallery/Resource
- SDWebImage
- SwiftyGif
- DKPhotoGallery/Resource (0.0.19):
- SDWebImage
- SwiftyGif
- file_picker (0.0.1):
- DKImagePickerController/PhotoGallery
- Flutter
- file_saver (0.0.1):
- Flutter
- Flutter (1.0.0)
- flutter_email_sender (0.0.1):
- Flutter
- flutter_inappwebview_ios (0.0.1):
- Flutter
- flutter_inappwebview_ios/Core (= 0.0.1)
- OrderedSet (~> 6.0.3)
- flutter_inappwebview_ios/Core (0.0.1):
- Flutter
- OrderedSet (~> 6.0.3)
- flutter_local_authentication (1.2.0):
- Flutter
- flutter_secure_storage (6.0.0):
- Flutter
- fluttertoast (0.0.2):
- Flutter
- listen_sharing_intent (1.9.2):
- Flutter
- local_auth_darwin (0.0.1):
- Flutter
- FlutterMacOS
- objective_c (0.0.1):
- Flutter
- open_file_ios (0.0.1):
- Flutter
- OrderedSet (6.0.3)
- package_info_plus (0.4.5):
- Flutter
- path_provider_foundation (0.0.1):
- Flutter
- FlutterMacOS
- privacy_screen (0.0.1):
- Flutter
- SDWebImage (5.21.0):
- SDWebImage/Core (= 5.21.0)
- SDWebImage/Core (5.21.0)
- Sentry/HybridSDK (8.46.0)
- sentry_flutter (8.14.2):
- Flutter
- FlutterMacOS
- Sentry/HybridSDK (= 8.46.0)
- share_plus (0.0.1):
- Flutter
- shared_preferences_foundation (0.0.1):
- Flutter
- FlutterMacOS
- sodium_libs (2.2.1):
- Flutter
- sqflite_darwin (0.0.4):
- Flutter
- FlutterMacOS
- SwiftyGif (5.4.5)
- ua_client_hints (1.4.1):
- Flutter
- url_launcher_ios (0.0.1):
- Flutter
DEPENDENCIES:
- app_links (from `.symlinks/plugins/app_links/ios`)
- cupertino_http (from `.symlinks/plugins/cupertino_http/darwin`)
- device_info_plus (from `.symlinks/plugins/device_info_plus/ios`)
- file_picker (from `.symlinks/plugins/file_picker/ios`)
- file_saver (from `.symlinks/plugins/file_saver/ios`)
- Flutter (from `Flutter`)
- flutter_email_sender (from `.symlinks/plugins/flutter_email_sender/ios`)
- flutter_inappwebview_ios (from `.symlinks/plugins/flutter_inappwebview_ios/ios`)
- flutter_local_authentication (from `.symlinks/plugins/flutter_local_authentication/ios`)
- flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`)
- fluttertoast (from `.symlinks/plugins/fluttertoast/ios`)
- listen_sharing_intent (from `.symlinks/plugins/listen_sharing_intent/ios`)
- local_auth_darwin (from `.symlinks/plugins/local_auth_darwin/darwin`)
- objective_c (from `.symlinks/plugins/objective_c/ios`)
- open_file_ios (from `.symlinks/plugins/open_file_ios/ios`)
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
- privacy_screen (from `.symlinks/plugins/privacy_screen/ios`)
- sentry_flutter (from `.symlinks/plugins/sentry_flutter/ios`)
- share_plus (from `.symlinks/plugins/share_plus/ios`)
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
- sodium_libs (from `.symlinks/plugins/sodium_libs/ios`)
- sqflite_darwin (from `.symlinks/plugins/sqflite_darwin/darwin`)
- ua_client_hints (from `.symlinks/plugins/ua_client_hints/ios`)
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
SPEC REPOS:
trunk:
- DKImagePickerController
- DKPhotoGallery
- OrderedSet
- SDWebImage
- Sentry
- SwiftyGif
EXTERNAL SOURCES:
app_links:
:path: ".symlinks/plugins/app_links/ios"
cupertino_http:
:path: ".symlinks/plugins/cupertino_http/darwin"
device_info_plus:
:path: ".symlinks/plugins/device_info_plus/ios"
file_picker:
:path: ".symlinks/plugins/file_picker/ios"
file_saver:
:path: ".symlinks/plugins/file_saver/ios"
Flutter:
:path: Flutter
flutter_email_sender:
:path: ".symlinks/plugins/flutter_email_sender/ios"
flutter_inappwebview_ios:
:path: ".symlinks/plugins/flutter_inappwebview_ios/ios"
flutter_local_authentication:
:path: ".symlinks/plugins/flutter_local_authentication/ios"
flutter_secure_storage:
:path: ".symlinks/plugins/flutter_secure_storage/ios"
fluttertoast:
:path: ".symlinks/plugins/fluttertoast/ios"
listen_sharing_intent:
:path: ".symlinks/plugins/listen_sharing_intent/ios"
local_auth_darwin:
:path: ".symlinks/plugins/local_auth_darwin/darwin"
objective_c:
:path: ".symlinks/plugins/objective_c/ios"
open_file_ios:
:path: ".symlinks/plugins/open_file_ios/ios"
package_info_plus:
:path: ".symlinks/plugins/package_info_plus/ios"
path_provider_foundation:
:path: ".symlinks/plugins/path_provider_foundation/darwin"
privacy_screen:
:path: ".symlinks/plugins/privacy_screen/ios"
sentry_flutter:
:path: ".symlinks/plugins/sentry_flutter/ios"
share_plus:
:path: ".symlinks/plugins/share_plus/ios"
shared_preferences_foundation:
:path: ".symlinks/plugins/shared_preferences_foundation/darwin"
sodium_libs:
:path: ".symlinks/plugins/sodium_libs/ios"
sqflite_darwin:
:path: ".symlinks/plugins/sqflite_darwin/darwin"
ua_client_hints:
:path: ".symlinks/plugins/ua_client_hints/ios"
url_launcher_ios:
:path: ".symlinks/plugins/url_launcher_ios/ios"
SPEC CHECKSUMS:
app_links: f3e17e4ee5e357b39d8b95290a9b2c299fca71c6
cupertino_http: 947a233f40cfea55167a49f2facc18434ea117ba
device_info_plus: c6fb39579d0f423935b0c9ce7ee2f44b71b9fce6
DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c
DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60
file_picker: b159e0c068aef54932bb15dc9fd1571818edaf49
file_saver: 503e386464dbe118f630e17b4c2e1190fa0cf808
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
flutter_email_sender: e03bdda7637bcd3539bfe718fddd980e9508efaa
flutter_inappwebview_ios: 6f63631e2c62a7c350263b13fa5427aedefe81d4
flutter_local_authentication: 1172a4dd88f6306dadce067454e2c4caf07977bb
flutter_secure_storage: d33dac7ae2ea08509be337e775f6b59f1ff45f12
fluttertoast: 21eecd6935e7064cc1fcb733a4c5a428f3f24f0f
listen_sharing_intent: 74a842adcbcf7bedf7bbc938c749da9155141b9a
local_auth_darwin: 66e40372f1c29f383a314c738c7446e2f7fdadc3
objective_c: 77e887b5ba1827970907e10e832eec1683f3431d
open_file_ios: 461db5853723763573e140de3193656f91990d9e
OrderedSet: e539b66b644ff081c73a262d24ad552a69be3a94
package_info_plus: c0502532a26c7662a62a356cebe2692ec5fe4ec4
path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46
privacy_screen: 1a131c052ceb3c3659934b003b0d397c2381a24e
SDWebImage: f84b0feeb08d2d11e6a9b843cb06d75ebf5b8868
Sentry: da60d980b197a46db0b35ea12cb8f39af48d8854
sentry_flutter: 2df8b0aab7e4aba81261c230cbea31c82a62dd1b
share_plus: 8b6f8b3447e494cca5317c8c3073de39b3600d1f
shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78
sodium_libs: 1faae17af662384acbd13e41867a0008cd2e2318
sqflite_darwin: 5a7236e3b501866c1c9befc6771dfd73ffb8702d
SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4
ua_client_hints: aeabd123262c087f0ce151ef96fa3ab77bfc8b38
url_launcher_ios: 5334b05cef931de560670eeae103fd3e431ac3fe
PODFILE CHECKSUM: d2d3220ea22664a259778d9e314054751db31361
COCOAPODS: 1.16.2

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:">
</FileRef>
</Workspace>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PreviewsEnabled</key>
<false/>
</dict>
</plist>

View File

@@ -0,0 +1,101 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1510"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit"
shouldUseLaunchSchemeArgsEnv = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</MacroExpansion>
<Testables>
<TestableReference
skipped = "NO"
parallelizable = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "331C8080294A63A400263BE5"
BuildableName = "RunnerTests.xctest"
BlueprintName = "RunnerTests"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
enableGPUValidationMode = "1"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</LaunchAction>
<ProfileAction
buildConfiguration = "Profile"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

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