app_bar_dialog.dart 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. import 'package:auto_route/auto_route.dart';
  2. import 'package:easy_localization/easy_localization.dart';
  3. import 'package:flutter/material.dart';
  4. import 'package:flutter_hooks/flutter_hooks.dart';
  5. import 'package:hooks_riverpod/hooks_riverpod.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 = Theme.of(context);
  24. bool isHorizontal = MediaQuery.of(context).size.width > 600;
  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: () => Navigator.of(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: Theme.of(context).primaryColor,
  53. fontSize: 15,
  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.labelMedium?.color,
  71. size: 20,
  72. ),
  73. ),
  74. title: Text(
  75. text,
  76. style:
  77. theme.textTheme.labelLarge?.copyWith(fontWeight: FontWeight.bold),
  78. ).tr(),
  79. onTap: onTap,
  80. );
  81. }
  82. buildSettingButton() {
  83. return buildActionButton(
  84. Icons.settings_rounded,
  85. "profile_drawer_settings",
  86. () => AutoRouter.of(context).push(const SettingsRoute()),
  87. );
  88. }
  89. buildAppLogButton() {
  90. return buildActionButton(
  91. Icons.assignment_outlined,
  92. "profile_drawer_app_logs",
  93. () => AutoRouter.of(context).push(const AppLogRoute()),
  94. );
  95. }
  96. buildSignOutButton() {
  97. return buildActionButton(
  98. Icons.logout_rounded,
  99. "profile_drawer_sign_out",
  100. () async {
  101. showDialog(
  102. context: context,
  103. builder: (BuildContext ctx) {
  104. return ConfirmDialog(
  105. title: "app_bar_signout_dialog_title",
  106. content: "app_bar_signout_dialog_content",
  107. ok: "app_bar_signout_dialog_ok",
  108. onOk: () async {
  109. await ref.watch(authenticationProvider.notifier).logout();
  110. ref.read(manualUploadProvider.notifier).cancelBackup();
  111. ref.watch(backupProvider.notifier).cancelBackup();
  112. ref.watch(assetProvider.notifier).clearAllAsset();
  113. ref.watch(websocketProvider.notifier).disconnect();
  114. AutoRouter.of(context).replace(const LoginRoute());
  115. },
  116. );
  117. },
  118. );
  119. },
  120. );
  121. }
  122. Widget buildStorageInformation() {
  123. return Padding(
  124. padding: const EdgeInsets.symmetric(horizontal: 10.0, vertical: 3),
  125. child: Container(
  126. padding: const EdgeInsets.symmetric(vertical: 4),
  127. decoration:
  128. BoxDecoration(color: Theme.of(context).colorScheme.surface),
  129. child: ListTile(
  130. minLeadingWidth: 50,
  131. leading: Icon(
  132. Icons.storage_rounded,
  133. color: theme.primaryColor,
  134. ),
  135. title: const Text(
  136. "backup_controller_page_server_storage",
  137. style: TextStyle(fontWeight: FontWeight.bold, fontSize: 14),
  138. ).tr(),
  139. isThreeLine: true,
  140. subtitle: Padding(
  141. padding: const EdgeInsets.only(top: 8.0),
  142. child: Column(
  143. crossAxisAlignment: CrossAxisAlignment.start,
  144. children: [
  145. Padding(
  146. padding: const EdgeInsets.only(top: 8.0),
  147. child: LinearProgressIndicator(
  148. minHeight: 5.0,
  149. value: backupState.serverInfo.diskUsagePercentage / 100.0,
  150. backgroundColor:
  151. Theme.of(context).colorScheme.onSurface.withAlpha(50),
  152. color: theme.primaryColor,
  153. ),
  154. ),
  155. Padding(
  156. padding: const EdgeInsets.only(top: 12.0),
  157. child:
  158. const Text('backup_controller_page_storage_format').tr(
  159. args: [
  160. backupState.serverInfo.diskUse,
  161. backupState.serverInfo.diskSize,
  162. ],
  163. ),
  164. ),
  165. ],
  166. ),
  167. ),
  168. ),
  169. ),
  170. );
  171. }
  172. buildFooter() {
  173. return Padding(
  174. padding: const EdgeInsets.only(top: 10, bottom: 20),
  175. child: Row(
  176. mainAxisAlignment: MainAxisAlignment.center,
  177. children: [
  178. InkWell(
  179. onTap: () {
  180. Navigator.of(context).pop();
  181. launchUrl(
  182. Uri.parse('https://immich.app'),
  183. mode: LaunchMode.externalApplication,
  184. );
  185. },
  186. child: Text(
  187. "profile_drawer_documentation",
  188. style: Theme.of(context).textTheme.bodySmall,
  189. ).tr(),
  190. ),
  191. const SizedBox(
  192. width: 20,
  193. child: Text(
  194. "•",
  195. textAlign: TextAlign.center,
  196. ),
  197. ),
  198. InkWell(
  199. onTap: () {
  200. Navigator.of(context).pop();
  201. launchUrl(
  202. Uri.parse('https://github.com/immich-app/immich'),
  203. mode: LaunchMode.externalApplication,
  204. );
  205. },
  206. child: Text(
  207. "profile_drawer_github",
  208. style: Theme.of(context).textTheme.bodySmall,
  209. ).tr(),
  210. ),
  211. ],
  212. ),
  213. );
  214. }
  215. return Dialog(
  216. clipBehavior: Clip.hardEdge,
  217. alignment: Alignment.topCenter,
  218. insetPadding: EdgeInsets.only(
  219. top: isHorizontal ? 20 : 60,
  220. left: horizontalPadding,
  221. right: horizontalPadding,
  222. bottom: isHorizontal ? 20 : 100,
  223. ),
  224. backgroundColor: theme.cardColor,
  225. shape: RoundedRectangleBorder(
  226. borderRadius: BorderRadius.circular(20),
  227. ),
  228. child: SizedBox(
  229. child: SingleChildScrollView(
  230. child: Column(
  231. mainAxisSize: MainAxisSize.min,
  232. children: [
  233. Container(
  234. padding: const EdgeInsets.all(20),
  235. child: buildTopRow(),
  236. ),
  237. const AppBarProfileInfoBox(),
  238. buildStorageInformation(),
  239. const AppBarServerInfo(),
  240. buildAppLogButton(),
  241. buildSettingButton(),
  242. buildSignOutButton(),
  243. buildFooter(),
  244. ],
  245. ),
  246. ),
  247. ),
  248. );
  249. }
  250. }