From 324f95fff11ec8342575a782a32134ef860c0853 Mon Sep 17 00:00:00 2001 From: ElNgatia Date: Sat, 2 Nov 2024 19:22:43 +0300 Subject: [PATCH 01/10] refactor: migrate flutter gradle plugin apply --- .gitignore | 12 +----------- android/app/build.gradle | 17 ++++++----------- android/build.gradle | 13 ------------- android/settings.gradle | 30 ++++++++++++++++++++++-------- 4 files changed, 29 insertions(+), 43 deletions(-) diff --git a/.gitignore b/.gitignore index 5e3a1f1..a4ef962 100644 --- a/.gitignore +++ b/.gitignore @@ -30,17 +30,7 @@ migrate_working_dir/ .packages .pub-cache/ .pub/ -!/ -/* -!/build/ -/build/* -!/build/app/ -/build/app/* -!/build/app/outputs/ -/build/app/outputs/* -!/build/app/outputs/flutter-apk/ -/build/app/outputs/flutter-apk/* -!/build/app/outputs/flutter-apk/app-release.apk +build/ # to keep release apk # Symbolication related diff --git a/android/app/build.gradle b/android/app/build.gradle index 666ae50..ccab691 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -1,3 +1,9 @@ +plugins { + id "com.android.application" + id "kotlin-android" + id "dev.flutter.flutter-gradle-plugin" +} + def localProperties = new Properties() def localPropertiesFile = rootProject.file('local.properties') if (localPropertiesFile.exists()) { @@ -6,10 +12,6 @@ if (localPropertiesFile.exists()) { } } -def flutterRoot = localProperties.getProperty('flutter.sdk') -if (flutterRoot == null) { - throw new Exception("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") -} def flutterVersionCode = localProperties.getProperty('flutter.versionCode') if (flutterVersionCode == null) { @@ -26,9 +28,6 @@ if (keystorePropertiesFile.exists()) { keystoreProperties.load(new FileInputStream(keystorePropertiesFile)) } -apply plugin: 'com.android.application' -apply plugin: 'kotlin-android' -apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" android { namespace "com.adventurequest.adventure_quest" @@ -78,7 +77,3 @@ android { flutter { source '../..' } - -dependencies { - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" -} diff --git a/android/build.gradle b/android/build.gradle index ce647a4..bc157bd 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -1,16 +1,3 @@ -buildscript { - ext.kotlin_version = '1.7.10' - repositories { - google() - mavenCentral() - } - - dependencies { - classpath 'com.android.tools.build:gradle:7.4.2' - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" - } -} - allprojects { repositories { google() diff --git a/android/settings.gradle b/android/settings.gradle index 44e62bc..599ca9d 100644 --- a/android/settings.gradle +++ b/android/settings.gradle @@ -1,11 +1,25 @@ -include ':app' +pluginManagement { + def flutterSdkPath = { + def properties = new Properties() + file("local.properties").withInputStream { properties.load(it) } + def flutterSdkPath = properties.getProperty("flutter.sdk") + assert flutterSdkPath != null, "flutter.sdk not set in local.properties" + return flutterSdkPath + }() -def localPropertiesFile = new File(rootProject.projectDir, "local.properties") -def properties = new Properties() + includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") -assert localPropertiesFile.exists() -localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } + repositories { + google() + mavenCentral() + gradlePluginPortal() + } +} -def flutterSdkPath = properties.getProperty("flutter.sdk") -assert flutterSdkPath != null, "flutter.sdk not set in local.properties" -apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" +plugins { + id "dev.flutter.flutter-plugin-loader" version "1.0.0" + id "com.android.application" version "7.4.2" apply false + id "org.jetbrains.kotlin.android" version "1.7.10" apply false +} + +include ":app" \ No newline at end of file From b3f955c85ba88668d60d6579655dea76db99fc42 Mon Sep 17 00:00:00 2001 From: ElNgatia Date: Sat, 2 Nov 2024 20:05:18 +0300 Subject: [PATCH 02/10] feat: implement main app structure and refactor entry point --- lib/app/app.dart | 24 ++++++++++++++++++++++++ lib/main.dart | 25 +++---------------------- 2 files changed, 27 insertions(+), 22 deletions(-) create mode 100644 lib/app/app.dart diff --git a/lib/app/app.dart b/lib/app/app.dart new file mode 100644 index 0000000..8fdc5da --- /dev/null +++ b/lib/app/app.dart @@ -0,0 +1,24 @@ +import 'package:flutter/material.dart'; + +import '../presentation/common_scaffold.dart'; +import '../utils/color_schemes.g.dart'; + +class App extends StatelessWidget { + const App({super.key}); + + // This widget is the root of your application. + @override + Widget build(BuildContext context) { + return MaterialApp( + debugShowCheckedModeBanner: false, + title: 'Adventure Quest', + theme: ThemeData( + useMaterial3: true, + colorScheme: lightColorScheme), + darkTheme: ThemeData( + useMaterial3: true, + colorScheme: darkColorScheme), + home: const CommonScaffold(), + ); + } +} diff --git a/lib/main.dart b/lib/main.dart index a1ee596..67b005f 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; -import '../utils/color_schemes.g.dart'; -import 'presentation/common_scaffold.dart'; + +import 'app/app.dart'; import 'utils/activities_model.dart'; void main() { @@ -12,27 +12,8 @@ void main() { create: (BuildContext context) { return ActivitiesModel(); }, - child: const MyApp(), + child: const App(), ), ); } -class MyApp extends StatelessWidget { - const MyApp({super.key}); - - // This widget is the root of your application. - @override - Widget build(BuildContext context) { - return MaterialApp( - debugShowCheckedModeBanner: false, - title: 'Adventure Quest', - theme: ThemeData( - useMaterial3: true, - colorScheme: lightColorScheme), - darkTheme: ThemeData( - useMaterial3: true, - colorScheme: darkColorScheme), - home: const CommonScaffold(), - ); - } -} From 8fbe6ef8dae6dcbe8148f514d465ed7375ca82a1 Mon Sep 17 00:00:00 2001 From: ElNgatia Date: Sat, 2 Nov 2024 20:05:54 +0300 Subject: [PATCH 03/10] fix: update Bored API base URL for activity retrieval --- lib/utils/activities_model.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/utils/activities_model.dart b/lib/utils/activities_model.dart index 6847108..d7fce0e 100644 --- a/lib/utils/activities_model.dart +++ b/lib/utils/activities_model.dart @@ -31,8 +31,8 @@ const List typeList = [ ]; class BoredApi { - Future> getActivity( - {String type = '', String participants = ''}) async {const baseUrl = 'https://www.boredapi.com/api/activity/'; + Future> getActivity({String type = '', String participants = ''}) async { + const baseUrl = 'https://bored.api.lewagon.com/api/activity/'; final String url; From 075af9e4d15f24ad2df9e0883cdac816980b1c48 Mon Sep 17 00:00:00 2001 From: ElNgatia Date: Sat, 2 Nov 2024 20:09:45 +0300 Subject: [PATCH 04/10] feat: add Activity model for handling activity data --- lib/model/activity.dart | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 lib/model/activity.dart diff --git a/lib/model/activity.dart b/lib/model/activity.dart new file mode 100644 index 0000000..c980813 --- /dev/null +++ b/lib/model/activity.dart @@ -0,0 +1,39 @@ +class Activity { + final String activity; + final String type; + final int participants; + final int price; + final String link; + final String key; + final int accessibility; + + Activity({ + required this.activity, + required this.type, + required this.participants, + required this.price, + required this.link, + required this.key, + required this.accessibility, + }); + + factory Activity.fromJson(Map json) => Activity( + activity: json["activity"], + type: json["type"], + participants: json["participants"], + price: json["price"], + link: json["link"], + key: json["key"], + accessibility: json["accessibility"], + ); + + Map toJson() => { + "activity": activity, + "type": type, + "participants": participants, + "price": price, + "link": link, + "key": key, + "accessibility": accessibility, + }; +} From 42ea11dece991a2fd8e18d4b85ca8e7c74a1f5ca Mon Sep 17 00:00:00 2001 From: ElNgatia Date: Sat, 2 Nov 2024 23:33:41 +0300 Subject: [PATCH 05/10] feat: integrate FVM for Flutter version management --- .fvmrc | 3 ++ .gitignore | 3 ++ .vscode/settings.json | 3 ++ pubspec.yaml | 76 +++++-------------------------------------- 4 files changed, 17 insertions(+), 68 deletions(-) create mode 100644 .fvmrc create mode 100644 .vscode/settings.json diff --git a/.fvmrc b/.fvmrc new file mode 100644 index 0000000..906bbb3 --- /dev/null +++ b/.fvmrc @@ -0,0 +1,3 @@ +{ + "flutter": "3.24.3" +} \ No newline at end of file diff --git a/.gitignore b/.gitignore index a4ef962..5e108b8 100644 --- a/.gitignore +++ b/.gitignore @@ -43,3 +43,6 @@ app.*.map.json /android/app/debug /android/app/profile /android/app/release + +# FVM Version Cache +.fvm/ \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..965328d --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "dart.flutterSdkPath": ".fvm/versions/3.24.3" +} \ No newline at end of file diff --git a/pubspec.yaml b/pubspec.yaml index 977c3fb..e522b27 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,94 +1,34 @@ name: adventure_quest description: A new Flutter project. -# The following line prevents the package from being accidentally published to -# pub.dev using `flutter pub publish`. This is preferred for private packages. + publish_to: 'none' # Remove this line if you wish to publish to pub.dev -# The following defines the version and build number for your application. -# A version number is three numbers separated by dots, like 1.2.43 -# followed by an optional build number separated by a +. -# Both the version and the builder number may be overridden in flutter -# build by specifying --build-name and --build-number, respectively. -# In Android, build-name is used as versionName while build-number used as versionCode. -# Read more about Android versioning at https://developer.android.com/studio/publish/versioning -# In iOS, build-name is used as CFBundleShortVersionString while build-number is used as CFBundleVersion. -# Read more about iOS versioning at -# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html -# In Windows, build-name is used as the major, minor, and patch parts -# of the product and file versions while build-number is used as the build suffix. version: 1.0.1+1 environment: sdk: '>=3.0.6 <4.0.0' -# Dependencies specify other packages that your package needs in order to work. -# To automatically upgrade your package dependencies to the latest versions -# consider running `flutter pub upgrade --major-versions`. Alternatively, -# dependencies can be manually updated by changing the version numbers below to -# the latest version available on pub.dev. To see which dependencies have newer -# versions available, run `flutter pub outdated`. dependencies: flutter: sdk: flutter - - - # The following adds the Cupertino Icons font to your application. - # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^1.0.2 - provider: ^6.0.5 - http: ^1.1.0 fluttertoast: ^8.2.2 - shared_preferences: ^2.2.0 + http: ^1.1.0 + provider: ^6.0.5 + # shared_preferences: ^2.2.0 + drift: ^2.21.0 + drift_flutter: ^0.2.1 dev_dependencies: flutter_test: sdk: flutter - # The "flutter_lints" package below contains a set of recommended lints to - # encourage good coding practices. The lint set provided by the package is - # activated in the `analysis_options.yaml` file located at the root of your - # package. See that file for information about deactivating specific lint - # rules and activating additional ones. flutter_lints: ^2.0.0 + drift_dev: ^2.21.2 + build_runner: ^2.4.9 -# For information on the generic Dart part of this file, see the -# following page: https://dart.dev/tools/pub/pubspec -# The following section is specific to Flutter packages. flutter: - - # The following line ensures that the Material Icons font is - # included with your application, so that you can use the icons in - # the material Icons class. uses-material-design: true - # To add assets to your application, add an assets section, like this: - # assets: - # - images/a_dot_burr.jpeg - # - images/a_dot_ham.jpeg - - # An image asset can refer to one or more resolution-specific "variants", see - # https://flutter.dev/assets-and-images/#resolution-aware - - # For details regarding adding assets from package dependencies, see - # https://flutter.dev/assets-and-images/#from-packages - # To add custom fonts to your application, add a fonts section here, - # in this "flutter" section. Each entry in this list should have a - # "family" key with the font family name, and a "fonts" key with a - # list giving the asset and other descriptors for the font. For - # example: - # fonts: - # - family: Schyler - # fonts: - # - asset: fonts/Schyler-Regular.ttf - # - asset: fonts/Schyler-Italic.ttf - # style: italic - # - family: Trajan Pro - # fonts: - # - asset: fonts/TrajanPro.ttf - # - asset: fonts/TrajanPro_Bold.ttf - # weight: 700 - # - # For details regarding fonts from package dependencies, - # see https://flutter.dev/custom-fonts/#from-packages From 8f83f047a8630fc87aecfe03707ca40e60d101b0 Mon Sep 17 00:00:00 2001 From: ElNgatia Date: Sat, 2 Nov 2024 23:34:11 +0300 Subject: [PATCH 06/10] feat: implement activity repository and local data source, update favorites handling --- android/app/build.gradle | 4 +- .../datasource/activity_local_datasource.dart | 27 ++++++++++++ .../activity_remote_datasource.dart | 23 ++++++++++ lib/activity/data/model/activity.dart | 37 ++++++++++++++++ .../repository/activity_repository.dart | 36 ++++++++++++++++ lib/presentation/favorites.dart | 42 +++++++------------ lib/utils/activities_model.dart | 13 ------ 7 files changed, 141 insertions(+), 41 deletions(-) create mode 100644 lib/activity/data/datasource/activity_local_datasource.dart create mode 100644 lib/activity/data/datasource/activity_remote_datasource.dart create mode 100644 lib/activity/data/model/activity.dart create mode 100644 lib/activity/repository/activity_repository.dart diff --git a/android/app/build.gradle b/android/app/build.gradle index ccab691..e7c5914 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -31,7 +31,7 @@ if (keystorePropertiesFile.exists()) { android { namespace "com.adventurequest.adventure_quest" - compileSdkVersion 33 + compileSdkVersion 34 ndkVersion flutter.ndkVersion compileOptions { @@ -53,7 +53,7 @@ android { // You can update the following values to match your application needs. // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration. minSdkVersion 21 - targetSdkVersion 31 + targetSdkVersion 34 versionCode 11 versionName "1.1.0" } diff --git a/lib/activity/data/datasource/activity_local_datasource.dart b/lib/activity/data/datasource/activity_local_datasource.dart new file mode 100644 index 0000000..af91f72 --- /dev/null +++ b/lib/activity/data/datasource/activity_local_datasource.dart @@ -0,0 +1,27 @@ +import 'package:adventure_quest/database/app_database.dart'; + +abstract class ActivityLocalDataSource { + // get activities, add activity, delete activity, + Future addActivity(activityCompanion); + void deleteActivity(int id); + Future> getActivity(); +} + +class ActivityLocalDataSourceImpl implements ActivityLocalDataSource { + @override + Future addActivity( activityCompanion) { + return appDatabase.into(appDatabase.activity).insert(activityCompanion); + } + + @override + void deleteActivity(int id) { + return appDatabase.delete(appDatabase.activity).where((tbl) => tbl.id.equals(id)); + } + + @override + Future> getActivity() { + return appDatabase.select(appDatabase.activity).get(); + } +} + +ActivityLocalDataSource activityLocalDataSource = ActivityLocalDataSourceImpl(); diff --git a/lib/activity/data/datasource/activity_remote_datasource.dart b/lib/activity/data/datasource/activity_remote_datasource.dart new file mode 100644 index 0000000..4c034f5 --- /dev/null +++ b/lib/activity/data/datasource/activity_remote_datasource.dart @@ -0,0 +1,23 @@ +import 'dart:convert'; + +import 'package:adventure_quest/activity/data/model/activity.dart'; +import 'package:http/http.dart' as http; + +abstract class ActivityRemoteDataSource { + Future fetchActivity(); +} + +class ActivityRemoteDataSourceImpl implements ActivityRemoteDataSource { + @override + Future fetchActivity() async { + try { + final response = await http.get(Uri.parse('https://bored.api.lewagon.com/api/activity/')); + + return ActivityModel.fromJson(json.decode(response.body)); + } catch (e) { + rethrow; + } + } +} + +ActivityRemoteDataSource activityRemoteDataSource = ActivityRemoteDataSourceImpl(); diff --git a/lib/activity/data/model/activity.dart b/lib/activity/data/model/activity.dart new file mode 100644 index 0000000..b3ab69d --- /dev/null +++ b/lib/activity/data/model/activity.dart @@ -0,0 +1,37 @@ +import 'package:drift/drift.dart'; + +class Activity extends Table { + IntColumn get id => integer().autoIncrement()(); + TextColumn get activity => text()(); + TextColumn get type => text()(); + IntColumn get participants => integer()(); + TextColumn get link => text()(); + TextColumn get key => text().unique()(); +} +class ActivityModel { + final int? id; + final String activity; + final String type; + final int participants; + final String link; + final String key; + + ActivityModel({ + this.id, + required this.activity, + required this.type, + required this.participants, + required this.link, + required this.key, + }); + + factory ActivityModel.fromJson(Map json) { + return ActivityModel( + activity: json['activity'] as String, + type: json['type'] as String, + participants: json['participants'] as int, + link: json['link'] as String, + key: json['key'] as String, + ); + } +} \ No newline at end of file diff --git a/lib/activity/repository/activity_repository.dart b/lib/activity/repository/activity_repository.dart new file mode 100644 index 0000000..782e271 --- /dev/null +++ b/lib/activity/repository/activity_repository.dart @@ -0,0 +1,36 @@ +import 'package:adventure_quest/activity/data/datasource/activity_local_datasource.dart'; +import 'package:adventure_quest/activity/data/datasource/activity_remote_datasource.dart'; +import 'package:adventure_quest/activity/data/model/activity.dart'; +import 'package:adventure_quest/database/app_database.dart'; + +abstract class ActivityRepository { + // fetch, get, delete, save, basic crud with api calls too + Future fetchActivity(); + Future> getActivity(); + Future saveActivity(activity); + void deleteActivity(int id); +} + +class ActivityRepositoryImpl implements ActivityRepository { + @override + void deleteActivity(int id) { + return activityLocalDataSource.deleteActivity(id); + } + + @override + Future fetchActivity() async { + return activityRemoteDataSource.fetchActivity(); + } + + @override + Future> getActivity() { + return activityLocalDataSource.getActivity(); + } + + @override + Future saveActivity(activityCompanion) { + return activityLocalDataSource.addActivity(activityCompanion); + } +} + +ActivityRepository activityRepository = ActivityRepositoryImpl(); diff --git a/lib/presentation/favorites.dart b/lib/presentation/favorites.dart index 47b57a3..bf1990a 100644 --- a/lib/presentation/favorites.dart +++ b/lib/presentation/favorites.dart @@ -1,8 +1,8 @@ -import 'dart:convert'; - +import 'package:adventure_quest/activity/data/datasource/activity_local_datasource.dart'; +import 'package:adventure_quest/database/app_database.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; -import 'package:shared_preferences/shared_preferences.dart'; + import '../utils/activities_model.dart'; @@ -14,7 +14,7 @@ class Favorites extends StatefulWidget { } class _FavoritesState extends State { - List> favorites = []; + List favorites = []; @override void initState() { @@ -22,32 +22,22 @@ class _FavoritesState extends State { _getFavorites(); } -Future _getFavorites() async { - final prefs = await SharedPreferences.getInstance(); - final favoritesStringList = prefs.getStringList('favorites') ?? []; + Future _getFavorites() async { + final favoritesStringList =await activityLocalDataSource.getActivity(); - setState(() { - favorites = favoritesStringList.map>((favoritesString) { - return Map.from(json.decode(favoritesString)); - }).toList(); - }); -} + setState(() { + favorites = favoritesStringList; + }); + } - Future _updateFavorites( - List> updatedFavorite) async { - final prefs = await SharedPreferences.getInstance(); - final updatedFavoriteJsonList = updatedFavorite.map((activity) { - return json.encode(activity); - }).toList(); + Future _updateFavorites(List> updatedFavorite) async { - await prefs.setStringList('favorites', updatedFavoriteJsonList); } @override Widget build(BuildContext context) { return Scaffold( - body: - Consumer(builder: (builder, activitiesModel, child) { + body: Consumer(builder: (builder, activitiesModel, child) { final activities = activitiesModel.activities; return ListView.separated( @@ -61,10 +51,10 @@ Future _getFavorites() async { borderRadius: BorderRadius.circular(10), ), title: Text( - activity['activity'] ?? '', + activity.activity, ), subtitle: Text( - activity['type'] ?? '', + activity.type , style: const TextStyle(fontWeight: FontWeight.w500), ), trailing: Row( @@ -79,12 +69,12 @@ Future _getFavorites() async { IconButton( icon: const Icon(Icons.cancel_outlined), onPressed: () { - activitiesModel.removeActivity(activity['key']); + activitiesModel.removeActivity(activity.key); setState(() { favorites.remove(activity); }); - _updateFavorites(favorites); + // _updateFavorites(favorites); }, ), ], diff --git a/lib/utils/activities_model.dart b/lib/utils/activities_model.dart index d7fce0e..423ecc5 100644 --- a/lib/utils/activities_model.dart +++ b/lib/utils/activities_model.dart @@ -17,19 +17,6 @@ class ActivitiesModel extends ChangeNotifier { } } -const List typeList = [ - '', - 'education', - 'recreational', - 'social', - 'diy', - 'charity', - 'cooking', - 'relaxation', - 'music', - 'busywork' -]; - class BoredApi { Future> getActivity({String type = '', String participants = ''}) async { const baseUrl = 'https://bored.api.lewagon.com/api/activity/'; From 2c334353f4e256b8539b8e4f776bd7c42144e6f5 Mon Sep 17 00:00:00 2001 From: ElNgatia Date: Sat, 2 Nov 2024 23:34:29 +0300 Subject: [PATCH 07/10] feat: add Drift database implementation for activity management --- lib/database/app_database.dart | 30 ++ lib/database/app_database.g.dart | 537 +++++++++++++++++++++++++++++ lib/model/activity.dart | 39 --- lib/presentation/home.dart | 48 +-- pubspec.lock | 575 ++++++++++++++++++++++++++----- test/widget_test.dart | 4 +- 6 files changed, 1069 insertions(+), 164 deletions(-) create mode 100644 lib/database/app_database.dart create mode 100644 lib/database/app_database.g.dart delete mode 100644 lib/model/activity.dart diff --git a/lib/database/app_database.dart b/lib/database/app_database.dart new file mode 100644 index 0000000..f8f3b1d --- /dev/null +++ b/lib/database/app_database.dart @@ -0,0 +1,30 @@ +import 'package:drift/drift.dart'; + +import 'package:adventure_quest/activity/data/model/activity.dart'; +import 'package:drift_flutter/drift_flutter.dart'; + +part 'app_database.g.dart'; + +@DriftDatabase(tables: [Activity]) +class AppDatabase extends _$AppDatabase { + AppDatabase() : super(_openDatabase()); + + @override + int get schemaVersion => 1; + + @override + MigrationStrategy get migration { + return MigrationStrategy( + onCreate: (m) async { + await m.createAll(); + }, + onUpgrade: (m, from, to) async {}, + ); + } + + static QueryExecutor _openDatabase() { + return driftDatabase(name: 'adventure_quest'); + } +} + +AppDatabase appDatabase = AppDatabase(); diff --git a/lib/database/app_database.g.dart b/lib/database/app_database.g.dart new file mode 100644 index 0000000..0693236 --- /dev/null +++ b/lib/database/app_database.g.dart @@ -0,0 +1,537 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'app_database.dart'; + +// ignore_for_file: type=lint +class $ActivityTable extends Activity + with TableInfo<$ActivityTable, ActivityData> { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + $ActivityTable(this.attachedDatabase, [this._alias]); + static const VerificationMeta _idMeta = const VerificationMeta('id'); + @override + late final GeneratedColumn id = GeneratedColumn( + 'id', aliasedName, false, + hasAutoIncrement: true, + type: DriftSqlType.int, + requiredDuringInsert: false, + defaultConstraints: + GeneratedColumn.constraintIsAlways('PRIMARY KEY AUTOINCREMENT')); + static const VerificationMeta _activityMeta = + const VerificationMeta('activity'); + @override + late final GeneratedColumn activity = GeneratedColumn( + 'activity', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + static const VerificationMeta _typeMeta = const VerificationMeta('type'); + @override + late final GeneratedColumn type = GeneratedColumn( + 'type', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + static const VerificationMeta _participantsMeta = + const VerificationMeta('participants'); + @override + late final GeneratedColumn participants = GeneratedColumn( + 'participants', aliasedName, false, + type: DriftSqlType.int, requiredDuringInsert: true); + static const VerificationMeta _linkMeta = const VerificationMeta('link'); + @override + late final GeneratedColumn link = GeneratedColumn( + 'link', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + static const VerificationMeta _keyMeta = const VerificationMeta('key'); + @override + late final GeneratedColumn key = GeneratedColumn( + 'key', aliasedName, false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways('UNIQUE')); + @override + List get $columns => + [id, activity, type, participants, link, key]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'activity'; + @override + VerificationContext validateIntegrity(Insertable instance, + {bool isInserting = false}) { + final context = VerificationContext(); + final data = instance.toColumns(true); + if (data.containsKey('id')) { + context.handle(_idMeta, id.isAcceptableOrUnknown(data['id']!, _idMeta)); + } + if (data.containsKey('activity')) { + context.handle(_activityMeta, + activity.isAcceptableOrUnknown(data['activity']!, _activityMeta)); + } else if (isInserting) { + context.missing(_activityMeta); + } + if (data.containsKey('type')) { + context.handle( + _typeMeta, type.isAcceptableOrUnknown(data['type']!, _typeMeta)); + } else if (isInserting) { + context.missing(_typeMeta); + } + if (data.containsKey('participants')) { + context.handle( + _participantsMeta, + participants.isAcceptableOrUnknown( + data['participants']!, _participantsMeta)); + } else if (isInserting) { + context.missing(_participantsMeta); + } + if (data.containsKey('link')) { + context.handle( + _linkMeta, link.isAcceptableOrUnknown(data['link']!, _linkMeta)); + } else if (isInserting) { + context.missing(_linkMeta); + } + if (data.containsKey('key')) { + context.handle( + _keyMeta, key.isAcceptableOrUnknown(data['key']!, _keyMeta)); + } else if (isInserting) { + context.missing(_keyMeta); + } + return context; + } + + @override + Set get $primaryKey => {id}; + @override + ActivityData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return ActivityData( + id: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}id'])!, + activity: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}activity'])!, + type: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}type'])!, + participants: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}participants'])!, + link: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}link'])!, + key: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}key'])!, + ); + } + + @override + $ActivityTable createAlias(String alias) { + return $ActivityTable(attachedDatabase, alias); + } +} + +class ActivityData extends DataClass implements Insertable { + final int id; + final String activity; + final String type; + final int participants; + final String link; + final String key; + const ActivityData( + {required this.id, + required this.activity, + required this.type, + required this.participants, + required this.link, + required this.key}); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = Variable(id); + map['activity'] = Variable(activity); + map['type'] = Variable(type); + map['participants'] = Variable(participants); + map['link'] = Variable(link); + map['key'] = Variable(key); + return map; + } + + ActivityCompanion toCompanion(bool nullToAbsent) { + return ActivityCompanion( + id: Value(id), + activity: Value(activity), + type: Value(type), + participants: Value(participants), + link: Value(link), + key: Value(key), + ); + } + + factory ActivityData.fromJson(Map json, + {ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return ActivityData( + id: serializer.fromJson(json['id']), + activity: serializer.fromJson(json['activity']), + type: serializer.fromJson(json['type']), + participants: serializer.fromJson(json['participants']), + link: serializer.fromJson(json['link']), + key: serializer.fromJson(json['key']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'activity': serializer.toJson(activity), + 'type': serializer.toJson(type), + 'participants': serializer.toJson(participants), + 'link': serializer.toJson(link), + 'key': serializer.toJson(key), + }; + } + + ActivityData copyWith( + {int? id, + String? activity, + String? type, + int? participants, + String? link, + String? key}) => + ActivityData( + id: id ?? this.id, + activity: activity ?? this.activity, + type: type ?? this.type, + participants: participants ?? this.participants, + link: link ?? this.link, + key: key ?? this.key, + ); + ActivityData copyWithCompanion(ActivityCompanion data) { + return ActivityData( + id: data.id.present ? data.id.value : this.id, + activity: data.activity.present ? data.activity.value : this.activity, + type: data.type.present ? data.type.value : this.type, + participants: data.participants.present + ? data.participants.value + : this.participants, + link: data.link.present ? data.link.value : this.link, + key: data.key.present ? data.key.value : this.key, + ); + } + + @override + String toString() { + return (StringBuffer('ActivityData(') + ..write('id: $id, ') + ..write('activity: $activity, ') + ..write('type: $type, ') + ..write('participants: $participants, ') + ..write('link: $link, ') + ..write('key: $key') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(id, activity, type, participants, link, key); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is ActivityData && + other.id == this.id && + other.activity == this.activity && + other.type == this.type && + other.participants == this.participants && + other.link == this.link && + other.key == this.key); +} + +class ActivityCompanion extends UpdateCompanion { + final Value id; + final Value activity; + final Value type; + final Value participants; + final Value link; + final Value key; + const ActivityCompanion({ + this.id = const Value.absent(), + this.activity = const Value.absent(), + this.type = const Value.absent(), + this.participants = const Value.absent(), + this.link = const Value.absent(), + this.key = const Value.absent(), + }); + ActivityCompanion.insert({ + this.id = const Value.absent(), + required String activity, + required String type, + required int participants, + required String link, + required String key, + }) : activity = Value(activity), + type = Value(type), + participants = Value(participants), + link = Value(link), + key = Value(key); + static Insertable custom({ + Expression? id, + Expression? activity, + Expression? type, + Expression? participants, + Expression? link, + Expression? key, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (activity != null) 'activity': activity, + if (type != null) 'type': type, + if (participants != null) 'participants': participants, + if (link != null) 'link': link, + if (key != null) 'key': key, + }); + } + + ActivityCompanion copyWith( + {Value? id, + Value? activity, + Value? type, + Value? participants, + Value? link, + Value? key}) { + return ActivityCompanion( + id: id ?? this.id, + activity: activity ?? this.activity, + type: type ?? this.type, + participants: participants ?? this.participants, + link: link ?? this.link, + key: key ?? this.key, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (activity.present) { + map['activity'] = Variable(activity.value); + } + if (type.present) { + map['type'] = Variable(type.value); + } + if (participants.present) { + map['participants'] = Variable(participants.value); + } + if (link.present) { + map['link'] = Variable(link.value); + } + if (key.present) { + map['key'] = Variable(key.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('ActivityCompanion(') + ..write('id: $id, ') + ..write('activity: $activity, ') + ..write('type: $type, ') + ..write('participants: $participants, ') + ..write('link: $link, ') + ..write('key: $key') + ..write(')')) + .toString(); + } +} + +abstract class _$AppDatabase extends GeneratedDatabase { + _$AppDatabase(QueryExecutor e) : super(e); + $AppDatabaseManager get managers => $AppDatabaseManager(this); + late final $ActivityTable activity = $ActivityTable(this); + @override + Iterable> get allTables => + allSchemaEntities.whereType>(); + @override + List get allSchemaEntities => [activity]; +} + +typedef $$ActivityTableCreateCompanionBuilder = ActivityCompanion Function({ + Value id, + required String activity, + required String type, + required int participants, + required String link, + required String key, +}); +typedef $$ActivityTableUpdateCompanionBuilder = ActivityCompanion Function({ + Value id, + Value activity, + Value type, + Value participants, + Value link, + Value key, +}); + +class $$ActivityTableFilterComposer + extends Composer<_$AppDatabase, $ActivityTable> { + $$ActivityTableFilterComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + ColumnFilters get id => $composableBuilder( + column: $table.id, builder: (column) => ColumnFilters(column)); + + ColumnFilters get activity => $composableBuilder( + column: $table.activity, builder: (column) => ColumnFilters(column)); + + ColumnFilters get type => $composableBuilder( + column: $table.type, builder: (column) => ColumnFilters(column)); + + ColumnFilters get participants => $composableBuilder( + column: $table.participants, builder: (column) => ColumnFilters(column)); + + ColumnFilters get link => $composableBuilder( + column: $table.link, builder: (column) => ColumnFilters(column)); + + ColumnFilters get key => $composableBuilder( + column: $table.key, builder: (column) => ColumnFilters(column)); +} + +class $$ActivityTableOrderingComposer + extends Composer<_$AppDatabase, $ActivityTable> { + $$ActivityTableOrderingComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + ColumnOrderings get id => $composableBuilder( + column: $table.id, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get activity => $composableBuilder( + column: $table.activity, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get type => $composableBuilder( + column: $table.type, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get participants => $composableBuilder( + column: $table.participants, + builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get link => $composableBuilder( + column: $table.link, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get key => $composableBuilder( + column: $table.key, builder: (column) => ColumnOrderings(column)); +} + +class $$ActivityTableAnnotationComposer + extends Composer<_$AppDatabase, $ActivityTable> { + $$ActivityTableAnnotationComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + GeneratedColumn get id => + $composableBuilder(column: $table.id, builder: (column) => column); + + GeneratedColumn get activity => + $composableBuilder(column: $table.activity, builder: (column) => column); + + GeneratedColumn get type => + $composableBuilder(column: $table.type, builder: (column) => column); + + GeneratedColumn get participants => $composableBuilder( + column: $table.participants, builder: (column) => column); + + GeneratedColumn get link => + $composableBuilder(column: $table.link, builder: (column) => column); + + GeneratedColumn get key => + $composableBuilder(column: $table.key, builder: (column) => column); +} + +class $$ActivityTableTableManager extends RootTableManager< + _$AppDatabase, + $ActivityTable, + ActivityData, + $$ActivityTableFilterComposer, + $$ActivityTableOrderingComposer, + $$ActivityTableAnnotationComposer, + $$ActivityTableCreateCompanionBuilder, + $$ActivityTableUpdateCompanionBuilder, + (ActivityData, BaseReferences<_$AppDatabase, $ActivityTable, ActivityData>), + ActivityData, + PrefetchHooks Function()> { + $$ActivityTableTableManager(_$AppDatabase db, $ActivityTable table) + : super(TableManagerState( + db: db, + table: table, + createFilteringComposer: () => + $$ActivityTableFilterComposer($db: db, $table: table), + createOrderingComposer: () => + $$ActivityTableOrderingComposer($db: db, $table: table), + createComputedFieldComposer: () => + $$ActivityTableAnnotationComposer($db: db, $table: table), + updateCompanionCallback: ({ + Value id = const Value.absent(), + Value activity = const Value.absent(), + Value type = const Value.absent(), + Value participants = const Value.absent(), + Value link = const Value.absent(), + Value key = const Value.absent(), + }) => + ActivityCompanion( + id: id, + activity: activity, + type: type, + participants: participants, + link: link, + key: key, + ), + createCompanionCallback: ({ + Value id = const Value.absent(), + required String activity, + required String type, + required int participants, + required String link, + required String key, + }) => + ActivityCompanion.insert( + id: id, + activity: activity, + type: type, + participants: participants, + link: link, + key: key, + ), + withReferenceMapper: (p0) => p0 + .map((e) => (e.readTable(table), BaseReferences(db, table, e))) + .toList(), + prefetchHooksCallback: null, + )); +} + +typedef $$ActivityTableProcessedTableManager = ProcessedTableManager< + _$AppDatabase, + $ActivityTable, + ActivityData, + $$ActivityTableFilterComposer, + $$ActivityTableOrderingComposer, + $$ActivityTableAnnotationComposer, + $$ActivityTableCreateCompanionBuilder, + $$ActivityTableUpdateCompanionBuilder, + (ActivityData, BaseReferences<_$AppDatabase, $ActivityTable, ActivityData>), + ActivityData, + PrefetchHooks Function()>; + +class $AppDatabaseManager { + final _$AppDatabase _db; + $AppDatabaseManager(this._db); + $$ActivityTableTableManager get activity => + $$ActivityTableTableManager(_db, _db.activity); +} diff --git a/lib/model/activity.dart b/lib/model/activity.dart deleted file mode 100644 index c980813..0000000 --- a/lib/model/activity.dart +++ /dev/null @@ -1,39 +0,0 @@ -class Activity { - final String activity; - final String type; - final int participants; - final int price; - final String link; - final String key; - final int accessibility; - - Activity({ - required this.activity, - required this.type, - required this.participants, - required this.price, - required this.link, - required this.key, - required this.accessibility, - }); - - factory Activity.fromJson(Map json) => Activity( - activity: json["activity"], - type: json["type"], - participants: json["participants"], - price: json["price"], - link: json["link"], - key: json["key"], - accessibility: json["accessibility"], - ); - - Map toJson() => { - "activity": activity, - "type": type, - "participants": participants, - "price": price, - "link": link, - "key": key, - "accessibility": accessibility, - }; -} diff --git a/lib/presentation/home.dart b/lib/presentation/home.dart index bab94e9..8d43db3 100644 --- a/lib/presentation/home.dart +++ b/lib/presentation/home.dart @@ -1,9 +1,10 @@ -import 'dart:convert'; + +import 'package:adventure_quest/activity/data/model/activity.dart'; +import 'package:adventure_quest/activity/repository/activity_repository.dart'; import 'package:adventure_quest/utils/activities_model.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; -import 'package:shared_preferences/shared_preferences.dart'; import 'package:fluttertoast/fluttertoast.dart'; class Home extends StatefulWidget { @@ -15,7 +16,7 @@ class Home extends StatefulWidget { class _HomeState extends State { final BoredApi _boredApi = BoredApi(); - Map? fetchedActivity; + ActivityModel? fetchedActivity; @override void initState() { @@ -24,7 +25,7 @@ class _HomeState extends State { } Future _getActivity() async { - final newActivity = await _boredApi.getActivity(); + final newActivity = await activityRepository.fetchActivity(); setState(() { fetchedActivity = newActivity; }); @@ -58,28 +59,23 @@ class _HomeState extends State { fontWeight: FontWeight.bold, ), ), - Center( - child: - Text(fetchedActivity!['activity'] ?? '')), + Center(child: Text(fetchedActivity!.activity)), const SizedBox( height: 10, ), const Text( 'Type', - style: TextStyle( - fontSize: 25, fontWeight: FontWeight.bold), + style: TextStyle(fontSize: 25, fontWeight: FontWeight.bold), ), - Text(fetchedActivity!['type'] ?? ''), + Text(fetchedActivity!.type), const SizedBox( height: 10, ), const Text( 'Participants', - style: TextStyle( - fontSize: 25, fontWeight: FontWeight.bold), + style: TextStyle(fontSize: 25, fontWeight: FontWeight.bold), ), - Text(fetchedActivity!['participants']?.toString() ?? - ''), + Text(fetchedActivity!.participants.toString()), ], ), if (fetchedActivity == null) @@ -96,10 +92,7 @@ class _HomeState extends State { children: [ ElevatedButton( onPressed: () async { - final newActivity = await _boredApi.getActivity(); - setState(() { - fetchedActivity = newActivity; - }); + _getActivity(); }, child: const Text( 'Get Activity', @@ -111,27 +104,14 @@ class _HomeState extends State { ElevatedButton( onPressed: () { if (fetchedActivity != null) { - // add to favorites - activitiesModel - .addActivity(Map.from(fetchedActivity!)); - - // save to local storage - SharedPreferences.getInstance() - .then((SharedPreferences prefs) { - final favorites = - prefs.getStringList('favorites') ?? []; - favorites.add(json.encode(fetchedActivity)); - prefs.setStringList('favorites', favorites); - }); + activityRepository.saveActivity(fetchedActivity); Fluttertoast.showToast( msg: 'Added to favorites', toastLength: Toast .LENGTH_SHORT, // Duration for how long the toast should be displayed - gravity: ToastGravity - .BOTTOM, // Position of the toast on the screen - backgroundColor: Colors - .grey[600], // Background color of the toast + gravity: ToastGravity.BOTTOM, // Position of the toast on the screen + backgroundColor: Colors.grey[600], // Background color of the toast textColor: Colors.white, ); } diff --git a/pubspec.lock b/pubspec.lock index d858e4f..ca23aab 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1,6 +1,43 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: + _fe_analyzer_shared: + dependency: transitive + description: + name: _fe_analyzer_shared + sha256: f256b0c0ba6c7577c15e2e4e114755640a875e885099367bf6e012b19314c834 + url: "https://pub.dev" + source: hosted + version: "72.0.0" + _macros: + dependency: transitive + description: dart + source: sdk + version: "0.3.2" + analyzer: + dependency: transitive + description: + name: analyzer + sha256: b652861553cd3990d8ed361f7979dc6d7053a9ac8843fa73820ab68ce5410139 + url: "https://pub.dev" + source: hosted + version: "6.7.0" + analyzer_plugin: + dependency: transitive + description: + name: analyzer_plugin + sha256: "9661b30b13a685efaee9f02e5d01ed9f2b423bd889d28a304d02d704aee69161" + url: "https://pub.dev" + source: hosted + version: "0.11.3" + args: + dependency: transitive + description: + name: args + sha256: bf9f5caeea8d8fe6721a9c358dd8a5c1947b27f1cfaa18b39c301273594919e6 + url: "https://pub.dev" + source: hosted + version: "2.6.0" async: dependency: transitive description: @@ -17,6 +54,70 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.1" + build: + dependency: transitive + description: + name: build + sha256: "80184af8b6cb3e5c1c4ec6d8544d27711700bc3e6d2efad04238c7b5290889f0" + url: "https://pub.dev" + source: hosted + version: "2.4.1" + build_config: + dependency: transitive + description: + name: build_config + sha256: bf80fcfb46a29945b423bd9aad884590fb1dc69b330a4d4700cac476af1708d1 + url: "https://pub.dev" + source: hosted + version: "1.1.1" + build_daemon: + dependency: transitive + description: + name: build_daemon + sha256: "79b2aef6ac2ed00046867ed354c88778c9c0f029df8a20fe10b5436826721ef9" + url: "https://pub.dev" + source: hosted + version: "4.0.2" + build_resolvers: + dependency: transitive + description: + name: build_resolvers + sha256: "339086358431fa15d7eca8b6a36e5d783728cf025e559b834f4609a1fcfb7b0a" + url: "https://pub.dev" + source: hosted + version: "2.4.2" + build_runner: + dependency: "direct dev" + description: + name: build_runner + sha256: "028819cfb90051c6b5440c7e574d1896f8037e3c96cf17aaeb054c9311cfbf4d" + url: "https://pub.dev" + source: hosted + version: "2.4.13" + build_runner_core: + dependency: transitive + description: + name: build_runner_core + sha256: f8126682b87a7282a339b871298cc12009cb67109cfa1614d6436fb0289193e0 + url: "https://pub.dev" + source: hosted + version: "7.3.2" + built_collection: + dependency: transitive + description: + name: built_collection + sha256: "376e3dd27b51ea877c28d525560790aee2e6fbb5f20e2f85d5081027d94e2100" + url: "https://pub.dev" + source: hosted + version: "5.1.1" + built_value: + dependency: transitive + description: + name: built_value + sha256: c7913a9737ee4007efedaffc968c049fd0f3d0e49109e778edc10de9426005cb + url: "https://pub.dev" + source: hosted + version: "8.9.2" characters: dependency: transitive description: @@ -25,6 +126,30 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.0" + charcode: + dependency: transitive + description: + name: charcode + sha256: fb98c0f6d12c920a02ee2d998da788bca066ca5f148492b7085ee23372b12306 + url: "https://pub.dev" + source: hosted + version: "1.3.1" + checked_yaml: + dependency: transitive + description: + name: checked_yaml + sha256: feb6bed21949061731a7a75fc5d2aa727cf160b91af9a3e464c5e3a32e28b5ff + url: "https://pub.dev" + source: hosted + version: "2.0.3" + cli_util: + dependency: transitive + description: + name: cli_util + sha256: ff6785f7e9e3c38ac98b2fb035701789de90154024a75b6cb926445e83197d1c + url: "https://pub.dev" + source: hosted + version: "0.4.2" clock: dependency: transitive description: @@ -33,22 +158,78 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.1" + code_builder: + dependency: transitive + description: + name: code_builder + sha256: "0ec10bf4a89e4c613960bf1e8b42c64127021740fb21640c29c909826a5eea3e" + url: "https://pub.dev" + source: hosted + version: "4.10.1" collection: dependency: transitive description: name: collection - sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c" + sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a url: "https://pub.dev" source: hosted - version: "1.17.1" + version: "1.18.0" + convert: + dependency: transitive + description: + name: convert + sha256: b30acd5944035672bc15c6b7a8b47d773e41e2f17de064350988c5d02adb1c68 + url: "https://pub.dev" + source: hosted + version: "3.1.2" + crypto: + dependency: transitive + description: + name: crypto + sha256: "1e445881f28f22d6140f181e07737b22f1e099a5e1ff94b0af2f9e4a463f4855" + url: "https://pub.dev" + source: hosted + version: "3.0.6" cupertino_icons: dependency: "direct main" description: name: cupertino_icons - sha256: e35129dc44c9118cee2a5603506d823bab99c68393879edb440e0090d07586be + sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6 + url: "https://pub.dev" + source: hosted + version: "1.0.8" + dart_style: + dependency: transitive + description: + name: dart_style + sha256: "7856d364b589d1f08986e140938578ed36ed948581fbc3bc9aef1805039ac5ab" + url: "https://pub.dev" + source: hosted + version: "2.3.7" + drift: + dependency: "direct main" + description: + name: drift + sha256: df027d168a2985a2e9da900adeba2ab0136f0d84436592cf3cd5135f82c8579c + url: "https://pub.dev" + source: hosted + version: "2.21.0" + drift_dev: + dependency: "direct dev" + description: + name: drift_dev + sha256: "623649abe932fc17bd32e578e7e05f7ac5e7dd0b33e6c8669a0634105d1389bf" + url: "https://pub.dev" + source: hosted + version: "2.21.2" + drift_flutter: + dependency: "direct main" + description: + name: drift_flutter + sha256: fec503e9d408f36bb345f9f6d24bc9d62b7b5f970db49760253d9e8d3acd48d5 url: "https://pub.dev" source: hosted - version: "1.0.5" + version: "0.2.1" fake_async: dependency: transitive description: @@ -61,18 +242,26 @@ packages: dependency: transitive description: name: ffi - sha256: "7bf0adc28a23d395f19f3f1eb21dd7cfd1dd9f8e1c50051c069122e6853bc878" + sha256: "16ed7b077ef01ad6170a3d0c57caa4a112a38d7a2ed5602e0aca9ca6f3d98da6" url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.3" file: dependency: transitive description: name: file - sha256: "1b92bec4fc2a72f59a8e15af5f52cd441e4a7860b49499d69dfa817af20e925d" + sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4 url: "https://pub.dev" source: hosted - version: "6.1.4" + version: "7.0.1" + fixnum: + dependency: transitive + description: + name: fixnum + sha256: b6dc7065e46c974bc7c5f143080a6764ec7a4be6da1285ececdc37be96de53be + url: "https://pub.dev" + source: hosted + version: "1.1.1" flutter: dependency: "direct main" description: flutter @@ -82,10 +271,10 @@ packages: dependency: "direct dev" description: name: flutter_lints - sha256: "2118df84ef0c3ca93f96123a616ae8540879991b8b57af2f81b76a7ada49b2a4" + sha256: a25a15ebbdfc33ab1cd26c63a6ee519df92338a9c10f122adda92938253bef04 url: "https://pub.dev" source: hosted - version: "2.0.2" + version: "2.0.3" flutter_test: dependency: "direct dev" description: flutter @@ -100,18 +289,50 @@ packages: dependency: "direct main" description: name: fluttertoast - sha256: "474f7d506230897a3cd28c965ec21c5328ae5605fc9c400cd330e9e9d6ac175c" + sha256: "95f349437aeebe524ef7d6c9bde3e6b4772717cf46a0eb6a3ceaddc740b297cc" + url: "https://pub.dev" + source: hosted + version: "8.2.8" + frontend_server_client: + dependency: transitive + description: + name: frontend_server_client + sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694 url: "https://pub.dev" source: hosted - version: "8.2.2" + version: "4.0.0" + glob: + dependency: transitive + description: + name: glob + sha256: "0e7014b3b7d4dac1ca4d6114f82bf1782ee86745b9b42a92c9289c23d8a0ab63" + url: "https://pub.dev" + source: hosted + version: "2.1.2" + graphs: + dependency: transitive + description: + name: graphs + sha256: "741bbf84165310a68ff28fe9e727332eef1407342fca52759cb21ad8177bb8d0" + url: "https://pub.dev" + source: hosted + version: "2.3.2" http: dependency: "direct main" description: name: http - sha256: "759d1a329847dd0f39226c688d3e06a6b8679668e350e2891a6474f8b4bb8525" + sha256: b9c29a161230ee03d3ccf545097fccd9b87a5264228c5d348202e0f0c28f9010 url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "1.2.2" + http_multi_server: + dependency: transitive + description: + name: http_multi_server + sha256: "97486f20f9c2f7be8f514851703d0119c3596d14ea63227af6f7a481ef2b2f8b" + url: "https://pub.dev" + source: hosted + version: "3.2.1" http_parser: dependency: transitive description: @@ -120,14 +341,54 @@ packages: url: "https://pub.dev" source: hosted version: "4.0.2" + io: + dependency: transitive + description: + name: io + sha256: "2ec25704aba361659e10e3e5f5d672068d332fc8ac516421d483a11e5cbd061e" + url: "https://pub.dev" + source: hosted + version: "1.0.4" js: dependency: transitive description: name: js - sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 + sha256: c1b2e9b5ea78c45e1a0788d29606ba27dc5f71f019f32ca5140f61ef071838cf + url: "https://pub.dev" + source: hosted + version: "0.7.1" + json_annotation: + dependency: transitive + description: + name: json_annotation + sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1" + url: "https://pub.dev" + source: hosted + version: "4.9.0" + leak_tracker: + dependency: transitive + description: + name: leak_tracker + sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05" + url: "https://pub.dev" + source: hosted + version: "10.0.5" + leak_tracker_flutter_testing: + dependency: transitive + description: + name: leak_tracker_flutter_testing + sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806" url: "https://pub.dev" source: hosted - version: "0.6.7" + version: "3.0.5" + leak_tracker_testing: + dependency: transitive + description: + name: leak_tracker_testing + sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" + url: "https://pub.dev" + source: hosted + version: "3.0.1" lints: dependency: transitive description: @@ -136,30 +397,54 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.1" + logging: + dependency: transitive + description: + name: logging + sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61 + url: "https://pub.dev" + source: hosted + version: "1.3.0" + macros: + dependency: transitive + description: + name: macros + sha256: "0acaed5d6b7eab89f63350bccd82119e6c602df0f391260d0e32b5e23db79536" + url: "https://pub.dev" + source: hosted + version: "0.1.2-main.4" matcher: dependency: transitive description: name: matcher - sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb" + sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb url: "https://pub.dev" source: hosted - version: "0.12.15" + version: "0.12.16+1" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724 + sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec url: "https://pub.dev" source: hosted - version: "0.2.0" + version: "0.11.1" meta: dependency: transitive description: name: meta - sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" + sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7 url: "https://pub.dev" source: hosted - version: "1.9.1" + version: "1.15.0" + mime: + dependency: transitive + description: + name: mime + sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6" + url: "https://pub.dev" + source: hosted + version: "2.0.0" nested: dependency: transitive description: @@ -168,147 +453,211 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.0" + package_config: + dependency: transitive + description: + name: package_config + sha256: "1c5b77ccc91e4823a5af61ee74e6b972db1ef98c2ff5a18d3161c982a55448bd" + url: "https://pub.dev" + source: hosted + version: "2.1.0" path: dependency: transitive description: name: path - sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" + sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" url: "https://pub.dev" source: hosted - version: "1.8.3" + version: "1.9.0" + path_provider: + dependency: transitive + description: + name: path_provider + sha256: "50c5dd5b6e1aaf6fb3a78b33f6aa3afca52bf903a8a5298f53101fdaee55bbcd" + url: "https://pub.dev" + source: hosted + version: "2.1.5" + path_provider_android: + dependency: transitive + description: + name: path_provider_android + sha256: c464428172cb986b758c6d1724c603097febb8fb855aa265aeecc9280c294d4a + url: "https://pub.dev" + source: hosted + version: "2.2.12" + path_provider_foundation: + dependency: transitive + description: + name: path_provider_foundation + sha256: f234384a3fdd67f989b4d54a5d73ca2a6c422fa55ae694381ae0f4375cd1ea16 + url: "https://pub.dev" + source: hosted + version: "2.4.0" path_provider_linux: dependency: transitive description: name: path_provider_linux - sha256: ba2b77f0c52a33db09fc8caf85b12df691bf28d983e84cf87ff6d693cfa007b3 + sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279 url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.2.1" path_provider_platform_interface: dependency: transitive description: name: path_provider_platform_interface - sha256: bced5679c7df11190e1ddc35f3222c858f328fff85c3942e46e7f5589bf9eb84 + sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334" url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.2" path_provider_windows: dependency: transitive description: name: path_provider_windows - sha256: ee0e0d164516b90ae1f970bdf29f726f1aa730d7cfc449ecc74c495378b705da + sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7 url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.3.0" platform: dependency: transitive description: name: platform - sha256: "57c07bf82207aee366dfaa3867b3164e4f03a238a461a11b0e8a3a510d51203d" + sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984" url: "https://pub.dev" source: hosted - version: "3.1.1" + version: "3.1.6" plugin_platform_interface: dependency: transitive description: name: plugin_platform_interface - sha256: "43798d895c929056255600343db8f049921cbec94d31ec87f1dc5c16c01935dd" + sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" url: "https://pub.dev" source: hosted - version: "2.1.5" - provider: - dependency: "direct main" + version: "2.1.8" + pool: + dependency: transitive description: - name: provider - sha256: cdbe7530b12ecd9eb455bdaa2fcb8d4dad22e80b8afb4798b41479d5ce26847f + name: pool + sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a" url: "https://pub.dev" source: hosted - version: "6.0.5" - shared_preferences: + version: "1.5.1" + provider: dependency: "direct main" description: - name: shared_preferences - sha256: "0344316c947ffeb3a529eac929e1978fcd37c26be4e8468628bac399365a3ca1" - url: "https://pub.dev" - source: hosted - version: "2.2.0" - shared_preferences_android: - dependency: transitive - description: - name: shared_preferences_android - sha256: fe8401ec5b6dcd739a0fe9588802069e608c3fdbfd3c3c93e546cf2f90438076 + name: provider + sha256: c8a055ee5ce3fd98d6fc872478b03823ffdb448699c6ebdbbc71d59b596fd48c url: "https://pub.dev" source: hosted - version: "2.2.0" - shared_preferences_foundation: + version: "6.1.2" + pub_semver: dependency: transitive description: - name: shared_preferences_foundation - sha256: d29753996d8eb8f7619a1f13df6ce65e34bc107bef6330739ed76f18b22310ef + name: pub_semver + sha256: "40d3ab1bbd474c4c2328c91e3a7df8c6dd629b79ece4c4bd04bee496a224fb0c" url: "https://pub.dev" source: hosted - version: "2.3.3" - shared_preferences_linux: + version: "2.1.4" + pubspec_parse: dependency: transitive description: - name: shared_preferences_linux - sha256: "71d6806d1449b0a9d4e85e0c7a917771e672a3d5dc61149cc9fac871115018e1" + name: pubspec_parse + sha256: c799b721d79eb6ee6fa56f00c04b472dcd44a30d258fac2174a6ec57302678f8 url: "https://pub.dev" source: hosted - version: "2.3.0" - shared_preferences_platform_interface: + version: "1.3.0" + recase: dependency: transitive description: - name: shared_preferences_platform_interface - sha256: "23b052f17a25b90ff2b61aad4cc962154da76fb62848a9ce088efe30d7c50ab1" + name: recase + sha256: e4eb4ec2dcdee52dcf99cb4ceabaffc631d7424ee55e56f280bc039737f89213 url: "https://pub.dev" source: hosted - version: "2.3.0" - shared_preferences_web: + version: "4.1.0" + shelf: dependency: transitive description: - name: shared_preferences_web - sha256: "7347b194fb0bbeb4058e6a4e87ee70350b6b2b90f8ac5f8bd5b3a01548f6d33a" + name: shelf + sha256: ad29c505aee705f41a4d8963641f91ac4cee3c8fad5947e033390a7bd8180fa4 url: "https://pub.dev" source: hosted - version: "2.2.0" - shared_preferences_windows: + version: "1.4.1" + shelf_web_socket: dependency: transitive description: - name: shared_preferences_windows - sha256: f95e6a43162bce43c9c3405f3eb6f39e5b5d11f65fab19196cf8225e2777624d + name: shelf_web_socket + sha256: "073c147238594ecd0d193f3456a5fe91c4b0abbcc68bf5cd95b36c4e194ac611" url: "https://pub.dev" source: hosted - version: "2.3.0" + version: "2.0.0" sky_engine: dependency: transitive description: flutter source: sdk version: "0.0.99" + source_gen: + dependency: transitive + description: + name: source_gen + sha256: "14658ba5f669685cd3d63701d01b31ea748310f7ab854e471962670abcf57832" + url: "https://pub.dev" + source: hosted + version: "1.5.0" source_span: dependency: transitive description: name: source_span - sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250 + sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" url: "https://pub.dev" source: hosted - version: "1.9.1" + version: "1.10.0" + sqlite3: + dependency: transitive + description: + name: sqlite3 + sha256: bb174b3ec2527f9c5f680f73a89af8149dd99782fbb56ea88ad0807c5638f2ed + url: "https://pub.dev" + source: hosted + version: "2.4.7" + sqlite3_flutter_libs: + dependency: transitive + description: + name: sqlite3_flutter_libs + sha256: "7ae52b23366e5295005022e62fa093f64bfe190810223ea0ebf733a4cd140bce" + url: "https://pub.dev" + source: hosted + version: "0.5.26" + sqlparser: + dependency: transitive + description: + name: sqlparser + sha256: d77749237609784e337ec36c979d41f6f38a7b279df98622ae23929c8eb954a4 + url: "https://pub.dev" + source: hosted + version: "0.39.2" stack_trace: dependency: transitive description: name: stack_trace - sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 + sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" url: "https://pub.dev" source: hosted - version: "1.11.0" + version: "1.11.1" stream_channel: dependency: transitive description: name: stream_channel - sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" + sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.2" + stream_transform: + dependency: transitive + description: + name: stream_transform + sha256: "14a00e794c7c11aa145a170587321aedce29769c08d7f58b1d141da75e3b1c6f" + url: "https://pub.dev" + source: hosted + version: "2.1.0" string_scanner: dependency: transitive description: @@ -329,18 +678,26 @@ packages: dependency: transitive description: name: test_api - sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb + sha256: "5b8a98dafc4d5c4c9c72d8b31ab2b23fc13422348d2997120294d3bac86b4ddb" + url: "https://pub.dev" + source: hosted + version: "0.7.2" + timing: + dependency: transitive + description: + name: timing + sha256: "70a3b636575d4163c477e6de42f247a23b315ae20e86442bebe32d3cabf61c32" url: "https://pub.dev" source: hosted - version: "0.5.1" + version: "1.0.1" typed_data: dependency: transitive description: name: typed_data - sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c + sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006 url: "https://pub.dev" source: hosted - version: "1.3.2" + version: "1.4.0" vector_math: dependency: transitive description: @@ -349,22 +706,62 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.4" - win32: + vm_service: + dependency: transitive + description: + name: vm_service + sha256: "5c5f338a667b4c644744b661f309fb8080bb94b18a7e91ef1dbd343bed00ed6d" + url: "https://pub.dev" + source: hosted + version: "14.2.5" + watcher: + dependency: transitive + description: + name: watcher + sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8" + url: "https://pub.dev" + source: hosted + version: "1.1.0" + web: dependency: transitive description: - name: win32 - sha256: "9e82a402b7f3d518fb9c02d0e9ae45952df31b9bf34d77baf19da2de03fc2aaa" + name: web + sha256: cd3543bd5798f6ad290ea73d210f423502e71900302dde696f8bff84bf89a1cb url: "https://pub.dev" source: hosted - version: "5.0.7" + version: "1.1.0" + web_socket: + dependency: transitive + description: + name: web_socket + sha256: "3c12d96c0c9a4eec095246debcea7b86c0324f22df69893d538fcc6f1b8cce83" + url: "https://pub.dev" + source: hosted + version: "0.1.6" + web_socket_channel: + dependency: transitive + description: + name: web_socket_channel + sha256: "9f187088ed104edd8662ca07af4b124465893caf063ba29758f97af57e61da8f" + url: "https://pub.dev" + source: hosted + version: "3.0.1" xdg_directories: dependency: transitive description: name: xdg_directories - sha256: f0c26453a2d47aa4c2570c6a033246a3fc62da2fe23c7ffdd0a7495086dc0247 + sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15" + url: "https://pub.dev" + source: hosted + version: "1.1.0" + yaml: + dependency: transitive + description: + name: yaml + sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5" url: "https://pub.dev" source: hosted - version: "1.0.2" + version: "3.1.2" sdks: - dart: ">=3.0.6 <4.0.0" - flutter: ">=3.3.0" + dart: ">=3.5.0 <4.0.0" + flutter: ">=3.24.0" diff --git a/test/widget_test.dart b/test/widget_test.dart index 43d2fbe..b3afff2 100644 --- a/test/widget_test.dart +++ b/test/widget_test.dart @@ -5,15 +5,15 @@ // gestures. You can also use WidgetTester to find child widgets in the widget // tree, read text, and verify that the values of widget properties are correct. +import 'package:adventure_quest/app/app.dart'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; -import 'package:adventure_quest/main.dart'; void main() { testWidgets('Counter increments smoke test', (WidgetTester tester) async { // Build our app and trigger a frame. - await tester.pumpWidget(const MyApp()); + await tester.pumpWidget(const App()); // Verify that our counter starts at 0. expect(find.text('0'), findsOneWidget); From dc82a97099c477df40e9ff81ba5bae4b0771a237 Mon Sep 17 00:00:00 2001 From: ElNgatia Date: Sun, 3 Nov 2024 14:26:11 +0300 Subject: [PATCH 08/10] refactor: reorganize color scheme files and update activity model to use Drift database --- .../activity_remote_datasource.dart | 8 +-- lib/activity/data/model/activity.dart | 29 +--------- .../repository/activity_repository.dart | 9 ++- lib/app/app.dart | 2 +- .../config}/color_schemes.g.dart | 0 lib/database/app_database.g.dart | 34 ++++++------ lib/presentation/home.dart | 55 +++++++++++-------- lib/utils/activities_model.dart | 20 +------ 8 files changed, 60 insertions(+), 97 deletions(-) rename lib/{utils => app/config}/color_schemes.g.dart (100%) diff --git a/lib/activity/data/datasource/activity_remote_datasource.dart b/lib/activity/data/datasource/activity_remote_datasource.dart index 4c034f5..e9936e4 100644 --- a/lib/activity/data/datasource/activity_remote_datasource.dart +++ b/lib/activity/data/datasource/activity_remote_datasource.dart @@ -1,19 +1,19 @@ import 'dart:convert'; -import 'package:adventure_quest/activity/data/model/activity.dart'; +import 'package:adventure_quest/database/app_database.dart'; import 'package:http/http.dart' as http; abstract class ActivityRemoteDataSource { - Future fetchActivity(); + Future fetchActivity(); } class ActivityRemoteDataSourceImpl implements ActivityRemoteDataSource { @override - Future fetchActivity() async { + Future fetchActivity() async { try { final response = await http.get(Uri.parse('https://bored.api.lewagon.com/api/activity/')); - return ActivityModel.fromJson(json.decode(response.body)); + return ActivityData.fromJson(json.decode(response.body)); } catch (e) { rethrow; } diff --git a/lib/activity/data/model/activity.dart b/lib/activity/data/model/activity.dart index b3ab69d..0641569 100644 --- a/lib/activity/data/model/activity.dart +++ b/lib/activity/data/model/activity.dart @@ -1,37 +1,10 @@ import 'package:drift/drift.dart'; class Activity extends Table { - IntColumn get id => integer().autoIncrement()(); + IntColumn get id => integer().autoIncrement().nullable()(); TextColumn get activity => text()(); TextColumn get type => text()(); IntColumn get participants => integer()(); TextColumn get link => text()(); TextColumn get key => text().unique()(); } -class ActivityModel { - final int? id; - final String activity; - final String type; - final int participants; - final String link; - final String key; - - ActivityModel({ - this.id, - required this.activity, - required this.type, - required this.participants, - required this.link, - required this.key, - }); - - factory ActivityModel.fromJson(Map json) { - return ActivityModel( - activity: json['activity'] as String, - type: json['type'] as String, - participants: json['participants'] as int, - link: json['link'] as String, - key: json['key'] as String, - ); - } -} \ No newline at end of file diff --git a/lib/activity/repository/activity_repository.dart b/lib/activity/repository/activity_repository.dart index 782e271..f6c4071 100644 --- a/lib/activity/repository/activity_repository.dart +++ b/lib/activity/repository/activity_repository.dart @@ -1,11 +1,10 @@ import 'package:adventure_quest/activity/data/datasource/activity_local_datasource.dart'; import 'package:adventure_quest/activity/data/datasource/activity_remote_datasource.dart'; -import 'package:adventure_quest/activity/data/model/activity.dart'; import 'package:adventure_quest/database/app_database.dart'; abstract class ActivityRepository { // fetch, get, delete, save, basic crud with api calls too - Future fetchActivity(); + Future fetchActivity(); Future> getActivity(); Future saveActivity(activity); void deleteActivity(int id); @@ -18,7 +17,7 @@ class ActivityRepositoryImpl implements ActivityRepository { } @override - Future fetchActivity() async { + Future fetchActivity() async { return activityRemoteDataSource.fetchActivity(); } @@ -28,8 +27,8 @@ class ActivityRepositoryImpl implements ActivityRepository { } @override - Future saveActivity(activityCompanion) { - return activityLocalDataSource.addActivity(activityCompanion); + Future saveActivity(activityCompanion) async { + return await activityLocalDataSource.addActivity(activityCompanion); } } diff --git a/lib/app/app.dart b/lib/app/app.dart index 8fdc5da..771c08f 100644 --- a/lib/app/app.dart +++ b/lib/app/app.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import '../presentation/common_scaffold.dart'; -import '../utils/color_schemes.g.dart'; +import 'config/color_schemes.g.dart'; class App extends StatelessWidget { const App({super.key}); diff --git a/lib/utils/color_schemes.g.dart b/lib/app/config/color_schemes.g.dart similarity index 100% rename from lib/utils/color_schemes.g.dart rename to lib/app/config/color_schemes.g.dart diff --git a/lib/database/app_database.g.dart b/lib/database/app_database.g.dart index 0693236..b03a3ac 100644 --- a/lib/database/app_database.g.dart +++ b/lib/database/app_database.g.dart @@ -12,7 +12,7 @@ class $ActivityTable extends Activity static const VerificationMeta _idMeta = const VerificationMeta('id'); @override late final GeneratedColumn id = GeneratedColumn( - 'id', aliasedName, false, + 'id', aliasedName, true, hasAutoIncrement: true, type: DriftSqlType.int, requiredDuringInsert: false, @@ -105,7 +105,7 @@ class $ActivityTable extends Activity final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; return ActivityData( id: attachedDatabase.typeMapping - .read(DriftSqlType.int, data['${effectivePrefix}id'])!, + .read(DriftSqlType.int, data['${effectivePrefix}id']), activity: attachedDatabase.typeMapping .read(DriftSqlType.string, data['${effectivePrefix}activity'])!, type: attachedDatabase.typeMapping @@ -126,14 +126,14 @@ class $ActivityTable extends Activity } class ActivityData extends DataClass implements Insertable { - final int id; + final int? id; final String activity; final String type; final int participants; final String link; final String key; const ActivityData( - {required this.id, + {this.id, required this.activity, required this.type, required this.participants, @@ -142,7 +142,9 @@ class ActivityData extends DataClass implements Insertable { @override Map toColumns(bool nullToAbsent) { final map = {}; - map['id'] = Variable(id); + if (!nullToAbsent || id != null) { + map['id'] = Variable(id); + } map['activity'] = Variable(activity); map['type'] = Variable(type); map['participants'] = Variable(participants); @@ -153,7 +155,7 @@ class ActivityData extends DataClass implements Insertable { ActivityCompanion toCompanion(bool nullToAbsent) { return ActivityCompanion( - id: Value(id), + id: id == null && nullToAbsent ? const Value.absent() : Value(id), activity: Value(activity), type: Value(type), participants: Value(participants), @@ -166,7 +168,7 @@ class ActivityData extends DataClass implements Insertable { {ValueSerializer? serializer}) { serializer ??= driftRuntimeOptions.defaultSerializer; return ActivityData( - id: serializer.fromJson(json['id']), + id: serializer.fromJson(json['id']), activity: serializer.fromJson(json['activity']), type: serializer.fromJson(json['type']), participants: serializer.fromJson(json['participants']), @@ -178,7 +180,7 @@ class ActivityData extends DataClass implements Insertable { Map toJson({ValueSerializer? serializer}) { serializer ??= driftRuntimeOptions.defaultSerializer; return { - 'id': serializer.toJson(id), + 'id': serializer.toJson(id), 'activity': serializer.toJson(activity), 'type': serializer.toJson(type), 'participants': serializer.toJson(participants), @@ -188,14 +190,14 @@ class ActivityData extends DataClass implements Insertable { } ActivityData copyWith( - {int? id, + {Value id = const Value.absent(), String? activity, String? type, int? participants, String? link, String? key}) => ActivityData( - id: id ?? this.id, + id: id.present ? id.value : this.id, activity: activity ?? this.activity, type: type ?? this.type, participants: participants ?? this.participants, @@ -243,7 +245,7 @@ class ActivityData extends DataClass implements Insertable { } class ActivityCompanion extends UpdateCompanion { - final Value id; + final Value id; final Value activity; final Value type; final Value participants; @@ -288,7 +290,7 @@ class ActivityCompanion extends UpdateCompanion { } ActivityCompanion copyWith( - {Value? id, + {Value? id, Value? activity, Value? type, Value? participants, @@ -354,7 +356,7 @@ abstract class _$AppDatabase extends GeneratedDatabase { } typedef $$ActivityTableCreateCompanionBuilder = ActivityCompanion Function({ - Value id, + Value id, required String activity, required String type, required int participants, @@ -362,7 +364,7 @@ typedef $$ActivityTableCreateCompanionBuilder = ActivityCompanion Function({ required String key, }); typedef $$ActivityTableUpdateCompanionBuilder = ActivityCompanion Function({ - Value id, + Value id, Value activity, Value type, Value participants, @@ -478,7 +480,7 @@ class $$ActivityTableTableManager extends RootTableManager< createComputedFieldComposer: () => $$ActivityTableAnnotationComposer($db: db, $table: table), updateCompanionCallback: ({ - Value id = const Value.absent(), + Value id = const Value.absent(), Value activity = const Value.absent(), Value type = const Value.absent(), Value participants = const Value.absent(), @@ -494,7 +496,7 @@ class $$ActivityTableTableManager extends RootTableManager< key: key, ), createCompanionCallback: ({ - Value id = const Value.absent(), + Value id = const Value.absent(), required String activity, required String type, required int participants, diff --git a/lib/presentation/home.dart b/lib/presentation/home.dart index 8d43db3..af4fdeb 100644 --- a/lib/presentation/home.dart +++ b/lib/presentation/home.dart @@ -1,11 +1,9 @@ - - -import 'package:adventure_quest/activity/data/model/activity.dart'; import 'package:adventure_quest/activity/repository/activity_repository.dart'; +import 'package:adventure_quest/database/app_database.dart'; import 'package:adventure_quest/utils/activities_model.dart'; import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; import 'package:fluttertoast/fluttertoast.dart'; +import 'package:provider/provider.dart'; class Home extends StatefulWidget { const Home({super.key}); @@ -15,14 +13,7 @@ class Home extends StatefulWidget { } class _HomeState extends State { - final BoredApi _boredApi = BoredApi(); - ActivityModel? fetchedActivity; - - @override - void initState() { - super.initState(); - _getActivity(); - } + ActivityData? fetchedActivity; Future _getActivity() async { final newActivity = await activityRepository.fetchActivity(); @@ -31,11 +22,16 @@ class _HomeState extends State { }); } + @override + void initState() { + super.initState(); + _getActivity(); + } @override Widget build(BuildContext context) { return Scaffold( - body: Consumer( - builder: (context, activitiesModel, child) { + body: Consumer( + builder: (context, activities, child) { return Padding( padding: const EdgeInsets.all(8.0), child: Column( @@ -102,18 +98,29 @@ class _HomeState extends State { width: 10, ), ElevatedButton( - onPressed: () { + onPressed: () async { if (fetchedActivity != null) { - activityRepository.saveActivity(fetchedActivity); + try { + await activityRepository.saveActivity(fetchedActivity); - Fluttertoast.showToast( - msg: 'Added to favorites', - toastLength: Toast - .LENGTH_SHORT, // Duration for how long the toast should be displayed - gravity: ToastGravity.BOTTOM, // Position of the toast on the screen - backgroundColor: Colors.grey[600], // Background color of the toast - textColor: Colors.white, - ); + Fluttertoast.showToast( + msg: 'Added to favorites', + toastLength: Toast + .LENGTH_SHORT, // Duration for how long the toast should be displayed + gravity: ToastGravity.BOTTOM, // Position of the toast on the screen + backgroundColor: Colors.grey[600], // Background color of the toast + textColor: Colors.white, + ); + } on Exception { + Fluttertoast.showToast( + msg: 'Activity already exists in favorites', + toastLength: Toast + .LENGTH_LONG, // Duration for how long the toast should be displayed + gravity: ToastGravity.BOTTOM, // Position of the toast on the screen + backgroundColor: Colors.red[600], // Background color of the toast + textColor: Colors.white, + ); + } } }, child: const Text('Add to Favorites')), diff --git a/lib/utils/activities_model.dart b/lib/utils/activities_model.dart index 423ecc5..ddc222b 100644 --- a/lib/utils/activities_model.dart +++ b/lib/utils/activities_model.dart @@ -1,8 +1,6 @@ import 'package:flutter/material.dart'; -import 'dart:convert'; -import 'package:http/http.dart' as http; -class ActivitiesModel extends ChangeNotifier { +class ActivitiesNotifier extends ChangeNotifier { final Map _activities = {}; Map get activities => _activities; @@ -17,19 +15,3 @@ class ActivitiesModel extends ChangeNotifier { } } -class BoredApi { - Future> getActivity({String type = '', String participants = ''}) async { - const baseUrl = 'https://bored.api.lewagon.com/api/activity/'; - - final String url; - - url = '$baseUrl?type=$type'; - - var response = await http.get(Uri.parse(url)); - if (response.statusCode == 200) { - return json.decode(response.body); - } else { - throw Exception('Failed to load activity'); - } - } -} From 1a4054cfab415f2ff14cc2772fcf6e06bb7ae02c Mon Sep 17 00:00:00 2001 From: ElNgatia Date: Sun, 3 Nov 2024 14:47:16 +0300 Subject: [PATCH 09/10] refactor: rename ActivitiesModel to ActivitiesNotifier and update references in favorites --- lib/main.dart | 2 +- lib/presentation/favorites.dart | 11 +++-------- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 67b005f..cbc6f4e 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -10,7 +10,7 @@ void main() { runApp( ChangeNotifierProvider( create: (BuildContext context) { - return ActivitiesModel(); + return ActivitiesNotifier(); }, child: const App(), ), diff --git a/lib/presentation/favorites.dart b/lib/presentation/favorites.dart index bf1990a..ea0e5c0 100644 --- a/lib/presentation/favorites.dart +++ b/lib/presentation/favorites.dart @@ -3,7 +3,6 @@ import 'package:adventure_quest/database/app_database.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; - import '../utils/activities_model.dart'; class Favorites extends StatefulWidget { @@ -23,21 +22,17 @@ class _FavoritesState extends State { } Future _getFavorites() async { - final favoritesStringList =await activityLocalDataSource.getActivity(); + final favoritesStringList = await activityLocalDataSource.getActivity(); setState(() { favorites = favoritesStringList; }); } - Future _updateFavorites(List> updatedFavorite) async { - - } - @override Widget build(BuildContext context) { return Scaffold( - body: Consumer(builder: (builder, activitiesModel, child) { + body: Consumer(builder: (builder, activitiesModel, child) { final activities = activitiesModel.activities; return ListView.separated( @@ -54,7 +49,7 @@ class _FavoritesState extends State { activity.activity, ), subtitle: Text( - activity.type , + activity.type, style: const TextStyle(fontWeight: FontWeight.w500), ), trailing: Row( From a52b8bf06287acf346bdca70594a9252c35f05af Mon Sep 17 00:00:00 2001 From: ElNgatia Date: Sun, 3 Nov 2024 15:01:18 +0300 Subject: [PATCH 10/10] refactor: update activity deletion method to return a Future and simplify favorites handling --- .../datasource/activity_local_datasource.dart | 6 +++--- lib/presentation/favorites.dart | 16 +++------------- 2 files changed, 6 insertions(+), 16 deletions(-) diff --git a/lib/activity/data/datasource/activity_local_datasource.dart b/lib/activity/data/datasource/activity_local_datasource.dart index af91f72..c307b7a 100644 --- a/lib/activity/data/datasource/activity_local_datasource.dart +++ b/lib/activity/data/datasource/activity_local_datasource.dart @@ -9,13 +9,13 @@ abstract class ActivityLocalDataSource { class ActivityLocalDataSourceImpl implements ActivityLocalDataSource { @override - Future addActivity( activityCompanion) { + Future addActivity(activityCompanion) { return appDatabase.into(appDatabase.activity).insert(activityCompanion); } @override - void deleteActivity(int id) { - return appDatabase.delete(appDatabase.activity).where((tbl) => tbl.id.equals(id)); + Future deleteActivity(int id) { + return (appDatabase.delete(appDatabase.activity)..where((tbl) => tbl.id.equals(id))).go(); } @override diff --git a/lib/presentation/favorites.dart b/lib/presentation/favorites.dart index ea0e5c0..167a7b3 100644 --- a/lib/presentation/favorites.dart +++ b/lib/presentation/favorites.dart @@ -55,21 +55,11 @@ class _FavoritesState extends State { trailing: Row( mainAxisSize: MainAxisSize.min, children: [ - // IconButton( - // onPressed: () { - // - // }, - // icon: Icon(Icons.done), - // ), IconButton( icon: const Icon(Icons.cancel_outlined), - onPressed: () { - activitiesModel.removeActivity(activity.key); - - setState(() { - favorites.remove(activity); - }); - // _updateFavorites(favorites); + onPressed: () async { + activityLocalDataSource.deleteActivity(activity.id!); + _getFavorites(); }, ), ],