From c666862762f98ecbd85d7e4bdc15a68d966e05f4 Mon Sep 17 00:00:00 2001 From: Amadeusz Sadowski Date: Wed, 22 Apr 2020 02:02:46 +0200 Subject: [PATCH] feat: GH Pages initial displayable wasm webapp --- GodMode.sln | 15 +++ .../Areas/Workspace/WorkspaceInfo.cs | 8 +- src/WarHub.GodMode.GithubPages/App.razor | 10 ++ .../Pages/Index.razor | 118 ++++++++++++++++++ src/WarHub.GodMode.GithubPages/Program.cs | 32 +++++ .../Properties/launchSettings.json | 31 +++++ .../Services/GitHubWorkspaceProvider.cs | 116 +++++++++++++++++ .../Services/WorkspaceProviderAggregate.cs | 38 ++++++ .../Shared/MainLayout.razor | 15 +++ .../Shared/NavMenu.razor | 35 ++++++ .../WarHub.GodMode.GithubPages.csproj | 26 ++++ src/WarHub.GodMode.GithubPages/_Imports.razor | 13 ++ .../wwwroot/index.html | 33 +++++ .../wwwroot/manifest.json | 19 +++ .../wwwroot/service-worker.js | 4 + .../wwwroot/service-worker.published.js | 48 +++++++ src/WarHub.GodMode/Pages/Index.razor | 14 ++- .../Services/GitHubWorkspaceProvider.cs | 2 +- src/WarHub.GodMode/_Imports.razor | 2 +- 19 files changed, 571 insertions(+), 8 deletions(-) create mode 100644 src/WarHub.GodMode.GithubPages/App.razor create mode 100644 src/WarHub.GodMode.GithubPages/Pages/Index.razor create mode 100644 src/WarHub.GodMode.GithubPages/Program.cs create mode 100644 src/WarHub.GodMode.GithubPages/Properties/launchSettings.json create mode 100644 src/WarHub.GodMode.GithubPages/Services/GitHubWorkspaceProvider.cs create mode 100644 src/WarHub.GodMode.GithubPages/Services/WorkspaceProviderAggregate.cs create mode 100644 src/WarHub.GodMode.GithubPages/Shared/MainLayout.razor create mode 100644 src/WarHub.GodMode.GithubPages/Shared/NavMenu.razor create mode 100644 src/WarHub.GodMode.GithubPages/WarHub.GodMode.GithubPages.csproj create mode 100644 src/WarHub.GodMode.GithubPages/_Imports.razor create mode 100644 src/WarHub.GodMode.GithubPages/wwwroot/index.html create mode 100644 src/WarHub.GodMode.GithubPages/wwwroot/manifest.json create mode 100644 src/WarHub.GodMode.GithubPages/wwwroot/service-worker.js create mode 100644 src/WarHub.GodMode.GithubPages/wwwroot/service-worker.published.js diff --git a/GodMode.sln b/GodMode.sln index 62a4c89..42005ad 100644 --- a/GodMode.sln +++ b/GodMode.sln @@ -11,6 +11,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WarHub.GodMode.Components", EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WarHub.GodMode.SourceAnalysis", "src\WarHub.GodMode.SourceAnalysis\WarHub.GodMode.SourceAnalysis.csproj", "{4AB89A61-2CBB-4B01-B956-CAF45D3A5A4B}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WarHub.GodMode.GithubPages", "src\WarHub.GodMode.GithubPages\WarHub.GodMode.GithubPages.csproj", "{D122F971-3169-44F7-B560-317A9B034370}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -57,6 +59,18 @@ Global {4AB89A61-2CBB-4B01-B956-CAF45D3A5A4B}.Release|x64.Build.0 = Release|Any CPU {4AB89A61-2CBB-4B01-B956-CAF45D3A5A4B}.Release|x86.ActiveCfg = Release|Any CPU {4AB89A61-2CBB-4B01-B956-CAF45D3A5A4B}.Release|x86.Build.0 = Release|Any CPU + {D122F971-3169-44F7-B560-317A9B034370}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D122F971-3169-44F7-B560-317A9B034370}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D122F971-3169-44F7-B560-317A9B034370}.Debug|x64.ActiveCfg = Debug|Any CPU + {D122F971-3169-44F7-B560-317A9B034370}.Debug|x64.Build.0 = Debug|Any CPU + {D122F971-3169-44F7-B560-317A9B034370}.Debug|x86.ActiveCfg = Debug|Any CPU + {D122F971-3169-44F7-B560-317A9B034370}.Debug|x86.Build.0 = Debug|Any CPU + {D122F971-3169-44F7-B560-317A9B034370}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D122F971-3169-44F7-B560-317A9B034370}.Release|Any CPU.Build.0 = Release|Any CPU + {D122F971-3169-44F7-B560-317A9B034370}.Release|x64.ActiveCfg = Release|Any CPU + {D122F971-3169-44F7-B560-317A9B034370}.Release|x64.Build.0 = Release|Any CPU + {D122F971-3169-44F7-B560-317A9B034370}.Release|x86.ActiveCfg = Release|Any CPU + {D122F971-3169-44F7-B560-317A9B034370}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -65,6 +79,7 @@ Global {D828D047-2598-4F18-B86C-AC3382BB0506} = {F2C4E8DB-68F0-4ED3-AAAD-009183BB5ADD} {2E086252-718E-490E-B886-F3A2B570E9FB} = {F2C4E8DB-68F0-4ED3-AAAD-009183BB5ADD} {4AB89A61-2CBB-4B01-B956-CAF45D3A5A4B} = {F2C4E8DB-68F0-4ED3-AAAD-009183BB5ADD} + {D122F971-3169-44F7-B560-317A9B034370} = {F2C4E8DB-68F0-4ED3-AAAD-009183BB5ADD} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {838E0D3E-F95E-483C-BEBE-DCE7BC1A93FB} diff --git a/src/WarHub.GodMode.Components/Areas/Workspace/WorkspaceInfo.cs b/src/WarHub.GodMode.Components/Areas/Workspace/WorkspaceInfo.cs index 65ec8e2..3b069cb 100644 --- a/src/WarHub.GodMode.Components/Areas/Workspace/WorkspaceInfo.cs +++ b/src/WarHub.GodMode.Components/Areas/Workspace/WorkspaceInfo.cs @@ -19,11 +19,13 @@ public sealed partial class WorkspaceInfo public string AppRoute => appRoute ??= Type switch { - WorkspaceType.GitHub => $"/gh/{GitHubRepository}", - WorkspaceType.LocalFilesystem => "/", - _ => throw new InvalidOperationException() + WorkspaceType.GitHub => $"gh/{GitHubRepository}", + WorkspaceType.LocalFilesystem => "", + _ => "" }; + public static WorkspaceInfo Invalid { get; } = new WorkspaceInfo(WorkspaceType.Invalid, null, null); + public static WorkspaceInfo CreateLocalFs(string path) => new WorkspaceInfo(WorkspaceType.LocalFilesystem, path, null); diff --git a/src/WarHub.GodMode.GithubPages/App.razor b/src/WarHub.GodMode.GithubPages/App.razor new file mode 100644 index 0000000..6f67a6e --- /dev/null +++ b/src/WarHub.GodMode.GithubPages/App.razor @@ -0,0 +1,10 @@ + + + + + + +

Sorry, there's nothing at this address.

+
+
+
diff --git a/src/WarHub.GodMode.GithubPages/Pages/Index.razor b/src/WarHub.GodMode.GithubPages/Pages/Index.razor new file mode 100644 index 0000000..3175913 --- /dev/null +++ b/src/WarHub.GodMode.GithubPages/Pages/Index.razor @@ -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 + +@TitleText + + + +@if (ErrorMessage is null) +{ + if (Workspace is { }) + { + + } + else if (WorkspaceInfo.Type == WorkspaceType.Invalid) + { + No workspace loaded. + } + else + { + Loading source... + } +} +else +{ +

@ErrorMessage

+} + +@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(); + } + } +} \ No newline at end of file diff --git a/src/WarHub.GodMode.GithubPages/Program.cs b/src/WarHub.GodMode.GithubPages/Program.cs new file mode 100644 index 0000000..cc2cc4f --- /dev/null +++ b/src/WarHub.GodMode.GithubPages/Program.cs @@ -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"); + + 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(); + services.AddScoped(); + services.AddScoped(); + } + } +} diff --git a/src/WarHub.GodMode.GithubPages/Properties/launchSettings.json b/src/WarHub.GodMode.GithubPages/Properties/launchSettings.json new file mode 100644 index 0000000..7e7b724 --- /dev/null +++ b/src/WarHub.GodMode.GithubPages/Properties/launchSettings.json @@ -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}" + } + } +} \ No newline at end of file diff --git a/src/WarHub.GodMode.GithubPages/Services/GitHubWorkspaceProvider.cs b/src/WarHub.GodMode.GithubPages/Services/GitHubWorkspaceProvider.cs new file mode 100644 index 0000000..f3ba85e --- /dev/null +++ b/src/WarHub.GodMode.GithubPages/Services/GitHubWorkspaceProvider.cs @@ -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 Cache { get; } + = new Dictionary(); + + public async Task GetWorkspace(WorkspaceInfo info) + { + if (info is { Type: WorkspaceType.GitHub, GitHubUrl: { } }) + { + return await GetWorkspaceCore(info); + } + return null; + } + + public async Task 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 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 datafiles) + { + RootPath = rootPath; + Datafiles = datafiles; + } + + public string RootPath { get; } + + public ImmutableArray Datafiles { get; } + + public ProjectConfigurationInfo Info { get; } = new ProjectConfigurationInfo.Builder + { + Filepath = ProjectConfiguration.FileExtension, + Configuration = new ProjectConfiguration.Builder + { + FormatProvider = ProjectFormatProviderType.BattleScribeXml, + OutputPath = ".", + SourceDirectories = ImmutableArray.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); + } + } +} diff --git a/src/WarHub.GodMode.GithubPages/Services/WorkspaceProviderAggregate.cs b/src/WarHub.GodMode.GithubPages/Services/WorkspaceProviderAggregate.cs new file mode 100644 index 0000000..ce52175 --- /dev/null +++ b/src/WarHub.GodMode.GithubPages/Services/WorkspaceProviderAggregate.cs @@ -0,0 +1,38 @@ +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Threading.Tasks; +using WarHub.ArmouryModel.ProjectModel; +using WarHub.GodMode.Components.Areas.Workspace; + +namespace WarHub.GodMode.GithubPages.Services +{ + public class WorkspaceProviderAggregate : IWorkspaceProviderAggregate + { + public WorkspaceProviderAggregate(GitHubWorkspaceProvider gitHubService) + { + GitHubService = gitHubService; + ProviderInfosByType = new WorkspaceProviderInfo[] + { + new WorkspaceProviderInfo.Builder + { + Type = WorkspaceType.GitHub, + InitialWorkspaceInfo = null, + Provider = GitHubService + }.ToImmutable() + }.ToImmutableDictionary(x => x.Type); + } + + public WorkspaceProviderInfo this[WorkspaceType type] => ProviderInfosByType[type]; + + public IEnumerable ProviderInfos => ProviderInfosByType.Values; + + private GitHubWorkspaceProvider GitHubService { get; } + + private ImmutableDictionary ProviderInfosByType { get; } + + public async Task GetWorkspace(WorkspaceInfo workspaceInfo) + { + return await this[workspaceInfo.Type].Provider.GetWorkspace(workspaceInfo); + } + } +} diff --git a/src/WarHub.GodMode.GithubPages/Shared/MainLayout.razor b/src/WarHub.GodMode.GithubPages/Shared/MainLayout.razor new file mode 100644 index 0000000..0f4e22a --- /dev/null +++ b/src/WarHub.GodMode.GithubPages/Shared/MainLayout.razor @@ -0,0 +1,15 @@ +@inherits LayoutComponentBase + + + +
+
+ About +
+ +
+ @Body +
+
diff --git a/src/WarHub.GodMode.GithubPages/Shared/NavMenu.razor b/src/WarHub.GodMode.GithubPages/Shared/NavMenu.razor new file mode 100644 index 0000000..b107311 --- /dev/null +++ b/src/WarHub.GodMode.GithubPages/Shared/NavMenu.razor @@ -0,0 +1,35 @@ + + +
+ +
+ +@code { + private bool collapseNavMenu = true; + + private string NavMenuCssClass => collapseNavMenu ? "collapse" : null; + + private void ToggleNavMenu() + { + collapseNavMenu = !collapseNavMenu; + } +} diff --git a/src/WarHub.GodMode.GithubPages/WarHub.GodMode.GithubPages.csproj b/src/WarHub.GodMode.GithubPages/WarHub.GodMode.GithubPages.csproj new file mode 100644 index 0000000..8b28fb7 --- /dev/null +++ b/src/WarHub.GodMode.GithubPages/WarHub.GodMode.GithubPages.csproj @@ -0,0 +1,26 @@ + + + + netstandard2.1 + 3.0 + service-worker-assets.js + + + + + + + + + + + + + + + + + + + + diff --git a/src/WarHub.GodMode.GithubPages/_Imports.razor b/src/WarHub.GodMode.GithubPages/_Imports.razor new file mode 100644 index 0000000..8c57777 --- /dev/null +++ b/src/WarHub.GodMode.GithubPages/_Imports.razor @@ -0,0 +1,13 @@ +@using System.Collections.Immutable; +@using System.Net.Http +@using System.Net.Http.Json +@using Microsoft.AspNetCore.Components.Forms +@using Microsoft.AspNetCore.Components.Routing +@using Microsoft.AspNetCore.Components.Web +@using Microsoft.JSInterop +@using MoreLinq +@using Toolbelt.Blazor.HeadElement +@using WarHub.GodMode.GithubPages +@using WarHub.GodMode.GithubPages.Shared +@using WarHub.GodMode.SourceAnalysis +@using WarHub.ArmouryModel.Source diff --git a/src/WarHub.GodMode.GithubPages/wwwroot/index.html b/src/WarHub.GodMode.GithubPages/wwwroot/index.html new file mode 100644 index 0000000..75f1f81 --- /dev/null +++ b/src/WarHub.GodMode.GithubPages/wwwroot/index.html @@ -0,0 +1,33 @@ + + + + + + + + GodMode + + + + + + + + + + + + + Loading... + +
+ An unhandled error has occurred. + Reload + 🗙 +
+ + + + + + diff --git a/src/WarHub.GodMode.GithubPages/wwwroot/manifest.json b/src/WarHub.GodMode.GithubPages/wwwroot/manifest.json new file mode 100644 index 0000000..da70379 --- /dev/null +++ b/src/WarHub.GodMode.GithubPages/wwwroot/manifest.json @@ -0,0 +1,19 @@ +{ + "name": "WarHub GodMode", + "short_name": "GodMode", + "start_url": "./", + "display": "standalone", + "background_color": "#ffffff", + "icons": [ + { + "src": "_content/WarHub.GodMode.Components/favicon-512.png", + "type": "image/png", + "sizes": "512x512" + }, + { + "src": "_content/WarHub.GodMode.Components/favicon-192.png", + "type": "image/png", + "sizes": "192x192" + } + ] +} diff --git a/src/WarHub.GodMode.GithubPages/wwwroot/service-worker.js b/src/WarHub.GodMode.GithubPages/wwwroot/service-worker.js new file mode 100644 index 0000000..fe614da --- /dev/null +++ b/src/WarHub.GodMode.GithubPages/wwwroot/service-worker.js @@ -0,0 +1,4 @@ +// In development, always fetch from the network and do not enable offline support. +// This is because caching would make development more difficult (changes would not +// be reflected on the first load after each change). +self.addEventListener('fetch', () => { }); diff --git a/src/WarHub.GodMode.GithubPages/wwwroot/service-worker.published.js b/src/WarHub.GodMode.GithubPages/wwwroot/service-worker.published.js new file mode 100644 index 0000000..15ffb07 --- /dev/null +++ b/src/WarHub.GodMode.GithubPages/wwwroot/service-worker.published.js @@ -0,0 +1,48 @@ +// Caution! Be sure you understand the caveats before publishing an application with +// offline support. See https://aka.ms/blazor-offline-considerations + +self.importScripts('./service-worker-assets.js'); +self.addEventListener('install', event => event.waitUntil(onInstall(event))); +self.addEventListener('activate', event => event.waitUntil(onActivate(event))); +self.addEventListener('fetch', event => event.respondWith(onFetch(event))); + +const cacheNamePrefix = 'offline-cache-'; +const cacheName = `${cacheNamePrefix}${self.assetsManifest.version}`; +const offlineAssetsInclude = [ /\.dll$/, /\.pdb$/, /\.wasm/, /\.html/, /\.js$/, /\.json$/, /\.css$/, /\.woff$/, /\.png$/, /\.jpe?g$/, /\.gif$/, /\.ico$/ ]; +const offlineAssetsExclude = [ /^service-worker\.js$/ ]; + +async function onInstall(event) { + console.info('Service worker: Install'); + + // Fetch and cache all matching items from the assets manifest + const assetsRequests = self.assetsManifest.assets + .filter(asset => offlineAssetsInclude.some(pattern => pattern.test(asset.url))) + .filter(asset => !offlineAssetsExclude.some(pattern => pattern.test(asset.url))) + .map(asset => new Request(asset.url, { integrity: asset.hash })); + await caches.open(cacheName).then(cache => cache.addAll(assetsRequests)); +} + +async function onActivate(event) { + console.info('Service worker: Activate'); + + // Delete unused caches + const cacheKeys = await caches.keys(); + await Promise.all(cacheKeys + .filter(key => key.startsWith(cacheNamePrefix) && key !== cacheName) + .map(key => caches.delete(key))); +} + +async function onFetch(event) { + let cachedResponse = null; + if (event.request.method === 'GET') { + // For all navigation requests, try to serve index.html from cache + // If you need some URLs to be server-rendered, edit the following check to exclude those URLs + const shouldServeIndexHtml = event.request.mode === 'navigate'; + + const request = shouldServeIndexHtml ? 'index.html' : event.request; + const cache = await caches.open(cacheName); + cachedResponse = await cache.match(request); + } + + return cachedResponse || fetch(event.request); +} diff --git a/src/WarHub.GodMode/Pages/Index.razor b/src/WarHub.GodMode/Pages/Index.razor index 151d2da..258eabe 100644 --- a/src/WarHub.GodMode/Pages/Index.razor +++ b/src/WarHub.GodMode/Pages/Index.razor @@ -17,6 +17,10 @@ { } + else if (WorkspaceInfo.Type == WorkspaceType.Invalid) + { + No workspace loaded. + } else { Loading source... @@ -94,15 +98,19 @@ else ErrorMessage = null; try { - Workspace = await ProviderAggregate.GetWorkspace(info); + if (info.Type != WorkspaceType.Invalid) + { + Workspace = await ProviderAggregate.GetWorkspace(info); + } } catch (Exception e) { ErrorMessage = $"Failed to load repository source: {e.Message}"; } - if (Navman.ToAbsoluteUri(info.AppRoute).ToString() != Navman.Uri) + var targetUri = Navman.ToAbsoluteUri(Navman.BaseUri + info.AppRoute).ToString(); + if (targetUri != Navman.Uri) { - Navman.NavigateTo(info.AppRoute); + Navman.NavigateTo(targetUri); } StateHasChanged(); } diff --git a/src/WarHub.GodMode/Services/GitHubWorkspaceProvider.cs b/src/WarHub.GodMode/Services/GitHubWorkspaceProvider.cs index b78486e..8a1ca14 100644 --- a/src/WarHub.GodMode/Services/GitHubWorkspaceProvider.cs +++ b/src/WarHub.GodMode/Services/GitHubWorkspaceProvider.cs @@ -44,7 +44,7 @@ public async Task GetWorkspaceCore(Uri repository) return await Task.Run(async () => { var repoPath = string.Concat(repository.Segments[^2..]); - var extractDirectory = Path.Join(Path.GetTempPath(), "godmode", "download", repoPath); + var extractDirectory = Path.Combine(Path.GetTempPath(), "godmode", "download", repoPath); if (Directory.Exists(extractDirectory)) { Directory.Delete(extractDirectory, recursive: true); diff --git a/src/WarHub.GodMode/_Imports.razor b/src/WarHub.GodMode/_Imports.razor index c30d3ea..c626eb9 100644 --- a/src/WarHub.GodMode/_Imports.razor +++ b/src/WarHub.GodMode/_Imports.razor @@ -6,7 +6,7 @@ @using Microsoft.AspNetCore.Components.Routing @using Microsoft.AspNetCore.Components.Web @using Microsoft.JSInterop -@using MoreLinq; +@using MoreLinq @using Toolbelt.Blazor.HeadElement @using WarHub.GodMode @using WarHub.GodMode.Shared