about: new version check
This commit is contained in:
parent
c05b646ddd
commit
45ba3155b0
13 changed files with 330 additions and 112 deletions
|
@ -1,11 +1,17 @@
|
||||||
|
import 'package:aves/model/settings/settings.dart';
|
||||||
|
import 'package:aves/theme/durations.dart';
|
||||||
import 'package:connectivity/connectivity.dart';
|
import 'package:connectivity/connectivity.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:github/github.dart';
|
||||||
import 'package:google_api_availability/google_api_availability.dart';
|
import 'package:google_api_availability/google_api_availability.dart';
|
||||||
|
import 'package:package_info/package_info.dart';
|
||||||
|
import 'package:version/version.dart';
|
||||||
|
|
||||||
final AvesAvailability availability = AvesAvailability._private();
|
final AvesAvailability availability = AvesAvailability._private();
|
||||||
|
|
||||||
class AvesAvailability {
|
class AvesAvailability {
|
||||||
bool _isConnected, _hasPlayServices;
|
bool _isConnected, _hasPlayServices, _isNewVersionAvailable;
|
||||||
|
|
||||||
AvesAvailability._private() {
|
AvesAvailability._private() {
|
||||||
Connectivity().onConnectivityChanged.listen(_updateConnectivityFromResult);
|
Connectivity().onConnectivityChanged.listen(_updateConnectivityFromResult);
|
||||||
|
@ -38,4 +44,29 @@ class AvesAvailability {
|
||||||
|
|
||||||
// local geolocation with `geocoder` requires Play Services
|
// local geolocation with `geocoder` requires Play Services
|
||||||
Future<bool> get canGeolocate => Future.wait<bool>([isConnected, hasPlayServices]).then((results) => results.every((result) => result));
|
Future<bool> get canGeolocate => Future.wait<bool>([isConnected, hasPlayServices]).then((results) => results.every((result) => result));
|
||||||
|
|
||||||
|
Future<bool> get isNewVersionAvailable async {
|
||||||
|
if (_isNewVersionAvailable != null) return SynchronousFuture(_isNewVersionAvailable);
|
||||||
|
|
||||||
|
final now = DateTime.now();
|
||||||
|
final dueDate = settings.lastVersionCheckDate.add(Durations.lastVersionCheckInterval);
|
||||||
|
if (now.isBefore(dueDate)) {
|
||||||
|
_isNewVersionAvailable = false;
|
||||||
|
return SynchronousFuture(_isNewVersionAvailable);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(await isConnected)) return false;
|
||||||
|
|
||||||
|
Version version(String s) => Version.parse(s.replaceFirst('v', ''));
|
||||||
|
final currentTag = (await PackageInfo.fromPlatform()).version;
|
||||||
|
final latestTag = (await GitHub().repositories.getLatestRelease(RepositorySlug('deckerst', 'aves'))).tagName;
|
||||||
|
_isNewVersionAvailable = version(latestTag) > version(currentTag);
|
||||||
|
if (_isNewVersionAvailable) {
|
||||||
|
debugPrint('Aves $latestTag is available on github');
|
||||||
|
} else {
|
||||||
|
debugPrint('Aves $currentTag is the latest version');
|
||||||
|
settings.lastVersionCheckDate = now;
|
||||||
|
}
|
||||||
|
return _isNewVersionAvailable;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,6 +64,9 @@ class Settings extends ChangeNotifier {
|
||||||
static const saveSearchHistoryKey = 'save_search_history';
|
static const saveSearchHistoryKey = 'save_search_history';
|
||||||
static const searchHistoryKey = 'search_history';
|
static const searchHistoryKey = 'search_history';
|
||||||
|
|
||||||
|
// version
|
||||||
|
static const lastVersionCheckDateKey = 'last_version_check_date';
|
||||||
|
|
||||||
Future<void> init() async {
|
Future<void> init() async {
|
||||||
_prefs = await SharedPreferences.getInstance();
|
_prefs = await SharedPreferences.getInstance();
|
||||||
}
|
}
|
||||||
|
@ -214,6 +217,12 @@ class Settings extends ChangeNotifier {
|
||||||
|
|
||||||
set searchHistory(List<CollectionFilter> newValue) => setAndNotify(searchHistoryKey, newValue.map((filter) => filter.toJson()).toList());
|
set searchHistory(List<CollectionFilter> newValue) => setAndNotify(searchHistoryKey, newValue.map((filter) => filter.toJson()).toList());
|
||||||
|
|
||||||
|
// version
|
||||||
|
|
||||||
|
DateTime get lastVersionCheckDate => DateTime.fromMillisecondsSinceEpoch(_prefs.getInt(lastVersionCheckDateKey) ?? 0);
|
||||||
|
|
||||||
|
set lastVersionCheckDate(DateTime newValue) => setAndNotify(lastVersionCheckDateKey, newValue.millisecondsSinceEpoch);
|
||||||
|
|
||||||
// convenience methods
|
// convenience methods
|
||||||
|
|
||||||
// ignore: avoid_positional_boolean_parameters
|
// ignore: avoid_positional_boolean_parameters
|
||||||
|
|
|
@ -35,7 +35,7 @@ class Durations {
|
||||||
static const viewerOverlayChangeAnimation = Duration(milliseconds: 150);
|
static const viewerOverlayChangeAnimation = Duration(milliseconds: 150);
|
||||||
static const viewerOverlayPageChooserAnimation = Duration(milliseconds: 200);
|
static const viewerOverlayPageChooserAnimation = Duration(milliseconds: 200);
|
||||||
|
|
||||||
// info
|
// info animations
|
||||||
static const mapStyleSwitchAnimation = Duration(milliseconds: 300);
|
static const mapStyleSwitchAnimation = Duration(milliseconds: 300);
|
||||||
static const xmpStructArrayCardTransition = Duration(milliseconds: 300);
|
static const xmpStructArrayCardTransition = Duration(milliseconds: 300);
|
||||||
|
|
||||||
|
@ -49,4 +49,7 @@ class Durations {
|
||||||
static const softKeyboardDisplayDelay = Duration(milliseconds: 300);
|
static const softKeyboardDisplayDelay = Duration(milliseconds: 300);
|
||||||
static const searchDebounceDelay = Duration(milliseconds: 250);
|
static const searchDebounceDelay = Duration(milliseconds: 250);
|
||||||
static const contentChangeDebounceDelay = Duration(milliseconds: 500);
|
static const contentChangeDebounceDelay = Duration(milliseconds: 500);
|
||||||
|
|
||||||
|
// app life
|
||||||
|
static const lastVersionCheckInterval = Duration(days: 7);
|
||||||
}
|
}
|
||||||
|
|
|
@ -167,6 +167,12 @@ class Constants {
|
||||||
licenseUrl: 'https://github.com/aloisdeniel/flutter_geocoder/blob/master/LICENSE',
|
licenseUrl: 'https://github.com/aloisdeniel/flutter_geocoder/blob/master/LICENSE',
|
||||||
sourceUrl: 'https://github.com/aloisdeniel/flutter_geocoder',
|
sourceUrl: 'https://github.com/aloisdeniel/flutter_geocoder',
|
||||||
),
|
),
|
||||||
|
Dependency(
|
||||||
|
name: 'Github',
|
||||||
|
license: 'MIT',
|
||||||
|
licenseUrl: 'https://github.com/SpinlockLabs/github.dart/blob/master/LICENSE',
|
||||||
|
sourceUrl: 'https://github.com/SpinlockLabs/github.dart',
|
||||||
|
),
|
||||||
Dependency(
|
Dependency(
|
||||||
name: 'Google Maps for Flutter',
|
name: 'Google Maps for Flutter',
|
||||||
license: 'BSD 3-Clause',
|
license: 'BSD 3-Clause',
|
||||||
|
@ -287,6 +293,12 @@ class Constants {
|
||||||
licenseUrl: 'https://github.com/flutter/plugins/blob/master/packages/url_launcher/url_launcher/LICENSE',
|
licenseUrl: 'https://github.com/flutter/plugins/blob/master/packages/url_launcher/url_launcher/LICENSE',
|
||||||
sourceUrl: 'https://github.com/flutter/plugins/blob/master/packages/url_launcher/url_launcher',
|
sourceUrl: 'https://github.com/flutter/plugins/blob/master/packages/url_launcher/url_launcher',
|
||||||
),
|
),
|
||||||
|
Dependency(
|
||||||
|
name: 'Version',
|
||||||
|
license: 'BSD 3-Clause',
|
||||||
|
licenseUrl: 'https://github.com/dartninja/version/blob/master/LICENSE',
|
||||||
|
sourceUrl: 'https://github.com/dartninja/version',
|
||||||
|
),
|
||||||
Dependency(
|
Dependency(
|
||||||
name: 'XML',
|
name: 'XML',
|
||||||
license: 'MIT',
|
license: 'MIT',
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
import 'package:aves/flutter_version.dart';
|
import 'package:aves/flutter_version.dart';
|
||||||
|
import 'package:aves/widgets/about/app_ref.dart';
|
||||||
|
import 'package:aves/widgets/about/credits.dart';
|
||||||
import 'package:aves/widgets/about/licenses.dart';
|
import 'package:aves/widgets/about/licenses.dart';
|
||||||
|
import 'package:aves/widgets/about/new_version.dart';
|
||||||
import 'package:aves/widgets/common/basic/link_chip.dart';
|
import 'package:aves/widgets/common/basic/link_chip.dart';
|
||||||
import 'package:aves/widgets/common/identity/aves_logo.dart';
|
import 'package:aves/widgets/common/identity/aves_logo.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
@ -23,43 +26,9 @@ class AboutPage extends StatelessWidget {
|
||||||
delegate: SliverChildListDelegate(
|
delegate: SliverChildListDelegate(
|
||||||
[
|
[
|
||||||
AppReference(),
|
AppReference(),
|
||||||
SizedBox(height: 16),
|
|
||||||
Divider(),
|
Divider(),
|
||||||
Padding(
|
AboutNewVersion(),
|
||||||
padding: EdgeInsets.symmetric(horizontal: 16),
|
AboutCredits(),
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
ConstrainedBox(
|
|
||||||
constraints: BoxConstraints(minHeight: 48),
|
|
||||||
child: Align(
|
|
||||||
alignment: AlignmentDirectional.centerStart,
|
|
||||||
child: Text(
|
|
||||||
'Credits',
|
|
||||||
style: Theme.of(context).textTheme.headline6.copyWith(fontFamily: 'Concourse Caps'),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
RichText(
|
|
||||||
text: TextSpan(
|
|
||||||
children: [
|
|
||||||
TextSpan(text: 'This app uses the font '),
|
|
||||||
WidgetSpan(
|
|
||||||
child: LinkChip(
|
|
||||||
text: 'Concourse',
|
|
||||||
url: 'https://mbtype.com/fonts/concourse/',
|
|
||||||
textStyle: TextStyle(fontWeight: FontWeight.bold),
|
|
||||||
),
|
|
||||||
alignment: PlaceholderAlignment.middle,
|
|
||||||
),
|
|
||||||
TextSpan(text: ' for titles and the media information page.'),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SizedBox(height: 16),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Divider(),
|
Divider(),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
@ -72,71 +41,3 @@ class AboutPage extends StatelessWidget {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class AppReference extends StatefulWidget {
|
|
||||||
@override
|
|
||||||
_AppReferenceState createState() => _AppReferenceState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _AppReferenceState extends State<AppReference> {
|
|
||||||
Future<PackageInfo> packageInfoLoader;
|
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
super.initState();
|
|
||||||
packageInfoLoader = PackageInfo.fromPlatform();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Center(
|
|
||||||
child: Column(
|
|
||||||
children: [
|
|
||||||
_buildAvesLine(),
|
|
||||||
_buildFlutterLine(),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget _buildAvesLine() {
|
|
||||||
final textTheme = Theme.of(context).textTheme;
|
|
||||||
final style = textTheme.headline6.copyWith(fontWeight: FontWeight.bold);
|
|
||||||
|
|
||||||
return FutureBuilder<PackageInfo>(
|
|
||||||
future: packageInfoLoader,
|
|
||||||
builder: (context, snapshot) {
|
|
||||||
return LinkChip(
|
|
||||||
leading: AvesLogo(
|
|
||||||
size: style.fontSize * 1.25,
|
|
||||||
),
|
|
||||||
text: 'Aves ${snapshot.data?.version}',
|
|
||||||
url: 'https://github.com/deckerst/aves',
|
|
||||||
textStyle: style,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget _buildFlutterLine() {
|
|
||||||
final style = DefaultTextStyle.of(context).style;
|
|
||||||
final subColor = style.color.withOpacity(.6);
|
|
||||||
|
|
||||||
return Text.rich(
|
|
||||||
TextSpan(
|
|
||||||
children: [
|
|
||||||
WidgetSpan(
|
|
||||||
child: Padding(
|
|
||||||
padding: EdgeInsetsDirectional.only(end: 4),
|
|
||||||
child: FlutterLogo(
|
|
||||||
size: style.fontSize * 1.25,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
TextSpan(text: 'Flutter ${version['frameworkVersion']}'),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
style: TextStyle(color: subColor),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
74
lib/widgets/about/app_ref.dart
Normal file
74
lib/widgets/about/app_ref.dart
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
import 'package:aves/flutter_version.dart';
|
||||||
|
import 'package:aves/widgets/common/basic/link_chip.dart';
|
||||||
|
import 'package:aves/widgets/common/identity/aves_logo.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:package_info/package_info.dart';
|
||||||
|
|
||||||
|
class AppReference extends StatefulWidget {
|
||||||
|
@override
|
||||||
|
_AppReferenceState createState() => _AppReferenceState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _AppReferenceState extends State<AppReference> {
|
||||||
|
Future<PackageInfo> _packageInfoLoader;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_packageInfoLoader = PackageInfo.fromPlatform();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Center(
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
_buildAvesLine(),
|
||||||
|
_buildFlutterLine(),
|
||||||
|
SizedBox(height: 16),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildAvesLine() {
|
||||||
|
final textTheme = Theme.of(context).textTheme;
|
||||||
|
final style = textTheme.headline6.copyWith(fontWeight: FontWeight.bold);
|
||||||
|
|
||||||
|
return FutureBuilder<PackageInfo>(
|
||||||
|
future: _packageInfoLoader,
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
return LinkChip(
|
||||||
|
leading: AvesLogo(
|
||||||
|
size: style.fontSize * 1.25,
|
||||||
|
),
|
||||||
|
text: 'Aves ${snapshot.data?.version}',
|
||||||
|
url: 'https://github.com/deckerst/aves',
|
||||||
|
textStyle: style,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildFlutterLine() {
|
||||||
|
final style = DefaultTextStyle.of(context).style;
|
||||||
|
final subColor = style.color.withOpacity(.6);
|
||||||
|
|
||||||
|
return Text.rich(
|
||||||
|
TextSpan(
|
||||||
|
children: [
|
||||||
|
WidgetSpan(
|
||||||
|
child: Padding(
|
||||||
|
padding: EdgeInsetsDirectional.only(end: 4),
|
||||||
|
child: FlutterLogo(
|
||||||
|
size: style.fontSize * 1.25,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
TextSpan(text: 'Flutter ${version['frameworkVersion']}'),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
style: TextStyle(color: subColor),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
43
lib/widgets/about/credits.dart
Normal file
43
lib/widgets/about/credits.dart
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
import 'package:aves/widgets/common/basic/link_chip.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class AboutCredits extends StatelessWidget {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Padding(
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 16),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
ConstrainedBox(
|
||||||
|
constraints: BoxConstraints(minHeight: 48),
|
||||||
|
child: Align(
|
||||||
|
alignment: AlignmentDirectional.centerStart,
|
||||||
|
child: Text(
|
||||||
|
'Credits',
|
||||||
|
style: Theme.of(context).textTheme.headline6.copyWith(fontFamily: 'Concourse Caps'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text.rich(
|
||||||
|
TextSpan(
|
||||||
|
children: [
|
||||||
|
TextSpan(text: 'This app uses the font '),
|
||||||
|
WidgetSpan(
|
||||||
|
child: LinkChip(
|
||||||
|
text: 'Concourse',
|
||||||
|
url: 'https://mbtype.com/fonts/concourse/',
|
||||||
|
textStyle: TextStyle(fontWeight: FontWeight.bold),
|
||||||
|
),
|
||||||
|
alignment: PlaceholderAlignment.middle,
|
||||||
|
),
|
||||||
|
TextSpan(text: ' for titles and the media information page.'),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(height: 16),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
92
lib/widgets/about/new_version.dart
Normal file
92
lib/widgets/about/new_version.dart
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
import 'package:aves/model/availability.dart';
|
||||||
|
import 'package:aves/widgets/about/news_badge.dart';
|
||||||
|
import 'package:aves/widgets/common/basic/link_chip.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class AboutNewVersion extends StatefulWidget {
|
||||||
|
@override
|
||||||
|
_AboutNewVersionState createState() => _AboutNewVersionState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _AboutNewVersionState extends State<AboutNewVersion> {
|
||||||
|
Future<bool> _newVersionLoader;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_newVersionLoader = availability.isNewVersionAvailable;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return FutureBuilder<bool>(
|
||||||
|
future: _newVersionLoader,
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
final newVersion = snapshot.data == true;
|
||||||
|
if (!newVersion) return SizedBox();
|
||||||
|
return Column(
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 16),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
ConstrainedBox(
|
||||||
|
constraints: BoxConstraints(minHeight: 48),
|
||||||
|
child: Align(
|
||||||
|
alignment: AlignmentDirectional.centerStart,
|
||||||
|
child: Text.rich(
|
||||||
|
TextSpan(
|
||||||
|
children: [
|
||||||
|
WidgetSpan(
|
||||||
|
child: Padding(
|
||||||
|
padding: EdgeInsetsDirectional.only(end: 8),
|
||||||
|
child: AboutNewsBadge(),
|
||||||
|
),
|
||||||
|
alignment: PlaceholderAlignment.middle,
|
||||||
|
),
|
||||||
|
TextSpan(
|
||||||
|
text: 'New Version Available',
|
||||||
|
style: Theme.of(context).textTheme.headline6.copyWith(fontFamily: 'Concourse Caps'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text.rich(
|
||||||
|
TextSpan(
|
||||||
|
children: [
|
||||||
|
TextSpan(text: 'A new version of Aves is available on '),
|
||||||
|
WidgetSpan(
|
||||||
|
child: LinkChip(
|
||||||
|
text: 'Github',
|
||||||
|
url: 'https://github.com/deckerst/aves/releases',
|
||||||
|
textStyle: TextStyle(fontWeight: FontWeight.bold),
|
||||||
|
),
|
||||||
|
alignment: PlaceholderAlignment.middle,
|
||||||
|
),
|
||||||
|
TextSpan(text: ' and '),
|
||||||
|
WidgetSpan(
|
||||||
|
child: LinkChip(
|
||||||
|
text: 'Google Play',
|
||||||
|
url: 'https://play.google.com/store/apps/details?id=deckers.thibault.aves',
|
||||||
|
textStyle: TextStyle(fontWeight: FontWeight.bold),
|
||||||
|
),
|
||||||
|
alignment: PlaceholderAlignment.middle,
|
||||||
|
),
|
||||||
|
TextSpan(text: '.'),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(height: 16),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Divider(),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
12
lib/widgets/about/news_badge.dart
Normal file
12
lib/widgets/about/news_badge.dart
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class AboutNewsBadge extends StatelessWidget {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Icon(
|
||||||
|
Icons.circle,
|
||||||
|
size: 12,
|
||||||
|
color: Colors.red,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -39,6 +39,7 @@ class DebugSettingsSection extends StatelessWidget {
|
||||||
'infoMapZoom': '${settings.infoMapZoom}',
|
'infoMapZoom': '${settings.infoMapZoom}',
|
||||||
'pinnedFilters': toMultiline(settings.pinnedFilters),
|
'pinnedFilters': toMultiline(settings.pinnedFilters),
|
||||||
'searchHistory': toMultiline(settings.searchHistory),
|
'searchHistory': toMultiline(settings.searchHistory),
|
||||||
|
'lastVersionCheckDate': '${settings.lastVersionCheckDate}',
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import 'dart:ui';
|
import 'dart:ui';
|
||||||
|
|
||||||
|
import 'package:aves/model/availability.dart';
|
||||||
import 'package:aves/model/filters/album.dart';
|
import 'package:aves/model/filters/album.dart';
|
||||||
import 'package:aves/model/filters/favourite.dart';
|
import 'package:aves/model/filters/favourite.dart';
|
||||||
import 'package:aves/model/filters/mime.dart';
|
import 'package:aves/model/filters/mime.dart';
|
||||||
|
@ -11,6 +12,7 @@ import 'package:aves/ref/mime_types.dart';
|
||||||
import 'package:aves/theme/icons.dart';
|
import 'package:aves/theme/icons.dart';
|
||||||
import 'package:aves/utils/android_file_utils.dart';
|
import 'package:aves/utils/android_file_utils.dart';
|
||||||
import 'package:aves/widgets/about/about_page.dart';
|
import 'package:aves/widgets/about/about_page.dart';
|
||||||
|
import 'package:aves/widgets/about/news_badge.dart';
|
||||||
import 'package:aves/widgets/common/extensions/media_query.dart';
|
import 'package:aves/widgets/common/extensions/media_query.dart';
|
||||||
import 'package:aves/widgets/common/identity/aves_icons.dart';
|
import 'package:aves/widgets/common/identity/aves_icons.dart';
|
||||||
import 'package:aves/widgets/common/identity/aves_logo.dart';
|
import 'package:aves/widgets/common/identity/aves_logo.dart';
|
||||||
|
@ -35,8 +37,16 @@ class AppDrawer extends StatefulWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
class _AppDrawerState extends State<AppDrawer> {
|
class _AppDrawerState extends State<AppDrawer> {
|
||||||
|
Future<bool> _newVersionLoader;
|
||||||
|
|
||||||
CollectionSource get source => widget.source;
|
CollectionSource get source => widget.source;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_newVersionLoader = availability.isNewVersionAvailable;
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final drawerItems = <Widget>[
|
final drawerItems = <Widget>[
|
||||||
|
@ -211,12 +221,19 @@ class _AppDrawerState extends State<AppDrawer> {
|
||||||
pageBuilder: (_) => SettingsPage(),
|
pageBuilder: (_) => SettingsPage(),
|
||||||
);
|
);
|
||||||
|
|
||||||
Widget get aboutTile => NavTile(
|
Widget get aboutTile => FutureBuilder<bool>(
|
||||||
icon: AIcons.info,
|
future: _newVersionLoader,
|
||||||
title: 'About',
|
builder: (context, snapshot) {
|
||||||
topLevel: false,
|
final newVersion = snapshot.data == true;
|
||||||
routeName: AboutPage.routeName,
|
return NavTile(
|
||||||
pageBuilder: (_) => AboutPage(),
|
icon: AIcons.info,
|
||||||
|
title: 'About',
|
||||||
|
trailing: newVersion ? AboutNewsBadge() : null,
|
||||||
|
topLevel: false,
|
||||||
|
routeName: AboutPage.routeName,
|
||||||
|
pageBuilder: (_) => AboutPage(),
|
||||||
|
);
|
||||||
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
Widget get debugTile => NavTile(
|
Widget get debugTile => NavTile(
|
||||||
|
|
21
pubspec.lock
21
pubspec.lock
|
@ -380,6 +380,13 @@ packages:
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.2.1"
|
version: "0.2.1"
|
||||||
|
github:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: github
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "7.0.4"
|
||||||
glob:
|
glob:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -464,6 +471,13 @@ packages:
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.6.3-nullsafety.2"
|
version: "0.6.3-nullsafety.2"
|
||||||
|
json_annotation:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: json_annotation
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "3.1.1"
|
||||||
json_rpc_2:
|
json_rpc_2:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -1043,6 +1057,13 @@ packages:
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.0-nullsafety.3"
|
version: "2.1.0-nullsafety.3"
|
||||||
|
version:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: version
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.2.0"
|
||||||
vm_service:
|
vm_service:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
|
@ -55,6 +55,7 @@ dependencies:
|
||||||
flutter_staggered_animations:
|
flutter_staggered_animations:
|
||||||
flutter_svg:
|
flutter_svg:
|
||||||
geocoder:
|
geocoder:
|
||||||
|
github:
|
||||||
google_api_availability:
|
google_api_availability:
|
||||||
google_maps_flutter:
|
google_maps_flutter:
|
||||||
intl:
|
intl:
|
||||||
|
@ -76,6 +77,7 @@ dependencies:
|
||||||
streams_channel:
|
streams_channel:
|
||||||
tuple:
|
tuple:
|
||||||
url_launcher:
|
url_launcher:
|
||||||
|
version:
|
||||||
xml:
|
xml:
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
|
|
Loading…
Reference in a new issue