diff --git a/.idea/.idea.Flawless-Version-Control/.idea/MarsCodeWorkspaceAppSettings.xml b/.idea/.idea.Flawless-Version-Control/.idea/MarsCodeWorkspaceAppSettings.xml new file mode 100644 index 0000000..05ed8ba --- /dev/null +++ b/.idea/.idea.Flawless-Version-Control/.idea/MarsCodeWorkspaceAppSettings.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/.idea.Flawless-Version-Control/.idea/avalonia.xml b/.idea/.idea.Flawless-Version-Control/.idea/avalonia.xml index 293ee92..ba59aa9 100644 --- a/.idea/.idea.Flawless-Version-Control/.idea/avalonia.xml +++ b/.idea/.idea.Flawless-Version-Control/.idea/avalonia.xml @@ -12,6 +12,7 @@ + @@ -19,9 +20,11 @@ + + diff --git a/Flawless.Client/Service/RepositoryService.cs b/Flawless.Client/Service/RepositoryService.cs index a570fe9..61adb88 100644 --- a/Flawless.Client/Service/RepositoryService.cs +++ b/Flawless.Client/Service/RepositoryService.cs @@ -473,7 +473,7 @@ public class RepositoryService : BaseService } } - public async ValueTask CloseIssueAsync(RepositoryModel repo, long issueId) + public async ValueTask CloseIssueAsync(RepositoryModel repo, ulong issueId) { var api = Api.C; try @@ -484,7 +484,7 @@ public class RepositoryService : BaseService return false; } - await api.Gateway.Close(repo.OwnerName, repo.Name, issueId); + await api.Gateway.Close(repo.OwnerName, repo.Name, (long) issueId); return true; } catch (Exception e) @@ -495,7 +495,7 @@ public class RepositoryService : BaseService } } - public async ValueTask ReopenIssueAsync(RepositoryModel repo, long issueId) + public async ValueTask ReopenIssueAsync(RepositoryModel repo, ulong issueId) { var api = Api.C; try @@ -506,7 +506,7 @@ public class RepositoryService : BaseService return false; } - await api.Gateway.Reopen(repo.OwnerName, repo.Name, issueId); + await api.Gateway.Reopen(repo.OwnerName, repo.Name, (long) issueId); return true; } catch (Exception e) diff --git a/Flawless.Client/ViewModels/IssueDetailViewModel.cs b/Flawless.Client/ViewModels/IssueDetailViewModel.cs new file mode 100644 index 0000000..d4bfac6 --- /dev/null +++ b/Flawless.Client/ViewModels/IssueDetailViewModel.cs @@ -0,0 +1,91 @@ +using System.Linq; +using System.Reactive.Threading.Tasks; +using System.Threading.Tasks; +using Flawless.Client; +using Flawless.Client.Models; +using ReactiveUI; +using Flawless.Client.Service; +using Flawless.Client.ViewModels; +using ReactiveUI.SourceGenerators; + +public partial class IssueDetailViewModel : RoutableViewModelBase +{ + [Reactive] private RepositoryModel.Issue? _currentIssue; + + [Reactive] private string _newComment; + + [Reactive] private RepositoryModel.Comment? _replyTo; + + private readonly RepositoryService _service; + + private readonly RepositoryModel _repo; + + public IssueDetailViewModel(IScreen screen, RepositoryModel repo, ulong issueId) : base(screen) + { + _repo = repo; + _service = RepositoryService.Current; + LoadDataAsync(repo, issueId); + } + + private async Task LoadDataAsync(RepositoryModel repo, ulong issueId) + { + using var _ = UIHelper.MakeLoading("Fetching comments from server..."); + if (!await _service.UpdateIssueDetailsFromServerAsync(repo, issueId)) + { + await NavigateBackAsync(); + UIHelper.NotifyError("Operation failed", "Can not open issue..."); + return; + } + + CurrentIssue = repo.Issues.First(x => x.Id == issueId); + } + + [ReactiveCommand] + private Task RefreshIssueAsync() => LoadDataAsync(_repo, CurrentIssue!.Id); + + [ReactiveCommand] + private async Task ToggleIssueStatusAsync() + { + if (CurrentIssue == null) return; + + using var _ = UIHelper.MakeLoading("Update issue..."); + if (CurrentIssue.Closed) + { + if (!await _service.ReopenIssueAsync(_repo, CurrentIssue.Id)) return; + + } + else + { + if (!await _service.CloseIssueAsync(_repo, CurrentIssue.Id)) return; + } + + CurrentIssue.Closed = !CurrentIssue.Closed; + } + + [ReactiveCommand] + private async Task AddCommentAsync() + { + if (CurrentIssue == null) return; + + using var _ = UIHelper.MakeLoading("Update issue..."); + if (string.IsNullOrWhiteSpace(NewComment)) + { + UIHelper.NotifyError("No input", "No comment has been written!"); + } + else + { + if (!await _service.AddCommentAsync(_repo, CurrentIssue.Id, NewComment, _replyTo?.Id ?? null)) return; + + _replyTo = null; + NewComment = string.Empty; + } + } + + [ReactiveCommand] + private async Task EditIssueAsync() + { + } + + [ReactiveCommand] + private Task NavigateBackAsync() => HostScreen.Router.NavigateBack.Execute().ToTask(); +} \ No newline at end of file diff --git a/Flawless.Client/ViewModels/ModalBox/IssueEditDialogViewModel.cs b/Flawless.Client/ViewModels/ModalBox/IssueEditDialogViewModel.cs new file mode 100644 index 0000000..65ea355 --- /dev/null +++ b/Flawless.Client/ViewModels/ModalBox/IssueEditDialogViewModel.cs @@ -0,0 +1,29 @@ +using System.Collections.Generic; +using System.Text; +using Flawless.Client.Models; +using ReactiveUI; +using ReactiveUI.SourceGenerators; + +namespace Flawless.Client.ViewModels.ModalBox; + +public partial class IssueEditDialogViewModel : ReactiveObject +{ + [Reactive] public string Title { get; set; } = string.Empty; + [Reactive] public string Description { get; set; } = string.Empty; + [Reactive] public string? Tag { get; set; } + + public bool IsEditMode { get; } + + public List AvailableTags { get; } = new() { "bug", "feature", "question" }; + + public IssueEditDialogViewModel(RepositoryModel.Issue? existingIssue = null) + { + IsEditMode = existingIssue != null; + if (IsEditMode) + { + Title = existingIssue!.Title; + Description = existingIssue.Description ?? string.Empty; + Tag = new StringBuilder().AppendJoin(',', existingIssue.Tags).ToString(); + } + } +} \ No newline at end of file diff --git a/Flawless.Client/ViewModels/RepositoryViewModel.cs b/Flawless.Client/ViewModels/RepositoryViewModel.cs index 4c31d8f..4b34584 100644 --- a/Flawless.Client/ViewModels/RepositoryViewModel.cs +++ b/Flawless.Client/ViewModels/RepositoryViewModel.cs @@ -400,8 +400,7 @@ public partial class RepositoryViewModel : RoutableViewModelBase if (!await RepositoryService.C.UpdateCommitsHistoryFromServerAsync(Repository)) return; var changes = new List(); CollectChanges(changes, LocalChangeSetRaw); - - + var result = await UIHelper.SimpleAskAsync( "All files will being matched with this commit. Do you wish to execute it?", DialogMode.Warning); @@ -419,7 +418,30 @@ public partial class RepositoryViewModel : RoutableViewModelBase SyncCommitsFromRepository(); } } + + [ReactiveCommand] + private async Task CreateIssueAsync() + { + + } + + [ReactiveCommand] + private async Task OpenIssueAsync() + { + + } + + [ReactiveCommand] + private async Task CloseIssueAsync() + { + + } + [ReactiveCommand] + private async Task ReopenIssueAsync() + { + + } [ReactiveCommand] private async Task PullLatestRepositoryAsync() diff --git a/Flawless.Client/Views/IssueDetailView.axaml b/Flawless.Client/Views/IssueDetailView.axaml new file mode 100644 index 0000000..0c098b1 --- /dev/null +++ b/Flawless.Client/Views/IssueDetailView.axaml @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Flawless.Client/Views/ModalBox/IssueEditDialogView.axaml b/Flawless.Client/Views/ModalBox/IssueEditDialogView.axaml new file mode 100644 index 0000000..463bb25 --- /dev/null +++ b/Flawless.Client/Views/ModalBox/IssueEditDialogView.axaml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Flawless.Client/Views/RepositoryPage/RepoIssuePageView.axaml b/Flawless.Client/Views/RepositoryPage/RepoIssuePageView.axaml index adaa6be..de50354 100644 --- a/Flawless.Client/Views/RepositoryPage/RepoIssuePageView.axaml +++ b/Flawless.Client/Views/RepositoryPage/RepoIssuePageView.axaml @@ -3,10 +3,68 @@ xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:vm="using:Flawless.Client.ViewModels" + xmlns:u="https://irihi.tech/ursa" x:DataType="vm:RepositoryViewModel" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" x:Class="Flawless.Client.Views.RepositoryPage.RepoIssuePageView"> - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +