app_update_dialog.dart 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. // @dart=2.9
  2. import 'package:flutter/material.dart';
  3. import 'package:logging/logging.dart';
  4. // import 'package:open_file/open_file.dart';
  5. import 'package:photos/core/configuration.dart';
  6. import 'package:photos/core/network.dart';
  7. import 'package:photos/ente_theme_data.dart';
  8. import 'package:photos/services/update_service.dart';
  9. class AppUpdateDialog extends StatefulWidget {
  10. final LatestVersionInfo latestVersionInfo;
  11. const AppUpdateDialog(this.latestVersionInfo, {Key key}) : super(key: key);
  12. @override
  13. State<AppUpdateDialog> createState() => _AppUpdateDialogState();
  14. }
  15. class _AppUpdateDialogState extends State<AppUpdateDialog> {
  16. @override
  17. Widget build(BuildContext context) {
  18. final List<Widget> changelog = [];
  19. for (final log in widget.latestVersionInfo.changelog) {
  20. changelog.add(
  21. Padding(
  22. padding: const EdgeInsets.fromLTRB(8, 4, 0, 4),
  23. child: Text("- " + log, style: Theme.of(context).textTheme.caption),
  24. ),
  25. );
  26. }
  27. final content = Column(
  28. crossAxisAlignment: CrossAxisAlignment.start,
  29. mainAxisSize: MainAxisSize.min,
  30. children: [
  31. Text(
  32. widget.latestVersionInfo.name,
  33. style: const TextStyle(
  34. fontSize: 20,
  35. fontWeight: FontWeight.bold,
  36. ),
  37. ),
  38. const Padding(padding: EdgeInsets.all(8)),
  39. const Text(
  40. "Changelog",
  41. style: TextStyle(
  42. fontSize: 18,
  43. ),
  44. ),
  45. const Padding(padding: EdgeInsets.all(4)),
  46. Column(
  47. crossAxisAlignment: CrossAxisAlignment.start,
  48. children: changelog,
  49. ),
  50. const Padding(padding: EdgeInsets.all(8)),
  51. SizedBox(
  52. width: double.infinity,
  53. height: 64,
  54. child: OutlinedButton(
  55. style: Theme.of(context).outlinedButtonTheme.style.copyWith(
  56. textStyle: MaterialStateProperty.resolveWith<TextStyle>(
  57. (Set<MaterialState> states) {
  58. return Theme.of(context).textTheme.subtitle1;
  59. },
  60. ),
  61. ),
  62. onPressed: () async {
  63. Navigator.pop(context);
  64. showDialog(
  65. context: context,
  66. builder: (BuildContext context) {
  67. return ApkDownloaderDialog(widget.latestVersionInfo);
  68. },
  69. barrierDismissible: false,
  70. );
  71. },
  72. child: const Text(
  73. "Update",
  74. ),
  75. ),
  76. ),
  77. ],
  78. );
  79. final shouldForceUpdate =
  80. UpdateService.instance.shouldForceUpdate(widget.latestVersionInfo);
  81. return WillPopScope(
  82. onWillPop: () async => !shouldForceUpdate,
  83. child: AlertDialog(
  84. title: Text(
  85. shouldForceUpdate ? "Critical update available" : "Update available",
  86. ),
  87. content: content,
  88. ),
  89. );
  90. }
  91. }
  92. class ApkDownloaderDialog extends StatefulWidget {
  93. final LatestVersionInfo versionInfo;
  94. const ApkDownloaderDialog(this.versionInfo, {Key key}) : super(key: key);
  95. @override
  96. State<ApkDownloaderDialog> createState() => _ApkDownloaderDialogState();
  97. }
  98. class _ApkDownloaderDialogState extends State<ApkDownloaderDialog> {
  99. String _saveUrl;
  100. double _downloadProgress;
  101. @override
  102. void initState() {
  103. super.initState();
  104. _saveUrl = Configuration.instance.getTempDirectory() +
  105. "ente-" +
  106. widget.versionInfo.name +
  107. ".apk";
  108. _downloadApk();
  109. }
  110. @override
  111. Widget build(BuildContext context) {
  112. return WillPopScope(
  113. onWillPop: () async => false,
  114. child: AlertDialog(
  115. title: const Text(
  116. "Downloading...",
  117. style: TextStyle(
  118. fontSize: 16,
  119. ),
  120. textAlign: TextAlign.center,
  121. ),
  122. content: LinearProgressIndicator(
  123. value: _downloadProgress,
  124. valueColor: AlwaysStoppedAnimation<Color>(
  125. Theme.of(context).colorScheme.greenAlternative,
  126. ),
  127. ),
  128. ),
  129. );
  130. }
  131. Future<void> _downloadApk() async {
  132. try {
  133. await Network.instance.getDio().download(
  134. widget.versionInfo.url,
  135. _saveUrl,
  136. onReceiveProgress: (count, _) {
  137. setState(() {
  138. _downloadProgress = count / widget.versionInfo.size;
  139. });
  140. },
  141. );
  142. Navigator.of(context, rootNavigator: true).pop('dialog');
  143. // OpenFile.open(_saveUrl);
  144. } catch (e) {
  145. Logger("ApkDownloader").severe(e);
  146. final AlertDialog alert = AlertDialog(
  147. title: const Text("Sorry"),
  148. content: const Text("The download could not be completed"),
  149. actions: [
  150. TextButton(
  151. child: const Text(
  152. "Ignore",
  153. style: TextStyle(
  154. color: Colors.white,
  155. ),
  156. ),
  157. onPressed: () {
  158. Navigator.of(context, rootNavigator: true).pop('dialog');
  159. Navigator.of(context, rootNavigator: true).pop('dialog');
  160. },
  161. ),
  162. TextButton(
  163. child: Text(
  164. "Retry",
  165. style: TextStyle(
  166. color: Theme.of(context).colorScheme.greenAlternative,
  167. ),
  168. ),
  169. onPressed: () {
  170. Navigator.of(context, rootNavigator: true).pop('dialog');
  171. Navigator.of(context, rootNavigator: true).pop('dialog');
  172. showDialog(
  173. context: context,
  174. builder: (BuildContext context) {
  175. return ApkDownloaderDialog(widget.versionInfo);
  176. },
  177. barrierDismissible: false,
  178. );
  179. },
  180. ),
  181. ],
  182. );
  183. showDialog(
  184. context: context,
  185. builder: (BuildContext context) {
  186. return alert;
  187. },
  188. barrierColor: Colors.black87,
  189. );
  190. return;
  191. }
  192. }
  193. }