From 23d9d12be58ca2e05bdd9aed5031cf9a38796c0b Mon Sep 17 00:00:00 2001 From: Ming Ming Date: Fri, 16 Apr 2021 16:45:17 +0800 Subject: [PATCH] Show changelog on upgrade if available --- lib/changelog.dart | 16 ++++++++ lib/k.dart | 3 +- lib/l10n/app_en.arb | 4 ++ lib/main.dart | 14 ++++++- lib/pref.dart | 5 +++ lib/widget/settings.dart | 2 +- lib/widget/splash.dart | 86 ++++++++++++++++++++++++++++++++++------ 7 files changed, 115 insertions(+), 15 deletions(-) create mode 100644 lib/changelog.dart diff --git a/lib/changelog.dart b/lib/changelog.dart new file mode 100644 index 00000000..a69d3866 --- /dev/null +++ b/lib/changelog.dart @@ -0,0 +1,16 @@ +const contents = [ + // v1 + null, + // v2 + null, + // v3 + null, + // v4 + null, + // v5 + null, + // v6 + null, + // v7 + null, +]; diff --git a/lib/k.dart b/lib/k.dart index 0b1e23c0..d520789a 100644 --- a/lib/k.dart +++ b/lib/k.dart @@ -1,5 +1,6 @@ /// Version string shown in settings page -const version = "6.0-c4da14"; +const versionStr = "6.0-c4da14"; +const version = 6; /// Show a snack bar for a short amount of time const snackBarDurationShort = const Duration(seconds: 4); diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index a17fcf78..ddba9784 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -344,6 +344,10 @@ "@downloadFailureNoPermissionNotification": { "description": "Inform user that the file cannot be downloaded due to missing storage permission" }, + "changelogTitle": "Changelog", + "@changelogTitle": { + "description": "Title of the changelog dialog" + }, "errorUnauthenticated": "Unauthenticated access. Please sign-in again if the problem continues", "@errorUnauthenticated": { "description": "Error message when server responds with HTTP401" diff --git a/lib/main.dart b/lib/main.dart index f93c55e7..2a8065ab 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -6,6 +6,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:kiwi/kiwi.dart'; import 'package:logging/logging.dart'; +import 'package:nc_photos/k.dart' as k; import 'package:nc_photos/metadata_task_manager.dart'; import 'package:nc_photos/mobile/platform.dart' if (dart.library.html) 'package:nc_photos/web/platform.dart' as platform; @@ -51,7 +52,18 @@ void _initLog() { }); } -Future _initPref() => Pref.init(); +Future _initPref() async { + await Pref.init(); + if (Pref.inst().getLastVersion(null) == null) { + if (Pref.inst().getSetupProgress(null) == null) { + // new install + await Pref.inst().setLastVersion(k.version); + } else { + // v6 is the last version without saving the version number in pref + await Pref.inst().setLastVersion(6); + } + } +} void _initBloc() { Bloc.observer = _BlocObserver(); diff --git a/lib/pref.dart b/lib/pref.dart index 57e62f10..f6a64c69 100644 --- a/lib/pref.dart +++ b/lib/pref.dart @@ -51,6 +51,11 @@ class Pref { Future setSetupProgress(int value) => _pref.setInt("setupProgress", value); + /// Return the version number when the app last ran + int getLastVersion([int def = 0]) => _pref.getInt("lastVersion") ?? def; + + Future setLastVersion(int value) => _pref.setInt("lastVersion", value); + Pref._(); static final _inst = Pref._(); diff --git a/lib/widget/settings.dart b/lib/widget/settings.dart index 6b8d7f51..b0307e47 100644 --- a/lib/widget/settings.dart +++ b/lib/widget/settings.dart @@ -79,7 +79,7 @@ class _SettingsState extends State { AppLocalizations.of(context).settingsAboutSectionTitle), ListTile( title: Text(AppLocalizations.of(context).settingsVersionTitle), - subtitle: const Text(k.version), + subtitle: const Text(k.versionStr), ), ListTile( title: diff --git a/lib/widget/splash.dart b/lib/widget/splash.dart index d1df6e04..14cc11c4 100644 --- a/lib/widget/splash.dart +++ b/lib/widget/splash.dart @@ -1,13 +1,15 @@ import 'package:flutter/material.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:logging/logging.dart'; +import 'package:nc_photos/changelog.dart' as changelog; +import 'package:nc_photos/k.dart' as k; import 'package:nc_photos/pref.dart'; import 'package:nc_photos/theme.dart'; import 'package:nc_photos/widget/home.dart'; import 'package:nc_photos/widget/setup.dart'; import 'package:nc_photos/widget/sign_in.dart'; -/// A useless widget class Splash extends StatefulWidget { static const routeName = "/splash"; @@ -22,17 +24,11 @@ class _SplashState extends State { initState() { super.initState(); WidgetsBinding.instance.addPostFrameCallback((timeStamp) { - Future.delayed(const Duration(seconds: 1)).then((_) { - final account = Pref.inst().getCurrentAccount(); - if (isNeedSetup()) { - Navigator.pushReplacementNamed(context, Setup.routeName); - } else if (account == null) { - Navigator.pushReplacementNamed(context, SignIn.routeName); - } else { - Navigator.pushReplacementNamed(context, Home.routeName, - arguments: HomeArguments(account)); - } - }); + if (_shouldUpgrade()) { + _handleUpgrade(); + } else { + _initTimedExit(); + } }); } @@ -69,4 +65,70 @@ class _SplashState extends State { ), ); } + + void _initTimedExit() { + Future.delayed(const Duration(seconds: 1)).then((_) { + final account = Pref.inst().getCurrentAccount(); + if (isNeedSetup()) { + Navigator.pushReplacementNamed(context, Setup.routeName); + } else if (account == null) { + Navigator.pushReplacementNamed(context, SignIn.routeName); + } else { + Navigator.pushReplacementNamed(context, Home.routeName, + arguments: HomeArguments(account)); + } + }); + } + + bool _shouldUpgrade() { + final lastVersion = Pref.inst().getLastVersion(k.version); + return lastVersion < k.version; + } + + void _handleUpgrade() { + final lastVersion = Pref.inst().getLastVersion(k.version); + // ... + + final change = _gatherChangelog(lastVersion); + if (change.isNotEmpty) { + showDialog( + context: context, + builder: (context) => AlertDialog( + title: Text(AppLocalizations.of(context).changelogTitle), + content: SingleChildScrollView( + child: Text(change), + ), + actions: [ + TextButton( + onPressed: () { + Navigator.of(context).pop(); + }, + child: Text(MaterialLocalizations.of(context).okButtonLabel), + ) + ], + ), + ).whenComplete(() { + _initTimedExit(); + Pref.inst().setLastVersion(k.version); + }); + } else { + _initTimedExit(); + Pref.inst().setLastVersion(k.version); + } + } + + String _gatherChangelog(int from) { + try { + return changelog.contents + .sublist(from) + .reversed + .where((element) => element != null) + .join("\n\n"); + } catch (e, stacktrace) { + _log.severe("[_gatherChangelog] Failed", e, stacktrace); + return ""; + } + } + + static final _log = Logger("widget.splash._SplashState"); }