1
0
mirror of https://github.com/Sonarr/Sonarr.git synced 2024-12-23 02:05:27 +02:00

Fixed: PWA Manifest with URL base

Closes #7107
This commit is contained in:
Mark McDowall 2024-08-18 18:58:29 -07:00 committed by GitHub
parent f45713bff8
commit aedcd046fc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 138 additions and 89 deletions

View File

@ -134,6 +134,12 @@ module.exports = (env) => {
{ {
source: 'frontend/src/Content/robots.txt', source: 'frontend/src/Content/robots.txt',
destination: path.join(distFolder, 'Content/robots.txt') destination: path.join(distFolder, 'Content/robots.txt')
},
// manifest.json and browserconfig.xml
{
source: 'frontend/src/Content/*.(json|xml)',
destination: path.join(distFolder, 'Content')
} }
] ]
} }

View File

@ -1,9 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<browserconfig>
<msapplication>
<tile>
<square150x150logo src="/Content/Images/Icons/mstile-150x150.png"/>
<TileColor>#00ccff</TileColor>
</tile>
</msapplication>
</browserconfig>

View File

@ -1,19 +0,0 @@
{
"name": "Sonarr",
"icons": [
{
"src": "android-chrome-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "android-chrome-512x512.png",
"sizes": "512x512",
"type": "image/png"
}
],
"start_url": "../../../../",
"theme_color": "#3a3f51",
"background_color": "#3a3f51",
"display": "standalone"
}

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<browserconfig>
<msapplication>
<tile>
<square150x150logo src="__URL_BASE__/Content/Images/Icons/mstile-150x150.png" />
<TileColor>
#00ccff
</TileColor>
</tile>
</msapplication>
</browserconfig>

View File

@ -0,0 +1,19 @@
{
"name": "Sonarr",
"icons": [
{
"src": "android-chrome-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "android-chrome-512x512.png",
"sizes": "512x512",
"type": "image/png"
}
],
"start_url": "__URL_BASE__/",
"theme_color": "#3a3f51",
"background_color": "#3a3f51",
"display": "standalone"
}

View File

@ -33,7 +33,7 @@
sizes="16x16" sizes="16x16"
href="/Content/Images/Icons/favicon-16x16.png" href="/Content/Images/Icons/favicon-16x16.png"
/> />
<link rel="manifest" href="/Content/Images/Icons/manifest.json" crossorigin="use-credentials" /> <link rel="manifest" href="/Content/manifest.json" crossorigin="use-credentials" />
<link <link
rel="mask-icon" rel="mask-icon"
href="/Content/Images/Icons/safari-pinned-tab.svg" href="/Content/Images/Icons/safari-pinned-tab.svg"
@ -47,7 +47,7 @@
/> />
<meta <meta
name="msapplication-config" name="msapplication-config"
content="/Content/Images/Icons/browserconfig.xml" content="/Content/browserconfig.xml"
/> />
<link rel="stylesheet" type="text/css" href="/Content/Fonts/fonts.css"> <link rel="stylesheet" type="text/css" href="/Content/Fonts/fonts.css">

View File

@ -11,8 +11,11 @@
<!-- Android/Apple Phone --> <!-- Android/Apple Phone -->
<meta name="mobile-web-app-capable" content="yes" /> <meta name="mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-capable" content="yes" /> <meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" /> <meta
<meta name="format-detection" content="telephone=no"> name="apple-mobile-web-app-status-bar-style"
content="black-translucent"
/>
<meta name="format-detection" content="telephone=no" />
<meta name="description" content="Sonarr" /> <meta name="description" content="Sonarr" />
@ -33,7 +36,11 @@
sizes="16x16" sizes="16x16"
href="/Content/Images/Icons/favicon-16x16.png" href="/Content/Images/Icons/favicon-16x16.png"
/> />
<link rel="manifest" href="/Content/Images/Icons/manifest.json" crossorigin="use-credentials" /> <link
rel="manifest"
href="/Content/manifest.json"
crossorigin="use-credentials"
/>
<link <link
rel="mask-icon" rel="mask-icon"
href="/Content/Images/Icons/safari-pinned-tab.svg" href="/Content/Images/Icons/safari-pinned-tab.svg"
@ -45,10 +52,7 @@
href="/favicon.ico" href="/favicon.ico"
data-no-hash data-no-hash
/> />
<meta <meta name="msapplication-config" content="/Content/browserconfig.xml" />
name="msapplication-config"
content="/Content/Images/Icons/browserconfig.xml"
/>
<link rel="stylesheet" type="text/css" href="/Content/styles.css" /> <link rel="stylesheet" type="text/css" href="/Content/styles.css" />
<link rel="stylesheet" type="text/css" href="/Content/Fonts/fonts.css" /> <link rel="stylesheet" type="text/css" href="/Content/Fonts/fonts.css" />
@ -59,7 +63,7 @@
body { body {
background-color: var(--pageBackground); background-color: var(--pageBackground);
color: var(--textColor); color: var(--textColor);
font-family: "Roboto", "open sans", "Helvetica Neue", Helvetica, Arial, font-family: 'Roboto', 'open sans', 'Helvetica Neue', Helvetica, Arial,
sans-serif; sans-serif;
} }
@ -209,9 +213,7 @@
</div> </div>
<div class="panel-body"> <div class="panel-body">
<div class="sign-in"> <div class="sign-in">SIGN IN TO CONTINUE</div>
SIGN IN TO CONTINUE
</div>
<form <form
role="form" role="form"
@ -230,8 +232,8 @@
pattern=".{1,}" pattern=".{1,}"
required required
title="User name is required" title="User name is required"
autoFocus="true" autofocus="true"
autoCapitalize="false" autocapitalize="false"
/> />
</div> </div>
@ -282,16 +284,16 @@
</body> </body>
<script type="text/javascript"> <script type="text/javascript">
var yearSpan = document.getElementById("year"); var yearSpan = document.getElementById('year');
yearSpan.innerHTML = "2010-" + new Date().getFullYear(); yearSpan.innerHTML = '2010-' + new Date().getFullYear();
var copyDiv = document.getElementById("copy"); var copyDiv = document.getElementById('copy');
copyDiv.classList.remove("hidden"); copyDiv.classList.remove('hidden');
if (window.location.search.indexOf("loginFailed=true") > -1) { if (window.location.search.indexOf('loginFailed=true') > -1) {
var loginFailedDiv = document.getElementById("login-failed"); var loginFailedDiv = document.getElementById('login-failed');
loginFailedDiv.classList.remove("hidden"); loginFailedDiv.classList.remove('hidden');
} }
var light = { var light = {
@ -311,7 +313,7 @@
primaryHoverBorderColor: '#3483e7', primaryHoverBorderColor: '#3483e7',
failedColor: '#f05050', failedColor: '#f05050',
forgotPasswordColor: '#909fa7', forgotPasswordColor: '#909fa7',
forgotPasswordAltColor: '#748690' forgotPasswordAltColor: '#748690',
}; };
var dark = { var dark = {
@ -331,21 +333,16 @@
primaryHoverBorderColor: '#3483e7', primaryHoverBorderColor: '#3483e7',
failedColor: '#f05050', failedColor: '#f05050',
forgotPasswordColor: '#737d83', forgotPasswordColor: '#737d83',
forgotPasswordAltColor: '#546067' forgotPasswordAltColor: '#546067',
}; };
var theme = "_THEME_"; var theme = '_THEME_';
var defaultDark = window.matchMedia('(prefers-color-scheme: dark)').matches; var defaultDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
var finalTheme = theme === 'dark' || (theme === 'auto' && defaultDark) ? var finalTheme =
dark : theme === 'dark' || (theme === 'auto' && defaultDark) ? dark : light;
light;
Object.entries(finalTheme).forEach(([key, value]) => { Object.entries(finalTheme).forEach(([key, value]) => {
document.documentElement.style.setProperty( document.documentElement.style.setProperty(`--${key}`, value);
`--${key}`,
value
);
}); });
</script> </script>
</html> </html>

View File

@ -1,4 +1,4 @@
using System.IO; using System.IO;
using NLog; using NLog;
using NzbDrone.Common.Disk; using NzbDrone.Common.Disk;
using NzbDrone.Common.EnvironmentInfo; using NzbDrone.Common.EnvironmentInfo;
@ -6,29 +6,22 @@
namespace Sonarr.Http.Frontend.Mappers namespace Sonarr.Http.Frontend.Mappers
{ {
public class BrowserConfig : StaticResourceMapperBase public class BrowserConfig : UrlBaseReplacementResourceMapperBase
{ {
private readonly IAppFolderInfo _appFolderInfo;
private readonly IConfigFileProvider _configFileProvider;
public BrowserConfig(IAppFolderInfo appFolderInfo, IDiskProvider diskProvider, IConfigFileProvider configFileProvider, Logger logger) public BrowserConfig(IAppFolderInfo appFolderInfo, IDiskProvider diskProvider, IConfigFileProvider configFileProvider, Logger logger)
: base(diskProvider, logger) : base(diskProvider, configFileProvider, logger)
{ {
_appFolderInfo = appFolderInfo; FilePath = Path.Combine(appFolderInfo.StartUpFolder, configFileProvider.UiFolder, "Content", "browserconfig.xml");
_configFileProvider = configFileProvider;
} }
public override string Map(string resourceUrl) public override string Map(string resourceUrl)
{ {
var path = resourceUrl.Replace('/', Path.DirectorySeparatorChar); return FilePath;
path = path.Trim(Path.DirectorySeparatorChar);
return Path.ChangeExtension(Path.Combine(_appFolderInfo.StartUpFolder, _configFileProvider.UiFolder, path), "xml");
} }
public override bool CanHandle(string resourceUrl) public override bool CanHandle(string resourceUrl)
{ {
return resourceUrl.StartsWith("/content/images/icons/browserconfig"); return resourceUrl.StartsWith("/Content/browserconfig");
} }
} }
} }

View File

@ -1,4 +1,4 @@
using System.IO; using System.IO;
using NLog; using NLog;
using NzbDrone.Common.Disk; using NzbDrone.Common.Disk;
using NzbDrone.Common.EnvironmentInfo; using NzbDrone.Common.EnvironmentInfo;
@ -6,29 +6,22 @@
namespace Sonarr.Http.Frontend.Mappers namespace Sonarr.Http.Frontend.Mappers
{ {
public class ManifestMapper : StaticResourceMapperBase public class ManifestMapper : UrlBaseReplacementResourceMapperBase
{ {
private readonly IAppFolderInfo _appFolderInfo;
private readonly IConfigFileProvider _configFileProvider;
public ManifestMapper(IAppFolderInfo appFolderInfo, IDiskProvider diskProvider, IConfigFileProvider configFileProvider, Logger logger) public ManifestMapper(IAppFolderInfo appFolderInfo, IDiskProvider diskProvider, IConfigFileProvider configFileProvider, Logger logger)
: base(diskProvider, logger) : base(diskProvider, configFileProvider, logger)
{ {
_appFolderInfo = appFolderInfo; FilePath = Path.Combine(appFolderInfo.StartUpFolder, configFileProvider.UiFolder, "Content", "manifest.json");
_configFileProvider = configFileProvider;
} }
public override string Map(string resourceUrl) public override string Map(string resourceUrl)
{ {
var path = resourceUrl.Replace('/', Path.DirectorySeparatorChar); return FilePath;
path = path.Trim(Path.DirectorySeparatorChar);
return Path.ChangeExtension(Path.Combine(_appFolderInfo.StartUpFolder, _configFileProvider.UiFolder, path), "json");
} }
public override bool CanHandle(string resourceUrl) public override bool CanHandle(string resourceUrl)
{ {
return resourceUrl.StartsWith("/Content/Images/Icons/manifest"); return resourceUrl.StartsWith("/Content/manifest");
} }
} }
} }

View File

@ -30,8 +30,8 @@ public override bool CanHandle(string resourceUrl)
{ {
resourceUrl = resourceUrl.ToLowerInvariant(); resourceUrl = resourceUrl.ToLowerInvariant();
if (resourceUrl.StartsWith("/content/images/icons/manifest") || if (resourceUrl.StartsWith("/content/manifest") ||
resourceUrl.StartsWith("/content/images/icons/browserconfig")) resourceUrl.StartsWith("/content/browserconfig"))
{ {
return false; return false;
} }

View File

@ -0,0 +1,58 @@
using System.IO;
using NLog;
using NzbDrone.Common.Disk;
using NzbDrone.Common.EnvironmentInfo;
using NzbDrone.Core.Configuration;
namespace Sonarr.Http.Frontend.Mappers
{
public abstract class UrlBaseReplacementResourceMapperBase : StaticResourceMapperBase
{
private readonly IDiskProvider _diskProvider;
private readonly string _urlBase;
private string _generatedContent;
public UrlBaseReplacementResourceMapperBase(IDiskProvider diskProvider, IConfigFileProvider configFileProvider, Logger logger)
: base(diskProvider, logger)
{
_diskProvider = diskProvider;
_urlBase = configFileProvider.UrlBase;
}
protected string FilePath;
public override string Map(string resourceUrl)
{
return FilePath;
}
protected override Stream GetContentStream(string filePath)
{
var text = GetFileText();
var stream = new MemoryStream();
var writer = new StreamWriter(stream);
writer.Write(text);
writer.Flush();
stream.Position = 0;
return stream;
}
protected virtual string GetFileText()
{
if (RuntimeInfo.IsProduction && _generatedContent != null)
{
return _generatedContent;
}
var text = _diskProvider.ReadAllText(FilePath);
text = text.Replace("__URL_BASE__", _urlBase);
_generatedContent = text;
return _generatedContent;
}
}
}