oqtane.framework/Oqtane.Client/UI/ThemeBuilder.razor
2023-05-17 17:13:08 -04:00

200 lines
8.9 KiB
Plaintext

@namespace Oqtane.UI
@inject IJSRuntime JSRuntime
@inject NavigationManager NavigationManager
@inject SiteState SiteState
@DynamicComponent
@code {
[CascadingParameter] PageState PageState { get; set; }
RenderFragment DynamicComponent { get; set; }
protected override void OnParametersSet()
{
// handle page redirection
if (!string.IsNullOrEmpty(PageState.Page.Url))
{
NavigationManager.NavigateTo(PageState.Page.Url);
return;
}
// set page title
if (!string.IsNullOrEmpty(PageState.Page.Title))
{
SiteState.Properties.PageTitle = PageState.Page.Title;
}
else
{
SiteState.Properties.PageTitle = PageState.Site.Name + " - " + PageState.Page.Name;
}
// set page head content
var headcontent = "";
// favicon
var favicon = "favicon.ico";
if (PageState.Site.FaviconFileId != null)
{
favicon = Utilities.FileUrl(PageState.Alias, PageState.Site.FaviconFileId.Value);
}
headcontent += $"<link id=\"app-favicon\" rel=\"shortcut icon\" type=\"image/x-icon\" href=\"{favicon}\" />\n";
// head content
if (!string.IsNullOrEmpty(PageState.Site.HeadContent))
{
headcontent += RemoveScripts(PageState.Site.HeadContent) + "\n";
}
if (!string.IsNullOrEmpty(PageState.Page.HeadContent))
{
headcontent += RemoveScripts(PageState.Page.HeadContent) + "\n";
}
// stylesheets
foreach (Resource resource in PageState.Page.Resources.Where(item => item.ResourceType == ResourceType.Stylesheet))
{
var url = (resource.Url.Contains("://")) ? resource.Url : PageState.Alias.BaseUrl + resource.Url;
headcontent += CreateLink(url, resource.Integrity, resource.CrossOrigin) + "\n";
}
// PWA manifest
if (PageState.Site.PwaIsEnabled && PageState.Site.PwaAppIconFileId != null && PageState.Site.PwaSplashIconFileId != null)
{
headcontent += "<link id=\"app-manifest\" rel=\"manifest\" />\n";
}
SiteState.Properties.HeadContent = headcontent;
// set page body content
var bodycontent = "";
if (PageState.Site.PwaIsEnabled && PageState.Site.PwaAppIconFileId != null && PageState.Site.PwaSplashIconFileId != null)
{
bodycontent += CreatePWAScript(PageState.Alias, PageState.Site, PageState.Route);
}
if (bodycontent != "")
{
SiteState.Properties.BodyContent = bodycontent;
}
DynamicComponent = builder =>
{
var themeType = Type.GetType(PageState.Page.ThemeType);
builder.OpenComponent(0, themeType);
builder.CloseComponent();
};
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (!firstRender)
{
if (PageState.Page.HeadContent != null && PageState.Page.HeadContent.Contains("<script"))
{
var interop = new Interop(JSRuntime);
var index = PageState.Page.HeadContent.IndexOf("<script");
while (index >= 0)
{
var script = PageState.Page.HeadContent.Substring(index, PageState.Page.HeadContent.IndexOf("</script>", index) + 9 - index);
var attributes = script.Substring(0, script.IndexOf(">")).Replace("\"", "").Split(" ");
string id = "";
string url = "";
string integrity = "";
string crossorigin = "";
bool es6module = false;
foreach (var attribute in attributes)
{
if (attribute.Contains("="))
{
var value = attribute.Split("=");
switch (value[0])
{
case "id":
id = value[1];
break;
case "src":
url = value[1];
break;
case "integrity":
integrity = value[1];
break;
case "crossorigin":
crossorigin = value[1];
break;
case "type":
es6module = (value[1] == "module");
break;
}
}
}
if (!string.IsNullOrEmpty(url))
{
url = (url.Contains("://")) ? url : PageState.Alias.BaseUrl + url;
await interop.IncludeScript(id, url, integrity, crossorigin, "", "head");
}
else
{
index = script.IndexOf(">") + 1;
await interop.IncludeScript(id, "", "", "", script.Substring(index, script.IndexOf("</script>") - index), "head");
}
index = PageState.Page.HeadContent.IndexOf("<script", index + 1);
}
}
}
}
private string RemoveScripts(string headcontent)
{
if (headcontent != null)
{
var index = headcontent.IndexOf("<script");
while (index >= 0)
{
headcontent = headcontent.Remove(index, headcontent.IndexOf("</script>") + 9 - index);
index = headcontent.IndexOf("<script");
}
}
return headcontent;
}
private string CreateLink(string url, string integrity, string crossorigin)
{
return "<link rel=\"stylesheet\" href=\"" + url + "\"" + (!string.IsNullOrEmpty(integrity) ? " integrity=\"" + integrity + "\"" : "") + (!string.IsNullOrEmpty(crossorigin) ? " crossorigin=\"" + crossorigin + "\"" : "") + " type=\"text/css\"/>";
}
private string CreatePWAScript(Alias alias, Site site, Route route)
{
return
"<script>" + Environment.NewLine +
" // PWA Manifest" + Environment.NewLine +
" setTimeout(() => {" + Environment.NewLine +
" var manifest = {" + Environment.NewLine +
" \"name\": \"" + site.Name + "\"," + Environment.NewLine +
" \"short_name\": \"" + site.Name + "\"," + Environment.NewLine +
" \"start_url\": \"" + route.SiteUrl + "/\"," + Environment.NewLine +
" \"display\": \"standalone\"," + Environment.NewLine +
" \"background_color\": \"#fff\"," + Environment.NewLine +
" \"description\": \"" + site.Name + "\"," + Environment.NewLine +
" \"icons\": [{" + Environment.NewLine +
" \"src\": \"" + route.RootUrl + Utilities.FileUrl(alias, site.PwaAppIconFileId.Value) + "\"," + Environment.NewLine +
" \"sizes\": \"192x192\"," + Environment.NewLine +
" \"type\": \"image/png\"" + Environment.NewLine +
" }, {" + Environment.NewLine +
" \"src\": \"" + route.RootUrl + Utilities.FileUrl(alias, site.PwaSplashIconFileId.Value) + "\"," + Environment.NewLine +
" \"sizes\": \"512x512\"," + Environment.NewLine +
" \"type\": \"image/png\"" + Environment.NewLine +
" }]" + Environment.NewLine +
" };" + Environment.NewLine +
" const serialized = JSON.stringify(manifest);" + Environment.NewLine +
" const blob = new Blob([serialized], {type: 'application/javascript'});" + Environment.NewLine +
" const url = URL.createObjectURL(blob);" + Environment.NewLine +
" document.getElementById('app-manifest').setAttribute('href', url);" + Environment.NewLine +
" }, 1000);" + Environment.NewLine +
"</script>" + Environment.NewLine +
"<script>" + Environment.NewLine +
" // PWA Service Worker" + Environment.NewLine +
" if ('serviceWorker' in navigator) {" + Environment.NewLine +
" navigator.serviceWorker.register('/service-worker.js').then(function(registration) {" + Environment.NewLine +
" console.log('ServiceWorker Registration Successful');" + Environment.NewLine +
" }).catch (function(err) {" + Environment.NewLine +
" console.log('ServiceWorker Registration Failed ', err);" + Environment.NewLine +
" });" + Environment.NewLine +
" };" + Environment.NewLine +
"</script>";
}
}