mirror of
https://github.com/gabehf/Fladder.git
synced 2026-03-09 07:28:14 -07:00
feature: Added update notification and download links per platform (#362)
Co-authored-by: PartyDonut <PartyDonut@users.noreply.github.com>
This commit is contained in:
parent
5ef7936c33
commit
2c71dde228
16 changed files with 712 additions and 8 deletions
77
lib/providers/update_provider.dart
Normal file
77
lib/providers/update_provider.dart
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
|
||||
import 'package:fladder/providers/settings/client_settings_provider.dart';
|
||||
import 'package:fladder/util/update_checker.dart';
|
||||
|
||||
part 'update_provider.freezed.dart';
|
||||
part 'update_provider.g.dart';
|
||||
|
||||
Set<TargetPlatform> get _directUpdatePlatforms => {
|
||||
TargetPlatform.linux,
|
||||
TargetPlatform.macOS,
|
||||
TargetPlatform.windows,
|
||||
};
|
||||
|
||||
final hasNewUpdateProvider = Provider<bool>((ref) {
|
||||
//Disable update notification for platforms that are updated outside of Github.
|
||||
if (!_directUpdatePlatforms.contains(defaultTargetPlatform) || kIsWeb) {
|
||||
return false;
|
||||
}
|
||||
return ref.watch(clientSettingsProvider.select((value) => value.lastViewedUpdate)) !=
|
||||
ref.watch(updateProvider.select((value) => value.latestRelease?.version));
|
||||
});
|
||||
|
||||
@Riverpod(keepAlive: true)
|
||||
class Update extends _$Update {
|
||||
final updateChecker = UpdateChecker();
|
||||
|
||||
Timer? _timer;
|
||||
|
||||
@override
|
||||
UpdatesModel build() {
|
||||
final checkForUpdates = ref.watch(clientSettingsProvider.select((value) => value.checkForUpdates));
|
||||
|
||||
if (!checkForUpdates) {
|
||||
_timer?.cancel();
|
||||
return UpdatesModel();
|
||||
}
|
||||
ref.onDispose(() {
|
||||
_timer?.cancel();
|
||||
});
|
||||
|
||||
_timer?.cancel();
|
||||
|
||||
_timer = Timer.periodic(const Duration(minutes: 30), (timer) {
|
||||
_fetchLatest();
|
||||
});
|
||||
|
||||
_fetchLatest();
|
||||
|
||||
return UpdatesModel();
|
||||
}
|
||||
|
||||
Future<List<ReleaseInfo>> _fetchLatest() async {
|
||||
final latest = await updateChecker.fetchRecentReleases();
|
||||
state = state.copyWith(
|
||||
lastRelease: latest,
|
||||
);
|
||||
return latest;
|
||||
}
|
||||
}
|
||||
|
||||
@Freezed(toJson: false, fromJson: false)
|
||||
class UpdatesModel with _$UpdatesModel {
|
||||
const UpdatesModel._();
|
||||
|
||||
factory UpdatesModel({
|
||||
@Default([]) List<ReleaseInfo> lastRelease,
|
||||
}) = _UpdatesModel;
|
||||
|
||||
ReleaseInfo? get latestRelease => lastRelease.firstWhereOrNull((value) => value.isNewerThanCurrent);
|
||||
}
|
||||
163
lib/providers/update_provider.freezed.dart
Normal file
163
lib/providers/update_provider.freezed.dart
Normal file
|
|
@ -0,0 +1,163 @@
|
|||
// coverage:ignore-file
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
// ignore_for_file: type=lint
|
||||
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
|
||||
|
||||
part of 'update_provider.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// FreezedGenerator
|
||||
// **************************************************************************
|
||||
|
||||
T _$identity<T>(T value) => value;
|
||||
|
||||
final _privateConstructorUsedError = UnsupportedError(
|
||||
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');
|
||||
|
||||
/// @nodoc
|
||||
mixin _$UpdatesModel {
|
||||
List<ReleaseInfo> get lastRelease => throw _privateConstructorUsedError;
|
||||
|
||||
/// Create a copy of UpdatesModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
$UpdatesModelCopyWith<UpdatesModel> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class $UpdatesModelCopyWith<$Res> {
|
||||
factory $UpdatesModelCopyWith(
|
||||
UpdatesModel value, $Res Function(UpdatesModel) then) =
|
||||
_$UpdatesModelCopyWithImpl<$Res, UpdatesModel>;
|
||||
@useResult
|
||||
$Res call({List<ReleaseInfo> lastRelease});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class _$UpdatesModelCopyWithImpl<$Res, $Val extends UpdatesModel>
|
||||
implements $UpdatesModelCopyWith<$Res> {
|
||||
_$UpdatesModelCopyWithImpl(this._value, this._then);
|
||||
|
||||
// ignore: unused_field
|
||||
final $Val _value;
|
||||
// ignore: unused_field
|
||||
final $Res Function($Val) _then;
|
||||
|
||||
/// Create a copy of UpdatesModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? lastRelease = null,
|
||||
}) {
|
||||
return _then(_value.copyWith(
|
||||
lastRelease: null == lastRelease
|
||||
? _value.lastRelease
|
||||
: lastRelease // ignore: cast_nullable_to_non_nullable
|
||||
as List<ReleaseInfo>,
|
||||
) as $Val);
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$$UpdatesModelImplCopyWith<$Res>
|
||||
implements $UpdatesModelCopyWith<$Res> {
|
||||
factory _$$UpdatesModelImplCopyWith(
|
||||
_$UpdatesModelImpl value, $Res Function(_$UpdatesModelImpl) then) =
|
||||
__$$UpdatesModelImplCopyWithImpl<$Res>;
|
||||
@override
|
||||
@useResult
|
||||
$Res call({List<ReleaseInfo> lastRelease});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$$UpdatesModelImplCopyWithImpl<$Res>
|
||||
extends _$UpdatesModelCopyWithImpl<$Res, _$UpdatesModelImpl>
|
||||
implements _$$UpdatesModelImplCopyWith<$Res> {
|
||||
__$$UpdatesModelImplCopyWithImpl(
|
||||
_$UpdatesModelImpl _value, $Res Function(_$UpdatesModelImpl) _then)
|
||||
: super(_value, _then);
|
||||
|
||||
/// Create a copy of UpdatesModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? lastRelease = null,
|
||||
}) {
|
||||
return _then(_$UpdatesModelImpl(
|
||||
lastRelease: null == lastRelease
|
||||
? _value._lastRelease
|
||||
: lastRelease // ignore: cast_nullable_to_non_nullable
|
||||
as List<ReleaseInfo>,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
class _$UpdatesModelImpl extends _UpdatesModel with DiagnosticableTreeMixin {
|
||||
_$UpdatesModelImpl({final List<ReleaseInfo> lastRelease = const []})
|
||||
: _lastRelease = lastRelease,
|
||||
super._();
|
||||
|
||||
final List<ReleaseInfo> _lastRelease;
|
||||
@override
|
||||
@JsonKey()
|
||||
List<ReleaseInfo> get lastRelease {
|
||||
if (_lastRelease is EqualUnmodifiableListView) return _lastRelease;
|
||||
// ignore: implicit_dynamic_type
|
||||
return EqualUnmodifiableListView(_lastRelease);
|
||||
}
|
||||
|
||||
@override
|
||||
String toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) {
|
||||
return 'UpdatesModel(lastRelease: $lastRelease)';
|
||||
}
|
||||
|
||||
@override
|
||||
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
|
||||
super.debugFillProperties(properties);
|
||||
properties
|
||||
..add(DiagnosticsProperty('type', 'UpdatesModel'))
|
||||
..add(DiagnosticsProperty('lastRelease', lastRelease));
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType &&
|
||||
other is _$UpdatesModelImpl &&
|
||||
const DeepCollectionEquality()
|
||||
.equals(other._lastRelease, _lastRelease));
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(
|
||||
runtimeType, const DeepCollectionEquality().hash(_lastRelease));
|
||||
|
||||
/// Create a copy of UpdatesModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
_$$UpdatesModelImplCopyWith<_$UpdatesModelImpl> get copyWith =>
|
||||
__$$UpdatesModelImplCopyWithImpl<_$UpdatesModelImpl>(this, _$identity);
|
||||
}
|
||||
|
||||
abstract class _UpdatesModel extends UpdatesModel {
|
||||
factory _UpdatesModel({final List<ReleaseInfo> lastRelease}) =
|
||||
_$UpdatesModelImpl;
|
||||
_UpdatesModel._() : super._();
|
||||
|
||||
@override
|
||||
List<ReleaseInfo> get lastRelease;
|
||||
|
||||
/// Create a copy of UpdatesModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
_$$UpdatesModelImplCopyWith<_$UpdatesModelImpl> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
24
lib/providers/update_provider.g.dart
Normal file
24
lib/providers/update_provider.g.dart
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'update_provider.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
String _$updateHash() => r'97f7aca4e255d654a9295e1e9e019536faf6455e';
|
||||
|
||||
/// See also [Update].
|
||||
@ProviderFor(Update)
|
||||
final updateProvider = NotifierProvider<Update, UpdatesModel>.internal(
|
||||
Update.new,
|
||||
name: r'updateProvider',
|
||||
debugGetCreateSourceHash:
|
||||
const bool.fromEnvironment('dart.vm.product') ? null : _$updateHash,
|
||||
dependencies: null,
|
||||
allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
typedef _$Update = Notifier<UpdatesModel>;
|
||||
// ignore_for_file: type=lint
|
||||
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package
|
||||
Loading…
Add table
Add a link
Reference in a new issue