Setup common accounts package

This commit is contained in:
vishnukvmd
2025-07-21 15:09:19 +05:30
committed by AmanRajSinghMourya
parent 0b766415a4
commit d227a2bf20
6 changed files with 0 additions and 1774 deletions

View File

@@ -1,74 +1 @@
# 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
include: package:flutter_lints/flutter.yaml

View File

@@ -1,32 +1,3 @@
export 'models/bonus.dart';
export 'models/delete_account.dart';
export 'models/sessions.dart';
export 'models/set_keys_request.dart';
export 'models/set_recovery_key_request.dart';
export 'models/srp.dart';
export 'models/subscription.dart';
export 'models/two_factor.dart';
export 'models/user_details.dart';
export 'pages/change_email_dialog.dart';
export 'pages/delete_account_page.dart';
export 'pages/email_entry_page.dart';
export 'pages/login_page.dart';
export 'pages/login_pwd_verification_page.dart';
export 'pages/ott_verification_page.dart';
export 'pages/passkey_page.dart';
export 'pages/password_entry_page.dart';
export 'pages/password_reentry_page.dart';
export 'pages/recovery_key_page.dart';
export 'pages/recovery_page.dart';
export 'pages/request_pwd_verification_page.dart';
export 'pages/sessions_page.dart';
export 'pages/two_factor_authentication_page.dart';
export 'pages/two_factor_recovery_page.dart';
export 'services/passkey_service.dart';
export 'services/user_service.dart';
/// A Flutter package containing account-related functionality for Ente apps
library ente_accounts;

View File

@@ -1,256 +1,6 @@
import 'dart:convert';
import 'dart:math';
import 'package:ente_accounts/models/bonus.dart';
import 'package:ente_accounts/models/subscription.dart';
class UserDetails {
final String email;
final int usage;
final int fileCount;
final int storageBonus;
final int sharedCollectionsCount;
final Subscription subscription;
final FamilyData? familyData;
final ProfileData? profileData;
final BonusData? bonusData;
const UserDetails(
this.email,
this.usage,
this.fileCount,
this.storageBonus,
this.sharedCollectionsCount,
this.subscription,
this.familyData,
this.profileData,
this.bonusData,
);
bool isPartOfFamily() {
return familyData?.members?.isNotEmpty ?? false;
}
bool hasPaidAddon() {
return bonusData?.getAddOnBonuses().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() {
final int? memberLimit = familyMemberStorageLimit();
if (memberLimit != null) {
return max(memberLimit - usage, 0);
}
return max(getTotalStorage() - getFamilyOrPersonalUsage(), 0);
}
// getTotalStorage will return total storage available including the
// storage bonus
int getTotalStorage() {
return (isPartOfFamily() ? familyData!.storage : subscription.storage) +
storageBonus;
}
// return the member storage limit if user is part of family and the admin
// has set the storage limit for the user.
int? familyMemberStorageLimit() {
if (isPartOfFamily()) {
try {
final FamilyMember currentUserMember = familyData!.members!
.firstWhere((element) => element.email.trim() == email.trim());
return currentUserMember.storageLimit;
} catch (e) {
return null;
}
}
return null;
}
// This is the total storage for which user has paid for.
int getPlanPlusAddonStorage() {
return (isPartOfFamily() ? familyData!.storage : subscription.storage) +
bonusData!.totalAddOnBonus();
}
factory UserDetails.fromMap(Map<String, dynamic> map) {
return UserDetails(
map['email'] as String,
map['usage'] as int,
(map['fileCount'] ?? 0) as int,
(map['storageBonus'] ?? 0) as int,
(map['sharedCollectionsCount'] ?? 0) as int,
Subscription.fromMap(map['subscription']),
FamilyData.fromMap(map['familyData']),
ProfileData.fromJson(map['profileData']),
BonusData.fromJson(map['bonusData']),
);
}
Map<String, dynamic> toMap() {
return {
'email': email,
'usage': usage,
'fileCount': fileCount,
'storageBonus': storageBonus,
'sharedCollectionsCount': sharedCollectionsCount,
'subscription': subscription.toMap(),
'familyData': familyData?.toMap(),
'profileData': profileData?.toJson(),
'bonusData': bonusData?.toJson(),
};
}
String toJson() => json.encode(toMap());
factory UserDetails.fromJson(String source) =>
UserDetails.fromMap(json.decode(source));
}
class FamilyMember {
final String email;
final int usage;
final String id;
final bool isAdmin;
final int? storageLimit;
FamilyMember(
this.email,
this.usage,
this.id,
this.isAdmin,
this.storageLimit,
);
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,
map['storageLimit'] as int?,
);
}
Map<String, dynamic> toMap() {
return {
'email': email,
'usage': usage,
'id': id,
'isAdmin': isAdmin,
'storageLimit': storageLimit,
};
}
String toJson() => json.encode(toMap());
factory FamilyMember.fromJson(String source) =>
FamilyMember.fromMap(json.decode(source));
}
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) {
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()
.fold(0, (sum, usage) => sum + usage);
}
FamilyMember? getMemberByID(String id) {
try {
return members!.firstWhere((element) => element.id == id);
} catch (e) {
return null;
}
}
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,
);
}
Map<String, dynamic> toMap() {
return {
'members': members?.map((x) => x.toMap()).toList(),
'storage': storage,
'expiryTime': expiryTime,
};
}
String toJson() => json.encode(toMap());
factory FamilyData.fromJson(String source) =>
FamilyData.fromMap(json.decode(source));
}
import 'dart:convert';
import 'dart:math';
import 'bonus.dart';
import 'subscription.dart';

View File

@@ -1,85 +1,3 @@
import 'package:ente_accounts/ente_accounts.dart';
import 'package:ente_strings/ente_strings.dart';
import 'package:ente_ui/utils/dialog_util.dart';
import 'package:ente_utils/email_util.dart';
import 'package:flutter/material.dart';
class ChangeEmailDialog extends StatefulWidget {
const ChangeEmailDialog({super.key});
@override
State<ChangeEmailDialog> createState() => _ChangeEmailDialogState();
}
class _ChangeEmailDialogState extends State<ChangeEmailDialog> {
String _email = "";
@override
Widget build(BuildContext context) {
return AlertDialog(
title: Text(context.strings.enterNewEmailHint),
content: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
TextFormField(
decoration: InputDecoration(
hintText: context.strings.email,
hintStyle: const TextStyle(
color: Colors.white30,
),
contentPadding: const EdgeInsets.all(12),
),
onChanged: (value) {
setState(() {
_email = value;
});
},
autocorrect: false,
keyboardType: TextInputType.emailAddress,
initialValue: _email,
autofocus: true,
),
],
),
),
actions: [
TextButton(
child: Text(
context.strings.cancel,
style: const TextStyle(
color: Colors.redAccent,
),
),
onPressed: () {
Navigator.pop(context);
},
),
TextButton(
child: Text(
context.strings.verify,
style: const TextStyle(
color: Colors.purple,
),
),
onPressed: () {
if (!isValidEmail(_email)) {
showErrorDialog(
context,
context.strings.invalidEmailTitle,
context.strings.invalidEmailMessage,
);
return;
}
UserService.instance.sendOtt(context, _email, isChangeEmail: true);
},
),
],
);
}
}
import 'package:ente_accounts/ente_accounts.dart';
import 'package:ente_ui/utils/dialog_util.dart';
import 'package:ente_utils/email_util.dart';

File diff suppressed because it is too large Load Diff

View File

@@ -2,65 +2,6 @@ name: ente_accounts
description: A Flutter package containing account-related models, pages, and services for Ente apps
version: 1.0.0
environment:
sdk: ">=3.0.0 <4.0.0"
flutter: ">=1.17.0"
dependencies:
app_links: ^6.3.3
bip39: ^1.0.6
collection: ^1.18.0
dio: ^5.4.0
dotted_border: ^3.1.0
email_validator: ^3.0.0
ente_base:
path: ../base
ente_configuration:
path: ../configuration
ente_crypto_dart:
git:
url: https://github.com/ente-io/ente_crypto_dart.git
ente_events:
path: ../events
ente_lock_screen:
path: ../lock_screen
ente_network:
path: ../network
ente_strings:
path: ../strings
ente_ui:
path: ../ui
ente_utils:
path: ../utils
file_saver: ^0.3.0
flutter:
sdk: flutter
logging: ^1.2.0
password_strength: ^0.2.0
pinput: ^5.0.1
pointycastle: ^3.7.3
share_plus: ^11.0.0
shared_preferences: ^2.2.2
step_progress_indicator: ^1.0.2
styled_text: ^8.1.0
url_launcher: ^6.3.1
url_launcher_ios: ^6.3.1
uuid: ^4.2.1
dev_dependencies:
flutter_lints: ^5.0.0
flutter_test:
sdk: flutter
flutter:
# This package is not meant to be published
publish_to: none
name: ente_accounts
description: A Flutter package containing account-related models, pages, and services for Ente apps
version: 1.0.0
environment:
sdk: ">=3.0.0 <4.0.0"
flutter: ">=1.17.0"