200 lines
5.8 KiB
Dart
200 lines
5.8 KiB
Dart
import 'dart:io';
|
|
|
|
import 'package:drift/drift.dart';
|
|
import 'package:drift/native.dart';
|
|
import 'package:path/path.dart' as p;
|
|
import 'package:path_provider/path_provider.dart';
|
|
import 'package:trainhub_flutter/core/constants/app_constants.dart';
|
|
import 'package:trainhub_flutter/data/database/daos/analysis_dao.dart';
|
|
import 'package:trainhub_flutter/data/database/daos/chat_dao.dart';
|
|
import 'package:trainhub_flutter/data/database/daos/exercise_dao.dart';
|
|
import 'package:trainhub_flutter/data/database/daos/knowledge_chunk_dao.dart';
|
|
import 'package:trainhub_flutter/data/database/daos/program_dao.dart';
|
|
import 'package:trainhub_flutter/data/database/daos/training_plan_dao.dart';
|
|
|
|
part 'app_database.g.dart';
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Existing tables (unchanged)
|
|
// ---------------------------------------------------------------------------
|
|
|
|
class Exercises extends Table {
|
|
TextColumn get id => text()();
|
|
TextColumn get name => text()();
|
|
TextColumn get instructions => text().nullable()();
|
|
TextColumn get enrichment => text().nullable()();
|
|
TextColumn get tags => text().nullable()();
|
|
TextColumn get videoUrl => text().nullable()();
|
|
|
|
@override
|
|
Set<Column> get primaryKey => {id};
|
|
}
|
|
|
|
class TrainingPlans extends Table {
|
|
TextColumn get id => text()();
|
|
TextColumn get name => text()();
|
|
TextColumn get sections => text().nullable()();
|
|
|
|
@override
|
|
Set<Column> get primaryKey => {id};
|
|
}
|
|
|
|
class Programs extends Table {
|
|
TextColumn get id => text()();
|
|
TextColumn get name => text()();
|
|
TextColumn get createdAt => text()();
|
|
|
|
@override
|
|
Set<Column> get primaryKey => {id};
|
|
}
|
|
|
|
class ProgramWeeks extends Table {
|
|
TextColumn get id => text()();
|
|
TextColumn get programId =>
|
|
text().references(Programs, #id, onDelete: KeyAction.cascade)();
|
|
IntColumn get position => integer()();
|
|
TextColumn get notes => text().nullable()();
|
|
|
|
@override
|
|
Set<Column> get primaryKey => {id};
|
|
}
|
|
|
|
class ProgramWorkouts extends Table {
|
|
TextColumn get id => text()();
|
|
TextColumn get weekId =>
|
|
text().references(ProgramWeeks, #id, onDelete: KeyAction.cascade)();
|
|
TextColumn get programId =>
|
|
text().references(Programs, #id, onDelete: KeyAction.cascade)();
|
|
TextColumn get day => text()();
|
|
TextColumn get type => text()();
|
|
TextColumn get refId => text().nullable()();
|
|
TextColumn get name => text().nullable()();
|
|
TextColumn get description => text().nullable()();
|
|
BoolColumn get completed => boolean().withDefault(const Constant(false))();
|
|
|
|
@override
|
|
Set<Column> get primaryKey => {id};
|
|
}
|
|
|
|
class AnalysisSessions extends Table {
|
|
TextColumn get id => text()();
|
|
TextColumn get name => text()();
|
|
TextColumn get date => text()();
|
|
TextColumn get videoPath => text().nullable()();
|
|
|
|
@override
|
|
Set<Column> get primaryKey => {id};
|
|
}
|
|
|
|
class Annotations extends Table {
|
|
TextColumn get id => text()();
|
|
TextColumn get sessionId =>
|
|
text().references(AnalysisSessions, #id, onDelete: KeyAction.cascade)();
|
|
RealColumn get startTime => real()();
|
|
RealColumn get endTime => real()();
|
|
TextColumn get name => text().nullable()();
|
|
TextColumn get description => text().nullable()();
|
|
TextColumn get color => text().nullable()();
|
|
|
|
@override
|
|
Set<Column> get primaryKey => {id};
|
|
}
|
|
|
|
class ChatSessions extends Table {
|
|
TextColumn get id => text()();
|
|
TextColumn get title => text().nullable()();
|
|
TextColumn get createdAt => text()();
|
|
TextColumn get updatedAt => text()();
|
|
|
|
@override
|
|
Set<Column> get primaryKey => {id};
|
|
}
|
|
|
|
class ChatMessages extends Table {
|
|
TextColumn get id => text()();
|
|
TextColumn get sessionId =>
|
|
text().references(ChatSessions, #id, onDelete: KeyAction.cascade)();
|
|
TextColumn get role => text()();
|
|
TextColumn get content => text()();
|
|
TextColumn get createdAt => text()();
|
|
|
|
@override
|
|
Set<Column> get primaryKey => {id};
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// v2: Knowledge base chunks
|
|
// ---------------------------------------------------------------------------
|
|
|
|
/// Stores text chunks and their JSON-encoded embedding vectors.
|
|
/// Used for Retrieval-Augmented Generation (RAG) in the AI chat.
|
|
class KnowledgeChunks extends Table {
|
|
/// UUID for this individual chunk.
|
|
TextColumn get id => text()();
|
|
|
|
/// All chunks from the same `addNote()` call share this ID.
|
|
TextColumn get sourceId => text()();
|
|
|
|
/// The raw text of the chunk (max ~500 chars).
|
|
TextColumn get content => text()();
|
|
|
|
/// JSON-encoded `List<double>` — the 768-dim Nomic embedding vector.
|
|
TextColumn get embedding => text()();
|
|
|
|
TextColumn get createdAt => text()();
|
|
|
|
@override
|
|
Set<Column> get primaryKey => {id};
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Database class
|
|
// ---------------------------------------------------------------------------
|
|
|
|
@DriftDatabase(
|
|
tables: [
|
|
Exercises,
|
|
TrainingPlans,
|
|
Programs,
|
|
ProgramWeeks,
|
|
ProgramWorkouts,
|
|
AnalysisSessions,
|
|
Annotations,
|
|
ChatSessions,
|
|
ChatMessages,
|
|
KnowledgeChunks, // added in schema v2
|
|
],
|
|
daos: [
|
|
ExerciseDao,
|
|
TrainingPlanDao,
|
|
ProgramDao,
|
|
AnalysisDao,
|
|
ChatDao,
|
|
KnowledgeChunkDao, // added in schema v2
|
|
],
|
|
)
|
|
class AppDatabase extends _$AppDatabase {
|
|
AppDatabase() : super(_openConnection());
|
|
|
|
@override
|
|
int get schemaVersion => 2;
|
|
|
|
@override
|
|
MigrationStrategy get migration => MigrationStrategy(
|
|
onUpgrade: (migrator, from, to) async {
|
|
// v1 → v2: add knowledge chunks table
|
|
if (from < 2) {
|
|
await migrator.createTable(knowledgeChunks);
|
|
}
|
|
},
|
|
);
|
|
}
|
|
|
|
LazyDatabase _openConnection() {
|
|
return LazyDatabase(() async {
|
|
final dbFolder = await getApplicationDocumentsDirectory();
|
|
final file = File(p.join(dbFolder.path, AppConstants.databaseName));
|
|
return NativeDatabase.createInBackground(file);
|
|
});
|
|
}
|