✨ Tour and introduce
This commit is contained in:
68
lib/services/tour.dart
Normal file
68
lib/services/tour.dart
Normal file
@ -0,0 +1,68 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
import 'package:island/pods/config.dart';
|
||||
import 'package:island/widgets/tour/techincal_review_intro.dart';
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
|
||||
part 'tour.g.dart';
|
||||
part 'tour.freezed.dart';
|
||||
|
||||
const kAppTourStatusKey = "app_tour_statuses";
|
||||
|
||||
const List<Tour> kAllTours = [
|
||||
Tour(id: 'technical_review_intro', isStartup: true),
|
||||
];
|
||||
|
||||
@freezed
|
||||
abstract class Tour with _$Tour {
|
||||
const Tour._();
|
||||
|
||||
const factory Tour({required String id, required bool isStartup}) = _Tour;
|
||||
|
||||
Widget get widget => switch (id) {
|
||||
'technical_review_intro' => const TechicalReviewIntroWidget(),
|
||||
_ => throw UnimplementedError(),
|
||||
};
|
||||
}
|
||||
|
||||
@riverpod
|
||||
class TourStatusNotifier extends _$TourStatusNotifier {
|
||||
@override
|
||||
Map<String, bool> build() {
|
||||
final prefs = ref.watch(sharedPreferencesProvider);
|
||||
final storedJson = prefs.getString(kAppTourStatusKey);
|
||||
if (storedJson != null) {
|
||||
try {
|
||||
final Map<String, dynamic> stored = jsonDecode(storedJson);
|
||||
return Map<String, bool>.from(stored);
|
||||
} catch (_) {
|
||||
return {for (final id in kAllTours.map((e) => e.id)) id: false};
|
||||
}
|
||||
}
|
||||
return {for (final id in kAllTours.map((e) => e.id)) id: false};
|
||||
}
|
||||
|
||||
bool isTourShown(String tourId) => state[tourId] ?? false;
|
||||
|
||||
Future<void> _saveState(Map<String, bool> newState) async {
|
||||
state = newState;
|
||||
final prefs = ref.read(sharedPreferencesProvider);
|
||||
await prefs.setString(kAppTourStatusKey, jsonEncode(newState));
|
||||
}
|
||||
|
||||
Future<Widget?> showTour(String tourId) async {
|
||||
if (!isTourShown(tourId) || true) {
|
||||
final newState = {...state, tourId: true};
|
||||
await _saveState(newState);
|
||||
return kAllTours.firstWhere((e) => e.id == tourId).widget;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
Future<void> resetTours() async {
|
||||
final newState = {for (final id in kAllTours.map((e) => e.id)) id: false};
|
||||
await _saveState(newState);
|
||||
}
|
||||
}
|
145
lib/services/tour.freezed.dart
Normal file
145
lib/services/tour.freezed.dart
Normal file
@ -0,0 +1,145 @@
|
||||
// dart format width=80
|
||||
// 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 'tour.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// FreezedGenerator
|
||||
// **************************************************************************
|
||||
|
||||
// dart format off
|
||||
T _$identity<T>(T value) => value;
|
||||
/// @nodoc
|
||||
mixin _$Tour {
|
||||
|
||||
String get id; bool get isStartup;
|
||||
/// Create a copy of Tour
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
$TourCopyWith<Tour> get copyWith => _$TourCopyWithImpl<Tour>(this as Tour, _$identity);
|
||||
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is Tour&&(identical(other.id, id) || other.id == id)&&(identical(other.isStartup, isStartup) || other.isStartup == isStartup));
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,id,isStartup);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'Tour(id: $id, isStartup: $isStartup)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class $TourCopyWith<$Res> {
|
||||
factory $TourCopyWith(Tour value, $Res Function(Tour) _then) = _$TourCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
String id, bool isStartup
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class _$TourCopyWithImpl<$Res>
|
||||
implements $TourCopyWith<$Res> {
|
||||
_$TourCopyWithImpl(this._self, this._then);
|
||||
|
||||
final Tour _self;
|
||||
final $Res Function(Tour) _then;
|
||||
|
||||
/// Create a copy of Tour
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? isStartup = null,}) {
|
||||
return _then(_self.copyWith(
|
||||
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||
as String,isStartup: null == isStartup ? _self.isStartup : isStartup // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// @nodoc
|
||||
|
||||
|
||||
class _Tour extends Tour {
|
||||
const _Tour({required this.id, required this.isStartup}): super._();
|
||||
|
||||
|
||||
@override final String id;
|
||||
@override final bool isStartup;
|
||||
|
||||
/// Create a copy of Tour
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
_$TourCopyWith<_Tour> get copyWith => __$TourCopyWithImpl<_Tour>(this, _$identity);
|
||||
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _Tour&&(identical(other.id, id) || other.id == id)&&(identical(other.isStartup, isStartup) || other.isStartup == isStartup));
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,id,isStartup);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'Tour(id: $id, isStartup: $isStartup)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class _$TourCopyWith<$Res> implements $TourCopyWith<$Res> {
|
||||
factory _$TourCopyWith(_Tour value, $Res Function(_Tour) _then) = __$TourCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
String id, bool isStartup
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class __$TourCopyWithImpl<$Res>
|
||||
implements _$TourCopyWith<$Res> {
|
||||
__$TourCopyWithImpl(this._self, this._then);
|
||||
|
||||
final _Tour _self;
|
||||
final $Res Function(_Tour) _then;
|
||||
|
||||
/// Create a copy of Tour
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? isStartup = null,}) {
|
||||
return _then(_Tour(
|
||||
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||
as String,isStartup: null == isStartup ? _self.isStartup : isStartup // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// dart format on
|
28
lib/services/tour.g.dart
Normal file
28
lib/services/tour.g.dart
Normal file
@ -0,0 +1,28 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'tour.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
String _$tourStatusNotifierHash() =>
|
||||
r'040aac2d7cf6d14e539c1b04cf311421ee133ed3';
|
||||
|
||||
/// See also [TourStatusNotifier].
|
||||
@ProviderFor(TourStatusNotifier)
|
||||
final tourStatusNotifierProvider =
|
||||
AutoDisposeNotifierProvider<TourStatusNotifier, Map<String, bool>>.internal(
|
||||
TourStatusNotifier.new,
|
||||
name: r'tourStatusNotifierProvider',
|
||||
debugGetCreateSourceHash:
|
||||
const bool.fromEnvironment('dart.vm.product')
|
||||
? null
|
||||
: _$tourStatusNotifierHash,
|
||||
dependencies: null,
|
||||
allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
typedef _$TourStatusNotifier = AutoDisposeNotifier<Map<String, bool>>;
|
||||
// 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
|
Reference in New Issue
Block a user