| // 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. |
| |
| #ifndef ASH_SYSTEM_FOCUS_MODE_FOCUS_MODE_TASKS_MODEL_H_ |
| #define ASH_SYSTEM_FOCUS_MODE_FOCUS_MODE_TASKS_MODEL_H_ |
| |
| #include <optional> |
| #include <vector> |
| |
| #include "ash/ash_export.h" |
| #include "ash/system/focus_mode/focus_mode_tasks_provider.h" |
| #include "base/functional/callback.h" |
| #include "base/memory/raw_ptr.h" |
| #include "base/memory/weak_ptr.h" |
| #include "base/observer_list.h" |
| #include "base/observer_list_types.h" |
| |
| namespace ash { |
| |
| class ASH_EXPORT FocusModeTasksModel final { |
| public: |
| // Options struct used to add or update a task. |
| struct TaskUpdate { |
| TaskUpdate(); |
| TaskUpdate(const TaskUpdate&); |
| ~TaskUpdate(); |
| |
| static TaskUpdate CompletedUpdate(const TaskId& task_id); |
| static TaskUpdate TitleUpdate(const TaskId& task_id, |
| std::string_view title); |
| static TaskUpdate NewTask(std::string_view title); |
| |
| std::optional<TaskId> task_id; |
| std::optional<std::string> title; |
| std::optional<bool> completed; |
| }; |
| |
| class Observer : public base::CheckedObserver { |
| public: |
| virtual void OnSelectedTaskChanged( |
| const std::optional<FocusModeTask>& selected_task) = 0; |
| virtual void OnTasksUpdated(const std::vector<FocusModeTask>& tasks) = 0; |
| virtual void OnTaskCompleted(const FocusModeTask& completed_task) = 0; |
| }; |
| |
| // Interface to enable the model to propagate updates/requests to the server. |
| class Delegate { |
| public: |
| // Fetch a single task by id. Primarily used for tasks loaded from |
| // preferences. |
| using FetchTaskCallback = |
| base::OnceCallback<void(const std::optional<FocusModeTask>& task)>; |
| virtual void FetchTask(const TaskId& task_id, |
| FetchTaskCallback callback) = 0; |
| |
| // Initiate a request for tasks. Implementer is expected to call |
| // `SetTaskList()` if this is successful. |
| virtual void FetchTasks() = 0; |
| |
| // Initiate a request to add the task specified by `update`. Set a callback |
| // to update the id. |
| virtual void AddTask(const TaskUpdate& update, |
| FetchTaskCallback callback) = 0; |
| |
| // Update an existing task described by `update`. |
| virtual void UpdateTask(const TaskUpdate& update) = 0; |
| }; |
| |
| FocusModeTasksModel(); |
| |
| FocusModeTasksModel(const FocusModeTasksModel&) = delete; |
| FocusModeTasksModel& operator=(const FocusModeTasksModel&) = delete; |
| |
| ~FocusModeTasksModel(); |
| |
| void AddObserver(Observer* observer); |
| void RemoveObserver(Observer* observer); |
| |
| void SetDelegate(base::WeakPtr<Delegate> delegate); |
| |
| // Initiate a request for updated task data from the server. |
| void RequestUpdate(); |
| |
| // Mark the task with `task_id` as the selected task. If it is different than |
| // the currently selected task, it will cause an `OnSelectedTaskChanged()` |
| // event. |
| bool SetSelectedTask(const TaskId& task_id); |
| |
| // Select `task` as the selected task. Will attempt to find the task in the |
| // task list by matching the id. If it cannot be found, the task will be added |
| // to the list and submitted as a new task to the server. |
| void SetSelectedTask(const FocusModeTask& task); |
| |
| // Set the selected task from preferences which may be partially constructed. |
| // This may trigger multiple events if the downloaded task data updates |
| // `task`. |
| void SetSelectedTaskFromPrefs(const TaskId& task); |
| |
| // Clears the selected task and triggers `Observer::OnSelectedTaskChanged()` |
| // if appropriate. |
| void ClearSelectedTask(); |
| |
| // Clears all the cached tasks data immediately. Will also notify observers of |
| // this change. |
| void Reset(); |
| |
| // Set the current task list as `tasks`. This will trigger an |
| // `OnTasksUpdated()` event. If this causes a change to the selected task, may |
| // cause an `OnSelectedTaskChanged()` event. |
| void SetTaskList(std::vector<FocusModeTask>&& tasks); |
| |
| // Updates the task with the matching `task_id` with the information from |
| // `task_update`. If the task is the selected task, this will cause an |
| // `OnSelectedTaskChanged()` event. This does NOT trigger `OnTasksUpdated()`. |
| void UpdateTask(const TaskUpdate& task_update); |
| |
| const std::vector<FocusModeTask>& tasks() const; |
| const FocusModeTask* selected_task() const; |
| |
| const FocusModeTask* PendingTaskForTesting() const; |
| const TaskId& PrefTaskIdForTesting() const; |
| |
| private: |
| void OnTaskAdded(const std::optional<FocusModeTask>& fetched_task); |
| |
| void OnPrefTaskFetched(const std::optional<FocusModeTask>& fetched_task); |
| |
| void OnSelectedTaskFetched(const std::optional<FocusModeTask>& fetched_task); |
| |
| // Inserts `task` at the front of `tasks_` then resets `selected_task_` and |
| // `pending_task_` pointers to the matching tasks in `tasks_`. |
| FocusModeTask* InsertTaskIntoTaskList(FocusModeTask&& task); |
| |
| base::WeakPtr<Delegate> delegate_; |
| |
| // A partially populated task set from preferences while we wait to finish |
| // fetching tasks. |
| std::optional<TaskId> pref_task_id_; |
| |
| std::vector<FocusModeTask> tasks_; |
| raw_ptr<FocusModeTask> selected_task_; |
| |
| // A task that was created by the user but has not been synced to the server |
| // so it does not have TaskId. |
| raw_ptr<FocusModeTask> pending_task_; |
| |
| base::ObserverList<Observer> observers_; |
| |
| base::WeakPtrFactory<FocusModeTasksModel> weak_ptr_factory_{this}; |
| }; |
| |
| } // namespace ash |
| |
| #endif // ASH_SYSTEM_FOCUS_MODE_FOCUS_MODE_TASKS_MODEL_H_ |