app_bar_dialog.dart 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. import 'package:easy_localization/easy_localization.dart';
  2. import 'package:flutter/material.dart';
  3. import 'package:flutter_hooks/flutter_hooks.dart';
  4. import 'package:hooks_riverpod/hooks_riverpod.dart';
  5. import 'package:immich_mobile/extensions/build_context_extensions.dart';
  6. import 'package:immich_mobile/modules/backup/models/backup_state.model.dart';
  7. import 'package:immich_mobile/modules/backup/providers/backup.provider.dart';
  8. import 'package:immich_mobile/modules/backup/providers/manual_upload.provider.dart';
  9. import 'package:immich_mobile/modules/login/providers/authentication.provider.dart';
  10. import 'package:immich_mobile/routing/router.dart';
  11. import 'package:immich_mobile/shared/providers/asset.provider.dart';
  12. import 'package:immich_mobile/shared/providers/user.provider.dart';
  13. import 'package:immich_mobile/shared/providers/websocket.provider.dart';
  14. import 'package:immich_mobile/shared/ui/app_bar_dialog/app_bar_profile_info.dart';
  15. import 'package:immich_mobile/shared/ui/app_bar_dialog/app_bar_server_info.dart';
  16. import 'package:immich_mobile/shared/ui/confirm_dialog.dart';
  17. import 'package:url_launcher/url_launcher.dart';
  18. class ImmichAppBarDialog extends HookConsumerWidget {
  19. const ImmichAppBarDialog({super.key});
  20. @override
  21. Widget build(BuildContext context, WidgetRef ref) {
  22. BackUpState backupState = ref.watch(backupProvider);
  23. final theme = context.themeData;
  24. bool isHorizontal = !context.isMobile;
  25. final horizontalPadding = isHorizontal ? 100.0 : 20.0;
  26. final user = ref.watch(currentUserProvider);
  27. useEffect(
  28. () {
  29. ref.read(backupProvider.notifier).updateServerInfo();
  30. return null;
  31. },
  32. [user],
  33. );
  34. buildTopRow() {
  35. return Row(
  36. children: [
  37. InkWell(
  38. onTap: () => context.pop(),
  39. child: const Icon(
  40. Icons.close,
  41. size: 20,
  42. ),
  43. ),
  44. Expanded(
  45. child: Align(
  46. alignment: Alignment.center,
  47. child: Text(
  48. 'IMMICH',
  49. style: TextStyle(
  50. fontFamily: 'SnowburstOne',
  51. fontWeight: FontWeight.bold,
  52. color: context.primaryColor,
  53. fontSize: 16,
  54. ),
  55. ),
  56. ),
  57. ),
  58. ],
  59. );
  60. }
  61. buildActionButton(IconData icon, String text, Function() onTap) {
  62. return ListTile(
  63. dense: true,
  64. visualDensity: VisualDensity.standard,
  65. contentPadding: const EdgeInsets.only(left: 30),
  66. minLeadingWidth: 40,
  67. leading: SizedBox(
  68. child: Icon(
  69. icon,
  70. color: theme.textTheme.labelLarge?.color?.withAlpha(250),
  71. size: 20,
  72. ),
  73. ),
  74. title: Text(
  75. text,
  76. style: theme.textTheme.labelLarge?.copyWith(
  77. color: theme.textTheme.labelLarge?.color?.withAlpha(250),
  78. ),
  79. ).tr(),
  80. onTap: onTap,
  81. );
  82. }
  83. buildSettingButton() {
  84. return buildActionButton(
  85. Icons.settings_rounded,
  86. "profile_drawer_settings",
  87. () => context.autoPush(const SettingsRoute()),
  88. );
  89. }
  90. buildAppLogButton() {
  91. return buildActionButton(
  92. Icons.assignment_outlined,
  93. "profile_drawer_app_logs",
  94. () => context.autoPush(const AppLogRoute()),
  95. );
  96. }
  97. buildSignOutButton() {
  98. return buildActionButton(
  99. Icons.logout_rounded,
  100. "profile_drawer_sign_out",
  101. () async {
  102. showDialog(
  103. context: context,
  104. builder: (BuildContext ctx) {
  105. return ConfirmDialog(
  106. title: "app_bar_signout_dialog_title",
  107. content: "app_bar_signout_dialog_content",
  108. ok: "app_bar_signout_dialog_ok",
  109. onOk: () async {
  110. await ref.watch(authenticationProvider.notifier).logout();
  111. ref.read(manualUploadProvider.notifier).cancelBackup();
  112. ref.watch(backupProvider.notifier).cancelBackup();
  113. ref.watch(assetProvider.notifier).clearAllAsset();
  114. ref.watch(websocketProvider.notifier).disconnect();
  115. context.autoReplace(const LoginRoute());
  116. },
  117. );
  118. },
  119. );
  120. },
  121. );
  122. }
  123. Widget buildStorageInformation() {
  124. return Padding(
  125. padding: const EdgeInsets.symmetric(horizontal: 10.0, vertical: 3),
  126. child: Container(
  127. padding: const EdgeInsets.symmetric(vertical: 4),
  128. decoration: BoxDecoration(
  129. color: context.isDarkTheme
  130. ? context.scaffoldBackgroundColor
  131. : const Color.fromARGB(255, 225, 229, 240),
  132. ),
  133. child: ListTile(
  134. minLeadingWidth: 50,
  135. leading: Icon(
  136. Icons.storage_rounded,
  137. color: theme.primaryColor,
  138. ),
  139. title: Text(
  140. "backup_controller_page_server_storage",
  141. style: context.textTheme.labelLarge?.copyWith(
  142. fontWeight: FontWeight.w500,
  143. ),
  144. ).tr(),
  145. isThreeLine: true,
  146. subtitle: Padding(
  147. padding: const EdgeInsets.only(top: 8.0),
  148. child: Column(
  149. crossAxisAlignment: CrossAxisAlignment.start,
  150. children: [
  151. Padding(
  152. padding: const EdgeInsets.only(top: 8.0),
  153. child: LinearProgressIndicator(
  154. minHeight: 5.0,
  155. value: backupState.serverInfo.diskUsagePercentage / 100.0,
  156. backgroundColor: Colors.grey,
  157. color: theme.primaryColor,
  158. ),
  159. ),
  160. Padding(
  161. padding: const EdgeInsets.only(top: 12.0),
  162. child:
  163. const Text('backup_controller_page_storage_format').tr(
  164. args: [
  165. backupState.serverInfo.diskUse,
  166. backupState.serverInfo.diskSize,
  167. ],
  168. ),
  169. ),
  170. ],
  171. ),
  172. ),
  173. ),
  174. ),
  175. );
  176. }
  177. buildFooter() {
  178. return Padding(
  179. padding: const EdgeInsets.only(top: 10, bottom: 20),
  180. child: Row(
  181. mainAxisAlignment: MainAxisAlignment.center,
  182. children: [
  183. InkWell(
  184. onTap: () {
  185. context.pop();
  186. launchUrl(
  187. Uri.parse('https://immich.app'),
  188. mode: LaunchMode.externalApplication,
  189. );
  190. },
  191. child: Text(
  192. "profile_drawer_documentation",
  193. style: context.textTheme.bodySmall,
  194. ).tr(),
  195. ),
  196. const SizedBox(
  197. width: 20,
  198. child: Text(
  199. "•",
  200. textAlign: TextAlign.center,
  201. ),
  202. ),
  203. InkWell(
  204. onTap: () {
  205. context.pop();
  206. launchUrl(
  207. Uri.parse('https://github.com/immich-app/immich'),
  208. mode: LaunchMode.externalApplication,
  209. );
  210. },
  211. child: Text(
  212. "profile_drawer_github",
  213. style: context.textTheme.bodySmall,
  214. ).tr(),
  215. ),
  216. ],
  217. ),
  218. );
  219. }
  220. return Dialog(
  221. clipBehavior: Clip.hardEdge,
  222. alignment: Alignment.topCenter,
  223. insetPadding: EdgeInsets.only(
  224. top: isHorizontal ? 20 : 40,
  225. left: horizontalPadding,
  226. right: horizontalPadding,
  227. bottom: isHorizontal ? 20 : 100,
  228. ),
  229. backgroundColor: theme.cardColor,
  230. shape: RoundedRectangleBorder(
  231. borderRadius: BorderRadius.circular(20),
  232. ),
  233. child: SizedBox(
  234. child: SingleChildScrollView(
  235. child: Column(
  236. mainAxisSize: MainAxisSize.min,
  237. children: [
  238. Container(
  239. padding: const EdgeInsets.all(20),
  240. child: buildTopRow(),
  241. ),
  242. const AppBarProfileInfoBox(),
  243. buildStorageInformation(),
  244. const AppBarServerInfo(),
  245. buildAppLogButton(),
  246. buildSettingButton(),
  247. buildSignOutButton(),
  248. buildFooter(),
  249. ],
  250. ),
  251. ),
  252. ),
  253. );
  254. }
  255. }