mirror of
https://github.com/immich-app/immich
synced 2025-11-14 17:36:12 +00:00
Implemented user profile upload and show on web/mobile (#191)
* Update mobile dependencies * Added image picker * Added mechanism to upload profile image * Added image type to send to web * Added styling for circle avatar * Fixxed issue with sharp cannot resize image properly * Finished displaying and uploading user profile * Added user profile to web
This commit is contained in:
parent
bdf38e7668
commit
d476b15312
17 changed files with 579 additions and 86 deletions
|
|
@ -38,5 +38,7 @@ class HiveBackupAlbumsAdapter extends TypeAdapter<HiveBackupAlbums> {
|
|||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
other is HiveBackupAlbumsAdapter && runtimeType == other.runtimeType && typeId == other.typeId;
|
||||
other is HiveBackupAlbumsAdapter &&
|
||||
runtimeType == other.runtimeType &&
|
||||
typeId == other.typeId;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,12 +45,16 @@ class BackupControllerPage extends HookConsumerWidget {
|
|||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
LinearPercentIndicator(
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 8.0),
|
||||
lineHeight: 5.0,
|
||||
percent: backupState.serverInfo.diskUsagePercentage / 100.0,
|
||||
backgroundColor: Colors.grey,
|
||||
progressColor: Theme.of(context).primaryColor,
|
||||
child: LinearPercentIndicator(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 0, vertical: 0),
|
||||
barRadius: const Radius.circular(2),
|
||||
lineHeight: 6.0,
|
||||
percent: backupState.serverInfo.diskUsagePercentage / 100.0,
|
||||
backgroundColor: Colors.grey,
|
||||
progressColor: Theme.of(context).primaryColor,
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 12.0),
|
||||
|
|
|
|||
|
|
@ -0,0 +1,93 @@
|
|||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:image_picker/image_picker.dart';
|
||||
|
||||
import 'package:immich_mobile/shared/services/user.service.dart';
|
||||
|
||||
enum UploadProfileStatus {
|
||||
idle,
|
||||
loading,
|
||||
success,
|
||||
failure,
|
||||
}
|
||||
|
||||
class UploadProfileImageState {
|
||||
// enum
|
||||
final UploadProfileStatus status;
|
||||
final String profileImagePath;
|
||||
UploadProfileImageState({
|
||||
required this.status,
|
||||
required this.profileImagePath,
|
||||
});
|
||||
|
||||
UploadProfileImageState copyWith({
|
||||
UploadProfileStatus? status,
|
||||
String? profileImagePath,
|
||||
}) {
|
||||
return UploadProfileImageState(
|
||||
status: status ?? this.status,
|
||||
profileImagePath: profileImagePath ?? this.profileImagePath,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
final result = <String, dynamic>{};
|
||||
|
||||
result.addAll({'status': status.index});
|
||||
result.addAll({'profileImagePath': profileImagePath});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
factory UploadProfileImageState.fromMap(Map<String, dynamic> map) {
|
||||
return UploadProfileImageState(
|
||||
status: UploadProfileStatus.values[map['status'] ?? 0],
|
||||
profileImagePath: map['profileImagePath'] ?? '',
|
||||
);
|
||||
}
|
||||
|
||||
String toJson() => json.encode(toMap());
|
||||
|
||||
factory UploadProfileImageState.fromJson(String source) => UploadProfileImageState.fromMap(json.decode(source));
|
||||
|
||||
@override
|
||||
String toString() => 'UploadProfileImageState(status: $status, profileImagePath: $profileImagePath)';
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (identical(this, other)) return true;
|
||||
|
||||
return other is UploadProfileImageState && other.status == status && other.profileImagePath == profileImagePath;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => status.hashCode ^ profileImagePath.hashCode;
|
||||
}
|
||||
|
||||
class UploadProfileImageNotifier extends StateNotifier<UploadProfileImageState> {
|
||||
UploadProfileImageNotifier()
|
||||
: super(UploadProfileImageState(
|
||||
profileImagePath: '',
|
||||
status: UploadProfileStatus.idle,
|
||||
));
|
||||
|
||||
Future<bool> upload(XFile file) async {
|
||||
state = state.copyWith(status: UploadProfileStatus.loading);
|
||||
|
||||
var res = await UserService().uploadProfileImage(file);
|
||||
|
||||
if (res != null) {
|
||||
debugPrint("Succesfully upload profile image");
|
||||
state = state.copyWith(status: UploadProfileStatus.success, profileImagePath: res.profileImagePath);
|
||||
return true;
|
||||
}
|
||||
|
||||
state = state.copyWith(status: UploadProfileStatus.failure);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
final uploadProfileImageProvider =
|
||||
StateNotifierProvider<UploadProfileImageNotifier, UploadProfileImageState>(((ref) => UploadProfileImageNotifier()));
|
||||
|
|
@ -1,7 +1,11 @@
|
|||
import 'package:auto_route/auto_route.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:hive_flutter/hive_flutter.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:image_picker/image_picker.dart';
|
||||
import 'package:immich_mobile/constants/hive_box.dart';
|
||||
import 'package:immich_mobile/modules/home/providers/upload_profile_image.provider.dart';
|
||||
import 'package:immich_mobile/shared/providers/asset.provider.dart';
|
||||
import 'package:immich_mobile/modules/login/models/authentication_state.model.dart';
|
||||
import 'package:immich_mobile/modules/login/providers/authentication.provider.dart';
|
||||
|
|
@ -9,17 +13,21 @@ import 'package:immich_mobile/shared/models/server_info_state.model.dart';
|
|||
import 'package:immich_mobile/modules/backup/providers/backup.provider.dart';
|
||||
import 'package:immich_mobile/shared/providers/server_info.provider.dart';
|
||||
import 'package:immich_mobile/shared/providers/websocket.provider.dart';
|
||||
import 'package:immich_mobile/shared/ui/immich_loading_indicator.dart';
|
||||
import 'package:package_info_plus/package_info_plus.dart';
|
||||
import 'dart:math';
|
||||
|
||||
class ProfileDrawer extends HookConsumerWidget {
|
||||
const ProfileDrawer({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
String endpoint = Hive.box(userInfoBox).get(serverEndpointKey);
|
||||
AuthenticationState _authState = ref.watch(authenticationProvider);
|
||||
ServerInfoState _serverInfoState = ref.watch(serverInfoProvider);
|
||||
|
||||
final uploadProfileImageStatus = ref.watch(uploadProfileImageProvider).status;
|
||||
final appInfo = useState({});
|
||||
var dummmy = Random().nextInt(1024);
|
||||
|
||||
_getPackageInfo() async {
|
||||
PackageInfo packageInfo = await PackageInfo.fromPlatform();
|
||||
|
|
@ -30,19 +38,74 @@ class ProfileDrawer extends HookConsumerWidget {
|
|||
};
|
||||
}
|
||||
|
||||
_buildUserProfileImage() {
|
||||
if (_authState.profileImagePath.isEmpty) {
|
||||
return const CircleAvatar(
|
||||
radius: 35,
|
||||
backgroundImage: AssetImage('assets/immich-logo-no-outline.png'),
|
||||
backgroundColor: Colors.transparent,
|
||||
);
|
||||
}
|
||||
|
||||
if (uploadProfileImageStatus == UploadProfileStatus.idle) {
|
||||
if (_authState.profileImagePath.isNotEmpty) {
|
||||
return CircleAvatar(
|
||||
radius: 35,
|
||||
backgroundImage: NetworkImage('$endpoint/user/profile-image/${_authState.userId}?d=${dummmy++}'),
|
||||
backgroundColor: Colors.transparent,
|
||||
);
|
||||
} else {
|
||||
return const CircleAvatar(
|
||||
radius: 35,
|
||||
backgroundImage: AssetImage('assets/immich-logo-no-outline.png'),
|
||||
backgroundColor: Colors.transparent,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (uploadProfileImageStatus == UploadProfileStatus.success) {
|
||||
return CircleAvatar(
|
||||
radius: 35,
|
||||
backgroundImage: NetworkImage('$endpoint/user/profile-image/${_authState.userId}?d=${dummmy++}'),
|
||||
backgroundColor: Colors.transparent,
|
||||
);
|
||||
}
|
||||
|
||||
if (uploadProfileImageStatus == UploadProfileStatus.failure) {
|
||||
return const CircleAvatar(
|
||||
radius: 35,
|
||||
backgroundImage: AssetImage('assets/immich-logo-no-outline.png'),
|
||||
backgroundColor: Colors.transparent,
|
||||
);
|
||||
}
|
||||
|
||||
if (uploadProfileImageStatus == UploadProfileStatus.loading) {
|
||||
return const ImmichLoadingIndicator();
|
||||
}
|
||||
|
||||
return Container();
|
||||
}
|
||||
|
||||
_pickUserProfileImage() async {
|
||||
final XFile? image = await ImagePicker().pickImage(source: ImageSource.gallery, maxHeight: 1024, maxWidth: 1024);
|
||||
|
||||
if (image != null) {
|
||||
var success = await ref.watch(uploadProfileImageProvider.notifier).upload(image);
|
||||
|
||||
if (success) {
|
||||
ref
|
||||
.watch(authenticationProvider.notifier)
|
||||
.updateUserProfileImagePath(ref.read(uploadProfileImageProvider).profileImagePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() {
|
||||
_getPackageInfo();
|
||||
|
||||
_buildUserProfileImage();
|
||||
return null;
|
||||
}, []);
|
||||
|
||||
return Drawer(
|
||||
shape: const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.only(
|
||||
topRight: Radius.circular(5),
|
||||
bottomRight: Radius.circular(5),
|
||||
),
|
||||
),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
|
|
@ -51,22 +114,60 @@ class ProfileDrawer extends HookConsumerWidget {
|
|||
padding: EdgeInsets.zero,
|
||||
children: [
|
||||
DrawerHeader(
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.grey[200],
|
||||
decoration: const BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
colors: [Color.fromARGB(255, 216, 219, 238), Color.fromARGB(255, 226, 230, 231)],
|
||||
begin: Alignment.centerRight,
|
||||
end: Alignment.centerLeft,
|
||||
),
|
||||
),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const Image(
|
||||
image: AssetImage('assets/immich-logo-no-outline.png'),
|
||||
width: 50,
|
||||
filterQuality: FilterQuality.high,
|
||||
Stack(
|
||||
clipBehavior: Clip.none,
|
||||
children: [
|
||||
_buildUserProfileImage(),
|
||||
Positioned(
|
||||
bottom: 0,
|
||||
right: -5,
|
||||
child: GestureDetector(
|
||||
onTap: _pickUserProfileImage,
|
||||
child: Material(
|
||||
color: Colors.grey[50],
|
||||
elevation: 2,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(50.0),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(5.0),
|
||||
child: Icon(
|
||||
Icons.edit,
|
||||
color: Theme.of(context).primaryColor,
|
||||
size: 14,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const Padding(padding: EdgeInsets.all(8)),
|
||||
Text(
|
||||
_authState.userEmail,
|
||||
style: TextStyle(color: Theme.of(context).primaryColor, fontWeight: FontWeight.bold),
|
||||
"${_authState.firstName} ${_authState.lastName}",
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).primaryColor,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 24,
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 4.0),
|
||||
child: Text(
|
||||
_authState.userEmail,
|
||||
style: TextStyle(color: Colors.grey[800], fontSize: 12),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
|
|
@ -97,7 +198,15 @@ class ProfileDrawer extends HookConsumerWidget {
|
|||
Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Card(
|
||||
elevation: 0,
|
||||
color: Colors.grey[100],
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(5), // if you need this
|
||||
side: const BorderSide(
|
||||
color: Color.fromARGB(101, 201, 201, 201),
|
||||
width: 1,
|
||||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12.0, vertical: 8),
|
||||
child: Column(
|
||||
|
|
|
|||
|
|
@ -8,6 +8,11 @@ class AuthenticationState {
|
|||
final String userId;
|
||||
final String userEmail;
|
||||
final bool isAuthenticated;
|
||||
final String firstName;
|
||||
final String lastName;
|
||||
final bool isAdmin;
|
||||
final bool isFirstLogin;
|
||||
final String profileImagePath;
|
||||
final DeviceInfoRemote deviceInfo;
|
||||
|
||||
AuthenticationState({
|
||||
|
|
@ -16,6 +21,11 @@ class AuthenticationState {
|
|||
required this.userId,
|
||||
required this.userEmail,
|
||||
required this.isAuthenticated,
|
||||
required this.firstName,
|
||||
required this.lastName,
|
||||
required this.isAdmin,
|
||||
required this.isFirstLogin,
|
||||
required this.profileImagePath,
|
||||
required this.deviceInfo,
|
||||
});
|
||||
|
||||
|
|
@ -25,6 +35,11 @@ class AuthenticationState {
|
|||
String? userId,
|
||||
String? userEmail,
|
||||
bool? isAuthenticated,
|
||||
String? firstName,
|
||||
String? lastName,
|
||||
bool? isAdmin,
|
||||
bool? isFirstLoggedIn,
|
||||
String? profileImagePath,
|
||||
DeviceInfoRemote? deviceInfo,
|
||||
}) {
|
||||
return AuthenticationState(
|
||||
|
|
@ -33,24 +48,36 @@ class AuthenticationState {
|
|||
userId: userId ?? this.userId,
|
||||
userEmail: userEmail ?? this.userEmail,
|
||||
isAuthenticated: isAuthenticated ?? this.isAuthenticated,
|
||||
firstName: firstName ?? this.firstName,
|
||||
lastName: lastName ?? this.lastName,
|
||||
isAdmin: isAdmin ?? this.isAdmin,
|
||||
isFirstLogin: isFirstLoggedIn ?? isFirstLogin,
|
||||
profileImagePath: profileImagePath ?? this.profileImagePath,
|
||||
deviceInfo: deviceInfo ?? this.deviceInfo,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'AuthenticationState(deviceId: $deviceId, deviceType: $deviceType, userId: $userId, userEmail: $userEmail, isAuthenticated: $isAuthenticated, deviceInfo: $deviceInfo)';
|
||||
return 'AuthenticationState(deviceId: $deviceId, deviceType: $deviceType, userId: $userId, userEmail: $userEmail, isAuthenticated: $isAuthenticated, firstName: $firstName, lastName: $lastName, isAdmin: $isAdmin, isFirstLoggedIn: $isFirstLogin, profileImagePath: $profileImagePath, deviceInfo: $deviceInfo)';
|
||||
}
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
return {
|
||||
'deviceId': deviceId,
|
||||
'deviceType': deviceType,
|
||||
'userId': userId,
|
||||
'userEmail': userEmail,
|
||||
'isAuthenticated': isAuthenticated,
|
||||
'deviceInfo': deviceInfo.toMap(),
|
||||
};
|
||||
final result = <String, dynamic>{};
|
||||
|
||||
result.addAll({'deviceId': deviceId});
|
||||
result.addAll({'deviceType': deviceType});
|
||||
result.addAll({'userId': userId});
|
||||
result.addAll({'userEmail': userEmail});
|
||||
result.addAll({'isAuthenticated': isAuthenticated});
|
||||
result.addAll({'firstName': firstName});
|
||||
result.addAll({'lastName': lastName});
|
||||
result.addAll({'isAdmin': isAdmin});
|
||||
result.addAll({'isFirstLogin': isFirstLogin});
|
||||
result.addAll({'profileImagePath': profileImagePath});
|
||||
result.addAll({'deviceInfo': deviceInfo.toMap()});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
factory AuthenticationState.fromMap(Map<String, dynamic> map) {
|
||||
|
|
@ -60,6 +87,11 @@ class AuthenticationState {
|
|||
userId: map['userId'] ?? '',
|
||||
userEmail: map['userEmail'] ?? '',
|
||||
isAuthenticated: map['isAuthenticated'] ?? false,
|
||||
firstName: map['firstName'] ?? '',
|
||||
lastName: map['lastName'] ?? '',
|
||||
isAdmin: map['isAdmin'] ?? false,
|
||||
isFirstLogin: map['isFirstLogin'] ?? false,
|
||||
profileImagePath: map['profileImagePath'] ?? '',
|
||||
deviceInfo: DeviceInfoRemote.fromMap(map['deviceInfo']),
|
||||
);
|
||||
}
|
||||
|
|
@ -78,6 +110,11 @@ class AuthenticationState {
|
|||
other.userId == userId &&
|
||||
other.userEmail == userEmail &&
|
||||
other.isAuthenticated == isAuthenticated &&
|
||||
other.firstName == firstName &&
|
||||
other.lastName == lastName &&
|
||||
other.isAdmin == isAdmin &&
|
||||
other.isFirstLogin == isFirstLogin &&
|
||||
other.profileImagePath == profileImagePath &&
|
||||
other.deviceInfo == deviceInfo;
|
||||
}
|
||||
|
||||
|
|
@ -88,6 +125,11 @@ class AuthenticationState {
|
|||
userId.hashCode ^
|
||||
userEmail.hashCode ^
|
||||
isAuthenticated.hashCode ^
|
||||
firstName.hashCode ^
|
||||
lastName.hashCode ^
|
||||
isAdmin.hashCode ^
|
||||
isFirstLogin.hashCode ^
|
||||
profileImagePath.hashCode ^
|
||||
deviceInfo.hashCode;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,31 +4,58 @@ class LogInReponse {
|
|||
final String accessToken;
|
||||
final String userId;
|
||||
final String userEmail;
|
||||
final String firstName;
|
||||
final String lastName;
|
||||
final String profileImagePath;
|
||||
final bool isAdmin;
|
||||
final bool isFirstLogin;
|
||||
|
||||
LogInReponse({
|
||||
required this.accessToken,
|
||||
required this.userId,
|
||||
required this.userEmail,
|
||||
required this.firstName,
|
||||
required this.lastName,
|
||||
required this.profileImagePath,
|
||||
required this.isAdmin,
|
||||
required this.isFirstLogin,
|
||||
});
|
||||
|
||||
LogInReponse copyWith({
|
||||
String? accessToken,
|
||||
String? userId,
|
||||
String? userEmail,
|
||||
String? firstName,
|
||||
String? lastName,
|
||||
String? profileImagePath,
|
||||
bool? isAdmin,
|
||||
bool? isFirstLogin,
|
||||
}) {
|
||||
return LogInReponse(
|
||||
accessToken: accessToken ?? this.accessToken,
|
||||
userId: userId ?? this.userId,
|
||||
userEmail: userEmail ?? this.userEmail,
|
||||
firstName: firstName ?? this.firstName,
|
||||
lastName: lastName ?? this.lastName,
|
||||
profileImagePath: profileImagePath ?? this.profileImagePath,
|
||||
isAdmin: isAdmin ?? this.isAdmin,
|
||||
isFirstLogin: isFirstLogin ?? this.isFirstLogin,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
return {
|
||||
'accessToken': accessToken,
|
||||
'userId': userId,
|
||||
'userEmail': userEmail,
|
||||
};
|
||||
final result = <String, dynamic>{};
|
||||
|
||||
result.addAll({'accessToken': accessToken});
|
||||
result.addAll({'userId': userId});
|
||||
result.addAll({'userEmail': userEmail});
|
||||
result.addAll({'firstName': firstName});
|
||||
result.addAll({'lastName': lastName});
|
||||
result.addAll({'profileImagePath': profileImagePath});
|
||||
result.addAll({'isAdmin': isAdmin});
|
||||
result.addAll({'isFirstLogin': isFirstLogin});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
factory LogInReponse.fromMap(Map<String, dynamic> map) {
|
||||
|
|
@ -36,6 +63,11 @@ class LogInReponse {
|
|||
accessToken: map['accessToken'] ?? '',
|
||||
userId: map['userId'] ?? '',
|
||||
userEmail: map['userEmail'] ?? '',
|
||||
firstName: map['firstName'] ?? '',
|
||||
lastName: map['lastName'] ?? '',
|
||||
profileImagePath: map['profileImagePath'] ?? '',
|
||||
isAdmin: map['isAdmin'] ?? false,
|
||||
isFirstLogin: map['isFirstLogin'] ?? false,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -44,7 +76,9 @@ class LogInReponse {
|
|||
factory LogInReponse.fromJson(String source) => LogInReponse.fromMap(json.decode(source));
|
||||
|
||||
@override
|
||||
String toString() => 'LogInReponse(accessToken: $accessToken, userId: $userId, userEmail: $userEmail)';
|
||||
String toString() {
|
||||
return 'LogInReponse(accessToken: $accessToken, userId: $userId, userEmail: $userEmail, firstName: $firstName, lastName: $lastName, profileImagePath: $profileImagePath, isAdmin: $isAdmin, isFirstLogin: $isFirstLogin)';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
|
|
@ -53,9 +87,23 @@ class LogInReponse {
|
|||
return other is LogInReponse &&
|
||||
other.accessToken == accessToken &&
|
||||
other.userId == userId &&
|
||||
other.userEmail == userEmail;
|
||||
other.userEmail == userEmail &&
|
||||
other.firstName == firstName &&
|
||||
other.lastName == lastName &&
|
||||
other.profileImagePath == profileImagePath &&
|
||||
other.isAdmin == isAdmin &&
|
||||
other.isFirstLogin == isFirstLogin;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => accessToken.hashCode ^ userId.hashCode ^ userEmail.hashCode;
|
||||
int get hashCode {
|
||||
return accessToken.hashCode ^
|
||||
userId.hashCode ^
|
||||
userEmail.hashCode ^
|
||||
firstName.hashCode ^
|
||||
lastName.hashCode ^
|
||||
profileImagePath.hashCode ^
|
||||
isAdmin.hashCode ^
|
||||
isFirstLogin.hashCode;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,9 +17,14 @@ class AuthenticationNotifier extends StateNotifier<AuthenticationState> {
|
|||
AuthenticationState(
|
||||
deviceId: "",
|
||||
deviceType: "",
|
||||
isAuthenticated: false,
|
||||
userId: "",
|
||||
userEmail: "",
|
||||
firstName: '',
|
||||
lastName: '',
|
||||
profileImagePath: '',
|
||||
isAdmin: false,
|
||||
isFirstLogin: false,
|
||||
isAuthenticated: false,
|
||||
deviceInfo: DeviceInfoRemote(
|
||||
id: 0,
|
||||
userId: "",
|
||||
|
|
@ -76,6 +81,11 @@ class AuthenticationNotifier extends StateNotifier<AuthenticationState> {
|
|||
isAuthenticated: true,
|
||||
userId: payload.userId,
|
||||
userEmail: payload.userEmail,
|
||||
firstName: payload.firstName,
|
||||
lastName: payload.lastName,
|
||||
profileImagePath: payload.profileImagePath,
|
||||
isAdmin: payload.isAdmin,
|
||||
isFirstLoggedIn: payload.isFirstLogin,
|
||||
);
|
||||
|
||||
if (isSavedLoginInfo) {
|
||||
|
|
@ -114,9 +124,14 @@ class AuthenticationNotifier extends StateNotifier<AuthenticationState> {
|
|||
state = AuthenticationState(
|
||||
deviceId: "",
|
||||
deviceType: "",
|
||||
isAuthenticated: false,
|
||||
userId: "",
|
||||
userEmail: "",
|
||||
firstName: '',
|
||||
lastName: '',
|
||||
profileImagePath: '',
|
||||
isFirstLogin: false,
|
||||
isAuthenticated: false,
|
||||
isAdmin: false,
|
||||
deviceInfo: DeviceInfoRemote(
|
||||
id: 0,
|
||||
userId: "",
|
||||
|
|
@ -139,6 +154,10 @@ class AuthenticationNotifier extends StateNotifier<AuthenticationState> {
|
|||
DeviceInfoRemote deviceInfoRemote = await _backupService.setAutoBackup(backupState, deviceId, deviceType);
|
||||
state = state.copyWith(deviceInfo: deviceInfoRemote);
|
||||
}
|
||||
|
||||
updateUserProfileImagePath(String path) {
|
||||
state = state.copyWith(profileImagePath: path);
|
||||
}
|
||||
}
|
||||
|
||||
final authenticationProvider = StateNotifierProvider<AuthenticationNotifier, AuthenticationState>((ref) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue