-
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: GH Pages initial displayable wasm webapp
- Loading branch information
Showing
19 changed files
with
571 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
<Router AppAssembly="@typeof(Program).Assembly"> | ||
<Found Context="routeData"> | ||
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" /> | ||
</Found> | ||
<NotFound> | ||
<LayoutView Layout="@typeof(MainLayout)"> | ||
<p>Sorry, there's nothing at this address.</p> | ||
</LayoutView> | ||
</NotFound> | ||
</Router> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
@page "/" | ||
@page "/gh/{GitHubOwner}/{GitHubRepository}" | ||
|
||
@using WarHub.ArmouryModel.ProjectModel | ||
@using WarHub.GodMode.Components.Areas.Workspace | ||
|
||
@inject NavigationManager Navman | ||
@inject IWorkspaceProviderAggregate ProviderAggregate | ||
|
||
<Title>@TitleText</Title> | ||
|
||
<RepositorySourceSelect WorkspaceInfo="WorkspaceInfo" WorkspaceInfoChanged="UpdateWorkspace" /> | ||
|
||
@if (ErrorMessage is null) | ||
{ | ||
if (Workspace is { }) | ||
{ | ||
<WorkspaceView Workspace="Workspace" /> | ||
} | ||
else if (WorkspaceInfo.Type == WorkspaceType.Invalid) | ||
{ | ||
<em>No workspace loaded.</em> | ||
} | ||
else | ||
{ | ||
<em>Loading source...</em> | ||
} | ||
} | ||
else | ||
{ | ||
<h4>@ErrorMessage</h4> | ||
} | ||
|
||
@code { | ||
[Parameter] | ||
public string GitHubOwner { get; set; } | ||
|
||
[Parameter] | ||
public string GitHubRepository { get; set; } | ||
|
||
string TitleText => WorkspaceInfo?.Type switch | ||
{ | ||
WorkspaceType.GitHub => WorkspaceInfo.GitHubRepository, | ||
_ => "GodMode" | ||
}; | ||
|
||
WorkspaceInfo FallbackWorkspaceInfo => WorkspaceInfo.Invalid; | ||
|
||
IWorkspace Workspace { get; set; } | ||
|
||
WorkspaceInfo WorkspaceInfo { get; set; } = WorkspaceInfo.Invalid; | ||
|
||
string ErrorMessage { get; set; } | ||
|
||
(WorkspaceInfo info, string error) ParseLocation() | ||
{ | ||
if (string.IsNullOrEmpty(GitHubOwner) || string.IsNullOrEmpty(GitHubRepository)) | ||
{ | ||
return (null, null); | ||
} | ||
var urlString = $"https://github.com/{GitHubOwner}/{GitHubRepository}"; | ||
try | ||
{ | ||
var url = new Uri(urlString); | ||
var info = WorkspaceInfo.CreateGitHub(url); | ||
return (info, null); | ||
} | ||
catch (Exception e) | ||
{ | ||
var msg = $"Failed to parse GitHub address '{urlString}': " + e.Message; | ||
return (null, msg); | ||
} | ||
} | ||
|
||
protected override async Task OnParametersSetAsync() | ||
{ | ||
await Update(); | ||
} | ||
|
||
protected override async Task OnInitializedAsync() | ||
{ | ||
await Update(); | ||
} | ||
|
||
async Task Update() | ||
{ | ||
var (info, message) = ParseLocation(); | ||
ErrorMessage = message; | ||
await UpdateWorkspace(info ?? FallbackWorkspaceInfo); | ||
} | ||
|
||
async Task UpdateWorkspace(WorkspaceInfo info) | ||
{ | ||
if (WorkspaceInfo != info || Workspace == null) | ||
{ | ||
WorkspaceInfo = info; | ||
Workspace = null; | ||
ErrorMessage = null; | ||
try | ||
{ | ||
if (info.Type != WorkspaceType.Invalid) | ||
{ | ||
Workspace = await ProviderAggregate.GetWorkspace(info); | ||
} | ||
} | ||
catch (Exception e) | ||
{ | ||
ErrorMessage = $"Failed to load repository source: {e.Message}"; | ||
} | ||
var targetUri = Navman.ToAbsoluteUri(Navman.BaseUri + info.AppRoute).ToString(); | ||
if (targetUri != Navman.Uri) | ||
{ | ||
Navman.NavigateTo(targetUri); | ||
} | ||
StateHasChanged(); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
using System; | ||
using System.Net.Http; | ||
using System.Threading.Tasks; | ||
using Microsoft.AspNetCore.Components.WebAssembly.Hosting; | ||
using Microsoft.Extensions.DependencyInjection; | ||
using Toolbelt.Blazor.Extensions.DependencyInjection; | ||
using WarHub.GodMode.Components.Areas.Workspace; | ||
using WarHub.GodMode.GithubPages.Services; | ||
|
||
namespace WarHub.GodMode.GithubPages | ||
{ | ||
public class Program | ||
{ | ||
public static async Task Main(string[] args) | ||
{ | ||
var builder = WebAssemblyHostBuilder.CreateDefault(args); | ||
builder.RootComponents.Add<App>("app"); | ||
|
||
builder.Services.AddSingleton(new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) }); | ||
ConfigureServices(builder.Services); | ||
|
||
await builder.Build().RunAsync(); | ||
} | ||
static void ConfigureServices(IServiceCollection services) | ||
{ | ||
services.AddHeadElementHelper(); | ||
services.AddSingleton<GitHubWorkspaceProvider>(); | ||
services.AddScoped<IWorkspaceProviderAggregate, WorkspaceProviderAggregate>(); | ||
services.AddScoped<IWorkspaceContextResolver, WorkspaceContextResolver>(); | ||
} | ||
} | ||
} |
31 changes: 31 additions & 0 deletions
31
src/WarHub.GodMode.GithubPages/Properties/launchSettings.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
{ | ||
"iisSettings": { | ||
"windowsAuthentication": false, | ||
"anonymousAuthentication": true, | ||
"iisExpress": { | ||
"applicationUrl": "http://localhost:19082", | ||
"sslPort": 44340 | ||
} | ||
}, | ||
"profiles": { | ||
"IIS Express": { | ||
"commandName": "IISExpress", | ||
"commandLineArgs": "--pathbase=/GodMode", | ||
"launchBrowser": true, | ||
"launchUrl": "GodMode", | ||
"environmentVariables": { | ||
"ASPNETCORE_ENVIRONMENT": "Development" | ||
}, | ||
"inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}" | ||
}, | ||
"WarHub.GodMode.GithubPages": { | ||
"commandName": "Project", | ||
"launchBrowser": true, | ||
"environmentVariables": { | ||
"ASPNETCORE_ENVIRONMENT": "Development" | ||
}, | ||
"applicationUrl": "https://localhost:5001;http://localhost:5000", | ||
"inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}" | ||
} | ||
} | ||
} |
116 changes: 116 additions & 0 deletions
116
src/WarHub.GodMode.GithubPages/Services/GitHubWorkspaceProvider.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Collections.Immutable; | ||
using System.IO; | ||
using System.IO.Compression; | ||
using System.Net.Http; | ||
using System.Threading.Tasks; | ||
using WarHub.ArmouryModel.ProjectModel; | ||
using WarHub.ArmouryModel.Source; | ||
using WarHub.ArmouryModel.Workspaces.BattleScribe; | ||
using WarHub.GodMode.Components.Areas.Workspace; | ||
|
||
namespace WarHub.GodMode.GithubPages.Services | ||
{ | ||
public class GitHubWorkspaceProvider : IWorkspaceProvider | ||
{ | ||
public GitHubWorkspaceProvider(HttpClient httpClient) | ||
{ | ||
HttpClient = httpClient; | ||
} | ||
|
||
private HttpClient HttpClient { get; } | ||
|
||
// TODO cache -> IndexedDB | ||
private Dictionary<Uri, IWorkspace> Cache { get; } | ||
= new Dictionary<Uri, IWorkspace>(); | ||
|
||
public async Task<IWorkspace> GetWorkspace(WorkspaceInfo info) | ||
{ | ||
if (info is { Type: WorkspaceType.GitHub, GitHubUrl: { } }) | ||
{ | ||
return await GetWorkspaceCore(info); | ||
} | ||
return null; | ||
} | ||
|
||
public async Task<IWorkspace> GetWorkspaceCore(WorkspaceInfo info) | ||
{ | ||
if (Cache.TryGetValue(info.GitHubUrl, out var cached)) | ||
{ | ||
return cached; | ||
} | ||
return await Task.Run(async () => | ||
{ | ||
var repoPath = string.Concat(info.GitHubUrl.Segments[^2..]); | ||
var repoUri = info.GitHubUrl + "/archive/master.zip"; | ||
var response = await HttpClient.GetAsync(repoUri); | ||
response.EnsureSuccessStatusCode(); | ||
using var zipStream = await response.Content.ReadAsStreamAsync(); | ||
using var zip = new ZipArchive(zipStream); | ||
var datafiles = GetDatafiles(zip).ToImmutableArray(); | ||
var workspace = new InMemoryWorkspace(info.GitHubUrl.ToString(), datafiles); | ||
return Cache[info.GitHubUrl] = workspace; | ||
}); | ||
|
||
IEnumerable<IDatafileInfo> GetDatafiles(ZipArchive zip) | ||
{ | ||
foreach (var entry in zip.Entries) | ||
{ | ||
using var entryStream = entry.Open(); | ||
var file = entry.Name.GetXmlDocumentKind() switch | ||
{ | ||
XmlDocumentKind.Gamesystem => entryStream.LoadSourceAuto(entry.Name), | ||
XmlDocumentKind.Catalogue => entryStream.LoadSourceAuto(entry.Name), | ||
_ => (IDatafileInfo)new UnknownTypeDatafileInfo(entry.Name) | ||
}; | ||
if (file is { }) | ||
{ | ||
yield return file; | ||
} | ||
} | ||
} | ||
} | ||
|
||
private class InMemoryWorkspace : IWorkspace | ||
{ | ||
public InMemoryWorkspace(string rootPath, ImmutableArray<IDatafileInfo> datafiles) | ||
{ | ||
RootPath = rootPath; | ||
Datafiles = datafiles; | ||
} | ||
|
||
public string RootPath { get; } | ||
|
||
public ImmutableArray<IDatafileInfo> Datafiles { get; } | ||
|
||
public ProjectConfigurationInfo Info { get; } = new ProjectConfigurationInfo.Builder | ||
{ | ||
Filepath = ProjectConfiguration.FileExtension, | ||
Configuration = new ProjectConfiguration.Builder | ||
{ | ||
FormatProvider = ProjectFormatProviderType.BattleScribeXml, | ||
OutputPath = ".", | ||
SourceDirectories = ImmutableArray<SourceFolder>.Empty, | ||
ToolsetVersion = ProjectToolset.Version | ||
}.ToImmutable() | ||
}.ToImmutable(); | ||
} | ||
|
||
private class UnknownTypeDatafileInfo : IDatafileInfo | ||
{ | ||
public UnknownTypeDatafileInfo(string filepath) | ||
{ | ||
Filepath = filepath; | ||
} | ||
|
||
public string Filepath { get; } | ||
|
||
public SourceKind DataKind => SourceKind.Unknown; | ||
|
||
public SourceNode GetData() => null; | ||
|
||
public string GetStorageName() => Path.GetFileNameWithoutExtension(Filepath); | ||
} | ||
} | ||
} |
Oops, something went wrong.