diff --git a/Moonlight/App/Http/Controllers/Api/AssetProxyController.cs b/Moonlight/App/Http/Controllers/Api/AssetProxyController.cs new file mode 100644 index 0000000..a8650a3 --- /dev/null +++ b/Moonlight/App/Http/Controllers/Api/AssetProxyController.cs @@ -0,0 +1,66 @@ +using System.Text; +using Microsoft.AspNetCore.Mvc; +using Moonlight.App.Helpers; +using Moonlight.App.Services.Sys; + +namespace Moonlight.App.Http.Controllers.Api; + +[ApiController] +[Route("api/assetproxy")] +public class AssetProxyController : Controller +{ + private readonly MoonlightThemeService ThemeService; + + public AssetProxyController(MoonlightThemeService themeService) + { + ThemeService = themeService; + } + + [HttpGet("theme/{id}/js")] + public async Task GetThemeJs(int id) + { + var enabledThemes = await ThemeService.GetEnabled(); + var selectedTheme = enabledThemes.FirstOrDefault(x => x.Id == id); + + if (selectedTheme == null) + return NotFound(); + + try + { + using var httpClient = new HttpClient(); + var content = await httpClient.GetByteArrayAsync(selectedTheme.JsUrl); + + return File(content, "text/javascript"); + } + catch (Exception e) + { + Logger.Warn($"Error proxying js for theme {id}"); + Logger.Warn(e); + return Problem(); + } + } + + [HttpGet("theme/{id}/css")] + public async Task GetThemeCss(int id) + { + var enabledThemes = await ThemeService.GetEnabled(); + var selectedTheme = enabledThemes.FirstOrDefault(x => x.Id == id); + + if (selectedTheme == null) + return NotFound(); + + try + { + using var httpClient = new HttpClient(); + var content = await httpClient.GetByteArrayAsync(selectedTheme.CssUrl); + + return File(content, "text/css"); + } + catch (Exception e) + { + Logger.Warn($"Error proxying css for theme {id}"); + Logger.Warn(e); + return Problem(); + } + } +} \ No newline at end of file diff --git a/Moonlight/App/Models/Abstractions/ApplicationTheme.cs b/Moonlight/App/Models/Abstractions/ApplicationTheme.cs index 7f6725d..60a20f1 100644 --- a/Moonlight/App/Models/Abstractions/ApplicationTheme.cs +++ b/Moonlight/App/Models/Abstractions/ApplicationTheme.cs @@ -2,6 +2,7 @@ public class ApplicationTheme { + public int Id { get; set; } public string Name { get; set; } = ""; public string Author { get; set; } = ""; public string? DonateUrl { get; set; } = ""; diff --git a/Moonlight/App/Services/Sys/MoonlightThemeService.cs b/Moonlight/App/Services/Sys/MoonlightThemeService.cs index 9d200e6..281e3f5 100644 --- a/Moonlight/App/Services/Sys/MoonlightThemeService.cs +++ b/Moonlight/App/Services/Sys/MoonlightThemeService.cs @@ -1,4 +1,5 @@ -using Moonlight.App.Database.Entities; +using Mappy.Net; +using Moonlight.App.Database.Entities; using Moonlight.App.Models.Abstractions; using Moonlight.App.Repositories; @@ -25,20 +26,13 @@ public class MoonlightThemeService themes.AddRange(themeRepo .Get() .ToArray() - .Select(x => new ApplicationTheme() - { - Name = x.Name, - Author = x.Author, - CssUrl = x.CssUrl, - JsUrl = x.JsUrl, - Enabled = x.Enabled, - DonateUrl = x.DonateUrl - })); + .Select(x => Mapper.Map(x))); if (ConfigService.Get().Theme.EnableDefault) { themes.Insert(0, new() { + Id = 0, Name = "Moonlight Default", Author = "MasuOwO", Enabled = true, diff --git a/Moonlight/Pages/_Host.cshtml b/Moonlight/Pages/_Host.cshtml index 381ac91..d738977 100644 --- a/Moonlight/Pages/_Host.cshtml +++ b/Moonlight/Pages/_Host.cshtml @@ -24,15 +24,18 @@ @foreach (var theme in themes) { + var finalUrl = theme.CssUrl.StartsWith("/") ? theme.CssUrl : $"/api/assetproxy/theme/{theme.Id}/css"; + - + } - + + @* *@ - + } } diff --git a/Moonlight/wwwroot/css/demotheme.css b/Moonlight/wwwroot/css/demotheme.css deleted file mode 100644 index ffe881f..0000000 --- a/Moonlight/wwwroot/css/demotheme.css +++ /dev/null @@ -1,3 +0,0 @@ -body { - background-color: #0d8ddc !important; -} \ No newline at end of file diff --git a/Moonlight/wwwroot/css/interfont.css b/Moonlight/wwwroot/css/interfont.css new file mode 100644 index 0000000..6af0116 --- /dev/null +++ b/Moonlight/wwwroot/css/interfont.css @@ -0,0 +1,280 @@ +/* cyrillic-ext */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 300; + src: url("/fonts/Inter.woff2") format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 300; + src: url("/fonts/Inter.woff2") format('woff2'); + unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 300; + src: url() format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 300; + src: url("/fonts/Inter.woff2") format('woff2'); + unicode-range: U+0370-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 300; + src: url("/fonts/Inter.woff2") format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 300; + src: url("/fonts/Inter.woff2") format('woff2'); + unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 300; + src: url("/fonts/Inter.woff2") format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 400; + src: url("/fonts/Inter.woff2") format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 400; + src: url("/fonts/Inter.woff2") format('woff2'); + unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 400; + src: url("/fonts/Inter.woff2") format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 400; + src: url() format('woff2'); + unicode-range: U+0370-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 400; + src: url("/fonts/Inter.woff2") format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 400; + src: url("/fonts/Inter.woff2") format('woff2'); + unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 400; + src: url("/fonts/Inter.woff2") format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 500; + src: url("/fonts/Inter.woff2") format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 500; + src: url("/fonts/Inter.woff2") format('woff2'); + unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 500; + src: url("/fonts/Inter.woff2") format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 500; + src: url("/fonts/Inter.woff2") format('woff2'); + unicode-range: U+0370-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 500; + src: url() format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 500; + src: url("/fonts/Inter.woff2") format('woff2'); + unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 500; + src: url("/fonts/Inter.woff2") format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 600; + src: url("/fonts/Inter.woff2") format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 600; + src: url("/fonts/Inter.woff2") format('woff2'); + unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 600; + src: url("/fonts/Inter.woff2") format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 600; + src: url("/fonts/Inter.woff2") format('woff2'); + unicode-range: U+0370-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 600; + src: url("/fonts/Inter.woff2") format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 600; + src: url("/fonts/Inter.woff2") format('woff2'); + unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 600; + src: url() format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 700; + src: url("/fonts/Inter.woff2") format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 700; + src: url("/fonts/Inter.woff2") format('woff2'); + unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 700; + src: url("/fonts/Inter.woff2") format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 700; + src: url("/fonts/Inter.woff2") format('woff2'); + unicode-range: U+0370-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 700; + src: url("/fonts/Inter.woff2") format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 700; + src: url("/fonts/Inter.woff2") format('woff2'); + unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 700; + src: url("/fonts/Inter.woff2") format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} \ No newline at end of file diff --git a/Moonlight/wwwroot/fonts/Inter.woff2 b/Moonlight/wwwroot/fonts/Inter.woff2 new file mode 100644 index 0000000..4025543 Binary files /dev/null and b/Moonlight/wwwroot/fonts/Inter.woff2 differ