Compare commits
13
Commits
dao
..
48f716cdb0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
48f716cdb0 | ||
|
|
e78788d67a | ||
|
|
e36d2a837a | ||
|
|
10332ec8be | ||
|
|
5f628d6b48 | ||
|
|
afe633e697 | ||
|
|
8e0ec614a0 | ||
|
|
fa374a5bc2 | ||
|
|
26d9386812 | ||
|
|
722a152130 | ||
|
|
cd8da31f4b | ||
|
|
029f037f90 | ||
|
|
3c2f2e9bae |
Vendored
+1
@@ -0,0 +1 @@
|
|||||||
|
-keep class androidx.lifecycle.DefaultLifecycleObserver
|
||||||
@@ -1,4 +1,7 @@
|
|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<uses-feature android:name="android.hardware.location.network" android:required="false" />
|
||||||
|
<uses-feature android:name="android.hardware.location.gps" android:required="false" />
|
||||||
|
<uses-permission android:name="android.permission.INTERNET"/>
|
||||||
<application
|
<application
|
||||||
android:label="sendtrain"
|
android:label="sendtrain"
|
||||||
android:name="${applicationName}"
|
android:name="${applicationName}"
|
||||||
@@ -17,12 +20,12 @@
|
|||||||
while the Flutter UI initializes. After that, this theme continues
|
while the Flutter UI initializes. After that, this theme continues
|
||||||
to determine the Window background behind the Flutter UI. -->
|
to determine the Window background behind the Flutter UI. -->
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="io.flutter.embedding.android.NormalTheme"
|
android:name="io.flutter.embedding.android.NormalTheme"
|
||||||
android:resource="@style/NormalTheme"
|
android:resource="@style/NormalTheme"
|
||||||
/>
|
/>
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN"/>
|
<action android:name="android.intent.action.MAIN" />
|
||||||
<category android:name="android.intent.category.LAUNCHER"/>
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
<!-- Don't delete the meta-data below.
|
<!-- Don't delete the meta-data below.
|
||||||
@@ -31,6 +34,8 @@
|
|||||||
android:name="flutterEmbedding"
|
android:name="flutterEmbedding"
|
||||||
android:value="2" />
|
android:value="2" />
|
||||||
</application>
|
</application>
|
||||||
|
<meta-data android:name="com.google.android.geo.API_KEY"
|
||||||
|
android:value="AIzaSyBCjMCEAyyNVpsnVYvZj6VL1mmB98Vd6AE" />
|
||||||
<!-- Required to query activities that can process text, see:
|
<!-- Required to query activities that can process text, see:
|
||||||
https://developer.android.com/training/package-visibility and
|
https://developer.android.com/training/package-visibility and
|
||||||
https://developer.android.com/reference/android/content/Intent#ACTION_PROCESS_TEXT.
|
https://developer.android.com/reference/android/content/Intent#ACTION_PROCESS_TEXT.
|
||||||
@@ -38,8 +43,9 @@
|
|||||||
In particular, this is used by the Flutter engine in io.flutter.plugin.text.ProcessTextPlugin. -->
|
In particular, this is used by the Flutter engine in io.flutter.plugin.text.ProcessTextPlugin. -->
|
||||||
<queries>
|
<queries>
|
||||||
<intent>
|
<intent>
|
||||||
<action android:name="android.intent.action.PROCESS_TEXT"/>
|
<action android:name="android.intent.action.PROCESS_TEXT" />
|
||||||
<data android:mimeType="text/plain"/>
|
<data android:mimeType="text/plain" />
|
||||||
|
|
||||||
</intent>
|
</intent>
|
||||||
</queries>
|
</queries>
|
||||||
</manifest>
|
</manifest>
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
import UIKit
|
import UIKit
|
||||||
import Flutter
|
import Flutter
|
||||||
|
import GoogleMaps
|
||||||
|
|
||||||
@UIApplicationMain
|
@UIApplicationMain
|
||||||
@objc class AppDelegate: FlutterAppDelegate {
|
@objc class AppDelegate: FlutterAppDelegate {
|
||||||
@@ -7,6 +8,7 @@ import Flutter
|
|||||||
_ application: UIApplication,
|
_ application: UIApplication,
|
||||||
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
|
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
|
||||||
) -> Bool {
|
) -> Bool {
|
||||||
|
GMSServices.provideAPIKey("AIzaSyBCjMCEAyyNVpsnVYvZj6VL1mmB98Vd6AE")
|
||||||
GeneratedPluginRegistrant.register(with: self)
|
GeneratedPluginRegistrant.register(with: self)
|
||||||
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
|
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,13 @@
|
|||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
<dict>
|
<dict>
|
||||||
|
<key>UIBackgroundModes</key>
|
||||||
|
<array>
|
||||||
|
<string>fetch</string>
|
||||||
|
<string>remote-notification</string>
|
||||||
|
</array>
|
||||||
|
<key>NSPhotoLibraryUsageDescription</key>
|
||||||
|
<string>The Photo library is used when selecting a photo to upload as media for a Session</string>
|
||||||
<key>CADisableMinimumFrameDurationOnPhone</key>
|
<key>CADisableMinimumFrameDurationOnPhone</key>
|
||||||
<true/>
|
<true/>
|
||||||
<key>CFBundleDevelopmentRegion</key>
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
|
|||||||
@@ -4,7 +4,8 @@ import 'package:sendtrain/database/database.dart';
|
|||||||
part 'activities_dao.g.dart';
|
part 'activities_dao.g.dart';
|
||||||
|
|
||||||
@DriftAccessor(tables: [Activities])
|
@DriftAccessor(tables: [Activities])
|
||||||
class ActivitiesDao extends DatabaseAccessor<AppDatabase> with _$ActivitiesDaoMixin {
|
class ActivitiesDao extends DatabaseAccessor<AppDatabase>
|
||||||
|
with _$ActivitiesDaoMixin {
|
||||||
ActivitiesDao(super.db);
|
ActivitiesDao(super.db);
|
||||||
|
|
||||||
Future<List<Activity>> all() async {
|
Future<List<Activity>> all() async {
|
||||||
@@ -12,24 +13,71 @@ class ActivitiesDao extends DatabaseAccessor<AppDatabase> with _$ActivitiesDaoMi
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<Activity> find(int id) async {
|
Future<Activity> find(int id) async {
|
||||||
return await (select(activities)..where((activity) => activity.id.equals(id) )).getSingle();
|
return await (select(activities)
|
||||||
|
..where((activity) => activity.id.equals(id)))
|
||||||
|
.getSingle();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<Activity>> sessionActivities(int id) async {
|
Future remove(Activity activity) => delete(activities).delete(activity);
|
||||||
final result = select(db.sessionActivities).join(
|
|
||||||
|
Future<List<Activity>> activitiesFromSession(int id) async {
|
||||||
|
final result = select(db.sessionActivities).join(
|
||||||
[
|
[
|
||||||
innerJoin(
|
innerJoin(
|
||||||
db.activities,
|
db.activities,
|
||||||
db.activities.id
|
db.activities.id.equalsExp(db.sessionActivities.activityId),
|
||||||
.equalsExp(db.sessionActivities.activityId),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
)..where(db.sessionActivities.sessionId.equals(id));
|
)..where(db.sessionActivities.sessionId.equals(id));
|
||||||
|
|
||||||
final activities = (await result.get())
|
final activities =
|
||||||
.map((e) => e.readTable(db.activities))
|
(await result.get()).map((e) => e.readTable(db.activities)).toList();
|
||||||
.toList();
|
|
||||||
|
|
||||||
return activities;
|
return activities;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Stream<List<Activity>> watchSessionActivities(int id) {
|
||||||
|
final query = select(db.sessionActivities).join(
|
||||||
|
[
|
||||||
|
innerJoin(
|
||||||
|
db.activities,
|
||||||
|
db.activities.id.equalsExp(db.sessionActivities.activityId),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)..where(db.sessionActivities.sessionId.equals(id));
|
||||||
|
|
||||||
|
return query.watch().map((rows){
|
||||||
|
final activities =
|
||||||
|
(rows).map((e) => e.readTable(db.activities)).toList();
|
||||||
|
|
||||||
|
return activities;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// MultiSelectable<SessionActivity> _selectableSessionActivities(int id) {
|
||||||
|
// // return select(db.sessionActivities)..limit(1, offset: 1);
|
||||||
|
// // final query = select(db.sessionActivities).join(
|
||||||
|
// // [
|
||||||
|
// // innerJoin(
|
||||||
|
// // db.activities,
|
||||||
|
// // db.activities.id.equalsExp(db.sessionActivities.activityId),
|
||||||
|
// // ),
|
||||||
|
// // ],
|
||||||
|
// // )..where(db.sessionActivities.sessionId.equals(id));
|
||||||
|
|
||||||
|
// // return query;
|
||||||
|
|
||||||
|
// final query = select(db.sessionActivities)..where((row) => row.sessionId.equals(id));
|
||||||
|
|
||||||
|
// query.join(
|
||||||
|
// [
|
||||||
|
// innerJoin(
|
||||||
|
// db.activities,
|
||||||
|
// db.activities.id.equalsExp(db.sessionActivities.activityId),
|
||||||
|
// ),
|
||||||
|
// ],
|
||||||
|
// );
|
||||||
|
|
||||||
|
// return query;
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
@@ -4,15 +4,21 @@ import 'package:sendtrain/database/database.dart';
|
|||||||
part 'media_items_dao.g.dart';
|
part 'media_items_dao.g.dart';
|
||||||
|
|
||||||
@DriftAccessor(tables: [MediaItems])
|
@DriftAccessor(tables: [MediaItems])
|
||||||
class MediaItemsDao extends DatabaseAccessor<AppDatabase> with _$MediaItemsDaoMixin {
|
class MediaItemsDao extends DatabaseAccessor<AppDatabase>
|
||||||
|
with _$MediaItemsDaoMixin {
|
||||||
MediaItemsDao(super.db);
|
MediaItemsDao(super.db);
|
||||||
|
|
||||||
|
Future createOrUpdate(MediaItemsCompanion mediaItem) =>
|
||||||
|
into(mediaItems).insertOnConflictUpdate(mediaItem);
|
||||||
|
|
||||||
Future<List<MediaItem>> all() async {
|
Future<List<MediaItem>> all() async {
|
||||||
return await select(mediaItems).get();
|
return await select(mediaItems).get();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<MediaItem> find(int id) async {
|
Future<MediaItem> find(int id) async {
|
||||||
return await (select(mediaItems)..where((mediaItem) => mediaItem.id.equals(id) )).getSingle();
|
return await (select(mediaItems)
|
||||||
|
..where((mediaItem) => mediaItem.id.equals(id)))
|
||||||
|
.getSingle();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<MediaItem>> fromActivity(Activity activity) async {
|
Future<List<MediaItem>> fromActivity(Activity activity) async {
|
||||||
@@ -24,18 +30,16 @@ class MediaItemsDao extends DatabaseAccessor<AppDatabase> with _$MediaItemsDaoMi
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
..where(
|
..where(db.objectMediaItems.objectType.equals(ObjectType.activities.name))
|
||||||
db.objectMediaItems.objectType.equals(ObjectType.activities.name))
|
|
||||||
..where(db.objectMediaItems.objectId.equals(activity.id));
|
..where(db.objectMediaItems.objectId.equals(activity.id));
|
||||||
|
|
||||||
final mediaItems = (await result.get())
|
final mediaItems =
|
||||||
.map((e) => e.readTable(db.mediaItems))
|
(await result.get()).map((e) => e.readTable(db.mediaItems)).toList();
|
||||||
.toList();
|
|
||||||
|
|
||||||
return mediaItems;
|
return mediaItems;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<MediaItem>> fromSession(Session session) async {
|
Future<List<MediaItem>> fromSession(int sessionId) async {
|
||||||
final result = select(db.objectMediaItems).join(
|
final result = select(db.objectMediaItems).join(
|
||||||
[
|
[
|
||||||
innerJoin(
|
innerJoin(
|
||||||
@@ -44,14 +48,37 @@ class MediaItemsDao extends DatabaseAccessor<AppDatabase> with _$MediaItemsDaoMi
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
..where(
|
..where(db.objectMediaItems.objectType.equals(ObjectType.sessions.name))
|
||||||
db.objectMediaItems.objectType.equals(ObjectType.sessions.name))
|
..where(db.objectMediaItems.objectId.equals(sessionId));
|
||||||
..where(db.objectMediaItems.objectId.equals(session.id));
|
|
||||||
|
|
||||||
final mediaItems = (await result.get())
|
final mediaItems =
|
||||||
.map((e) => e.readTable(db.mediaItems))
|
(await result.get()).map((e) => e.readTable(db.mediaItems)).toList();
|
||||||
.toList();
|
|
||||||
|
|
||||||
return mediaItems;
|
return mediaItems;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Stream<List<MediaItem>> watchSessionMediaItems(int id) {
|
||||||
|
final query = select(db.objectMediaItems).join(
|
||||||
|
[
|
||||||
|
innerJoin(
|
||||||
|
db.mediaItems,
|
||||||
|
db.mediaItems.id.equalsExp(db.objectMediaItems.mediaId),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
..where(db.objectMediaItems.objectType.equals(ObjectType.sessions.name))
|
||||||
|
..where(db.objectMediaItems.objectId.equals(id));
|
||||||
|
|
||||||
|
return query.watch().map((rows) {
|
||||||
|
final mediaItems = (rows).map((e) => e.readTable(db.mediaItems)).toList();
|
||||||
|
|
||||||
|
return mediaItems;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Future remove(MediaItem mediaItem) => delete(mediaItems).delete(mediaItem);
|
||||||
|
Future removeAll(Iterable<int> mediaItemIds) {
|
||||||
|
return (delete(mediaItems)..where((table) => table.id.isIn(mediaItemIds)))
|
||||||
|
.go();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
import 'package:drift/drift.dart';
|
||||||
|
import 'package:sendtrain/database/database.dart';
|
||||||
|
|
||||||
|
part 'object_media_items_dao.g.dart';
|
||||||
|
|
||||||
|
@DriftAccessor(tables: [ObjectMediaItems])
|
||||||
|
class ObjectMediaItemsDao extends DatabaseAccessor<AppDatabase> with _$ObjectMediaItemsDaoMixin {
|
||||||
|
ObjectMediaItemsDao(super.db);
|
||||||
|
|
||||||
|
Future createOrUpdate(ObjectMediaItemsCompanion objectMediaItem) => into(objectMediaItems).insertOnConflictUpdate(objectMediaItem);
|
||||||
|
|
||||||
|
Future<List<ObjectMediaItem>> all() async {
|
||||||
|
return await select(objectMediaItems).get();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<ObjectMediaItem> find(int id) async {
|
||||||
|
return await (select(objectMediaItems)..where((objectMediaItem) => objectMediaItem.id.equals(id) )).getSingle();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'object_media_items_dao.dart';
|
||||||
|
|
||||||
|
// ignore_for_file: type=lint
|
||||||
|
mixin _$ObjectMediaItemsDaoMixin on DatabaseAccessor<AppDatabase> {
|
||||||
|
$MediaItemsTable get mediaItems => attachedDatabase.mediaItems;
|
||||||
|
$ObjectMediaItemsTable get objectMediaItems =>
|
||||||
|
attachedDatabase.objectMediaItems;
|
||||||
|
}
|
||||||
@@ -7,11 +7,10 @@ part 'sessions_dao.g.dart';
|
|||||||
class SessionsDao extends DatabaseAccessor<AppDatabase> with _$SessionsDaoMixin {
|
class SessionsDao extends DatabaseAccessor<AppDatabase> with _$SessionsDaoMixin {
|
||||||
SessionsDao(super.db);
|
SessionsDao(super.db);
|
||||||
|
|
||||||
Future<List<Session>> all() async {
|
Future<Session> find(int id) => (select(sessions)..where((session) => session.id.equals(id) )).getSingle();
|
||||||
return await select(sessions).get();
|
Future<List<Session>> all() => select(sessions).get();
|
||||||
}
|
Stream<List<Session>> watch() => select(sessions).watch();
|
||||||
|
Future createOrUpdate(SessionsCompanion session) => into(sessions).insertOnConflictUpdate(session);
|
||||||
Future<Session> find(int id) async {
|
Future replace(Session session) => update(sessions).replace(session);
|
||||||
return await (select(sessions)..where((session) => session.id.equals(id) )).getSingle();
|
Future remove(Session session) => delete(sessions).delete(session);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -4,6 +4,7 @@ import 'package:sendtrain/daos/actions_dao.dart';
|
|||||||
import 'package:sendtrain/daos/activities_dao.dart';
|
import 'package:sendtrain/daos/activities_dao.dart';
|
||||||
import 'package:sendtrain/daos/activity_actions_dao.dart';
|
import 'package:sendtrain/daos/activity_actions_dao.dart';
|
||||||
import 'package:sendtrain/daos/media_items_dao.dart';
|
import 'package:sendtrain/daos/media_items_dao.dart';
|
||||||
|
import 'package:sendtrain/daos/object_media_items_dao.dart';
|
||||||
import 'package:sendtrain/daos/session_activities_dao.dart';
|
import 'package:sendtrain/daos/session_activities_dao.dart';
|
||||||
import 'package:sendtrain/daos/sessions_dao.dart';
|
import 'package:sendtrain/daos/sessions_dao.dart';
|
||||||
import 'package:sendtrain/database/seed.dart';
|
import 'package:sendtrain/database/seed.dart';
|
||||||
@@ -22,6 +23,7 @@ part 'database.g.dart';
|
|||||||
SessionsDao,
|
SessionsDao,
|
||||||
ActivitiesDao,
|
ActivitiesDao,
|
||||||
MediaItemsDao,
|
MediaItemsDao,
|
||||||
|
ObjectMediaItemsDao,
|
||||||
SessionActivitiesDao,
|
SessionActivitiesDao,
|
||||||
ActivityActionsDao,
|
ActivityActionsDao,
|
||||||
ActionsDao
|
ActionsDao
|
||||||
@@ -33,7 +35,7 @@ class AppDatabase extends _$AppDatabase {
|
|||||||
AppDatabase() : super(_openConnection());
|
AppDatabase() : super(_openConnection());
|
||||||
|
|
||||||
@override
|
@override
|
||||||
int get schemaVersion => 4;
|
int get schemaVersion => 10;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
MigrationStrategy get migration {
|
MigrationStrategy get migration {
|
||||||
@@ -64,6 +66,7 @@ class Sessions extends Table {
|
|||||||
TextColumn get title => text().withLength(min: 3, max: 32)();
|
TextColumn get title => text().withLength(min: 3, max: 32)();
|
||||||
TextColumn get content => text().named('body')();
|
TextColumn get content => text().named('body')();
|
||||||
TextColumn get status => textEnum<SessionStatus>()();
|
TextColumn get status => textEnum<SessionStatus>()();
|
||||||
|
TextColumn get address => text().withLength(min: 3, max: 256).nullable()();
|
||||||
DateTimeColumn get date => dateTime().nullable()();
|
DateTimeColumn get date => dateTime().nullable()();
|
||||||
DateTimeColumn get createdAt =>
|
DateTimeColumn get createdAt =>
|
||||||
dateTime().withDefault(Variable(DateTime.now()))();
|
dateTime().withDefault(Variable(DateTime.now()))();
|
||||||
@@ -71,8 +74,8 @@ class Sessions extends Table {
|
|||||||
|
|
||||||
class SessionActivities extends Table {
|
class SessionActivities extends Table {
|
||||||
IntColumn get id => integer().autoIncrement()();
|
IntColumn get id => integer().autoIncrement()();
|
||||||
IntColumn get sessionId => integer().references(Sessions, #id)();
|
IntColumn get sessionId => integer().references(Sessions, #id, onDelete: KeyAction.cascade)();
|
||||||
IntColumn get activityId => integer().references(Activities, #id)();
|
IntColumn get activityId => integer().references(Activities, #id, onDelete: KeyAction.cascade)();
|
||||||
IntColumn get position => integer()();
|
IntColumn get position => integer()();
|
||||||
TextColumn get results => text().nullable()();
|
TextColumn get results => text().nullable()();
|
||||||
TextColumn get achievements => text().nullable()();
|
TextColumn get achievements => text().nullable()();
|
||||||
@@ -107,8 +110,8 @@ class Activities extends Table {
|
|||||||
|
|
||||||
class ActivityActions extends Table {
|
class ActivityActions extends Table {
|
||||||
IntColumn get id => integer().autoIncrement()();
|
IntColumn get id => integer().autoIncrement()();
|
||||||
IntColumn get activityId => integer().references(Activities, #id)();
|
IntColumn get activityId => integer().references(Activities, #id, onDelete: KeyAction.cascade)();
|
||||||
IntColumn get actionId => integer().references(Actions, #id)();
|
IntColumn get actionId => integer().references(Actions, #id, onDelete: KeyAction.cascade)();
|
||||||
IntColumn get position => integer()();
|
IntColumn get position => integer()();
|
||||||
DateTimeColumn get createdAt =>
|
DateTimeColumn get createdAt =>
|
||||||
dateTime().withDefault(Variable(DateTime.now()))();
|
dateTime().withDefault(Variable(DateTime.now()))();
|
||||||
@@ -133,18 +136,18 @@ class ObjectMediaItems extends Table {
|
|||||||
IntColumn get id => integer().autoIncrement()();
|
IntColumn get id => integer().autoIncrement()();
|
||||||
IntColumn get objectId => integer()();
|
IntColumn get objectId => integer()();
|
||||||
TextColumn get objectType => textEnum<ObjectType>()();
|
TextColumn get objectType => textEnum<ObjectType>()();
|
||||||
IntColumn get mediaId => integer().references(MediaItems, #id)();
|
IntColumn get mediaId => integer().references(MediaItems, #id, onDelete: KeyAction.cascade)();
|
||||||
DateTimeColumn get createdAt =>
|
DateTimeColumn get createdAt =>
|
||||||
dateTime().withDefault(Variable(DateTime.now()))();
|
dateTime().withDefault(Variable(DateTime.now()))();
|
||||||
}
|
}
|
||||||
|
|
||||||
enum MediaType { youtube, image }
|
enum MediaType { youtube, image, location, localImage, localVideo }
|
||||||
|
|
||||||
class MediaItems extends Table {
|
class MediaItems extends Table {
|
||||||
IntColumn get id => integer().autoIncrement()();
|
IntColumn get id => integer().autoIncrement()();
|
||||||
TextColumn get title => text().withLength(min: 3, max: 32)();
|
TextColumn get title => text().withLength(min: 3, max: 32)();
|
||||||
TextColumn get description => text().named('body')();
|
TextColumn get description => text().named('body')();
|
||||||
TextColumn get reference => text().withLength(min: 3, max: 256)();
|
TextColumn get reference => text()();
|
||||||
TextColumn get type => textEnum<MediaType>()();
|
TextColumn get type => textEnum<MediaType>()();
|
||||||
DateTimeColumn get createdAt =>
|
DateTimeColumn get createdAt =>
|
||||||
dateTime().withDefault(Variable(DateTime.now()))();
|
dateTime().withDefault(Variable(DateTime.now()))();
|
||||||
|
|||||||
+112
-16
@@ -37,6 +37,15 @@ class $SessionsTable extends Sessions with TableInfo<$SessionsTable, Session> {
|
|||||||
GeneratedColumn<String>('status', aliasedName, false,
|
GeneratedColumn<String>('status', aliasedName, false,
|
||||||
type: DriftSqlType.string, requiredDuringInsert: true)
|
type: DriftSqlType.string, requiredDuringInsert: true)
|
||||||
.withConverter<SessionStatus>($SessionsTable.$converterstatus);
|
.withConverter<SessionStatus>($SessionsTable.$converterstatus);
|
||||||
|
static const VerificationMeta _addressMeta =
|
||||||
|
const VerificationMeta('address');
|
||||||
|
@override
|
||||||
|
late final GeneratedColumn<String> address = GeneratedColumn<String>(
|
||||||
|
'address', aliasedName, true,
|
||||||
|
additionalChecks:
|
||||||
|
GeneratedColumn.checkTextLength(minTextLength: 3, maxTextLength: 256),
|
||||||
|
type: DriftSqlType.string,
|
||||||
|
requiredDuringInsert: false);
|
||||||
static const VerificationMeta _dateMeta = const VerificationMeta('date');
|
static const VerificationMeta _dateMeta = const VerificationMeta('date');
|
||||||
@override
|
@override
|
||||||
late final GeneratedColumn<DateTime> date = GeneratedColumn<DateTime>(
|
late final GeneratedColumn<DateTime> date = GeneratedColumn<DateTime>(
|
||||||
@@ -52,7 +61,7 @@ class $SessionsTable extends Sessions with TableInfo<$SessionsTable, Session> {
|
|||||||
defaultValue: Variable(DateTime.now()));
|
defaultValue: Variable(DateTime.now()));
|
||||||
@override
|
@override
|
||||||
List<GeneratedColumn> get $columns =>
|
List<GeneratedColumn> get $columns =>
|
||||||
[id, title, content, status, date, createdAt];
|
[id, title, content, status, address, date, createdAt];
|
||||||
@override
|
@override
|
||||||
String get aliasedName => _alias ?? actualTableName;
|
String get aliasedName => _alias ?? actualTableName;
|
||||||
@override
|
@override
|
||||||
@@ -79,6 +88,10 @@ class $SessionsTable extends Sessions with TableInfo<$SessionsTable, Session> {
|
|||||||
context.missing(_contentMeta);
|
context.missing(_contentMeta);
|
||||||
}
|
}
|
||||||
context.handle(_statusMeta, const VerificationResult.success());
|
context.handle(_statusMeta, const VerificationResult.success());
|
||||||
|
if (data.containsKey('address')) {
|
||||||
|
context.handle(_addressMeta,
|
||||||
|
address.isAcceptableOrUnknown(data['address']!, _addressMeta));
|
||||||
|
}
|
||||||
if (data.containsKey('date')) {
|
if (data.containsKey('date')) {
|
||||||
context.handle(
|
context.handle(
|
||||||
_dateMeta, date.isAcceptableOrUnknown(data['date']!, _dateMeta));
|
_dateMeta, date.isAcceptableOrUnknown(data['date']!, _dateMeta));
|
||||||
@@ -105,6 +118,8 @@ class $SessionsTable extends Sessions with TableInfo<$SessionsTable, Session> {
|
|||||||
status: $SessionsTable.$converterstatus.fromSql(attachedDatabase
|
status: $SessionsTable.$converterstatus.fromSql(attachedDatabase
|
||||||
.typeMapping
|
.typeMapping
|
||||||
.read(DriftSqlType.string, data['${effectivePrefix}status'])!),
|
.read(DriftSqlType.string, data['${effectivePrefix}status'])!),
|
||||||
|
address: attachedDatabase.typeMapping
|
||||||
|
.read(DriftSqlType.string, data['${effectivePrefix}address']),
|
||||||
date: attachedDatabase.typeMapping
|
date: attachedDatabase.typeMapping
|
||||||
.read(DriftSqlType.dateTime, data['${effectivePrefix}date']),
|
.read(DriftSqlType.dateTime, data['${effectivePrefix}date']),
|
||||||
createdAt: attachedDatabase.typeMapping
|
createdAt: attachedDatabase.typeMapping
|
||||||
@@ -126,6 +141,7 @@ class Session extends DataClass implements Insertable<Session> {
|
|||||||
final String title;
|
final String title;
|
||||||
final String content;
|
final String content;
|
||||||
final SessionStatus status;
|
final SessionStatus status;
|
||||||
|
final String? address;
|
||||||
final DateTime? date;
|
final DateTime? date;
|
||||||
final DateTime createdAt;
|
final DateTime createdAt;
|
||||||
const Session(
|
const Session(
|
||||||
@@ -133,6 +149,7 @@ class Session extends DataClass implements Insertable<Session> {
|
|||||||
required this.title,
|
required this.title,
|
||||||
required this.content,
|
required this.content,
|
||||||
required this.status,
|
required this.status,
|
||||||
|
this.address,
|
||||||
this.date,
|
this.date,
|
||||||
required this.createdAt});
|
required this.createdAt});
|
||||||
@override
|
@override
|
||||||
@@ -145,6 +162,9 @@ class Session extends DataClass implements Insertable<Session> {
|
|||||||
map['status'] =
|
map['status'] =
|
||||||
Variable<String>($SessionsTable.$converterstatus.toSql(status));
|
Variable<String>($SessionsTable.$converterstatus.toSql(status));
|
||||||
}
|
}
|
||||||
|
if (!nullToAbsent || address != null) {
|
||||||
|
map['address'] = Variable<String>(address);
|
||||||
|
}
|
||||||
if (!nullToAbsent || date != null) {
|
if (!nullToAbsent || date != null) {
|
||||||
map['date'] = Variable<DateTime>(date);
|
map['date'] = Variable<DateTime>(date);
|
||||||
}
|
}
|
||||||
@@ -158,6 +178,9 @@ class Session extends DataClass implements Insertable<Session> {
|
|||||||
title: Value(title),
|
title: Value(title),
|
||||||
content: Value(content),
|
content: Value(content),
|
||||||
status: Value(status),
|
status: Value(status),
|
||||||
|
address: address == null && nullToAbsent
|
||||||
|
? const Value.absent()
|
||||||
|
: Value(address),
|
||||||
date: date == null && nullToAbsent ? const Value.absent() : Value(date),
|
date: date == null && nullToAbsent ? const Value.absent() : Value(date),
|
||||||
createdAt: Value(createdAt),
|
createdAt: Value(createdAt),
|
||||||
);
|
);
|
||||||
@@ -172,6 +195,7 @@ class Session extends DataClass implements Insertable<Session> {
|
|||||||
content: serializer.fromJson<String>(json['content']),
|
content: serializer.fromJson<String>(json['content']),
|
||||||
status: $SessionsTable.$converterstatus
|
status: $SessionsTable.$converterstatus
|
||||||
.fromJson(serializer.fromJson<String>(json['status'])),
|
.fromJson(serializer.fromJson<String>(json['status'])),
|
||||||
|
address: serializer.fromJson<String?>(json['address']),
|
||||||
date: serializer.fromJson<DateTime?>(json['date']),
|
date: serializer.fromJson<DateTime?>(json['date']),
|
||||||
createdAt: serializer.fromJson<DateTime>(json['createdAt']),
|
createdAt: serializer.fromJson<DateTime>(json['createdAt']),
|
||||||
);
|
);
|
||||||
@@ -185,6 +209,7 @@ class Session extends DataClass implements Insertable<Session> {
|
|||||||
'content': serializer.toJson<String>(content),
|
'content': serializer.toJson<String>(content),
|
||||||
'status': serializer
|
'status': serializer
|
||||||
.toJson<String>($SessionsTable.$converterstatus.toJson(status)),
|
.toJson<String>($SessionsTable.$converterstatus.toJson(status)),
|
||||||
|
'address': serializer.toJson<String?>(address),
|
||||||
'date': serializer.toJson<DateTime?>(date),
|
'date': serializer.toJson<DateTime?>(date),
|
||||||
'createdAt': serializer.toJson<DateTime>(createdAt),
|
'createdAt': serializer.toJson<DateTime>(createdAt),
|
||||||
};
|
};
|
||||||
@@ -195,6 +220,7 @@ class Session extends DataClass implements Insertable<Session> {
|
|||||||
String? title,
|
String? title,
|
||||||
String? content,
|
String? content,
|
||||||
SessionStatus? status,
|
SessionStatus? status,
|
||||||
|
Value<String?> address = const Value.absent(),
|
||||||
Value<DateTime?> date = const Value.absent(),
|
Value<DateTime?> date = const Value.absent(),
|
||||||
DateTime? createdAt}) =>
|
DateTime? createdAt}) =>
|
||||||
Session(
|
Session(
|
||||||
@@ -202,6 +228,7 @@ class Session extends DataClass implements Insertable<Session> {
|
|||||||
title: title ?? this.title,
|
title: title ?? this.title,
|
||||||
content: content ?? this.content,
|
content: content ?? this.content,
|
||||||
status: status ?? this.status,
|
status: status ?? this.status,
|
||||||
|
address: address.present ? address.value : this.address,
|
||||||
date: date.present ? date.value : this.date,
|
date: date.present ? date.value : this.date,
|
||||||
createdAt: createdAt ?? this.createdAt,
|
createdAt: createdAt ?? this.createdAt,
|
||||||
);
|
);
|
||||||
@@ -211,6 +238,7 @@ class Session extends DataClass implements Insertable<Session> {
|
|||||||
title: data.title.present ? data.title.value : this.title,
|
title: data.title.present ? data.title.value : this.title,
|
||||||
content: data.content.present ? data.content.value : this.content,
|
content: data.content.present ? data.content.value : this.content,
|
||||||
status: data.status.present ? data.status.value : this.status,
|
status: data.status.present ? data.status.value : this.status,
|
||||||
|
address: data.address.present ? data.address.value : this.address,
|
||||||
date: data.date.present ? data.date.value : this.date,
|
date: data.date.present ? data.date.value : this.date,
|
||||||
createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt,
|
createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt,
|
||||||
);
|
);
|
||||||
@@ -223,6 +251,7 @@ class Session extends DataClass implements Insertable<Session> {
|
|||||||
..write('title: $title, ')
|
..write('title: $title, ')
|
||||||
..write('content: $content, ')
|
..write('content: $content, ')
|
||||||
..write('status: $status, ')
|
..write('status: $status, ')
|
||||||
|
..write('address: $address, ')
|
||||||
..write('date: $date, ')
|
..write('date: $date, ')
|
||||||
..write('createdAt: $createdAt')
|
..write('createdAt: $createdAt')
|
||||||
..write(')'))
|
..write(')'))
|
||||||
@@ -230,7 +259,8 @@ class Session extends DataClass implements Insertable<Session> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(id, title, content, status, date, createdAt);
|
int get hashCode =>
|
||||||
|
Object.hash(id, title, content, status, address, date, createdAt);
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) =>
|
bool operator ==(Object other) =>
|
||||||
identical(this, other) ||
|
identical(this, other) ||
|
||||||
@@ -239,6 +269,7 @@ class Session extends DataClass implements Insertable<Session> {
|
|||||||
other.title == this.title &&
|
other.title == this.title &&
|
||||||
other.content == this.content &&
|
other.content == this.content &&
|
||||||
other.status == this.status &&
|
other.status == this.status &&
|
||||||
|
other.address == this.address &&
|
||||||
other.date == this.date &&
|
other.date == this.date &&
|
||||||
other.createdAt == this.createdAt);
|
other.createdAt == this.createdAt);
|
||||||
}
|
}
|
||||||
@@ -248,6 +279,7 @@ class SessionsCompanion extends UpdateCompanion<Session> {
|
|||||||
final Value<String> title;
|
final Value<String> title;
|
||||||
final Value<String> content;
|
final Value<String> content;
|
||||||
final Value<SessionStatus> status;
|
final Value<SessionStatus> status;
|
||||||
|
final Value<String?> address;
|
||||||
final Value<DateTime?> date;
|
final Value<DateTime?> date;
|
||||||
final Value<DateTime> createdAt;
|
final Value<DateTime> createdAt;
|
||||||
const SessionsCompanion({
|
const SessionsCompanion({
|
||||||
@@ -255,6 +287,7 @@ class SessionsCompanion extends UpdateCompanion<Session> {
|
|||||||
this.title = const Value.absent(),
|
this.title = const Value.absent(),
|
||||||
this.content = const Value.absent(),
|
this.content = const Value.absent(),
|
||||||
this.status = const Value.absent(),
|
this.status = const Value.absent(),
|
||||||
|
this.address = const Value.absent(),
|
||||||
this.date = const Value.absent(),
|
this.date = const Value.absent(),
|
||||||
this.createdAt = const Value.absent(),
|
this.createdAt = const Value.absent(),
|
||||||
});
|
});
|
||||||
@@ -263,6 +296,7 @@ class SessionsCompanion extends UpdateCompanion<Session> {
|
|||||||
required String title,
|
required String title,
|
||||||
required String content,
|
required String content,
|
||||||
required SessionStatus status,
|
required SessionStatus status,
|
||||||
|
this.address = const Value.absent(),
|
||||||
this.date = const Value.absent(),
|
this.date = const Value.absent(),
|
||||||
this.createdAt = const Value.absent(),
|
this.createdAt = const Value.absent(),
|
||||||
}) : title = Value(title),
|
}) : title = Value(title),
|
||||||
@@ -273,6 +307,7 @@ class SessionsCompanion extends UpdateCompanion<Session> {
|
|||||||
Expression<String>? title,
|
Expression<String>? title,
|
||||||
Expression<String>? content,
|
Expression<String>? content,
|
||||||
Expression<String>? status,
|
Expression<String>? status,
|
||||||
|
Expression<String>? address,
|
||||||
Expression<DateTime>? date,
|
Expression<DateTime>? date,
|
||||||
Expression<DateTime>? createdAt,
|
Expression<DateTime>? createdAt,
|
||||||
}) {
|
}) {
|
||||||
@@ -281,6 +316,7 @@ class SessionsCompanion extends UpdateCompanion<Session> {
|
|||||||
if (title != null) 'title': title,
|
if (title != null) 'title': title,
|
||||||
if (content != null) 'body': content,
|
if (content != null) 'body': content,
|
||||||
if (status != null) 'status': status,
|
if (status != null) 'status': status,
|
||||||
|
if (address != null) 'address': address,
|
||||||
if (date != null) 'date': date,
|
if (date != null) 'date': date,
|
||||||
if (createdAt != null) 'created_at': createdAt,
|
if (createdAt != null) 'created_at': createdAt,
|
||||||
});
|
});
|
||||||
@@ -291,6 +327,7 @@ class SessionsCompanion extends UpdateCompanion<Session> {
|
|||||||
Value<String>? title,
|
Value<String>? title,
|
||||||
Value<String>? content,
|
Value<String>? content,
|
||||||
Value<SessionStatus>? status,
|
Value<SessionStatus>? status,
|
||||||
|
Value<String?>? address,
|
||||||
Value<DateTime?>? date,
|
Value<DateTime?>? date,
|
||||||
Value<DateTime>? createdAt}) {
|
Value<DateTime>? createdAt}) {
|
||||||
return SessionsCompanion(
|
return SessionsCompanion(
|
||||||
@@ -298,6 +335,7 @@ class SessionsCompanion extends UpdateCompanion<Session> {
|
|||||||
title: title ?? this.title,
|
title: title ?? this.title,
|
||||||
content: content ?? this.content,
|
content: content ?? this.content,
|
||||||
status: status ?? this.status,
|
status: status ?? this.status,
|
||||||
|
address: address ?? this.address,
|
||||||
date: date ?? this.date,
|
date: date ?? this.date,
|
||||||
createdAt: createdAt ?? this.createdAt,
|
createdAt: createdAt ?? this.createdAt,
|
||||||
);
|
);
|
||||||
@@ -319,6 +357,9 @@ class SessionsCompanion extends UpdateCompanion<Session> {
|
|||||||
map['status'] =
|
map['status'] =
|
||||||
Variable<String>($SessionsTable.$converterstatus.toSql(status.value));
|
Variable<String>($SessionsTable.$converterstatus.toSql(status.value));
|
||||||
}
|
}
|
||||||
|
if (address.present) {
|
||||||
|
map['address'] = Variable<String>(address.value);
|
||||||
|
}
|
||||||
if (date.present) {
|
if (date.present) {
|
||||||
map['date'] = Variable<DateTime>(date.value);
|
map['date'] = Variable<DateTime>(date.value);
|
||||||
}
|
}
|
||||||
@@ -335,6 +376,7 @@ class SessionsCompanion extends UpdateCompanion<Session> {
|
|||||||
..write('title: $title, ')
|
..write('title: $title, ')
|
||||||
..write('content: $content, ')
|
..write('content: $content, ')
|
||||||
..write('status: $status, ')
|
..write('status: $status, ')
|
||||||
|
..write('address: $address, ')
|
||||||
..write('date: $date, ')
|
..write('date: $date, ')
|
||||||
..write('createdAt: $createdAt')
|
..write('createdAt: $createdAt')
|
||||||
..write(')'))
|
..write(')'))
|
||||||
@@ -714,8 +756,8 @@ class $SessionActivitiesTable extends SessionActivities
|
|||||||
'session_id', aliasedName, false,
|
'session_id', aliasedName, false,
|
||||||
type: DriftSqlType.int,
|
type: DriftSqlType.int,
|
||||||
requiredDuringInsert: true,
|
requiredDuringInsert: true,
|
||||||
defaultConstraints:
|
defaultConstraints: GeneratedColumn.constraintIsAlways(
|
||||||
GeneratedColumn.constraintIsAlways('REFERENCES sessions (id)'));
|
'REFERENCES sessions (id) ON DELETE CASCADE'));
|
||||||
static const VerificationMeta _activityIdMeta =
|
static const VerificationMeta _activityIdMeta =
|
||||||
const VerificationMeta('activityId');
|
const VerificationMeta('activityId');
|
||||||
@override
|
@override
|
||||||
@@ -723,8 +765,8 @@ class $SessionActivitiesTable extends SessionActivities
|
|||||||
'activity_id', aliasedName, false,
|
'activity_id', aliasedName, false,
|
||||||
type: DriftSqlType.int,
|
type: DriftSqlType.int,
|
||||||
requiredDuringInsert: true,
|
requiredDuringInsert: true,
|
||||||
defaultConstraints:
|
defaultConstraints: GeneratedColumn.constraintIsAlways(
|
||||||
GeneratedColumn.constraintIsAlways('REFERENCES activities (id)'));
|
'REFERENCES activities (id) ON DELETE CASCADE'));
|
||||||
static const VerificationMeta _positionMeta =
|
static const VerificationMeta _positionMeta =
|
||||||
const VerificationMeta('position');
|
const VerificationMeta('position');
|
||||||
@override
|
@override
|
||||||
@@ -1402,8 +1444,8 @@ class $ActivityActionsTable extends ActivityActions
|
|||||||
'activity_id', aliasedName, false,
|
'activity_id', aliasedName, false,
|
||||||
type: DriftSqlType.int,
|
type: DriftSqlType.int,
|
||||||
requiredDuringInsert: true,
|
requiredDuringInsert: true,
|
||||||
defaultConstraints:
|
defaultConstraints: GeneratedColumn.constraintIsAlways(
|
||||||
GeneratedColumn.constraintIsAlways('REFERENCES activities (id)'));
|
'REFERENCES activities (id) ON DELETE CASCADE'));
|
||||||
static const VerificationMeta _actionIdMeta =
|
static const VerificationMeta _actionIdMeta =
|
||||||
const VerificationMeta('actionId');
|
const VerificationMeta('actionId');
|
||||||
@override
|
@override
|
||||||
@@ -1411,8 +1453,8 @@ class $ActivityActionsTable extends ActivityActions
|
|||||||
'action_id', aliasedName, false,
|
'action_id', aliasedName, false,
|
||||||
type: DriftSqlType.int,
|
type: DriftSqlType.int,
|
||||||
requiredDuringInsert: true,
|
requiredDuringInsert: true,
|
||||||
defaultConstraints:
|
defaultConstraints: GeneratedColumn.constraintIsAlways(
|
||||||
GeneratedColumn.constraintIsAlways('REFERENCES actions (id)'));
|
'REFERENCES actions (id) ON DELETE CASCADE'));
|
||||||
static const VerificationMeta _positionMeta =
|
static const VerificationMeta _positionMeta =
|
||||||
const VerificationMeta('position');
|
const VerificationMeta('position');
|
||||||
@override
|
@override
|
||||||
@@ -1722,10 +1764,7 @@ class $MediaItemsTable extends MediaItems
|
|||||||
@override
|
@override
|
||||||
late final GeneratedColumn<String> reference = GeneratedColumn<String>(
|
late final GeneratedColumn<String> reference = GeneratedColumn<String>(
|
||||||
'reference', aliasedName, false,
|
'reference', aliasedName, false,
|
||||||
additionalChecks:
|
type: DriftSqlType.string, requiredDuringInsert: true);
|
||||||
GeneratedColumn.checkTextLength(minTextLength: 3, maxTextLength: 256),
|
|
||||||
type: DriftSqlType.string,
|
|
||||||
requiredDuringInsert: true);
|
|
||||||
static const VerificationMeta _typeMeta = const VerificationMeta('type');
|
static const VerificationMeta _typeMeta = const VerificationMeta('type');
|
||||||
@override
|
@override
|
||||||
late final GeneratedColumnWithTypeConverter<MediaType, String> type =
|
late final GeneratedColumnWithTypeConverter<MediaType, String> type =
|
||||||
@@ -2070,8 +2109,8 @@ class $ObjectMediaItemsTable extends ObjectMediaItems
|
|||||||
'media_id', aliasedName, false,
|
'media_id', aliasedName, false,
|
||||||
type: DriftSqlType.int,
|
type: DriftSqlType.int,
|
||||||
requiredDuringInsert: true,
|
requiredDuringInsert: true,
|
||||||
defaultConstraints:
|
defaultConstraints: GeneratedColumn.constraintIsAlways(
|
||||||
GeneratedColumn.constraintIsAlways('REFERENCES media_items (id)'));
|
'REFERENCES media_items (id) ON DELETE CASCADE'));
|
||||||
static const VerificationMeta _createdAtMeta =
|
static const VerificationMeta _createdAtMeta =
|
||||||
const VerificationMeta('createdAt');
|
const VerificationMeta('createdAt');
|
||||||
@override
|
@override
|
||||||
@@ -2359,6 +2398,8 @@ abstract class _$AppDatabase extends GeneratedDatabase {
|
|||||||
late final SessionsDao sessionsDao = SessionsDao(this as AppDatabase);
|
late final SessionsDao sessionsDao = SessionsDao(this as AppDatabase);
|
||||||
late final ActivitiesDao activitiesDao = ActivitiesDao(this as AppDatabase);
|
late final ActivitiesDao activitiesDao = ActivitiesDao(this as AppDatabase);
|
||||||
late final MediaItemsDao mediaItemsDao = MediaItemsDao(this as AppDatabase);
|
late final MediaItemsDao mediaItemsDao = MediaItemsDao(this as AppDatabase);
|
||||||
|
late final ObjectMediaItemsDao objectMediaItemsDao =
|
||||||
|
ObjectMediaItemsDao(this as AppDatabase);
|
||||||
late final SessionActivitiesDao sessionActivitiesDao =
|
late final SessionActivitiesDao sessionActivitiesDao =
|
||||||
SessionActivitiesDao(this as AppDatabase);
|
SessionActivitiesDao(this as AppDatabase);
|
||||||
late final ActivityActionsDao activityActionsDao =
|
late final ActivityActionsDao activityActionsDao =
|
||||||
@@ -2377,6 +2418,46 @@ abstract class _$AppDatabase extends GeneratedDatabase {
|
|||||||
mediaItems,
|
mediaItems,
|
||||||
objectMediaItems
|
objectMediaItems
|
||||||
];
|
];
|
||||||
|
@override
|
||||||
|
StreamQueryUpdateRules get streamUpdateRules => const StreamQueryUpdateRules(
|
||||||
|
[
|
||||||
|
WritePropagation(
|
||||||
|
on: TableUpdateQuery.onTableName('sessions',
|
||||||
|
limitUpdateKind: UpdateKind.delete),
|
||||||
|
result: [
|
||||||
|
TableUpdate('session_activities', kind: UpdateKind.delete),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
WritePropagation(
|
||||||
|
on: TableUpdateQuery.onTableName('activities',
|
||||||
|
limitUpdateKind: UpdateKind.delete),
|
||||||
|
result: [
|
||||||
|
TableUpdate('session_activities', kind: UpdateKind.delete),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
WritePropagation(
|
||||||
|
on: TableUpdateQuery.onTableName('activities',
|
||||||
|
limitUpdateKind: UpdateKind.delete),
|
||||||
|
result: [
|
||||||
|
TableUpdate('activity_actions', kind: UpdateKind.delete),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
WritePropagation(
|
||||||
|
on: TableUpdateQuery.onTableName('actions',
|
||||||
|
limitUpdateKind: UpdateKind.delete),
|
||||||
|
result: [
|
||||||
|
TableUpdate('activity_actions', kind: UpdateKind.delete),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
WritePropagation(
|
||||||
|
on: TableUpdateQuery.onTableName('media_items',
|
||||||
|
limitUpdateKind: UpdateKind.delete),
|
||||||
|
result: [
|
||||||
|
TableUpdate('object_media_items', kind: UpdateKind.delete),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef $$SessionsTableCreateCompanionBuilder = SessionsCompanion Function({
|
typedef $$SessionsTableCreateCompanionBuilder = SessionsCompanion Function({
|
||||||
@@ -2384,6 +2465,7 @@ typedef $$SessionsTableCreateCompanionBuilder = SessionsCompanion Function({
|
|||||||
required String title,
|
required String title,
|
||||||
required String content,
|
required String content,
|
||||||
required SessionStatus status,
|
required SessionStatus status,
|
||||||
|
Value<String?> address,
|
||||||
Value<DateTime?> date,
|
Value<DateTime?> date,
|
||||||
Value<DateTime> createdAt,
|
Value<DateTime> createdAt,
|
||||||
});
|
});
|
||||||
@@ -2392,6 +2474,7 @@ typedef $$SessionsTableUpdateCompanionBuilder = SessionsCompanion Function({
|
|||||||
Value<String> title,
|
Value<String> title,
|
||||||
Value<String> content,
|
Value<String> content,
|
||||||
Value<SessionStatus> status,
|
Value<SessionStatus> status,
|
||||||
|
Value<String?> address,
|
||||||
Value<DateTime?> date,
|
Value<DateTime?> date,
|
||||||
Value<DateTime> createdAt,
|
Value<DateTime> createdAt,
|
||||||
});
|
});
|
||||||
@@ -2441,6 +2524,9 @@ class $$SessionsTableFilterComposer
|
|||||||
column: $table.status,
|
column: $table.status,
|
||||||
builder: (column) => ColumnWithTypeConverterFilters(column));
|
builder: (column) => ColumnWithTypeConverterFilters(column));
|
||||||
|
|
||||||
|
ColumnFilters<String> get address => $composableBuilder(
|
||||||
|
column: $table.address, builder: (column) => ColumnFilters(column));
|
||||||
|
|
||||||
ColumnFilters<DateTime> get date => $composableBuilder(
|
ColumnFilters<DateTime> get date => $composableBuilder(
|
||||||
column: $table.date, builder: (column) => ColumnFilters(column));
|
column: $table.date, builder: (column) => ColumnFilters(column));
|
||||||
|
|
||||||
@@ -2490,6 +2576,9 @@ class $$SessionsTableOrderingComposer
|
|||||||
ColumnOrderings<String> get status => $composableBuilder(
|
ColumnOrderings<String> get status => $composableBuilder(
|
||||||
column: $table.status, builder: (column) => ColumnOrderings(column));
|
column: $table.status, builder: (column) => ColumnOrderings(column));
|
||||||
|
|
||||||
|
ColumnOrderings<String> get address => $composableBuilder(
|
||||||
|
column: $table.address, builder: (column) => ColumnOrderings(column));
|
||||||
|
|
||||||
ColumnOrderings<DateTime> get date => $composableBuilder(
|
ColumnOrderings<DateTime> get date => $composableBuilder(
|
||||||
column: $table.date, builder: (column) => ColumnOrderings(column));
|
column: $table.date, builder: (column) => ColumnOrderings(column));
|
||||||
|
|
||||||
@@ -2518,6 +2607,9 @@ class $$SessionsTableAnnotationComposer
|
|||||||
GeneratedColumnWithTypeConverter<SessionStatus, String> get status =>
|
GeneratedColumnWithTypeConverter<SessionStatus, String> get status =>
|
||||||
$composableBuilder(column: $table.status, builder: (column) => column);
|
$composableBuilder(column: $table.status, builder: (column) => column);
|
||||||
|
|
||||||
|
GeneratedColumn<String> get address =>
|
||||||
|
$composableBuilder(column: $table.address, builder: (column) => column);
|
||||||
|
|
||||||
GeneratedColumn<DateTime> get date =>
|
GeneratedColumn<DateTime> get date =>
|
||||||
$composableBuilder(column: $table.date, builder: (column) => column);
|
$composableBuilder(column: $table.date, builder: (column) => column);
|
||||||
|
|
||||||
@@ -2574,6 +2666,7 @@ class $$SessionsTableTableManager extends RootTableManager<
|
|||||||
Value<String> title = const Value.absent(),
|
Value<String> title = const Value.absent(),
|
||||||
Value<String> content = const Value.absent(),
|
Value<String> content = const Value.absent(),
|
||||||
Value<SessionStatus> status = const Value.absent(),
|
Value<SessionStatus> status = const Value.absent(),
|
||||||
|
Value<String?> address = const Value.absent(),
|
||||||
Value<DateTime?> date = const Value.absent(),
|
Value<DateTime?> date = const Value.absent(),
|
||||||
Value<DateTime> createdAt = const Value.absent(),
|
Value<DateTime> createdAt = const Value.absent(),
|
||||||
}) =>
|
}) =>
|
||||||
@@ -2582,6 +2675,7 @@ class $$SessionsTableTableManager extends RootTableManager<
|
|||||||
title: title,
|
title: title,
|
||||||
content: content,
|
content: content,
|
||||||
status: status,
|
status: status,
|
||||||
|
address: address,
|
||||||
date: date,
|
date: date,
|
||||||
createdAt: createdAt,
|
createdAt: createdAt,
|
||||||
),
|
),
|
||||||
@@ -2590,6 +2684,7 @@ class $$SessionsTableTableManager extends RootTableManager<
|
|||||||
required String title,
|
required String title,
|
||||||
required String content,
|
required String content,
|
||||||
required SessionStatus status,
|
required SessionStatus status,
|
||||||
|
Value<String?> address = const Value.absent(),
|
||||||
Value<DateTime?> date = const Value.absent(),
|
Value<DateTime?> date = const Value.absent(),
|
||||||
Value<DateTime> createdAt = const Value.absent(),
|
Value<DateTime> createdAt = const Value.absent(),
|
||||||
}) =>
|
}) =>
|
||||||
@@ -2598,6 +2693,7 @@ class $$SessionsTableTableManager extends RootTableManager<
|
|||||||
title: title,
|
title: title,
|
||||||
content: content,
|
content: content,
|
||||||
status: status,
|
status: status,
|
||||||
|
address: address,
|
||||||
date: date,
|
date: date,
|
||||||
createdAt: createdAt,
|
createdAt: createdAt,
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -647,10 +647,857 @@ class Shape10 extends i0.VersionedTable {
|
|||||||
columnsByName['created_at']! as i1.GeneratedColumn<DateTime>;
|
columnsByName['created_at']! as i1.GeneratedColumn<DateTime>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final class Schema5 extends i0.VersionedSchema {
|
||||||
|
Schema5({required super.database}) : super(version: 5);
|
||||||
|
@override
|
||||||
|
late final List<i1.DatabaseSchemaEntity> entities = [
|
||||||
|
sessions,
|
||||||
|
activities,
|
||||||
|
sessionActivities,
|
||||||
|
actions,
|
||||||
|
activityActions,
|
||||||
|
mediaItems,
|
||||||
|
objectMediaItems,
|
||||||
|
];
|
||||||
|
late final Shape11 sessions = Shape11(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'sessions',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [],
|
||||||
|
columns: [
|
||||||
|
_column_0,
|
||||||
|
_column_1,
|
||||||
|
_column_2,
|
||||||
|
_column_3,
|
||||||
|
_column_20,
|
||||||
|
_column_4,
|
||||||
|
_column_5,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape1 activities = Shape1(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'activities',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [],
|
||||||
|
columns: [
|
||||||
|
_column_0,
|
||||||
|
_column_1,
|
||||||
|
_column_6,
|
||||||
|
_column_2,
|
||||||
|
_column_7,
|
||||||
|
_column_5,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape9 sessionActivities = Shape9(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'session_activities',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [],
|
||||||
|
columns: [
|
||||||
|
_column_0,
|
||||||
|
_column_8,
|
||||||
|
_column_9,
|
||||||
|
_column_19,
|
||||||
|
_column_10,
|
||||||
|
_column_11,
|
||||||
|
_column_5,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape3 actions = Shape3(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'actions',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [],
|
||||||
|
columns: [
|
||||||
|
_column_0,
|
||||||
|
_column_1,
|
||||||
|
_column_2,
|
||||||
|
_column_12,
|
||||||
|
_column_5,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape10 activityActions = Shape10(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'activity_actions',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [],
|
||||||
|
columns: [
|
||||||
|
_column_0,
|
||||||
|
_column_9,
|
||||||
|
_column_13,
|
||||||
|
_column_19,
|
||||||
|
_column_5,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape5 mediaItems = Shape5(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'media_items',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [],
|
||||||
|
columns: [
|
||||||
|
_column_0,
|
||||||
|
_column_1,
|
||||||
|
_column_2,
|
||||||
|
_column_14,
|
||||||
|
_column_6,
|
||||||
|
_column_5,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape6 objectMediaItems = Shape6(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'object_media_items',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [],
|
||||||
|
columns: [
|
||||||
|
_column_0,
|
||||||
|
_column_15,
|
||||||
|
_column_16,
|
||||||
|
_column_17,
|
||||||
|
_column_5,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
}
|
||||||
|
|
||||||
|
class Shape11 extends i0.VersionedTable {
|
||||||
|
Shape11({required super.source, required super.alias}) : super.aliased();
|
||||||
|
i1.GeneratedColumn<int> get id =>
|
||||||
|
columnsByName['id']! as i1.GeneratedColumn<int>;
|
||||||
|
i1.GeneratedColumn<String> get title =>
|
||||||
|
columnsByName['title']! as i1.GeneratedColumn<String>;
|
||||||
|
i1.GeneratedColumn<String> get content =>
|
||||||
|
columnsByName['body']! as i1.GeneratedColumn<String>;
|
||||||
|
i1.GeneratedColumn<String> get status =>
|
||||||
|
columnsByName['status']! as i1.GeneratedColumn<String>;
|
||||||
|
i1.GeneratedColumn<String> get address =>
|
||||||
|
columnsByName['address']! as i1.GeneratedColumn<String>;
|
||||||
|
i1.GeneratedColumn<DateTime> get date =>
|
||||||
|
columnsByName['date']! as i1.GeneratedColumn<DateTime>;
|
||||||
|
i1.GeneratedColumn<DateTime> get createdAt =>
|
||||||
|
columnsByName['created_at']! as i1.GeneratedColumn<DateTime>;
|
||||||
|
}
|
||||||
|
|
||||||
|
i1.GeneratedColumn<String> _column_20(String aliasedName) =>
|
||||||
|
i1.GeneratedColumn<String>('address', aliasedName, true,
|
||||||
|
additionalChecks: i1.GeneratedColumn.checkTextLength(
|
||||||
|
minTextLength: 3, maxTextLength: 256),
|
||||||
|
type: i1.DriftSqlType.string);
|
||||||
|
|
||||||
|
final class Schema6 extends i0.VersionedSchema {
|
||||||
|
Schema6({required super.database}) : super(version: 6);
|
||||||
|
@override
|
||||||
|
late final List<i1.DatabaseSchemaEntity> entities = [
|
||||||
|
sessions,
|
||||||
|
activities,
|
||||||
|
sessionActivities,
|
||||||
|
actions,
|
||||||
|
activityActions,
|
||||||
|
mediaItems,
|
||||||
|
objectMediaItems,
|
||||||
|
];
|
||||||
|
late final Shape11 sessions = Shape11(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'sessions',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [],
|
||||||
|
columns: [
|
||||||
|
_column_0,
|
||||||
|
_column_1,
|
||||||
|
_column_2,
|
||||||
|
_column_3,
|
||||||
|
_column_20,
|
||||||
|
_column_4,
|
||||||
|
_column_5,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape1 activities = Shape1(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'activities',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [],
|
||||||
|
columns: [
|
||||||
|
_column_0,
|
||||||
|
_column_1,
|
||||||
|
_column_6,
|
||||||
|
_column_2,
|
||||||
|
_column_7,
|
||||||
|
_column_5,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape9 sessionActivities = Shape9(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'session_activities',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [],
|
||||||
|
columns: [
|
||||||
|
_column_0,
|
||||||
|
_column_21,
|
||||||
|
_column_22,
|
||||||
|
_column_19,
|
||||||
|
_column_10,
|
||||||
|
_column_11,
|
||||||
|
_column_5,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape3 actions = Shape3(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'actions',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [],
|
||||||
|
columns: [
|
||||||
|
_column_0,
|
||||||
|
_column_1,
|
||||||
|
_column_2,
|
||||||
|
_column_12,
|
||||||
|
_column_5,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape10 activityActions = Shape10(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'activity_actions',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [],
|
||||||
|
columns: [
|
||||||
|
_column_0,
|
||||||
|
_column_22,
|
||||||
|
_column_23,
|
||||||
|
_column_19,
|
||||||
|
_column_5,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape5 mediaItems = Shape5(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'media_items',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [],
|
||||||
|
columns: [
|
||||||
|
_column_0,
|
||||||
|
_column_1,
|
||||||
|
_column_2,
|
||||||
|
_column_14,
|
||||||
|
_column_6,
|
||||||
|
_column_5,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape6 objectMediaItems = Shape6(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'object_media_items',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [],
|
||||||
|
columns: [
|
||||||
|
_column_0,
|
||||||
|
_column_15,
|
||||||
|
_column_16,
|
||||||
|
_column_24,
|
||||||
|
_column_5,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
}
|
||||||
|
|
||||||
|
i1.GeneratedColumn<int> _column_21(String aliasedName) =>
|
||||||
|
i1.GeneratedColumn<int>('session_id', aliasedName, false,
|
||||||
|
type: i1.DriftSqlType.int,
|
||||||
|
defaultConstraints: i1.GeneratedColumn.constraintIsAlways(
|
||||||
|
'REFERENCES sessions (id) ON DELETE CASCADE'));
|
||||||
|
i1.GeneratedColumn<int> _column_22(String aliasedName) =>
|
||||||
|
i1.GeneratedColumn<int>('activity_id', aliasedName, false,
|
||||||
|
type: i1.DriftSqlType.int,
|
||||||
|
defaultConstraints: i1.GeneratedColumn.constraintIsAlways(
|
||||||
|
'REFERENCES activities (id) ON DELETE CASCADE'));
|
||||||
|
i1.GeneratedColumn<int> _column_23(String aliasedName) =>
|
||||||
|
i1.GeneratedColumn<int>('action_id', aliasedName, false,
|
||||||
|
type: i1.DriftSqlType.int,
|
||||||
|
defaultConstraints: i1.GeneratedColumn.constraintIsAlways(
|
||||||
|
'REFERENCES actions (id) ON DELETE CASCADE'));
|
||||||
|
i1.GeneratedColumn<int> _column_24(String aliasedName) =>
|
||||||
|
i1.GeneratedColumn<int>('media_id', aliasedName, false,
|
||||||
|
type: i1.DriftSqlType.int,
|
||||||
|
defaultConstraints: i1.GeneratedColumn.constraintIsAlways(
|
||||||
|
'REFERENCES media_items (id) ON DELETE CASCADE'));
|
||||||
|
|
||||||
|
final class Schema7 extends i0.VersionedSchema {
|
||||||
|
Schema7({required super.database}) : super(version: 7);
|
||||||
|
@override
|
||||||
|
late final List<i1.DatabaseSchemaEntity> entities = [
|
||||||
|
sessions,
|
||||||
|
activities,
|
||||||
|
sessionActivities,
|
||||||
|
actions,
|
||||||
|
activityActions,
|
||||||
|
mediaItems,
|
||||||
|
objectMediaItems,
|
||||||
|
];
|
||||||
|
late final Shape11 sessions = Shape11(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'sessions',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [],
|
||||||
|
columns: [
|
||||||
|
_column_0,
|
||||||
|
_column_1,
|
||||||
|
_column_2,
|
||||||
|
_column_3,
|
||||||
|
_column_20,
|
||||||
|
_column_4,
|
||||||
|
_column_5,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape1 activities = Shape1(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'activities',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [],
|
||||||
|
columns: [
|
||||||
|
_column_0,
|
||||||
|
_column_1,
|
||||||
|
_column_6,
|
||||||
|
_column_2,
|
||||||
|
_column_7,
|
||||||
|
_column_5,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape9 sessionActivities = Shape9(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'session_activities',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [],
|
||||||
|
columns: [
|
||||||
|
_column_0,
|
||||||
|
_column_21,
|
||||||
|
_column_22,
|
||||||
|
_column_19,
|
||||||
|
_column_10,
|
||||||
|
_column_11,
|
||||||
|
_column_5,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape3 actions = Shape3(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'actions',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [],
|
||||||
|
columns: [
|
||||||
|
_column_0,
|
||||||
|
_column_1,
|
||||||
|
_column_2,
|
||||||
|
_column_12,
|
||||||
|
_column_5,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape10 activityActions = Shape10(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'activity_actions',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [],
|
||||||
|
columns: [
|
||||||
|
_column_0,
|
||||||
|
_column_22,
|
||||||
|
_column_23,
|
||||||
|
_column_19,
|
||||||
|
_column_5,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape5 mediaItems = Shape5(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'media_items',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [],
|
||||||
|
columns: [
|
||||||
|
_column_0,
|
||||||
|
_column_1,
|
||||||
|
_column_2,
|
||||||
|
_column_14,
|
||||||
|
_column_6,
|
||||||
|
_column_5,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape6 objectMediaItems = Shape6(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'object_media_items',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [],
|
||||||
|
columns: [
|
||||||
|
_column_0,
|
||||||
|
_column_15,
|
||||||
|
_column_16,
|
||||||
|
_column_24,
|
||||||
|
_column_5,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
}
|
||||||
|
|
||||||
|
final class Schema8 extends i0.VersionedSchema {
|
||||||
|
Schema8({required super.database}) : super(version: 8);
|
||||||
|
@override
|
||||||
|
late final List<i1.DatabaseSchemaEntity> entities = [
|
||||||
|
sessions,
|
||||||
|
activities,
|
||||||
|
sessionActivities,
|
||||||
|
actions,
|
||||||
|
activityActions,
|
||||||
|
mediaItems,
|
||||||
|
objectMediaItems,
|
||||||
|
];
|
||||||
|
late final Shape11 sessions = Shape11(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'sessions',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [],
|
||||||
|
columns: [
|
||||||
|
_column_0,
|
||||||
|
_column_1,
|
||||||
|
_column_2,
|
||||||
|
_column_3,
|
||||||
|
_column_20,
|
||||||
|
_column_4,
|
||||||
|
_column_5,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape1 activities = Shape1(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'activities',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [],
|
||||||
|
columns: [
|
||||||
|
_column_0,
|
||||||
|
_column_1,
|
||||||
|
_column_6,
|
||||||
|
_column_2,
|
||||||
|
_column_7,
|
||||||
|
_column_5,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape9 sessionActivities = Shape9(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'session_activities',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [],
|
||||||
|
columns: [
|
||||||
|
_column_0,
|
||||||
|
_column_21,
|
||||||
|
_column_22,
|
||||||
|
_column_19,
|
||||||
|
_column_10,
|
||||||
|
_column_11,
|
||||||
|
_column_5,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape3 actions = Shape3(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'actions',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [],
|
||||||
|
columns: [
|
||||||
|
_column_0,
|
||||||
|
_column_1,
|
||||||
|
_column_2,
|
||||||
|
_column_12,
|
||||||
|
_column_5,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape10 activityActions = Shape10(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'activity_actions',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [],
|
||||||
|
columns: [
|
||||||
|
_column_0,
|
||||||
|
_column_22,
|
||||||
|
_column_23,
|
||||||
|
_column_19,
|
||||||
|
_column_5,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape5 mediaItems = Shape5(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'media_items',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [],
|
||||||
|
columns: [
|
||||||
|
_column_0,
|
||||||
|
_column_1,
|
||||||
|
_column_2,
|
||||||
|
_column_14,
|
||||||
|
_column_6,
|
||||||
|
_column_5,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape6 objectMediaItems = Shape6(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'object_media_items',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [],
|
||||||
|
columns: [
|
||||||
|
_column_0,
|
||||||
|
_column_15,
|
||||||
|
_column_16,
|
||||||
|
_column_24,
|
||||||
|
_column_5,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
}
|
||||||
|
|
||||||
|
final class Schema9 extends i0.VersionedSchema {
|
||||||
|
Schema9({required super.database}) : super(version: 9);
|
||||||
|
@override
|
||||||
|
late final List<i1.DatabaseSchemaEntity> entities = [
|
||||||
|
sessions,
|
||||||
|
activities,
|
||||||
|
sessionActivities,
|
||||||
|
actions,
|
||||||
|
activityActions,
|
||||||
|
mediaItems,
|
||||||
|
objectMediaItems,
|
||||||
|
];
|
||||||
|
late final Shape11 sessions = Shape11(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'sessions',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [],
|
||||||
|
columns: [
|
||||||
|
_column_0,
|
||||||
|
_column_1,
|
||||||
|
_column_2,
|
||||||
|
_column_3,
|
||||||
|
_column_20,
|
||||||
|
_column_4,
|
||||||
|
_column_5,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape1 activities = Shape1(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'activities',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [],
|
||||||
|
columns: [
|
||||||
|
_column_0,
|
||||||
|
_column_1,
|
||||||
|
_column_6,
|
||||||
|
_column_2,
|
||||||
|
_column_7,
|
||||||
|
_column_5,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape9 sessionActivities = Shape9(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'session_activities',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [],
|
||||||
|
columns: [
|
||||||
|
_column_0,
|
||||||
|
_column_21,
|
||||||
|
_column_22,
|
||||||
|
_column_19,
|
||||||
|
_column_10,
|
||||||
|
_column_11,
|
||||||
|
_column_5,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape3 actions = Shape3(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'actions',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [],
|
||||||
|
columns: [
|
||||||
|
_column_0,
|
||||||
|
_column_1,
|
||||||
|
_column_2,
|
||||||
|
_column_12,
|
||||||
|
_column_5,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape10 activityActions = Shape10(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'activity_actions',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [],
|
||||||
|
columns: [
|
||||||
|
_column_0,
|
||||||
|
_column_22,
|
||||||
|
_column_23,
|
||||||
|
_column_19,
|
||||||
|
_column_5,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape5 mediaItems = Shape5(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'media_items',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [],
|
||||||
|
columns: [
|
||||||
|
_column_0,
|
||||||
|
_column_1,
|
||||||
|
_column_2,
|
||||||
|
_column_25,
|
||||||
|
_column_6,
|
||||||
|
_column_5,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape6 objectMediaItems = Shape6(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'object_media_items',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [],
|
||||||
|
columns: [
|
||||||
|
_column_0,
|
||||||
|
_column_15,
|
||||||
|
_column_16,
|
||||||
|
_column_24,
|
||||||
|
_column_5,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
}
|
||||||
|
|
||||||
|
i1.GeneratedColumn<String> _column_25(String aliasedName) =>
|
||||||
|
i1.GeneratedColumn<String>('reference', aliasedName, false,
|
||||||
|
type: i1.DriftSqlType.string);
|
||||||
|
|
||||||
|
final class Schema10 extends i0.VersionedSchema {
|
||||||
|
Schema10({required super.database}) : super(version: 10);
|
||||||
|
@override
|
||||||
|
late final List<i1.DatabaseSchemaEntity> entities = [
|
||||||
|
sessions,
|
||||||
|
activities,
|
||||||
|
sessionActivities,
|
||||||
|
actions,
|
||||||
|
activityActions,
|
||||||
|
mediaItems,
|
||||||
|
objectMediaItems,
|
||||||
|
];
|
||||||
|
late final Shape11 sessions = Shape11(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'sessions',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [],
|
||||||
|
columns: [
|
||||||
|
_column_0,
|
||||||
|
_column_1,
|
||||||
|
_column_2,
|
||||||
|
_column_3,
|
||||||
|
_column_20,
|
||||||
|
_column_4,
|
||||||
|
_column_5,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape1 activities = Shape1(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'activities',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [],
|
||||||
|
columns: [
|
||||||
|
_column_0,
|
||||||
|
_column_1,
|
||||||
|
_column_6,
|
||||||
|
_column_2,
|
||||||
|
_column_7,
|
||||||
|
_column_5,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape9 sessionActivities = Shape9(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'session_activities',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [],
|
||||||
|
columns: [
|
||||||
|
_column_0,
|
||||||
|
_column_21,
|
||||||
|
_column_22,
|
||||||
|
_column_19,
|
||||||
|
_column_10,
|
||||||
|
_column_11,
|
||||||
|
_column_5,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape3 actions = Shape3(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'actions',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [],
|
||||||
|
columns: [
|
||||||
|
_column_0,
|
||||||
|
_column_1,
|
||||||
|
_column_2,
|
||||||
|
_column_12,
|
||||||
|
_column_5,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape10 activityActions = Shape10(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'activity_actions',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [],
|
||||||
|
columns: [
|
||||||
|
_column_0,
|
||||||
|
_column_22,
|
||||||
|
_column_23,
|
||||||
|
_column_19,
|
||||||
|
_column_5,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape5 mediaItems = Shape5(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'media_items',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [],
|
||||||
|
columns: [
|
||||||
|
_column_0,
|
||||||
|
_column_1,
|
||||||
|
_column_2,
|
||||||
|
_column_25,
|
||||||
|
_column_6,
|
||||||
|
_column_5,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape6 objectMediaItems = Shape6(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'object_media_items',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [],
|
||||||
|
columns: [
|
||||||
|
_column_0,
|
||||||
|
_column_15,
|
||||||
|
_column_16,
|
||||||
|
_column_24,
|
||||||
|
_column_5,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
}
|
||||||
|
|
||||||
i0.MigrationStepWithVersion migrationSteps({
|
i0.MigrationStepWithVersion migrationSteps({
|
||||||
required Future<void> Function(i1.Migrator m, Schema2 schema) from1To2,
|
required Future<void> Function(i1.Migrator m, Schema2 schema) from1To2,
|
||||||
required Future<void> Function(i1.Migrator m, Schema3 schema) from2To3,
|
required Future<void> Function(i1.Migrator m, Schema3 schema) from2To3,
|
||||||
required Future<void> Function(i1.Migrator m, Schema4 schema) from3To4,
|
required Future<void> Function(i1.Migrator m, Schema4 schema) from3To4,
|
||||||
|
required Future<void> Function(i1.Migrator m, Schema5 schema) from4To5,
|
||||||
|
required Future<void> Function(i1.Migrator m, Schema6 schema) from5To6,
|
||||||
|
required Future<void> Function(i1.Migrator m, Schema7 schema) from6To7,
|
||||||
|
required Future<void> Function(i1.Migrator m, Schema8 schema) from7To8,
|
||||||
|
required Future<void> Function(i1.Migrator m, Schema9 schema) from8To9,
|
||||||
|
required Future<void> Function(i1.Migrator m, Schema10 schema) from9To10,
|
||||||
}) {
|
}) {
|
||||||
return (currentVersion, database) async {
|
return (currentVersion, database) async {
|
||||||
switch (currentVersion) {
|
switch (currentVersion) {
|
||||||
@@ -669,6 +1516,36 @@ i0.MigrationStepWithVersion migrationSteps({
|
|||||||
final migrator = i1.Migrator(database, schema);
|
final migrator = i1.Migrator(database, schema);
|
||||||
await from3To4(migrator, schema);
|
await from3To4(migrator, schema);
|
||||||
return 4;
|
return 4;
|
||||||
|
case 4:
|
||||||
|
final schema = Schema5(database: database);
|
||||||
|
final migrator = i1.Migrator(database, schema);
|
||||||
|
await from4To5(migrator, schema);
|
||||||
|
return 5;
|
||||||
|
case 5:
|
||||||
|
final schema = Schema6(database: database);
|
||||||
|
final migrator = i1.Migrator(database, schema);
|
||||||
|
await from5To6(migrator, schema);
|
||||||
|
return 6;
|
||||||
|
case 6:
|
||||||
|
final schema = Schema7(database: database);
|
||||||
|
final migrator = i1.Migrator(database, schema);
|
||||||
|
await from6To7(migrator, schema);
|
||||||
|
return 7;
|
||||||
|
case 7:
|
||||||
|
final schema = Schema8(database: database);
|
||||||
|
final migrator = i1.Migrator(database, schema);
|
||||||
|
await from7To8(migrator, schema);
|
||||||
|
return 8;
|
||||||
|
case 8:
|
||||||
|
final schema = Schema9(database: database);
|
||||||
|
final migrator = i1.Migrator(database, schema);
|
||||||
|
await from8To9(migrator, schema);
|
||||||
|
return 9;
|
||||||
|
case 9:
|
||||||
|
final schema = Schema10(database: database);
|
||||||
|
final migrator = i1.Migrator(database, schema);
|
||||||
|
await from9To10(migrator, schema);
|
||||||
|
return 10;
|
||||||
default:
|
default:
|
||||||
throw ArgumentError.value('Unknown migration from $currentVersion');
|
throw ArgumentError.value('Unknown migration from $currentVersion');
|
||||||
}
|
}
|
||||||
@@ -679,10 +1556,22 @@ i1.OnUpgrade stepByStep({
|
|||||||
required Future<void> Function(i1.Migrator m, Schema2 schema) from1To2,
|
required Future<void> Function(i1.Migrator m, Schema2 schema) from1To2,
|
||||||
required Future<void> Function(i1.Migrator m, Schema3 schema) from2To3,
|
required Future<void> Function(i1.Migrator m, Schema3 schema) from2To3,
|
||||||
required Future<void> Function(i1.Migrator m, Schema4 schema) from3To4,
|
required Future<void> Function(i1.Migrator m, Schema4 schema) from3To4,
|
||||||
|
required Future<void> Function(i1.Migrator m, Schema5 schema) from4To5,
|
||||||
|
required Future<void> Function(i1.Migrator m, Schema6 schema) from5To6,
|
||||||
|
required Future<void> Function(i1.Migrator m, Schema7 schema) from6To7,
|
||||||
|
required Future<void> Function(i1.Migrator m, Schema8 schema) from7To8,
|
||||||
|
required Future<void> Function(i1.Migrator m, Schema9 schema) from8To9,
|
||||||
|
required Future<void> Function(i1.Migrator m, Schema10 schema) from9To10,
|
||||||
}) =>
|
}) =>
|
||||||
i0.VersionedSchema.stepByStepHelper(
|
i0.VersionedSchema.stepByStepHelper(
|
||||||
step: migrationSteps(
|
step: migrationSteps(
|
||||||
from1To2: from1To2,
|
from1To2: from1To2,
|
||||||
from2To3: from2To3,
|
from2To3: from2To3,
|
||||||
from3To4: from3To4,
|
from3To4: from3To4,
|
||||||
|
from4To5: from4To5,
|
||||||
|
from5To6: from5To6,
|
||||||
|
from6To7: from6To7,
|
||||||
|
from7To8: from7To8,
|
||||||
|
from8To9: from8To9,
|
||||||
|
from9To10: from9To10,
|
||||||
));
|
));
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+26
-3
@@ -7,24 +7,29 @@ Future<void> seedDb(AppDatabase database) async {
|
|||||||
// seed data setup
|
// seed data setup
|
||||||
final List<List> sessionValues = [
|
final List<List> sessionValues = [
|
||||||
[
|
[
|
||||||
'Projecting @ Climbers Rock',
|
'Projecting',
|
||||||
'Beta pully beta beta pinch one arm crimpy. Futuristic pinch, dyno dynamic drop knee climb. Climbing ondra slopey onsight beta ondra power endurance.'
|
'Beta pully beta beta pinch one arm crimpy. Futuristic pinch, dyno dynamic drop knee climb. Climbing ondra slopey onsight beta ondra power endurance.'
|
||||||
|
'Climbers Rock Inc.'
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'Moonboard @ Boardroom',
|
'Moonboard',
|
||||||
'Beta pully beta beta pinch one arm crimpy. Futuristic pinch, dyno dynamic drop knee climb. Climbing ondra slopey onsight beta ondra power endurance.'
|
'Beta pully beta beta pinch one arm crimpy. Futuristic pinch, dyno dynamic drop knee climb. Climbing ondra slopey onsight beta ondra power endurance.'
|
||||||
|
'Beta Bloc'
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'Off-Wall Training',
|
'Off-Wall Training',
|
||||||
'Beta pully beta beta pinch one arm crimpy. Futuristic pinch, dyno dynamic drop knee climb. Climbing ondra slopey onsight beta ondra power endurance.'
|
'Beta pully beta beta pinch one arm crimpy. Futuristic pinch, dyno dynamic drop knee climb. Climbing ondra slopey onsight beta ondra power endurance.'
|
||||||
|
'Climbers Rcok Inc.'
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'Climbing Outdoors',
|
'Climbing Outdoors',
|
||||||
'Beta pully beta beta pinch one arm crimpy. Futuristic pinch, dyno dynamic drop knee climb. Climbing ondra slopey onsight beta ondra power endurance.'
|
'Beta pully beta beta pinch one arm crimpy. Futuristic pinch, dyno dynamic drop knee climb. Climbing ondra slopey onsight beta ondra power endurance.'
|
||||||
|
'Gravity Hamilton'
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'Volume Session @ Gravity',
|
'Volume Session',
|
||||||
'Beta pully beta beta pinch one arm crimpy. Futuristic pinch, dyno dynamic drop knee climb. Climbing ondra slopey onsight beta ondra power endurance.'
|
'Beta pully beta beta pinch one arm crimpy. Futuristic pinch, dyno dynamic drop knee climb. Climbing ondra slopey onsight beta ondra power endurance.'
|
||||||
|
'Up the Bloc'
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -61,6 +66,7 @@ Future<void> seedDb(AppDatabase database) async {
|
|||||||
title: sessionValue[0],
|
title: sessionValue[0],
|
||||||
content: sessionValue[1],
|
content: sessionValue[1],
|
||||||
status: status,
|
status: status,
|
||||||
|
address: sessionValue[2],
|
||||||
date: Value(DateTime.now())))
|
date: Value(DateTime.now())))
|
||||||
.then((sessionId) async {
|
.then((sessionId) async {
|
||||||
// activities things
|
// activities things
|
||||||
@@ -162,6 +168,23 @@ Future<void> seedDb(AppDatabase database) async {
|
|||||||
objectType: ObjectType.sessions));
|
objectType: ObjectType.sessions));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await database
|
||||||
|
.into(database.mediaItems)
|
||||||
|
.insert(MediaItemsCompanion.insert(
|
||||||
|
title: 'Locations details',
|
||||||
|
description:
|
||||||
|
'5155 Harvester Rd #1, Burlington, ON L7L 6V2, Canada',
|
||||||
|
reference:
|
||||||
|
'https://lh3.googleusercontent.com/places/ANXAkqHwtb5oRMGG3haJkaHeTxdTI1lQ17RgvkCXwzA1dGV53BXPbHrdXIs1mLC_-4exyRW8dbYhMOeiOCHJqGeVBx-dNtABZAl9tQA=s4800-w800',
|
||||||
|
type: MediaType.location))
|
||||||
|
.then((mediaId) async {
|
||||||
|
await database.into(database.objectMediaItems).insert(
|
||||||
|
ObjectMediaItemsCompanion.insert(
|
||||||
|
objectId: sessionId,
|
||||||
|
mediaId: mediaId,
|
||||||
|
objectType: ObjectType.sessions));
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
import 'package:intl/intl.dart';
|
||||||
|
|
||||||
|
final DateFormat dateFormat = DateFormat('yyyy-MM-dd');
|
||||||
|
|
||||||
|
String formattedTime(int timeInSecond) {
|
||||||
|
int sec = timeInSecond % 60;
|
||||||
|
int min = (timeInSecond / 60).floor();
|
||||||
|
String minute = min.toString().length <= 1 ? "0$min" : "$min";
|
||||||
|
String second = sec.toString().length <= 1 ? "0$sec" : "$sec";
|
||||||
|
return "$minute:$second";
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:sendtrain/database/database.dart';
|
||||||
|
|
||||||
|
ImageProvider findMediaByType(List<MediaItem> media, MediaType type) {
|
||||||
|
Iterable<MediaItem>? found = media.where((m) => m.type == type);
|
||||||
|
Image image;
|
||||||
|
|
||||||
|
if (found.isNotEmpty) {
|
||||||
|
image = Image.network(found.first.reference);
|
||||||
|
} else {
|
||||||
|
// Element is not found
|
||||||
|
image = Image.asset('assets/images/placeholder.jpg');
|
||||||
|
}
|
||||||
|
|
||||||
|
return image.image;
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:sendtrain/database/database.dart';
|
||||||
|
import 'package:sendtrain/widgets/media/media_details.dart';
|
||||||
|
|
||||||
|
showMediaDetailWidget(BuildContext context, MediaItem media) {
|
||||||
|
showModalBottomSheet<void>(
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(10.0)),
|
||||||
|
),
|
||||||
|
context: context,
|
||||||
|
showDragHandle: true,
|
||||||
|
isScrollControlled: true,
|
||||||
|
useSafeArea: true,
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return MediaDetails(media: media);
|
||||||
|
});
|
||||||
|
}
|
||||||
+32
-6
@@ -2,19 +2,35 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:sendtrain/database/database.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/widgets/screens/activities_screen.dart';
|
||||||
import 'package:sendtrain/screens/sessions_screen.dart';
|
import 'package:sendtrain/widgets/screens/sessions_screen.dart';
|
||||||
// ignore: unused_import
|
// ignore: unused_import
|
||||||
import 'package:sendtrain/database/seed.dart';
|
import 'package:sendtrain/database/seed.dart';
|
||||||
|
import 'package:sendtrain/widgets/sessions/session_editor.dart';
|
||||||
|
|
||||||
class SendTrain extends StatelessWidget {
|
class SendTrain extends StatelessWidget {
|
||||||
const SendTrain({super.key});
|
const SendTrain({super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final ThemeData themeData = ThemeData.dark(useMaterial3: true);
|
||||||
return MaterialApp(
|
return MaterialApp(
|
||||||
title: "Sendtrain",
|
title: "Sendtrain",
|
||||||
theme: ThemeData.dark(useMaterial3: true),
|
theme: themeData.copyWith(
|
||||||
|
filledButtonTheme: FilledButtonThemeData(
|
||||||
|
style: FilledButton.styleFrom(
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
floatingActionButtonTheme: FloatingActionButtonThemeData(
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(12))),
|
||||||
|
inputDecorationTheme: InputDecorationTheme(
|
||||||
|
fillColor: themeData.colorScheme.surface,
|
||||||
|
),
|
||||||
|
),
|
||||||
home: const App());
|
home: const App());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -73,7 +89,7 @@ class _AppState extends State<App> {
|
|||||||
NavigationDestination(
|
NavigationDestination(
|
||||||
icon: Icon(Icons.sports), label: "Sessions"),
|
icon: Icon(Icons.sports), label: "Sessions"),
|
||||||
NavigationDestination(
|
NavigationDestination(
|
||||||
icon: Icon(Icons.landscape), label: "Activities"),
|
icon: Icon(Icons.sports_gymnastics_rounded), label: "Activities"),
|
||||||
NavigationDestination(
|
NavigationDestination(
|
||||||
icon: Icon(Icons.calendar_month_rounded), label: "Plan"),
|
icon: Icon(Icons.calendar_month_rounded), label: "Plan"),
|
||||||
NavigationDestination(
|
NavigationDestination(
|
||||||
@@ -83,11 +99,21 @@ class _AppState extends State<App> {
|
|||||||
]),
|
]),
|
||||||
floatingActionButton: FloatingActionButton.extended(
|
floatingActionButton: FloatingActionButton.extended(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
// Add your onPressed code here!
|
showModalBottomSheet<void>(
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(10.0)),
|
||||||
|
),
|
||||||
|
context: context,
|
||||||
|
showDragHandle: true,
|
||||||
|
isScrollControlled: true,
|
||||||
|
useSafeArea: true,
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return SessionEditor();
|
||||||
|
});
|
||||||
},
|
},
|
||||||
label: const Text('New Session'),
|
label: const Text('New Session'),
|
||||||
icon: const Icon(Icons.add_chart),
|
icon: const Icon(Icons.add_chart),
|
||||||
backgroundColor: Colors.deepPurple,
|
// backgroundColor: Colors.deepPurple,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ class ActivityTimerModel with ChangeNotifier {
|
|||||||
int _actionCounter = 0;
|
int _actionCounter = 0;
|
||||||
Activity? _activity;
|
Activity? _activity;
|
||||||
List _sets = [];
|
List _sets = [];
|
||||||
List _actions = [];
|
// List _actions = [];
|
||||||
int _currentActionNum = 0;
|
int _currentActionNum = 0;
|
||||||
int _currentSetNum = 0;
|
int _currentSetNum = 0;
|
||||||
Timer? _periodicTimer;
|
Timer? _periodicTimer;
|
||||||
@@ -37,7 +37,7 @@ class ActivityTimerModel with ChangeNotifier {
|
|||||||
_activity = activity;
|
_activity = activity;
|
||||||
// only one action for now
|
// only one action for now
|
||||||
_sets = json.decode(actions[0].set);
|
_sets = json.decode(actions[0].set);
|
||||||
_actions = actions;
|
// _actions = actions;
|
||||||
_currentActionNum = 0;
|
_currentActionNum = 0;
|
||||||
_currentSetNum = 0;
|
_currentSetNum = 0;
|
||||||
setActionCount();
|
setActionCount();
|
||||||
|
|||||||
@@ -0,0 +1,99 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
|
import 'package:http/http.dart';
|
||||||
|
import 'package:uuid/uuid.dart';
|
||||||
|
|
||||||
|
class GooglePlacesService {
|
||||||
|
final sessionToken = Uuid().v4();
|
||||||
|
final apiKey = "AIzaSyBCjMCEAyyNVpsnVYvZj6VL1mmB98Vd6AE";
|
||||||
|
final client = Client();
|
||||||
|
|
||||||
|
void finish() {
|
||||||
|
client.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<List<Suggestion>?> fetchSuggestions(String input, String lang) async {
|
||||||
|
var headers = {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'X-Goog-Api-Key': apiKey,
|
||||||
|
"Access-Control-Allow-Origin": "*",
|
||||||
|
'X-Goog-FieldMask':
|
||||||
|
'places.displayName,places.id,places.formattedAddress,places.photos'
|
||||||
|
};
|
||||||
|
var request = Request('POST',
|
||||||
|
Uri.parse('https://places.googleapis.com/v1/places:searchText'));
|
||||||
|
request.body = json.encode({"textQuery": input});
|
||||||
|
request.headers.addAll(headers);
|
||||||
|
|
||||||
|
StreamedResponse response = await request.send();
|
||||||
|
|
||||||
|
if (response.statusCode == 200) {
|
||||||
|
final result = json.decode(await response.stream.bytesToString());
|
||||||
|
|
||||||
|
if (result.isNotEmpty) {
|
||||||
|
return result['places']
|
||||||
|
.map<Suggestion>((p) => Suggestion(
|
||||||
|
placeId: p['id'],
|
||||||
|
description: p['displayName']['text'],
|
||||||
|
address: p['formattedAddress'],
|
||||||
|
imageReferences: p['photos']))
|
||||||
|
.toList();
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw Exception(response.reasonPhrase);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future fetchPhoto(String name) async {
|
||||||
|
var headers = {
|
||||||
|
"Access-Control-Allow-Origin": "*",
|
||||||
|
};
|
||||||
|
|
||||||
|
var request = Request('GET',
|
||||||
|
Uri.parse('https://places.googleapis.com/v1/$name/media?key=$apiKey&maxWidthPx=800&skipHttpRedirect=true')
|
||||||
|
);
|
||||||
|
request.headers.addAll(headers);
|
||||||
|
|
||||||
|
StreamedResponse response = await request.send();
|
||||||
|
|
||||||
|
if (response.statusCode == 200) {
|
||||||
|
final result = json.decode(await response.stream.bytesToString());
|
||||||
|
|
||||||
|
if (result.isNotEmpty) {
|
||||||
|
return result;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw Exception(response.reasonPhrase);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Suggestion {
|
||||||
|
final String placeId;
|
||||||
|
final String description;
|
||||||
|
final String address;
|
||||||
|
final List<dynamic>? imageReferences;
|
||||||
|
|
||||||
|
Suggestion(
|
||||||
|
{required this.placeId,
|
||||||
|
required this.description,
|
||||||
|
required this.address,
|
||||||
|
this.imageReferences});
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'Suggestion(description: $description, placeId: $placeId)';
|
||||||
|
}
|
||||||
|
|
||||||
|
Map toJson() => {
|
||||||
|
'placeId': placeId,
|
||||||
|
'name': description,
|
||||||
|
'address': address,
|
||||||
|
'imageReferences': imageReferences
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
|
||||||
|
typedef _Debounceable<S, T> = Future<S?> Function(T parameter);
|
||||||
|
|
||||||
|
class Debouncer {
|
||||||
|
Debouncer(this._duration, this._callback);
|
||||||
|
|
||||||
|
final Duration _duration;
|
||||||
|
final dynamic _callback;
|
||||||
|
late final _Debounceable<dynamic, String> _debouncedSearch = _debounce<dynamic, String>(_callback);
|
||||||
|
|
||||||
|
/// Returns a new function that is a debounced version of the given function.
|
||||||
|
///
|
||||||
|
/// This means that the original function will be called only after no calls
|
||||||
|
/// have been made for the given Duration.
|
||||||
|
_Debounceable<S, T> _debounce<S, T>(_Debounceable<S?, T> function) {
|
||||||
|
_DebounceTimer? debounceTimer;
|
||||||
|
|
||||||
|
return (T parameter) async {
|
||||||
|
if (debounceTimer != null && !debounceTimer!.isCompleted) {
|
||||||
|
debounceTimer!.cancel();
|
||||||
|
}
|
||||||
|
debounceTimer = _DebounceTimer(_duration);
|
||||||
|
try {
|
||||||
|
await debounceTimer!.future;
|
||||||
|
} on _CancelException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return function(parameter);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
process(data) {
|
||||||
|
return _debouncedSearch(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// A wrapper around Timer used for debouncing.
|
||||||
|
class _DebounceTimer {
|
||||||
|
final Duration debounceDuration;
|
||||||
|
|
||||||
|
_DebounceTimer(
|
||||||
|
this.debounceDuration
|
||||||
|
) {
|
||||||
|
_timer = Timer(debounceDuration, _onComplete);
|
||||||
|
}
|
||||||
|
|
||||||
|
late final Timer _timer;
|
||||||
|
final Completer<void> _completer = Completer<void>();
|
||||||
|
|
||||||
|
void _onComplete() {
|
||||||
|
_completer.complete();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> get future => _completer.future;
|
||||||
|
|
||||||
|
bool get isCompleted => _completer.isCompleted;
|
||||||
|
|
||||||
|
void cancel() {
|
||||||
|
_timer.cancel();
|
||||||
|
_completer.completeError(const _CancelException());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// An exception indicating that the timer was canceled.
|
||||||
|
class _CancelException implements Exception {
|
||||||
|
const _CancelException();
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import '../widgets/activity_type_filter.dart';
|
import 'activity_type_filter.dart';
|
||||||
|
|
||||||
class ActivitiesHeader extends StatefulWidget {
|
class ActivitiesHeader extends StatefulWidget {
|
||||||
const ActivitiesHeader({super.key});
|
const ActivitiesHeader({super.key});
|
||||||
@@ -0,0 +1,101 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
import 'package:sendtrain/daos/activities_dao.dart';
|
||||||
|
import 'package:sendtrain/daos/media_items_dao.dart';
|
||||||
|
import 'package:sendtrain/database/database.dart';
|
||||||
|
import 'package:sendtrain/extensions/string_extensions.dart';
|
||||||
|
import 'package:sendtrain/helpers/date_time_helpers.dart';
|
||||||
|
import 'package:sendtrain/helpers/media_helpers.dart';
|
||||||
|
import 'package:sendtrain/models/activity_timer_model.dart';
|
||||||
|
import 'package:sendtrain/widgets/activities/activity_view.dart';
|
||||||
|
import 'package:sendtrain/widgets/builders/dialogs.dart';
|
||||||
|
import 'package:sendtrain/widgets/generic/elements/card_image.dart';
|
||||||
|
import 'package:sendtrain/widgets/generic/elements/generic_progress_indicator.dart';
|
||||||
|
|
||||||
|
class ActivityCard extends StatefulWidget {
|
||||||
|
final Activity activity;
|
||||||
|
|
||||||
|
const ActivityCard({super.key, required this.activity});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<ActivityCard> createState() => ActivityCardState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class ActivityCardState extends State<ActivityCard> {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final ActivityTimerModel atm =
|
||||||
|
Provider.of<ActivityTimerModel>(context);
|
||||||
|
|
||||||
|
return FutureBuilder<List<MediaItem>>(
|
||||||
|
future: MediaItemsDao(Provider.of<AppDatabase>(context))
|
||||||
|
.fromActivity(widget.activity),
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
if (snapshot.hasData) {
|
||||||
|
List<MediaItem> 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: () => showGenericDialog(
|
||||||
|
ActivityView(activity: widget.activity), context),
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: <Widget>[
|
||||||
|
ListTile(
|
||||||
|
// visualDensity: VisualDensity(horizontal: VisualDensity.maximumDensity),
|
||||||
|
leading: CardImage(
|
||||||
|
image: findMediaByType(mediaItems, MediaType.image)),
|
||||||
|
title: Consumer<ActivityTimerModel>(
|
||||||
|
builder: (context, atm, child) {
|
||||||
|
if (atm.activity?.id == widget.activity.id) {
|
||||||
|
return Text(
|
||||||
|
maxLines: 1,
|
||||||
|
"${widget.activity.title.toTitleCase()} (${formattedTime(atm.totalTime)})");
|
||||||
|
} else {
|
||||||
|
return Text(
|
||||||
|
maxLines: 1,
|
||||||
|
widget.activity.title.toTitleCase());
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
subtitle:
|
||||||
|
Text(maxLines: 2, widget.activity.description),
|
||||||
|
contentPadding: EdgeInsets.only(left: 13),
|
||||||
|
trailing: Flex(
|
||||||
|
direction: Axis.vertical,
|
||||||
|
mainAxisSize: MainAxisSize.max,
|
||||||
|
children: [
|
||||||
|
IconButton(
|
||||||
|
padding: EdgeInsets.all(0),
|
||||||
|
alignment: Alignment.topCenter,
|
||||||
|
visualDensity: VisualDensity.compact,
|
||||||
|
icon: Icon(Icons.close_rounded),
|
||||||
|
onPressed: () {
|
||||||
|
showRemovalDialog(
|
||||||
|
'Activity Removal',
|
||||||
|
'Would you like to permanently remove this activity from the current session?',
|
||||||
|
context,
|
||||||
|
ActivitiesDao(
|
||||||
|
Provider.of<AppDatabase>(
|
||||||
|
context,
|
||||||
|
listen: false)),
|
||||||
|
widget.activity)
|
||||||
|
.then((result) {
|
||||||
|
setState(() {});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
)
|
||||||
|
])),
|
||||||
|
],
|
||||||
|
)),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return GenericProgressIndicator();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,10 +5,10 @@ import 'package:sendtrain/daos/actions_dao.dart';
|
|||||||
import 'package:sendtrain/database/database.dart';
|
import 'package:sendtrain/database/database.dart';
|
||||||
import 'package:sendtrain/extensions/string_extensions.dart';
|
import 'package:sendtrain/extensions/string_extensions.dart';
|
||||||
import 'package:sendtrain/models/activity_timer_model.dart';
|
import 'package:sendtrain/models/activity_timer_model.dart';
|
||||||
import 'package:sendtrain/widgets/activity_action_view.dart';
|
import 'package:sendtrain/widgets/activities/activity_action_view.dart';
|
||||||
import 'package:sendtrain/widgets/activity_view_categories.dart';
|
import 'package:sendtrain/widgets/activities/activity_view_categories.dart';
|
||||||
import 'package:sendtrain/widgets/activity_view_media.dart';
|
import 'package:sendtrain/widgets/activities/activity_view_media.dart';
|
||||||
import 'package:sendtrain/widgets/activity_view_types.dart';
|
import 'package:sendtrain/widgets/activities/activity_view_types.dart';
|
||||||
|
|
||||||
class ActivityView extends StatefulWidget {
|
class ActivityView extends StatefulWidget {
|
||||||
const ActivityView(
|
const ActivityView(
|
||||||
@@ -44,6 +44,16 @@ class _ActivityViewState extends State<ActivityView> {
|
|||||||
blur: 10,
|
blur: 10,
|
||||||
),
|
),
|
||||||
children: [
|
children: [
|
||||||
|
FloatingActionButton.extended(
|
||||||
|
icon: const Icon(Icons.upload_outlined),
|
||||||
|
label: Text('Upload Media'),
|
||||||
|
onPressed: () {},
|
||||||
|
),
|
||||||
|
FloatingActionButton.extended(
|
||||||
|
icon: const Icon(Icons.note_add_outlined),
|
||||||
|
label: Text('Add Note'),
|
||||||
|
onPressed: () {},
|
||||||
|
),
|
||||||
FloatingActionButton.extended(
|
FloatingActionButton.extended(
|
||||||
icon: const Icon(Icons.history_outlined),
|
icon: const Icon(Icons.history_outlined),
|
||||||
label: Text('Restart'),
|
label: Text('Restart'),
|
||||||
@@ -54,11 +64,6 @@ class _ActivityViewState extends State<ActivityView> {
|
|||||||
label: Text('Done'),
|
label: Text('Done'),
|
||||||
onPressed: () {},
|
onPressed: () {},
|
||||||
),
|
),
|
||||||
FloatingActionButton.extended(
|
|
||||||
icon: const Icon(Icons.edit_outlined),
|
|
||||||
label: Text('Edit'),
|
|
||||||
onPressed: () {},
|
|
||||||
),
|
|
||||||
]),
|
]),
|
||||||
body: Column(
|
body: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
+1
-1
@@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:sendtrain/daos/media_items_dao.dart';
|
import 'package:sendtrain/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/media_card.dart';
|
||||||
|
|
||||||
class ActivityViewMedia extends StatelessWidget {
|
class ActivityViewMedia extends StatelessWidget {
|
||||||
const ActivityViewMedia({super.key, required this.activity});
|
const ActivityViewMedia({super.key, required this.activity});
|
||||||
@@ -1,150 +0,0 @@
|
|||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:provider/provider.dart';
|
|
||||||
import 'package:sendtrain/daos/media_items_dao.dart';
|
|
||||||
import 'package:sendtrain/database/database.dart';
|
|
||||||
import 'package:sendtrain/extensions/string_extensions.dart';
|
|
||||||
import 'package:sendtrain/models/activity_timer_model.dart';
|
|
||||||
import 'package:sendtrain/widgets/activity_view.dart';
|
|
||||||
|
|
||||||
class ActivityCard extends StatefulWidget {
|
|
||||||
final Activity activity;
|
|
||||||
|
|
||||||
const ActivityCard({super.key, required this.activity});
|
|
||||||
|
|
||||||
@override
|
|
||||||
State<ActivityCard> createState() => ActivityCardState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class ActivityCardState extends State<ActivityCard> {
|
|
||||||
String formattedTime(int timeInSecond) {
|
|
||||||
int sec = timeInSecond % 60;
|
|
||||||
int min = (timeInSecond / 60).floor();
|
|
||||||
String minute = min.toString().length <= 1 ? "0$min" : "$min";
|
|
||||||
String second = sec.toString().length <= 1 ? "0$sec" : "$sec";
|
|
||||||
return "$minute:$second";
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
final ActivityTimerModel atm =
|
|
||||||
Provider.of<ActivityTimerModel>(context, listen: false);
|
|
||||||
|
|
||||||
return FutureBuilder<List<MediaItem>>(
|
|
||||||
future: MediaItemsDao(Provider.of<AppDatabase>(context))
|
|
||||||
.fromActivity(widget.activity),
|
|
||||||
builder: (context, snapshot) {
|
|
||||||
if (snapshot.hasData) {
|
|
||||||
List<MediaItem> 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<double> animation,
|
|
||||||
Animation<double> secondaryAnimation,
|
|
||||||
Widget child) {
|
|
||||||
Animation<Offset> custom = Tween<Offset>(
|
|
||||||
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: <Widget>[
|
|
||||||
ListTile(
|
|
||||||
// visualDensity: VisualDensity(horizontal: VisualDensity.maximumDensity),
|
|
||||||
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.fill,
|
|
||||||
image:
|
|
||||||
findMediaByType(mediaItems, 'image')),
|
|
||||||
// color: Colors.blue,
|
|
||||||
borderRadius: const BorderRadius.all(
|
|
||||||
Radius.elliptical(8, 8)),
|
|
||||||
),
|
|
||||||
)),
|
|
||||||
title: Consumer<ActivityTimerModel>(
|
|
||||||
builder: (context, atm, child) {
|
|
||||||
if (atm.activity?.id == widget.activity.id) {
|
|
||||||
return Text(
|
|
||||||
maxLines: 1,
|
|
||||||
"${widget.activity.title.toTitleCase()} (${formattedTime(atm.totalTime)})");
|
|
||||||
} else {
|
|
||||||
return Text(maxLines: 1, widget.activity.title.toTitleCase());
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
subtitle: Text(maxLines: 2, widget.activity.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: <Widget>[
|
|
||||||
TextButton(
|
|
||||||
onPressed: () =>
|
|
||||||
Navigator.pop(context, 'Cancel'),
|
|
||||||
child: const Text('Cancel'),
|
|
||||||
),
|
|
||||||
TextButton(
|
|
||||||
onPressed: () =>
|
|
||||||
Navigator.pop(context, 'OK'),
|
|
||||||
child: const Text('OK'),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
)),
|
|
||||||
],
|
|
||||||
)),
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return Container(
|
|
||||||
alignment: Alignment.center,
|
|
||||||
child: SizedBox(
|
|
||||||
height: 50.0,
|
|
||||||
width: 50.0,
|
|
||||||
child: CircularProgressIndicator(),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
ImageProvider findMediaByType(List<MediaItem> media, String type) {
|
|
||||||
Iterable<MediaItem>? found = media.where((m) => m.type == MediaType.image);
|
|
||||||
|
|
||||||
if (found.isNotEmpty) {
|
|
||||||
return NetworkImage(found.first.reference);
|
|
||||||
} else {
|
|
||||||
// Element is not found
|
|
||||||
return const AssetImage('assets/images/placeholder.jpg');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
Future showGenericDialog(dynamic object, BuildContext parentContext) {
|
||||||
|
return showGeneralDialog(
|
||||||
|
barrierColor: Colors.black.withOpacity(0.5),
|
||||||
|
transitionDuration: const Duration(milliseconds: 220),
|
||||||
|
transitionBuilder: (BuildContext context, Animation<double> animation,
|
||||||
|
Animation<double> secondaryAnimation, Widget child) {
|
||||||
|
Animation<Offset> custom = Tween<Offset>(
|
||||||
|
begin: const Offset(0.0, 1.0), end: const Offset(0.0, 0.0))
|
||||||
|
.animate(animation);
|
||||||
|
return SlideTransition(
|
||||||
|
position: custom, child: Dialog.fullscreen(child: object));
|
||||||
|
},
|
||||||
|
barrierDismissible: true,
|
||||||
|
barrierLabel: '',
|
||||||
|
context: parentContext,
|
||||||
|
pageBuilder: (context, animation1, animation2) {
|
||||||
|
return Container();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Future showRemovalDialog(String title, String content, BuildContext context,
|
||||||
|
dynamic dao, dynamic object) {
|
||||||
|
return showAdaptiveDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (BuildContext context) => AlertDialog(
|
||||||
|
title: Text(title),
|
||||||
|
content: Text(content),
|
||||||
|
actions: <Widget>[
|
||||||
|
TextButton(
|
||||||
|
onPressed: () => {
|
||||||
|
Navigator.pop(context, 'Cancel'),
|
||||||
|
},
|
||||||
|
child: const Text('Cancel'),
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
onPressed: () => {dao.remove(object), Navigator.pop(context, 'OK')},
|
||||||
|
child: const Text('OK'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class CardContent extends StatelessWidget {
|
||||||
|
const CardContent({super.key, required this.content});
|
||||||
|
|
||||||
|
final String content;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return ListTile(
|
||||||
|
contentPadding: const EdgeInsets.fromLTRB(15, 0, 15, 15),
|
||||||
|
title: Text(
|
||||||
|
maxLines: 2,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
style: const TextStyle(fontWeight: FontWeight.w300),
|
||||||
|
content),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
enum SizeAxis { width, height }
|
||||||
|
|
||||||
|
class CardImage extends StatelessWidget {
|
||||||
|
const CardImage({super.key, required this.image, this.padding, this.size});
|
||||||
|
|
||||||
|
final ImageProvider<Object> image;
|
||||||
|
final EdgeInsets? padding;
|
||||||
|
|
||||||
|
final Map<SizeAxis, double>? size;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Padding(
|
||||||
|
padding: padding ?? const EdgeInsets.fromLTRB(0, 0, 0, 0),
|
||||||
|
child: Container(
|
||||||
|
width: size?[SizeAxis.width] ?? 60,
|
||||||
|
height: size?[SizeAxis.height] ?? 60,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
image: DecorationImage(
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
image: image,
|
||||||
|
onError: (error, stackTrace) => AssetImage('assets/images/placeholder.jpg')
|
||||||
|
// color: Colors.blue,
|
||||||
|
),
|
||||||
|
borderRadius: BorderRadius.all(Radius.elliptical(8, 8)),
|
||||||
|
),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,105 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
import 'dart:math';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:sendtrain/services/apis/google_places_service.dart';
|
||||||
|
import 'package:sendtrain/services/functional/debouncer.dart';
|
||||||
|
import 'package:sendtrain/widgets/generic/elements/form_text_input.dart';
|
||||||
|
|
||||||
|
class FormSearchInput extends StatefulWidget {
|
||||||
|
const FormSearchInput(
|
||||||
|
{super.key, required this.sessionController, this.optionalPayload});
|
||||||
|
|
||||||
|
final TextEditingController sessionController;
|
||||||
|
final dynamic optionalPayload;
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<FormSearchInput> createState() => _FormSearchInputState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _FormSearchInputState extends State<FormSearchInput> {
|
||||||
|
String? _currentQuery;
|
||||||
|
|
||||||
|
final service = GooglePlacesService();
|
||||||
|
|
||||||
|
// The most recent suggestions received from the API.
|
||||||
|
late Iterable<Widget> _lastOptions = <Widget>[];
|
||||||
|
late final Debouncer debouncer;
|
||||||
|
|
||||||
|
// Calls the "remote" API to search with the given query. Returns null when
|
||||||
|
// the call has been made obsolete.
|
||||||
|
Future<Iterable<Suggestion>?> _search(String query) async {
|
||||||
|
_currentQuery = query;
|
||||||
|
|
||||||
|
// In a real application, there should be some error handling here.
|
||||||
|
// final Iterable<String> options = await _FakeAPI.search(_currentQuery!);
|
||||||
|
if (query.isNotEmpty) {
|
||||||
|
final List<Suggestion>? suggestions =
|
||||||
|
await service.fetchSuggestions(_currentQuery!, 'en');
|
||||||
|
|
||||||
|
// If another search happened after this one, throw away these options.
|
||||||
|
if (_currentQuery != query) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
_currentQuery = null;
|
||||||
|
|
||||||
|
return suggestions?.map((suggestion) => suggestion);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
debouncer = Debouncer(Duration(milliseconds: 50), _search);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return SearchAnchor(
|
||||||
|
builder: (BuildContext context, SearchController controller) {
|
||||||
|
return FormTextInput(
|
||||||
|
controller: widget.sessionController,
|
||||||
|
title: 'Location (optional)',
|
||||||
|
icon: Icon(Icons.search_rounded),
|
||||||
|
maxLines: 2,
|
||||||
|
requiresValidation: false,
|
||||||
|
onTap: () {
|
||||||
|
controller.openView();
|
||||||
|
});
|
||||||
|
}, suggestionsBuilder:
|
||||||
|
(BuildContext context, SearchController controller) async {
|
||||||
|
final List<Suggestion>? options =
|
||||||
|
(await debouncer.process(controller.text))?.toList();
|
||||||
|
if (options == null) {
|
||||||
|
return _lastOptions;
|
||||||
|
}
|
||||||
|
_lastOptions = List<ListTile>.generate(options.length, (int index) {
|
||||||
|
final Suggestion item = options[index];
|
||||||
|
return ListTile(
|
||||||
|
title: Text(item.description),
|
||||||
|
onTap: () async {
|
||||||
|
// widget.optionalPayload = service.fetchPhoto(json.decode(item.image));
|
||||||
|
if (item.imageReferences != null) {
|
||||||
|
// get a random photo item from the returned result
|
||||||
|
Map<String, dynamic> photo = item.imageReferences![
|
||||||
|
Random().nextInt(item.imageReferences!.length)];
|
||||||
|
|
||||||
|
await service.fetchPhoto(photo['name']).then((photoMap) {
|
||||||
|
widget.optionalPayload.photoUri = photoMap['photoUri'];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
widget.optionalPayload.address = item.address;
|
||||||
|
widget.sessionController.text = item.description;
|
||||||
|
service.finish();
|
||||||
|
controller.closeView(item.description);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
return _lastOptions;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class FormTextInput extends StatelessWidget {
|
||||||
|
const FormTextInput(
|
||||||
|
{super.key,
|
||||||
|
required this.controller,
|
||||||
|
required this.title,
|
||||||
|
this.icon,
|
||||||
|
this.maxLines,
|
||||||
|
this.minLines,
|
||||||
|
this.onTap,
|
||||||
|
this.requiresValidation=true});
|
||||||
|
|
||||||
|
final TextEditingController controller;
|
||||||
|
final String title;
|
||||||
|
final int? maxLines;
|
||||||
|
final int? minLines;
|
||||||
|
final Icon? icon;
|
||||||
|
final dynamic onTap;
|
||||||
|
final bool requiresValidation;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Padding(
|
||||||
|
padding: EdgeInsets.only(top: 10, bottom: 10),
|
||||||
|
child: TextFormField(
|
||||||
|
minLines: minLines ?? 1,
|
||||||
|
maxLines: maxLines ?? 1,
|
||||||
|
controller: controller,
|
||||||
|
decoration: InputDecoration(
|
||||||
|
filled: true,
|
||||||
|
prefixIcon: icon ?? Icon(Icons.draw_rounded),
|
||||||
|
border: OutlineInputBorder(
|
||||||
|
borderSide: BorderSide.none,
|
||||||
|
borderRadius: BorderRadius.circular(12)),
|
||||||
|
labelText: title,
|
||||||
|
),
|
||||||
|
validator: (String? value) {
|
||||||
|
if (requiresValidation == true) {
|
||||||
|
if (value == null || value.isEmpty) {
|
||||||
|
return 'Please enter some text';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value.length < 3) {
|
||||||
|
return 'Please enter a minimum of 3 characters';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
onTap: () {
|
||||||
|
if (onTap != null) {
|
||||||
|
onTap();
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class GenericProgressIndicator extends StatelessWidget {
|
||||||
|
const GenericProgressIndicator({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: SizedBox(
|
||||||
|
height: 50.0,
|
||||||
|
width: 50.0,
|
||||||
|
child: CircularProgressIndicator(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,101 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
import 'dart:io';
|
||||||
|
import 'dart:typed_data';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
import 'package:sendtrain/daos/media_items_dao.dart';
|
||||||
|
import 'package:sendtrain/database/database.dart';
|
||||||
|
import 'package:sendtrain/helpers/widget_helpers.dart';
|
||||||
|
import 'package:sendtrain/widgets/builders/dialogs.dart';
|
||||||
|
import 'package:video_player/video_player.dart';
|
||||||
|
|
||||||
|
class MediaCard extends StatefulWidget {
|
||||||
|
const MediaCard({super.key, required this.media, this.callback});
|
||||||
|
|
||||||
|
final MediaItem media;
|
||||||
|
final Function? callback;
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<MediaCard> createState() => _MediaCardState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _MediaCardState extends State<MediaCard> {
|
||||||
|
// late VideoPlayerController _controller;
|
||||||
|
late MediaItem media;
|
||||||
|
late Function? callback;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
media = widget.media;
|
||||||
|
callback = widget.callback;
|
||||||
|
// _controller = VideoPlayerController.asset(dataSource)
|
||||||
|
// ..initialize().then((_) {
|
||||||
|
// setState(() {}); //when your thumbnail will show.
|
||||||
|
// });
|
||||||
|
}
|
||||||
|
|
||||||
|
// @override
|
||||||
|
// void dispose() {
|
||||||
|
// super.dispose();
|
||||||
|
// _controller.dispose();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Future<VideoPlayerController> createVideoPlayer() async {
|
||||||
|
// final File file =
|
||||||
|
// await ImgB64Decoder.fileFromB64String(widget.encodedBytes);
|
||||||
|
// final VideoPlayerController controller = VideoPlayerController.file(file);
|
||||||
|
// await controller.initialize();
|
||||||
|
// await controller.setLooping(true);
|
||||||
|
// return controller;
|
||||||
|
// }
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
DecorationImage mediaImage(MediaItem media) {
|
||||||
|
dynamic image;
|
||||||
|
|
||||||
|
if (media.type == MediaType.image || media.type == MediaType.location) {
|
||||||
|
image = NetworkImage(media.reference);
|
||||||
|
} else if (media.type == MediaType.localImage) {
|
||||||
|
image = Image.memory(base64Decode(media.reference)).image;
|
||||||
|
} else if (media.type == MediaType.youtube) {
|
||||||
|
image =
|
||||||
|
NetworkImage('https://img.youtube.com/vi/${media.reference}/0.jpg');
|
||||||
|
} else if (media.type == MediaType.localVideo) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return DecorationImage(image: image, fit: BoxFit.cover);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(10),
|
||||||
|
image: mediaImage(media),
|
||||||
|
),
|
||||||
|
child: Card(
|
||||||
|
color: Colors.transparent,
|
||||||
|
shape:
|
||||||
|
RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
|
||||||
|
shadowColor: const Color.fromARGB(0, 255, 255, 255),
|
||||||
|
child: TextButton(
|
||||||
|
onLongPress: () => showRemovalDialog(
|
||||||
|
'Media Removal',
|
||||||
|
'Would you like to permanently remove this media from the current session?',
|
||||||
|
context,
|
||||||
|
MediaItemsDao(Provider.of<AppDatabase>(context,
|
||||||
|
listen: false)),
|
||||||
|
media)
|
||||||
|
.then((result) {
|
||||||
|
if (callback != null) {
|
||||||
|
callback!();
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
onPressed: () => showMediaDetailWidget(context, media),
|
||||||
|
child: const ListTile(
|
||||||
|
title: Text(''),
|
||||||
|
))));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:sendtrain/database/database.dart';
|
||||||
|
import 'package:youtube_player_flutter/youtube_player_flutter.dart';
|
||||||
|
|
||||||
|
class MediaContent extends StatelessWidget {
|
||||||
|
const MediaContent({super.key, required this.media});
|
||||||
|
|
||||||
|
final MediaItem media;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
YoutubePlayerController controller = YoutubePlayerController(
|
||||||
|
initialVideoId: media.reference,
|
||||||
|
flags: const YoutubePlayerFlags(
|
||||||
|
autoPlay: false, mute: true, showLiveFullscreenButton: false));
|
||||||
|
|
||||||
|
if (media.type == MediaType.image || media.type == MediaType.location) {
|
||||||
|
return Image(image: NetworkImage(media.reference));
|
||||||
|
} else if (media.type == MediaType.localImage) {
|
||||||
|
return Image.memory(base64Decode(media.reference));
|
||||||
|
} else if (media.type == MediaType.youtube) {
|
||||||
|
return YoutubePlayer(
|
||||||
|
controller: controller,
|
||||||
|
aspectRatio: 16 / 9,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return const Image(image: AssetImage('assets/images/placeholder.jpg'));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:sendtrain/database/database.dart';
|
||||||
|
import 'package:sendtrain/widgets/media/media_content.dart';
|
||||||
|
|
||||||
|
class MediaDetails extends StatelessWidget {
|
||||||
|
const MediaDetails({super.key, required this.media});
|
||||||
|
|
||||||
|
final MediaItem media;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Padding(
|
||||||
|
padding: EdgeInsets.fromLTRB(15, 0, 15, 15),
|
||||||
|
child: ListView(
|
||||||
|
shrinkWrap: true,
|
||||||
|
children: <Widget>[
|
||||||
|
ClipRRect(
|
||||||
|
borderRadius: BorderRadius.circular(10),
|
||||||
|
child: MediaContent(media: media),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 15),
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.fromLTRB(15, 0, 15, 15),
|
||||||
|
child: Text(
|
||||||
|
media.description,
|
||||||
|
style: const TextStyle(fontSize: 20),
|
||||||
|
)),
|
||||||
|
|
||||||
|
const Divider(
|
||||||
|
indent: 20,
|
||||||
|
endIndent: 20,
|
||||||
|
)
|
||||||
|
]));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,93 +0,0 @@
|
|||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:sendtrain/database/database.dart';
|
|
||||||
import 'package:youtube_player_flutter/youtube_player_flutter.dart';
|
|
||||||
|
|
||||||
class MediaCard extends StatelessWidget {
|
|
||||||
const MediaCard({super.key, required this.media});
|
|
||||||
|
|
||||||
final MediaItem media;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
YoutubePlayerController controller = YoutubePlayerController(
|
|
||||||
initialVideoId: media.reference,
|
|
||||||
flags: const YoutubePlayerFlags(
|
|
||||||
autoPlay: false, mute: true, showLiveFullscreenButton: false));
|
|
||||||
|
|
||||||
DecorationImage mediaImage(MediaItem media) {
|
|
||||||
String image = '';
|
|
||||||
|
|
||||||
if (media.type == MediaType.image) {
|
|
||||||
image = media.reference;
|
|
||||||
} else if (media.type == MediaType.youtube) {
|
|
||||||
image = 'https://img.youtube.com/vi/${media.reference}/0.jpg';
|
|
||||||
}
|
|
||||||
|
|
||||||
return DecorationImage(image: NetworkImage(image), fit: BoxFit.cover);
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget mediaItem(MediaItem media) {
|
|
||||||
if (media.type == MediaType.image) {
|
|
||||||
return Image(image: NetworkImage(media.reference));
|
|
||||||
} else if (media.type == MediaType.youtube) {
|
|
||||||
return YoutubePlayer(
|
|
||||||
controller: controller,
|
|
||||||
aspectRatio: 16 / 9,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return const Image(image: AssetImage('assets/images/placeholder.jpg'));
|
|
||||||
}
|
|
||||||
|
|
||||||
return Container(
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
borderRadius: BorderRadius.circular(10),
|
|
||||||
image: mediaImage(media),
|
|
||||||
),
|
|
||||||
child: Card(
|
|
||||||
color: Colors.transparent,
|
|
||||||
shape:
|
|
||||||
RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
|
|
||||||
shadowColor: const Color.fromARGB(0, 255, 255, 255),
|
|
||||||
child: TextButton(
|
|
||||||
onPressed: () => showDialog<String>(
|
|
||||||
context: context,
|
|
||||||
builder: (BuildContext context) => Dialog.fullscreen(
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.all(8.0),
|
|
||||||
child: Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
|
||||||
children: <Widget>[
|
|
||||||
mediaItem(media),
|
|
||||||
const SizedBox(height: 15),
|
|
||||||
Text(
|
|
||||||
media.description,
|
|
||||||
style: const TextStyle(fontSize: 20),
|
|
||||||
),
|
|
||||||
const Divider(
|
|
||||||
indent: 20,
|
|
||||||
endIndent: 20,
|
|
||||||
color: Colors.deepPurple,
|
|
||||||
),
|
|
||||||
// const Text(
|
|
||||||
// 'Comments',
|
|
||||||
// style: TextStyle(fontSize: 20),
|
|
||||||
// ),
|
|
||||||
const SizedBox(height: 15),
|
|
||||||
TextButton(
|
|
||||||
onPressed: () {
|
|
||||||
Navigator.pop(context);
|
|
||||||
},
|
|
||||||
child: const Text('Close'),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
child: const ListTile(
|
|
||||||
title: Text(''),
|
|
||||||
))));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -3,8 +3,8 @@ import 'package:sendtrain/classes/activity_action.dart';
|
|||||||
import 'package:sendtrain/database/database.dart' hide ActivityAction;
|
import 'package:sendtrain/database/database.dart' hide ActivityAction;
|
||||||
import 'package:sendtrain/models/activity_model.dart';
|
import 'package:sendtrain/models/activity_model.dart';
|
||||||
|
|
||||||
import '../widgets/activities_header.dart';
|
// import '../widgets/activities/activities_header.dart';
|
||||||
import '../widgets/activity_card.dart';
|
// import '../widgets/activities/activity_card.dart';
|
||||||
|
|
||||||
class ActivitiesScreen extends StatefulWidget {
|
class ActivitiesScreen extends StatefulWidget {
|
||||||
const ActivitiesScreen({super.key});
|
const ActivitiesScreen({super.key});
|
||||||
@@ -1,31 +1,64 @@
|
|||||||
|
// import 'package:drift/drift.dart' hide Column;
|
||||||
|
import 'package:drift/drift.dart' hide Column;
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:sendtrain/daos/sessions_dao.dart';
|
import 'package:sendtrain/daos/sessions_dao.dart';
|
||||||
import 'package:sendtrain/database/database.dart';
|
import 'package:sendtrain/database/database.dart';
|
||||||
import '../widgets/session_card.dart';
|
import 'package:sendtrain/widgets/generic/elements/generic_progress_indicator.dart';
|
||||||
|
import 'package:sendtrain/widgets/sessions/session_card.dart';
|
||||||
|
import 'package:collection/collection.dart';
|
||||||
|
|
||||||
class SessionsScreen extends StatelessWidget {
|
class SessionsScreen extends StatefulWidget {
|
||||||
const SessionsScreen({super.key});
|
const SessionsScreen({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<SessionsScreen> createState() => _SessionsScreenState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _SessionsScreenState extends State<SessionsScreen> {
|
||||||
|
Widget getSessionCard(session) {
|
||||||
|
if (session != null) {
|
||||||
|
return SessionCard(session: session);
|
||||||
|
} else {
|
||||||
|
return Padding(
|
||||||
|
padding: EdgeInsets.all(15),
|
||||||
|
child: Icon(Icons.do_not_disturb_alt_outlined));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return FutureBuilder<List<Session>>(
|
SessionsDao dao = SessionsDao(Provider.of<AppDatabase>(context));
|
||||||
future: SessionsDao(Provider.of<AppDatabase>(context)).all(),
|
|
||||||
|
return StreamBuilder<List<Session>>(
|
||||||
|
stream: dao.watch(),
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
if (snapshot.hasData && snapshot.data!.isNotEmpty) {
|
if (snapshot.hasData && snapshot.data!.isNotEmpty) {
|
||||||
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 ||
|
||||||
session.status == SessionStatus.missed);
|
session.status == SessionStatus.missed);
|
||||||
final upcoming = sessions.firstWhere(
|
final upcoming = sessions.firstWhereOrNull(
|
||||||
(session) => session.status == SessionStatus.pending);
|
(session) => session.status == SessionStatus.pending);
|
||||||
final current = sessions.firstWhere(
|
final current = sessions.firstWhereOrNull(
|
||||||
(session) => session.status == SessionStatus.started);
|
(session) => session.status == SessionStatus.started);
|
||||||
|
|
||||||
|
if (current == null && upcoming != null) {
|
||||||
|
dao.createOrUpdate(SessionsCompanion(
|
||||||
|
id: Value(upcoming.id),
|
||||||
|
title: Value(upcoming.title),
|
||||||
|
content: Value(upcoming.content),
|
||||||
|
status: Value(SessionStatus.started),
|
||||||
|
address: Value(upcoming.address),
|
||||||
|
date: Value(upcoming.date)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
List<Widget> previousSessions = List.generate(pending.length,
|
List<Widget> previousSessions = List.generate(pending.length,
|
||||||
(i) => SessionCard(type: 1, session: pending.elementAt(i)));
|
(i) => SessionCard(type: 1, session: pending.elementAt(i)));
|
||||||
Widget upcomingSession = SessionCard(session: upcoming);
|
|
||||||
Widget currentSession = SessionCard(session: current);
|
Widget upcomingSession = getSessionCard(upcoming);
|
||||||
|
Widget currentSession = getSessionCard(current);
|
||||||
|
|
||||||
return Column(
|
return Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
@@ -63,13 +96,7 @@ class SessionsScreen extends StatelessWidget {
|
|||||||
],
|
],
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return Container(
|
return GenericProgressIndicator();
|
||||||
alignment: Alignment.center,
|
|
||||||
child: SizedBox(
|
|
||||||
height: 50.0,
|
|
||||||
width: 50.0,
|
|
||||||
child: CircularProgressIndicator(),
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -1,164 +0,0 @@
|
|||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:intl/intl.dart';
|
|
||||||
import 'package:intl/date_symbol_data_local.dart';
|
|
||||||
import 'package:sendtrain/database/database.dart' hide ActivityAction;
|
|
||||||
import 'package:sendtrain/extensions/string_extensions.dart';
|
|
||||||
import 'package:sendtrain/widgets/session_view.dart';
|
|
||||||
|
|
||||||
class SessionCard extends StatelessWidget {
|
|
||||||
final int type;
|
|
||||||
final Session session;
|
|
||||||
const SessionCard({super.key, this.type = 0, required this.session});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
initializeDateFormatting('en');
|
|
||||||
final DateFormat dateFormat = DateFormat('yyyy-MM-dd');
|
|
||||||
|
|
||||||
Color color = (session.status == SessionStatus.started)
|
|
||||||
? Theme.of(context).colorScheme.primaryContainer
|
|
||||||
: Theme.of(context).colorScheme.surfaceContainerLow;
|
|
||||||
|
|
||||||
if (type == 0) {
|
|
||||||
return Card(
|
|
||||||
color: color,
|
|
||||||
margin: const EdgeInsets.fromLTRB(15, 15, 15, 0),
|
|
||||||
clipBehavior: Clip.hardEdge,
|
|
||||||
child: InkWell(
|
|
||||||
splashColor: Colors.deepPurple,
|
|
||||||
onTap: () => showGeneralDialog(
|
|
||||||
barrierColor: Colors.black.withOpacity(0.5),
|
|
||||||
transitionDuration: const Duration(milliseconds: 220),
|
|
||||||
transitionBuilder: (BuildContext context,
|
|
||||||
Animation<double> animation,
|
|
||||||
Animation<double> secondaryAnimation,
|
|
||||||
Widget child) {
|
|
||||||
Animation<Offset> custom = Tween<Offset>(
|
|
||||||
begin: const Offset(0.0, 1.0),
|
|
||||||
end: const Offset(0.0, 0.0))
|
|
||||||
.animate(animation);
|
|
||||||
return SlideTransition(
|
|
||||||
position: custom,
|
|
||||||
child: Dialog.fullscreen(child: SessionView(session: session)));
|
|
||||||
},
|
|
||||||
barrierDismissible: true,
|
|
||||||
barrierLabel: '',
|
|
||||||
context: context,
|
|
||||||
pageBuilder: (context, animation1, animation2) {
|
|
||||||
return Container();
|
|
||||||
}),
|
|
||||||
child: Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: <Widget>[
|
|
||||||
ListTile(
|
|
||||||
leading: Padding(
|
|
||||||
padding: const EdgeInsets.fromLTRB(0, 8, 0, 0),
|
|
||||||
child: Container(
|
|
||||||
width: 60,
|
|
||||||
decoration: const BoxDecoration(
|
|
||||||
image: DecorationImage(
|
|
||||||
fit: BoxFit.cover,
|
|
||||||
image:
|
|
||||||
AssetImage('assets/images/placeholder.jpg')),
|
|
||||||
// color: Colors.blue,
|
|
||||||
borderRadius:
|
|
||||||
BorderRadius.all(Radius.elliptical(10, 10)),
|
|
||||||
),
|
|
||||||
)),
|
|
||||||
title: Text(maxLines: 1, session.title.toTitleCase()),
|
|
||||||
subtitle: Text(maxLines: 1, dateFormat.format(session.date as DateTime)),
|
|
||||||
trailing: IconButton(
|
|
||||||
visualDensity: VisualDensity.compact,
|
|
||||||
icon: Icon(Icons.close_rounded),
|
|
||||||
onPressed: () {
|
|
||||||
showAdaptiveDialog(
|
|
||||||
context: context,
|
|
||||||
builder: (BuildContext context) => AlertDialog(
|
|
||||||
title: const Text('Session Removal'),
|
|
||||||
content: const Text(
|
|
||||||
'Would you like to permanently remove this session?'),
|
|
||||||
actions: <Widget>[
|
|
||||||
TextButton(
|
|
||||||
onPressed: () => Navigator.pop(context, 'Cancel'),
|
|
||||||
child: const Text('Cancel'),
|
|
||||||
),
|
|
||||||
TextButton(
|
|
||||||
onPressed: () => Navigator.pop(context, 'OK'),
|
|
||||||
child: const Text('OK'),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
ListTile(
|
|
||||||
contentPadding: const EdgeInsets.fromLTRB(15, 0, 15, 15),
|
|
||||||
title: Text(
|
|
||||||
maxLines: 2,
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
style: const TextStyle(fontWeight: FontWeight.w300),
|
|
||||||
session.content),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
)),
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return Card(
|
|
||||||
color: color,
|
|
||||||
child: InkWell(
|
|
||||||
// overlayColor: MaterialStateColor(Colors.deepPurple as int),
|
|
||||||
splashColor: Colors.deepPurple,
|
|
||||||
borderRadius: const BorderRadius.all(Radius.elliptical(10, 10)),
|
|
||||||
onTap: () => showGeneralDialog(
|
|
||||||
// barrierColor: Colors.black.withOpacity(0.5),
|
|
||||||
transitionDuration: const Duration(milliseconds: 220),
|
|
||||||
transitionBuilder: (BuildContext context,
|
|
||||||
Animation<double> animation,
|
|
||||||
Animation<double> secondaryAnimation,
|
|
||||||
Widget child) {
|
|
||||||
Animation<Offset> custom = Tween<Offset>(
|
|
||||||
begin: const Offset(0.0, 1.0),
|
|
||||||
end: const Offset(0.0, 0.0))
|
|
||||||
.animate(animation);
|
|
||||||
return SlideTransition(
|
|
||||||
position: custom,
|
|
||||||
child:
|
|
||||||
Dialog.fullscreen(child: SessionView(session: session)));
|
|
||||||
},
|
|
||||||
barrierDismissible: true,
|
|
||||||
barrierLabel: '',
|
|
||||||
context: context,
|
|
||||||
pageBuilder: (context, animation1, animation2) {
|
|
||||||
return Container();
|
|
||||||
}),
|
|
||||||
child: Container(
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
// color: const Color.fromARGB(47, 0, 0, 0),
|
|
||||||
borderRadius: BorderRadius.circular(10),
|
|
||||||
image: const DecorationImage(
|
|
||||||
colorFilter: ColorFilter.mode(
|
|
||||||
Color.fromARGB(220, 41, 39, 39),
|
|
||||||
BlendMode.hardLight),
|
|
||||||
image: AssetImage('assets/images/placeholder.jpg'),
|
|
||||||
fit: BoxFit.cover),
|
|
||||||
),
|
|
||||||
child: Align(
|
|
||||||
alignment: Alignment.center,
|
|
||||||
child: Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: <Widget>[
|
|
||||||
ListTile(
|
|
||||||
title: Text(
|
|
||||||
maxLines: 3,
|
|
||||||
session.title.toTitleCase(),
|
|
||||||
textAlign: TextAlign.center),
|
|
||||||
subtitle: Text(
|
|
||||||
maxLines: 1,
|
|
||||||
dateFormat.format(session.date as DateTime),
|
|
||||||
textAlign: TextAlign.center),
|
|
||||||
),
|
|
||||||
])))));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:intl/date_symbol_data_local.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
import 'package:sendtrain/daos/media_items_dao.dart';
|
||||||
|
import 'package:sendtrain/database/database.dart' hide ActivityAction;
|
||||||
|
import 'package:sendtrain/widgets/generic/elements/generic_progress_indicator.dart';
|
||||||
|
import 'package:sendtrain/widgets/sessions/session_card_full.dart';
|
||||||
|
import 'package:sendtrain/widgets/sessions/session_card_small.dart';
|
||||||
|
|
||||||
|
class SessionCard extends StatefulWidget {
|
||||||
|
final int type;
|
||||||
|
final Session session;
|
||||||
|
const SessionCard({super.key, this.type = 0, required this.session});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<SessionCard> createState() => _SessionCardState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _SessionCardState extends State<SessionCard> {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final int type = widget.type;
|
||||||
|
final Session session = widget.session;
|
||||||
|
|
||||||
|
initializeDateFormatting('en');
|
||||||
|
|
||||||
|
return StreamBuilder<List<MediaItem>>(
|
||||||
|
stream: MediaItemsDao(Provider.of<AppDatabase>(context))
|
||||||
|
.watchSessionMediaItems(session.id),
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
if (snapshot.hasData) {
|
||||||
|
List<MediaItem> mediaItems = snapshot.data!;
|
||||||
|
|
||||||
|
if (type == 0) {
|
||||||
|
return SessionCardFull(session: session, mediaItems: mediaItems);
|
||||||
|
} else {
|
||||||
|
return SessionCardSmall(session: session, mediaItems: mediaItems);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return GenericProgressIndicator();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
import 'package:sendtrain/daos/sessions_dao.dart';
|
||||||
|
import 'package:sendtrain/database/database.dart';
|
||||||
|
import 'package:sendtrain/extensions/string_extensions.dart';
|
||||||
|
import 'package:sendtrain/helpers/date_time_helpers.dart';
|
||||||
|
import 'package:sendtrain/helpers/media_helpers.dart';
|
||||||
|
import 'package:sendtrain/helpers/widget_helpers.dart';
|
||||||
|
import 'package:sendtrain/widgets/builders/dialogs.dart';
|
||||||
|
import 'package:sendtrain/widgets/generic/elements/card_content.dart';
|
||||||
|
import 'package:sendtrain/widgets/generic/elements/card_image.dart';
|
||||||
|
import 'package:sendtrain/widgets/sessions/session_view.dart';
|
||||||
|
import 'package:collection/collection.dart';
|
||||||
|
|
||||||
|
class SessionCardFull extends StatefulWidget {
|
||||||
|
const SessionCardFull(
|
||||||
|
{super.key, required this.session, required this.mediaItems});
|
||||||
|
|
||||||
|
final Session session;
|
||||||
|
final List<MediaItem> mediaItems;
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<SessionCardFull> createState() => _SessionCardFullState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _SessionCardFullState extends State<SessionCardFull> {
|
||||||
|
// late final List<MediaItem> mediaItems;
|
||||||
|
// late final MediaItem? sessionImage;
|
||||||
|
// late final Session session;
|
||||||
|
|
||||||
|
String sessionTitle(Session session) {
|
||||||
|
String title = session.title.toTitleCase();
|
||||||
|
|
||||||
|
if (session.address != null) title = "$title @ ${session.address}";
|
||||||
|
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
|
||||||
|
// @override
|
||||||
|
// initState() {
|
||||||
|
// super.initState();
|
||||||
|
// session = widget.session;
|
||||||
|
// mediaItems = widget.mediaItems;
|
||||||
|
// sessionImage = mediaItems
|
||||||
|
// .firstWhereOrNull((mediaItem) => mediaItem.type == MediaType.location);
|
||||||
|
// }
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final Session session = widget.session;
|
||||||
|
final List<MediaItem> mediaItems = widget.mediaItems;
|
||||||
|
final MediaItem? sessionImage = mediaItems
|
||||||
|
.firstWhereOrNull((mediaItem) => mediaItem.type == MediaType.location);
|
||||||
|
|
||||||
|
return Card(
|
||||||
|
color: (session.status == SessionStatus.started)
|
||||||
|
? Theme.of(context).colorScheme.primaryContainer
|
||||||
|
: Theme.of(context).colorScheme.surfaceContainerLow,
|
||||||
|
margin: const EdgeInsets.fromLTRB(15, 15, 15, 0),
|
||||||
|
clipBehavior: Clip.hardEdge,
|
||||||
|
child: InkWell(
|
||||||
|
splashColor: Colors.deepPurple,
|
||||||
|
onLongPress: () => showMediaDetailWidget(context, sessionImage!),
|
||||||
|
onTap: () =>
|
||||||
|
showGenericDialog(SessionView(session: session), context),
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: <Widget>[
|
||||||
|
ListTile(
|
||||||
|
contentPadding: EdgeInsets.only(left: 8),
|
||||||
|
leading: CardImage(
|
||||||
|
image: findMediaByType(mediaItems, MediaType.location),
|
||||||
|
padding: EdgeInsets.only(left: 5, top: 5)),
|
||||||
|
title: Text(maxLines: 1, sessionTitle(session)),
|
||||||
|
subtitle: Text(
|
||||||
|
maxLines: 1, dateFormat.format(session.date as DateTime)),
|
||||||
|
trailing: IconButton(
|
||||||
|
padding: EdgeInsets.all(0),
|
||||||
|
alignment: Alignment.topCenter,
|
||||||
|
icon: Icon(Icons.close_rounded),
|
||||||
|
onPressed: () {
|
||||||
|
showRemovalDialog(
|
||||||
|
'Session Removal',
|
||||||
|
'Would you like to permanently remove this session?',
|
||||||
|
context,
|
||||||
|
SessionsDao(Provider.of<AppDatabase>(context,
|
||||||
|
listen: false)),
|
||||||
|
session)
|
||||||
|
.then((result) {
|
||||||
|
setState(() {});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
CardContent(content: session.content)
|
||||||
|
],
|
||||||
|
)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:sendtrain/database/database.dart';
|
||||||
|
import 'package:sendtrain/extensions/string_extensions.dart';
|
||||||
|
import 'package:sendtrain/helpers/date_time_helpers.dart';
|
||||||
|
import 'package:sendtrain/helpers/media_helpers.dart';
|
||||||
|
import 'package:sendtrain/helpers/widget_helpers.dart';
|
||||||
|
import 'package:sendtrain/widgets/builders/dialogs.dart';
|
||||||
|
import 'package:sendtrain/widgets/sessions/session_view.dart';
|
||||||
|
import 'package:collection/collection.dart';
|
||||||
|
|
||||||
|
class SessionCardSmall extends StatefulWidget {
|
||||||
|
const SessionCardSmall(
|
||||||
|
{super.key, required this.session, required this.mediaItems});
|
||||||
|
|
||||||
|
final Session session;
|
||||||
|
final List<MediaItem> mediaItems;
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<SessionCardSmall> createState() => _SessionCardSmallState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _SessionCardSmallState extends State<SessionCardSmall> {
|
||||||
|
// late final List<MediaItem> mediaItems;
|
||||||
|
// late final MediaItem? sessionImage;
|
||||||
|
// late final Session session;
|
||||||
|
|
||||||
|
// @override
|
||||||
|
// initState() {
|
||||||
|
// super.initState();
|
||||||
|
// session = widget.session;
|
||||||
|
// mediaItems = widget.mediaItems;
|
||||||
|
// sessionImage = mediaItems.firstWhereOrNull((mediaItem) => mediaItem.type == MediaType.location);
|
||||||
|
// }
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final Session session = widget.session;
|
||||||
|
final List<MediaItem> mediaItems = widget.mediaItems;
|
||||||
|
final MediaItem? sessionImage = mediaItems
|
||||||
|
.firstWhereOrNull((mediaItem) => mediaItem.type == MediaType.location);
|
||||||
|
|
||||||
|
return Card(
|
||||||
|
color: (session.status == SessionStatus.started)
|
||||||
|
? Theme.of(context).colorScheme.primaryContainer
|
||||||
|
: Theme.of(context).colorScheme.surfaceContainerLow,
|
||||||
|
child: InkWell(
|
||||||
|
// overlayColor: MaterialStateColor(Colors.deepPurple as int),
|
||||||
|
splashColor: Colors.deepPurple,
|
||||||
|
borderRadius: const BorderRadius.all(Radius.elliptical(10, 10)),
|
||||||
|
onLongPress: () {
|
||||||
|
if (sessionImage != null) {
|
||||||
|
showMediaDetailWidget(context, sessionImage);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onTap: () =>
|
||||||
|
showGenericDialog(SessionView(session: session), context),
|
||||||
|
child: Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
// color: const Color.fromARGB(47, 0, 0, 0),
|
||||||
|
borderRadius: BorderRadius.circular(10),
|
||||||
|
image: DecorationImage(
|
||||||
|
colorFilter: ColorFilter.mode(
|
||||||
|
Color.fromARGB(220, 41, 39, 39), BlendMode.hardLight),
|
||||||
|
image: findMediaByType(mediaItems, MediaType.location),
|
||||||
|
fit: BoxFit.cover),
|
||||||
|
),
|
||||||
|
child: Align(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: <Widget>[
|
||||||
|
ListTile(
|
||||||
|
title: Text(
|
||||||
|
maxLines: 3,
|
||||||
|
session.title.toTitleCase(),
|
||||||
|
textAlign: TextAlign.center),
|
||||||
|
subtitle: Text(
|
||||||
|
maxLines: 1,
|
||||||
|
dateFormat.format(session.date as DateTime),
|
||||||
|
textAlign: TextAlign.center),
|
||||||
|
),
|
||||||
|
])))));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,294 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
|
import 'package:drift/drift.dart' hide Column;
|
||||||
|
import 'package:file_picker/file_picker.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:intl/intl.dart';
|
||||||
|
import 'package:mime/mime.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
import 'package:sendtrain/daos/media_items_dao.dart';
|
||||||
|
import 'package:sendtrain/daos/object_media_items_dao.dart';
|
||||||
|
import 'package:sendtrain/daos/sessions_dao.dart';
|
||||||
|
import 'package:sendtrain/database/database.dart';
|
||||||
|
import 'package:sendtrain/widgets/builders/dialogs.dart';
|
||||||
|
import 'package:sendtrain/widgets/generic/elements/form_search_input.dart';
|
||||||
|
import 'package:sendtrain/widgets/generic/elements/form_text_input.dart';
|
||||||
|
import 'package:sendtrain/widgets/sessions/session_view.dart';
|
||||||
|
|
||||||
|
class SessionEditor extends StatefulWidget {
|
||||||
|
const SessionEditor({super.key, this.data, this.session, this.callback});
|
||||||
|
|
||||||
|
final Session? session;
|
||||||
|
final Map<String, dynamic>? data;
|
||||||
|
final Function? callback;
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<SessionEditor> createState() => _SessionEditorState();
|
||||||
|
}
|
||||||
|
|
||||||
|
// used to pass the result of the found image back to current context...
|
||||||
|
class SessionPayload {
|
||||||
|
String? photoUri;
|
||||||
|
String? address;
|
||||||
|
List<PlatformFile>? files;
|
||||||
|
}
|
||||||
|
|
||||||
|
class _SessionEditorState extends State<SessionEditor> {
|
||||||
|
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
|
||||||
|
late AppDatabase db;
|
||||||
|
String editorType = 'Create';
|
||||||
|
|
||||||
|
final Map<String, TextEditingController> sessionCreateController = {
|
||||||
|
'name': TextEditingController(),
|
||||||
|
'content': TextEditingController(),
|
||||||
|
'status': TextEditingController(),
|
||||||
|
'date': TextEditingController(),
|
||||||
|
'address': TextEditingController(),
|
||||||
|
'media': TextEditingController(),
|
||||||
|
};
|
||||||
|
|
||||||
|
final SessionPayload sessionPayload = SessionPayload();
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
db = Provider.of<AppDatabase>(context, listen: false);
|
||||||
|
|
||||||
|
// if we're editing a session, we'll want to populate it with the appropriate values
|
||||||
|
if (widget.session != null) {
|
||||||
|
editorType = 'Edit';
|
||||||
|
final Session session = widget.session!;
|
||||||
|
sessionCreateController['name']?.text = session.title;
|
||||||
|
sessionCreateController['content']?.text = session.content;
|
||||||
|
sessionCreateController['status']?.text = session.status.name;
|
||||||
|
sessionCreateController['date']?.text =
|
||||||
|
DateFormat('yyyy-MM-dd').format(session.date!);
|
||||||
|
if (session.address != null) {
|
||||||
|
sessionCreateController['address']?.text = session.address!;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future createSession(context) async {
|
||||||
|
Map<Symbol, Value> payload = {
|
||||||
|
Symbol('title'): Value<String>(sessionCreateController['name']!.text),
|
||||||
|
Symbol('content'):
|
||||||
|
Value<String>(sessionCreateController['content']!.text),
|
||||||
|
// we want to maintain existing status during update
|
||||||
|
Symbol('status'): widget.session != null
|
||||||
|
? Value<SessionStatus>(widget.session!.status)
|
||||||
|
: Value<SessionStatus>(SessionStatus.pending),
|
||||||
|
Symbol('date'): Value<DateTime>(
|
||||||
|
DateTime.parse(sessionCreateController['date']!.text)),
|
||||||
|
};
|
||||||
|
|
||||||
|
// if a session exists we'll want to update it
|
||||||
|
// so the payload needs the session id
|
||||||
|
if (widget.session != null) {
|
||||||
|
payload[Symbol('id')] = Value<int>(widget.session!.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
// optional params
|
||||||
|
if (sessionCreateController['address']!.text.isNotEmpty) {
|
||||||
|
payload[Symbol('address')] =
|
||||||
|
Value<String>(sessionCreateController['address']!.text);
|
||||||
|
}
|
||||||
|
|
||||||
|
return await SessionsDao(db)
|
||||||
|
.createOrUpdate(Function.apply(SessionsCompanion.new, [], payload));
|
||||||
|
}
|
||||||
|
|
||||||
|
Future deleteSessionMedia(int sessionId, MediaType mediaType) async {
|
||||||
|
List<MediaItem> deletedMedia =
|
||||||
|
(await MediaItemsDao(db).fromSession(sessionId))
|
||||||
|
.where((mediaItem) => mediaItem.type == mediaType)
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
for (int i = 0; i < deletedMedia.length; i++) {
|
||||||
|
await MediaItemsDao(db).remove(deletedMedia[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future createSessionMedia(
|
||||||
|
title,
|
||||||
|
sessionId,
|
||||||
|
description,
|
||||||
|
reference,
|
||||||
|
mediaType,
|
||||||
|
) async {
|
||||||
|
// if (sessionPayload.photoUri != null) {
|
||||||
|
MediaItemsCompanion mediaItem = MediaItemsCompanion(
|
||||||
|
title: Value(title),
|
||||||
|
description: Value(description),
|
||||||
|
reference: Value(reference.toString()),
|
||||||
|
type: Value(mediaType));
|
||||||
|
|
||||||
|
return await MediaItemsDao(db).createOrUpdate(mediaItem).then((id) async {
|
||||||
|
ObjectMediaItemsCompanion omi = ObjectMediaItemsCompanion(
|
||||||
|
objectId: Value(sessionId),
|
||||||
|
objectType: Value(ObjectType.sessions),
|
||||||
|
mediaId: Value(id),
|
||||||
|
);
|
||||||
|
|
||||||
|
await ObjectMediaItemsDao(db).createOrUpdate(omi);
|
||||||
|
});
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
sessionCreateController['date']!.text =
|
||||||
|
DateFormat('yyyy-MM-dd').format(DateTime.now());
|
||||||
|
|
||||||
|
return Padding(
|
||||||
|
padding: EdgeInsets.fromLTRB(15, 0, 15, 15),
|
||||||
|
child: Form(
|
||||||
|
key: _formKey,
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: <Widget>[
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.only(top: 10, bottom: 10),
|
||||||
|
child: Text('$editorType Session',
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: Theme.of(context).textTheme.titleLarge)),
|
||||||
|
FormTextInput(
|
||||||
|
controller: sessionCreateController['name']!,
|
||||||
|
title: 'Title'),
|
||||||
|
FormTextInput(
|
||||||
|
controller: sessionCreateController['content']!,
|
||||||
|
title: 'Description',
|
||||||
|
icon: Icon(Icons.description_rounded),
|
||||||
|
maxLines: 10),
|
||||||
|
FormTextInput(
|
||||||
|
controller: sessionCreateController['date']!,
|
||||||
|
title: 'Date',
|
||||||
|
icon: Icon(Icons.date_range_rounded),
|
||||||
|
onTap: () {
|
||||||
|
showDatePicker(
|
||||||
|
context: context,
|
||||||
|
initialDate: DateTime.now(),
|
||||||
|
firstDate: DateTime.now(),
|
||||||
|
lastDate: DateTime.now().add(Duration(days: 365)))
|
||||||
|
.then((date) {
|
||||||
|
if (date != null) {
|
||||||
|
sessionCreateController['date']?.text =
|
||||||
|
DateFormat('yyyy-MM-dd').format(date);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}),
|
||||||
|
FormSearchInput(
|
||||||
|
sessionController: sessionCreateController['address']!,
|
||||||
|
optionalPayload: sessionPayload),
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.only(top: 10, bottom: 10),
|
||||||
|
child: TextFormField(
|
||||||
|
readOnly: true,
|
||||||
|
decoration: InputDecoration(
|
||||||
|
prefixIcon: Icon(Icons.image_rounded),
|
||||||
|
filled: true,
|
||||||
|
border: OutlineInputBorder(
|
||||||
|
borderSide: BorderSide.none,
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
),
|
||||||
|
labelText: 'Media (optional)',
|
||||||
|
),
|
||||||
|
controller: sessionCreateController['media'],
|
||||||
|
onTap: () async {
|
||||||
|
FilePickerResult? result = await FilePicker.platform
|
||||||
|
.pickFiles(
|
||||||
|
allowMultiple: true, type: FileType.image);
|
||||||
|
|
||||||
|
if (result != null) {
|
||||||
|
List<PlatformFile> files = result.files;
|
||||||
|
sessionCreateController['media']!.text =
|
||||||
|
files.map((file) => file.name).toString();
|
||||||
|
sessionPayload.files = files;
|
||||||
|
}
|
||||||
|
})),
|
||||||
|
Row(mainAxisAlignment: MainAxisAlignment.end, children: [
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.only(top: 10),
|
||||||
|
child: FilledButton(
|
||||||
|
onPressed: () async => {
|
||||||
|
if (_formKey.currentState!.validate())
|
||||||
|
{
|
||||||
|
await createSession(_formKey.currentContext)
|
||||||
|
.then((sessionId) async {
|
||||||
|
int currentSessionId = sessionId;
|
||||||
|
|
||||||
|
// dirft weirdly doesn't return the proper id if
|
||||||
|
// an upsert ends up bein an update, so we'll
|
||||||
|
// set the id to the provided session for an update
|
||||||
|
if (widget.session != null) {
|
||||||
|
currentSessionId = widget.session!.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if we've found a photo add it to media!
|
||||||
|
if (sessionPayload.photoUri != null) {
|
||||||
|
await deleteSessionMedia(
|
||||||
|
currentSessionId,
|
||||||
|
MediaType.location);
|
||||||
|
await createSessionMedia(
|
||||||
|
'Location Image',
|
||||||
|
currentSessionId,
|
||||||
|
sessionPayload.address,
|
||||||
|
sessionPayload.photoUri,
|
||||||
|
MediaType.location);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if we've selected files to save, save them
|
||||||
|
if (sessionPayload.files != null) {
|
||||||
|
for (int i = 0;
|
||||||
|
i < sessionPayload.files!.length;
|
||||||
|
i++) {
|
||||||
|
PlatformFile file =
|
||||||
|
sessionPayload.files![i];
|
||||||
|
String? type = lookupMimeType(file.path!)!.split('/').first;
|
||||||
|
Uint8List fileBytes =
|
||||||
|
await file.xFile.readAsBytes();
|
||||||
|
|
||||||
|
MediaType mediaType = MediaType.localImage;
|
||||||
|
if (type == "video") {
|
||||||
|
mediaType = MediaType.localVideo;
|
||||||
|
}
|
||||||
|
|
||||||
|
await createSessionMedia(
|
||||||
|
'Local Media',
|
||||||
|
currentSessionId,
|
||||||
|
file.name,
|
||||||
|
base64Encode(fileBytes),
|
||||||
|
mediaType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if session is null it's new so we show the dialog
|
||||||
|
// otherwise the dialog is already open, so no need
|
||||||
|
if (widget.session == null) {
|
||||||
|
SessionsDao(db)
|
||||||
|
.find(currentSessionId)
|
||||||
|
.then((session) =>
|
||||||
|
showGenericDialog(
|
||||||
|
SessionView(
|
||||||
|
session: session),
|
||||||
|
_formKey.currentContext!));
|
||||||
|
}
|
||||||
|
|
||||||
|
Navigator.pop(
|
||||||
|
_formKey.currentContext!, 'Submit');
|
||||||
|
|
||||||
|
if (widget.callback != null) {
|
||||||
|
await widget
|
||||||
|
.callback!(widget.session!.id);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: Text('Submit')))
|
||||||
|
]),
|
||||||
|
],
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,32 +3,77 @@ 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:provider/provider.dart';
|
||||||
import 'package:sendtrain/daos/activities_dao.dart';
|
|
||||||
|
|
||||||
|
import 'package:sendtrain/daos/activities_dao.dart';
|
||||||
|
import 'package:sendtrain/daos/sessions_dao.dart';
|
||||||
import 'package:sendtrain/database/database.dart';
|
import 'package:sendtrain/database/database.dart';
|
||||||
import 'package:sendtrain/extensions/string_extensions.dart';
|
import 'package:sendtrain/extensions/string_extensions.dart';
|
||||||
import 'package:sendtrain/widgets/session_view_achievements.dart';
|
import 'package:sendtrain/widgets/generic/elements/generic_progress_indicator.dart';
|
||||||
import 'package:sendtrain/widgets/session_view_activities.dart';
|
import 'package:sendtrain/widgets/sessions/session_editor.dart';
|
||||||
import 'package:sendtrain/widgets/session_view_media.dart';
|
import 'package:sendtrain/widgets/sessions/session_view_achievements.dart';
|
||||||
|
import 'package:sendtrain/widgets/sessions/session_view_activities.dart';
|
||||||
|
import 'package:sendtrain/widgets/sessions/session_view_media.dart';
|
||||||
|
|
||||||
class SessionView extends StatelessWidget {
|
class SessionView extends StatefulWidget {
|
||||||
const SessionView({super.key, required this.session});
|
const SessionView({super.key, required this.session});
|
||||||
|
|
||||||
final Session session;
|
final Session session;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
State<SessionView> createState() => _SessionViewState();
|
||||||
initializeDateFormatting('en');
|
}
|
||||||
final DateFormat dateFormat = DateFormat('yyyy-MM-dd');
|
|
||||||
|
|
||||||
return FutureBuilder<List<Activity>>(
|
class _SessionViewState extends State<SessionView> {
|
||||||
future: ActivitiesDao(Provider.of<AppDatabase>(context)).sessionActivities(session.id),
|
final _fabKey = GlobalKey<ExpandableFabState>();
|
||||||
|
late Session session;
|
||||||
|
late DateFormat dateFormat;
|
||||||
|
|
||||||
|
String title() {
|
||||||
|
String title = session.title.toTitleCase();
|
||||||
|
|
||||||
|
if (session.address != null) {
|
||||||
|
title = "$title @ ${session.address}";
|
||||||
|
}
|
||||||
|
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
|
||||||
|
void resetState(int sessionId) async {
|
||||||
|
Session updatedSession =
|
||||||
|
await SessionsDao(Provider.of<AppDatabase>(context, listen: false))
|
||||||
|
.find(sessionId);
|
||||||
|
|
||||||
|
final state = _fabKey.currentState;
|
||||||
|
if (state != null) {
|
||||||
|
state.toggle();
|
||||||
|
}
|
||||||
|
|
||||||
|
setState(() {
|
||||||
|
session = updatedSession;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
initState() {
|
||||||
|
super.initState();
|
||||||
|
initializeDateFormatting('en');
|
||||||
|
dateFormat = DateFormat('yyyy-MM-dd');
|
||||||
|
session = widget.session;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return StreamBuilder<List<Activity>>(
|
||||||
|
stream: ActivitiesDao(Provider.of<AppDatabase>(context))
|
||||||
|
.watchSessionActivities(session.id),
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
if (snapshot.hasData) {
|
if (snapshot.hasData) {
|
||||||
final activities = snapshot.data!;
|
final activities = snapshot.data!;
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
floatingActionButtonLocation: ExpandableFab.location,
|
floatingActionButtonLocation: ExpandableFab.location,
|
||||||
floatingActionButton: ExpandableFab(
|
floatingActionButton: ExpandableFab(
|
||||||
|
key: _fabKey,
|
||||||
distance: 70,
|
distance: 70,
|
||||||
type: ExpandableFabType.up,
|
type: ExpandableFabType.up,
|
||||||
overlayStyle: ExpandableFabOverlayStyle(
|
overlayStyle: ExpandableFabOverlayStyle(
|
||||||
@@ -39,17 +84,55 @@ class SessionView extends StatelessWidget {
|
|||||||
FloatingActionButton.extended(
|
FloatingActionButton.extended(
|
||||||
icon: const Icon(Icons.history_outlined),
|
icon: const Icon(Icons.history_outlined),
|
||||||
label: Text('Restart'),
|
label: Text('Restart'),
|
||||||
onPressed: () {},
|
onPressed: () {
|
||||||
|
Session newSession =
|
||||||
|
session.copyWith(status: SessionStatus.pending);
|
||||||
|
|
||||||
|
SessionsDao(Provider.of<AppDatabase>(context,
|
||||||
|
listen: false))
|
||||||
|
.replace(newSession);
|
||||||
|
|
||||||
|
final state = _fabKey.currentState;
|
||||||
|
if (state != null) {
|
||||||
|
state.toggle();
|
||||||
|
}
|
||||||
|
},
|
||||||
),
|
),
|
||||||
FloatingActionButton.extended(
|
FloatingActionButton.extended(
|
||||||
icon: const Icon(Icons.done_all_outlined),
|
icon: const Icon(Icons.done_all_outlined),
|
||||||
label: Text('Done'),
|
label: Text('Done'),
|
||||||
onPressed: () {},
|
onPressed: () {
|
||||||
|
Session newSession =
|
||||||
|
session.copyWith(status: SessionStatus.completed);
|
||||||
|
|
||||||
|
SessionsDao(Provider.of<AppDatabase>(context,
|
||||||
|
listen: false))
|
||||||
|
.replace(newSession);
|
||||||
|
|
||||||
|
final state = _fabKey.currentState;
|
||||||
|
if (state != null) {
|
||||||
|
state.toggle();
|
||||||
|
}
|
||||||
|
},
|
||||||
),
|
),
|
||||||
FloatingActionButton.extended(
|
FloatingActionButton.extended(
|
||||||
icon: const Icon(Icons.edit_outlined),
|
icon: const Icon(Icons.edit_outlined),
|
||||||
label: Text('Edit'),
|
label: Text('Edit'),
|
||||||
onPressed: () {},
|
onPressed: () {
|
||||||
|
showModalBottomSheet<void>(
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius:
|
||||||
|
BorderRadius.all(Radius.circular(10.0)),
|
||||||
|
),
|
||||||
|
context: context,
|
||||||
|
showDragHandle: true,
|
||||||
|
isScrollControlled: true,
|
||||||
|
useSafeArea: true,
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return SessionEditor(
|
||||||
|
session: session, callback: resetState);
|
||||||
|
});
|
||||||
|
},
|
||||||
),
|
),
|
||||||
]),
|
]),
|
||||||
body: Column(
|
body: Column(
|
||||||
@@ -68,7 +151,7 @@ class SessionView extends StatelessWidget {
|
|||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
fontSize: 25, fontWeight: FontWeight.bold),
|
fontSize: 25, fontWeight: FontWeight.bold),
|
||||||
session.title.toTitleCase())),
|
title())),
|
||||||
SessionViewAchievements(session: session),
|
SessionViewAchievements(session: session),
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(left: 15, right: 15),
|
padding: const EdgeInsets.only(left: 15, right: 15),
|
||||||
@@ -88,18 +171,11 @@ class SessionView extends StatelessWidget {
|
|||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 20, fontWeight: FontWeight.bold),
|
fontSize: 20, fontWeight: FontWeight.bold),
|
||||||
'Activites:')),
|
'Activites:')),
|
||||||
SessionViewActivities(
|
SessionViewActivities(activities: activities),
|
||||||
activities: activities),
|
|
||||||
],
|
],
|
||||||
));
|
));
|
||||||
} else {
|
} else {
|
||||||
return Container(
|
return GenericProgressIndicator();
|
||||||
alignment: Alignment.center,
|
|
||||||
child: SizedBox(
|
|
||||||
height: 50.0,
|
|
||||||
width: 50.0,
|
|
||||||
child: CircularProgressIndicator(),
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
+32
-18
@@ -34,28 +34,42 @@ class SessionViewAchievements extends StatelessWidget {
|
|||||||
final sessionActivities = snapshot.data!;
|
final sessionActivities = snapshot.data!;
|
||||||
final achievements = getAchievements(sessionActivities);
|
final achievements = getAchievements(sessionActivities);
|
||||||
|
|
||||||
|
Widget content;
|
||||||
|
if (achievements.isEmpty) {
|
||||||
|
content = Padding(
|
||||||
|
padding: const EdgeInsets.only(left: 10, right: 5),
|
||||||
|
child: ActionChip(
|
||||||
|
visualDensity: VisualDensity.compact,
|
||||||
|
avatar: const Icon(Icons.check_circle_outline),
|
||||||
|
label: Text(maxLines: 1, 'Add Achievements!'),
|
||||||
|
onPressed: () {},
|
||||||
|
));
|
||||||
|
} else {
|
||||||
|
content = ListView.builder(
|
||||||
|
scrollDirection: Axis.horizontal,
|
||||||
|
padding: const EdgeInsets.fromLTRB(10, 0, 10, 0),
|
||||||
|
itemCount: achievements.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, achievements[index].toTitleCase()),
|
||||||
|
onPressed: () {
|
||||||
|
// remove achievements
|
||||||
|
},
|
||||||
|
));
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return Column(
|
return Column(
|
||||||
children: [
|
children: [
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(bottom: 10),
|
padding: const EdgeInsets.only(bottom: 10),
|
||||||
child: SizedBox(
|
child: SizedBox(height: 40, child: content)),
|
||||||
height: 40,
|
|
||||||
child: ListView.builder(
|
|
||||||
scrollDirection: Axis.horizontal,
|
|
||||||
padding: const EdgeInsets.fromLTRB(10, 0, 10, 0),
|
|
||||||
itemCount: achievements.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, achievements[index].toTitleCase()),
|
|
||||||
onPressed: () {},
|
|
||||||
));
|
|
||||||
},
|
|
||||||
))),
|
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
+10
-4
@@ -1,22 +1,28 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:sendtrain/database/database.dart';
|
import 'package:sendtrain/database/database.dart';
|
||||||
import 'package:sendtrain/widgets/activity_card.dart';
|
import 'package:sendtrain/widgets/activities/activity_card.dart';
|
||||||
|
|
||||||
class SessionViewActivities extends StatelessWidget {
|
class SessionViewActivities extends StatefulWidget {
|
||||||
const SessionViewActivities({super.key, required this.activities });
|
const SessionViewActivities({super.key, required this.activities });
|
||||||
|
|
||||||
final List<Activity> activities;
|
final List<Activity> activities;
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<SessionViewActivities> createState() => _SessionViewActivitiesState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _SessionViewActivitiesState extends State<SessionViewActivities> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Expanded(
|
return Expanded(
|
||||||
child: ListView.builder(
|
child: ListView.builder(
|
||||||
// shrinkWrap: true,
|
// shrinkWrap: true,
|
||||||
padding: const EdgeInsets.fromLTRB(10, 0, 10, 0),
|
padding: const EdgeInsets.fromLTRB(10, 0, 10, 0),
|
||||||
itemCount: activities.length,
|
itemCount: widget.activities.length,
|
||||||
itemBuilder: (BuildContext context, int index) {
|
itemBuilder: (BuildContext context, int index) {
|
||||||
return ActivityCard(
|
return ActivityCard(
|
||||||
activity: activities[index]);
|
activity: widget.activities[index]);
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@@ -2,24 +2,33 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:sendtrain/daos/media_items_dao.dart';
|
import 'package:sendtrain/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/media_card.dart';
|
||||||
|
|
||||||
class SessionViewMedia extends StatelessWidget {
|
class SessionViewMedia extends StatefulWidget {
|
||||||
const SessionViewMedia({super.key, required this.session});
|
const SessionViewMedia({super.key, required this.session});
|
||||||
|
|
||||||
final Session session;
|
final Session session;
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<SessionViewMedia> createState() => _SessionViewMediaState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _SessionViewMediaState extends State<SessionViewMedia> {
|
||||||
|
void resetState() {
|
||||||
|
setState(() {});
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return FutureBuilder<List<MediaItem>>(
|
return StreamBuilder<List<MediaItem>>(
|
||||||
future: MediaItemsDao(Provider.of<AppDatabase>(context))
|
stream: MediaItemsDao(Provider.of<AppDatabase>(context))
|
||||||
.fromSession(session),
|
.fromSession(widget.session.id).asStream(),
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
if (snapshot.hasData) {
|
if (snapshot.hasData) {
|
||||||
final mediaItems = snapshot.data!;
|
final mediaItems = snapshot.data!;
|
||||||
|
|
||||||
List<Widget> mediaCards = List.generate(
|
List<Widget> mediaCards = List.generate(
|
||||||
mediaItems.length, (i) => MediaCard(media: mediaItems[i]));
|
mediaItems.length, (i) => MediaCard(media: mediaItems[i], callback: resetState));
|
||||||
|
|
||||||
return Column(
|
return Column(
|
||||||
children: [
|
children: [
|
||||||
@@ -44,6 +44,12 @@ dependencies:
|
|||||||
drift: ^2.22.1
|
drift: ^2.22.1
|
||||||
flutter_expandable_fab: ^2.3.0
|
flutter_expandable_fab: ^2.3.0
|
||||||
drift_flutter: ^0.2.2
|
drift_flutter: ^0.2.2
|
||||||
|
map_location_picker: ^1.2.7
|
||||||
|
file_picker: ^8.1.7
|
||||||
|
http: ^1.2.2
|
||||||
|
uuid: ^4.5.1
|
||||||
|
mime: ^2.0.0
|
||||||
|
video_player: ^2.9.2
|
||||||
|
|
||||||
flutter_launcher_name:
|
flutter_launcher_name:
|
||||||
name: "SendTrain"
|
name: "SendTrain"
|
||||||
|
|||||||
@@ -7,6 +7,12 @@ import 'schema_v1.dart' as v1;
|
|||||||
import 'schema_v2.dart' as v2;
|
import 'schema_v2.dart' as v2;
|
||||||
import 'schema_v3.dart' as v3;
|
import 'schema_v3.dart' as v3;
|
||||||
import 'schema_v4.dart' as v4;
|
import 'schema_v4.dart' as v4;
|
||||||
|
import 'schema_v5.dart' as v5;
|
||||||
|
import 'schema_v6.dart' as v6;
|
||||||
|
import 'schema_v7.dart' as v7;
|
||||||
|
import 'schema_v8.dart' as v8;
|
||||||
|
import 'schema_v9.dart' as v9;
|
||||||
|
import 'schema_v10.dart' as v10;
|
||||||
|
|
||||||
class GeneratedHelper implements SchemaInstantiationHelper {
|
class GeneratedHelper implements SchemaInstantiationHelper {
|
||||||
@override
|
@override
|
||||||
@@ -20,10 +26,22 @@ class GeneratedHelper implements SchemaInstantiationHelper {
|
|||||||
return v3.DatabaseAtV3(db);
|
return v3.DatabaseAtV3(db);
|
||||||
case 4:
|
case 4:
|
||||||
return v4.DatabaseAtV4(db);
|
return v4.DatabaseAtV4(db);
|
||||||
|
case 5:
|
||||||
|
return v5.DatabaseAtV5(db);
|
||||||
|
case 6:
|
||||||
|
return v6.DatabaseAtV6(db);
|
||||||
|
case 7:
|
||||||
|
return v7.DatabaseAtV7(db);
|
||||||
|
case 8:
|
||||||
|
return v8.DatabaseAtV8(db);
|
||||||
|
case 9:
|
||||||
|
return v9.DatabaseAtV9(db);
|
||||||
|
case 10:
|
||||||
|
return v10.DatabaseAtV10(db);
|
||||||
default:
|
default:
|
||||||
throw MissingSchemaException(version, versions);
|
throw MissingSchemaException(version, versions);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const versions = const [1, 2, 3, 4];
|
static const versions = const [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user