Initial Commit

This commit is contained in:
Sebastian Cabrera 2021-08-02 05:44:37 -04:00
parent 53eb92e9af
commit 270ab7d11f
15341 changed files with 700234 additions and 0 deletions

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 1035e37a45cca054e9ac5defc9e1f0c7
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,237 @@
using System;
using System.Collections.Generic;
using JetBrains.Annotations;
using Unity.Cloud.Collaborate.Models.Enums;
using Unity.Cloud.Collaborate.Models.Structures;
namespace Unity.Cloud.Collaborate.Models.Api
{
internal interface ISourceControlProvider
{
/// <summary>
/// Event called whenever the change list is updated.
/// </summary>
event Action UpdatedChangeList;
/// <summary>
/// Event called whenever the selected change list is updated.
/// </summary>
event Action<IReadOnlyList<string>> UpdatedSelectedChangeList;
/// <summary>
/// Event called whenever the list of historical revisions is updated.
/// </summary>
event Action UpdatedHistoryEntries;
/// <summary>
/// Event called whenever a long operation (with progress) has completed / started.
/// </summary>
event Action<bool> UpdatedOperationStatus;
/// <summary>
/// Event called whenever a long operation progress has changed.
/// </summary>
event Action<IProgressInfo> UpdatedOperationProgress;
/// <summary>
/// Event called whenever an error has occurred.
/// </summary>
event Action<IErrorInfo> ErrorOccurred;
/// <summary>
/// Event called whenever an error has cleared.
/// </summary>
event Action ErrorCleared;
/// <summary>
/// Event called whenever the conflict state changes.
/// </summary>
event Action<bool> UpdatedConflictState;
/// <summary>
/// Event called whenever the availability of remote revisions changes.
/// </summary>
event Action<bool> UpdatedRemoteRevisionsAvailability;
/// <summary>
/// Event that is triggered when the project status changes.
/// </summary>
event Action<ProjectStatus> UpdatedProjectStatus;
/// <summary>
/// Get whether there are available revisions to fetch.
/// </summary>
/// <returns>True if there are revisions available</returns>
bool GetRemoteRevisionAvailability();
/// <summary>
/// Get whether there is a conflict or not.
/// </summary>
/// <returns>True if there is a conflict.</returns>
bool GetConflictedState();
/// <summary>
/// Get the current progress state.
/// </summary>
/// <returns>The current progress state. Null if no operation ongoing.</returns>
[CanBeNull]
IProgressInfo GetProgressState();
/// <summary>
/// Get the current error state.
/// </summary>
/// <returns>The current error state. Null if no errors presently.</returns>
[CanBeNull]
IErrorInfo GetErrorState();
/// <summary>
/// Returns the current project status.
/// </summary>
/// <returns>Current project status.</returns>
ProjectStatus GetProjectStatus();
/// <summary>
/// Request the current change list.
/// </summary>
/// <param name="callback">Callback for the result.</param>
void RequestChangeList([NotNull] Action<IReadOnlyList<IChangeEntry>> callback);
/// <summary>
/// Publish files to Collaborate.
/// </summary>
/// <param name="message">Message to commit with.</param>
/// <param name="changes">Changes to publish. Pass null to publish all.</param>
void RequestPublish([NotNull] string message, [CanBeNull] IReadOnlyList<IChangeEntry> changes = null);
/// <summary>
/// Request a single historical revision.
/// </summary>
/// <param name="revisionId">Id of the revision to request.</param>
/// <param name="callback">Callback for the result.</param>
void RequestHistoryEntry([NotNull] string revisionId, [NotNull] Action<IHistoryEntry> callback);
/// <summary>
/// Request a page of historical revisions.
/// </summary>
/// <param name="offset">Where to start the page from.</param>
/// <param name="pageSize">Number of entries in the page.</param>
/// <param name="callback">Callback for the result.</param>
void RequestHistoryPage(int offset, int pageSize, [NotNull] Action<IReadOnlyList<IHistoryEntry>> callback);
/// <summary>
/// Request the total number of historical revisions.
/// </summary>
/// <param name="callback">Callback for the result.</param>
void RequestHistoryCount([NotNull] Action<int?> callback);
/// <summary>
/// Revert the specified file to the state of the current revision.
/// of the source control system, or delete it if it's a new file.
/// </summary>
/// <param name="entry">Entry to discard.</param>
void RequestDiscard([NotNull] IChangeEntry entry);
/// <summary>
/// Revert the specified files to the state of the current revision.
/// of the source control system.
/// </summary>
/// <param name="paths">List of entries to discard.</param>
void RequestBulkDiscard([NotNull] IReadOnlyList<IChangeEntry> entries);
/// <summary>
/// Diff the changes for the file at the given path.
/// </summary>
/// <param name="path">Path of the file to diff.</param>
void RequestDiffChanges([NotNull] string path);
/// <summary>
/// Returns true if the provider supports revert.
/// </summary>
bool SupportsRevert { get; }
/// <summary>
/// Request revert the specified files to the given revision.
/// </summary>
/// <param name="revisionId">Revision to revert the files back to.</param>
/// <param name="files">Files to revert back.</param>
void RequestRevert([NotNull] string revisionId, [NotNull] IReadOnlyList<string> files);
/// <summary>
/// Request to update the state of the project to a new provided revision.
/// </summary>
/// <param name="revisionId">New revision id of the project to go to.</param>
void RequestUpdateTo([NotNull] string revisionId);
/// <summary>
/// Request to take the state of the project back to the given (and current) revision.
/// </summary>
/// <param name="revisionId">Current revision id of the project to go back to.</param>
void RequestRestoreTo([NotNull] string revisionId);
/// <summary>
/// Request to take the state of the project back to the given revision, but do not change the current revision or history.
/// </summary>
/// <param name="revisionId">Revision id to go back to.</param>
void RequestGoBackTo([NotNull] string revisionId);
/// <summary>
/// Clears the error state.
/// </summary>
void ClearError();
/// <summary>
/// Show the difference between both version of a conlicted file.
/// </summary>
/// <param name="path">Path of the file to show.</param>
void RequestShowConflictedDifferences([NotNull] string path);
/// <summary>
/// Request to choose merge for the provided conflict.
/// </summary>
/// <param name="path">Path of the file to choose merge for.</param>
void RequestChooseMerge([NotNull] string path);
/// <summary>
/// Request to choose mine for the provided conflict.
/// </summary>
/// <param name="paths">Paths of the files to choose mine for.</param>
void RequestChooseMine([NotNull] string[] paths);
/// <summary>
/// Request to choose remote for the provided conflict.
/// </summary>
/// <param name="paths">Paths of the files to choose remote for.</param>
void RequestChooseRemote([NotNull] string[] paths);
/// <summary>
/// Request sync to latest revision.
/// </summary>
void RequestSync();
/// <summary>
/// Request cancel current job.
/// </summary>
void RequestCancelJob();
/// <summary>
/// Request to turn on the service.
/// </summary>
/// <returns></returns>
void RequestTurnOnService();
/// <summary>
/// Show the service page.
/// </summary>
void ShowServicePage();
/// <summary>
/// Show login page.
/// </summary>
void ShowLoginPage();
/// <summary>
/// Show no seat page.
/// </summary>
void ShowNoSeatPage();
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c09dfd4388accab4b956bcef16d321a1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,419 @@
using System;
using System.Collections.Generic;
using System.Linq;
using JetBrains.Annotations;
using Unity.Cloud.Collaborate.Models.Api;
using Unity.Cloud.Collaborate.Models.Structures;
using Unity.Cloud.Collaborate.UserInterface;
using Unity.Cloud.Collaborate.Utilities;
using UnityEngine;
using UnityEngine.Assertions;
namespace Unity.Cloud.Collaborate.Models
{
internal class ChangesModel : IChangesModel
{
protected readonly ISourceControlProvider m_Provider;
/// <inheritdoc />
public event Action UpdatedChangeList;
/// <inheritdoc />
public event Action OnUpdatedSelectedChanges;
/// <inheritdoc />
public event Action<bool> BusyStatusUpdated;
/// <inheritdoc />
public event Action StateChanged;
internal Dictionary<string, IChangeEntryData> entryData;
internal Dictionary<string, bool> toggledEntries;
IReadOnlyList<IChangeEntryData> m_Conflicted;
readonly ChangeEntryData m_AllItem;
readonly HashSet<string> m_Requests;
const string k_RequestNewList = "request-new-list";
/// <inheritdoc />
public string SavedRevisionSummary { get; set; }
/// <inheritdoc />
public string SavedSearchQuery { get; set; }
/// <inheritdoc />
public int ToggledCount { get; private set; }
/// <inheritdoc />
public int TotalCount { get; private set; }
/// <inheritdoc />
public int ConflictedCount => m_Conflicted.Count;
/// <inheritdoc />
public bool Conflicted => m_Provider.GetConflictedState();
/// <inheritdoc />
public bool Busy => m_Requests.Count != 0;
public ChangesModel(ISourceControlProvider provider)
{
m_Provider = provider;
m_Requests = new HashSet<string>();
m_AllItem = new ChangeEntryData { Entry = new ChangeEntry(string.Empty), All = true };
entryData = new Dictionary<string, IChangeEntryData>();
m_Conflicted = new List<IChangeEntryData>();
toggledEntries = new Dictionary<string, bool>();
SavedSearchQuery = string.Empty;
SavedRevisionSummary = string.Empty;
}
/// <inheritdoc />
public void OnStart()
{
// Setup events.
m_Provider.UpdatedChangeList += OnUpdatedChangeList;
m_Provider.UpdatedSelectedChangeList += OnUpdatedSelectedChangesList;
}
/// <inheritdoc />
public void OnStop()
{
// Clean up.
m_Provider.UpdatedChangeList -= OnUpdatedChangeList;
m_Provider.UpdatedSelectedChangeList -= OnUpdatedSelectedChangesList;
}
/// <inheritdoc />
public void RestoreState(IWindowCache cache)
{
// Populate data from cache.
SavedRevisionSummary = cache.RevisionSummary;
SavedSearchQuery = cache.ChangesSearchValue;
toggledEntries = cache.SimpleSelectedItems ?? new Dictionary<string, bool>();
StateChanged?.Invoke();
}
/// <inheritdoc />
public void SaveState(IWindowCache cache)
{
// Save data.
cache.RevisionSummary = SavedRevisionSummary;
cache.ChangesSearchValue = SavedSearchQuery;
cache.SimpleSelectedItems = new SelectedItemsDictionary(toggledEntries);
}
/// <summary>
/// Event handler for when the source control provider receives an updated history list.
/// </summary>
void OnUpdatedChangeList()
{
// Only one request at a time.
if (!AddRequest(k_RequestNewList)) return;
m_Provider.RequestChangeList(OnReceivedChangeList);
}
void OnUpdatedSelectedChangesList(IReadOnlyList<string> list)
{
ToggleAllEntries(false);
foreach (var path in list)
{
UpdateEntryToggle(path, true);
}
OnUpdatedSelectedChanges?.Invoke();
}
/// <summary>
/// Event handler to receive changes from the provider.
/// </summary>
/// <param name="list">Change list received.</param>
void OnReceivedChangeList([CanBeNull] IReadOnlyList<IChangeEntry> list)
{
if (list != null)
{
UpdateChangeList(list);
UpdatedChangeList?.Invoke();
}
else
{
Debug.LogError("Failed to fetch latest change list.");
}
RemoveRequest(k_RequestNewList);
}
/// <summary>
/// Convert and cache new list of changes.
/// </summary>
/// <param name="list">New list of changes.</param>
internal virtual void UpdateChangeList([NotNull] IReadOnlyList<IChangeEntry> list)
{
TotalCount = list.Count;
// Create a new set of containers.
var newEntryData = new Dictionary<string, IChangeEntryData> { [string.Empty] = m_AllItem };
var newToggledEntries = new Dictionary<string, bool>();
var conflicted = new List<IChangeEntryData>();
var all = m_AllItem.Toggled;
var toggledCount = 0;
foreach (var entry in list)
{
// Transfer toggled state from old lookup into new.
toggledEntries.TryGetValue(entry.Path, out var toggled);
toggled = toggled || all || entry.Staged;
newToggledEntries[entry.Path] = toggled;
// Create a new data item for the entry.
var item = new ChangeEntryData { Entry = entry, Toggled = toggled };
newEntryData.Add(entry.Path, item);
// Update counts.
if (toggled)
{
toggledCount++;
}
if (entry.Unmerged)
{
conflicted.Add(item);
}
}
// Store the new containers.
entryData = newEntryData;
toggledEntries = newToggledEntries;
ToggledCount = toggledCount;
m_Conflicted = conflicted;
UpdateAllItemToggle();
}
/// <inheritdoc />
public virtual bool UpdateEntryToggle(string path, bool toggled)
{
var entry = (ChangeEntryData)entryData[path];
// Toggle all items if needed.
if (entry.All)
{
return ToggleAllEntries(toggled);
}
// Update the toggled count.
if (entry.Toggled && !toggled)
{
ToggledCount--;
}
else if (!entry.Toggled && toggled)
{
ToggledCount++;
}
// Store the value in the dictionary and data item.
toggledEntries[entry.Entry.Path] = toggled;
entry.Toggled = toggled;
// Update the "All" option if needed.
return UpdateAllItemToggle();
}
/// <inheritdoc />
public IReadOnlyList<IChangeEntryData> GetToggledEntries(string query = null)
{
// Filter items by search query
query = StringUtility.TrimAndToLower(query);
return entryData.Values.Where(e => !e.All && e.Toggled && e.Entry.Path.ToLower().Contains(query)).ToList();
}
/// <inheritdoc />
public IReadOnlyList<IChangeEntryData> GetUntoggledEntries(string query = null)
{
// Filter items by search query
query = StringUtility.TrimAndToLower(query);
return entryData.Values.Where(e => !e.All && !e.Toggled && e.Entry.Path.ToLower().Contains(query)).ToList();
}
/// <inheritdoc />
public IReadOnlyList<IChangeEntryData> GetAllEntries(string query = null)
{
// Filter items by search query
query = StringUtility.TrimAndToLower(query);
return entryData.Values.Where(e => e.Entry.Path.ToLower().Contains(query)).ToList();
}
/// <inheritdoc />
public IReadOnlyList<IChangeEntryData> GetConflictedEntries(string query = null)
{
// Filter items by search query
query = StringUtility.TrimAndToLower(query);
return entryData.Values.Where(e => !e.All && e.Conflicted && e.Entry.Path.ToLower().Contains(query))
.ToList();
}
/// <summary>
/// Update the state of the "All" entry. If all entries are toggled, then "All" should be toggled too;
/// otherwise, "All" should be untoggled.
/// </summary>
/// <returns>True if the "All" entry was modified.</returns>
bool UpdateAllItemToggle()
{
// Update state of the "All" option
var allItemToggled = m_AllItem.Toggled;
if (entryData.Count == 0) return false;
if (ToggledCount == entryData.Count - 1)
{
// If every entry is toggled, then set AllItem as toggled.
toggledEntries[m_AllItem.Entry.Path] = true;
m_AllItem.Toggled = true;
return !allItemToggled;
}
// Otherwise, set AllItem as not toggled.
toggledEntries[m_AllItem.Entry.Path] = false;
m_AllItem.Toggled = false;
return allItemToggled;
}
/// <summary>
/// Toggle on or off all entries in the list.
/// </summary>
/// <param name="toggled">Whether to toggle off or on.</param>
/// <returns>True if the list has been modified.</returns>
bool ToggleAllEntries(bool toggled)
{
// Update all values in the dictionary.
toggledEntries.Keys.ToList().ForEach(x => toggledEntries[x] = toggled);
// Compute the number of toggled items (excluding the single All).
if (toggled)
{
ToggledCount = entryData.Count - 1;
}
else
{
ToggledCount = 0;
}
// Update all values in the list.
foreach (var kv in entryData)
{
((ChangeEntryData)kv.Value).Toggled = toggled;
}
return true;
}
/// <summary>
/// Add a started request.
/// </summary>
/// <param name="requestId">Id of the request to add.</param>
/// <returns>False if the request already exists.</returns>
bool AddRequest(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;
}
/// <summary>
/// Remove a finished request.
/// </summary>
/// <param name="requestId">Id of the request to remove.</param>
void RemoveRequest(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);
}
/// <inheritdoc />
public void RequestInitialData()
{
// Only one request at a time.
if (!AddRequest(k_RequestNewList)) return;
m_Provider.RequestChangeList(OnReceivedChangeList);
}
/// <inheritdoc />
public void RequestDiffChanges(string path)
{
m_Provider.RequestDiffChanges(path);
}
/// <inheritdoc />
public void RequestDiscard(IChangeEntry entry)
{
m_Provider.RequestDiscard(entry);
}
/// <inheritdoc />
public void RequestBulkDiscard(IReadOnlyList<IChangeEntry> entries)
{
m_Provider.RequestBulkDiscard(entries);
}
/// <inheritdoc />
public void RequestPublish(string message, IReadOnlyList<IChangeEntry> changes)
{
m_Provider.RequestPublish(message, changes);
}
/// <inheritdoc />
public void RequestShowConflictedDifferences(string path)
{
m_Provider.RequestShowConflictedDifferences(path);
}
/// <inheritdoc />
public void RequestChooseMerge(string path)
{
m_Provider.RequestChooseMerge(path);
}
/// <inheritdoc />
public void RequestChooseMine(string[] paths)
{
m_Provider.RequestChooseMine(paths);
}
/// <inheritdoc />
public void RequestChooseRemote(string[] paths)
{
m_Provider.RequestChooseRemote(paths);
}
/// <summary>
/// Implementation of IChangeEntryData with each field given a setter so that the data can be updated.
/// </summary>
class ChangeEntryData : IChangeEntryData
{
/// <inheritdoc />
public IChangeEntry Entry { get; set; }
/// <inheritdoc />
public bool Toggled { get; set; }
/// <inheritdoc />
public bool All { get; set; }
/// <inheritdoc />
public bool ToggleReadOnly => Entry.Staged;
/// <inheritdoc />
public bool Conflicted => Entry.Unmerged;
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: be5614f7eb757aa4cb62354fceb307db
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 08d752e03d484e968b3ec248adb23357
timeCreated: 1573260450

View file

@ -0,0 +1,14 @@
namespace Unity.Cloud.Collaborate.Models.Enums
{
internal enum ProjectStatus
{
Unbound,
Offline,
Maintenance,
LoggedOut,
NoSeat,
Bound,
Loading,
Ready
}
}

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 021989652c46434d98428c7e02cb8ab8
timeCreated: 1573260471

View file

@ -0,0 +1,219 @@
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<string> m_Requests;
const string k_RequestPage = "request-page";
const string k_RequestEntry = "request-entry";
const string k_RequestEntryNumber = "request-entry-number";
/// <inheritdoc />
public event Action HistoryListUpdated;
/// <inheritdoc />
public event Action<IReadOnlyList<IHistoryEntry>> HistoryListReceived;
/// <inheritdoc />
public event Action<IHistoryEntry> SelectedRevisionReceived;
/// <inheritdoc />
public event Action<bool> BusyStatusUpdated;
/// <inheritdoc />
public event Action<int?> EntryCountUpdated;
/// <inheritdoc />
public event Action StateChanged;
public HistoryModel([NotNull] ISourceControlProvider provider)
{
m_Provider = provider;
m_Requests = new HashSet<string>();
SelectedRevisionId = string.Empty;
SavedRevisionId = string.Empty;
}
/// <inheritdoc />
public void OnStart()
{
// Setup events
m_Provider.UpdatedHistoryEntries += OnUpdatedHistoryEntries;
}
/// <inheritdoc />
public void OnStop()
{
// Clean up.
m_Provider.UpdatedHistoryEntries -= OnUpdatedHistoryEntries;
}
/// <inheritdoc />
public void RestoreState(IWindowCache cache)
{
// Populate data.
PageNumber = cache.HistoryPageNumber;
SavedRevisionId = cache.SelectedHistoryRevision;
StateChanged?.Invoke();
}
/// <inheritdoc />
public void SaveState(IWindowCache cache)
{
// Update cache.
cache.HistoryPageNumber = PageNumber;
cache.SelectedHistoryRevision = SelectedRevisionId;
}
/// <summary>
/// Event handler for when the requested history entry count has been received.
/// </summary>
/// <param name="entryCount">Received entry count.</param>
void OnReceivedHistoryEntryCount(int? entryCount)
{
RemoveRequest(k_RequestEntryNumber);
EntryCountUpdated?.Invoke(entryCount);
}
/// <summary>
/// Event handler for when the requested page of history entries has been received.
/// </summary>
/// <param name="list">Received list of entries.</param>
void OnReceivedHistoryPage(IReadOnlyList<IHistoryEntry> list)
{
RemoveRequest(k_RequestPage);
HistoryListReceived?.Invoke(list);
}
/// <summary>
/// Event handler for when a requested single history entry has been received.
/// </summary>
/// <param name="entry">Received entry.</param>
void OnReceivedHistoryEntry(IHistoryEntry entry)
{
RemoveRequest(k_RequestEntry);
SelectedRevisionReceived?.Invoke(entry);
}
/// <summary>
/// Event handler for when the provider has received an updated history list.
/// </summary>
void OnUpdatedHistoryEntries()
{
HistoryListUpdated?.Invoke();
}
/// <inheritdoc />
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);
}
/// <inheritdoc />
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);
}
/// <inheritdoc />
public void RequestEntryNumber()
{
// Only one request at a time.
if (!AddRequest(k_RequestEntryNumber)) return;
m_Provider.RequestHistoryCount(OnReceivedHistoryEntryCount);
}
/// <inheritdoc />
public void RequestUpdateTo(string revisionId)
{
m_Provider.RequestUpdateTo(revisionId);
}
/// <inheritdoc />
public void RequestRestoreTo(string revisionId)
{
m_Provider.RequestRestoreTo(revisionId);
}
/// <inheritdoc />
public void RequestGoBackTo(string revisionId)
{
m_Provider.RequestGoBackTo(revisionId);
}
/// <inheritdoc />
public bool SupportsRevert => m_Provider.SupportsRevert;
/// <inheritdoc />
public void RequestRevert(string revisionId, IReadOnlyList<string> files)
{
m_Provider.RequestRevert(revisionId, files);
}
/// <summary>
/// Add a started request.
/// </summary>
/// <param name="requestId">Id of the request to add.</param>
/// <returns>False if the request already exists.</returns>
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;
}
/// <summary>
/// Remove a finished request.
/// </summary>
/// <param name="requestId">Id of the request to remove.</param>
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);
}
/// <inheritdoc />
public bool Busy => m_Requests.Count != 0;
/// <inheritdoc />
public int PageNumber { get; set; }
/// <inheritdoc />
public string SelectedRevisionId { get; private set; }
/// <inheritdoc />
public string SavedRevisionId { get; private set; }
/// <inheritdoc />
public bool IsRevisionSelected => !string.IsNullOrEmpty(SelectedRevisionId);
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 07b8b72b8f62e694ca3d8a35b7ca065d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,156 @@
using System;
using System.Collections.Generic;
using JetBrains.Annotations;
using Unity.Cloud.Collaborate.Models.Structures;
namespace Unity.Cloud.Collaborate.Models
{
internal interface IChangesModel : IModel
{
/// <summary>
/// Event triggered when an updated change list is available.
/// </summary>
event Action UpdatedChangeList;
/// <summary>
/// Event triggered when an updated selection of change list is available.
/// </summary>
event Action OnUpdatedSelectedChanges;
/// <summary>
/// Event triggered when the busy status changes.
/// </summary>
event Action<bool> BusyStatusUpdated;
/// <summary>
/// Stored revision summary.
/// </summary>
[NotNull]
string SavedRevisionSummary { get; set; }
/// <summary>
/// Stored search query.
/// </summary>
[NotNull]
string SavedSearchQuery { get; set; }
/// <summary>
/// Number of toggled entries.
/// </summary>
int ToggledCount { get; }
/// <summary>
/// Total number of entries.
/// </summary>
int TotalCount { get; }
/// <summary>
/// Number of conflicted entries.
/// </summary>
int ConflictedCount { get; }
/// <summary>
/// Whether or not conflicts exist.
/// </summary>
bool Conflicted { get; }
/// <summary>
/// Whether or not the model is busy with a request.
/// </summary>
bool Busy { get; }
/// <summary>
/// Request initial data to populate the change list.
/// </summary>
void RequestInitialData();
/// <summary>
/// Set the value of the toggle for the given path.
/// </summary>
/// <param name="path">Path to modify the toggle for.</param>
/// <param name="toggled">Value to set the toggle to.</param>
/// <returns>True if more than one entry has had its value change.</returns>
bool UpdateEntryToggle([NotNull] string path, bool toggled);
/// <summary>
/// Get the list of toggled entries. Can be long running in the case of a large change list.
/// </summary>
/// <param name="query">Query to filter the entries via.</param>
/// <returns>The filtered toggled list.</returns>
[NotNull]
IReadOnlyList<IChangeEntryData> GetToggledEntries([CanBeNull] string query = null);
/// <summary>
/// Get the list of untoggled entries. Can be long running in the case of a large change list.
/// </summary>
/// <param name="query">Query to filter the entries via.</param>
/// <returns>The filtered untoggled list.</returns>
[NotNull]
IReadOnlyList<IChangeEntryData> GetUntoggledEntries([CanBeNull] string query = null);
/// <summary>
/// Get full list of changes. Can be long running in the case of a large change list.
/// </summary>
/// <param name="query">Query to filter the changes with</param>
/// <returns>The filtered change list.</returns>
[NotNull]
IReadOnlyList<IChangeEntryData> GetAllEntries([CanBeNull] string query = null);
/// <summary>
/// Get the list of conflicted entries. Can be long running in the case of a large change list.
/// </summary>
/// <param name="query">Query to filter the entries via.</param>
/// <returns>The filtered conflicted list.</returns>
[NotNull]
IReadOnlyList<IChangeEntryData> GetConflictedEntries([CanBeNull] string query = null);
/// <summary>
/// Request diff of the file at the given path.
/// </summary>
/// <param name="path">Path to file to diff.</param>
void RequestDiffChanges([NotNull] string path);
/// <summary>
/// Request discard of the file at the given path.
/// </summary>
/// <param name="entry">Entry to discard.</param>
void RequestDiscard([NotNull] IChangeEntry entry);
/// <summary>
/// Request discard of the given list of files.
/// </summary>
/// <param name="entries">List of entries to discard.</param>
void RequestBulkDiscard([NotNull] IReadOnlyList<IChangeEntry> entries);
/// <summary>
/// Request publish with the given message and list of files.
/// </summary>
/// <param name="message">Message for the revision.</param>
/// <param name="changes">Changes to publish.</param>
void RequestPublish([NotNull] string message, [NotNull] IReadOnlyList<IChangeEntry> changes);
/// <summary>
/// Show the difference between both version of a conflicted file.
/// </summary>
/// <param name="path">Path of the file to show.</param>
void RequestShowConflictedDifferences([NotNull] string path);
/// <summary>
/// Request to choose merge for the provided conflict.
/// </summary>
/// <param name="path">Path of the file to choose merge for.</param>
void RequestChooseMerge([NotNull] string path);
/// <summary>
/// Request to choose mine for the provided conflict.
/// </summary>
/// <param name="paths">Paths of the files to choose mine for.</param>
void RequestChooseMine([NotNull] string[] paths);
/// <summary>
/// Request to choose remote for the provided conflict.
/// </summary>
/// <param name="paths">Paths of the files to choose remote for.</param>
void RequestChooseRemote([NotNull] string[] paths);
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: dd56ef3217ca6a64d8908f59a5213bc1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,108 @@
using System;
using System.Collections.Generic;
using JetBrains.Annotations;
using Unity.Cloud.Collaborate.Models.Structures;
namespace Unity.Cloud.Collaborate.Models
{
internal interface IHistoryModel : IModel
{
/// <summary>
/// Event triggered when the history list has been updated.
/// </summary>
event Action HistoryListUpdated;
/// <summary>
/// Event triggered when the requested page of revisions is received.
/// </summary>
event Action<IReadOnlyList<IHistoryEntry>> HistoryListReceived;
/// <summary>
/// Event triggered when the requested revision is received.
/// </summary>
event Action<IHistoryEntry> SelectedRevisionReceived;
/// <summary>
/// Event triggered when the busy status changes.
/// </summary>
event Action<bool> BusyStatusUpdated;
/// <summary>
/// Event triggered when the requested entry count is received.
/// </summary>
event Action<int?> EntryCountUpdated;
/// <summary>
/// Whether or not the model is busy with a request.
/// </summary>
bool Busy { get; }
/// <summary>
/// Current page number.
/// </summary>
int PageNumber { get; set; }
/// <summary>
/// Currently selected revision id.
/// </summary>
[NotNull]
string SelectedRevisionId { get; }
/// <summary>
/// Revision saved before domain reload.
/// </summary>
[NotNull]
string SavedRevisionId { get; }
/// <summary>
/// True if a revision is currently selected.
/// </summary>
bool IsRevisionSelected { get; }
/// <summary>
/// Request the current page of given size. Result returns via the HistoryListReceived event.
/// </summary>
/// <param name="pageSize"></param>
void RequestPageOfRevisions(int pageSize);
/// <summary>
/// Request the revision with the given id. Result returned via the SelectedRevisionReceived event.
/// </summary>
/// <param name="revisionId"></param>
void RequestSingleRevision([NotNull] string revisionId);
/// <summary>
/// Request the count of entries. Result returned via the EntryCountUpdated event.
/// </summary>
void RequestEntryNumber();
/// <summary>
/// Request to update the state of the project to a new provided revision.
/// </summary>
/// <param name="revisionId">New revision id of the project to go to.</param>
void RequestUpdateTo([NotNull] string revisionId);
/// <summary>
/// Request to take the state of the project back to the given (and current) revision.
/// </summary>
/// <param name="revisionId">Current revision id of the project to go back to.</param>
void RequestRestoreTo([NotNull] string revisionId);
/// <summary>
/// Request to take the state of the project back to the given revision, but do not change the current revision or history.
/// </summary>
/// <param name="revisionId">Revision id to go back to.</param>
void RequestGoBackTo([NotNull] string revisionId);
/// <summary>
/// Returns true if revert is supported.
/// </summary>
bool SupportsRevert { get; }
/// <summary>
/// Request to revert the specified files to the given revision.
/// </summary>
/// <param name="revisionId">Revision to revert the files back to.</param>
/// <param name="files">Files to revert back.</param>
void RequestRevert([NotNull] string revisionId, [NotNull] IReadOnlyList<string> files);
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f63e0d4f125d9e94d96937cf245e7c7b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,123 @@
using System;
using Unity.Cloud.Collaborate.Models.Structures;
using JetBrains.Annotations;
namespace Unity.Cloud.Collaborate.Models
{
internal interface IMainModel : IModel
{
/// <summary>
/// Signal when the local state switches between conflicted or not.
/// </summary>
event Action<bool> ConflictStatusChange;
/// <summary>
/// Signal when an operation with progress has started or stopped.
/// </summary>
event Action<bool> OperationStatusChange;
/// <summary>
/// Signal with incremental details of the operation in progress.
/// </summary>
event Action<IProgressInfo> OperationProgressChange;
/// <summary>
/// Signal when an error has occurred.
/// </summary>
event Action<IErrorInfo> ErrorOccurred;
/// <summary>
/// Signal when the error has cleared.
/// </summary>
event Action ErrorCleared;
/// <summary>
/// Signal whether or not the there are remote revisions to be fetched.
/// </summary>
event Action<bool> RemoteRevisionsAvailabilityChange;
/// <summary>
/// Signal when the state of the back button is updated. For example: clearing it or showing a new one.
/// The string included is the new label for the back navigation button. If that value is null, clear the back
/// navigation.
/// </summary>
event Action<string> BackButtonStateUpdated;
/// <summary>
/// Returns true if there are remote revisions available.
/// </summary>
bool RemoteRevisionsAvailable { get; }
/// <summary>
/// Returns true if there's a conflict locally.
/// </summary>
bool Conflicted { get; }
/// <summary>
/// Returns progress info if there is any.
/// </summary>
[CanBeNull]
IProgressInfo ProgressInfo { get; }
/// <summary>
/// Returns error info if there is any.
/// </summary>
[CanBeNull]
IErrorInfo ErrorInfo { get; }
/// <summary>
/// Current tab index being displayed.
/// </summary>
int CurrentTabIndex { get; set; }
/// <summary>
/// Returns a history model.
/// </summary>
/// <returns>Singleton history model for this main model.</returns>
[NotNull]
IHistoryModel ConstructHistoryModel();
/// <summary>
/// Returns a Changes model.
/// </summary>
/// <returns>Singleton change model for this main model.</returns>
[NotNull]
IChangesModel ConstructChangesModel();
/// <summary>
/// Clears any set error.
/// </summary>
void ClearError();
/// <summary>
/// Sync to latest revision.
/// </summary>
void RequestSync();
/// <summary>
/// Request cancel current job.
/// </summary>
void RequestCancelJob();
/// <summary>
/// Returns the current back navigation. Null if none exists presently.
/// </summary>
/// <returns>Current back navigation id, text, and action.</returns>
(string id, string text, Action backAction)? GetBackNavigation();
/// <summary>
/// Register back navigation to be made available to the user to navigate backwards in the UI.
/// </summary>
/// <param name="id">Id for the back event.</param>
/// <param name="text">Text for the back label.</param>
/// <param name="backAction">Action to perform to go back.</param>
void RegisterBackNavigation(string id, string text, Action backAction);
/// <summary>
/// Unregister back navigation if the given id matches the currently displayed back navigation.
/// </summary>
/// <param name="id">Id for the back event.</param>
/// <returns>True if id matched.</returns>
bool UnregisterBackNavigation(string id);
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8d9ce712c947c534e9cd0e14d6bfc4ed
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,36 @@
using System;
using JetBrains.Annotations;
using Unity.Cloud.Collaborate.UserInterface;
namespace Unity.Cloud.Collaborate.Models
{
internal interface IModel
{
/// <summary>
/// Inform the presenter that the state of the model has changed.
/// </summary>
event Action StateChanged;
/// <summary>
/// Called when the model is started and the model should setup events and fetch data.
/// </summary>
void OnStart();
/// <summary>
/// Called when the model should be stopped and data and events should closed.
/// </summary>
void OnStop();
/// <summary>
/// Restores the state of the model from the provide cache. Must be called after OnStart.
/// </summary>
/// <param name="cache">Cache to read the state from.</param>
void RestoreState([NotNull] IWindowCache cache);
/// <summary>
/// Saves the state of the model into the cache. Must be called before OnStop.
/// </summary>
/// <param name="cache">Cache to save the state into.</param>
void SaveState([NotNull] IWindowCache cache);
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 56baab22ec61f4c47a18e2225eef217a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,38 @@
using System;
using Unity.Cloud.Collaborate.Models.Enums;
namespace Unity.Cloud.Collaborate.Models
{
internal interface IStartModel : IModel
{
/// <summary>
/// Event that is triggered when the project status changes.
/// </summary>
event Action<ProjectStatus> ProjectStatusChanged;
/// <summary>
/// Returns the current project status.
/// </summary>
ProjectStatus ProjectStatus { get; }
/// <summary>
/// Request to turn on the service.
/// </summary>
void RequestTurnOnService();
/// <summary>
/// Show the service page.
/// </summary>
void ShowServicePage();
/// <summary>
/// Show login page.
/// </summary>
void ShowLoginPage();
/// <summary>
/// Show no seat page.
/// </summary>
void ShowNoSeatPage();
}
}

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 73a830e91bd5403cad57bb7b7e9a2b7f
timeCreated: 1573168727

View file

@ -0,0 +1,215 @@
using System;
using JetBrains.Annotations;
using Unity.Cloud.Collaborate.Models.Api;
using Unity.Cloud.Collaborate.Models.Structures;
using Unity.Cloud.Collaborate.UserInterface;
using UnityEngine.Assertions;
namespace Unity.Cloud.Collaborate.Models
{
internal class MainModel : IMainModel
{
[NotNull]
readonly ISourceControlProvider m_Provider;
/// <inheritdoc />
public event Action<bool> ConflictStatusChange;
/// <inheritdoc />
public event Action<bool> OperationStatusChange;
/// <inheritdoc />
public event Action<IProgressInfo> OperationProgressChange;
/// <inheritdoc />
public event Action<IErrorInfo> ErrorOccurred;
/// <inheritdoc />
public event Action ErrorCleared;
/// <inheritdoc />
public event Action<bool> RemoteRevisionsAvailabilityChange;
/// <inheritdoc />
public event Action<string> BackButtonStateUpdated;
/// <inheritdoc />
public event Action StateChanged;
[NotNull]
readonly IHistoryModel m_HistoryModel;
[NotNull]
readonly IChangesModel m_ChangesModel;
(string id, string text, Action backEvent)? m_BackNavigation;
public MainModel([NotNull] ISourceControlProvider provider)
{
m_Provider = provider;
m_HistoryModel = new HistoryModel(m_Provider);
m_ChangesModel = new ChangesModel(m_Provider);
}
/// <inheritdoc />
public void OnStart()
{
// Setup events
m_Provider.UpdatedOperationStatus += OnUpdatedOperationStatus;
m_Provider.UpdatedOperationProgress += OnUpdatedOperationProgress;
m_Provider.ErrorOccurred += OnErrorOccurred;
m_Provider.ErrorCleared += OnErrorCleared;
m_Provider.UpdatedConflictState += OnUpdatedConflictState;
m_Provider.UpdatedRemoteRevisionsAvailability += OnUpdatedRemoteRevisionsAvailability;
// Propagate event to "child" models.
m_HistoryModel.OnStart();
m_ChangesModel.OnStart();
}
/// <inheritdoc />
public void OnStop()
{
// Clean up.
m_Provider.UpdatedOperationStatus -= OnUpdatedOperationStatus;
m_Provider.UpdatedOperationProgress -= OnUpdatedOperationProgress;
m_Provider.ErrorOccurred -= OnErrorOccurred;
m_Provider.ErrorCleared -= OnErrorCleared;
m_Provider.UpdatedConflictState -= OnUpdatedConflictState;
m_Provider.UpdatedRemoteRevisionsAvailability -= OnUpdatedRemoteRevisionsAvailability;
// Propagate event to "child" models.
m_HistoryModel.OnStop();
m_ChangesModel.OnStop();
}
/// <inheritdoc />
public void RestoreState(IWindowCache cache)
{
// Read in cached data.
CurrentTabIndex = cache.TabIndex;
StateChanged?.Invoke();
// Propagate restore call to "child" models.
m_HistoryModel.RestoreState(cache);
m_ChangesModel.RestoreState(cache);
}
/// <inheritdoc />
public void SaveState(IWindowCache cache)
{
// Cache data.
cache.TabIndex = CurrentTabIndex;
// Propagate save call to "child" models.
m_HistoryModel.SaveState(cache);
m_ChangesModel.SaveState(cache);
}
/// <inheritdoc />
public bool RemoteRevisionsAvailable => m_Provider.GetRemoteRevisionAvailability();
/// <inheritdoc />
public bool Conflicted => m_Provider.GetConflictedState();
/// <inheritdoc />
public IProgressInfo ProgressInfo => m_Provider.GetProgressState();
/// <inheritdoc />
public IErrorInfo ErrorInfo => m_Provider.GetErrorState();
/// <inheritdoc />
public int CurrentTabIndex { get; set; }
/// <inheritdoc />
public IHistoryModel ConstructHistoryModel()
{
return m_HistoryModel;
}
/// <inheritdoc />
public IChangesModel ConstructChangesModel()
{
return m_ChangesModel;
}
/// <inheritdoc />
public void ClearError()
{
m_Provider.ClearError();
}
/// <inheritdoc />
public void RequestSync()
{
m_Provider.RequestSync();
}
/// <inheritdoc />
public void RequestCancelJob()
{
m_Provider.RequestCancelJob();
}
/// <inheritdoc />
public (string id, string text, Action backAction)? GetBackNavigation()
{
return m_BackNavigation;
}
/// <inheritdoc />
public void RegisterBackNavigation(string id, string text, Action backAction)
{
Assert.IsTrue(m_BackNavigation == null, "There should only be one back navigation registered at a time.");
m_BackNavigation = (id, text, backAction);
BackButtonStateUpdated?.Invoke(text);
}
/// <inheritdoc />
public bool UnregisterBackNavigation(string id)
{
if (m_BackNavigation?.id != id) return false;
m_BackNavigation = null;
BackButtonStateUpdated?.Invoke(null);
return true;
}
/// <summary>
/// Event handler for when the availability of remote revisions changes.
/// </summary>
/// <param name="available">New availability status.</param>
void OnUpdatedRemoteRevisionsAvailability(bool available)
{
RemoteRevisionsAvailabilityChange?.Invoke(available);
}
/// <summary>
/// Event handler for when the conflicted status changes.
/// </summary>
/// <param name="conflicted">New conflicted status.</param>
void OnUpdatedConflictState(bool conflicted)
{
ConflictStatusChange?.Invoke(conflicted);
}
void OnUpdatedOperationStatus(bool inProgress)
{
OperationStatusChange?.Invoke(inProgress);
}
void OnUpdatedOperationProgress(IProgressInfo progressInfo)
{
OperationProgressChange?.Invoke(progressInfo);
}
void OnErrorOccurred(IErrorInfo errorInfo)
{
ErrorOccurred?.Invoke(errorInfo);
}
void OnErrorCleared()
{
ErrorCleared?.Invoke();
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5c791e3ea7c531a479fc05e4f6f8bb84
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 5077039f5f09867409f4d38400d486b8
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d37dadfaf8b86b646ba0601379837c3c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,6 @@
# Models
In this directory, we have all of the interfaces and implementations of the Models in the package's **MVP** architecture.
In `Api/` we have the interfaces that the Models take to communicate with the backend.
In `Enums/` and `Structures/` we have the supporting data structures for the interfaces in `Api/`.
In `Providers/` we have the implementations of the interfaces in `Api/`. At this moment only `Collab.cs` exists.

View file

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 53cdcf379b41d8f439db624b6ef90749
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,81 @@
using System;
using JetBrains.Annotations;
using Unity.Cloud.Collaborate.Models.Api;
using Unity.Cloud.Collaborate.Models.Enums;
using Unity.Cloud.Collaborate.UserInterface;
using UnityEngine;
namespace Unity.Cloud.Collaborate.Models
{
internal class StartModel : IStartModel
{
[NotNull]
readonly ISourceControlProvider m_Provider;
/// <inheritdoc />
public event Action<ProjectStatus> ProjectStatusChanged;
/// <inheritdoc />
public event Action StateChanged;
public StartModel([NotNull] ISourceControlProvider provider)
{
m_Provider = provider;
}
/// <inheritdoc />
public void OnStart()
{
m_Provider.UpdatedProjectStatus += OnUpdatedProjectStatus;
}
/// <inheritdoc />
public void OnStop()
{
m_Provider.UpdatedProjectStatus -= OnUpdatedProjectStatus;
}
/// <inheritdoc />
public void RestoreState(IWindowCache cache)
{
StateChanged?.Invoke();
}
/// <inheritdoc />
public void SaveState(IWindowCache cache)
{
}
/// <inheritdoc />
public ProjectStatus ProjectStatus => m_Provider.GetProjectStatus();
/// <inheritdoc />
public void RequestTurnOnService()
{
m_Provider.RequestTurnOnService();
}
/// <inheritdoc />
public void ShowServicePage()
{
m_Provider.ShowServicePage();
}
/// <inheritdoc />
public void ShowLoginPage()
{
m_Provider.ShowLoginPage();
}
/// <inheritdoc />
public void ShowNoSeatPage()
{
m_Provider.ShowNoSeatPage();
}
void OnUpdatedProjectStatus(ProjectStatus status)
{
ProjectStatusChanged?.Invoke(status);
}
}
}

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: bc09d6ca0c1f48a98e7af0d10e1c8d16
timeCreated: 1573168761

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 17ec05e4840248f4c8392a5f54cbadbd
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,57 @@
using System;
namespace Unity.Cloud.Collaborate.Models.Structures
{
internal struct ChangeEntry : IChangeEntry
{
public ChangeEntry(string path = default, string originalPath = default, ChangeEntryStatus status = default, bool staged = default, bool unmerged = default, object tag = default)
{
Path = path;
OriginalPath = originalPath;
Status = status;
Staged = staged;
Unmerged = unmerged;
Tag = tag;
}
public string Path { get; }
public string OriginalPath { get; }
public ChangeEntryStatus Status { get; }
public bool Staged { get; }
public bool Unmerged { get; }
public object Tag { get; }
/// <inheritdoc />
public string StatusToString()
{
switch (Status)
{
case ChangeEntryStatus.Added:
case ChangeEntryStatus.Untracked:
return "added";
case ChangeEntryStatus.Modified:
case ChangeEntryStatus.TypeChange:
return "edited";
case ChangeEntryStatus.Deleted:
return "deleted";
case ChangeEntryStatus.Renamed:
case ChangeEntryStatus.Copied:
return "moved";
case ChangeEntryStatus.Unmerged:
return "conflicted";
case ChangeEntryStatus.None:
break;
case ChangeEntryStatus.Ignored:
break;
case ChangeEntryStatus.Unknown:
break;
case ChangeEntryStatus.Broken:
break;
default:
throw new ArgumentOutOfRangeException();
}
// TODO: find a way to handle/display the unexpected/broken status types.
return null;
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a06ca22308e4a294baa8076df3d577a8
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,24 @@
using System;
namespace Unity.Cloud.Collaborate.Models.Structures
{
internal struct ErrorInfo : IErrorInfo
{
public ErrorInfo(int code = default, int priority = default, int behaviour = default, string message = default, string shortMessage = default, string codeString = default)
{
Code = code;
Priority = (ErrorInfoPriority)priority;
Behaviour = (ErrorInfoBehavior)behaviour;
Message = message;
ShortMessage = shortMessage;
CodeString = codeString;
}
public int Code { get; }
public ErrorInfoPriority Priority { get; }
public ErrorInfoBehavior Behaviour { get; }
public string Message { get; }
public string ShortMessage { get; }
public string CodeString { get; }
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a733b24daacf4f74193e71f8d85f6fcc
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,40 @@
using System;
using System.Collections.Generic;
using Unity.Cloud.Collaborate.Assets;
namespace Unity.Cloud.Collaborate.Models.Structures
{
internal struct HistoryEntry : IHistoryEntry
{
public HistoryEntry(string revisionId = default, HistoryEntryStatus status = HistoryEntryStatus.Behind, string authorName = default, string message = default, DateTimeOffset time = default, IReadOnlyList<IChangeEntry> changes = default)
{
Status = status;
RevisionId = revisionId;
AuthorName = authorName;
Message = message;
Time = time;
Changes = changes;
}
public HistoryEntryStatus Status { get; }
public string RevisionId { get; }
public string AuthorName { get; }
public string Message { get; }
public DateTimeOffset Time { get; }
public IReadOnlyList<IChangeEntry> Changes { get; }
public string GetGotoText()
{
switch (Status)
{
case HistoryEntryStatus.Ahead:
return StringAssets.update;
case HistoryEntryStatus.Current:
return StringAssets.restore;
case HistoryEntryStatus.Behind:
return StringAssets.goBackTo;
default:
throw new ArgumentOutOfRangeException();
}
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 59fa6a9f6da130c4ebbd61120302fbfa
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,34 @@
namespace Unity.Cloud.Collaborate.Models.Structures
{
internal enum ChangeEntryStatus
{
None,
Untracked,
Ignored,
Modified,
Added,
Deleted,
Renamed,
Copied,
TypeChange,
Unmerged,
Unknown,
Broken
}
internal interface IChangeEntry
{
string Path { get; }
string OriginalPath { get; }
ChangeEntryStatus Status { get; }
bool Staged { get; }
bool Unmerged { get; }
object Tag { get; }
/// <summary>
/// Returns the string name of the status of this entry. Returns null if the status isn't used at present.
/// </summary>
/// <returns>String of used status. Null otherwise.</returns>
string StatusToString();
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c1548be0adf9df34f829fbde7f53bbb8
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,13 @@
using System;
namespace Unity.Cloud.Collaborate.Models.Structures
{
internal interface IChangeEntryData
{
IChangeEntry Entry { get; }
bool Toggled { get; }
bool All { get; }
bool ToggleReadOnly { get; }
bool Conflicted { get; }
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 05bce9dd4cadabf489417a9fc8f718b4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,30 @@
namespace Unity.Cloud.Collaborate.Models.Structures
{
internal interface IErrorInfo
{
int Code { get; }
ErrorInfoPriority Priority { get; }
ErrorInfoBehavior Behaviour { get; }
string Message { get; }
string ShortMessage { get; }
string CodeString { get; }
}
internal enum ErrorInfoPriority
{
Critical = 0,
Error,
Warning,
Info,
None
}
internal enum ErrorInfoBehavior
{
Alert = 0,
Automatic,
Hidden,
ConsoleOnly,
Reconnect
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 21285ef58054efb4c9264cf10346216e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,29 @@
using System;
using System.Collections.Generic;
namespace Unity.Cloud.Collaborate.Models.Structures
{
internal enum HistoryEntryStatus
{
Ahead,
Current,
Behind
}
internal interface IHistoryEntry
{
HistoryEntryStatus Status { get; }
string RevisionId { get; }
string AuthorName { get; }
string Message { get; }
DateTimeOffset Time { get; }
IReadOnlyList<IChangeEntry> Changes { get; }
string GetGotoText();
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 20c0159592ada804fbbbd1b0c38314b3
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,23 @@
namespace Unity.Cloud.Collaborate.Models.Structures
{
internal interface IProgressInfo
{
string Title { get; }
string Details { get; }
int CurrentCount { get; }
int TotalCount { get; }
string LastErrorString { get; }
ulong LastError { get; }
bool CanCancel { get; }
bool PercentageProgressType { get; }
int PercentageComplete { get; }
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d0f575ad752150f40ab16bb26ee52665
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,38 @@
using System;
namespace Unity.Cloud.Collaborate.Models.Structures
{
internal struct ProgressInfo : IProgressInfo
{
public ProgressInfo(string title = default, string details = default, int currentCount = default, int totalCount = default, string lastErrorString = default, ulong lastError = default, bool canCancel = false, bool percentageProgressType = false, int percentageComplete = default)
{
Title = title;
Details = details;
CurrentCount = currentCount;
TotalCount = totalCount;
LastErrorString = lastErrorString;
LastError = lastError;
CanCancel = canCancel;
PercentageProgressType = percentageProgressType;
PercentageComplete = percentageComplete;
}
public string Title { get; }
public string Details { get; }
public int CurrentCount { get; }
public int TotalCount { get; }
public string LastErrorString { get; }
public ulong LastError { get; }
public bool CanCancel { get; }
public bool PercentageProgressType { get; }
public int PercentageComplete { get; }
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f7de8279b79bd9143a9285439fdd6218
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: