convert to dao calls, prep for migration strategy and first start db seed

This commit is contained in:
Joshua Burman 2024-12-20 13:56:26 -05:00
parent 67d7a374d4
commit 5d27744ead
11 changed files with 90 additions and 63 deletions

View File

@ -9,6 +9,10 @@
# packages, and plugins designed to encourage good coding practices. # packages, and plugins designed to encourage good coding practices.
include: package:flutter_lints/flutter.yaml include: package:flutter_lints/flutter.yaml
analyzer:
exclude:
- "**/*.g.dart"
linter: linter:
# The lint rules applied to this project can be customized in the # The lint rules applied to this project can be customized in the
# section below to disable rules from the `package:flutter_lints/flutter.yaml` # section below to disable rules from the `package:flutter_lints/flutter.yaml`

View File

@ -2,6 +2,7 @@ import 'package:drift/drift.dart';
import 'package:drift_flutter/drift_flutter.dart'; import 'package:drift_flutter/drift_flutter.dart';
import 'package:sendtrain/database/daos/activities_dao.dart'; import 'package:sendtrain/database/daos/activities_dao.dart';
import 'package:sendtrain/database/daos/sessions_dao.dart'; import 'package:sendtrain/database/daos/sessions_dao.dart';
import 'package:sendtrain/database/seed.dart';
part 'database.g.dart'; part 'database.g.dart';
@ -125,6 +126,16 @@ class AppDatabase extends _$AppDatabase {
@override @override
int get schemaVersion => 1; int get schemaVersion => 1;
@override
MigrationStrategy get migration {
return MigrationStrategy(
onCreate: (m) async {
await m.createAll(); // create all tables
await seedDb(); // seed the tables
}
);
}
static QueryExecutor _openConnection() { static QueryExecutor _openConnection() {
// `driftDatabase` from `package:drift_flutter` stores the database in // `driftDatabase` from `package:drift_flutter` stores the database in
// `getApplicationDocumentsDirectory()`. // `getApplicationDocumentsDirectory()`.

View File

@ -3,7 +3,7 @@ import 'dart:math';
import 'package:drift/drift.dart'; import 'package:drift/drift.dart';
import 'package:sendtrain/database/database.dart'; import 'package:sendtrain/database/database.dart';
void seedDb() { Future<void> seedDb() async {
final database = AppDatabase(); final database = AppDatabase();
// seed data setup // seed data setup

View File

@ -1,5 +1,6 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:sendtrain/database/database.dart';
import 'package:sendtrain/models/activity_timer_model.dart'; import 'package:sendtrain/models/activity_timer_model.dart';
import 'package:sendtrain/screens/activities_screen.dart'; import 'package:sendtrain/screens/activities_screen.dart';
import 'package:sendtrain/screens/sessions_screen.dart'; import 'package:sendtrain/screens/sessions_screen.dart';
@ -11,7 +12,6 @@ class SendTrain extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
// seedDb();
return MaterialApp( return MaterialApp(
title: "Sendtrain", title: "Sendtrain",
theme: ThemeData.dark(useMaterial3: true), theme: ThemeData.dark(useMaterial3: true),
@ -93,10 +93,13 @@ class _AppState extends State<App> {
} }
void main() { void main() {
runApp( runApp(MultiProvider(
ChangeNotifierProvider( providers: [
create: (context) => ActivityTimerModel(), ChangeNotifierProvider(create: (context) => ActivityTimerModel()),
child: const SendTrain(), Provider<AppDatabase>(
), create: (context) => AppDatabase(),
); dispose: (context, db) => db.close()),
],
child: const SendTrain(),
));
} }

View File

@ -2,11 +2,13 @@ import 'dart:async';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:scrollable_positioned_list/scrollable_positioned_list.dart'; import 'package:scrollable_positioned_list/scrollable_positioned_list.dart';
import 'package:sendtrain/database/database.dart';
import 'package:sendtrain/models/activity_model.dart'; import 'package:sendtrain/models/activity_model.dart';
class ActivityTimerModel with ChangeNotifier { class ActivityTimerModel with ChangeNotifier {
int _actionCounter = 0; int _actionCounter = 0;
ActivityModel? _activity; ActivityModel? _activityModel;
Activity? _activity;
List _sets = []; List _sets = [];
int _currentActionNum = 0; int _currentActionNum = 0;
int _currentSetNum = 0; int _currentSetNum = 0;
@ -20,20 +22,21 @@ class ActivityTimerModel with ChangeNotifier {
dynamic get currentAction => currentSet[_currentActionNum]; dynamic get currentAction => currentSet[_currentActionNum];
int get currentSetNum => _currentSetNum; int get currentSetNum => _currentSetNum;
dynamic get currentSet => _sets[_currentSetNum]; dynamic get currentSet => _sets[_currentSetNum];
ActivityModel? get activity => _activity; ActivityModel? get activityModel => _activityModel;
Activity? get activity => _activity;
List get sets => _sets; List get sets => _sets;
Timer? get periodicTimer => _periodicTimer; Timer? get periodicTimer => _periodicTimer;
bool get isActive => _isActive(); bool get isActive => _isActive();
double get progress => _progress; double get progress => _progress;
int get totalTime => _totalTime; int get totalTime => _totalTime;
void setup(ActivityModel activity) { void setup(ActivityModel activityModel) {
if (_activity == null || activity.id != _activity?.id) { if (_activityModel == null || activityModel.id != _activityModel?.id) {
_periodicTimer?.cancel(); _periodicTimer?.cancel();
_progress = 0; _progress = 0;
_isc = null; _isc = null;
_activity = activity; _activityModel = activityModel;
_sets = activity.actions[0].items(); _sets = activityModel.actions[0].items();
_currentActionNum = 0; _currentActionNum = 0;
_currentSetNum = 0; _currentSetNum = 0;
setActionCount(); setActionCount();

View File

@ -1,19 +1,18 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:sendtrain/database/daos/sessions_dao.dart'; import 'package:sendtrain/database/daos/sessions_dao.dart';
import 'package:sendtrain/database/database.dart'; import 'package:sendtrain/database/database.dart';
import '../widgets/session_card.dart'; import '../widgets/session_card.dart';
class SessionsScreen extends StatelessWidget { class SessionsScreen extends StatelessWidget {
final AppDatabase database = AppDatabase(); const SessionsScreen({super.key});
SessionsScreen({super.key});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return FutureBuilder<List<Session>>( return FutureBuilder<List<Session>>(
future: SessionsDao(database).all(), future: SessionsDao(Provider.of<AppDatabase>(context)).all(),
builder: (context, snapshot) { builder: (context, snapshot) {
if (snapshot.hasData) { if (snapshot.hasData) {
database.close();
final sessions = snapshot.data!; final sessions = snapshot.data!;
final pending = sessions.where((session) => final pending = sessions.where((session) =>
session.status == SessionStatus.completed || session.status == SessionStatus.completed ||
@ -28,8 +27,6 @@ class SessionsScreen extends StatelessWidget {
Widget upcomingSession = SessionCard(session: upcoming); Widget upcomingSession = SessionCard(session: upcoming);
Widget currentSession = SessionCard(session: current); Widget currentSession = SessionCard(session: current);
database.close();
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[ children: <Widget>[
@ -66,7 +63,13 @@ class SessionsScreen extends StatelessWidget {
], ],
); );
} else { } else {
return const CircularProgressIndicator(); return Container(
alignment: Alignment.center,
child: SizedBox(
height: 50.0,
width: 50.0,
child: CircularProgressIndicator(),
));
} }
}); });
} }

View File

@ -25,7 +25,7 @@ class ActivityActionViewState extends State<ActivityActionView> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
ActivityTimerModel atm = ActivityTimerModel atm =
Provider.of<ActivityTimerModel>(context, listen: true); Provider.of<ActivityTimerModel>(context, listen: true);
List<List<Map<String, dynamic>>> sets = atm.activity!.actions[0].items(); List<List<Map<String, dynamic>>> sets = atm.activityModel!.actions[0].items();
// we need to set the scroll controller // we need to set the scroll controller
// so we can update the selected item position // so we can update the selected item position

View File

@ -36,28 +36,28 @@ class ActivityCardState extends State<ActivityCard> {
: Theme.of(context).colorScheme.surfaceContainerLow, : Theme.of(context).colorScheme.surfaceContainerLow,
clipBehavior: Clip.hardEdge, clipBehavior: Clip.hardEdge,
child: InkWell( child: InkWell(
// onTap: () => showGeneralDialog( onTap: () => showGeneralDialog(
// barrierColor: Colors.black.withOpacity(0.5), barrierColor: Colors.black.withOpacity(0.5),
// transitionDuration: const Duration(milliseconds: 220), transitionDuration: const Duration(milliseconds: 220),
// transitionBuilder: (BuildContext context, transitionBuilder: (BuildContext context,
// Animation<double> animation, Animation<double> animation,
// Animation<double> secondaryAnimation, Animation<double> secondaryAnimation,
// Widget child) { Widget child) {
// Animation<Offset> custom = Tween<Offset>( Animation<Offset> custom = Tween<Offset>(
// begin: const Offset(0.0, 1.0), begin: const Offset(0.0, 1.0),
// end: const Offset(0.0, 0.0)) end: const Offset(0.0, 0.0))
// .animate(animation); .animate(animation);
// return SlideTransition( return SlideTransition(
// position: custom, position: custom,
// child: Dialog.fullscreen( child: Dialog.fullscreen(
// child: ActivityView(activity: widget.activity))); child: ActivityView(activity: widget.activity)));
// }, },
// barrierDismissible: true, barrierDismissible: true,
// barrierLabel: '', barrierLabel: '',
// context: context, context: context,
// pageBuilder: (context, animation1, animation2) { pageBuilder: (context, animation1, animation2) {
// return Container(); return Container();
// }), }),
child: Column( child: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: <Widget>[ children: <Widget>[
@ -65,6 +65,7 @@ class ActivityCardState extends State<ActivityCard> {
leading: Padding( leading: Padding(
padding: const EdgeInsets.fromLTRB(0, 0, 0, 0), padding: const EdgeInsets.fromLTRB(0, 0, 0, 0),
child: Container( child: Container(
padding: EdgeInsets.only(top: 5, bottom: 5),
width: 60, width: 60,
decoration: BoxDecoration( decoration: BoxDecoration(
image: DecorationImage( image: DecorationImage(

View File

@ -1,8 +1,8 @@
import 'package:drift/drift.dart' hide Column;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_expandable_fab/flutter_expandable_fab.dart'; import 'package:flutter_expandable_fab/flutter_expandable_fab.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
import 'package:intl/date_symbol_data_local.dart'; import 'package:intl/date_symbol_data_local.dart';
import 'package:provider/provider.dart';
import 'package:sendtrain/database/daos/activities_dao.dart'; import 'package:sendtrain/database/daos/activities_dao.dart';
import 'package:sendtrain/database/database.dart'; import 'package:sendtrain/database/database.dart';
@ -12,11 +12,10 @@ import 'package:sendtrain/widgets/session_view_activities.dart';
import 'package:sendtrain/widgets/session_view_media.dart'; import 'package:sendtrain/widgets/session_view_media.dart';
class SessionView extends StatelessWidget { class SessionView extends StatelessWidget {
SessionView({super.key, required this.data, required this.session}); const SessionView({super.key, required this.data, required this.session});
final SessionModel data; final SessionModel data;
final Session session; final Session session;
final AppDatabase database = AppDatabase();
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -24,11 +23,10 @@ class SessionView extends StatelessWidget {
final DateFormat dateFormat = DateFormat('yyyy-MM-dd'); final DateFormat dateFormat = DateFormat('yyyy-MM-dd');
return FutureBuilder<List<Activity>>( return FutureBuilder<List<Activity>>(
future: ActivitiesDao(database).sessionActivities(session.id), future: ActivitiesDao(Provider.of<AppDatabase>(context)).sessionActivities(session.id),
builder: (context, snapshot) { builder: (context, snapshot) {
if (snapshot.hasData) { if (snapshot.hasData) {
final activities = snapshot.data!; final activities = snapshot.data!;
database.close();
return Scaffold( return Scaffold(
floatingActionButtonLocation: ExpandableFab.location, floatingActionButtonLocation: ExpandableFab.location,
floatingActionButton: ExpandableFab( floatingActionButton: ExpandableFab(
@ -84,7 +82,7 @@ class SessionView extends StatelessWidget {
style: TextStyle( style: TextStyle(
fontSize: 20, fontWeight: FontWeight.bold), fontSize: 20, fontWeight: FontWeight.bold),
'Media:')), 'Media:')),
SessionViewMedia(session: session, media: data.media), SessionViewMedia(session: session),
const Padding( const Padding(
padding: EdgeInsets.fromLTRB(15, 30, 0, 10), padding: EdgeInsets.fromLTRB(15, 30, 0, 10),
child: Text( child: Text(
@ -96,7 +94,13 @@ class SessionView extends StatelessWidget {
], ],
)); ));
} else { } else {
return const CircularProgressIndicator(); return Container(
alignment: Alignment.center,
child: SizedBox(
height: 50.0,
width: 50.0,
child: CircularProgressIndicator(),
));
} }
}); });
} }

View File

@ -1,12 +1,12 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:sendtrain/database/daos/session_activities_dao.dart'; import 'package:sendtrain/database/daos/session_activities_dao.dart';
import 'package:sendtrain/database/database.dart'; import 'package:sendtrain/database/database.dart';
class SessionViewAchievements extends StatelessWidget { class SessionViewAchievements extends StatelessWidget {
SessionViewAchievements({super.key, required this.session}); const SessionViewAchievements({super.key, required this.session});
final Session session; final Session session;
final AppDatabase database = AppDatabase();
List<String> getAchievements(List<SessionActivity> sessionActivities) { List<String> getAchievements(List<SessionActivity> sessionActivities) {
List<String> achievements = []; List<String> achievements = [];
@ -26,12 +26,12 @@ class SessionViewAchievements extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return FutureBuilder<List<SessionActivity>>( return FutureBuilder<List<SessionActivity>>(
future: SessionActivitiesDao(database).sessionActivitiesBySessionId(session.id), future: SessionActivitiesDao(Provider.of<AppDatabase>(context)).sessionActivitiesBySessionId(session.id),
builder: (context, snapshot) { builder: (context, snapshot) {
if (snapshot.hasData) { if (snapshot.hasData) {
final sessionActivities = snapshot.data!; final sessionActivities = snapshot.data!;
final achievements = getAchievements(sessionActivities); final achievements = getAchievements(sessionActivities);
database.close(); // database.close();
return Column( return Column(
children: [ children: [
@ -58,7 +58,7 @@ class SessionViewAchievements extends StatelessWidget {
], ],
); );
} else { } else {
return const CircularProgressIndicator(); return Padding(padding: EdgeInsets.all(15), child:CircularProgressIndicator());
} }
}); });
} }

View File

@ -1,24 +1,22 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:sendtrain/classes/media.dart'; import 'package:provider/provider.dart';
import 'package:sendtrain/database/daos/media_items_dao.dart'; import 'package:sendtrain/database/daos/media_items_dao.dart';
import 'package:sendtrain/database/database.dart'; import 'package:sendtrain/database/database.dart';
import 'package:sendtrain/widgets/media_card.dart'; import 'package:sendtrain/widgets/media_card.dart';
class SessionViewMedia extends StatelessWidget { class SessionViewMedia extends StatelessWidget {
SessionViewMedia({super.key, this.media, required this.session}); const SessionViewMedia({super.key, required this.session});
final List<Media>? media;
final Session session; final Session session;
final AppDatabase database = AppDatabase();
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return FutureBuilder<List<MediaItem>>( return FutureBuilder<List<MediaItem>>(
future: MediaItemsDao(database).mediaItemsFromSession(session), future: MediaItemsDao(Provider.of<AppDatabase>(context)).mediaItemsFromSession(session),
builder: (context, snapshot) { builder: (context, snapshot) {
if (snapshot.hasData) { if (snapshot.hasData) {
final mediaItems = snapshot.data!; final mediaItems = snapshot.data!;
database.close(); // database.close();
List<Widget> mediaCards = List.generate( List<Widget> mediaCards = List.generate(
mediaItems.length, (i) => MediaCard(media: mediaItems[i])); mediaItems.length, (i) => MediaCard(media: mediaItems[i]));
@ -37,7 +35,7 @@ class SessionViewMedia extends StatelessWidget {
], ],
); );
} else { } else {
return CircularProgressIndicator(); return Padding(padding: EdgeInsets.all(15), child:CircularProgressIndicator());
} }
}); });
} }