using System; using System.Collections.Generic; using JetBrains.Annotations; using Unity.Cloud.Collaborate.Models.Api; using Unity.Cloud.Collaborate.Models.Structures; using Unity.Cloud.Collaborate.UserInterface; using UnityEngine; using UnityEngine.Assertions; namespace Unity.Cloud.Collaborate.Models { internal class HistoryModel : IHistoryModel { [NotNull] readonly ISourceControlProvider m_Provider; [NotNull] readonly HashSet m_Requests; const string k_RequestPage = "request-page"; const string k_RequestEntry = "request-entry"; const string k_RequestEntryNumber = "request-entry-number"; /// public event Action HistoryListUpdated; /// public event Action> HistoryListReceived; /// public event Action SelectedRevisionReceived; /// public event Action BusyStatusUpdated; /// public event Action EntryCountUpdated; /// public event Action StateChanged; public HistoryModel([NotNull] ISourceControlProvider provider) { m_Provider = provider; m_Requests = new HashSet(); SelectedRevisionId = string.Empty; SavedRevisionId = string.Empty; } /// public void OnStart() { // Setup events m_Provider.UpdatedHistoryEntries += OnUpdatedHistoryEntries; } /// public void OnStop() { // Clean up. m_Provider.UpdatedHistoryEntries -= OnUpdatedHistoryEntries; } /// public void RestoreState(IWindowCache cache) { // Populate data. PageNumber = cache.HistoryPageNumber; SavedRevisionId = cache.SelectedHistoryRevision; StateChanged?.Invoke(); } /// public void SaveState(IWindowCache cache) { // Update cache. cache.HistoryPageNumber = PageNumber; cache.SelectedHistoryRevision = SelectedRevisionId; } /// /// Event handler for when the requested history entry count has been received. /// /// Received entry count. void OnReceivedHistoryEntryCount(int? entryCount) { RemoveRequest(k_RequestEntryNumber); EntryCountUpdated?.Invoke(entryCount); } /// /// Event handler for when the requested page of history entries has been received. /// /// Received list of entries. void OnReceivedHistoryPage(IReadOnlyList list) { RemoveRequest(k_RequestPage); HistoryListReceived?.Invoke(list); } /// /// Event handler for when a requested single history entry has been received. /// /// Received entry. void OnReceivedHistoryEntry(IHistoryEntry entry) { RemoveRequest(k_RequestEntry); SelectedRevisionReceived?.Invoke(entry); } /// /// Event handler for when the provider has received an updated history list. /// void OnUpdatedHistoryEntries() { HistoryListUpdated?.Invoke(); } /// public void RequestPageOfRevisions(int pageSize) { // Only one request at a time. if (!AddRequest(k_RequestPage)) return; SelectedRevisionId = string.Empty; m_Provider.RequestHistoryPage(PageNumber * pageSize, pageSize, OnReceivedHistoryPage); } /// public void RequestSingleRevision(string revisionId) { // Only one request at a time. if (!AddRequest(k_RequestEntry)) return; SavedRevisionId = string.Empty; SelectedRevisionId = revisionId; m_Provider.RequestHistoryEntry(revisionId, OnReceivedHistoryEntry); } /// public void RequestEntryNumber() { // Only one request at a time. if (!AddRequest(k_RequestEntryNumber)) return; m_Provider.RequestHistoryCount(OnReceivedHistoryEntryCount); } /// public void RequestUpdateTo(string revisionId) { m_Provider.RequestUpdateTo(revisionId); } /// public void RequestRestoreTo(string revisionId) { m_Provider.RequestRestoreTo(revisionId); } /// public void RequestGoBackTo(string revisionId) { m_Provider.RequestGoBackTo(revisionId); } /// public bool SupportsRevert => m_Provider.SupportsRevert; /// public void RequestRevert(string revisionId, IReadOnlyList files) { m_Provider.RequestRevert(revisionId, files); } /// /// Add a started request. /// /// Id of the request to add. /// False if the request already exists. bool AddRequest([NotNull] string requestId) { if (m_Requests.Contains(requestId)) return false; m_Requests.Add(requestId); // Signal background activity if this is the only thing running. if (m_Requests.Count == 1) BusyStatusUpdated?.Invoke(true); return true; } /// /// Remove a finished request. /// /// Id of the request to remove. void RemoveRequest([NotNull] string requestId) { Assert.IsTrue(m_Requests.Contains(requestId), $"Expects request to have first been made for it to have been finished: {requestId}"); m_Requests.Remove(requestId); // Signal no background activity if no requests in progress if (m_Requests.Count == 0) BusyStatusUpdated?.Invoke(false); } /// public bool Busy => m_Requests.Count != 0; /// public int PageNumber { get; set; } /// public string SelectedRevisionId { get; private set; } /// public string SavedRevisionId { get; private set; } /// public bool IsRevisionSelected => !string.IsNullOrEmpty(SelectedRevisionId); } }