chromium/ash/system/focus_mode/focus_mode_session.cc

// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ash/system/focus_mode/focus_mode_session.h"

#include <algorithm>

#include "ash/system/focus_mode/focus_mode_util.h"
#include "base/check_op.h"
#include "base/notreached.h"
#include "base/time/time.h"

namespace ash {

FocusModeSession::FocusModeSession(const base::TimeDelta& session_duration,
                                   const base::Time& end_time)
    : session_duration_(session_duration), end_time_(end_time) {}

FocusModeSession::State FocusModeSession::GetState(
    const base::Time& now) const {
  if (now < end_time_) {
    return State::kOn;
  }

  if (persistent_ending_ ||
      now < (end_time_ + focus_mode_util::kEndingMomentDuration)) {
    return State::kEnding;
  }

  return State::kOff;
}

FocusModeSession::Snapshot FocusModeSession::GetSnapshot(
    const base::Time& now) const {
  State state = GetState(now);
  base::TimeDelta remaining_time = GetTimeRemaining(now);
  base::TimeDelta time_elapsed = session_duration_ - remaining_time;
  double progress = time_elapsed / session_duration_;
  return {state, session_duration_, time_elapsed, remaining_time, progress};
}

void FocusModeSession::ExtendSession(const base::Time& now) {
  if (session_duration_ >= focus_mode_util::kMaximumDuration) {
    return;
  }

  const base::TimeDelta valid_new_session_duration =
      std::min(session_duration_ + focus_mode_util::kExtendDuration,
               focus_mode_util::kMaximumDuration);

  // Update `end_time_` only during the ending moment or if a focus session is
  // active.
  const base::TimeDelta session_duration_increase =
      valid_new_session_duration - session_duration_;
  CHECK(!session_duration_increase.is_negative());
  switch (GetState(now)) {
    case State::kOn:
      end_time_ += session_duration_increase;
      break;
    case State::kEnding:
      end_time_ = now + session_duration_increase;
      break;
    case State::kOff:
      break;
  }

  session_duration_ = valid_new_session_duration;
  persistent_ending_ = false;
}

base::TimeDelta FocusModeSession::GetTimeRemaining(
    const base::Time& now) const {
  base::TimeDelta remaining = end_time_ - now;
  return remaining.is_negative() ? base::TimeDelta() : remaining;
}

}  // namespace ash