From 1234a300e15b5e4c773c25bb7883440407c7353d Mon Sep 17 00:00:00 2001 From: Joshua Burman Date: Sat, 21 Dec 2024 17:51:24 -0500 Subject: [PATCH] small refactor, better dao thigns --- lib/daos/activities_dao.dart | 4 +- lib/daos/media_items_dao.dart | 26 ++- lib/daos/session_activities_dao.dart | 6 +- lib/daos/sessions_dao.dart | 4 +- lib/models/activity_timer_model.dart | 3 +- lib/widgets/activity_card.dart | 192 +++++++++++---------- lib/widgets/activity_view.dart | 95 ++-------- lib/widgets/session_view_achievements.dart | 2 +- lib/widgets/session_view_media.dart | 2 +- 9 files changed, 152 insertions(+), 182 deletions(-) diff --git a/lib/daos/activities_dao.dart b/lib/daos/activities_dao.dart index 3a50042..b11bd78 100644 --- a/lib/daos/activities_dao.dart +++ b/lib/daos/activities_dao.dart @@ -11,8 +11,8 @@ class ActivitiesDao extends DatabaseAccessor with _$ActivitiesDaoMi return await select(activities).get(); } - Future> find(int id) async { - return await (select(activities)..where((activity) => activity.id.equals(id) )).get(); + Future find(int id) async { + return await (select(activities)..where((activity) => activity.id.equals(id) )).getSingle(); } Future> sessionActivities(int id) async { diff --git a/lib/daos/media_items_dao.dart b/lib/daos/media_items_dao.dart index 2f2fced..4e204f5 100644 --- a/lib/daos/media_items_dao.dart +++ b/lib/daos/media_items_dao.dart @@ -11,11 +11,31 @@ class MediaItemsDao extends DatabaseAccessor with _$MediaItemsDaoMi return await select(mediaItems).get(); } - Future> find(int id) async { - return await (select(mediaItems)..where((mediaItem) => mediaItem.id.equals(id) )).get(); + Future find(int id) async { + return await (select(mediaItems)..where((mediaItem) => mediaItem.id.equals(id) )).getSingle(); } - Future> mediaItemsFromSession(Session session) async { + Future> fromActivity(Activity activity) async { + final result = select(db.objectMediaItems).join( + [ + innerJoin( + db.mediaItems, + db.mediaItems.id.equalsExp(db.objectMediaItems.mediaId), + ), + ], + ) + ..where( + db.objectMediaItems.objectType.equals(ObjectType.activities.name)) + ..where(db.objectMediaItems.objectId.equals(activity.id)); + + final mediaItems = (await result.get()) + .map((e) => e.readTable(db.mediaItems)) + .toList(); + + return mediaItems; + } + + Future> fromSession(Session session) async { final result = select(db.objectMediaItems).join( [ innerJoin( diff --git a/lib/daos/session_activities_dao.dart b/lib/daos/session_activities_dao.dart index bb4a0c6..9c645ae 100644 --- a/lib/daos/session_activities_dao.dart +++ b/lib/daos/session_activities_dao.dart @@ -11,11 +11,11 @@ class SessionActivitiesDao extends DatabaseAccessor with _$SessionA return await select(sessionActivities).get(); } - Future> find(int id) async { - return await (select(sessionActivities)..where((sessionActivity) => sessionActivity.id.equals(id) )).get(); + Future find(int id) async { + return await (select(sessionActivities)..where((sessionActivity) => sessionActivity.id.equals(id) )).getSingle(); } - Future> sessionActivitiesBySessionId(int id) async { + Future> fromSessionId(int id) async { final result = db.managers.sessionActivities .filter((sessionActivity) => sessionActivity.sessionId.id(id)); diff --git a/lib/daos/sessions_dao.dart b/lib/daos/sessions_dao.dart index bb7aee5..a54a702 100644 --- a/lib/daos/sessions_dao.dart +++ b/lib/daos/sessions_dao.dart @@ -11,7 +11,7 @@ class SessionsDao extends DatabaseAccessor with _$SessionsDaoMixin return await select(sessions).get(); } - Future> find(int id) async { - return await (select(sessions)..where((session) => session.id.equals(id) )).get(); + Future find(int id) async { + return await (select(sessions)..where((session) => session.id.equals(id) )).getSingle(); } } \ No newline at end of file diff --git a/lib/models/activity_timer_model.dart b/lib/models/activity_timer_model.dart index 24e5d11..771155c 100644 --- a/lib/models/activity_timer_model.dart +++ b/lib/models/activity_timer_model.dart @@ -30,12 +30,13 @@ class ActivityTimerModel with ChangeNotifier { double get progress => _progress; int get totalTime => _totalTime; - void setup(ActivityModel activityModel) { + void setup(ActivityModel activityModel, Activity activity) { if (_activityModel == null || activityModel.id != _activityModel?.id) { _periodicTimer?.cancel(); _progress = 0; _isc = null; _activityModel = activityModel; + _activity = activity; _sets = activityModel.actions[0].items(); _currentActionNum = 0; _currentSetNum = 0; diff --git a/lib/widgets/activity_card.dart b/lib/widgets/activity_card.dart index 4a5adc2..f474c85 100644 --- a/lib/widgets/activity_card.dart +++ b/lib/widgets/activity_card.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; -import 'package:sendtrain/classes/media.dart'; +import 'package:sendtrain/daos/media_items_dao.dart'; import 'package:sendtrain/database/database.dart'; import 'package:sendtrain/models/activity_model.dart'; import 'package:sendtrain/models/activity_timer_model.dart'; @@ -30,97 +30,113 @@ class ActivityCardState extends State { final ActivityTimerModel atm = Provider.of(context, listen: false); - return Card( - color: atm.activity?.id == widget.activity.id - ? Theme.of(context).colorScheme.primaryContainer - : Theme.of(context).colorScheme.surfaceContainerLow, - clipBehavior: Clip.hardEdge, - child: InkWell( - onTap: () => showGeneralDialog( - barrierColor: Colors.black.withOpacity(0.5), - transitionDuration: const Duration(milliseconds: 220), - transitionBuilder: (BuildContext context, - Animation animation, - Animation secondaryAnimation, - Widget child) { - Animation custom = Tween( - begin: const Offset(0.0, 1.0), - end: const Offset(0.0, 0.0)) - .animate(animation); - return SlideTransition( - position: custom, - child: Dialog.fullscreen( - child: ActivityView(activity: widget.activity))); - }, - barrierDismissible: true, - barrierLabel: '', - context: context, - pageBuilder: (context, animation1, animation2) { - return Container(); - }), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - ListTile( - leading: Padding( - padding: const EdgeInsets.fromLTRB(0, 0, 0, 0), - child: Container( - padding: EdgeInsets.only(top: 5, bottom: 5), - width: 60, - decoration: BoxDecoration( - image: DecorationImage( - fit: BoxFit.cover, - image: findMediaByType( - widget.activity.actions[0].media, 'image')), - // color: Colors.blue, - borderRadius: - const BorderRadius.all(Radius.elliptical(10, 10)), - ), - )), - title: Consumer( - builder: (context, atm, child) { - if (atm.activity?.id == widget.activity.id) { - return Text( - maxLines: 1, - "${widget.data.title} (${formattedTime(atm.totalTime)})"); - } else { - return Text(maxLines: 1, widget.data.title); - } - }, - ), - subtitle: Text(maxLines: 2, widget.data.description), - trailing: IconButton( - visualDensity: VisualDensity.compact, - icon: Icon(Icons.close_rounded), - onPressed: () { - showAdaptiveDialog( - context: context, - builder: (BuildContext context) => AlertDialog( - title: const Text('Activity Removal'), - content: const Text('Would you like to permanently remove this activity from the current session?'), - actions: [ - TextButton( - onPressed: () => Navigator.pop(context, 'Cancel'), - child: const Text('Cancel'), - ), - TextButton( - onPressed: () => Navigator.pop(context, 'OK'), - child: const Text('OK'), - ), - ], - ), - ); - }, + return FutureBuilder>( + future: MediaItemsDao(Provider.of(context)) + .fromActivity(widget.data), + builder: (context, snapshot) { + if (snapshot.hasData) { + List mediaItems = snapshot.data!; + + return Card( + color: atm.activity?.id == widget.activity.id + ? Theme.of(context).colorScheme.primaryContainer + : Theme.of(context).colorScheme.surfaceContainerLow, + clipBehavior: Clip.hardEdge, + child: InkWell( + onTap: () => showGeneralDialog( + barrierColor: Colors.black.withOpacity(0.5), + transitionDuration: const Duration(milliseconds: 220), + transitionBuilder: (BuildContext context, + Animation animation, + Animation secondaryAnimation, + Widget child) { + Animation custom = Tween( + begin: const Offset(0.0, 1.0), + end: const Offset(0.0, 0.0)) + .animate(animation); + return SlideTransition( + position: custom, + child: Dialog.fullscreen( + child: ActivityView( + activityModel: widget.activity, + activity: widget.data))); + }, + barrierDismissible: true, + barrierLabel: '', + context: context, + pageBuilder: (context, animation1, animation2) { + return Container(); + }), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + ListTile( + leading: Padding( + padding: const EdgeInsets.fromLTRB(0, 0, 0, 0), + child: Container( + padding: EdgeInsets.only(top: 5, bottom: 5), + width: 60, + decoration: BoxDecoration( + image: DecorationImage( + fit: BoxFit.cover, + image: + findMediaByType(mediaItems, 'image')), + // color: Colors.blue, + borderRadius: const BorderRadius.all( + Radius.elliptical(10, 10)), + ), + )), + title: Consumer( + builder: (context, atm, child) { + if (atm.activity?.id == widget.activity.id) { + return Text( + maxLines: 1, + "${widget.data.title} (${formattedTime(atm.totalTime)})"); + } else { + return Text(maxLines: 1, widget.data.title); + } + }, + ), + subtitle: Text(maxLines: 2, widget.data.description), + trailing: IconButton( + visualDensity: VisualDensity.compact, + icon: Icon(Icons.close_rounded), + onPressed: () { + showAdaptiveDialog( + context: context, + builder: (BuildContext context) => AlertDialog( + title: const Text('Activity Removal'), + content: const Text( + 'Would you like to permanently remove this activity from the current session?'), + actions: [ + TextButton( + onPressed: () => + Navigator.pop(context, 'Cancel'), + child: const Text('Cancel'), + ), + TextButton( + onPressed: () => + Navigator.pop(context, 'OK'), + child: const Text('OK'), + ), + ], + ), + ); + }, + )), + ], )), - ], - )), - ); + ); + } else { + return CircularProgressIndicator(); + } + }); } - ImageProvider findMediaByType(List? media, String type) { - var found = media?.where((m) => m.type == 'image'); + ImageProvider findMediaByType(List media, String type) { + Iterable? found = media.where((m) => m.type == MediaType.image); - if (found != null) { + if (found.isNotEmpty) { return NetworkImage(found.first.reference); } else { // Element is not found diff --git a/lib/widgets/activity_view.dart b/lib/widgets/activity_view.dart index 0c01a08..eeff698 100644 --- a/lib/widgets/activity_view.dart +++ b/lib/widgets/activity_view.dart @@ -1,16 +1,18 @@ import 'package:flutter/material.dart'; import 'package:flutter_expandable_fab/flutter_expandable_fab.dart'; import 'package:provider/provider.dart'; -import 'package:sendtrain/classes/activity_action.dart'; -import 'package:sendtrain/classes/media.dart'; +import 'package:sendtrain/database/database.dart'; import 'package:sendtrain/models/activity_model.dart'; import 'package:sendtrain/models/activity_timer_model.dart'; import 'package:sendtrain/widgets/activity_action_view.dart'; -import 'package:sendtrain/widgets/media_card.dart'; +import 'package:sendtrain/widgets/activity_view_categories.dart'; +import 'package:sendtrain/widgets/activity_view_media.dart'; class ActivityView extends StatefulWidget { - const ActivityView({super.key, required this.activity}); - final ActivityModel activity; + const ActivityView( + {super.key, required this.activityModel, required this.activity}); + final ActivityModel activityModel; + final Activity activity; @override State createState() => _ActivityViewState(); @@ -19,11 +21,12 @@ class ActivityView extends StatefulWidget { class _ActivityViewState extends State { @override Widget build(BuildContext context) { - ActivityModel activity = widget.activity; + final ActivityModel activityModel = widget.activityModel; + final Activity activity = widget.activity; ActivityTimerModel atm = Provider.of(context, listen: false); - atm.setup(activity); + atm.setup(activityModel, activity); return Scaffold( floatingActionButtonLocation: ExpandableFab.location, @@ -63,15 +66,15 @@ class _ActivityViewState extends State { maxLines: 1, style: const TextStyle( fontSize: 25, fontWeight: FontWeight.bold), - activity.title)), - ActivityViewCategories(categories: activity.categories), + activityModel.title)), + ActivityViewCategories(categories: activityModel.categories), Padding( padding: const EdgeInsets.only( top: 0, bottom: 20, left: 15, right: 15), child: Text( textAlign: TextAlign.left, style: const TextStyle(fontSize: 15), - activity.description)), + activityModel.description)), ActivityViewMedia(activity: activity), const Padding( padding: EdgeInsets.fromLTRB(15, 30, 0, 10), @@ -139,77 +142,7 @@ class _ActivityViewState extends State { semanticsLabel: 'Activity Progress', ); })), - ActivityActionView(action: activity.actions[0]), + ActivityActionView(action: activityModel.actions[0]), ])); } } - -class ActivityViewCategories extends StatelessWidget { - const ActivityViewCategories({super.key, this.categories}); - - final List? categories; - - @override - Widget build(BuildContext context) { - return Column( - children: [ - Padding( - padding: const EdgeInsets.only(bottom: 10), - child: SizedBox( - height: 40, - child: ListView.builder( - shrinkWrap: true, - scrollDirection: Axis.horizontal, - padding: const EdgeInsets.fromLTRB(10, 0, 10, 0), - itemCount: categories?.length, - itemBuilder: (BuildContext context, int index) { - return Padding( - padding: const EdgeInsets.only(right: 5), - child: ActionChip( - visualDensity: VisualDensity.compact, - avatar: const Icon(Icons.check_circle_outline), - label: Text(maxLines: 1, '${categories?[index]}'), - onPressed: () {}, - )); - }, - ))), - ], - ); - } -} - -class ActivityViewMedia extends StatelessWidget { - const ActivityViewMedia({super.key, this.activity}); - - final ActivityModel? activity; - - @override - Widget build(BuildContext context) { - List media = []; - - for (ActivityAction action in activity!.actions) { - if (action.media!.isNotEmpty) { - media.addAll(action.media as Iterable); - } - } - - return Text("media!"); - // List mediaCards = - // List.generate(media.length, (i) => MediaCard(media: media[i])); - - // return Column( - // children: [ - // SizedBox( - // width: double.infinity, - // height: 100, - // child: GridView.count( - // padding: const EdgeInsets.fromLTRB(15, 0, 0, 0), - // scrollDirection: Axis.horizontal, - // crossAxisSpacing: 5, - // mainAxisSpacing: 5, - // crossAxisCount: 1, - // children: mediaCards)) - // ], - // ); - } -} diff --git a/lib/widgets/session_view_achievements.dart b/lib/widgets/session_view_achievements.dart index b830f04..cde1cfa 100644 --- a/lib/widgets/session_view_achievements.dart +++ b/lib/widgets/session_view_achievements.dart @@ -27,7 +27,7 @@ class SessionViewAchievements extends StatelessWidget { Widget build(BuildContext context) { return FutureBuilder>( future: SessionActivitiesDao(Provider.of(context)) - .sessionActivitiesBySessionId(session.id), + .fromSessionId(session.id), builder: (context, snapshot) { if (snapshot.hasData) { final sessionActivities = snapshot.data!; diff --git a/lib/widgets/session_view_media.dart b/lib/widgets/session_view_media.dart index c9267f5..8e614ad 100644 --- a/lib/widgets/session_view_media.dart +++ b/lib/widgets/session_view_media.dart @@ -13,7 +13,7 @@ class SessionViewMedia extends StatelessWidget { Widget build(BuildContext context) { return FutureBuilder>( future: MediaItemsDao(Provider.of(context)) - .mediaItemsFromSession(session), + .fromSession(session), builder: (context, snapshot) { if (snapshot.hasData) { final mediaItems = snapshot.data!;