added timestamp to bloc cache, showing age in offline mode
This commit is contained in:
parent
3281b134e0
commit
ebbb70dc96
@ -4,6 +4,6 @@ import 'data_loader.dart';
|
|||||||
|
|
||||||
abstract class MhslDataLoader<TResult> extends DataLoader<TResult> {
|
abstract class MhslDataLoader<TResult> extends DataLoader<TResult> {
|
||||||
MhslDataLoader() : super(Dio(BaseOptions(
|
MhslDataLoader() : super(Dio(BaseOptions(
|
||||||
baseUrl: 'https://mhsl.eu/marianum/marianummobile/'
|
baseUrl: 'https://mhsl.eu/marianum/marianummobile/'
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ import 'dart:async';
|
|||||||
import 'package:bloc/bloc.dart';
|
import 'package:bloc/bloc.dart';
|
||||||
import 'package:connectivity_plus/connectivity_plus.dart';
|
import 'package:connectivity_plus/connectivity_plus.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:jiffy/jiffy.dart';
|
||||||
|
|
||||||
import 'loadable_state_event.dart';
|
import 'loadable_state_event.dart';
|
||||||
import 'loadable_state_state.dart';
|
import 'loadable_state_state.dart';
|
||||||
@ -29,7 +30,6 @@ class LoadableStateBloc extends Bloc<LoadableStateEvent, LoadableStateState> {
|
|||||||
bool connectivityStatusKnown() => state.connections != null;
|
bool connectivityStatusKnown() => state.connections != null;
|
||||||
bool isConnected() => !(state.connections?.contains(ConnectivityResult.none) ?? true);
|
bool isConnected() => !(state.connections?.contains(ConnectivityResult.none) ?? true);
|
||||||
bool allowRetry() => reFetch != null;
|
bool allowRetry() => reFetch != null;
|
||||||
bool showErrorMessage() => isConnected() && reFetch != null;
|
|
||||||
|
|
||||||
IconData connectionIcon() => connectivityStatusKnown()
|
IconData connectionIcon() => connectivityStatusKnown()
|
||||||
? isConnected()
|
? isConnected()
|
||||||
@ -37,10 +37,10 @@ class LoadableStateBloc extends Bloc<LoadableStateEvent, LoadableStateState> {
|
|||||||
: Icons.signal_wifi_connected_no_internet_4
|
: Icons.signal_wifi_connected_no_internet_4
|
||||||
: Icons.device_unknown;
|
: Icons.device_unknown;
|
||||||
|
|
||||||
String connectionText() => connectivityStatusKnown()
|
String connectionText({int? lastUpdated}) => connectivityStatusKnown()
|
||||||
? isConnected()
|
? isConnected()
|
||||||
? 'Verbindung fehlgeschlagen'
|
? 'Verbindung fehlgeschlagen'
|
||||||
: 'Offline'
|
: 'Offline${lastUpdated == null ? '' : ' - Stand von ${Jiffy.parseFromMillisecondsSinceEpoch(lastUpdated).fromNow()}'}'
|
||||||
: 'Unbekannte Fehlerursache';
|
: 'Unbekannte Fehlerursache';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -11,6 +11,7 @@ class LoadableState<TState> with _$LoadableState {
|
|||||||
const factory LoadableState({
|
const factory LoadableState({
|
||||||
@Default(true) bool isLoading,
|
@Default(true) bool isLoading,
|
||||||
@Default(null) TState? data,
|
@Default(null) TState? data,
|
||||||
|
@Default(null) int? lastFetch,
|
||||||
@Default(null) void Function()? reFetch,
|
@Default(null) void Function()? reFetch,
|
||||||
@Default(null) LoadingError? error,
|
@Default(null) LoadingError? error,
|
||||||
}) = _LoadableState;
|
}) = _LoadableState;
|
||||||
|
@ -18,6 +18,7 @@ final _privateConstructorUsedError = UnsupportedError(
|
|||||||
mixin _$LoadableState<TState> {
|
mixin _$LoadableState<TState> {
|
||||||
bool get isLoading => throw _privateConstructorUsedError;
|
bool get isLoading => throw _privateConstructorUsedError;
|
||||||
TState? get data => throw _privateConstructorUsedError;
|
TState? get data => throw _privateConstructorUsedError;
|
||||||
|
int? get lastFetch => throw _privateConstructorUsedError;
|
||||||
void Function()? get reFetch => throw _privateConstructorUsedError;
|
void Function()? get reFetch => throw _privateConstructorUsedError;
|
||||||
LoadingError? get error => throw _privateConstructorUsedError;
|
LoadingError? get error => throw _privateConstructorUsedError;
|
||||||
|
|
||||||
@ -35,6 +36,7 @@ abstract class $LoadableStateCopyWith<TState, $Res> {
|
|||||||
$Res call(
|
$Res call(
|
||||||
{bool isLoading,
|
{bool isLoading,
|
||||||
TState? data,
|
TState? data,
|
||||||
|
int? lastFetch,
|
||||||
void Function()? reFetch,
|
void Function()? reFetch,
|
||||||
LoadingError? error});
|
LoadingError? error});
|
||||||
|
|
||||||
@ -57,6 +59,7 @@ class _$LoadableStateCopyWithImpl<TState, $Res,
|
|||||||
$Res call({
|
$Res call({
|
||||||
Object? isLoading = null,
|
Object? isLoading = null,
|
||||||
Object? data = freezed,
|
Object? data = freezed,
|
||||||
|
Object? lastFetch = freezed,
|
||||||
Object? reFetch = freezed,
|
Object? reFetch = freezed,
|
||||||
Object? error = freezed,
|
Object? error = freezed,
|
||||||
}) {
|
}) {
|
||||||
@ -69,6 +72,10 @@ class _$LoadableStateCopyWithImpl<TState, $Res,
|
|||||||
? _value.data
|
? _value.data
|
||||||
: data // ignore: cast_nullable_to_non_nullable
|
: data // ignore: cast_nullable_to_non_nullable
|
||||||
as TState?,
|
as TState?,
|
||||||
|
lastFetch: freezed == lastFetch
|
||||||
|
? _value.lastFetch
|
||||||
|
: lastFetch // ignore: cast_nullable_to_non_nullable
|
||||||
|
as int?,
|
||||||
reFetch: freezed == reFetch
|
reFetch: freezed == reFetch
|
||||||
? _value.reFetch
|
? _value.reFetch
|
||||||
: reFetch // ignore: cast_nullable_to_non_nullable
|
: reFetch // ignore: cast_nullable_to_non_nullable
|
||||||
@ -104,6 +111,7 @@ abstract class _$$LoadableStateImplCopyWith<TState, $Res>
|
|||||||
$Res call(
|
$Res call(
|
||||||
{bool isLoading,
|
{bool isLoading,
|
||||||
TState? data,
|
TState? data,
|
||||||
|
int? lastFetch,
|
||||||
void Function()? reFetch,
|
void Function()? reFetch,
|
||||||
LoadingError? error});
|
LoadingError? error});
|
||||||
|
|
||||||
@ -125,6 +133,7 @@ class __$$LoadableStateImplCopyWithImpl<TState, $Res>
|
|||||||
$Res call({
|
$Res call({
|
||||||
Object? isLoading = null,
|
Object? isLoading = null,
|
||||||
Object? data = freezed,
|
Object? data = freezed,
|
||||||
|
Object? lastFetch = freezed,
|
||||||
Object? reFetch = freezed,
|
Object? reFetch = freezed,
|
||||||
Object? error = freezed,
|
Object? error = freezed,
|
||||||
}) {
|
}) {
|
||||||
@ -137,6 +146,10 @@ class __$$LoadableStateImplCopyWithImpl<TState, $Res>
|
|||||||
? _value.data
|
? _value.data
|
||||||
: data // ignore: cast_nullable_to_non_nullable
|
: data // ignore: cast_nullable_to_non_nullable
|
||||||
as TState?,
|
as TState?,
|
||||||
|
lastFetch: freezed == lastFetch
|
||||||
|
? _value.lastFetch
|
||||||
|
: lastFetch // ignore: cast_nullable_to_non_nullable
|
||||||
|
as int?,
|
||||||
reFetch: freezed == reFetch
|
reFetch: freezed == reFetch
|
||||||
? _value.reFetch
|
? _value.reFetch
|
||||||
: reFetch // ignore: cast_nullable_to_non_nullable
|
: reFetch // ignore: cast_nullable_to_non_nullable
|
||||||
@ -155,6 +168,7 @@ class _$LoadableStateImpl<TState> extends _LoadableState<TState> {
|
|||||||
const _$LoadableStateImpl(
|
const _$LoadableStateImpl(
|
||||||
{this.isLoading = true,
|
{this.isLoading = true,
|
||||||
this.data = null,
|
this.data = null,
|
||||||
|
this.lastFetch = null,
|
||||||
this.reFetch = null,
|
this.reFetch = null,
|
||||||
this.error = null})
|
this.error = null})
|
||||||
: super._();
|
: super._();
|
||||||
@ -167,6 +181,9 @@ class _$LoadableStateImpl<TState> extends _LoadableState<TState> {
|
|||||||
final TState? data;
|
final TState? data;
|
||||||
@override
|
@override
|
||||||
@JsonKey()
|
@JsonKey()
|
||||||
|
final int? lastFetch;
|
||||||
|
@override
|
||||||
|
@JsonKey()
|
||||||
final void Function()? reFetch;
|
final void Function()? reFetch;
|
||||||
@override
|
@override
|
||||||
@JsonKey()
|
@JsonKey()
|
||||||
@ -174,7 +191,7 @@ class _$LoadableStateImpl<TState> extends _LoadableState<TState> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'LoadableState<$TState>(isLoading: $isLoading, data: $data, reFetch: $reFetch, error: $error)';
|
return 'LoadableState<$TState>(isLoading: $isLoading, data: $data, lastFetch: $lastFetch, reFetch: $reFetch, error: $error)';
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -185,13 +202,15 @@ class _$LoadableStateImpl<TState> extends _LoadableState<TState> {
|
|||||||
(identical(other.isLoading, isLoading) ||
|
(identical(other.isLoading, isLoading) ||
|
||||||
other.isLoading == isLoading) &&
|
other.isLoading == isLoading) &&
|
||||||
const DeepCollectionEquality().equals(other.data, data) &&
|
const DeepCollectionEquality().equals(other.data, data) &&
|
||||||
|
(identical(other.lastFetch, lastFetch) ||
|
||||||
|
other.lastFetch == lastFetch) &&
|
||||||
(identical(other.reFetch, reFetch) || other.reFetch == reFetch) &&
|
(identical(other.reFetch, reFetch) || other.reFetch == reFetch) &&
|
||||||
(identical(other.error, error) || other.error == error));
|
(identical(other.error, error) || other.error == error));
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(runtimeType, isLoading,
|
int get hashCode => Object.hash(runtimeType, isLoading,
|
||||||
const DeepCollectionEquality().hash(data), reFetch, error);
|
const DeepCollectionEquality().hash(data), lastFetch, reFetch, error);
|
||||||
|
|
||||||
@JsonKey(ignore: true)
|
@JsonKey(ignore: true)
|
||||||
@override
|
@override
|
||||||
@ -205,6 +224,7 @@ abstract class _LoadableState<TState> extends LoadableState<TState> {
|
|||||||
const factory _LoadableState(
|
const factory _LoadableState(
|
||||||
{final bool isLoading,
|
{final bool isLoading,
|
||||||
final TState? data,
|
final TState? data,
|
||||||
|
final int? lastFetch,
|
||||||
final void Function()? reFetch,
|
final void Function()? reFetch,
|
||||||
final LoadingError? error}) = _$LoadableStateImpl<TState>;
|
final LoadingError? error}) = _$LoadableStateImpl<TState>;
|
||||||
const _LoadableState._() : super._();
|
const _LoadableState._() : super._();
|
||||||
@ -214,6 +234,8 @@ abstract class _LoadableState<TState> extends LoadableState<TState> {
|
|||||||
@override
|
@override
|
||||||
TState? get data;
|
TState? get data;
|
||||||
@override
|
@override
|
||||||
|
int? get lastFetch;
|
||||||
|
@override
|
||||||
void Function()? get reFetch;
|
void Function()? get reFetch;
|
||||||
@override
|
@override
|
||||||
LoadingError? get error;
|
LoadingError? get error;
|
||||||
|
@ -53,13 +53,13 @@ class LoadableStateConsumer<TController extends Bloc<LoadableHydratedBlocEvent<T
|
|||||||
bloc.reFetch = loadableState.reFetch;
|
bloc.reFetch = loadableState.reFetch;
|
||||||
return Column(
|
return Column(
|
||||||
children: [
|
children: [
|
||||||
LoadableStateErrorBar(visible: loadableState.showErrorBar()),
|
LoadableStateErrorBar(visible: loadableState.showErrorBar(), message: loadableState.error?.message, lastUpdated: loadableState.lastFetch),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Stack(
|
child: Stack(
|
||||||
children: [
|
children: [
|
||||||
LoadableStatePrimaryLoading(visible: loadableState.showPrimaryLoading()),
|
LoadableStatePrimaryLoading(visible: loadableState.showPrimaryLoading()),
|
||||||
LoadableStateBackgroundLoading(visible: loadableState.showBackgroundLoading()),
|
LoadableStateBackgroundLoading(visible: loadableState.showBackgroundLoading()),
|
||||||
LoadableStateErrorScreen(visible: loadableState.showError()),
|
LoadableStateErrorScreen(visible: loadableState.showError(), message: loadableState.error?.message),
|
||||||
|
|
||||||
AnimatedOpacity(
|
AnimatedOpacity(
|
||||||
opacity: loadableState.showContent() ? 1.0 : 0.0,
|
opacity: loadableState.showContent() ? 1.0 : 0.0,
|
||||||
|
@ -1,11 +1,14 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
|
import '../../../../../widget/infoDialog.dart';
|
||||||
import '../bloc/loadable_state_bloc.dart';
|
import '../bloc/loadable_state_bloc.dart';
|
||||||
|
|
||||||
class LoadableStateErrorBar extends StatelessWidget {
|
class LoadableStateErrorBar extends StatelessWidget {
|
||||||
final bool visible;
|
final bool visible;
|
||||||
const LoadableStateErrorBar({required this.visible, super.key});
|
final String? message;
|
||||||
|
final int? lastUpdated;
|
||||||
|
const LoadableStateErrorBar({required this.visible, this.message, this.lastUpdated, super.key});
|
||||||
|
|
||||||
final Duration animationDuration = const Duration(milliseconds: 200);
|
final Duration animationDuration = const Duration(milliseconds: 200);
|
||||||
|
|
||||||
@ -29,25 +32,31 @@ class LoadableStateErrorBar extends StatelessWidget {
|
|||||||
builder: (context) {
|
builder: (context) {
|
||||||
var bloc = context.watch<LoadableStateBloc>();
|
var bloc = context.watch<LoadableStateBloc>();
|
||||||
var status = (
|
var status = (
|
||||||
icon: bloc.connectionIcon(),
|
icon: bloc.connectionIcon(),
|
||||||
text: bloc.connectionText(),
|
text: bloc.connectionText(lastUpdated: lastUpdated),
|
||||||
color: bloc.connectivityStatusKnown() && !bloc.isConnected()
|
color: bloc.connectivityStatusKnown() && !bloc.isConnected()
|
||||||
? Colors.grey.shade600
|
? Colors.grey.shade600
|
||||||
: Theme.of(context).primaryColor
|
: Theme.of(context).primaryColor
|
||||||
);
|
);
|
||||||
|
|
||||||
return Container(
|
return InkWell(
|
||||||
height: 20,
|
onTap: () {
|
||||||
decoration: BoxDecoration(
|
if(!bloc.isConnected()) return;
|
||||||
color: status.color,
|
InfoDialog.show(context, 'Exception: ${message.toString()}');
|
||||||
),
|
},
|
||||||
child: Row(
|
child: Container(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
height: 20,
|
||||||
children: [
|
decoration: BoxDecoration(
|
||||||
Icon(status.icon, size: 14),
|
color: status.color,
|
||||||
const SizedBox(width: 10),
|
),
|
||||||
Text(status.text, style: const TextStyle(fontSize: 12))
|
child: Row(
|
||||||
],
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Icon(status.icon, size: 14),
|
||||||
|
const SizedBox(width: 10),
|
||||||
|
Text(status.text, style: const TextStyle(fontSize: 12))
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
@ -6,7 +6,8 @@ import 'loadable_state_consumer.dart';
|
|||||||
|
|
||||||
class LoadableStateErrorScreen extends StatelessWidget {
|
class LoadableStateErrorScreen extends StatelessWidget {
|
||||||
final bool visible;
|
final bool visible;
|
||||||
const LoadableStateErrorScreen({required this.visible, super.key});
|
final String? message;
|
||||||
|
const LoadableStateErrorScreen({required this.visible, this.message, super.key});
|
||||||
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -28,11 +29,19 @@ class LoadableStateErrorScreen extends StatelessWidget {
|
|||||||
if(bloc.allowRetry()) ...[
|
if(bloc.allowRetry()) ...[
|
||||||
const SizedBox(height: 10),
|
const SizedBox(height: 10),
|
||||||
TextButton(onPressed: () => bloc.reFetch!(), child: const Text('Erneut versuschen')),
|
TextButton(onPressed: () => bloc.reFetch!(), child: const Text('Erneut versuschen')),
|
||||||
],
|
|
||||||
|
|
||||||
if(bloc.showErrorMessage()) ...[
|
|
||||||
const SizedBox(height: 40),
|
const SizedBox(height: 40),
|
||||||
Text("bloc.loadingError!.message", style: TextStyle(color: Theme.of(context).hintColor, fontSize: 12))
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 20),
|
||||||
|
child: Text(
|
||||||
|
message ?? 'Task failed successfully :)',
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(context).hintColor,
|
||||||
|
fontSize: 12
|
||||||
|
),
|
||||||
|
maxLines: 10,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
@ -6,6 +6,7 @@ import '../../loadableState/loading_error.dart';
|
|||||||
import '../../repository/repository.dart';
|
import '../../repository/repository.dart';
|
||||||
import 'loadable_hydrated_bloc_event.dart';
|
import 'loadable_hydrated_bloc_event.dart';
|
||||||
import '../../loadableState/loadable_state.dart';
|
import '../../loadableState/loadable_state.dart';
|
||||||
|
import 'loadable_save_context.dart';
|
||||||
|
|
||||||
abstract class LoadableHydratedBloc<
|
abstract class LoadableHydratedBloc<
|
||||||
TEvent extends LoadableHydratedBlocEvent<TState>,
|
TEvent extends LoadableHydratedBlocEvent<TState>,
|
||||||
@ -17,10 +18,29 @@ abstract class LoadableHydratedBloc<
|
|||||||
> {
|
> {
|
||||||
late TRepository _repository;
|
late TRepository _repository;
|
||||||
LoadableHydratedBloc() : super(const LoadableState()) {
|
LoadableHydratedBloc() : super(const LoadableState()) {
|
||||||
on<Emit<TState>>((event, emit) => emit(LoadableState(isLoading: event.loading, data: event.state(innerState ?? fromNothing()), reFetch: retry)));
|
|
||||||
on<RefetchStarted<TState>>((event, emit) => emit(LoadableState(isLoading: true, data: innerState)));
|
on<Emit<TState>>((event, emit) => emit(LoadableState(
|
||||||
|
isLoading: event.loading,
|
||||||
|
data: event.state(innerState ?? fromNothing()),
|
||||||
|
lastFetch: DateTime.now().millisecondsSinceEpoch,
|
||||||
|
reFetch: retry
|
||||||
|
)));
|
||||||
|
|
||||||
|
on<RefetchStarted<TState>>((event, emit) => emit(LoadableState(
|
||||||
|
isLoading: true,
|
||||||
|
data: innerState,
|
||||||
|
lastFetch: state.lastFetch
|
||||||
|
)));
|
||||||
|
|
||||||
on<ClearState<TState>>((event, emit) => emit(const LoadableState()));
|
on<ClearState<TState>>((event, emit) => emit(const LoadableState()));
|
||||||
on<Error<TState>>((event, emit) => emit(LoadableState(isLoading: false, data: innerState, reFetch: retry, error: event.error)));
|
|
||||||
|
on<Error<TState>>((event, emit) => emit(LoadableState(
|
||||||
|
isLoading: false,
|
||||||
|
data: innerState,
|
||||||
|
lastFetch: state.lastFetch,
|
||||||
|
reFetch: retry,
|
||||||
|
error: event.error
|
||||||
|
)));
|
||||||
|
|
||||||
_repository = repository();
|
_repository = repository();
|
||||||
fetch();
|
fetch();
|
||||||
@ -41,19 +61,26 @@ abstract class LoadableHydratedBloc<
|
|||||||
(e) {
|
(e) {
|
||||||
log('Error while fetching ${TState.toString()}: ${e.toString()}');
|
log('Error while fetching ${TState.toString()}: ${e.toString()}');
|
||||||
add(Error(LoadingError(
|
add(Error(LoadingError(
|
||||||
message: e.toString(),
|
message: e.message,
|
||||||
allowRetry: true,
|
allowRetry: true,
|
||||||
)));
|
)));
|
||||||
}
|
},
|
||||||
).then((value) {
|
).then((value) {
|
||||||
log('Fetch for ${TState.toString()} completed!');
|
log('Fetch for ${TState.toString()} completed!');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
fromJson(Map<String, dynamic> json) => LoadableState(isLoading: true, data: fromStorage(json));
|
fromJson(Map<String, dynamic> json) {
|
||||||
|
var rawData = LoadableSaveContext.unwrap(json);
|
||||||
|
return LoadableState(isLoading: true, lastFetch: rawData.meta.timestamp, data: fromStorage(rawData.data));
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Map<String, dynamic>? toJson(LoadableState<TState> state) => state.data == null ? {} : state.data.toJson();
|
Map<String, dynamic>? toJson(LoadableState<TState> state) => LoadableSaveContext.wrap(
|
||||||
|
toStorage(state.data),
|
||||||
|
state.lastFetch ?? DateTime.now().millisecondsSinceEpoch
|
||||||
|
);
|
||||||
|
|
||||||
Future<void> gatherData();
|
Future<void> gatherData();
|
||||||
TRepository repository();
|
TRepository repository();
|
||||||
|
@ -0,0 +1,24 @@
|
|||||||
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
|
|
||||||
|
part 'loadable_save_context.freezed.dart';
|
||||||
|
part 'loadable_save_context.g.dart';
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
class LoadableSaveContext with _$LoadableSaveContext {
|
||||||
|
const LoadableSaveContext._();
|
||||||
|
const factory LoadableSaveContext({
|
||||||
|
required int timestamp,
|
||||||
|
}) = _LoadableSaveContext;
|
||||||
|
|
||||||
|
factory LoadableSaveContext.fromJson(Map<String, dynamic> json) => _$LoadableSaveContextFromJson(json);
|
||||||
|
|
||||||
|
static String dataKey = 'data';
|
||||||
|
static String metaKey = 'meta';
|
||||||
|
|
||||||
|
static Map<String, dynamic> wrap(Map<String, dynamic>? data, int lastFetch) =>
|
||||||
|
{dataKey: data, metaKey: LoadableSaveContext(timestamp: lastFetch).toJson()};
|
||||||
|
|
||||||
|
static ({Map<String, dynamic> data, LoadableSaveContext meta}) unwrap(Map<String, dynamic> data) =>
|
||||||
|
(data: data[dataKey] as Map<String, dynamic>, meta: LoadableSaveContext.fromJson(data[metaKey]));
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,155 @@
|
|||||||
|
// 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 'loadable_save_context.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');
|
||||||
|
|
||||||
|
LoadableSaveContext _$LoadableSaveContextFromJson(Map<String, dynamic> json) {
|
||||||
|
return _LoadableSaveContext.fromJson(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
mixin _$LoadableSaveContext {
|
||||||
|
int get timestamp => throw _privateConstructorUsedError;
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||||
|
@JsonKey(ignore: true)
|
||||||
|
$LoadableSaveContextCopyWith<LoadableSaveContext> get copyWith =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class $LoadableSaveContextCopyWith<$Res> {
|
||||||
|
factory $LoadableSaveContextCopyWith(
|
||||||
|
LoadableSaveContext value, $Res Function(LoadableSaveContext) then) =
|
||||||
|
_$LoadableSaveContextCopyWithImpl<$Res, LoadableSaveContext>;
|
||||||
|
@useResult
|
||||||
|
$Res call({int timestamp});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class _$LoadableSaveContextCopyWithImpl<$Res, $Val extends LoadableSaveContext>
|
||||||
|
implements $LoadableSaveContextCopyWith<$Res> {
|
||||||
|
_$LoadableSaveContextCopyWithImpl(this._value, this._then);
|
||||||
|
|
||||||
|
// ignore: unused_field
|
||||||
|
final $Val _value;
|
||||||
|
// ignore: unused_field
|
||||||
|
final $Res Function($Val) _then;
|
||||||
|
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
@override
|
||||||
|
$Res call({
|
||||||
|
Object? timestamp = null,
|
||||||
|
}) {
|
||||||
|
return _then(_value.copyWith(
|
||||||
|
timestamp: null == timestamp
|
||||||
|
? _value.timestamp
|
||||||
|
: timestamp // ignore: cast_nullable_to_non_nullable
|
||||||
|
as int,
|
||||||
|
) as $Val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class _$$LoadableSaveContextImplCopyWith<$Res>
|
||||||
|
implements $LoadableSaveContextCopyWith<$Res> {
|
||||||
|
factory _$$LoadableSaveContextImplCopyWith(_$LoadableSaveContextImpl value,
|
||||||
|
$Res Function(_$LoadableSaveContextImpl) then) =
|
||||||
|
__$$LoadableSaveContextImplCopyWithImpl<$Res>;
|
||||||
|
@override
|
||||||
|
@useResult
|
||||||
|
$Res call({int timestamp});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class __$$LoadableSaveContextImplCopyWithImpl<$Res>
|
||||||
|
extends _$LoadableSaveContextCopyWithImpl<$Res, _$LoadableSaveContextImpl>
|
||||||
|
implements _$$LoadableSaveContextImplCopyWith<$Res> {
|
||||||
|
__$$LoadableSaveContextImplCopyWithImpl(_$LoadableSaveContextImpl _value,
|
||||||
|
$Res Function(_$LoadableSaveContextImpl) _then)
|
||||||
|
: super(_value, _then);
|
||||||
|
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
@override
|
||||||
|
$Res call({
|
||||||
|
Object? timestamp = null,
|
||||||
|
}) {
|
||||||
|
return _then(_$LoadableSaveContextImpl(
|
||||||
|
timestamp: null == timestamp
|
||||||
|
? _value.timestamp
|
||||||
|
: timestamp // ignore: cast_nullable_to_non_nullable
|
||||||
|
as int,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
@JsonSerializable()
|
||||||
|
class _$LoadableSaveContextImpl extends _LoadableSaveContext {
|
||||||
|
const _$LoadableSaveContextImpl({required this.timestamp}) : super._();
|
||||||
|
|
||||||
|
factory _$LoadableSaveContextImpl.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$$LoadableSaveContextImplFromJson(json);
|
||||||
|
|
||||||
|
@override
|
||||||
|
final int timestamp;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'LoadableSaveContext(timestamp: $timestamp)';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) ||
|
||||||
|
(other.runtimeType == runtimeType &&
|
||||||
|
other is _$LoadableSaveContextImpl &&
|
||||||
|
(identical(other.timestamp, timestamp) ||
|
||||||
|
other.timestamp == timestamp));
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonKey(ignore: true)
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(runtimeType, timestamp);
|
||||||
|
|
||||||
|
@JsonKey(ignore: true)
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
_$$LoadableSaveContextImplCopyWith<_$LoadableSaveContextImpl> get copyWith =>
|
||||||
|
__$$LoadableSaveContextImplCopyWithImpl<_$LoadableSaveContextImpl>(
|
||||||
|
this, _$identity);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
return _$$LoadableSaveContextImplToJson(
|
||||||
|
this,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class _LoadableSaveContext extends LoadableSaveContext {
|
||||||
|
const factory _LoadableSaveContext({required final int timestamp}) =
|
||||||
|
_$LoadableSaveContextImpl;
|
||||||
|
const _LoadableSaveContext._() : super._();
|
||||||
|
|
||||||
|
factory _LoadableSaveContext.fromJson(Map<String, dynamic> json) =
|
||||||
|
_$LoadableSaveContextImpl.fromJson;
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get timestamp;
|
||||||
|
@override
|
||||||
|
@JsonKey(ignore: true)
|
||||||
|
_$$LoadableSaveContextImplCopyWith<_$LoadableSaveContextImpl> get copyWith =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'loadable_save_context.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// JsonSerializableGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
_$LoadableSaveContextImpl _$$LoadableSaveContextImplFromJson(
|
||||||
|
Map<String, dynamic> json) =>
|
||||||
|
_$LoadableSaveContextImpl(
|
||||||
|
timestamp: json['timestamp'] as int,
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> _$$LoadableSaveContextImplToJson(
|
||||||
|
_$LoadableSaveContextImpl instance) =>
|
||||||
|
<String, dynamic>{
|
||||||
|
'timestamp': instance.timestamp,
|
||||||
|
};
|
@ -72,10 +72,6 @@ class Overhang extends StatelessWidget {
|
|||||||
trailing: const Icon(Icons.arrow_right),
|
trailing: const Icon(Icons.arrow_right),
|
||||||
onTap: () => pushScreen(context, withNavBar: false, screen: const FeedbackDialog()),
|
onTap: () => pushScreen(context, withNavBar: false, screen: const FeedbackDialog()),
|
||||||
),
|
),
|
||||||
const ListTile(
|
|
||||||
leading: Icon(Icons.science_outlined),
|
|
||||||
// onTap: () => pushScreen(context, withNavBar: false, screen: const GradeAveragesScreen()),
|
|
||||||
)
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user