backup_controller_page.dart 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. import 'package:auto_route/auto_route.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/modules/login/models/authentication_state.model.dart';
  6. import 'package:immich_mobile/shared/models/backup_state.model.dart';
  7. import 'package:immich_mobile/modules/login/providers/authentication.provider.dart';
  8. import 'package:immich_mobile/shared/providers/backup.provider.dart';
  9. import 'package:percent_indicator/linear_percent_indicator.dart';
  10. class BackupControllerPage extends HookConsumerWidget {
  11. const BackupControllerPage({Key? key}) : super(key: key);
  12. @override
  13. Widget build(BuildContext context, WidgetRef ref) {
  14. BackUpState _backupState = ref.watch(backupProvider);
  15. AuthenticationState _authenticationState = ref.watch(authenticationProvider);
  16. bool shouldBackup = _backupState.totalAssetCount - _backupState.assetOnDatabase == 0 ? false : true;
  17. useEffect(() {
  18. if (_backupState.backupProgress != BackUpProgressEnum.inProgress) {
  19. ref.read(backupProvider.notifier).getBackupInfo();
  20. }
  21. return null;
  22. }, []);
  23. Widget _buildStorageInformation() {
  24. return ListTile(
  25. leading: Icon(
  26. Icons.storage_rounded,
  27. color: Theme.of(context).primaryColor,
  28. ),
  29. title: const Text(
  30. "Server Storage",
  31. style: TextStyle(fontWeight: FontWeight.bold, fontSize: 14),
  32. ),
  33. subtitle: Padding(
  34. padding: const EdgeInsets.only(top: 8.0),
  35. child: Column(
  36. crossAxisAlignment: CrossAxisAlignment.start,
  37. children: [
  38. LinearPercentIndicator(
  39. padding: const EdgeInsets.only(top: 8.0),
  40. lineHeight: 5.0,
  41. percent: _backupState.serverInfo.diskUsagePercentage / 100.0,
  42. backgroundColor: Colors.grey,
  43. progressColor: Theme.of(context).primaryColor,
  44. ),
  45. Padding(
  46. padding: const EdgeInsets.only(top: 12.0),
  47. child: Text('${_backupState.serverInfo.diskUse} of ${_backupState.serverInfo.diskSize} used'),
  48. ),
  49. ],
  50. ),
  51. ),
  52. );
  53. }
  54. ListTile _buildBackupController() {
  55. var backUpOption = _authenticationState.deviceInfo.isAutoBackup ? "on" : "off";
  56. var isAutoBackup = _authenticationState.deviceInfo.isAutoBackup;
  57. var backupBtnText = _authenticationState.deviceInfo.isAutoBackup ? "off" : "on";
  58. return ListTile(
  59. isThreeLine: true,
  60. leading: isAutoBackup
  61. ? Icon(
  62. Icons.cloud_done_rounded,
  63. color: Theme.of(context).primaryColor,
  64. )
  65. : const Icon(Icons.cloud_off_rounded),
  66. title: Text(
  67. "Back up is $backUpOption",
  68. style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 14),
  69. ),
  70. subtitle: Padding(
  71. padding: const EdgeInsets.symmetric(vertical: 8.0),
  72. child: Column(
  73. crossAxisAlignment: CrossAxisAlignment.start,
  74. children: [
  75. !isAutoBackup
  76. ? const Text(
  77. "Turn on backup to automatically upload new assets to the server.",
  78. style: TextStyle(fontSize: 14),
  79. )
  80. : Container(),
  81. OutlinedButton(
  82. onPressed: () {
  83. isAutoBackup
  84. ? ref.watch(authenticationProvider.notifier).setAutoBackup(false)
  85. : ref.watch(authenticationProvider.notifier).setAutoBackup(true);
  86. },
  87. child: Text("Turn $backupBtnText Backup"),
  88. )
  89. ],
  90. ),
  91. ),
  92. );
  93. }
  94. return Scaffold(
  95. appBar: AppBar(
  96. title: const Text(
  97. "Backup",
  98. style: TextStyle(fontWeight: FontWeight.bold),
  99. ),
  100. leading: IconButton(
  101. onPressed: () {
  102. AutoRouter.of(context).pop(true);
  103. },
  104. icon: const Icon(Icons.arrow_back_ios_rounded)),
  105. ),
  106. body: Padding(
  107. padding: const EdgeInsets.all(16.0),
  108. child: ListView(
  109. // crossAxisAlignment: CrossAxisAlignment.start,
  110. children: [
  111. const Padding(
  112. padding: EdgeInsets.all(8.0),
  113. child: Text(
  114. "Backup Information",
  115. style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16),
  116. ),
  117. ),
  118. BackupInfoCard(
  119. title: "Total",
  120. subtitle: "All images and videos on the device",
  121. info: "${_backupState.totalAssetCount}",
  122. ),
  123. BackupInfoCard(
  124. title: "Backup",
  125. subtitle: "Images and videos of the device that are backup on server",
  126. info: "${_backupState.assetOnDatabase}",
  127. ),
  128. BackupInfoCard(
  129. title: "Remainder",
  130. subtitle: "Images and videos that has not been backing up",
  131. info: "${_backupState.totalAssetCount - _backupState.assetOnDatabase}",
  132. ),
  133. const Divider(),
  134. _buildBackupController(),
  135. const Divider(),
  136. _buildStorageInformation(),
  137. const Divider(),
  138. Padding(
  139. padding: const EdgeInsets.all(8.0),
  140. child: Text(
  141. "Asset that were being backup: ${_backupState.backingUpAssetCount} [${_backupState.progressInPercentage.toStringAsFixed(0)}%]"),
  142. ),
  143. Padding(
  144. padding: const EdgeInsets.only(left: 8.0),
  145. child: Row(children: [
  146. const Text("Backup Progress:"),
  147. const Padding(padding: EdgeInsets.symmetric(horizontal: 2)),
  148. _backupState.backupProgress == BackUpProgressEnum.inProgress
  149. ? const CircularProgressIndicator.adaptive()
  150. : const Text("Done"),
  151. ]),
  152. ),
  153. Padding(
  154. padding: const EdgeInsets.all(8.0),
  155. child: Container(
  156. child: _backupState.backupProgress == BackUpProgressEnum.inProgress
  157. ? ElevatedButton(
  158. style: ElevatedButton.styleFrom(primary: Colors.red[300]),
  159. onPressed: () {
  160. ref.read(backupProvider.notifier).cancelBackup();
  161. },
  162. child: const Text("Cancel"),
  163. )
  164. : ElevatedButton(
  165. onPressed: shouldBackup
  166. ? () {
  167. ref.read(backupProvider.notifier).startBackupProcess();
  168. }
  169. : null,
  170. child: const Text("Start Backup"),
  171. ),
  172. ),
  173. )
  174. ],
  175. ),
  176. ),
  177. );
  178. }
  179. }
  180. class BackupInfoCard extends StatelessWidget {
  181. final String title;
  182. final String subtitle;
  183. final String info;
  184. const BackupInfoCard({Key? key, required this.title, required this.subtitle, required this.info}) : super(key: key);
  185. @override
  186. Widget build(BuildContext context) {
  187. return Card(
  188. shape: RoundedRectangleBorder(
  189. borderRadius: BorderRadius.circular(5), // if you need this
  190. side: const BorderSide(
  191. color: Colors.black12,
  192. width: 1,
  193. ),
  194. ),
  195. elevation: 0,
  196. borderOnForeground: false,
  197. child: ListTile(
  198. minVerticalPadding: 15,
  199. isThreeLine: true,
  200. title: Text(
  201. title,
  202. style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 20),
  203. ),
  204. subtitle: Padding(
  205. padding: const EdgeInsets.only(top: 8.0),
  206. child: Text(
  207. subtitle,
  208. style: const TextStyle(color: Color(0xFF808080), fontSize: 12),
  209. ),
  210. ),
  211. trailing: Column(
  212. mainAxisAlignment: MainAxisAlignment.center,
  213. children: [
  214. Text(
  215. info,
  216. style: const TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
  217. ),
  218. const Text("assets"),
  219. ],
  220. ),
  221. ),
  222. );
  223. }
  224. }