import 'dart:io' show Platform, Directory; import 'package:flutter/material.dart'; import 'package:path/path.dart' as path; import 'package:sqflite_common_ffi/sqflite_ffi.dart'; const settingsDir = '.journaler'; const dbFileName = 'journaler.db'; class DB { static late Database db; static const String _schema = ''' CREATE TABLE IF NOT EXISTS notes ( id INTEGER PRIMARY KEY AUTOINCREMENT, date TEXT DEFAULT CURRENT_TIMESTAMP, content TEXT NOT NULL ); CREATE INDEX IF NOT EXISTS idx_notes_date ON notes (date); CREATE UNIQUE INDEX IF NOT EXISTS idx_notes_date_unique ON notes (date); -- Todos are "static", we are only interested in the latest entry -- ie. they're not really a list but instead a string -- But we will also keep a history of all todos -- Because we might as well CREATE TABLE IF NOT EXISTS scratches ( id INTEGER PRIMARY KEY AUTOINCREMENT, date TEXT DEFAULT CURRENT_TIMESTAMP, content TEXT NOT NULL ); CREATE INDEX IF NOT EXISTS idx_scratches_date ON scratches (date); CREATE UNIQUE INDEX IF NOT EXISTS idx_scratches_date_unique ON scratches (date); CREATE TABLE IF NOT EXISTS settings ( key TEXT PRIMARY KEY NOT NULL, value TEXT NOT NULL ); '''; static Future _getDatabasePath() async { debugPrint('Attempting to get database path...'); if (Platform.isWindows || Platform.isLinux) { // Get user's home directory final home = Platform.environment['HOME'] ?? Platform.environment['USERPROFILE']; if (home == null) { throw Exception('Could not find home directory'); } debugPrint('Home directory found: home'); final dbDir = Directory(path.join(home, settingsDir)); if (!await dbDir.exists()) { await dbDir.create(recursive: true); debugPrint('$settingsDir directory created'); } else { debugPrint('$settingsDir directory already exists'); } return path.join(dbDir.path, dbFileName); } else { // Default path for other platforms final databasesPath = await databaseFactoryFfi.getDatabasesPath(); debugPrint('Using default databases path: databasesPath'); return path.join(databasesPath, dbFileName); } } static Future init() async { debugPrint('Starting database initialization...'); sqfliteFfiInit(); final dbPath = await _getDatabasePath(); debugPrint('Database path: dbPath'); try { db = await databaseFactoryFfi.openDatabase( dbPath, options: OpenDatabaseOptions( version: 1, onCreate: (db, version) async { debugPrint('Creating database schema...'); await db.execute(_schema); debugPrint('Database schema created successfully'); }, ), ); debugPrint('Database opened and initialized'); } catch (e) { debugPrint('Failed to initialize database: e'); rethrow; } } // Settings Management static Future getSetting(String key) async { final List> maps = await db.query( 'settings', columns: ['value'], where: 'key = ?', whereArgs: [key], ); if (maps.isNotEmpty) { return maps.first['value'] as String?; } return null; } static Future setSetting(String key, String value) async { await db.insert( 'settings', {'key': key, 'value': value}, conflictAlgorithm: ConflictAlgorithm.replace, ); debugPrint("Setting updated: $key = $value"); } }