diff --git a/PlaylistShared.Pwa/Components/Global/AudioPlayer.razor b/PlaylistShared.Pwa/Components/Global/AudioPlayer.razor
index d4534b2..fcc78cc 100644
--- a/PlaylistShared.Pwa/Components/Global/AudioPlayer.razor
+++ b/PlaylistShared.Pwa/Components/Global/AudioPlayer.razor
@@ -8,20 +8,20 @@
@inject HttpClient Http
-
+
{ _isPlayHovered = true; }"
@onmouseleave="() => { _isPlayHovered = false; }"
- Class="relative d-inline-block rounded-sm overflow-hidden"
- style="cursor: pointer; width: 50px; height: 50px;">
+ Class="relative d-inline-block rounded-sm overflow-hidden cursor-pointer"
+ Style="width: 50px; height: 50px;">
@if (!string.IsNullOrEmpty(AudioPlayerService.CurrentTrack?.CoverUri))
{
-
+
}
-
+
@if (AudioPlayerService.CurrentTrack != null)
{
-
+
-
+
@AudioPlayerService.CurrentTrack.Title
@@ -61,8 +61,8 @@
-
- @AudioPlayerService.CurrentTimeString / @AudioPlayerService.TotalTimeString
+
+ @AudioPlayerService.CurrentTimeString
@@ -71,28 +71,30 @@
{
}
-
-
- _volumeIsOpen = true"
- @onmouseleave="() => _volumeIsOpen = false"
- @onwheel="OnVolumeHandleWheel"
- Style="position: relative; display: flex; align-items: center;">
+
+
+
+ _volumeIsOpen = true"
+ @onmouseleave="() => _volumeIsOpen = false"
+ @onwheel="OnVolumeHandleWheel"
+ Style="position: relative; display: flex; align-items: center;">
-
+
-
-
+
+
-
-
+
+
+
@@ -123,6 +125,11 @@
AudioPlayerService.OnStateChanged += OnServiceStateChanged;
}
+ protected override void OnParametersSet()
+ {
+ StateHasChanged();
+ }
+
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
diff --git a/PlaylistShared.Pwa/Components/Global/ContextualBarContent.cs b/PlaylistShared.Pwa/Components/Global/ContextualBarContent.cs
new file mode 100644
index 0000000..598b41a
--- /dev/null
+++ b/PlaylistShared.Pwa/Components/Global/ContextualBarContent.cs
@@ -0,0 +1,30 @@
+using Microsoft.AspNetCore.Components;
+using PlaylistShared.Pwa.Services;
+
+namespace PlaylistShared.Pwa.Components.Global;
+
+public class ContextualBarContent : ComponentBase, IDisposable
+{
+ [Inject]
+ public ContextualActionBarService ContextualActionBarService { get; set; } = default!;
+
+ [Parameter]
+ public ContextualActionBarPosition Position { get; set; } = ContextualActionBarPosition.Default;
+
+ [Parameter]
+ public RenderFragment? ChildContent { get; set; }
+
+ protected override void OnParametersSet()
+ {
+ ContextualActionBarService.Content = ChildContent;
+ ContextualActionBarService.Position = Position;
+ ContextualActionBarService.ChangeParameters();
+ }
+
+ public void Dispose()
+ {
+ ContextualActionBarService.Content = null;
+ ContextualActionBarService.Position = ContextualActionBarPosition.Default;
+ ContextualActionBarService.ChangeParameters();
+ }
+}
\ No newline at end of file
diff --git a/PlaylistShared.Pwa/Components/Global/ContextualBarContent.razor b/PlaylistShared.Pwa/Components/Global/ContextualBarContent.razor
deleted file mode 100644
index 7bcb783..0000000
--- a/PlaylistShared.Pwa/Components/Global/ContextualBarContent.razor
+++ /dev/null
@@ -1,21 +0,0 @@
-@implements IDisposable
-@inject ContextualActionBarService ContextualActionBarService
-
-@code {
- [Parameter] public ContextualActionBarPosition Position { get; set; } = ContextualActionBarPosition.Default;
- [Parameter] public RenderFragment? ChildContent { get; set; }
-
- protected override void OnParametersSet()
- {
- ContextualActionBarService.Content = ChildContent;
- ContextualActionBarService.Position = Position;
- ContextualActionBarService.ChangeParameters();
- }
-
- public void Dispose()
- {
- ContextualActionBarService.Content = null;
- ContextualActionBarService.Position = ContextualActionBarPosition.Default;
- ContextualActionBarService.ChangeParameters();
- }
-}
\ No newline at end of file
diff --git a/PlaylistShared.Pwa/Components/SharedPlaylist/PlaylistHeader.razor b/PlaylistShared.Pwa/Components/SharedPlaylist/PlaylistHeader.razor
deleted file mode 100644
index 873ccde..0000000
--- a/PlaylistShared.Pwa/Components/SharedPlaylist/PlaylistHeader.razor
+++ /dev/null
@@ -1,165 +0,0 @@
-@using PlaylistShared.Pwa.Components.Common
-@using PlaylistShared.Shared.Enums
-@using System.Security.Claims
-@using PlaylistShared.Shared.SharedPlaylist
-@inject HttpClient Http
-@inject NavigationManager Navigation
-@inject AuthenticationStateProvider AuthProvider
-@inject ISnackbar Snackbar
-@inject IDialogService DialogService
-
-
- @if (!string.IsNullOrEmpty(Playlist?.CoverUrl))
- {
-
- }
-
-
-
- @Playlist?.Title
-
-
-
-
-
- @* ПК ВЕРСИЯ: Показываем все кнопки *@
-
-
-
- @if (_isCreator && _isAuthenticated)
- {
-
- }
-
-
- @* МОБИЛЬНАЯ ВЕРСИЯ: Уводим в многоточие *@
-
-
-
-
-
-
-
-
- @if (_isCreator && _isAuthenticated)
- {
-
-
- }
-
-
-
-
-
-
-@code {
- [Parameter] public SharedPlaylistDto? Playlist { get; set; }
- [Parameter] public EventCallback OnPermissionsChanged { get; set; }
-
- private bool _isAuthenticated;
- private bool _isCreator;
- private string? _currentUserId;
- private bool _isFavorite;
- private bool _favoriteLoading;
-
- protected override async Task OnInitializedAsync()
- {
- var authState = await AuthProvider.GetAuthenticationStateAsync();
- _isAuthenticated = authState.User.Identity?.IsAuthenticated == true;
- _currentUserId = authState.User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
- _isCreator = Playlist?.CreatorUserId.ToString() == _currentUserId;
- if (_isAuthenticated)
- {
- await CheckFavoriteStatus();
- }
- }
-
- private async Task CheckFavoriteStatus()
- {
- if (Playlist == null) return;
- try
- {
- var response = await Http.GetFromJsonAsync>($"/api/favorites/{Playlist.ShareToken}/check");
- if (response?.Success == true)
- _isFavorite = response.Data;
- }
- catch { }
- }
-
- private async Task ToggleFavorite()
- {
- if (Playlist == null) return;
-
- if (!_isAuthenticated)
- {
- Snackbar.Add("Добавление в избранное только авторизованным пользователям", Severity.Warning);
- return;
- }
-
- _favoriteLoading = true;
- try
- {
- if (_isFavorite)
- {
- var response = await Http.DeleteAsync($"/api/favorites/{Playlist.ShareToken}");
- if (response.IsSuccessStatusCode)
- {
- _isFavorite = false;
- Snackbar.Add("Плейлист удалён из избранного", Severity.Success);
- }
- else
- {
- Snackbar.Add("Ошибка удаления из избранного", Severity.Error);
- }
- }
- else
- {
- var response = await Http.PostAsync($"/api/favorites/{Playlist.ShareToken}", null);
- if (response.IsSuccessStatusCode)
- {
- _isFavorite = true;
- Snackbar.Add("Плейлист добавлен в избранное", Severity.Success);
- }
- else
- {
- Snackbar.Add("Ошибка добавления в избранное", Severity.Error);
- }
- }
- }
- catch (Exception ex)
- {
- Snackbar.Add($"Ошибка: {ex.Message}", Severity.Error);
- }
- finally
- {
- _favoriteLoading = false;
- StateHasChanged();
- }
- }
-
- private async Task OpenPermissionsDialog()
- {
- if (Playlist == null) return;
- var initialPermissions = new UpdatePermissionsDto
- {
- ViewPermission = Playlist.ViewPermission,
- PlayPermission = Playlist.PlayPermission,
- AddPermission = Playlist.AddPermission,
- RemovePermission = Playlist.RemovePermission
- };
- var parameters = new DialogParameters
- {
- { nameof(PermissionsDialog.ShareToken), Playlist.ShareToken },
- { nameof(PermissionsDialog.InitialPermissions), initialPermissions }
- };
- var dialog = await DialogService.ShowAsync("Настройки доступа", parameters);
- var result = await dialog.Result;
- if (!result.Canceled)
- {
- await OnPermissionsChanged.InvokeAsync();
- }
- }
-}
\ No newline at end of file
diff --git a/PlaylistShared.Pwa/Layout/MainLayout.razor b/PlaylistShared.Pwa/Layout/MainLayout.razor
index ade03e2..3e7b50d 100644
--- a/PlaylistShared.Pwa/Layout/MainLayout.razor
+++ b/PlaylistShared.Pwa/Layout/MainLayout.razor
@@ -30,7 +30,7 @@
}
-
+
diff --git a/PlaylistShared.Pwa/Pages/SharedPlaylistView.razor b/PlaylistShared.Pwa/Pages/SharedPlaylistView.razor
index 2e28f92..a6f5520 100644
--- a/PlaylistShared.Pwa/Pages/SharedPlaylistView.razor
+++ b/PlaylistShared.Pwa/Pages/SharedPlaylistView.razor
@@ -16,16 +16,16 @@
@inject AuthenticationStateProvider AuthProvider
@inject IDialogService DialogService
-
-
+
+
@*Первый элемент растянется на всю высоту*@
@* --- ВЕРСИЯ ДЛЯ ПК (сетка) --- *@
-
+
-
+
@PlaylistCardHeaderContent
@@ -147,6 +147,7 @@
scroll-snap-align: start;
flex: 0 0 auto; /* Запрещает карточкам сжиматься */
}
+
/* Скрываем скроллбар для эстетики */
.horizontal-scroll-container::-webkit-scrollbar { display: none; }
.horizontal-scroll-container { -ms-overflow-style: none; scrollbar-width: none; }
diff --git a/PlaylistShared.Pwa/Properties/launchSettings.json b/PlaylistShared.Pwa/Properties/launchSettings.json
index f14a056..6aad80f 100644
--- a/PlaylistShared.Pwa/Properties/launchSettings.json
+++ b/PlaylistShared.Pwa/Properties/launchSettings.json
@@ -12,6 +12,15 @@
}
},
+ "https (silent)": {
+ "commandName": "Project",
+ "dotnetRunMessages": true,
+ "applicationUrl": "https://localhost:7225;http://localhost:5181",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+
"https (prod)": {
"commandName": "Project",
"dotnetRunMessages": true,
diff --git a/PlaylistShared.Pwa/wwwroot/manifest.webmanifest b/PlaylistShared.Pwa/wwwroot/manifest.webmanifest
index 274009e..665fea4 100644
--- a/PlaylistShared.Pwa/wwwroot/manifest.webmanifest
+++ b/PlaylistShared.Pwa/wwwroot/manifest.webmanifest
@@ -7,11 +7,11 @@
"handle_links": "preferred",
"display": "standalone",
"background_color": "#1a1a27",
- "theme_color": "#7e6fff",
+ "theme_color": "#1a1a27",
"launch_handler": {
"client_mode": "focus-existing"
},
-
+
"prefer_related_applications": false,
"icons": [
{