Compare commits
2 Commits
e36d2a837a
...
48f716cdb0
Author | SHA1 | Date | |
---|---|---|---|
![]() |
48f716cdb0 | ||
![]() |
e78788d67a |
android/app/src/main
lib
daos
database
main.dartwidgets
test/drift/sendtrain/generated
@ -1,6 +1,7 @@
|
||||
<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
|
||||
android:label="sendtrain"
|
||||
android:name="${applicationName}"
|
||||
|
@ -76,6 +76,7 @@ class MediaItemsDao extends DatabaseAccessor<AppDatabase>
|
||||
});
|
||||
}
|
||||
|
||||
Future remove(MediaItem mediaItem) => delete(mediaItems).delete(mediaItem);
|
||||
Future removeAll(Iterable<int> mediaItemIds) {
|
||||
return (delete(mediaItems)..where((table) => table.id.isIn(mediaItemIds)))
|
||||
.go();
|
||||
|
@ -8,7 +8,7 @@ class SessionsDao extends DatabaseAccessor<AppDatabase> with _$SessionsDaoMixin
|
||||
SessionsDao(super.db);
|
||||
|
||||
Future<Session> find(int id) => (select(sessions)..where((session) => session.id.equals(id) )).getSingle();
|
||||
Future<List<Session>> all() => (select(sessions)..orderBy([(session) => OrderingTerm(expression: session.createdAt, mode: OrderingMode.desc)])).get();
|
||||
Future<List<Session>> all() => select(sessions).get();
|
||||
Stream<List<Session>> watch() => select(sessions).watch();
|
||||
Future createOrUpdate(SessionsCompanion session) => into(sessions).insertOnConflictUpdate(session);
|
||||
Future replace(Session session) => update(sessions).replace(session);
|
||||
|
@ -35,7 +35,7 @@ class AppDatabase extends _$AppDatabase {
|
||||
AppDatabase() : super(_openConnection());
|
||||
|
||||
@override
|
||||
int get schemaVersion => 7;
|
||||
int get schemaVersion => 10;
|
||||
|
||||
@override
|
||||
MigrationStrategy get migration {
|
||||
@ -141,13 +141,13 @@ class ObjectMediaItems extends Table {
|
||||
dateTime().withDefault(Variable(DateTime.now()))();
|
||||
}
|
||||
|
||||
enum MediaType { youtube, image, location }
|
||||
enum MediaType { youtube, image, location, localImage, localVideo }
|
||||
|
||||
class MediaItems extends Table {
|
||||
IntColumn get id => integer().autoIncrement()();
|
||||
TextColumn get title => text().withLength(min: 3, max: 32)();
|
||||
TextColumn get description => text().named('body')();
|
||||
TextColumn get reference => text().withLength(min: 3, max: 256)();
|
||||
TextColumn get reference => text()();
|
||||
TextColumn get type => textEnum<MediaType>()();
|
||||
DateTimeColumn get createdAt =>
|
||||
dateTime().withDefault(Variable(DateTime.now()))();
|
||||
|
@ -1764,10 +1764,7 @@ class $MediaItemsTable extends MediaItems
|
||||
@override
|
||||
late final GeneratedColumn<String> reference = GeneratedColumn<String>(
|
||||
'reference', aliasedName, false,
|
||||
additionalChecks:
|
||||
GeneratedColumn.checkTextLength(minTextLength: 3, maxTextLength: 256),
|
||||
type: DriftSqlType.string,
|
||||
requiredDuringInsert: true);
|
||||
type: DriftSqlType.string, requiredDuringInsert: true);
|
||||
static const VerificationMeta _typeMeta = const VerificationMeta('type');
|
||||
@override
|
||||
late final GeneratedColumnWithTypeConverter<MediaType, String> type =
|
||||
|
@ -1088,6 +1088,406 @@ final class Schema7 extends i0.VersionedSchema {
|
||||
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({
|
||||
required Future<void> Function(i1.Migrator m, Schema2 schema) from1To2,
|
||||
required Future<void> Function(i1.Migrator m, Schema3 schema) from2To3,
|
||||
@ -1095,6 +1495,9 @@ i0.MigrationStepWithVersion migrationSteps({
|
||||
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 {
|
||||
switch (currentVersion) {
|
||||
@ -1128,6 +1531,21 @@ i0.MigrationStepWithVersion migrationSteps({
|
||||
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:
|
||||
throw ArgumentError.value('Unknown migration from $currentVersion');
|
||||
}
|
||||
@ -1141,6 +1559,9 @@ i1.OnUpgrade stepByStep({
|
||||
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(
|
||||
step: migrationSteps(
|
||||
@ -1150,4 +1571,7 @@ i1.OnUpgrade stepByStep({
|
||||
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
@ -7,24 +7,29 @@ Future<void> seedDb(AppDatabase database) async {
|
||||
// seed data setup
|
||||
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.'
|
||||
'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 Bloc'
|
||||
],
|
||||
[
|
||||
'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.'
|
||||
'Climbers Rcok Inc.'
|
||||
],
|
||||
[
|
||||
'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.'
|
||||
'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.'
|
||||
'Up the Bloc'
|
||||
],
|
||||
];
|
||||
|
||||
@ -61,6 +66,7 @@ Future<void> seedDb(AppDatabase database) async {
|
||||
title: sessionValue[0],
|
||||
content: sessionValue[1],
|
||||
status: status,
|
||||
address: sessionValue[2],
|
||||
date: Value(DateTime.now())))
|
||||
.then((sessionId) async {
|
||||
// activities things
|
||||
@ -162,6 +168,23 @@ Future<void> seedDb(AppDatabase database) async {
|
||||
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));
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -89,7 +89,7 @@ class _AppState extends State<App> {
|
||||
NavigationDestination(
|
||||
icon: Icon(Icons.sports), label: "Sessions"),
|
||||
NavigationDestination(
|
||||
icon: Icon(Icons.landscape), label: "Activities"),
|
||||
icon: Icon(Icons.sports_gymnastics_rounded), label: "Activities"),
|
||||
NavigationDestination(
|
||||
icon: Icon(Icons.calendar_month_rounded), label: "Plan"),
|
||||
NavigationDestination(
|
||||
|
@ -1,24 +1,73 @@
|
||||
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 StatelessWidget {
|
||||
const MediaCard({super.key, required this.media});
|
||||
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) {
|
||||
String image = '';
|
||||
dynamic image;
|
||||
|
||||
if (media.type == MediaType.image || media.type == MediaType.location) {
|
||||
image = media.reference;
|
||||
image = NetworkImage(media.reference);
|
||||
} else if (media.type == MediaType.localImage) {
|
||||
image = Image.memory(base64Decode(media.reference)).image;
|
||||
} else if (media.type == MediaType.youtube) {
|
||||
image = 'https://img.youtube.com/vi/${media.reference}/0.jpg';
|
||||
image =
|
||||
NetworkImage('https://img.youtube.com/vi/${media.reference}/0.jpg');
|
||||
} else if (media.type == MediaType.localVideo) {
|
||||
|
||||
}
|
||||
|
||||
return DecorationImage(image: NetworkImage(image), fit: BoxFit.cover);
|
||||
return DecorationImage(image: image, fit: BoxFit.cover);
|
||||
}
|
||||
|
||||
return Container(
|
||||
@ -32,6 +81,18 @@ class MediaCard extends StatelessWidget {
|
||||
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(''),
|
||||
|
@ -1,3 +1,5 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:sendtrain/database/database.dart';
|
||||
import 'package:youtube_player_flutter/youtube_player_flutter.dart';
|
||||
@ -16,6 +18,8 @@ class MediaContent extends StatelessWidget {
|
||||
|
||||
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,
|
||||
|
@ -11,9 +11,8 @@ class MediaDetails extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
return Padding(
|
||||
padding: EdgeInsets.fromLTRB(15, 0, 15, 15),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
child: ListView(
|
||||
shrinkWrap: true,
|
||||
children: <Widget>[
|
||||
ClipRRect(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
@ -26,6 +25,7 @@ class MediaDetails extends StatelessWidget {
|
||||
media.description,
|
||||
style: const TextStyle(fontSize: 20),
|
||||
)),
|
||||
|
||||
const Divider(
|
||||
indent: 20,
|
||||
endIndent: 20,
|
||||
|
@ -24,9 +24,9 @@ class SessionCardFull extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _SessionCardFullState extends State<SessionCardFull> {
|
||||
late final List<MediaItem> mediaItems;
|
||||
late final MediaItem? sessionImage;
|
||||
late final Session session;
|
||||
// late final List<MediaItem> mediaItems;
|
||||
// late final MediaItem? sessionImage;
|
||||
// late final Session session;
|
||||
|
||||
String sessionTitle(Session session) {
|
||||
String title = session.title.toTitleCase();
|
||||
@ -36,17 +36,22 @@ class _SessionCardFullState extends State<SessionCardFull> {
|
||||
return title;
|
||||
}
|
||||
|
||||
@override
|
||||
initState() {
|
||||
super.initState();
|
||||
session = widget.session;
|
||||
mediaItems = widget.mediaItems;
|
||||
sessionImage = mediaItems
|
||||
.firstWhereOrNull((mediaItem) => mediaItem.type == MediaType.location);
|
||||
}
|
||||
// @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
|
||||
|
@ -20,20 +20,25 @@ class SessionCardSmall extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _SessionCardSmallState extends State<SessionCardSmall> {
|
||||
late final List<MediaItem> mediaItems;
|
||||
late final MediaItem? sessionImage;
|
||||
late final Session session;
|
||||
// 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
|
||||
// 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
|
||||
@ -42,7 +47,11 @@ class _SessionCardSmallState extends State<SessionCardSmall> {
|
||||
// overlayColor: MaterialStateColor(Colors.deepPurple as int),
|
||||
splashColor: Colors.deepPurple,
|
||||
borderRadius: const BorderRadius.all(Radius.elliptical(10, 10)),
|
||||
onLongPress: () => showMediaDetailWidget(context, sessionImage!),
|
||||
onLongPress: () {
|
||||
if (sessionImage != null) {
|
||||
showMediaDetailWidget(context, sessionImage);
|
||||
}
|
||||
},
|
||||
onTap: () =>
|
||||
showGenericDialog(SessionView(session: session), context),
|
||||
child: Container(
|
||||
|
@ -1,8 +1,11 @@
|
||||
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';
|
||||
@ -28,6 +31,7 @@ class SessionEditor extends StatefulWidget {
|
||||
class SessionPayload {
|
||||
String? photoUri;
|
||||
String? address;
|
||||
List<PlatformFile>? files;
|
||||
}
|
||||
|
||||
class _SessionEditorState extends State<SessionEditor> {
|
||||
@ -95,32 +99,43 @@ class _SessionEditorState extends State<SessionEditor> {
|
||||
.createOrUpdate(Function.apply(SessionsCompanion.new, [], payload));
|
||||
}
|
||||
|
||||
Future createSessionMedia(context, sessionId) async {
|
||||
Future deleteSessionMedia(int sessionId, MediaType mediaType) async {
|
||||
List<MediaItem> deletedMedia =
|
||||
await MediaItemsDao(db).fromSession(sessionId)
|
||||
..where((mediaItem) => mediaItem.type == MediaType.location);
|
||||
(await MediaItemsDao(db).fromSession(sessionId))
|
||||
.where((mediaItem) => mediaItem.type == mediaType)
|
||||
.toList();
|
||||
|
||||
await MediaItemsDao(db).removeAll(deletedMedia.map((m) => m.id));
|
||||
|
||||
if (sessionPayload.photoUri != null) {
|
||||
MediaItemsCompanion mediaItem = MediaItemsCompanion(
|
||||
title: Value('Location Image'),
|
||||
description: Value(sessionPayload.address!),
|
||||
reference: Value(sessionPayload.photoUri!),
|
||||
type: Value(MediaType.location));
|
||||
|
||||
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);
|
||||
});
|
||||
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 =
|
||||
@ -164,33 +179,35 @@ class _SessionEditorState extends State<SessionEditor> {
|
||||
}
|
||||
});
|
||||
}),
|
||||
// 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: 'Select Media (optional)',
|
||||
// ),
|
||||
// controller: sessionCreateController['media'],
|
||||
// onTap: () async {
|
||||
// FilePickerResult? result = await FilePicker.platform
|
||||
// .pickFiles(allowMultiple: true);
|
||||
|
||||
// if (result != null) {
|
||||
// List<File> files = result.paths
|
||||
// .map((path) => File(path!))
|
||||
// .toList();
|
||||
// }
|
||||
// })),
|
||||
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),
|
||||
@ -211,9 +228,40 @@ class _SessionEditorState extends State<SessionEditor> {
|
||||
|
||||
// if we've found a photo add it to media!
|
||||
if (sessionPayload.photoUri != null) {
|
||||
await deleteSessionMedia(
|
||||
currentSessionId,
|
||||
MediaType.location);
|
||||
await createSessionMedia(
|
||||
_formKey.currentContext,
|
||||
currentSessionId);
|
||||
'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
|
||||
|
@ -34,28 +34,42 @@ class SessionViewAchievements extends StatelessWidget {
|
||||
final sessionActivities = snapshot.data!;
|
||||
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(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 10),
|
||||
child: SizedBox(
|
||||
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: () {},
|
||||
));
|
||||
},
|
||||
))),
|
||||
child: SizedBox(height: 40, child: content)),
|
||||
],
|
||||
);
|
||||
} else {
|
||||
|
@ -4,22 +4,31 @@ import 'package:sendtrain/daos/media_items_dao.dart';
|
||||
import 'package:sendtrain/database/database.dart';
|
||||
import 'package:sendtrain/widgets/media/media_card.dart';
|
||||
|
||||
class SessionViewMedia extends StatelessWidget {
|
||||
class SessionViewMedia extends StatefulWidget {
|
||||
const SessionViewMedia({super.key, required this.session});
|
||||
|
||||
final Session session;
|
||||
|
||||
@override
|
||||
State<SessionViewMedia> createState() => _SessionViewMediaState();
|
||||
}
|
||||
|
||||
class _SessionViewMediaState extends State<SessionViewMedia> {
|
||||
void resetState() {
|
||||
setState(() {});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return FutureBuilder<List<MediaItem>>(
|
||||
future: MediaItemsDao(Provider.of<AppDatabase>(context))
|
||||
.fromSession(session.id),
|
||||
return StreamBuilder<List<MediaItem>>(
|
||||
stream: MediaItemsDao(Provider.of<AppDatabase>(context))
|
||||
.fromSession(widget.session.id).asStream(),
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.hasData) {
|
||||
final mediaItems = snapshot.data!;
|
||||
|
||||
List<Widget> mediaCards = List.generate(
|
||||
mediaItems.length, (i) => MediaCard(media: mediaItems[i]));
|
||||
mediaItems.length, (i) => MediaCard(media: mediaItems[i], callback: resetState));
|
||||
|
||||
return Column(
|
||||
children: [
|
||||
|
@ -48,6 +48,8 @@ dependencies:
|
||||
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:
|
||||
name: "SendTrain"
|
||||
|
@ -10,6 +10,9 @@ 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 {
|
||||
@override
|
||||
@ -29,10 +32,16 @@ class GeneratedHelper implements SchemaInstantiationHelper {
|
||||
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:
|
||||
throw MissingSchemaException(version, versions);
|
||||
}
|
||||
}
|
||||
|
||||
static const versions = const [1, 2, 3, 4, 5, 6, 7];
|
||||
static const versions = const [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
|
||||
}
|
||||
|
2009
test/drift/sendtrain/generated/schema_v10.dart
Normal file
2009
test/drift/sendtrain/generated/schema_v10.dart
Normal file
File diff suppressed because it is too large
Load Diff
2012
test/drift/sendtrain/generated/schema_v8.dart
Normal file
2012
test/drift/sendtrain/generated/schema_v8.dart
Normal file
File diff suppressed because it is too large
Load Diff
2009
test/drift/sendtrain/generated/schema_v9.dart
Normal file
2009
test/drift/sendtrain/generated/schema_v9.dart
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user