@using RackPeek.Domain.Git
@using RackPeek.Domain.Git.UseCases
@inject InitRepoUseCase InitRepo
@inject CommitAllUseCase CommitAll
@inject RestoreAllUseCase RestoreAll
@inject PushUseCase PushUseCase
@inject PullUseCase PullUseCase
@inject AddRemoteUseCase AddRemoteUseCase
@inject IGitRepository GitRepo
@implements IDisposable
@if (_status == GitRepoStatus.NotAvailable)
{
@if (!string.IsNullOrEmpty(_branch) && _hasRemote)
{
}
@if (_status == GitRepoStatus.Clean && _hasRemote)
{
Saved
}
else if (_status == GitRepoStatus.Dirty && _hasRemote)
{
@if (_showDropdown)
{
@if (!_confirmDiscard)
{
}
else
{
Sure?
}
}
}
@if (!_hasRemote)
{
@if (_showAddRemote)
{
}
else
{
}
Connect a remote repository to enable saving and sync.
}
else
{
@if (_showSyncDropdown)
{
}
}
@if (_errorMessage is not null)
{
@_errorMessage
}
}
@code {
private GitRepoStatus _status = GitRepoStatus.NotAvailable;
private string _branch = "";
private bool _isCommitting;
private bool _isRestoring;
private bool _confirmDiscard;
private bool _showDropdown;
private bool _showAddRemote;
private bool _showSyncDropdown;
private bool _showHistory;
private bool _hasRemote;
private bool _isFetching;
private bool _isPushing;
private bool _isPulling;
private bool _isInitializing;
private bool _confirmInit;
private string? _errorMessage;
private string _remoteUrl = "";
private string _diffContent = "";
private string[] _changedFiles = [];
private GitLogEntry[] _logEntries = [];
private PeriodicTimer? _timer;
private CancellationTokenSource? _cts;
private GitSyncStatus _syncStatus = new(0,0,false);
private bool _isBusy => _isCommitting || _isRestoring || _isSyncing;
private bool _isSyncing => _isPushing || _isPulling || _isFetching;
protected override async Task OnInitializedAsync()
{
_status = GitRepo.GetStatus();
if (_status == GitRepoStatus.NotAvailable)
return;
_branch = GitRepo.GetCurrentBranch();
_hasRemote = GitRepo.HasRemote();
_cts = new CancellationTokenSource();
_timer = new PeriodicTimer(TimeSpan.FromSeconds(15));
_ = PollStatusAsync(_cts.Token);
await Task.CompletedTask;
}
private async Task PollStatusAsync(CancellationToken ct)
{
try
{
while (_timer != null && await _timer.WaitForNextTickAsync(ct))
{
if (_isBusy)
continue;
var newStatus = GitRepo.GetStatus();
if (newStatus != _status)
{
_status = newStatus;
await InvokeAsync(StateHasChanged);
}
}
}
catch (OperationCanceledException) {}
}
private async Task InitRepoAsync()
{
_errorMessage = null;
_isInitializing = true;
try
{
var error = await InitRepo.ExecuteAsync();
if (error != null)
{
_errorMessage = error;
return;
}
_status = GitRepo.GetStatus();
_branch = GitRepo.GetCurrentBranch();
_hasRemote = GitRepo.HasRemote();
}
catch (Exception ex)
{
_errorMessage = $"Init error: {ex.Message}";
}
finally
{
_isInitializing = false;
}
}
private void CancelAddRemote()
{
_showAddRemote = false;
_remoteUrl = "";
}
private async Task AddRemoteAsync()
{
_errorMessage = null;
try
{
var error = await AddRemoteUseCase.ExecuteAsync(_remoteUrl);
if (error != null)
{
_errorMessage = error;
return;
}
_hasRemote = true;
_showAddRemote = false;
_remoteUrl = "";
_syncStatus = GitRepo.FetchAndGetSyncStatus();
if (_syncStatus.Behind > 0)
await PullAsync();
}
catch (Exception ex)
{
_errorMessage = $"Remote error: {ex.Message}";
}
}
private async Task CommitAsync()
{
if (!_hasRemote)
{
_errorMessage = "Add a remote repository before saving.";
return;
}
_errorMessage = null;
_isCommitting = true;
try
{
var error = await CommitAll.ExecuteAsync(
$"rackpeek: save config {DateTime.UtcNow:yyyy-MM-dd HH:mm:ss} UTC");
if (error != null)
_errorMessage = error;
_status = GitRepo.GetStatus();
}
catch (Exception ex)
{
_errorMessage = $"Commit error: {ex.Message}";
}
finally
{
_isCommitting = false;
}
}
private void ToggleDropdown()
{
_showDropdown = !_showDropdown;
_showSyncDropdown = false;
}
private void ToggleSyncAsync()
{
_showSyncDropdown = !_showSyncDropdown;
_showDropdown = false;
if (_showSyncDropdown)
{
_isFetching = true;
try
{
_syncStatus = GitRepo.FetchAndGetSyncStatus();
}
finally
{
_isFetching = false;
}
}
}
private async Task PushAsync()
{
if (!_hasRemote)
{
_errorMessage = "Add a remote first.";
return;
}
_errorMessage = null;
_isPushing = true;
try
{
var error = await PushUseCase.ExecuteAsync();
if (error != null)
_errorMessage = error;
_syncStatus = GitRepo.FetchAndGetSyncStatus();
}
catch (Exception ex)
{
_errorMessage = $"Push error: {ex.Message}";
}
finally
{
_isPushing = false;
}
}
private async Task PullAsync()
{
_errorMessage = null;
_isPulling = true;
try
{
var error = await PullUseCase.ExecuteAsync();
if (error != null)
_errorMessage = error;
_syncStatus = GitRepo.FetchAndGetSyncStatus();
_status = GitRepo.GetStatus();
}
catch (Exception ex)
{
_errorMessage = $"Pull error: {ex.Message}";
}
finally
{
_isPulling = false;
}
}
public void Dispose()
{
_cts?.Cancel();
_cts?.Dispose();
_timer?.Dispose();
}
private void OpenDiffAsync()
{
_showDropdown = false;
try
{
_changedFiles = GitRepo.GetChangedFiles();
_diffContent = GitRepo.GetDiff();
}
catch (Exception ex)
{
_errorMessage = $"Diff error: {ex.Message}";
}
}
private async Task DiscardAsync()
{
_errorMessage = null;
_isRestoring = true;
_confirmDiscard = false;
_showDropdown = false;
try
{
var error = await RestoreAll.ExecuteAsync();
if (error != null)
_errorMessage = error;
_status = GitRepo.GetStatus();
}
catch (Exception ex)
{
_errorMessage = $"Discard error: {ex.Message}";
}
finally
{
_isRestoring = false;
}
}
private void ToggleHistoryAsync()
{
if (_showHistory)
{
_showHistory = false;
return;
}
try
{
_logEntries = GitRepo.GetLog(20);
_showHistory = true;
}
catch (Exception ex)
{
_errorMessage = $"History error: {ex.Message}";
}
}
}