Use Hive instead of SharedPrefrerences to save preferences

This commit is contained in:
Erfan Rahmati
2022-07-04 05:01:59 +04:30
parent bb53d9eb08
commit fbf55da924
19 changed files with 496 additions and 171 deletions

View File

@ -1,11 +1,32 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:hive_flutter/adapters.dart';
import 'package:movielab/models/hive/hive_helper/register_adapters.dart';
import 'package:movielab/modules/cache/cache_data.dart';
import 'package:movielab/pages/main/main_page.dart';
import 'package:movielab/pages/splash/splash_screen.dart';
import 'constants/colors.dart';
import 'constants/routes.dart';
import 'models/hive/models/show_preview.dart';
import 'pages/main/home/home_data_controller.dart';
import 'pages/main/main_controller.dart';
import 'pages/main/search/search_bar/search_bar_controller.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
// Initialize Hive and Hive Flutter
await Hive.initFlutter();
registerAdapters();
Hive.openBox<HiveShowPreview>('bookmarks');
// Initialize the controllers
Get.put(MainController());
Get.put(HomeDataController());
Get.put(SearchBarController());
Get.put(CacheData());
void main() {
runApp(const App());
}

35
lib/models/convertor.dart Normal file
View File

@ -0,0 +1,35 @@
import 'show_models/full_show_model.dart';
import 'show_models/show_preview_model.dart';
Future<ShowPreview> convertFullShowToShowPreview(
FullShow fullShow, String rank) async {
String crew = "";
await getShowCrew(fullShow: fullShow).then((value) => crew = value);
return ShowPreview(
id: fullShow.id,
rank: rank,
title: fullShow.title,
crew: crew,
image: fullShow.image,
year: fullShow.year,
imDbRating: fullShow.imDbRating,
weekend: fullShow.weekend,
gross: fullShow.gross,
weeks: fullShow.weeks,
worldwideLifetimeGross: fullShow.worldwideLifetimeGross,
domestic: fullShow.domestic,
domesticLifetimeGross: fullShow.domesticLifetimeGross,
foreign: fullShow.foreign,
foreignLifetimeGross: fullShow.foreignLifetimeGross,
);
}
Future<String> getShowCrew({required FullShow fullShow}) async {
List<String> crewList = [];
String crew = "";
for (int i = 0; i < 3; i++) {
crewList.add(fullShow.actorList[i].name);
}
crew = crewList.join(", ");
return crew;
}

View File

@ -0,0 +1,75 @@
import 'package:movielab/models/hive/models/show_preview.dart';
import 'package:movielab/models/show_models/show_preview_model.dart';
import '../show_models/full_show_model.dart';
ShowPreview convertHiveToShowPreview(HiveShowPreview hive) {
return ShowPreview(
id: hive.id,
rank: hive.rank,
title: hive.title,
crew: hive.crew,
image: hive.image,
year: hive.year,
imDbRating: hive.imDbRating,
weekend: hive.weekend,
gross: hive.gross,
weeks: hive.weeks,
worldwideLifetimeGross: hive.worldwideLifetimeGross,
domestic: hive.domestic,
domesticLifetimeGross: hive.domesticLifetimeGross,
foreign: hive.foreign,
foreignLifetimeGross: hive.foreignLifetimeGross,
);
}
HiveShowPreview convertShowPreviewToHive(ShowPreview showPreview) {
return HiveShowPreview()
..id = showPreview.id
..rank = showPreview.rank
..title = showPreview.title
..crew = showPreview.crew
..image = showPreview.image
..year = showPreview.year
..imDbRating = showPreview.imDbRating
..weekend = showPreview.weekend
..gross = showPreview.gross
..weeks = showPreview.weeks
..worldwideLifetimeGross = showPreview.worldwideLifetimeGross
..domestic = showPreview.domestic
..domesticLifetimeGross = showPreview.domesticLifetimeGross
..foreign = showPreview.foreign
..foreignLifetimeGross = showPreview.foreignLifetimeGross;
}
Future<HiveShowPreview> convertFullShowToHive(
FullShow fullShow, String rank) async {
String crew = "";
await getShowCrew(fullShow: fullShow).then((value) => crew = value);
return HiveShowPreview()
..id = fullShow.id
..rank = rank
..title = fullShow.title
..crew = crew
..image = fullShow.image
..year = fullShow.year
..imDbRating = fullShow.imDbRating
..weekend = fullShow.weekend
..gross = fullShow.gross
..weeks = fullShow.weeks
..worldwideLifetimeGross = fullShow.worldwideLifetimeGross
..domestic = fullShow.domestic
..domesticLifetimeGross = fullShow.domesticLifetimeGross
..foreign = fullShow.foreign
..foreignLifetimeGross = fullShow.foreignLifetimeGross;
}
Future<String> getShowCrew({required FullShow fullShow}) async {
List<String> crewList = [];
String crew = "";
for (int i = 0; i < 3; i++) {
crewList.add(fullShow.actorList[i].name);
}
crew = crewList.join(", ");
return crew;
}

View File

@ -0,0 +1,17 @@
class ShowPreviewFields {
static const int id = 0;
static const int rank = 1;
static const int title = 2;
static const int crew = 3;
static const int image = 4;
static const int year = 5;
static const int imDbRating = 6;
static const int weekend = 7;
static const int gross = 8;
static const int weeks = 9;
static const int worldwideLifetimeGross = 10;
static const int domesticLifetimeGross = 11;
static const int domestic = 12;
static const int foreignLifetimeGross = 13;
static const int foreign = 14;
}

View File

@ -0,0 +1,5 @@
class HiveAdapters {
static const String searchResult = 'SearchResultAdapter';
static const String showPreview = 'ShowPreviewAdapter';
static const String preferencesShareholder = 'PreferencesShareholderAdapter';
}

View File

@ -0,0 +1,5 @@
class HiveTypes {
static const int searchResult = 0;
static const int showPreview = 1;
static const int preferencesShareholder = 2;
}

View File

@ -0,0 +1,6 @@
import 'package:hive/hive.dart';
import '../models/show_preview.dart';
void registerAdapters() {
Hive.registerAdapter(HiveShowPreviewAdapter());
}

View File

@ -0,0 +1,40 @@
import 'package:hive/hive.dart';
import '../hive_helper/fields/show_preview_fields.dart';
import '../hive_helper/hive_adapters.dart';
import '../hive_helper/hive_types.dart';
part 'show_preview.g.dart';
@HiveType(typeId: HiveTypes.showPreview, adapterName: HiveAdapters.showPreview)
class HiveShowPreview extends HiveObject {
@HiveField(ShowPreviewFields.id)
late String id;
@HiveField(ShowPreviewFields.rank)
late String rank;
@HiveField(ShowPreviewFields.title)
late String title;
@HiveField(ShowPreviewFields.crew)
late String crew;
@HiveField(ShowPreviewFields.image)
late String image;
@HiveField(ShowPreviewFields.year)
late String year;
@HiveField(ShowPreviewFields.imDbRating)
late String imDbRating;
@HiveField(ShowPreviewFields.weekend)
late String weekend;
@HiveField(ShowPreviewFields.gross)
late String gross;
@HiveField(ShowPreviewFields.weeks)
late String weeks;
@HiveField(ShowPreviewFields.worldwideLifetimeGross)
late String worldwideLifetimeGross;
@HiveField(ShowPreviewFields.domesticLifetimeGross)
late String domesticLifetimeGross;
@HiveField(ShowPreviewFields.domestic)
late String domestic;
@HiveField(ShowPreviewFields.foreignLifetimeGross)
late String foreignLifetimeGross;
@HiveField(ShowPreviewFields.foreign)
late String foreign;
}

View File

@ -0,0 +1,82 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'show_preview.dart';
// **************************************************************************
// TypeAdapterGenerator
// **************************************************************************
class HiveShowPreviewAdapter extends TypeAdapter<HiveShowPreview> {
@override
final int typeId = 1;
@override
HiveShowPreview read(BinaryReader reader) {
final numOfFields = reader.readByte();
final fields = <int, dynamic>{
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
};
return HiveShowPreview()
..id = fields[0] as String
..rank = fields[1] as String
..title = fields[2] as String
..crew = fields[3] as String
..image = fields[4] as String
..year = fields[5] as String
..imDbRating = fields[6] as String
..weekend = fields[7] as String
..gross = fields[8] as String
..weeks = fields[9] as String
..worldwideLifetimeGross = fields[10] as String
..domesticLifetimeGross = fields[11] as String
..domestic = fields[12] as String
..foreignLifetimeGross = fields[13] as String
..foreign = fields[14] as String;
}
@override
void write(BinaryWriter writer, HiveShowPreview obj) {
writer
..writeByte(15)
..writeByte(0)
..write(obj.id)
..writeByte(1)
..write(obj.rank)
..writeByte(2)
..write(obj.title)
..writeByte(3)
..write(obj.crew)
..writeByte(4)
..write(obj.image)
..writeByte(5)
..write(obj.year)
..writeByte(6)
..write(obj.imDbRating)
..writeByte(7)
..write(obj.weekend)
..writeByte(8)
..write(obj.gross)
..writeByte(9)
..write(obj.weeks)
..writeByte(10)
..write(obj.worldwideLifetimeGross)
..writeByte(11)
..write(obj.domesticLifetimeGross)
..writeByte(12)
..write(obj.domestic)
..writeByte(13)
..write(obj.foreignLifetimeGross)
..writeByte(14)
..write(obj.foreign);
}
@override
int get hashCode => typeId.hashCode;
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is HiveShowPreviewAdapter &&
runtimeType == other.runtimeType &&
typeId == other.typeId;
}

View File

@ -1,29 +1,13 @@
import 'package:flutter/foundation.dart';
import 'package:get/get.dart';
import 'package:movielab/pages/main/bookmarks/bookmarks_controller.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:hive_flutter/adapters.dart';
import '../models/hive/convertor.dart';
import '../models/hive/models/show_preview.dart';
import '../models/show_models/full_show_model.dart';
import '../models/show_models/show_preview_model.dart';
class PreferencesShareholder {
// Get all bookmarks from the shared preferences
Future<bool> getBookmarks() async {
final SharedPreferences prefs = await SharedPreferences.getInstance();
final bookmarksString = prefs.getString('bookmarks');
List<ShowPreview> bookmarks = [];
if (bookmarksString != null) {
bookmarks = ShowPreview.decode(bookmarksString);
}
Get.find<BookmarksPageController>()
.updateBookmarksList(bookmarks: bookmarks);
return true;
}
// Delete all bookmarks from the shared preferences
Future<bool> deleteBookmarks() async {
final SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.remove('bookmarks');
Get.find<BookmarksPageController>().updateBookmarksList(bookmarks: []);
Hive.deleteBoxFromDisk("bookmarks");
if (kDebugMode) {
print("All bookmarks deleted");
}
@ -32,106 +16,45 @@ class PreferencesShareholder {
// Add a movie to the bookmarks list in the shared preferences
Future<bool> addBookmark({required FullShow fullShow}) async {
final SharedPreferences prefs = await SharedPreferences.getInstance();
final bookmarksJson = prefs.getString("bookmarks");
List<ShowPreview> bookmarks = [];
if (bookmarksJson != null) {
bookmarks = ShowPreview.decode(bookmarksJson);
}
String showCrew = "";
await getShowCrew(fullShow: fullShow).then((value) => showCrew = value);
// Type "FullShow" is not a subtype of "Show", so we have to convert it to "Show"
ShowPreview show = ShowPreview(
id: fullShow.id,
rank: (bookmarks.length + 1).toString(),
title: fullShow.title,
crew: showCrew,
image: fullShow.image.toString().replaceAll(
"._V1_UX128_CR0,3,128,176_AL_.jpg", "._V1_Ratio0.6716_AL_.jpg"),
year: fullShow.year,
imDbRating: fullShow.imDbRating,
weekend: fullShow.weekend,
gross: fullShow.gross,
weeks: fullShow.weeks,
worldwideLifetimeGross: fullShow.worldwideLifetimeGross,
domestic: fullShow.domestic,
domesticLifetimeGross: fullShow.domesticLifetimeGross,
foreign: fullShow.foreign,
foreignLifetimeGross: fullShow.foreignLifetimeGross,
);
bookmarks.add(show);
// Encode the bookmarks to json, so it can be stored in SharedPreferences
final String encodedData = ShowPreview.encode(bookmarks);
prefs.setString("bookmarks", encodedData);
Get.find<BookmarksPageController>()
.updateBookmarksList(bookmarks: bookmarks);
Box<HiveShowPreview> bookmarks = Hive.box<HiveShowPreview>('bookmarks');
HiveShowPreview hiveShow = await convertFullShowToHive(
fullShow, (bookmarks.length + 1).toString());
bookmarks.put(bookmarks.length + 1, hiveShow);
if (kDebugMode) {
print("Item added to bookmarks");
}
return true;
}
// Delete a movie or tv show from the bookmarks list in the shared preferences
Future<bool> deleteBookmark({FullShow? fullShow, ShowPreview? show}) async {
final SharedPreferences prefs = await SharedPreferences.getInstance();
List<ShowPreview> bookmarks = Get.find<BookmarksPageController>().bookmarks;
Future<bool> deleteBookmark({required String showId}) async {
Box<HiveShowPreview> bookmarks = Hive.box<HiveShowPreview>('bookmarks');
for (int i = 0; i < bookmarks.length; i++) {
if (fullShow != null) {
if (bookmarks[i].id == fullShow.id) {
if (kDebugMode) {
print(bookmarks.length);
}
bookmarks.remove(bookmarks[i]);
if (kDebugMode) {
print(bookmarks.length);
}
}
} else if (show != null) {
if (bookmarks[i].id == show.id) {
if (kDebugMode) {
print(bookmarks.length);
}
bookmarks.remove(bookmarks[i]);
if (kDebugMode) {
print(bookmarks.length);
}
if (bookmarks.getAt(i)?.id == showId) {
bookmarks.deleteAt(i);
if (kDebugMode) {
print("Item deleted from bookmarks");
}
return true;
}
}
final String encodedData = ShowPreview.encode(bookmarks);
prefs.setString("bookmarks", encodedData);
Get.find<BookmarksPageController>()
.updateBookmarksList(bookmarks: bookmarks);
if (kDebugMode) {
print("Item deleted from bookmarks");
}
return true;
return false;
}
// Get a bool value that is there any bookmarks in the shared preferences or not
Future<bool> isThereInBookmarks({required String showId}) async {
List<ShowPreview> bookmarks = Get.find<BookmarksPageController>().bookmarks;
bool isThere = false;
Box<HiveShowPreview> bookmarks = Hive.box<HiveShowPreview>('bookmarks');
for (int i = 0; i < bookmarks.length; i++) {
if (bookmarks[i].id == showId) {
isThere = true;
if (bookmarks.getAt(i)?.id == showId) {
if (kDebugMode) {
print("Item is in bookmarks");
}
return true;
}
}
return isThere;
}
Future<String> getShowCrew({required FullShow fullShow}) async {
List<String> crewList = [];
String crew = "";
for (int i = 0; i < 3; i++) {
crewList.add(fullShow.actorList[i].name);
if (kDebugMode) {
print("Item is not in bookmarks");
}
crew = crewList.join(", ");
return crew;
return false;
}
}

View File

@ -1,11 +0,0 @@
import 'package:get/get.dart';
import '../../../models/show_models/show_preview_model.dart';
class BookmarksPageController extends GetxController {
List<ShowPreview> bookmarks = [];
updateBookmarksList({required List<ShowPreview> bookmarks}) {
this.bookmarks = bookmarks;
update();
}
}

View File

@ -1,14 +1,15 @@
import 'package:flutter/material.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:get/get.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:hive_flutter/adapters.dart';
import 'package:movielab/constants/colors.dart';
import 'package:movielab/models/hive/models/show_preview.dart';
import 'package:movielab/modules/preferences_shareholder.dart';
import 'package:movielab/pages/main/bookmarks/bookmarks_controller.dart';
import 'package:movielab/pages/show/show_box/bookmarks_show_box.dart';
import 'package:movielab/widgets/loading_error.dart';
import 'package:ms_undraw/ms_undraw.dart';
import '../../../models/hive/convertor.dart';
import '../../../widgets/loading_error.dart';
import '../../show/show_box/bookmarks_show_box.dart';
class BookmarksPage extends StatelessWidget {
const BookmarksPage({Key? key}) : super(key: key);
@ -17,45 +18,48 @@ class BookmarksPage extends StatelessWidget {
Widget build(BuildContext context) {
final preferencesShareholder = PreferencesShareholder();
return GetBuilder<BookmarksPageController>(
builder: (_) {
return Scaffold(
backgroundColor: kBackgroundColor,
floatingActionButton: Container(
height: 55.0,
width: 55.0,
margin: const EdgeInsets.only(bottom: 7.5, right: 5),
child: FittedBox(
child: FloatingActionButton(
onPressed: () {
preferencesShareholder.deleteBookmarks();
},
tooltip: "Delete all",
backgroundColor: Colors.white,
child: const Icon(
FontAwesomeIcons.trash,
color: kBlueColor,
)),
),
),
appBar: AppBar(
centerTitle: true,
automaticallyImplyLeading: false,
backgroundColor: kBackgroundColor,
title: Text("Bookmarks",
style: GoogleFonts.poppins(
color: Colors.white,
fontSize: 25,
fontWeight: FontWeight.bold)),
),
body: _.bookmarks.isNotEmpty
return Scaffold(
backgroundColor: kBackgroundColor,
floatingActionButton: Container(
height: 55.0,
width: 55.0,
margin: const EdgeInsets.only(bottom: 7.5, right: 5),
child: FittedBox(
child: FloatingActionButton(
onPressed: () {
preferencesShareholder.deleteBookmarks();
},
tooltip: "Delete all",
backgroundColor: Colors.white,
child: const Icon(
FontAwesomeIcons.trash,
color: kBlueColor,
)),
),
),
appBar: AppBar(
centerTitle: true,
automaticallyImplyLeading: false,
backgroundColor: kBackgroundColor,
title: Text("Bookmarks",
style: GoogleFonts.poppins(
color: Colors.white,
fontSize: 25,
fontWeight: FontWeight.bold)),
),
body: ValueListenableBuilder<Box<HiveShowPreview>>(
valueListenable: Hive.box<HiveShowPreview>('bookmarks').listenable(),
builder: (context, box, _) {
final bookmarks = box.values.toList().cast<HiveShowPreview>();
print(bookmarks.toString());
return bookmarks.isNotEmpty
? ListView.builder(
itemCount: _.bookmarks.length,
itemCount: bookmarks.length,
physics: const BouncingScrollPhysics(),
itemBuilder: (context, index) {
return BookmarksShowBox(
showPreview:
_.bookmarks[_.bookmarks.length - index - 1]);
showPreview: convertHiveToShowPreview(
bookmarks[bookmarks.length - index - 1]));
},
)
: Column(
@ -85,8 +89,8 @@ class BookmarksPage extends StatelessWidget {
tryAgain: () {}),
),
),
]));
},
);
]);
},
));
}
}

View File

@ -4,6 +4,7 @@ import 'package:get/get.dart';
class MainController extends GetxController {
// Main page bottom navigation bar page index controller
int selectedIndex = 0;
changeIndex(int index) {
// If user select a page that is already selected, page should be scroll to top
if (index == selectedIndex) {

View File

@ -169,5 +169,5 @@ class BookmarksShowBox extends StatelessWidget {
void delete(BuildContext context, ShowPreview showPreview) {
final preferencesShareholder = PreferencesShareholder();
preferencesShareholder.deleteBookmark(show: showPreview);
preferencesShareholder.deleteBookmark(showId: showPreview.id);
}

View File

@ -47,7 +47,7 @@ class _ShowPageNavBarState extends State<ShowPageNavBar> {
isBookmarked
? {
preferencesShareholder.deleteBookmark(
fullShow: widget.show),
showId: widget.show.id),
setState(() {
isBookmarked = false;
})

View File

@ -7,11 +7,9 @@ import '../../modules/api_requester.dart';
Future<RequestResult> getInitialData() async {
final apiRequester = APIRequester();
final preferencesShareholder = PreferencesShareholder();
try {
await apiRequester.getPopularMovies();
await apiRequester.getPopularTVShows();
await preferencesShareholder.getBookmarks();
} catch (e) {
await Future.delayed(const Duration(seconds: 1));
return RequestResult.FAILURE_USER_PROBLEM;

View File

@ -1,16 +1,10 @@
import 'package:flutter/material.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'package:get/get.dart';
import 'package:movielab/modules/navigate.dart';
import '../../constants/colors.dart';
import '../../constants/types.dart';
import '../../modules/cache/cache_data.dart';
import '../../modules/system_ui_overlay_style.dart';
import '../../pages/main/bookmarks/bookmarks_controller.dart';
import '../../pages/main/home/home_data_controller.dart';
import '../../pages/main/main_controller.dart';
import '../../pages/main/main_page.dart';
import '../../pages/main/search/search_bar/search_bar_controller.dart';
import '../../widgets/loading_error.dart';
import 'get_initial_data.dart';
@ -28,11 +22,6 @@ class _SplashScreenState extends State<SplashScreen> {
super.initState();
setSystemUIOverlayStyle(systemUIOverlayStyle: SystemUIOverlayStyle.DARK);
// Start the state managments
Get.put(MainController());
Get.put(HomeDataController());
Get.put(SearchBarController());
Get.put(CacheData());
Get.put(BookmarksPageController());
_loadData();
}

View File

@ -43,6 +43,62 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.0"
build:
dependency: transitive
description:
name: build
url: "https://pub.dartlang.org"
source: hosted
version: "2.3.0"
build_config:
dependency: transitive
description:
name: build_config
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.0"
build_daemon:
dependency: transitive
description:
name: build_daemon
url: "https://pub.dartlang.org"
source: hosted
version: "3.1.0"
build_resolvers:
dependency: transitive
description:
name: build_resolvers
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.9"
build_runner:
dependency: "direct dev"
description:
name: build_runner
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.11"
build_runner_core:
dependency: transitive
description:
name: build_runner_core
url: "https://pub.dartlang.org"
source: hosted
version: "7.2.3"
built_collection:
dependency: transitive
description:
name: built_collection
url: "https://pub.dartlang.org"
source: hosted
version: "5.1.1"
built_value:
dependency: transitive
description:
name: built_value
url: "https://pub.dartlang.org"
source: hosted
version: "8.3.3"
cached_network_image:
dependency: "direct main"
description:
@ -78,6 +134,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.1"
checked_yaml:
dependency: transitive
description:
name: checked_yaml
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.1"
clock:
dependency: transitive
description:
@ -85,6 +148,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0"
code_builder:
dependency: transitive
description:
name: code_builder
url: "https://pub.dartlang.org"
source: hosted
version: "4.1.0"
collection:
dependency: transitive
description:
@ -120,6 +190,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.4"
dart_style:
dependency: transitive
description:
name: dart_style
url: "https://pub.dartlang.org"
source: hosted
version: "2.2.3"
fake_async:
dependency: transitive
description:
@ -141,6 +218,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "6.1.2"
fixnum:
dependency: transitive
description:
name: fixnum
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.1"
flutter:
dependency: "direct main"
description: flutter
@ -247,6 +331,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "5.0.5"
graphs:
dependency: transitive
description:
name: graphs
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.0"
hive:
dependency: "direct main"
description:
@ -261,6 +352,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0"
hive_generator:
dependency: "direct dev"
description:
name: hive_generator
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.3"
http:
dependency: "direct main"
description:
@ -499,6 +597,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.1"
pubspec_parse:
dependency: transitive
description:
name: pubspec_parse
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.0"
rxdart:
dependency: transitive
description:
@ -595,6 +700,20 @@ packages:
description: flutter
source: sdk
version: "0.0.99"
source_gen:
dependency: transitive
description:
name: source_gen
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.2"
source_helper:
dependency: transitive
description:
name: source_helper
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.2"
source_map_stack_trace:
dependency: transitive
description:
@ -658,6 +777,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.0"
stream_transform:
dependency: transitive
description:
name: stream_transform
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0"
string_scanner:
dependency: transitive
description:
@ -700,6 +826,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "0.4.13"
timing:
dependency: transitive
description:
name: timing
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.0"
typed_data:
dependency: transitive
description:

View File

@ -41,6 +41,8 @@ dev_dependencies:
sdk: flutter
flutter_lints: ^2.0.1
test: ^1.17.12
build_runner: ^2.1.7
hive_generator: ^1.1.2
flutter:
uses-material-design: true