diff --git a/ios/Flutter/AppFrameworkInfo.plist b/ios/Flutter/AppFrameworkInfo.plist
index 8d4492f..9625e10 100644
--- a/ios/Flutter/AppFrameworkInfo.plist
+++ b/ios/Flutter/AppFrameworkInfo.plist
@@ -21,6 +21,6 @@
CFBundleVersion
1.0
MinimumOSVersion
- 9.0
+ 11.0
diff --git a/ios/Podfile b/ios/Podfile
index 1e8c3c9..88359b2 100644
--- a/ios/Podfile
+++ b/ios/Podfile
@@ -1,5 +1,5 @@
# Uncomment this line to define a global platform for your project
-# platform :ios, '9.0'
+# platform :ios, '11.0'
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
diff --git a/ios/Podfile.lock b/ios/Podfile.lock
index 4880c33..a154239 100644
--- a/ios/Podfile.lock
+++ b/ios/Podfile.lock
@@ -1,4 +1,6 @@
PODS:
+ - device_info_plus (0.0.1):
+ - Flutter
- Flutter (1.0.0)
- flutter_native_splash (0.0.1):
- Flutter
@@ -25,6 +27,7 @@ PODS:
- Flutter
DEPENDENCIES:
+ - device_info_plus (from `.symlinks/plugins/device_info_plus/ios`)
- Flutter (from `Flutter`)
- flutter_native_splash (from `.symlinks/plugins/flutter_native_splash/ios`)
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
@@ -40,6 +43,8 @@ SPEC REPOS:
- Sentry
EXTERNAL SOURCES:
+ device_info_plus:
+ :path: ".symlinks/plugins/device_info_plus/ios"
Flutter:
:path: Flutter
flutter_native_splash:
@@ -58,7 +63,8 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/url_launcher_ios/ios"
SPEC CHECKSUMS:
- Flutter: 50d75fe2f02b26cc09d224853bb45737f8b3214a
+ device_info_plus: e5c5da33f982a436e103237c0c85f9031142abed
+ Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854
flutter_native_splash: 52501b97d1c0a5f898d687f1646226c1f93c56ef
FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a
package_info_plus: 6c92f08e1f853dc01228d6f553146438dafcd14e
@@ -69,6 +75,6 @@ SPEC CHECKSUMS:
sqflite: 6d358c025f5b867b29ed92fc697fd34924e11904
url_launcher_ios: 839c58cdb4279282219f5e248c3321761ff3c4de
-PODFILE CHECKSUM: aafe91acc616949ddb318b77800a7f51bffa2a4c
+PODFILE CHECKSUM: ef19549a9bc3046e7bb7d2fab4d021637c0c58a3
COCOAPODS: 1.11.3
diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj
index 1ccfe8e..6f9779f 100644
--- a/ios/Runner.xcodeproj/project.pbxproj
+++ b/ios/Runner.xcodeproj/project.pbxproj
@@ -350,7 +350,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 9.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 11.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
@@ -429,7 +429,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 9.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 11.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
@@ -479,7 +479,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 9.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 11.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
diff --git a/lib/core/widgets/dwi_appbar.dart b/lib/core/widgets/dwi_appbar.dart
index 20c9780..1bd5075 100644
--- a/lib/core/widgets/dwi_appbar.dart
+++ b/lib/core/widgets/dwi_appbar.dart
@@ -1,7 +1,9 @@
+import 'package:dwi/core/widgets/widgets.dart';
import 'package:dwi/features/features.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
+import 'package:upgrader/upgrader.dart';
/// DWIAppBar
class DWIAppBar extends StatelessWidget implements PreferredSizeWidget {
@@ -17,6 +19,7 @@ class DWIAppBar extends StatelessWidget implements PreferredSizeWidget {
preferredSize: preferredSize,
child: AppBar(
actions: const [
+ _UpdateButton(),
_AddCounterButton(),
_DeleteCounterButton(),
_AboutButton(),
@@ -85,3 +88,30 @@ class _DeleteCounterButton extends StatelessWidget {
);
}
}
+
+class _UpdateButton extends StatelessWidget {
+ const _UpdateButton({
+ Key? key,
+ }) : super(key: key);
+
+ @override
+ Widget build(BuildContext context) {
+ return UpgradeWidget(
+ upgrader: Upgrader(
+ //! This is a bit of a hack to allow the alert dialog to be shown
+ //! repeatedly.
+ durationUntilAlertAgain: const Duration(milliseconds: 500),
+ showReleaseNotes: false,
+ showIgnore: false,
+ ),
+ builder: (context, upgrader) => CircleAvatar(
+ child: IconButton(
+ onPressed: () {
+ upgrader.checkVersion(context: context);
+ },
+ icon: const Icon(Icons.upload),
+ ),
+ ),
+ );
+ }
+}
diff --git a/lib/core/widgets/upgrade_widget.dart b/lib/core/widgets/upgrade_widget.dart
new file mode 100644
index 0000000..fe5d29c
--- /dev/null
+++ b/lib/core/widgets/upgrade_widget.dart
@@ -0,0 +1,51 @@
+import 'dart:developer';
+
+import 'package:flutter/material.dart';
+import 'package:upgrader/upgrader.dart';
+
+/// Defines a builder function that allows you to create a custom widget
+/// that is displayed in a similar fashion as [UpgradeCard]
+typedef UpgradeWidgetBuilder = Widget Function(
+ BuildContext context,
+ Upgrader upgrader,
+);
+
+/// A widget to display by checking upgrader info available.
+class UpgradeWidget extends UpgradeBase {
+ /// Creates a new [UpgradeWidget].
+ UpgradeWidget({
+ Key? key,
+ Upgrader? upgrader,
+ required this.builder,
+ }) : super(upgrader ?? Upgrader.sharedInstance as Upgrader, key: key);
+
+ /// Defines how the widget will be built. Allows the implementation of custom
+ /// widgets.
+ final UpgradeWidgetBuilder builder;
+
+ /// Describes the part of the user interface represented by this widget.
+ @override
+ Widget build(BuildContext context, UpgradeBaseState state) {
+ if (upgrader.debugLogging) {
+ log('UpgradeWidget: build UpgradeWidget');
+ }
+
+ return FutureBuilder(
+ future: state.initialized,
+ builder: (BuildContext context, AsyncSnapshot processed) {
+ if (processed.connectionState == ConnectionState.done &&
+ processed.data != null &&
+ processed.data!) {
+ if (upgrader.shouldDisplayUpgrade()) {
+ if (upgrader.debugLogging) {
+ log('UpgradeWidget: will call builder');
+ }
+ return builder.call(context, upgrader);
+ }
+ }
+
+ return const SizedBox.shrink();
+ },
+ );
+ }
+}
diff --git a/lib/core/widgets/widgets.dart b/lib/core/widgets/widgets.dart
index d2750e3..7b3e9c6 100644
--- a/lib/core/widgets/widgets.dart
+++ b/lib/core/widgets/widgets.dart
@@ -1,2 +1,3 @@
export 'dwi_appbar.dart';
export 'empty_state.dart';
+export 'upgrade_widget.dart';
diff --git a/lib/main.dart b/lib/main.dart
index 4b09847..ba93c39 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -1,11 +1,20 @@
import 'package:data/data.dart';
import 'package:domain/domain.dart';
import 'package:dwi/core/application/application.dart';
+import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:sentry_flutter/sentry_flutter.dart';
+import 'package:upgrader/upgrader.dart';
Future main() async {
+ WidgetsFlutterBinding.ensureInitialized();
+
+ // Only call clearSavedSettings() during testing to reset internal values.
+ if (kDebugMode) {
+ await Upgrader.clearSavedSettings();
+ }
+
await SentryFlutter.init(
(options) {},
appRunner: () => runApp(
diff --git a/pubspec.lock b/pubspec.lock
index cbb740d..5f76c8c 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -7,14 +7,14 @@ packages:
name: _fe_analyzer_shared
url: "https://pub.dartlang.org"
source: hosted
- version: "31.0.0"
+ version: "38.0.0"
analyzer:
dependency: transitive
description:
name: analyzer
url: "https://pub.dartlang.org"
source: hosted
- version: "2.8.0"
+ version: "3.4.1"
archive:
dependency: transitive
description:
@@ -35,7 +35,7 @@ packages:
name: async
url: "https://pub.dartlang.org"
source: hosted
- version: "2.8.2"
+ version: "2.9.0"
bloc:
dependency: transitive
description:
@@ -84,7 +84,7 @@ packages:
name: characters
url: "https://pub.dartlang.org"
source: hosted
- version: "1.2.0"
+ version: "1.2.1"
charcode:
dependency: transitive
description:
@@ -112,7 +112,7 @@ packages:
name: clock
url: "https://pub.dartlang.org"
source: hosted
- version: "1.1.0"
+ version: "1.1.1"
code_builder:
dependency: transitive
description:
@@ -169,6 +169,48 @@ packages:
relative: true
source: path
version: "1.0.0"
+ device_info_plus:
+ dependency: transitive
+ description:
+ name: device_info_plus
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "4.1.3"
+ device_info_plus_linux:
+ dependency: transitive
+ description:
+ name: device_info_plus_linux
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "3.0.0"
+ device_info_plus_macos:
+ dependency: transitive
+ description:
+ name: device_info_plus_macos
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "3.0.0"
+ device_info_plus_platform_interface:
+ dependency: transitive
+ description:
+ name: device_info_plus_platform_interface
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "3.0.0"
+ device_info_plus_web:
+ dependency: transitive
+ description:
+ name: device_info_plus_web
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "3.0.0"
+ device_info_plus_windows:
+ dependency: transitive
+ description:
+ name: device_info_plus_windows
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "4.1.0"
diff_match_patch:
dependency: transitive
description:
@@ -196,7 +238,7 @@ packages:
name: fake_async
url: "https://pub.dartlang.org"
source: hosted
- version: "1.3.0"
+ version: "1.3.1"
ffi:
dependency: transitive
description:
@@ -370,21 +412,21 @@ packages:
name: matcher
url: "https://pub.dartlang.org"
source: hosted
- version: "0.12.11"
+ version: "0.12.12"
material_color_utilities:
dependency: transitive
description:
name: material_color_utilities
url: "https://pub.dartlang.org"
source: hosted
- version: "0.1.4"
+ version: "0.1.5"
meta:
dependency: transitive
description:
name: meta
url: "https://pub.dartlang.org"
source: hosted
- version: "1.7.0"
+ version: "1.8.0"
mime:
dependency: transitive
description:
@@ -420,6 +462,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.1"
+ os_detect:
+ dependency: transitive
+ description:
+ name: os_detect
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "2.0.1"
package_config:
dependency: transitive
description:
@@ -475,7 +524,7 @@ packages:
name: path
url: "https://pub.dartlang.org"
source: hosted
- version: "1.8.1"
+ version: "1.8.2"
path_provider:
dependency: transitive
description:
@@ -711,7 +760,7 @@ packages:
name: source_span
url: "https://pub.dartlang.org"
source: hosted
- version: "1.8.2"
+ version: "1.9.0"
sqflite:
dependency: transitive
description:
@@ -746,7 +795,7 @@ packages:
name: string_scanner
url: "https://pub.dartlang.org"
source: hosted
- version: "1.1.0"
+ version: "1.1.1"
synchronized:
dependency: transitive
description:
@@ -760,28 +809,28 @@ packages:
name: term_glyph
url: "https://pub.dartlang.org"
source: hosted
- version: "1.2.0"
+ version: "1.2.1"
test:
dependency: transitive
description:
name: test
url: "https://pub.dartlang.org"
source: hosted
- version: "1.20.2"
+ version: "1.21.4"
test_api:
dependency: transitive
description:
name: test_api
url: "https://pub.dartlang.org"
source: hosted
- version: "0.4.9"
+ version: "0.4.12"
test_core:
dependency: transitive
description:
name: test_core
url: "https://pub.dartlang.org"
source: hosted
- version: "0.4.11"
+ version: "0.4.16"
typed_data:
dependency: transitive
description:
@@ -796,6 +845,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.4"
+ upgrader:
+ dependency: "direct main"
+ description:
+ name: upgrader
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "4.8.0"
url_launcher:
dependency: "direct main"
description:
@@ -866,6 +922,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.2"
+ version:
+ dependency: transitive
+ description:
+ name: version
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "3.0.2"
very_good_analysis:
dependency: "direct dev"
description:
diff --git a/pubspec.yaml b/pubspec.yaml
index 697db31..772a402 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -7,33 +7,24 @@ environment:
sdk: '>=2.12.0 <3.0.0'
dependencies:
- # Data layer
data:
path: packages/data
- # Domain layer
domain:
path: packages/domain
- # Value equality
equatable: ^2.0.5
fl_chart: ^0.55.1
flutter:
sdk: flutter
- # Bloc for state management
flutter_bloc: ^8.1.1
- # Feather Icons package
flutter_feather_icons: ^2.0.0
flutter_localizations:
sdk: flutter
- # Build Information
intl: ^0.17.0
package_info_plus: ^1.4.3+1
- # Monitoring
sentry_flutter: ^6.9.1
- # Launcher for URLs
+ upgrader: ^4.8.0
url_launcher: ^6.1.5
- # UUID
uuid: ^3.0.6
- # Bug Reporting
wiredash: ^1.5.0
dev_dependencies:
@@ -47,7 +38,7 @@ dev_dependencies:
flutter_icons:
image_path: 'assets/launcher/dwi-512x512-android.png'
- android: true # can specify file name here e.g. "ic_launcher"
+ android: true
ios: true
adaptive_icon_background: '#56F0D4'
adaptive_icon_foreground: 'assets/launcher/dwi-foreground.png'