Search code examples
databaseflutterdartsqliteredundancy

How to save Some Dynamic data without duplications in SQLite


I'm developing a Pomodoro App using flutter. and this is my first Flutter Project. In this case I want to save focus session data in a SQLite Database. I have the Following code in focus_provider.dart (this is linked as a widget to demo_page.dart which is a widget that provides the timer to the app.)

import 'package:flutter/foundation.dart';
import 'package:sqflite/sqflite.dart';
import '../db/db_helper.dart';
import 'package:path/path.dart';

class FocusProvider with ChangeNotifier {
  // Timer variables
  bool isPlaying = false;
  bool isTimerRunning = false;
  double timerValue = 0.0;
  int maxDuration = 10; // Default max duration in seconds

  // Focus stats
  Duration totalFocusTime = Duration.zero;
  double goalPercentage = 0.0;

  // Daily Goal
  int _dailyGoalInSeconds = 28800; // Default to 8 hours
  int get dailyGoalInSeconds => _dailyGoalInSeconds;

  // Elapsed time tracking
  Duration _elapsedTime = Duration.zero;
  DateTime? _startPauseTime;

  // Constructor to initialize data
  FocusProvider() {
    loadDailyGoal();
    loadTotalFocusTime();
    logDatabasePath();
  }

  // Start the timer
  void startTimer() {
    isTimerRunning = true;
    isPlaying = true;

    if (_startPauseTime != null) {
      _elapsedTime += DateTime.now().difference(_startPauseTime!);
    }

    notifyListeners();
  }

  void logDatabasePath() async {
    final dbPath = await getDatabasesPath();
    print('Database Path: ${join(dbPath, 'focus_pro.db')}');
  }

  // Pause the timer and save the session
  Future<void> pauseTimer() async {
    isTimerRunning = false;
    isPlaying = false;
    _startPauseTime = DateTime.now();

    if (_elapsedTime.inSeconds > 0) {
      await saveFocusSession();
    }

    notifyListeners();
  }

  // Reset the timer and save the session if needed
  Future<void> resetTimer() async {
    if (_elapsedTime.inSeconds > 0) {
      await saveFocusSession();
    }

    isTimerRunning = false;
    isPlaying = false;
    timerValue = 0.0;
    _elapsedTime = Duration.zero;
    _startPauseTime = null;
    notifyListeners();
  }

  // Update timer progress
  void updateTimerValue(double value) {
    timerValue = value;
    notifyListeners();
  }

  // Save the focus session duration
  Future<void> saveFocusSession() async {
    if (_startPauseTime != null) {
      _elapsedTime += DateTime.now().difference(_startPauseTime!);
    }

    final sessionDuration = _elapsedTime;

    if (sessionDuration.inSeconds > 0) {
      await addFocusSession(sessionDuration);
    }

    _elapsedTime = Duration.zero;
    _startPauseTime = null;
  }

  // Add a new focus session
  Future<void> addFocusSession(Duration sessionDuration,
      {bool isCompleted = true}) async {
    final dbHelper = DBHelper();
    final today = DateTime.now().toIso8601String().split('T').first;

    await dbHelper.insertFocusSession(
        today, sessionDuration.inSeconds, isCompleted);

    // Update total focus time
    totalFocusTime += sessionDuration;
    updateGoalPercentage(_dailyGoalInSeconds);
    notifyListeners();
  }

// rest of the code
}

I want to save the current focused duration when user press the pause button or reset button (implemented in demo_page.dart). I tried this in various ways but every time got troubled. sometimes data (duration) duplications were happened.

What I want to do :

Imagine, the user starts a 10 min Focus session. he pause the timer at 5th minute. then the data should be saved in db (300 in seconds). again he starts the timer, then pause at 7th min. 120 should be saved as the duration. but it's been saved 420 (all 7 mins.). after that when completing the timer, it again saves another 600 (the full 10min duration set by user)

in the demo_page.dart, I have following code. I have a doubt that there's a problem in somewhere on calling functions.

void _onTimerComplete() {
    final provider = Provider.of<FocusProvider>(context, listen: false);
    provider.addFocusSession(Duration(seconds: provider.maxDuration));
// rest

Additionally, I'm using a db_helper.dart file.


Solution

  • Yeah it was resolved! I just did some changes in demo_page.dart to call the function from there.

    This logic solved the bug.

    // Calculate the incremental duration since the last save
    int currentTimerValue = provider.timerValue.toInt();
    int incrementalDuration = currentTimerValue - provider.lastSavedTime;
    
    // Save the incremental duration if it's valid
    if (incrementalDuration > 0) {
      provider.addFocusSession(Duration(seconds: incrementalDuration),
          isCompleted: true, taskType: selectedItem);
      provider.lastSavedTime = currentTimerValue; // Update the last saved time
    }