Enable auto update checks
This commit is contained in:
parent
cdb9a11f3d
commit
31de45bf1c
5 changed files with 231 additions and 0 deletions
61
lib/services/update_service.dart
Normal file
61
lib/services/update_service.dart
Normal file
|
@ -0,0 +1,61 @@
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:package_info_plus/package_info_plus.dart';
|
||||
import 'package:photos/core/network.dart';
|
||||
|
||||
class UpdateService {
|
||||
UpdateService._privateConstructor();
|
||||
static final UpdateService instance = UpdateService._privateConstructor();
|
||||
|
||||
LatestVersionInfo _latestVersion;
|
||||
|
||||
Future<bool> shouldUpdate() async {
|
||||
if (Platform.isIOS) {
|
||||
return false;
|
||||
}
|
||||
_latestVersion = await _getLatestVersionInfo();
|
||||
final currentVersionCode =
|
||||
int.parse((await PackageInfo.fromPlatform()).buildNumber);
|
||||
return currentVersionCode < _latestVersion.code;
|
||||
}
|
||||
|
||||
LatestVersionInfo getLatestVersionInfo() {
|
||||
return _latestVersion;
|
||||
}
|
||||
|
||||
Future<LatestVersionInfo> _getLatestVersionInfo() async {
|
||||
final response = await Network.instance
|
||||
.getDio()
|
||||
.get("https://android.ente.io/release-info.json");
|
||||
return LatestVersionInfo.fromMap(response.data["latestVersion"]);
|
||||
}
|
||||
}
|
||||
|
||||
class LatestVersionInfo {
|
||||
final String name;
|
||||
final int code;
|
||||
final List<String> changelog;
|
||||
final bool shouldForceUpdate;
|
||||
final String url;
|
||||
final int size;
|
||||
|
||||
LatestVersionInfo(
|
||||
this.name,
|
||||
this.code,
|
||||
this.changelog,
|
||||
this.shouldForceUpdate,
|
||||
this.url,
|
||||
this.size,
|
||||
);
|
||||
|
||||
factory LatestVersionInfo.fromMap(Map<String, dynamic> map) {
|
||||
return LatestVersionInfo(
|
||||
map['name'],
|
||||
map['code'],
|
||||
List<String>.from(map['changelog']),
|
||||
map['shouldForceUpdate'],
|
||||
map['url'],
|
||||
map['size'],
|
||||
);
|
||||
}
|
||||
}
|
148
lib/ui/app_update_dialog.dart
Normal file
148
lib/ui/app_update_dialog.dart
Normal file
|
@ -0,0 +1,148 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:open_file/open_file.dart';
|
||||
import 'package:photos/core/configuration.dart';
|
||||
import 'package:photos/core/network.dart';
|
||||
import 'package:photos/services/update_service.dart';
|
||||
import 'package:photos/ui/common_elements.dart';
|
||||
import 'package:photos/utils/dialog_util.dart';
|
||||
|
||||
class AppUpdateDialog extends StatefulWidget {
|
||||
final LatestVersionInfo latestVersionInfo;
|
||||
|
||||
AppUpdateDialog(this.latestVersionInfo, {Key key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_AppUpdateDialogState createState() => _AppUpdateDialogState();
|
||||
}
|
||||
|
||||
class _AppUpdateDialogState extends State<AppUpdateDialog> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final List<Widget> changelog = [];
|
||||
for (final log in widget.latestVersionInfo.changelog) {
|
||||
changelog.add(Padding(
|
||||
padding: const EdgeInsets.fromLTRB(8, 4, 0, 4),
|
||||
child: Text("- " + log,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: Colors.white.withOpacity(0.7),
|
||||
)),
|
||||
));
|
||||
}
|
||||
final content = Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(
|
||||
widget.latestVersionInfo.name,
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
Padding(padding: EdgeInsets.all(8)),
|
||||
Text("changelog",
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
)),
|
||||
Padding(padding: EdgeInsets.all(4)),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: changelog,
|
||||
),
|
||||
Padding(padding: EdgeInsets.all(8)),
|
||||
Container(
|
||||
width: double.infinity,
|
||||
height: 64,
|
||||
padding: const EdgeInsets.fromLTRB(64, 0, 64, 0),
|
||||
child: button(
|
||||
"update",
|
||||
fontSize: 16,
|
||||
onPressed: () async {
|
||||
Navigator.pop(context);
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return ApkDownloaderDialog(widget.latestVersionInfo);
|
||||
},
|
||||
barrierDismissible: false,
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
return WillPopScope(
|
||||
onWillPop: () async => !widget.latestVersionInfo.shouldForceUpdate,
|
||||
child: AlertDialog(
|
||||
title: Text("update available"),
|
||||
content: content,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class ApkDownloaderDialog extends StatefulWidget {
|
||||
final LatestVersionInfo versionInfo;
|
||||
|
||||
ApkDownloaderDialog(this.versionInfo, {Key key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_ApkDownloaderDialogState createState() => _ApkDownloaderDialogState();
|
||||
}
|
||||
|
||||
class _ApkDownloaderDialogState extends State<ApkDownloaderDialog> {
|
||||
String _saveUrl;
|
||||
double _downloadProgress;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_saveUrl = Configuration.instance.getTempDirectory() +
|
||||
"ente-" +
|
||||
widget.versionInfo.name +
|
||||
".apk";
|
||||
_downloadApk();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return WillPopScope(
|
||||
onWillPop: () async => false,
|
||||
child: AlertDialog(
|
||||
title: Text(
|
||||
"downloading...",
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
content: LinearProgressIndicator(
|
||||
value: _downloadProgress,
|
||||
valueColor:
|
||||
AlwaysStoppedAnimation<Color>(Theme.of(context).buttonColor),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _downloadApk() async {
|
||||
try {
|
||||
await Network.instance.getDio().download(widget.versionInfo.url, _saveUrl,
|
||||
onReceiveProgress: (count, _) {
|
||||
setState(() {
|
||||
_downloadProgress = count / widget.versionInfo.size;
|
||||
});
|
||||
});
|
||||
} catch (e) {
|
||||
Logger("ApkDownloader").severe(e);
|
||||
Navigator.pop(context);
|
||||
showGenericErrorDialog(context);
|
||||
return;
|
||||
}
|
||||
Navigator.pop(context);
|
||||
OpenFile.open(_saveUrl);
|
||||
}
|
||||
}
|
|
@ -17,6 +17,8 @@ import 'package:photos/events/trigger_logout_event.dart';
|
|||
import 'package:photos/events/user_logged_out_event.dart';
|
||||
import 'package:photos/models/selected_files.dart';
|
||||
import 'package:photos/services/sync_service.dart';
|
||||
import 'package:photos/services/update_service.dart';
|
||||
import 'package:photos/ui/app_update_dialog.dart';
|
||||
import 'package:photos/ui/backup_folder_selection_page.dart';
|
||||
import 'package:photos/ui/collections_gallery_widget.dart';
|
||||
import 'package:photos/ui/extents_page_view.dart';
|
||||
|
@ -126,6 +128,18 @@ class _HomeWidgetState extends State<HomeWidget> {
|
|||
setState(() {});
|
||||
});
|
||||
_initDeepLinks();
|
||||
UpdateService.instance.shouldUpdate().then((shouldUpdate) {
|
||||
if (shouldUpdate) {
|
||||
Future.delayed(Duration.zero, () {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return AppUpdateDialog(
|
||||
UpdateService.instance.getLatestVersionInfo());
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
super.initState();
|
||||
}
|
||||
|
||||
|
|
|
@ -478,6 +478,13 @@ packages:
|
|||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.0+1"
|
||||
open_file:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: open_file
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.2.1"
|
||||
package_info_plus:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
|
|
@ -79,6 +79,7 @@ dependencies:
|
|||
loading_animations: ^2.1.0
|
||||
dots_indicator: ^2.0.0
|
||||
flutter_local_notifications: ^5.0.0+4
|
||||
open_file: ^3.2.1
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
|
Loading…
Add table
Reference in a new issue