mirror of https://github.com/evanferrao/mynotes
mynotes: Implement CRUD operations using sqlite
This commit is contained in:
parent
68854afae6
commit
93164afa7c
|
|
@ -4,7 +4,8 @@ import 'package:flutter/material.dart';
|
|||
@immutable
|
||||
class AuthUser {
|
||||
final bool isEmailVerified;
|
||||
AuthUser({required this.isEmailVerified});
|
||||
const AuthUser({required this.isEmailVerified});
|
||||
|
||||
factory AuthUser.fromFirebase(User user) => AuthUser(isEmailVerified: user.emailVerified);
|
||||
factory AuthUser.fromFirebase(User user) =>
|
||||
AuthUser(isEmailVerified: user.emailVerified);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,17 @@
|
|||
class DatabaseAlreadyOpenException implements Exception {}
|
||||
|
||||
class UnableToGetDocumentsDirectory implements Exception {}
|
||||
|
||||
class DatebaseNotOpen implements Exception {}
|
||||
|
||||
class CouldNotDeleteUser implements Exception {}
|
||||
|
||||
class UserAlreadyExists implements Exception {}
|
||||
|
||||
class CouldNotFindUser implements Exception {}
|
||||
|
||||
class CouldNotDeleteNote implements Exception {}
|
||||
|
||||
class CouldNotFindNote implements Exception {}
|
||||
|
||||
class CouldNotUpdateNote implements Exception {}
|
||||
|
|
@ -0,0 +1,272 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:mynotes/services/crud/crud_crudexceptions.dart';
|
||||
import 'package:sqflite/sqflite.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:path/path.dart';
|
||||
|
||||
class NotesService {
|
||||
Database? _db;
|
||||
|
||||
Future<DatabaseNote> updateNote({
|
||||
required DatabaseNote note,
|
||||
required String text,
|
||||
}) async {
|
||||
final db = _getDatabaseOrThrow();
|
||||
await getNote(id: note.id);
|
||||
final updatesCount = await db.update(noteTable, {
|
||||
textColumn: text,
|
||||
isSyncedWithCloudColumn: 0,
|
||||
});
|
||||
|
||||
if (updatesCount == 0) {
|
||||
throw CouldNotUpdateNote();
|
||||
} else {
|
||||
return await getNote(id: note.id);
|
||||
}
|
||||
}
|
||||
|
||||
Future<Iterable<DatabaseNote>> getAllNote({required int id}) async {
|
||||
final db = _getDatabaseOrThrow();
|
||||
final notes = await db.query(
|
||||
noteTable,
|
||||
);
|
||||
return notes.map((noteRow) => DatabaseNote.fromRow(noteRow));
|
||||
// where is noteRow coming from?
|
||||
// The noteRow variable is a parameter of the map method. The map method is called on the notes list, which is a list of rows returned by the query method. The map method takes a function as an argument and applies that function to each element of the list. In this case, the function is an anonymous function that takes a row as a parameter and returns a DatabaseNote object created from that row.
|
||||
// what is the type of noteRow?
|
||||
// The type of noteRow is Map<String, Object?>. This is the type of the rows returned by the query method. Each row is a map where the keys are column names and the values are the corresponding values in the row.
|
||||
// but noteRow is not defined in the function getAllNote?
|
||||
// The noteRow variable is a parameter of the anonymous function passed to the map method. The map method applies the function to each element of the list and passes the element as an argument to the function. In this case, the element is a row returned by the query method, and the function creates a DatabaseNote object from that row.
|
||||
}
|
||||
|
||||
Future<DatabaseNote> getNote({required int id}) async {
|
||||
final db = _getDatabaseOrThrow();
|
||||
final notes = await db.query(
|
||||
noteTable,
|
||||
limit: 1,
|
||||
where: '$idColumn = ?',
|
||||
whereArgs: [id],
|
||||
);
|
||||
if (notes.isEmpty) {
|
||||
throw CouldNotFindNote();
|
||||
} else {
|
||||
return DatabaseNote.fromRow(notes.first);
|
||||
}
|
||||
}
|
||||
|
||||
Future<int> deleteAllNotes() async {
|
||||
final db = _getDatabaseOrThrow();
|
||||
return await db.delete(noteTable);
|
||||
}
|
||||
|
||||
Future<void> deleteNote({required int id}) async {
|
||||
final db = _getDatabaseOrThrow();
|
||||
final deletedCount = await db.delete(
|
||||
noteTable,
|
||||
where: '$idColumn = ?',
|
||||
whereArgs: [id],
|
||||
);
|
||||
if (deletedCount == 0) {
|
||||
throw CouldNotDeleteNote();
|
||||
}
|
||||
}
|
||||
|
||||
Future<DatabaseNote> createNote({required DatabaseUser owner}) async {
|
||||
final db = _getDatabaseOrThrow();
|
||||
final dbUser = await getUser(email: owner.email);
|
||||
|
||||
// make sure owner exists in the database with the correct id
|
||||
if (dbUser != owner) {
|
||||
throw CouldNotFindUser();
|
||||
}
|
||||
|
||||
const text = '';
|
||||
// create the note
|
||||
final noteId = await db.insert(noteTable, {
|
||||
userIdColumn: owner.id,
|
||||
textColumn: text,
|
||||
isSyncedWithCloudColumn: 1,
|
||||
});
|
||||
|
||||
final note = DatabaseNote(
|
||||
id: noteId,
|
||||
userId: owner.id,
|
||||
text: text,
|
||||
isSyncedWithCloud: true,
|
||||
);
|
||||
return note;
|
||||
}
|
||||
|
||||
Future<DatabaseUser> getUser({required String email}) async {
|
||||
final db = _getDatabaseOrThrow();
|
||||
final user = await db.query(
|
||||
userTable,
|
||||
limit: 1,
|
||||
where: '$emailColumn = ?',
|
||||
whereArgs: [email.toLowerCase()],
|
||||
);
|
||||
if (user.isEmpty) {
|
||||
throw UserAlreadyExists();
|
||||
} else {
|
||||
return DatabaseUser.fromRow(user.first);
|
||||
}
|
||||
}
|
||||
|
||||
Future<DatabaseUser> createUser({required String email}) async {
|
||||
final db = _getDatabaseOrThrow();
|
||||
final results = await db.query(
|
||||
userTable,
|
||||
limit: 1,
|
||||
where: '$emailColumn = ?',
|
||||
whereArgs: [email.toLowerCase()],
|
||||
);
|
||||
if (results.isNotEmpty) {
|
||||
throw UserAlreadyExists();
|
||||
}
|
||||
|
||||
final userId = await db.insert(
|
||||
userTable,
|
||||
{emailColumn: email.toLowerCase()},
|
||||
);
|
||||
return DatabaseUser(id: userId, email: email);
|
||||
}
|
||||
|
||||
Future<void> deleteUser({required String email}) async {
|
||||
final db = _getDatabaseOrThrow();
|
||||
final deletedCount = await db.delete(
|
||||
userTable,
|
||||
where: '$emailColumn = ?',
|
||||
whereArgs: [email.toLowerCase()],
|
||||
);
|
||||
if (deletedCount != 1) {
|
||||
throw CouldNotDeleteUser();
|
||||
}
|
||||
}
|
||||
|
||||
Database _getDatabaseOrThrow() {
|
||||
final db = _db;
|
||||
if (db == null) {
|
||||
throw DatebaseNotOpen();
|
||||
} else {
|
||||
return db;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> close() async {
|
||||
final db = _db;
|
||||
if (db == null) {
|
||||
throw DatebaseNotOpen();
|
||||
} else {
|
||||
await db.close();
|
||||
_db = null;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> open() async {
|
||||
if (_db != null) {
|
||||
throw DatabaseAlreadyOpenException();
|
||||
}
|
||||
try {
|
||||
final docsPath = await getApplicationDocumentsDirectory();
|
||||
final dbPath = join(docsPath.path, dbName);
|
||||
final db = await openDatabase(dbPath);
|
||||
_db = db;
|
||||
|
||||
// Create the user tables if they don't exist
|
||||
await db.execute(createUserTable);
|
||||
// Create the notes tables if they don't exist
|
||||
await db.execute(createnoteTable);
|
||||
} on MissingPlatformDirectoryException {
|
||||
throw UnableToGetDocumentsDirectory();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@immutable
|
||||
class DatabaseUser {
|
||||
final int id;
|
||||
final String email;
|
||||
const DatabaseUser({
|
||||
required this.id,
|
||||
required this.email,
|
||||
});
|
||||
|
||||
DatabaseUser.fromRow(Map<String, Object?> map)
|
||||
// why Object? and not Object
|
||||
// The Object? type allows the value to be null. If the value is null, the map[idColumn] as int expression will throw an exception. If the value is not null, the map[idColumn] as int expression will return the value as an int.
|
||||
: id = map[idColumn] as int,
|
||||
email = map[emailColumn] as String;
|
||||
// where is the fromRow method?
|
||||
// The fromRow method is a factory constructor that creates a DatabaseUser object from a row in the database.
|
||||
// What is a factory constructor?
|
||||
// A factory constructor is a constructor that returns an instance of a class. It is used to create objects of a class without exposing the constructor to the outside world.
|
||||
// so can i call fromRow anything? or does it have to be fromRow?
|
||||
// You can call the factory constructor anything you want. The name fromRow is a convention used to indicate that the method creates an object from a row in a database.
|
||||
// can i name it fromMyRow or fromDatabaseRow?
|
||||
// Yes, you can name it fromMyRow. The name of the factory constructor is up to you, but it is a good practice to use a name that describes what the method does.
|
||||
|
||||
@override
|
||||
String toString() => 'Person, ID = $id, email = $email';
|
||||
|
||||
@override
|
||||
bool operator ==(covariant DatabaseUser other) => id == other.id;
|
||||
|
||||
@override
|
||||
int get hashCode => id.hashCode;
|
||||
}
|
||||
|
||||
class DatabaseNote {
|
||||
final int id;
|
||||
final int userId;
|
||||
final String text;
|
||||
final bool isSyncedWithCloud;
|
||||
|
||||
const DatabaseNote({
|
||||
required this.id,
|
||||
required this.userId,
|
||||
required this.text,
|
||||
required this.isSyncedWithCloud,
|
||||
});
|
||||
|
||||
DatabaseNote.fromRow(Map<String, Object?> map)
|
||||
// what does fromRow do?
|
||||
// The fromRow method is a factory constructor that creates a DatabaseNote object from a row in the database.
|
||||
: id = map[idColumn] as int,
|
||||
userId = map[userIdColumn] as int,
|
||||
text = map[textColumn] as String,
|
||||
isSyncedWithCloud =
|
||||
(map[isSyncedWithCloudColumn] as int) == 1 ? true : false;
|
||||
// isSyncedWithCloud = map[isSyncedWithCloudColumn] as bool;
|
||||
// what is the difference between the two lines above?
|
||||
// The first line converts the value of the isSyncedWithCloudColumn to a boolean value by checking if it is equal to 1. If it is equal to 1, it sets the value to true; otherwise, it sets it to false.
|
||||
//The second line assumes that the value of the isSyncedWithCloudColumn is already a boolean value and assigns it directly to the isSyncedWithCloud property.
|
||||
@override
|
||||
String toString() =>
|
||||
'Note, ID = $id, userId = $userId, isSyncedWithCloud = $isSyncedWithCloud, text = $text';
|
||||
}
|
||||
|
||||
const dbName = 'notes.db';
|
||||
const noteTable = 'notes';
|
||||
const userTable = 'user';
|
||||
const idColumn = 'id';
|
||||
const emailColumn = 'email';
|
||||
const userIdColumn = 'user_id';
|
||||
const textColumn = 'text';
|
||||
const isSyncedWithCloudColumn = 'is_synced_with_cloud';
|
||||
const createUserTable = '''
|
||||
CREATE TABLE IF NOT EXISTS $userTable (
|
||||
$idColumn INTEGER NOT NULL,
|
||||
$emailColumn TEXT NOT NULL UNIQUE,
|
||||
PRIMARY KEY ($idColumn AUTOINCREMENT)
|
||||
);
|
||||
''';
|
||||
const createnoteTable = '''
|
||||
CREATE TABLE IF NOT EXISTS $noteTable (
|
||||
$idColumn INTEGER NOT NULL,
|
||||
$userIdColumn INTEGER NOT NULL,
|
||||
$textColumn TEXT,
|
||||
$isSyncedWithCloudColumn INTEGER NOT NULL DEFAULT 0,
|
||||
FOREIGN KEY ($userIdColumn) REFERENCES $userTable($idColumn),
|
||||
PRIMARY KEY ($idColumn AUTOINCREMENT)
|
||||
);
|
||||
''';
|
||||
|
|
@ -9,10 +9,14 @@ import cloud_firestore
|
|||
import firebase_analytics
|
||||
import firebase_auth
|
||||
import firebase_core
|
||||
import path_provider_foundation
|
||||
import sqflite
|
||||
|
||||
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||
FLTFirebaseFirestorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseFirestorePlugin"))
|
||||
FLTFirebaseAnalyticsPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseAnalyticsPlugin"))
|
||||
FLTFirebaseAuthPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseAuthPlugin"))
|
||||
FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin"))
|
||||
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
|
||||
SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin"))
|
||||
}
|
||||
|
|
|
|||
148
pubspec.lock
148
pubspec.lock
|
|
@ -13,10 +13,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: _flutterfire_internals
|
||||
sha256: a315d1c444402c3fa468de626d33a1c666041c87e9e195e8fb355b7084aefcc1
|
||||
sha256: b46f62516902afb04befa4b30eb6a12ac1f58ca8cb25fb9d632407259555dd3d
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.3.38"
|
||||
version: "1.3.39"
|
||||
analyzer:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -69,26 +69,26 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: cloud_firestore
|
||||
sha256: "1232370ad04c21c699d0e73b2dc2e1c3b49258f89a16f0119036fd3c6e8aa2f5"
|
||||
sha256: "240c1c3598e62ad58ee665b6df9c65172d2fbe4742770c21ed060e013cb8e037"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.0.2"
|
||||
version: "5.1.0"
|
||||
cloud_firestore_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: cloud_firestore_platform_interface
|
||||
sha256: cfc64ae4a48bbb0ff6730b04f2d4653043c7a9b9008a991b1f2012a534b79e26
|
||||
sha256: "5b5a9c2b5a85bf995f12e7447c4197d7ad659533d642d3d904ccbb509f83d62a"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.2.8"
|
||||
version: "6.2.9"
|
||||
cloud_firestore_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: cloud_firestore_web
|
||||
sha256: "3db4e4c10feae18d80da86982781578c8e76cb6a43cf83110d8d6a62af9a952a"
|
||||
sha256: "898e9f65548df65ca7b2cff9f32cf233424ceccff1d870b8819ea2b8050d5b39"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.0.2"
|
||||
version: "4.0.3"
|
||||
collection:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -137,6 +137,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.3.1"
|
||||
ffi:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: ffi
|
||||
sha256: "493f37e7df1804778ff3a53bd691d8692ddf69702cf4c1c1096a2e41b4779e21"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.2"
|
||||
file:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -149,58 +157,58 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: firebase_analytics
|
||||
sha256: "726596f4ac3352978238274c33234435e61bdb811484ea3d6a2b857bf47a2715"
|
||||
sha256: "2017da2cb0745fa912e13aadfc94e49691796cf6b7ed37edbca2a2388713da11"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "11.1.0"
|
||||
version: "11.2.0"
|
||||
firebase_analytics_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: firebase_analytics_platform_interface
|
||||
sha256: db445c727aa38038f91a3c6f6873d045a6740c79d03c0b6c61959e0c6ecfd771
|
||||
sha256: "4ea00fe31ff74c92c613e082193b55bd21f0653b536dd77cc1ba4cf60771d214"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.1.0"
|
||||
version: "4.2.0"
|
||||
firebase_analytics_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: firebase_analytics_web
|
||||
sha256: "49a8a5ca0bf7fd7541e4b0915b8eb99816edc7a610d5078b89ae013a813fd567"
|
||||
sha256: e5ce84f0c4e6fb8f8ca673d009445938a61845d8fa6b42c11913d5bbdbedf300
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.5.8"
|
||||
version: "0.5.9"
|
||||
firebase_auth:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: firebase_auth
|
||||
sha256: "087fdcb54b0af6f4c5c756e1db4f90e9b65871b9b3a75fabaa0e0ee578301669"
|
||||
sha256: a41b56878fa6aef3ea52962329b47eee333672d4b0ecc406e071b9fc729f242c
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.1.1"
|
||||
version: "5.1.2"
|
||||
firebase_auth_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: firebase_auth_platform_interface
|
||||
sha256: "8fac689f71ac3489a785579e99a4bad24a93ad3d78c313fb786ee517012d25f1"
|
||||
sha256: d1c68097588f3b75ef79a22102ff96c311735c254353bccf6824d19f1a7e86b9
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "7.4.1"
|
||||
version: "7.4.2"
|
||||
firebase_auth_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: firebase_auth_web
|
||||
sha256: "486b2527fcfcab01278378d8d4791f4f7bee8a9f15bf35e801ba08fbdd84c234"
|
||||
sha256: e66ec0ae5697ee39ccd4865d6887cb0df220dd4ea0b21404910c68ca4c1a731a
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.12.3"
|
||||
version: "5.12.4"
|
||||
firebase_core:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: firebase_core
|
||||
sha256: "1e06b0538ab3108a61d895ee16951670b491c4a94fce8f2d30e5de7a5eca4b28"
|
||||
sha256: "5159984ce9b70727473eb388394650677c02c925aaa6c9439905e1f30966a4d5"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.1"
|
||||
version: "3.2.0"
|
||||
firebase_core_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -213,10 +221,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: firebase_core_web
|
||||
sha256: "6643fe3dbd021e6ccfb751f7882b39df355708afbdeb4130fc50f9305a9d1a3d"
|
||||
sha256: "23509cb3cddfb3c910c143279ac3f07f06d3120f7d835e4a5d4b42558e978712"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.17.2"
|
||||
version: "2.17.3"
|
||||
flutter:
|
||||
dependency: "direct main"
|
||||
description: flutter
|
||||
|
|
@ -377,13 +385,69 @@ packages:
|
|||
source: hosted
|
||||
version: "2.1.0"
|
||||
path:
|
||||
dependency: transitive
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: path
|
||||
sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.9.0"
|
||||
path_provider:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: path_provider
|
||||
sha256: c9e7d3a4cd1410877472158bee69963a4579f78b68c65a2b7d40d1a7a88bb161
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.3"
|
||||
path_provider_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_android
|
||||
sha256: "30c5aa827a6ae95ce2853cdc5fe3971daaac00f6f081c419c013f7f57bff2f5e"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.2.7"
|
||||
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: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.2.1"
|
||||
path_provider_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_platform_interface
|
||||
sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.2"
|
||||
path_provider_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_windows
|
||||
sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.3.0"
|
||||
platform:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: platform
|
||||
sha256: "9b71283fc13df574056616011fb138fd3b793ea47cc509c189a6c3fa5f8a1a65"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.5"
|
||||
plugin_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -469,6 +533,22 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.10.0"
|
||||
sqflite:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: sqflite
|
||||
sha256: a43e5a27235518c03ca238e7b4732cf35eabe863a369ceba6cbefa537a66f16d
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.3.3+1"
|
||||
sqflite_common:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: sqflite_common
|
||||
sha256: "3da423ce7baf868be70e2c0976c28a1bb2f73644268b7ffa7d2e08eab71f16a4"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.5.4"
|
||||
stack_trace:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -493,6 +573,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
synchronized:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: synchronized
|
||||
sha256: "539ef412b170d65ecdafd780f924e5be3f60032a1128df156adad6c5b373d558"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.0+1"
|
||||
term_glyph:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -581,6 +669,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.1"
|
||||
xdg_directories:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: xdg_directories
|
||||
sha256: faea9dee56b520b55a566385b84f2e8de55e7496104adada9962e0bd11bcff1d
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.4"
|
||||
yaml:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -591,4 +687,4 @@ packages:
|
|||
version: "3.1.2"
|
||||
sdks:
|
||||
dart: ">=3.4.1 <4.0.0"
|
||||
flutter: ">=3.18.0-18.0.pre.54"
|
||||
flutter: ">=3.22.0"
|
||||
|
|
|
|||
|
|
@ -39,6 +39,9 @@ dependencies:
|
|||
firebase_auth: ^5.1.1
|
||||
cloud_firestore: ^5.0.2
|
||||
firebase_analytics: ^11.1.0
|
||||
sqflite: ^2.3.3+1
|
||||
path_provider: ^2.1.3
|
||||
path: ^1.9.0
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
|
|
|||
Loading…
Reference in New Issue