loading_photos_widget.dart 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. import 'dart:async';
  2. import 'dart:io';
  3. import 'package:flutter/material.dart';
  4. import 'package:lottie/lottie.dart';
  5. import 'package:photos/core/event_bus.dart';
  6. import 'package:photos/ente_theme_data.dart';
  7. import 'package:photos/events/local_import_progress.dart';
  8. import 'package:photos/events/sync_status_update_event.dart';
  9. import 'package:photos/services/local_sync_service.dart';
  10. import 'package:photos/ui/backup_folder_selection_page.dart';
  11. import 'package:photos/ui/common/bottom_shadow.dart';
  12. import 'package:photos/utils/navigation_util.dart';
  13. class LoadingPhotosWidget extends StatefulWidget {
  14. const LoadingPhotosWidget({Key? key}) : super(key: key);
  15. @override
  16. State<LoadingPhotosWidget> createState() => _LoadingPhotosWidgetState();
  17. }
  18. class _LoadingPhotosWidgetState extends State<LoadingPhotosWidget> {
  19. late StreamSubscription<SyncStatusUpdate> _firstImportEvent;
  20. late StreamSubscription<LocalImportProgressEvent> _imprortProgressEvent;
  21. int _currentPage = 0;
  22. String _loadingMessage = "Loading your photos...";
  23. final PageController _pageController = PageController(
  24. initialPage: 0,
  25. );
  26. final List<String> _messages = [
  27. "You can share your plan with your family",
  28. "We have preserved over 5 million memories so far",
  29. "web.ente.io has a slick uploader",
  30. "All our apps are open source",
  31. "Our encryption protocols have been reviewed by engineers at Google, Apple, Amazon, and Facebook",
  32. "You can share links to your albums with your loved ones",
  33. "Our mobile apps run in the background to encrypt and backup new photos you take",
  34. "We use Xchacha20Poly1305 to safely encrypt your data",
  35. "One of our data centers is in an underground fall out shelter in Paris",
  36. ];
  37. @override
  38. void initState() {
  39. super.initState();
  40. _firstImportEvent =
  41. Bus.instance.on<SyncStatusUpdate>().listen((event) async {
  42. if (mounted && event.status == SyncStatus.completedFirstGalleryImport) {
  43. if (LocalSyncService.instance.hasGrantedLimitedPermissions()) {
  44. // Do nothing, let HomeWidget refresh
  45. } else {
  46. routeToPage(
  47. context,
  48. const BackupFolderSelectionPage(
  49. isOnboarding: true,
  50. buttonText: "Start backup",
  51. ),
  52. );
  53. }
  54. }
  55. });
  56. _imprortProgressEvent =
  57. Bus.instance.on<LocalImportProgressEvent>().listen((event) {
  58. if (Platform.isAndroid) {
  59. _loadingMessage = 'Processing ${event.folderName}...';
  60. if (mounted) {
  61. setState(() {});
  62. }
  63. }
  64. });
  65. Timer.periodic(const Duration(seconds: 5), (Timer timer) {
  66. if (!mounted) {
  67. return;
  68. }
  69. if (_currentPage < _messages.length - 1) {
  70. _currentPage++;
  71. } else {
  72. _currentPage = 0;
  73. }
  74. _pageController.animateToPage(
  75. _currentPage,
  76. duration: const Duration(milliseconds: 300),
  77. curve: Curves.easeIn,
  78. );
  79. });
  80. }
  81. @override
  82. void dispose() {
  83. _firstImportEvent.cancel();
  84. _imprortProgressEvent.cancel();
  85. super.dispose();
  86. }
  87. @override
  88. Widget build(BuildContext context) {
  89. final isLightMode =
  90. MediaQuery.of(context).platformBrightness == Brightness.light;
  91. return Scaffold(
  92. body: SingleChildScrollView(
  93. child: Center(
  94. child: Padding(
  95. padding: const EdgeInsets.symmetric(horizontal: 20),
  96. child: Column(
  97. crossAxisAlignment: CrossAxisAlignment.center,
  98. children: [
  99. Stack(
  100. alignment: Alignment.center,
  101. children: [
  102. isLightMode
  103. ? Image.asset(
  104. 'assets/loading_photos_background.png',
  105. color: Colors.white.withOpacity(0.5),
  106. colorBlendMode: BlendMode.modulate,
  107. )
  108. : Image.asset(
  109. 'assets/loading_photos_background_dark.png',
  110. color: Colors.white.withOpacity(0.25),
  111. colorBlendMode: BlendMode.modulate,
  112. ),
  113. Column(
  114. children: [
  115. const SizedBox(height: 24),
  116. Lottie.asset(
  117. 'assets/loadingGalleryLottie.json',
  118. height: 400,
  119. ),
  120. ],
  121. )
  122. ],
  123. ),
  124. Text(
  125. _loadingMessage,
  126. style: TextStyle(
  127. color: Theme.of(context).colorScheme.subTextColor,
  128. ),
  129. ),
  130. const SizedBox(height: 54),
  131. Column(
  132. children: [
  133. Row(
  134. mainAxisAlignment: MainAxisAlignment.start,
  135. children: [
  136. Text(
  137. "Did you know?",
  138. style: Theme.of(context)
  139. .textTheme
  140. .headline6!
  141. .copyWith(
  142. color: Theme.of(context).colorScheme.greenText,
  143. ),
  144. ),
  145. ],
  146. ),
  147. const SizedBox(
  148. height: 16,
  149. ),
  150. SizedBox(
  151. height: 175,
  152. child: Stack(
  153. children: [
  154. PageView.builder(
  155. scrollDirection: Axis.vertical,
  156. controller: _pageController,
  157. itemBuilder: (context, index) {
  158. return _getMessage(_messages[index]);
  159. },
  160. itemCount: _messages.length,
  161. physics: const NeverScrollableScrollPhysics(),
  162. ),
  163. const Positioned(
  164. bottom: 0,
  165. left: 0,
  166. right: 0,
  167. child: BottomShadowWidget(),
  168. )
  169. ],
  170. ),
  171. ),
  172. ],
  173. ),
  174. ],
  175. ),
  176. ),
  177. ),
  178. ),
  179. );
  180. }
  181. Widget _getMessage(String text) {
  182. return Text(
  183. text,
  184. textAlign: TextAlign.start,
  185. style: Theme.of(context)
  186. .textTheme
  187. .headline5!
  188. .copyWith(color: Theme.of(context).colorScheme.defaultTextColor),
  189. );
  190. }
  191. }