From 6fb2f90cd821f923f782438c2549cbfd59f5f283 Mon Sep 17 00:00:00 2001 From: FrigaT Date: Mon, 13 Apr 2026 14:18:14 +0300 Subject: [PATCH] =?UTF-8?q?=D0=A3=D0=B4=D0=B0=D0=BB=D0=B5=D0=BD=D0=BE=20?= =?UTF-8?q?=D0=BB=D0=B8=D1=88=D0=BD=D0=B5=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- PlaylistShared.PWA2123/App.razor | 19 --- .../Layout/LoginDisplay.razor | 19 --- .../Layout/MainLayout.razor | 100 ---------------- .../Layout/MainLayout.razor.css | 77 ------------ PlaylistShared.PWA2123/Layout/NavMenu.razor | 9 -- .../Layout/RedirectToLogin.razor | 9 -- .../Pages/AuthCallback.razor | 24 ---- .../Pages/Authentication.razor | 7 -- PlaylistShared.PWA2123/Pages/Counter.razor | 18 --- PlaylistShared.PWA2123/Pages/Home.razor | 18 --- PlaylistShared.PWA2123/Pages/Login.razor | 52 --------- .../Pages/LoginDisplay.razor | 11 -- PlaylistShared.PWA2123/Pages/Logout.razor | 12 -- PlaylistShared.PWA2123/Pages/NotFound.razor | 9 -- PlaylistShared.PWA2123/Pages/Weather.razor | 52 --------- .../PlaylistShared.PWA.csproj | 25 ---- PlaylistShared.PWA2123/Program.cs | 36 ------ .../Properties/launchSettings.json | 15 --- PlaylistShared.PWA2123/Services/ApiClient.cs | 77 ------------ .../Services/AuthStateProvider.cs | 99 ---------------- .../Services/TokenStorage.cs | 31 ----- PlaylistShared.PWA2123/_Imports.razor | 13 --- .../wwwroot/appsettings.Development.json | 6 - .../wwwroot/appsettings.json | 6 - PlaylistShared.PWA2123/wwwroot/css/app.css | 110 ------------------ PlaylistShared.PWA2123/wwwroot/favicon.png | Bin 2588 -> 0 bytes PlaylistShared.PWA2123/wwwroot/icon-192.png | Bin 8799 -> 0 bytes PlaylistShared.PWA2123/wwwroot/icon-512.png | Bin 23883 -> 0 bytes PlaylistShared.PWA2123/wwwroot/index.html | 41 ------- .../wwwroot/manifest.webmanifest | 22 ---- .../wwwroot/sample-data/weather.json | 27 ----- .../wwwroot/service-worker.js | 4 - .../wwwroot/service-worker.published.js | 55 --------- 33 files changed, 1003 deletions(-) delete mode 100644 PlaylistShared.PWA2123/App.razor delete mode 100644 PlaylistShared.PWA2123/Layout/LoginDisplay.razor delete mode 100644 PlaylistShared.PWA2123/Layout/MainLayout.razor delete mode 100644 PlaylistShared.PWA2123/Layout/MainLayout.razor.css delete mode 100644 PlaylistShared.PWA2123/Layout/NavMenu.razor delete mode 100644 PlaylistShared.PWA2123/Layout/RedirectToLogin.razor delete mode 100644 PlaylistShared.PWA2123/Pages/AuthCallback.razor delete mode 100644 PlaylistShared.PWA2123/Pages/Authentication.razor delete mode 100644 PlaylistShared.PWA2123/Pages/Counter.razor delete mode 100644 PlaylistShared.PWA2123/Pages/Home.razor delete mode 100644 PlaylistShared.PWA2123/Pages/Login.razor delete mode 100644 PlaylistShared.PWA2123/Pages/LoginDisplay.razor delete mode 100644 PlaylistShared.PWA2123/Pages/Logout.razor delete mode 100644 PlaylistShared.PWA2123/Pages/NotFound.razor delete mode 100644 PlaylistShared.PWA2123/Pages/Weather.razor delete mode 100644 PlaylistShared.PWA2123/PlaylistShared.PWA.csproj delete mode 100644 PlaylistShared.PWA2123/Program.cs delete mode 100644 PlaylistShared.PWA2123/Properties/launchSettings.json delete mode 100644 PlaylistShared.PWA2123/Services/ApiClient.cs delete mode 100644 PlaylistShared.PWA2123/Services/AuthStateProvider.cs delete mode 100644 PlaylistShared.PWA2123/Services/TokenStorage.cs delete mode 100644 PlaylistShared.PWA2123/_Imports.razor delete mode 100644 PlaylistShared.PWA2123/wwwroot/appsettings.Development.json delete mode 100644 PlaylistShared.PWA2123/wwwroot/appsettings.json delete mode 100644 PlaylistShared.PWA2123/wwwroot/css/app.css delete mode 100644 PlaylistShared.PWA2123/wwwroot/favicon.png delete mode 100644 PlaylistShared.PWA2123/wwwroot/icon-192.png delete mode 100644 PlaylistShared.PWA2123/wwwroot/icon-512.png delete mode 100644 PlaylistShared.PWA2123/wwwroot/index.html delete mode 100644 PlaylistShared.PWA2123/wwwroot/manifest.webmanifest delete mode 100644 PlaylistShared.PWA2123/wwwroot/sample-data/weather.json delete mode 100644 PlaylistShared.PWA2123/wwwroot/service-worker.js delete mode 100644 PlaylistShared.PWA2123/wwwroot/service-worker.published.js diff --git a/PlaylistShared.PWA2123/App.razor b/PlaylistShared.PWA2123/App.razor deleted file mode 100644 index 34eb91e..0000000 --- a/PlaylistShared.PWA2123/App.razor +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - @if (context.User.Identity?.IsAuthenticated != true) - { - - } - else - { -

You are not authorized to access this resource.

- } -
-
- -
-
-
diff --git a/PlaylistShared.PWA2123/Layout/LoginDisplay.razor b/PlaylistShared.PWA2123/Layout/LoginDisplay.razor deleted file mode 100644 index 21b0d19..0000000 --- a/PlaylistShared.PWA2123/Layout/LoginDisplay.razor +++ /dev/null @@ -1,19 +0,0 @@ -@using Microsoft.AspNetCore.Components.WebAssembly.Authentication -@inject NavigationManager Navigation - - - - Hello, @context.User.Identity?.Name! - Log out - - - Log in - - - -@code{ - public void BeginLogOut() - { - Navigation.NavigateToLogout("authentication/logout"); - } -} diff --git a/PlaylistShared.PWA2123/Layout/MainLayout.razor b/PlaylistShared.PWA2123/Layout/MainLayout.razor deleted file mode 100644 index 3cd4ef5..0000000 --- a/PlaylistShared.PWA2123/Layout/MainLayout.razor +++ /dev/null @@ -1,100 +0,0 @@ -@inherits LayoutComponentBase - - - - - - - - - - Application - - - - - About - - - - - - - - - @Body - - - -@code { - private bool _drawerOpen = true; - private bool _isDarkMode = true; - private MudTheme? _theme; - - protected override void OnInitialized() - { - base.OnInitialized(); - - _theme = new() - { - PaletteLight = _lightPalette, - PaletteDark = _darkPalette, - LayoutProperties = new LayoutProperties() - }; - } - - private void DrawerToggle() - { - _drawerOpen = !_drawerOpen; - } - - private void DarkModeToggle() - { - _isDarkMode = !_isDarkMode; - } - - private readonly PaletteLight _lightPalette = new() - { - Black = "#110e2d", - AppbarText = "#424242", - AppbarBackground = "rgba(255,255,255,0.8)", - DrawerBackground = "#ffffff", - GrayLight = "#e8e8e8", - GrayLighter = "#f9f9f9", - }; - - private readonly PaletteDark _darkPalette = new() - { - Primary = "#7e6fff", - Surface = "#1e1e2d", - Background = "#1a1a27", - BackgroundGray = "#151521", - AppbarText = "#92929f", - AppbarBackground = "rgba(26,26,39,0.8)", - DrawerBackground = "#1a1a27", - ActionDefault = "#74718e", - ActionDisabled = "#9999994d", - ActionDisabledBackground = "#605f6d4d", - TextPrimary = "#b2b0bf", - TextSecondary = "#92929f", - TextDisabled = "#ffffff33", - DrawerIcon = "#92929f", - DrawerText = "#92929f", - GrayLight = "#2a2833", - GrayLighter = "#1e1e2d", - Info = "#4a86ff", - Success = "#3dcb6c", - Warning = "#ffb545", - Error = "#ff3f5f", - LinesDefault = "#33323e", - TableLines = "#33323e", - Divider = "#292838", - OverlayLight = "#1e1e2d80", - }; - - public string DarkLightModeButtonIcon => _isDarkMode switch - { - true => Icons.Material.Rounded.AutoMode, - false => Icons.Material.Outlined.DarkMode, - }; -} diff --git a/PlaylistShared.PWA2123/Layout/MainLayout.razor.css b/PlaylistShared.PWA2123/Layout/MainLayout.razor.css deleted file mode 100644 index ecf25e5..0000000 --- a/PlaylistShared.PWA2123/Layout/MainLayout.razor.css +++ /dev/null @@ -1,77 +0,0 @@ -.page { - position: relative; - display: flex; - flex-direction: column; -} - -main { - flex: 1; -} - -.sidebar { - background-image: linear-gradient(180deg, rgb(5, 39, 103) 0%, #3a0647 70%); -} - -.top-row { - background-color: #f7f7f7; - border-bottom: 1px solid #d6d5d5; - justify-content: flex-end; - height: 3.5rem; - display: flex; - align-items: center; -} - - .top-row ::deep a, .top-row ::deep .btn-link { - white-space: nowrap; - margin-left: 1.5rem; - text-decoration: none; - } - - .top-row ::deep a:hover, .top-row ::deep .btn-link:hover { - text-decoration: underline; - } - - .top-row ::deep a:first-child { - overflow: hidden; - text-overflow: ellipsis; - } - -@media (max-width: 640.98px) { - .top-row { - justify-content: space-between; - } - - .top-row ::deep a, .top-row ::deep .btn-link { - margin-left: 0; - } -} - -@media (min-width: 641px) { - .page { - flex-direction: row; - } - - .sidebar { - width: 250px; - height: 100vh; - position: sticky; - top: 0; - } - - .top-row { - position: sticky; - top: 0; - z-index: 1; - } - - .top-row.auth ::deep a:first-child { - flex: 1; - text-align: right; - width: 0; - } - - .top-row, article { - padding-left: 2rem !important; - padding-right: 1.5rem !important; - } -} diff --git a/PlaylistShared.PWA2123/Layout/NavMenu.razor b/PlaylistShared.PWA2123/Layout/NavMenu.razor deleted file mode 100644 index fba6968..0000000 --- a/PlaylistShared.PWA2123/Layout/NavMenu.razor +++ /dev/null @@ -1,9 +0,0 @@ - - Home - - - Создать плейлист - Мои ссылки - - - \ No newline at end of file diff --git a/PlaylistShared.PWA2123/Layout/RedirectToLogin.razor b/PlaylistShared.PWA2123/Layout/RedirectToLogin.razor deleted file mode 100644 index a1cf400..0000000 --- a/PlaylistShared.PWA2123/Layout/RedirectToLogin.razor +++ /dev/null @@ -1,9 +0,0 @@ -@using Microsoft.AspNetCore.Components.WebAssembly.Authentication -@inject NavigationManager Navigation - -@code { - protected override void OnInitialized() - { - Navigation.NavigateToLogin("authentication/login"); - } -} diff --git a/PlaylistShared.PWA2123/Pages/AuthCallback.razor b/PlaylistShared.PWA2123/Pages/AuthCallback.razor deleted file mode 100644 index a0493a3..0000000 --- a/PlaylistShared.PWA2123/Pages/AuthCallback.razor +++ /dev/null @@ -1,24 +0,0 @@ -@page "/auth-callback" -@using PlaylistShared.PWA.Services -@inject NavigationManager Navigation -@inject AuthStateProvider AuthProvider -@inject ISnackbar Snackbar - -@code { - [Parameter] public string? Token { get; set; } - [Parameter] public string? RefreshToken { get; set; } - - protected override async Task OnInitializedAsync() - { - if (!string.IsNullOrEmpty(Token) && !string.IsNullOrEmpty(RefreshToken)) - { - await AuthProvider.MarkUserAsAuthenticated(Token, RefreshToken); - Navigation.NavigateTo("/"); - } - else - { - Snackbar.Add("Ошибка аутентификации через Яндекс", Severity.Error); - Navigation.NavigateTo("/login"); - } - } -} \ No newline at end of file diff --git a/PlaylistShared.PWA2123/Pages/Authentication.razor b/PlaylistShared.PWA2123/Pages/Authentication.razor deleted file mode 100644 index 6c74356..0000000 --- a/PlaylistShared.PWA2123/Pages/Authentication.razor +++ /dev/null @@ -1,7 +0,0 @@ -@page "/authentication/{action}" -@using Microsoft.AspNetCore.Components.WebAssembly.Authentication - - -@code{ - [Parameter] public string? Action { get; set; } -} diff --git a/PlaylistShared.PWA2123/Pages/Counter.razor b/PlaylistShared.PWA2123/Pages/Counter.razor deleted file mode 100644 index b7be219..0000000 --- a/PlaylistShared.PWA2123/Pages/Counter.razor +++ /dev/null @@ -1,18 +0,0 @@ -@page "/counter" - -Counter - -Counter - -Current count: @currentCount - -Click me - -@code { - private int currentCount = 0; - - private void IncrementCount() - { - currentCount++; - } -} diff --git a/PlaylistShared.PWA2123/Pages/Home.razor b/PlaylistShared.PWA2123/Pages/Home.razor deleted file mode 100644 index 7721bf2..0000000 --- a/PlaylistShared.PWA2123/Pages/Home.razor +++ /dev/null @@ -1,18 +0,0 @@ -@page "/" - -Home - -Hello, world! -Welcome to your new app, powered by MudBlazor and the .NET 10 Template! - - - Before authentication will function correctly, you must configure your provider details in Program.cs. - - - - - You can find documentation and examples on our website here: - - www.mudblazor.com - - diff --git a/PlaylistShared.PWA2123/Pages/Login.razor b/PlaylistShared.PWA2123/Pages/Login.razor deleted file mode 100644 index a7f8e97..0000000 --- a/PlaylistShared.PWA2123/Pages/Login.razor +++ /dev/null @@ -1,52 +0,0 @@ -@page "/login" -@using PlaylistShared.PWA.Services -@inject NavigationManager Navigation -@inject AuthStateProvider AuthProvider -@inject ApiClient ApiClient -@inject ISnackbar Snackbar - - - - - Вход в PlaylistShared - - - Войти через Яндекс - - - или - - - - Войти по паролю - - - Нет аккаунта? Зарегистрироваться - - - - - -@code { - private string _username = ""; - private string _password = ""; - - private void LoginWithYandex() - { - Navigation.NavigateTo("https://localhost:5001/api/externalauth/login-yandex", true); - } - - private async Task LoginWithPassword() - { - var result = await ApiClient.LoginAsync(_username, _password); - if (result != null) - { - await AuthProvider.MarkUserAsAuthenticated(result.Token, result.RefreshToken); - Navigation.NavigateTo("/"); - } - else - { - Snackbar.Add("Неверный логин или пароль", Severity.Error); - } - } -} \ No newline at end of file diff --git a/PlaylistShared.PWA2123/Pages/LoginDisplay.razor b/PlaylistShared.PWA2123/Pages/LoginDisplay.razor deleted file mode 100644 index 608f18d..0000000 --- a/PlaylistShared.PWA2123/Pages/LoginDisplay.razor +++ /dev/null @@ -1,11 +0,0 @@ -@inject NavigationManager Navigation - - - - Hello, @context.User.Identity?.Name! - Log out - - - Log in - - \ No newline at end of file diff --git a/PlaylistShared.PWA2123/Pages/Logout.razor b/PlaylistShared.PWA2123/Pages/Logout.razor deleted file mode 100644 index da74e30..0000000 --- a/PlaylistShared.PWA2123/Pages/Logout.razor +++ /dev/null @@ -1,12 +0,0 @@ -@page "/logout" -@using PlaylistShared.PWA.Services -@inject AuthStateProvider AuthProvider -@inject NavigationManager Navigation - -@code { - protected override async Task OnInitializedAsync() - { - await AuthProvider.MarkUserAsLoggedOut(); - Navigation.NavigateTo("/"); - } -} \ No newline at end of file diff --git a/PlaylistShared.PWA2123/Pages/NotFound.razor b/PlaylistShared.PWA2123/Pages/NotFound.razor deleted file mode 100644 index 56c8cc4..0000000 --- a/PlaylistShared.PWA2123/Pages/NotFound.razor +++ /dev/null @@ -1,9 +0,0 @@ -@page "/not-found" -@layout MainLayout - -Not Found - -404 - Page Not Found -Sorry, the content you are looking for does not exist. - -Go to Home diff --git a/PlaylistShared.PWA2123/Pages/Weather.razor b/PlaylistShared.PWA2123/Pages/Weather.razor deleted file mode 100644 index 242bcf3..0000000 --- a/PlaylistShared.PWA2123/Pages/Weather.razor +++ /dev/null @@ -1,52 +0,0 @@ -@page "/weather" -@inject HttpClient Http - -Weather - -Weather forecast -This component demonstrates fetching data from the server. - -@if (forecasts == null) -{ - -} -else -{ - - - Date - Temp. (C) - Temp. (F) - Summary - - - @context.Date - @context.TemperatureC - @context.TemperatureF - @context.Summary - - - - - -} - -@code { - private WeatherForecast[]? forecasts; - - protected override async Task OnInitializedAsync() - { - forecasts = await Http.GetFromJsonAsync("sample-data/weather.json"); - } - - public class WeatherForecast - { - public DateOnly Date { get; set; } - - public int TemperatureC { get; set; } - - public string? Summary { get; set; } - - public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); - } -} diff --git a/PlaylistShared.PWA2123/PlaylistShared.PWA.csproj b/PlaylistShared.PWA2123/PlaylistShared.PWA.csproj deleted file mode 100644 index 3f89db1..0000000 --- a/PlaylistShared.PWA2123/PlaylistShared.PWA.csproj +++ /dev/null @@ -1,25 +0,0 @@ - - - - net10.0 - enable - enable - true - service-worker-assets.js - - - - - - - - - - - - - - - - - diff --git a/PlaylistShared.PWA2123/Program.cs b/PlaylistShared.PWA2123/Program.cs deleted file mode 100644 index 60c51ca..0000000 --- a/PlaylistShared.PWA2123/Program.cs +++ /dev/null @@ -1,36 +0,0 @@ -using Microsoft.AspNetCore.Components.Web; -using Microsoft.AspNetCore.Components.WebAssembly.Hosting; -using MudBlazor.Services; -using PlaylistShared.PWA; -using PlaylistShared.PWA.Services; - -internal class Program -{ - private static async global::System.Threading.Tasks.Task Main(string[] args) - { - var builder = WebAssemblyHostBuilder.CreateDefault(args); - builder.RootComponents.Add("#app"); - builder.RootComponents.Add("head::after"); - - builder.Services.AddMudServices(); - builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) }); - - builder.Services.AddScoped(); - builder.Services.AddScoped(); - builder.Services.AddScoped(); - - builder.Services.AddAuthorizationCore(); - builder.Services.AddCascadingAuthenticationState(); - - /* - builder.Services.AddOidcAuthentication(options => - { - // Configure your authentication provider options here. - // For more information, see https://aka.ms/blazor-standalone-auth - builder.Configuration.Bind("Local", options.ProviderOptions); - }); - */ - - await builder.Build().RunAsync(); - } -} \ No newline at end of file diff --git a/PlaylistShared.PWA2123/Properties/launchSettings.json b/PlaylistShared.PWA2123/Properties/launchSettings.json deleted file mode 100644 index 4adf325..0000000 --- a/PlaylistShared.PWA2123/Properties/launchSettings.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "$schema": "https://json.schemastore.org/launchsettings.json", - "profiles": { - "https": { - "commandName": "Project", - "dotnetRunMessages": true, - "launchBrowser": true, - "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", - "applicationUrl": "https://localhost:7244;http://localhost:5143", - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - } - } -} diff --git a/PlaylistShared.PWA2123/Services/ApiClient.cs b/PlaylistShared.PWA2123/Services/ApiClient.cs deleted file mode 100644 index c0afbbb..0000000 --- a/PlaylistShared.PWA2123/Services/ApiClient.cs +++ /dev/null @@ -1,77 +0,0 @@ -using PlaylistShared.Shared.DTO; -using PlaylistShared.Shared.Models; -using System.Net.Http.Json; - -namespace PlaylistShared.PWA.Services; - -public class ApiClient -{ - private readonly HttpClient _http; - private readonly TokenStorage _tokenStorage; - - public ApiClient(HttpClient http, TokenStorage tokenStorage) - { - _http = http; - _tokenStorage = tokenStorage; - } - - public async Task RefreshTokenAsync(string? refreshToken) - { - var response = await _http.PostAsJsonAsync("/api/account/refresh-token", new RefreshTokenRequest { RefreshToken = refreshToken }); - if (!response.IsSuccessStatusCode) return null; - var apiResponse = await response.Content.ReadFromJsonAsync>(); - return apiResponse?.Data; - } - - public async Task LoginAsync(string username, string password) - { - var response = await _http.PostAsJsonAsync("/api/account/login", new LoginRequest { Username = username, Password = password }); - if (!response.IsSuccessStatusCode) return null; - var apiResponse = await response.Content.ReadFromJsonAsync>(); - return apiResponse?.Data; - } - - public async Task RegisterAsync(string username, string email, string password) - { - var response = await _http.PostAsJsonAsync("/api/account/register", new RegisterRequest { Username = username, Email = email, Password = password }); - if (!response.IsSuccessStatusCode) return null; - var apiResponse = await response.Content.ReadFromJsonAsync>(); - return apiResponse?.Data; - } - - public async Task CreateSharedPlaylistAsync(SharePlaylistDto dto) - { - var response = await _http.PostAsJsonAsync("/api/sharedplaylist", dto); - if (!response.IsSuccessStatusCode) return null; - var apiResponse = await response.Content.ReadFromJsonAsync>(); - return apiResponse?.Data; - } - - public async Task GetSharedPlaylistAsync(string token) - { - var response = await _http.GetAsync($"/api/sharedplaylist/{token}"); - if (!response.IsSuccessStatusCode) return null; - var apiResponse = await response.Content.ReadFromJsonAsync>(); - return apiResponse?.Data; - } - - public async Task AddTracksAsync(string sharedPlaylistToken, List trackIds) - { - var response = await _http.PostAsJsonAsync("/api/playlist/add-tracks", new AddTrackRequest - { - SharedPlaylistToken = sharedPlaylistToken, - TrackIds = trackIds - }); - return response.IsSuccessStatusCode; - } - - public async Task RemoveTracksAsync(string sharedPlaylistToken, List trackIds) - { - var response = await _http.PostAsJsonAsync("/api/playlist/remove-tracks", new AddTrackRequest - { - SharedPlaylistToken = sharedPlaylistToken, - TrackIds = trackIds - }); - return response.IsSuccessStatusCode; - } -} \ No newline at end of file diff --git a/PlaylistShared.PWA2123/Services/AuthStateProvider.cs b/PlaylistShared.PWA2123/Services/AuthStateProvider.cs deleted file mode 100644 index 538d115..0000000 --- a/PlaylistShared.PWA2123/Services/AuthStateProvider.cs +++ /dev/null @@ -1,99 +0,0 @@ -using System.Net.Http.Headers; -using System.Security.Claims; - -namespace PlaylistShared.PWA.Services; - -public class AuthStateProvider : AuthenticationStateProvider, IDisposable -{ - private readonly TokenStorage _tokenStorage; - private readonly ApiClient _apiClient; - private readonly HttpClient _http; - private Timer? _refreshTimer; - private ClaimsPrincipal _currentUser = new(new ClaimsIdentity()); - - public AuthStateProvider(TokenStorage tokenStorage, ApiClient apiClient, HttpClient http) - { - _tokenStorage = tokenStorage; - _apiClient = apiClient; - _http = http; - } - - public override async Task GetAuthenticationStateAsync() - { - var (token, refreshToken) = await _tokenStorage.GetTokensAsync(); - if (string.IsNullOrEmpty(token)) - return new AuthenticationState(_currentUser); - - var principal = ParseToken(token); - if (principal == null) - return new AuthenticationState(_currentUser); - - _currentUser = principal; - _http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); - ScheduleTokenRefresh(token, refreshToken); - return new AuthenticationState(principal); - } - - public async Task MarkUserAsAuthenticated(string token, string refreshToken) - { - await _tokenStorage.SetTokensAsync(token, refreshToken); - var principal = ParseToken(token); - _currentUser = principal ?? new ClaimsPrincipal(new ClaimsIdentity()); - _http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); - NotifyAuthenticationStateChanged(GetAuthenticationStateAsync()); - } - - public async Task MarkUserAsLoggedOut() - { - await _tokenStorage.ClearTokensAsync(); - _currentUser = new ClaimsPrincipal(new ClaimsIdentity()); - _http.DefaultRequestHeaders.Authorization = null; - NotifyAuthenticationStateChanged(GetAuthenticationStateAsync()); - } - - private ClaimsPrincipal? ParseToken(string token) - { - try - { - var handler = new JwtSecurityTokenHandler(); - var jwt = handler.ReadJwtToken(token); - var identity = new ClaimsIdentity(jwt.Claims, "jwt"); - return new ClaimsPrincipal(identity); - } - catch - { - return null; - } - } - - private void ScheduleTokenRefresh(string token, string? refreshToken) - { - var handler = new JwtSecurityTokenHandler(); - var jwt = handler.ReadJwtToken(token); - var expiresAt = jwt.ValidTo; - var timeToExpiry = expiresAt - DateTime.UtcNow; - var refreshTime = timeToExpiry - TimeSpan.FromMinutes(5); - - if (refreshTime > TimeSpan.Zero && !string.IsNullOrEmpty(refreshToken)) - { - _refreshTimer?.Dispose(); - _refreshTimer = new Timer(async _ => - { - try - { - var newToken = await _apiClient.RefreshTokenAsync(refreshToken); - if (newToken != null) - await MarkUserAsAuthenticated(newToken.Token, newToken.RefreshToken); - else - await MarkUserAsLoggedOut(); - } - catch - { - await MarkUserAsLoggedOut(); - } - }, null, (int)refreshTime.TotalMilliseconds, Timeout.Infinite); - } - } - - public void Dispose() => _refreshTimer?.Dispose(); -} \ No newline at end of file diff --git a/PlaylistShared.PWA2123/Services/TokenStorage.cs b/PlaylistShared.PWA2123/Services/TokenStorage.cs deleted file mode 100644 index bcc7277..0000000 --- a/PlaylistShared.PWA2123/Services/TokenStorage.cs +++ /dev/null @@ -1,31 +0,0 @@ -using Microsoft.JSInterop; - -namespace PlaylistShared.PWA.Services; - -public class TokenStorage -{ - private readonly IJSRuntime _js; - private const string TokenKey = "jwt_token"; - private const string RefreshTokenKey = "refresh_token"; - - public TokenStorage(IJSRuntime js) => _js = js; - - public async Task SetTokensAsync(string token, string refreshToken) - { - await _js.InvokeVoidAsync("localStorage.setItem", TokenKey, token); - await _js.InvokeVoidAsync("localStorage.setItem", RefreshTokenKey, refreshToken); - } - - public async Task<(string? token, string? refreshToken)> GetTokensAsync() - { - var token = await _js.InvokeAsync("localStorage.getItem", TokenKey); - var refreshToken = await _js.InvokeAsync("localStorage.getItem", RefreshTokenKey); - return (token, refreshToken); - } - - public async Task ClearTokensAsync() - { - await _js.InvokeVoidAsync("localStorage.removeItem", TokenKey); - await _js.InvokeVoidAsync("localStorage.removeItem", RefreshTokenKey); - } -} \ No newline at end of file diff --git a/PlaylistShared.PWA2123/_Imports.razor b/PlaylistShared.PWA2123/_Imports.razor deleted file mode 100644 index 4278aa7..0000000 --- a/PlaylistShared.PWA2123/_Imports.razor +++ /dev/null @@ -1,13 +0,0 @@ -@using System.Net.Http -@using System.Net.Http.Json -@using Microsoft.AspNetCore.Components.Authorization -@using Microsoft.AspNetCore.Components.Forms -@using Microsoft.AspNetCore.Components.Routing -@using Microsoft.AspNetCore.Components.Web -@using Microsoft.AspNetCore.Components.Web.Virtualization -@using Microsoft.AspNetCore.Components.WebAssembly.Http -@using Microsoft.JSInterop -@using PlaylistShared.PWA -@using PlaylistShared.PWA.Layout -@using PlaylistShared.PWA.Services -@using MudBlazor diff --git a/PlaylistShared.PWA2123/wwwroot/appsettings.Development.json b/PlaylistShared.PWA2123/wwwroot/appsettings.Development.json deleted file mode 100644 index fdae94a..0000000 --- a/PlaylistShared.PWA2123/wwwroot/appsettings.Development.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "Local": { - "Authority": "https://login.microsoftonline.com/", - "ClientId": "33333333-3333-3333-33333333333333333" - } -} diff --git a/PlaylistShared.PWA2123/wwwroot/appsettings.json b/PlaylistShared.PWA2123/wwwroot/appsettings.json deleted file mode 100644 index fdae94a..0000000 --- a/PlaylistShared.PWA2123/wwwroot/appsettings.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "Local": { - "Authority": "https://login.microsoftonline.com/", - "ClientId": "33333333-3333-3333-33333333333333333" - } -} diff --git a/PlaylistShared.PWA2123/wwwroot/css/app.css b/PlaylistShared.PWA2123/wwwroot/css/app.css deleted file mode 100644 index e24afa9..0000000 --- a/PlaylistShared.PWA2123/wwwroot/css/app.css +++ /dev/null @@ -1,110 +0,0 @@ -html, body { - font-family: 'Roboto', Helvetica, Arial, sans-serif; -} - -#blazor-error-ui { - color-scheme: light; - background: rgba(30, 30, 45, 0.95); - color: #f5f5f7; - border: 1px solid rgba(255, 255, 255, 0.08); - border-radius: 12px; - box-shadow: 0 12px 32px rgba(0, 0, 0, 0.35); - backdrop-filter: blur(6px); - box-sizing: border-box; - display: none; - left: 50%; - right: auto; - bottom: 1rem; - width: min(52rem, calc(100vw - 2rem)); - transform: translateX(-50%); - padding: 0.85rem 4rem 0.85rem 1rem; - position: fixed; - z-index: 2000; -} - - #blazor-error-ui .reload { - color: #594AE2; - font-weight: 600; - margin-left: 0.5rem; - text-decoration: none; - } - - #blazor-error-ui .reload:hover { - text-decoration: underline; - } - - #blazor-error-ui .dismiss { - cursor: pointer; - position: absolute; - right: 1rem; - top: 0.55rem; - width: 1.75rem; - height: 1.75rem; - line-height: 1.65rem; - text-align: center; - border-radius: 999px; - color: #d7d7df; - background: rgba(255, 255, 255, 0.06); - border: 1px solid rgba(255, 255, 255, 0.08); - } - - #blazor-error-ui .dismiss:hover { - background: rgba(255, 255, 255, 0.12); - } - -.blazor-error-boundary { - background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121; - padding: 1rem 1rem 1rem 3.7rem; - color: white; -} - - .blazor-error-boundary::after { - content: "An error has occurred." - } - -.loading-progress { - position: absolute; - display: block; - width: 8rem; - height: 8rem; - inset: 20vh 0 auto 0; - margin: 0 auto 0 auto; -} - - .loading-progress circle { - fill: none; - stroke: #e0e0e0; - stroke-width: 0.6rem; - transform-origin: 50% 50%; - transform: rotate(-90deg); - } - - .loading-progress circle:last-child { - stroke: #594AE2; - stroke-dasharray: calc(3.141 * var(--blazor-load-percentage, 0%) * 0.8), 500%; - transition: stroke-dasharray 0.05s ease-in-out; - } - -.loading-progress-text { - position: absolute; - text-align: center; - font-weight: bold; - inset: calc(20vh + 3.25rem) 0 auto 0.2rem; -} - - .loading-progress-text:after { - content: var(--blazor-load-percentage-text, "Loading"); - } - -code { - color: #c02d76; -} - -.form-floating > .form-control-plaintext::placeholder, .form-floating > .form-control::placeholder { - color: var(--bs-secondary-color); - text-align: end; -} - -.form-floating > .form-control-plaintext:focus::placeholder, .form-floating > .form-control:focus::placeholder { - text-align: start; -} diff --git a/PlaylistShared.PWA2123/wwwroot/favicon.png b/PlaylistShared.PWA2123/wwwroot/favicon.png deleted file mode 100644 index 8a4358cf0d7c5dfe0e7ac5838351ba6b055995cc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2588 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 diff --git a/PlaylistShared.PWA2123/wwwroot/icon-512.png b/PlaylistShared.PWA2123/wwwroot/icon-512.png deleted file mode 100644 index 2326ede971cbe512169beb919954173c071108c2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 23883 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 - - - - - - PlaylistShared.PWA - - - - - - - - - - - - - - -

- - - - -
-
- -
- An unhandled error has occurred. - Reload - 🗙 -
- - - - - - - diff --git a/PlaylistShared.PWA2123/wwwroot/manifest.webmanifest b/PlaylistShared.PWA2123/wwwroot/manifest.webmanifest deleted file mode 100644 index 5496339..0000000 --- a/PlaylistShared.PWA2123/wwwroot/manifest.webmanifest +++ /dev/null @@ -1,22 +0,0 @@ -{ - "name": "PlaylistShared.PWA", - "short_name": "PlaylistShared.PWA", - "id": "./", - "start_url": "./", - "display": "standalone", - "background_color": "#ffffff", - "theme_color": "#03173d", - "prefer_related_applications": false, - "icons": [ - { - "src": "icon-512.png", - "type": "image/png", - "sizes": "512x512" - }, - { - "src": "icon-192.png", - "type": "image/png", - "sizes": "192x192" - } - ] -} diff --git a/PlaylistShared.PWA2123/wwwroot/sample-data/weather.json b/PlaylistShared.PWA2123/wwwroot/sample-data/weather.json deleted file mode 100644 index b745973..0000000 --- a/PlaylistShared.PWA2123/wwwroot/sample-data/weather.json +++ /dev/null @@ -1,27 +0,0 @@ -[ - { - "date": "2022-01-06", - "temperatureC": 1, - "summary": "Freezing" - }, - { - "date": "2022-01-07", - "temperatureC": 14, - "summary": "Bracing" - }, - { - "date": "2022-01-08", - "temperatureC": -13, - "summary": "Freezing" - }, - { - "date": "2022-01-09", - "temperatureC": -16, - "summary": "Balmy" - }, - { - "date": "2022-01-10", - "temperatureC": -2, - "summary": "Chilly" - } -] diff --git a/PlaylistShared.PWA2123/wwwroot/service-worker.js b/PlaylistShared.PWA2123/wwwroot/service-worker.js deleted file mode 100644 index fe614da..0000000 --- a/PlaylistShared.PWA2123/wwwroot/service-worker.js +++ /dev/null @@ -1,4 +0,0 @@ -// 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/PlaylistShared.PWA2123/wwwroot/service-worker.published.js b/PlaylistShared.PWA2123/wwwroot/service-worker.published.js deleted file mode 100644 index 51a0e5c..0000000 --- a/PlaylistShared.PWA2123/wwwroot/service-worker.published.js +++ /dev/null @@ -1,55 +0,0 @@ -// 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$/, /\.blat$/, /\.dat$/, /\.webmanifest$/ ]; -const offlineAssetsExclude = [ /^service-worker\.js$/ ]; - -// Replace with your base path if you are hosting on a subfolder. Ensure there is a trailing '/'. -const base = "/"; -const baseUrl = new URL(base, self.origin); -const manifestUrlList = self.assetsManifest.assets.map(asset => new URL(asset.url, baseUrl).href); - -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, cache: 'no-cache' })); - 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, - // unless that request is for an offline resource. - // If you need some URLs to be server-rendered, edit the following check to exclude those URLs - const shouldServeIndexHtml = event.request.mode === 'navigate' - && !manifestUrlList.some(url => url === event.request.url); - - const request = shouldServeIndexHtml ? 'index.html' : event.request; - const cache = await caches.open(cacheName); - cachedResponse = await cache.match(request); - } - - return cachedResponse || fetch(event.request); -}