about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRory& <root@rory.gay>2024-04-25 06:31:52 +0200
committerRory& <root@rory.gay>2024-04-25 06:31:52 +0200
commit3054b456dcb54f069a5d8aaa615c1dfe060eef9b (patch)
treece89fbd1478206ac19fefa23035b68801bd25d4e
parentAdd basic project management (diff)
downloadBugMine-3054b456dcb54f069a5d8aaa615c1dfe060eef9b.tar.xz
Add projects logic, start of issues
-rw-r--r--BugMine.DevTools.CLI/BugMine.DevTools.CLI.csproj17
-rw-r--r--BugMine.DevTools.CLI/Program.cs9
-rw-r--r--BugMine.DevTools.CLI/Properties/launchSettings.json12
-rw-r--r--BugMine.DevTools.CLI/Worker.cs123
-rw-r--r--BugMine.DevTools.CLI/appsettings.Development.json8
-rw-r--r--BugMine.DevTools.CLI/appsettings.json8
-rw-r--r--BugMine.DevTools.CLI/auth.json6
-rw-r--r--BugMine.Sdk/BugMineClient.cs54
-rw-r--r--BugMine.Sdk/BugMineProject.cs16
-rw-r--r--BugMine.Sdk/Events/State/BugMineRoomMetadata.cs11
-rw-r--r--BugMine.Sdk/Exceptions/BugMineException.cs23
-rw-r--r--BugMine.Web/Classes/BugMineStorage.cs4
-rw-r--r--BugMine.Web/Components/IssueImportWorker.razor2
-rw-r--r--BugMine.Web/Pages/Auth/LegacyLogin.razor2
-rw-r--r--BugMine.Web/Pages/Auth/Login.razor1
-rw-r--r--BugMine.Web/Pages/DevTools.razor12
-rw-r--r--BugMine.Web/Pages/Projects/Index.razor17
-rw-r--r--BugMine.Web/Pages/Projects/ViewProject.razor95
-rw-r--r--BugMine.sln6
m---------LibMatrix0
20 files changed, 387 insertions, 39 deletions
diff --git a/BugMine.DevTools.CLI/BugMine.DevTools.CLI.csproj b/BugMine.DevTools.CLI/BugMine.DevTools.CLI.csproj
new file mode 100644

index 0000000..f07ebda --- /dev/null +++ b/BugMine.DevTools.CLI/BugMine.DevTools.CLI.csproj
@@ -0,0 +1,17 @@ +<Project Sdk="Microsoft.NET.Sdk.Worker"> + + <PropertyGroup> + <TargetFramework>net8.0</TargetFramework> + <Nullable>enable</Nullable> + <ImplicitUsings>enable</ImplicitUsings> + <UserSecretsId>dotnet-BugMine.DevTools.CLI-68C1536A-FE5E-4724-8406-B1B1430F105A</UserSecretsId> + </PropertyGroup> + + <ItemGroup> + <PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0"/> + </ItemGroup> + + <ItemGroup> + <ProjectReference Include="..\BugMine.Sdk\BugMine.Sdk.csproj" /> + </ItemGroup> +</Project> diff --git a/BugMine.DevTools.CLI/Program.cs b/BugMine.DevTools.CLI/Program.cs new file mode 100644
index 0000000..6e5bead --- /dev/null +++ b/BugMine.DevTools.CLI/Program.cs
@@ -0,0 +1,9 @@ +using BugMine.DevTools.CLI; +using BugMine.Web.Classes; + +var builder = Host.CreateApplicationBuilder(args); +builder.Services.AddBugMine(new() { AppName = "BugMine DevTools CLI" }); +builder.Services.AddHostedService<Worker>(); + +var host = builder.Build(); +host.Run(); \ No newline at end of file diff --git a/BugMine.DevTools.CLI/Properties/launchSettings.json b/BugMine.DevTools.CLI/Properties/launchSettings.json new file mode 100644
index 0000000..43460c6 --- /dev/null +++ b/BugMine.DevTools.CLI/Properties/launchSettings.json
@@ -0,0 +1,12 @@ +{ + "$schema": "http://json.schemastore.org/launchsettings.json", + "profiles": { + "BugMine.DevTools.CLI": { + "commandName": "Project", + "dotnetRunMessages": true, + "environmentVariables": { + "DOTNET_ENVIRONMENT": "Development" + } + } + } +} diff --git a/BugMine.DevTools.CLI/Worker.cs b/BugMine.DevTools.CLI/Worker.cs new file mode 100644
index 0000000..8cd931e --- /dev/null +++ b/BugMine.DevTools.CLI/Worker.cs
@@ -0,0 +1,123 @@ +using System.Text.Json; +using ArcaneLibs.Extensions; +using BugMine.Web.Classes; +using LibMatrix.EventTypes.Spec.State; +using LibMatrix.Responses; +using LibMatrix.Services; + +namespace BugMine.DevTools.CLI; + +public class Worker(ILogger<Worker> logger, HomeserverProviderService hsProvider) : BackgroundService { + private readonly ILogger<Worker> _logger = logger; + private BugMineClient? Client { get; set; } + + protected override async Task ExecuteAsync(CancellationToken stoppingToken) { + if (!File.Exists("auth.json")) { + Console.Write("Homeserver: "); + var homeserver = Console.ReadLine()!; + Console.Write("Username: "); + var username = Console.ReadLine()!; + Console.Write("Password: "); + var password = Console.ReadLine()!; + + var login = await hsProvider.Login(homeserver, username, password); + await File.WriteAllTextAsync("auth.json", login.ToJson(), stoppingToken); + } + + var auth = await JsonSerializer.DeserializeAsync<LoginResponse>(File.OpenRead("auth.json")); + Client = new BugMineClient(await hsProvider.GetAuthenticatedWithToken(auth.Homeserver, auth.AccessToken, useGeneric: true)); + + while (!stoppingToken.IsCancellationRequested) { + Console.WriteLine(""" + 1) List all projects + 2) Create 500 projects + 3) Destroy all projects + 4) Get room count + """); + + var input = Console.ReadKey(); + Console.WriteLine(); + switch (input.Key) { + case ConsoleKey.D1: { + if (Client is null) { + _logger.LogError("No client available."); + break; + } + + var projects = Client.GetProjects(); + await foreach (var project in projects) { + Console.WriteLine(project.ToJson(indent: false)); + } + + break; + } + case ConsoleKey.D2: { + if (Client is null) { + _logger.LogError("No client available."); + break; + } + + await MassCreateProjects(); + break; + } + case ConsoleKey.D3: { + if (Client is null) { + _logger.LogError("No client available."); + break; + } + + await DestroyAllProjects(); + break; + } + case ConsoleKey.D4: { + if (Client is null) { + _logger.LogError("No client available."); + break; + } + + var rooms = await Client.Homeserver.GetJoinedRooms(); + Console.WriteLine(rooms.Count()); + break; + } + } + } + } + + private async Task DestroyAllProjects() { + var ss = new SemaphoreSlim(4, 4); + await foreach (var proj in Client.Homeserver.GetJoinedRoomsByType(null!)) { + if (proj.RoomId == "!UktPWOzit8gmms5FQ6:conduit.matrixunittests.rory.gay") continue; + Task.Run(async () => { + // await ss.WaitAsync(); + await proj.SendStateEventAsync(RoomNameEventContent.EventId, new RoomNameEventContent() { + Name = "Disbanded BugMine project." + }); + await proj.SendStateEventAsync(RoomJoinRulesEventContent.EventId, new RoomJoinRulesEventContent() { + JoinRule = RoomJoinRulesEventContent.JoinRules.Private + }); + await proj.SendStateEventAsync(RoomCanonicalAliasEventContent.EventId, new RoomCanonicalAliasEventContent() { + Alias = null + }); + await proj.LeaveAsync("Disbanded room."); + // ss.Release(); + }); + } + } + + private async Task MassCreateProjects() { + // var rooms = await Client.Homeserver.GetJoinedRooms(); + // List<string> roomNames = (await Task.WhenAll(rooms.Select(x => x.GetNameAsync()))).Where(x => x != null).ToList(); + for (int i = 0; i < 500; i++) { + Task.Run(async () => { + // var randomName = roomNames[Random.Shared.Next(roomNames.Count)]; + var proj = await Client.CreateProject(new() { + Name = /*randomName + */Guid.NewGuid().ToString()[..8] + }); + + // await proj.CreateIssue(new() { + // Name = "meow" + // }); + }); + } + } +} \ No newline at end of file diff --git a/BugMine.DevTools.CLI/appsettings.Development.json b/BugMine.DevTools.CLI/appsettings.Development.json new file mode 100644
index 0000000..b2dcdb6 --- /dev/null +++ b/BugMine.DevTools.CLI/appsettings.Development.json
@@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.Hosting.Lifetime": "Information" + } + } +} diff --git a/BugMine.DevTools.CLI/appsettings.json b/BugMine.DevTools.CLI/appsettings.json new file mode 100644
index 0000000..b2dcdb6 --- /dev/null +++ b/BugMine.DevTools.CLI/appsettings.json
@@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.Hosting.Lifetime": "Information" + } + } +} diff --git a/BugMine.DevTools.CLI/auth.json b/BugMine.DevTools.CLI/auth.json new file mode 100644
index 0000000..e42970e --- /dev/null +++ b/BugMine.DevTools.CLI/auth.json
@@ -0,0 +1,6 @@ +{ + "access_token": "wODFOcoMnoruFaUGrjWibY80sVVEqSUg", + "device_id": "VHX31Cw6jz", + "home_server": "conduit.matrixunittests.rory.gay", + "user_id": "@meow:conduit.matrixunittests.rory.gay" +} \ No newline at end of file diff --git a/BugMine.Sdk/BugMineClient.cs b/BugMine.Sdk/BugMineClient.cs
index be80c3a..db47b85 100644 --- a/BugMine.Sdk/BugMineClient.cs +++ b/BugMine.Sdk/BugMineClient.cs
@@ -1,15 +1,18 @@ using System.Text.RegularExpressions; using ArcaneLibs.Extensions; +using BugMine.Web.Classes.Exceptions; +using LibMatrix; using LibMatrix.Homeservers; using LibMatrix.Responses; +using LibMatrix.RoomTypes; namespace BugMine.Web.Classes; public class BugMineClient(AuthenticatedHomeserverGeneric homeserver) { public AuthenticatedHomeserverGeneric Homeserver { get; } = homeserver; - + public async IAsyncEnumerable<BugMineProject> GetProjects() { - List<Task<BugMineProject>> tasks = []; + List<Task<BugMineProject>> tasks = []; await foreach (var room in homeserver.GetJoinedRoomsByType(BugMineProject.RoomType)) { tasks.Add(room.AsBugMineProject()); } @@ -21,35 +24,58 @@ public class BugMineClient(AuthenticatedHomeserverGeneric homeserver) { } public async Task<BugMineProject> CreateProject(ProjectInfo request) { - var alias = string.Join('_', Regex.Matches(request.Name, @"[a-zA-Z0-9]+").Select(x => x.Value))+"-bugmine"; - + var alias = string.Join('_', Regex.Matches(request.Name, @"[a-zA-Z0-9]+").Select(x => x.Value)) + "-bugmine"; + var crr = new CreateRoomRequest() { CreationContent = new() { ["type"] = "gay.rory.bugmine.project" }, Name = $"{request.Name} (BugMine project)", - RoomAliasName = alias + RoomAliasName = alias, + InitialState = [ + new StateEvent() { + Type = "m.room.join_rules", + RawContent = new() { + ["join_rule"] = "public" + } + }, + new StateEvent() { + Type = ProjectInfo.EventId, + TypedContent = request + } + ] }; - + var response = await Homeserver.CreateRoom(crr); - await response.SendStateEventAsync(ProjectInfo.EventId, request); - + // await response.SendStateEventAsync(ProjectInfo.EventId, request); + return await response.AsBugMineProject(); } public async Task<BugMineProject?> GetProject(string projectSlug) { - if (projectSlug.StartsWith('!')) { - var room = homeserver.GetRoom(projectSlug); - if (room == null) return null; + var room = await ResolveProjectSlug(projectSlug); + + if (room == null) return null; - return await (await room.AsBugMineProject()).InitializeAsync(); + var rooms = await Homeserver.GetJoinedRooms(); + if (!rooms.Any(r => r.RoomId == room.RoomId)) throw new BugMineException(BugMineException.ErrorCodes.UserNotInRoom); + + return await (await room.AsBugMineProject()).InitializeAsync(); + } + + public async Task<GenericRoom?> ResolveProjectSlug(string projectSlug) { + GenericRoom? room; + if (projectSlug.StartsWith('!')) { + room = homeserver.GetRoom(projectSlug); } else { var alias = $"#{projectSlug}"; var resolveResult = await Homeserver.ResolveRoomAliasAsync(alias); if (string.IsNullOrEmpty(resolveResult?.RoomId)) return null; //TODO: fallback to finding via joined rooms' canonical alias event? - - return await (await homeserver.GetRoom(resolveResult.RoomId).AsBugMineProject()).InitializeAsync(); + + room = homeserver.GetRoom(resolveResult.RoomId); } + + return room; } } \ No newline at end of file diff --git a/BugMine.Sdk/BugMineProject.cs b/BugMine.Sdk/BugMineProject.cs
index c90ba6e..babb680 100644 --- a/BugMine.Sdk/BugMineProject.cs +++ b/BugMine.Sdk/BugMineProject.cs
@@ -1,4 +1,5 @@ using System.Text.Json.Nodes; +using LibMatrix.EventTypes.Spec.State; using LibMatrix.Homeservers; using LibMatrix.RoomTypes; @@ -13,27 +14,34 @@ public class BugMineProject(GenericRoom room) { public async Task<BugMineProject> InitializeAsync() { Info = (await Room.GetStateAsync<ProjectInfo>(ProjectInfo.EventId))!; var alias = await room.GetCanonicalAliasAsync(); - + if (alias != null) ProjectSlug = alias.Alias?[1..] ?? room.RoomId; else ProjectSlug = room.RoomId; - + return this; } public async Task<BugMineIssue> CreateIssue(BugMineIssueData issue) { // add relation to room creation event issue.RelatesTo = new() { - EventId = (await Room.GetStateEventAsync("m.room.create")).EventId, + EventId = await room.GetStateEventIdAsync(RoomCreateEventContent.EventId), RelationType = "gay.rory.bugmine.issue" }; var eventId = await Room.SendTimelineEventAsync(BugMineIssueData.EventId, issue); - + // return new BugMineIssueAccessor(Room, await Room.GetEventAsync<>(eventId)); var evt = await room.GetEventAsync(eventId.EventId); Console.WriteLine(evt); return new BugMineIssue(Room, evt); } + + public async IAsyncEnumerable<BugMineIssue> GetIssues() { + var creationEventId = await room.GetStateEventIdAsync(RoomCreateEventContent.EventId); + await foreach (var evt in room.GetRelatedEventsAsync(creationEventId, "gay.rory.bugmine.issue", BugMineIssueData.EventId)) { + yield return new BugMineIssue(Room, evt); + } + } } public static class ProjectRoomExtensions { diff --git a/BugMine.Sdk/Events/State/BugMineRoomMetadata.cs b/BugMine.Sdk/Events/State/BugMineRoomMetadata.cs new file mode 100644
index 0000000..a6686d3 --- /dev/null +++ b/BugMine.Sdk/Events/State/BugMineRoomMetadata.cs
@@ -0,0 +1,11 @@ +using LibMatrix.EventTypes; + +namespace BugMine.Web.Classes; + +[MatrixEvent(EventName = EventId)] +public class BugMineRoomMetadata : EventContent { + public const string EventId = "gay.rory.bugmine.room_metadata"; + + public string RoomCreationEventId { get; set; } + +} \ No newline at end of file diff --git a/BugMine.Sdk/Exceptions/BugMineException.cs b/BugMine.Sdk/Exceptions/BugMineException.cs new file mode 100644
index 0000000..7e843b3 --- /dev/null +++ b/BugMine.Sdk/Exceptions/BugMineException.cs
@@ -0,0 +1,23 @@ +using System.Diagnostics.CodeAnalysis; +using LibMatrix; + +namespace BugMine.Web.Classes.Exceptions; + +public class BugMineException : MatrixException { + [SetsRequiredMembers] + public BugMineException(string errorCode, string? message = null) { + ErrorCode = errorCode; + Error = message ?? Message; + } + + public sealed override string Message => + $"{ErrorCode}: {ErrorCode switch { + // common + ErrorCodes.UserNotInRoom => "User is not in the room", + _ => base.Message + }}"; + + public new static class ErrorCodes { + public const string UserNotInRoom = "BUGMINE_USER_NOT_IN_ROOM"; + } +} \ No newline at end of file diff --git a/BugMine.Web/Classes/BugMineStorage.cs b/BugMine.Web/Classes/BugMineStorage.cs
index 73b46b5..3c838c7 100644 --- a/BugMine.Web/Classes/BugMineStorage.cs +++ b/BugMine.Web/Classes/BugMineStorage.cs
@@ -74,7 +74,7 @@ public class BugMineStorage( return session; } - public async Task<BugMineClient?> GetCurrentSessionOrNull() { + public async Task<BugMineClient?> GetCurrentSessionOrNull(bool navigateOnInvalid = true) { BugMineClient? session = null; try { @@ -85,7 +85,7 @@ public class BugMineStorage( if (e.ErrorCode == "M_UNKNOWN_TOKEN") { var token = await GetCurrentToken(); logger.LogWarning("Encountered invalid token for {user} on {homeserver}", token.UserId, token.Homeserver); - navigationManager.NavigateTo("/InvalidSession?ctx=" + token.AccessToken); + if (navigateOnInvalid) navigationManager.NavigateTo("/InvalidSession?ctx=" + token.AccessToken); return null; } diff --git a/BugMine.Web/Components/IssueImportWorker.razor b/BugMine.Web/Components/IssueImportWorker.razor
index bc72156..b53daf7 100644 --- a/BugMine.Web/Components/IssueImportWorker.razor +++ b/BugMine.Web/Components/IssueImportWorker.razor
@@ -15,7 +15,7 @@ private string Status { get; set; } = ""; protected override async Task OnInitializedAsync() { while(Client == null) { - Client = await BugMineStorage.GetCurrentSessionOrNull(); + Client = await BugMineStorage.GetCurrentSessionOrNull(false); if(Client == null) { await Task.Delay(1000); } diff --git a/BugMine.Web/Pages/Auth/LegacyLogin.razor b/BugMine.Web/Pages/Auth/LegacyLogin.razor
index 5257028..eec381a 100644 --- a/BugMine.Web/Pages/Auth/LegacyLogin.razor +++ b/BugMine.Web/Pages/Auth/LegacyLogin.razor
@@ -23,7 +23,7 @@ <br/> <LinkButton OnClick="@(() => LoginWithAuth(authData))">Log in</LinkButton> -<h4>Continue as guest</h4> +<h4>Continue as guest (doesn't work)</h4> <hr/> <LinkButton OnClick="@(() => LoginWithAuth(new LoginStruct { Homeserver = "matrix.org", Username = "guest", Password = "guest" }))">Log in as guest</LinkButton> diff --git a/BugMine.Web/Pages/Auth/Login.razor b/BugMine.Web/Pages/Auth/Login.razor
index 7b457ec..bea449e 100644 --- a/BugMine.Web/Pages/Auth/Login.razor +++ b/BugMine.Web/Pages/Auth/Login.razor
@@ -61,7 +61,6 @@ Homeserver = await hsProvider.GetRemoteHomeserver(HomeserverName); CurrentStage = await Homeserver.Auth.GetAvailableFlowsAsync(enableRegister: true, enableGuest: true); - StateHasChanged(); } diff --git a/BugMine.Web/Pages/DevTools.razor b/BugMine.Web/Pages/DevTools.razor
index f8fc408..afed0cc 100644 --- a/BugMine.Web/Pages/DevTools.razor +++ b/BugMine.Web/Pages/DevTools.razor
@@ -15,10 +15,10 @@ } private async Task DestroyAllProjects() { - var ss = new SemaphoreSlim(16, 16); + var ss = new SemaphoreSlim(4, 4); await foreach (var proj in Client.Homeserver.GetJoinedRoomsByType(BugMineProject.RoomType)) { - Task.Run(async () => { - await ss.WaitAsync(); + // Task.Run(async () => { + // await ss.WaitAsync(); await proj.SendStateEventAsync(RoomNameEventContent.EventId, new RoomNameEventContent() { Name = "Disbanded BugMine project." }); @@ -29,15 +29,15 @@ Alias = null }); await proj.LeaveAsync("Disbanded room."); - ss.Release(); - }); + // ss.Release(); + // }); } } private async Task MassCreateProjects() { // var rooms = await Client.Homeserver.GetJoinedRooms(); // List<string> roomNames = (await Task.WhenAll(rooms.Select(x => x.GetNameAsync()))).Where(x => x != null).ToList(); - for (int i = 0; i < 5; i++) { + for (int i = 0; i < 20; i++) { Task.Run(async () => { // var randomName = roomNames[Random.Shared.Next(roomNames.Count)]; var proj = await Client.CreateProject(new() { diff --git a/BugMine.Web/Pages/Projects/Index.razor b/BugMine.Web/Pages/Projects/Index.razor
index eaf8dc1..47c2f4a 100644 --- a/BugMine.Web/Pages/Projects/Index.razor +++ b/BugMine.Web/Pages/Projects/Index.razor
@@ -2,7 +2,13 @@ @using LibMatrix.Homeservers <h3>Projects</h3> -@if (Projects.Count == 0) { +@if (Client == null) { + <p>Authenticating... <SimpleSpinner/></p> +} +else if (Projects is null) { + <p>Loading projects... <SimpleSpinner/></p> +} +else if (Projects.Count == 0) { <p>There are no projects to display.</p> } else { @@ -28,7 +34,7 @@ else { @code { private BugMineClient? Client { get; set; } - private List<BugMineProject> Projects { get; set; } = []; + private List<BugMineProject>? Projects { get; set; } private CancellationTokenSource? _cts = new(); protected override async Task OnInitializedAsync() { @@ -36,12 +42,17 @@ else { if (Client == null) { return; } - + StateHasChanged(); + await foreach (var project in Client.GetProjects()) { + Projects ??= []; Projects.Add(project); StateHasChanged(); // await Task.Delay(100); } + + Projects ??= []; + StateHasChanged(); } private async Task Navigate(BugMineProject project) { diff --git a/BugMine.Web/Pages/Projects/ViewProject.razor b/BugMine.Web/Pages/Projects/ViewProject.razor
index de94c79..a778728 100644 --- a/BugMine.Web/Pages/Projects/ViewProject.razor +++ b/BugMine.Web/Pages/Projects/ViewProject.razor
@@ -1,33 +1,114 @@ @page "/Projects/{ProjectSlug}/" +@using LibMatrix +@using BugMine.Web.Classes.Exceptions <ProgressLog ></ProgressLog> @if (Client is null) { <p>Authenticating</p> } -else if(Project is null) { - <p>Loading</p> +else if (Project is null) { + @if (Progress == "loading") { + <p>Loading project <SimpleSpinner/></p> + } + else if (Progress == "not-in-room") { + <p>You are not in the project room.</p> + <p>You must join before you can view or interact with this project.</p> + <LinkButton OnClick="TryJoin">Attempt to join</LinkButton> + } } else { <h1>@Project.Info.Name</h1> + + @if (Constants.Debug) { + <p>Debug, beware: here be dragons!</p> + <LinkButton OnClick="@Project.Room.PermanentlyBrickRoomAsync">Dispose room</LinkButton> + } + + @if (Progress == "loading-issues") { + <p>Loading issues, got @(Issues?.Count ?? 0) so far... <SimpleSpinner/></p> + } @* <p>@Project.Description</p> *@ } @code { - [Parameter] public string ProjectSlug { get; set; } - + private string? _progress = "loading"; + + [Parameter] + public string ProjectSlug { get; set; } = null!; + private BugMineClient? Client { get; set; } private BugMineProject? Project { get; set; } + + private List<BugMineIssue>? Issues { get; set; } + + private string? Progress { + get => _progress; + set { + _progress = value; + StateHasChanged(); + } + } protected override async Task OnInitializedAsync() { - Client = await BugMineStorage.GetCurrentSessionOrNavigate(); + Client ??= await BugMineStorage.GetCurrentSessionOrNavigate(); if (Client == null) { return; } + + Progress = "loading"; StateHasChanged(); + + try { + Project = await Client.GetProject(ProjectSlug); + } + catch (MatrixException e) { + if (e.ErrorCode == BugMineException.ErrorCodes.UserNotInRoom) { + Progress = "not-in-room"; + StateHasChanged(); + return; + } + + throw; + } - Project = await Client.GetProject(ProjectSlug); + Progress = "loading-issues"; + await foreach (var issue in Project.GetIssues()) { + Issues ??= new List<BugMineIssue>(); + Issues.Add(issue); + StateHasChanged(); + } + + + StateHasChanged(); } -} \ No newline at end of file + private async Task TryJoin() { + var room = await Client.ResolveProjectSlug(ProjectSlug); + bool success = false; + while (!success) { + try { + await room.JoinAsync(); + if (!string.IsNullOrWhiteSpace(room.RoomId)) { + success = true; + } + else { + await Task.Delay(1000); + } + } + catch (MatrixException e) { + // if (e.ErrorCode == MatrixException.ErrorCodes.) { + // await Task.Delay(1000); + // continue; + // } + + throw; + } + } + + await OnInitializedAsync(); + } + +} + diff --git a/BugMine.sln b/BugMine.sln
index 5ad7b35..c6b4a4b 100644 --- a/BugMine.sln +++ b/BugMine.sln
@@ -16,6 +16,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BugMine.Web", "BugMine.Web\ EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BugMine.Sdk", "BugMine.Sdk\BugMine.Sdk.csproj", "{EC02CDCE-8DDD-42AF-80AE-92A15A9B5AC4}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BugMine.DevTools.CLI", "BugMine.DevTools.CLI\BugMine.DevTools.CLI.csproj", "{E4E398A6-98CE-4B78-9E80-42A03765CE07}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -42,6 +44,10 @@ Global {EC02CDCE-8DDD-42AF-80AE-92A15A9B5AC4}.Debug|Any CPU.Build.0 = Debug|Any CPU {EC02CDCE-8DDD-42AF-80AE-92A15A9B5AC4}.Release|Any CPU.ActiveCfg = Release|Any CPU {EC02CDCE-8DDD-42AF-80AE-92A15A9B5AC4}.Release|Any CPU.Build.0 = Release|Any CPU + {E4E398A6-98CE-4B78-9E80-42A03765CE07}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E4E398A6-98CE-4B78-9E80-42A03765CE07}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E4E398A6-98CE-4B78-9E80-42A03765CE07}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E4E398A6-98CE-4B78-9E80-42A03765CE07}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(NestedProjects) = preSolution {F4E241C3-0300-4B87-8707-BCBDEF1F0185} = {8F4F6BEC-0C66-486B-A21A-1C35B2EDAD33} diff --git a/LibMatrix b/LibMatrix -Subproject 440807e02393410327cd86d5ffa007dee98f895 +Subproject 5ca0a45606ad2ca7e1ca45a3b27be08e9640dd9