From aedcd046fc4fc621dae4b231cc80d4b269a69177 Mon Sep 17 00:00:00 2001 From: Mark McDowall Date: Sun, 18 Aug 2024 18:58:29 -0700 Subject: [PATCH] Fixed: PWA Manifest with URL base Closes #7107 --- frontend/build/webpack.config.js | 6 ++ .../Content/Images/Icons/browserconfig.xml | 9 --- .../src/Content/Images/Icons/manifest.json | 19 ------ frontend/src/Content/browserconfig.xml | 11 ++++ frontend/src/Content/manifest.json | 19 ++++++ frontend/src/index.ejs | 4 +- frontend/src/login.html | 59 +++++++++---------- .../Frontend/Mappers/BrowserConfig.cs | 19 ++---- .../Frontend/Mappers/ManifestMapper.cs | 19 ++---- .../Frontend/Mappers/StaticResourceMapper.cs | 4 +- .../UrlBaseReplacementResourceMapperBase.cs | 58 ++++++++++++++++++ 11 files changed, 138 insertions(+), 89 deletions(-) delete mode 100644 frontend/src/Content/Images/Icons/browserconfig.xml delete mode 100644 frontend/src/Content/Images/Icons/manifest.json create mode 100644 frontend/src/Content/browserconfig.xml create mode 100644 frontend/src/Content/manifest.json create mode 100644 src/Sonarr.Http/Frontend/Mappers/UrlBaseReplacementResourceMapperBase.cs diff --git a/frontend/build/webpack.config.js b/frontend/build/webpack.config.js index 616ee5637..85056b3cd 100644 --- a/frontend/build/webpack.config.js +++ b/frontend/build/webpack.config.js @@ -134,6 +134,12 @@ module.exports = (env) => { { source: 'frontend/src/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') } ] } diff --git a/frontend/src/Content/Images/Icons/browserconfig.xml b/frontend/src/Content/Images/Icons/browserconfig.xml deleted file mode 100644 index 993924968..000000000 --- a/frontend/src/Content/Images/Icons/browserconfig.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - #00ccff - - - diff --git a/frontend/src/Content/Images/Icons/manifest.json b/frontend/src/Content/Images/Icons/manifest.json deleted file mode 100644 index c7bd44495..000000000 --- a/frontend/src/Content/Images/Icons/manifest.json +++ /dev/null @@ -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" -} diff --git a/frontend/src/Content/browserconfig.xml b/frontend/src/Content/browserconfig.xml new file mode 100644 index 000000000..646112d06 --- /dev/null +++ b/frontend/src/Content/browserconfig.xml @@ -0,0 +1,11 @@ + + + + + + + #00ccff + + + + diff --git a/frontend/src/Content/manifest.json b/frontend/src/Content/manifest.json new file mode 100644 index 000000000..42a38e13e --- /dev/null +++ b/frontend/src/Content/manifest.json @@ -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" +} diff --git a/frontend/src/index.ejs b/frontend/src/index.ejs index 3f5ec6f2a..c86078033 100644 --- a/frontend/src/index.ejs +++ b/frontend/src/index.ejs @@ -33,7 +33,7 @@ sizes="16x16" href="/Content/Images/Icons/favicon-16x16.png" /> - + diff --git a/frontend/src/login.html b/frontend/src/login.html index 8ec1aef51..e2be93a74 100644 --- a/frontend/src/login.html +++ b/frontend/src/login.html @@ -11,8 +11,11 @@ - - + + @@ -33,7 +36,11 @@ sizes="16x16" href="/Content/Images/Icons/favicon-16x16.png" /> - + - + @@ -59,7 +63,7 @@ body { background-color: var(--pageBackground); color: var(--textColor); - font-family: "Roboto", "open sans", "Helvetica Neue", Helvetica, Arial, + font-family: 'Roboto', 'open sans', 'Helvetica Neue', Helvetica, Arial, sans-serif; } @@ -209,9 +213,7 @@
- +
@@ -282,16 +284,16 @@ diff --git a/src/Sonarr.Http/Frontend/Mappers/BrowserConfig.cs b/src/Sonarr.Http/Frontend/Mappers/BrowserConfig.cs index 50eb6103f..3cb1488df 100644 --- a/src/Sonarr.Http/Frontend/Mappers/BrowserConfig.cs +++ b/src/Sonarr.Http/Frontend/Mappers/BrowserConfig.cs @@ -1,4 +1,4 @@ -using System.IO; +using System.IO; using NLog; using NzbDrone.Common.Disk; using NzbDrone.Common.EnvironmentInfo; @@ -6,29 +6,22 @@ using NzbDrone.Core.Configuration; 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) - : base(diskProvider, logger) + : base(diskProvider, configFileProvider, logger) { - _appFolderInfo = appFolderInfo; - _configFileProvider = configFileProvider; + FilePath = Path.Combine(appFolderInfo.StartUpFolder, configFileProvider.UiFolder, "Content", "browserconfig.xml"); } public override string Map(string resourceUrl) { - var path = resourceUrl.Replace('/', Path.DirectorySeparatorChar); - path = path.Trim(Path.DirectorySeparatorChar); - - return Path.ChangeExtension(Path.Combine(_appFolderInfo.StartUpFolder, _configFileProvider.UiFolder, path), "xml"); + return FilePath; } public override bool CanHandle(string resourceUrl) { - return resourceUrl.StartsWith("/content/images/icons/browserconfig"); + return resourceUrl.StartsWith("/Content/browserconfig"); } } } diff --git a/src/Sonarr.Http/Frontend/Mappers/ManifestMapper.cs b/src/Sonarr.Http/Frontend/Mappers/ManifestMapper.cs index 4af375b97..424af1cda 100644 --- a/src/Sonarr.Http/Frontend/Mappers/ManifestMapper.cs +++ b/src/Sonarr.Http/Frontend/Mappers/ManifestMapper.cs @@ -1,4 +1,4 @@ -using System.IO; +using System.IO; using NLog; using NzbDrone.Common.Disk; using NzbDrone.Common.EnvironmentInfo; @@ -6,29 +6,22 @@ using NzbDrone.Core.Configuration; 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) - : base(diskProvider, logger) + : base(diskProvider, configFileProvider, logger) { - _appFolderInfo = appFolderInfo; - _configFileProvider = configFileProvider; + FilePath = Path.Combine(appFolderInfo.StartUpFolder, configFileProvider.UiFolder, "Content", "manifest.json"); } public override string Map(string resourceUrl) { - var path = resourceUrl.Replace('/', Path.DirectorySeparatorChar); - path = path.Trim(Path.DirectorySeparatorChar); - - return Path.ChangeExtension(Path.Combine(_appFolderInfo.StartUpFolder, _configFileProvider.UiFolder, path), "json"); + return FilePath; } public override bool CanHandle(string resourceUrl) { - return resourceUrl.StartsWith("/Content/Images/Icons/manifest"); + return resourceUrl.StartsWith("/Content/manifest"); } } } diff --git a/src/Sonarr.Http/Frontend/Mappers/StaticResourceMapper.cs b/src/Sonarr.Http/Frontend/Mappers/StaticResourceMapper.cs index 32b8ecb42..e3dbabcb0 100644 --- a/src/Sonarr.Http/Frontend/Mappers/StaticResourceMapper.cs +++ b/src/Sonarr.Http/Frontend/Mappers/StaticResourceMapper.cs @@ -30,8 +30,8 @@ namespace Sonarr.Http.Frontend.Mappers { resourceUrl = resourceUrl.ToLowerInvariant(); - if (resourceUrl.StartsWith("/content/images/icons/manifest") || - resourceUrl.StartsWith("/content/images/icons/browserconfig")) + if (resourceUrl.StartsWith("/content/manifest") || + resourceUrl.StartsWith("/content/browserconfig")) { return false; } diff --git a/src/Sonarr.Http/Frontend/Mappers/UrlBaseReplacementResourceMapperBase.cs b/src/Sonarr.Http/Frontend/Mappers/UrlBaseReplacementResourceMapperBase.cs new file mode 100644 index 000000000..c79d16464 --- /dev/null +++ b/src/Sonarr.Http/Frontend/Mappers/UrlBaseReplacementResourceMapperBase.cs @@ -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; + } + } +}