profile_drawer_header.dart 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. import 'dart:math';
  2. import 'package:flutter/material.dart';
  3. import 'package:flutter_hooks/flutter_hooks.dart';
  4. import 'package:hive_flutter/hive_flutter.dart';
  5. import 'package:hooks_riverpod/hooks_riverpod.dart';
  6. import 'package:image_picker/image_picker.dart';
  7. import 'package:immich_mobile/constants/hive_box.dart';
  8. import 'package:immich_mobile/modules/home/providers/upload_profile_image.provider.dart';
  9. import 'package:immich_mobile/modules/login/models/authentication_state.model.dart';
  10. import 'package:immich_mobile/modules/login/providers/authentication.provider.dart';
  11. import 'package:immich_mobile/shared/ui/immich_loading_indicator.dart';
  12. class ProfileDrawerHeader extends HookConsumerWidget {
  13. const ProfileDrawerHeader({
  14. Key? key,
  15. }) : super(key: key);
  16. @override
  17. Widget build(BuildContext context, WidgetRef ref) {
  18. String endpoint = Hive.box(userInfoBox).get(serverEndpointKey);
  19. AuthenticationState authState = ref.watch(authenticationProvider);
  20. final uploadProfileImageStatus =
  21. ref.watch(uploadProfileImageProvider).status;
  22. var dummy = Random().nextInt(1024);
  23. final isDarkMode = Theme.of(context).brightness == Brightness.dark;
  24. buildUserProfileImage() {
  25. if (authState.profileImagePath.isEmpty) {
  26. return const CircleAvatar(
  27. radius: 35,
  28. backgroundImage: AssetImage('assets/immich-logo-no-outline.png'),
  29. backgroundColor: Colors.transparent,
  30. );
  31. }
  32. if (uploadProfileImageStatus == UploadProfileStatus.idle) {
  33. if (authState.profileImagePath.isNotEmpty) {
  34. return CircleAvatar(
  35. backgroundColor: Theme.of(context).primaryColor,
  36. radius: 35,
  37. child: CircleAvatar(
  38. radius: 34,
  39. backgroundImage: NetworkImage(
  40. '$endpoint/user/profile-image/${authState.userId}?d=${dummy++}',
  41. ),
  42. backgroundColor: Colors.transparent,
  43. ),
  44. );
  45. } else {
  46. return const CircleAvatar(
  47. radius: 33,
  48. backgroundImage: AssetImage('assets/immich-logo-no-outline.png'),
  49. backgroundColor: Colors.transparent,
  50. );
  51. }
  52. }
  53. if (uploadProfileImageStatus == UploadProfileStatus.success) {
  54. return CircleAvatar(
  55. radius: 35,
  56. backgroundImage: NetworkImage(
  57. '$endpoint/user/profile-image/${authState.userId}?d=${dummy++}',
  58. ),
  59. backgroundColor: Colors.transparent,
  60. );
  61. }
  62. if (uploadProfileImageStatus == UploadProfileStatus.failure) {
  63. return const CircleAvatar(
  64. radius: 35,
  65. backgroundImage: AssetImage('assets/immich-logo-no-outline.png'),
  66. backgroundColor: Colors.transparent,
  67. );
  68. }
  69. if (uploadProfileImageStatus == UploadProfileStatus.loading) {
  70. return const ImmichLoadingIndicator();
  71. }
  72. return const SizedBox();
  73. }
  74. pickUserProfileImage() async {
  75. final XFile? image = await ImagePicker().pickImage(
  76. source: ImageSource.gallery,
  77. maxHeight: 1024,
  78. maxWidth: 1024,
  79. );
  80. if (image != null) {
  81. var success =
  82. await ref.watch(uploadProfileImageProvider.notifier).upload(image);
  83. if (success) {
  84. ref.watch(authenticationProvider.notifier).updateUserProfileImagePath(
  85. ref.read(uploadProfileImageProvider).profileImagePath,
  86. );
  87. }
  88. }
  89. }
  90. useEffect(
  91. () {
  92. // buildUserProfileImage();
  93. return null;
  94. },
  95. [],
  96. );
  97. return DrawerHeader(
  98. decoration: BoxDecoration(
  99. gradient: LinearGradient(
  100. colors: isDarkMode
  101. ? [
  102. const Color.fromARGB(255, 22, 25, 48),
  103. const Color.fromARGB(255, 13, 13, 13),
  104. const Color.fromARGB(255, 0, 0, 0),
  105. ]
  106. : [
  107. const Color.fromARGB(255, 216, 219, 238),
  108. const Color.fromARGB(255, 242, 242, 242),
  109. Colors.white,
  110. ],
  111. begin: Alignment.centerRight,
  112. end: Alignment.centerLeft,
  113. ),
  114. ),
  115. child: Column(
  116. mainAxisAlignment: MainAxisAlignment.start,
  117. crossAxisAlignment: CrossAxisAlignment.start,
  118. children: [
  119. Stack(
  120. clipBehavior: Clip.none,
  121. children: [
  122. buildUserProfileImage(),
  123. Positioned(
  124. bottom: 0,
  125. right: -5,
  126. child: GestureDetector(
  127. onTap: pickUserProfileImage,
  128. child: Material(
  129. color: isDarkMode ? Colors.grey[900] : Colors.grey[100],
  130. elevation: 3,
  131. shape: RoundedRectangleBorder(
  132. borderRadius: BorderRadius.circular(50.0),
  133. ),
  134. child: Padding(
  135. padding: const EdgeInsets.all(5.0),
  136. child: Icon(
  137. Icons.edit,
  138. color: Theme.of(context).primaryColor,
  139. size: 14,
  140. ),
  141. ),
  142. ),
  143. ),
  144. ),
  145. ],
  146. ),
  147. Text(
  148. "${authState.firstName} ${authState.lastName}",
  149. style: TextStyle(
  150. color: Theme.of(context).primaryColor,
  151. fontWeight: FontWeight.bold,
  152. fontSize: 24,
  153. ),
  154. ),
  155. Text(
  156. authState.userEmail,
  157. style: Theme.of(context).textTheme.labelMedium,
  158. )
  159. ],
  160. ),
  161. );
  162. }
  163. }