Доработка строки состояния
This commit is contained in:
@@ -6,22 +6,10 @@
|
|||||||
[Parameter] public RenderFragment? ChildContent { get; set; }
|
[Parameter] public RenderFragment? ChildContent { get; set; }
|
||||||
|
|
||||||
protected override void OnParametersSet()
|
protected override void OnParametersSet()
|
||||||
{
|
|
||||||
bool isChanged = false;
|
|
||||||
|
|
||||||
if (ContextualActionBarService.Content != ChildContent)
|
|
||||||
{
|
{
|
||||||
ContextualActionBarService.Content = ChildContent;
|
ContextualActionBarService.Content = ChildContent;
|
||||||
isChanged = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ContextualActionBarService.Bottom != Bottom)
|
|
||||||
{
|
|
||||||
ContextualActionBarService.Bottom = Bottom;
|
ContextualActionBarService.Bottom = Bottom;
|
||||||
isChanged = true;
|
ContextualActionBarService.ChangeParameters();
|
||||||
}
|
|
||||||
|
|
||||||
if (isChanged) ContextualActionBarService.ChangeParameters();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
|
|||||||
@@ -25,7 +25,32 @@
|
|||||||
<MudHidden Breakpoint="Breakpoint.MdAndUp" Invert>
|
<MudHidden Breakpoint="Breakpoint.MdAndUp" Invert>
|
||||||
<MudGrid Spacing="2" Class="flex-grow-1 pt-2" Style="height: 100%;">
|
<MudGrid Spacing="2" Class="flex-grow-1 pt-2" Style="height: 100%;">
|
||||||
<MudItem xs="12" md="6" Style="height: 100%; overflow-y: auto;">
|
<MudItem xs="12" md="6" Style="height: 100%; overflow-y: auto;">
|
||||||
@PlaylistCardContent
|
<MudCard Elevation="4" Class="d-flex flex-column" Style="height: 100%;">
|
||||||
|
<MudCardHeader Class="pb-0">
|
||||||
|
<CardHeaderContent>
|
||||||
|
@PlaylistCardHeaderContent
|
||||||
|
</CardHeaderContent>
|
||||||
|
<CardHeaderActions>
|
||||||
|
<MudIconButton Icon="@(_isFavorite? Icons.Material.Filled.Star : Icons.Material.Outlined.StarBorder)"
|
||||||
|
Color="Color.Warning"
|
||||||
|
OnClick="ToggleFavorite"
|
||||||
|
Disabled="_favoriteLoading"
|
||||||
|
Size="Size.Medium" />
|
||||||
|
|
||||||
|
<ShareButton />
|
||||||
|
|
||||||
|
@if (_isCreator && _isAuthenticated)
|
||||||
|
{
|
||||||
|
<MudIconButton Icon="@Icons.Material.Filled.Settings" OnClick="OpenPermissionsDialog" Size="Size.Medium" />
|
||||||
|
}
|
||||||
|
<MudIconButton Icon="@Icons.Material.Filled.Refresh" OnClick="LoadTracks" Disabled="@_tracksLoading" />
|
||||||
|
</CardHeaderActions>
|
||||||
|
</MudCardHeader>
|
||||||
|
|
||||||
|
<MudCardContent Class="flex-grow-1 overflow-auto flex-column py-0">
|
||||||
|
@PlaylistCardBodyContent
|
||||||
|
</MudCardContent>
|
||||||
|
</MudCard>
|
||||||
</MudItem>
|
</MudItem>
|
||||||
|
|
||||||
@if (_canAdd)
|
@if (_canAdd)
|
||||||
@@ -46,7 +71,17 @@
|
|||||||
<div class="flex-grow-1 relative pa-0" style="min-height: 0;">
|
<div class="flex-grow-1 relative pa-0" style="min-height: 0;">
|
||||||
<div class="@(_activeMobileTab == 0 ? "d-flex" : "d-none") flex-column" style="height: 100%;">
|
<div class="@(_activeMobileTab == 0 ? "d-flex" : "d-none") flex-column" style="height: 100%;">
|
||||||
<div class="flex-grow-1 overflow-auto pb-1">
|
<div class="flex-grow-1 overflow-auto pb-1">
|
||||||
@PlaylistCardContent
|
<MudCard Elevation="0" Class="d-flex flex-column" Style="height: 100%;">
|
||||||
|
<MudCardHeader Class="pb-0">
|
||||||
|
<CardHeaderContent>
|
||||||
|
@PlaylistCardHeaderContent
|
||||||
|
</CardHeaderContent>
|
||||||
|
</MudCardHeader>
|
||||||
|
|
||||||
|
<MudCardContent Class="flex-grow-1 overflow-auto flex-column py-0">
|
||||||
|
@PlaylistCardBodyContent
|
||||||
|
</MudCardContent>
|
||||||
|
</MudCard>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -62,18 +97,33 @@
|
|||||||
|
|
||||||
@* Кастомная панель навигации внизу *@
|
@* Кастомная панель навигации внизу *@
|
||||||
<ContextualBarContent Bottom>
|
<ContextualBarContent Bottom>
|
||||||
<MudNavMenu Margin="Margin.None" Class="d-flex flex-row justify-space-around">
|
|
||||||
<MudIconButton Icon="@Icons.Material.Filled.LibraryMusic"
|
<MudIconButton Icon="@Icons.Material.Filled.LibraryMusic"
|
||||||
Color="@(_activeMobileTab == 0 ? Color.Primary : Color.Default)"
|
Color="@(_activeMobileTab == 0 ? Color.Primary : Color.Default)"
|
||||||
OnClick="() => _activeMobileTab = 0" />
|
OnClick="() => _activeMobileTab = 0" />
|
||||||
@if (_canAdd)
|
|
||||||
{
|
|
||||||
<MudIconButton Icon="@Icons.Material.Filled.AddCircle"
|
<MudIconButton Icon="@Icons.Material.Filled.AddCircle"
|
||||||
Color="@(_activeMobileTab == 1 ? Color.Primary : Color.Default)"
|
Color="@(_activeMobileTab == 1 ? Color.Primary : Color.Default)"
|
||||||
OnClick="() => _activeMobileTab = 1" />
|
OnClick="() => _activeMobileTab = 1" />
|
||||||
}
|
|
||||||
</MudNavMenu>
|
|
||||||
|
|
||||||
|
<MudSpacer />
|
||||||
|
<MudMenu Icon="@Icons.Material.Filled.MoreVert"
|
||||||
|
AnchorOrigin="Origin.TopRight"
|
||||||
|
TransformOrigin="Origin.TopRight">
|
||||||
|
|
||||||
|
<MudMenuItem Icon="@(_isFavorite? Icons.Material.Filled.Star : Icons.Material.Outlined.StarBorder)"
|
||||||
|
IconColor="Color.Warning"
|
||||||
|
Label="Избранное"
|
||||||
|
OnClick="ToggleFavorite"
|
||||||
|
Disabled="@_favoriteLoading"
|
||||||
|
/>
|
||||||
|
|
||||||
|
@if (_isCreator && _isAuthenticated)
|
||||||
|
{
|
||||||
|
<MudMenuItem Icon="@Icons.Material.Filled.Settings"
|
||||||
|
OnClick="OpenPermissionsDialog"
|
||||||
|
Label="Настройки" />
|
||||||
|
}
|
||||||
|
</MudMenu>
|
||||||
</ContextualBarContent>
|
</ContextualBarContent>
|
||||||
</div>
|
</div>
|
||||||
</MudHidden>
|
</MudHidden>
|
||||||
@@ -108,26 +158,33 @@
|
|||||||
/// <summary>Токен расшаренного плейлиста</summary>
|
/// <summary>Токен расшаренного плейлиста</summary>
|
||||||
[Parameter] public required string Token { get; set; }
|
[Parameter] public required string Token { get; set; }
|
||||||
|
|
||||||
private RenderFragment PlaylistCardContent => __builder =>
|
|
||||||
|
/// <summary>Элемент: заголовок плейлиста</summary>
|
||||||
|
private RenderFragment PlaylistCardHeaderContent => __builder =>
|
||||||
{
|
{
|
||||||
<MudCard Elevation="0" Class="d-flex flex-column" Style="height: 100%;">
|
|
||||||
<MudCardHeader Class="py-0">
|
|
||||||
<CardHeaderContent>
|
|
||||||
@if (_loading)
|
@if (_loading)
|
||||||
{
|
{
|
||||||
<MudSkeleton Width="200px" Height="32px" SkeletonType="SkeletonType.Text" />
|
<MudSkeleton Width="200px" Height="32px" SkeletonType="SkeletonType.Text" />
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
<PlaylistHeader Playlist="@_playlist" />
|
|
||||||
}
|
|
||||||
</CardHeaderContent>
|
|
||||||
<CardHeaderActions>
|
|
||||||
<MudIconButton Icon="@Icons.Material.Filled.Refresh" OnClick="LoadTracks" Disabled="@_tracksLoading" />
|
|
||||||
</CardHeaderActions>
|
|
||||||
</MudCardHeader>
|
|
||||||
|
|
||||||
<MudCardContent Class="flex-grow-1 overflow-auto flex-column py-0">
|
<MudStack Row AlignItems="AlignItems.Center">
|
||||||
|
@if (!string.IsNullOrEmpty(_playlist?.CoverUrl))
|
||||||
|
{
|
||||||
|
<MudImage Src="@_playlist.CoverUrl.FormatCoverUrl(60, 60)" Height="60" Width="60" Class="rounded shadow-sm" />
|
||||||
|
}
|
||||||
|
|
||||||
|
<MudText Typo="Typo.h6" Color="Color.Primary">
|
||||||
|
@_playlist?.Title
|
||||||
|
</MudText>
|
||||||
|
</MudStack>
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// <summary>Элемент: треки плейлиста</summary>
|
||||||
|
private RenderFragment PlaylistCardBodyContent => __builder =>
|
||||||
|
{
|
||||||
@if (_loading || _tracksLoading)
|
@if (_loading || _tracksLoading)
|
||||||
{
|
{
|
||||||
<TrackItemSkeleton />
|
<TrackItemSkeleton />
|
||||||
@@ -157,14 +214,13 @@
|
|||||||
</RowTemplate>
|
</RowTemplate>
|
||||||
</MudTable>
|
</MudTable>
|
||||||
}
|
}
|
||||||
</MudCardContent>
|
|
||||||
</MudCard>
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// <summary>Элемент: блок добавления треков</summary>
|
||||||
private RenderFragment AddTrackCardContent => __builder =>
|
private RenderFragment AddTrackCardContent => __builder =>
|
||||||
{
|
{
|
||||||
<MudCard Class="d-flex flex-column" Elevation="0" Style="height: 100%;">
|
<MudCard Class="d-flex flex-column" Elevation="0" Style="height: 100%;">
|
||||||
<MudCardHeader Class="py-0">
|
<MudCardHeader Class="pb-0">
|
||||||
<MudStack Style="width: 100%;" Spacing="0">
|
<MudStack Style="width: 100%;" Spacing="0">
|
||||||
<MudText Typo="Typo.h6" Color="Color.Primary" Class="mb-4">Добавление треков</MudText>
|
<MudText Typo="Typo.h6" Color="Color.Primary" Class="mb-4">Добавление треков</MudText>
|
||||||
<MudTextField @bind-Value="_searchQuery"
|
<MudTextField @bind-Value="_searchQuery"
|
||||||
@@ -338,10 +394,17 @@
|
|||||||
private bool _isSearching = false;
|
private bool _isSearching = false;
|
||||||
/// <summary>Ссылка на поле ввода</summary>
|
/// <summary>Ссылка на поле ввода</summary>
|
||||||
private MudTextField<string> _searchField;
|
private MudTextField<string> _searchField;
|
||||||
|
|
||||||
/// <summary>Результат поиска.</summary>
|
/// <summary>Результат поиска.</summary>
|
||||||
private YandexSearchResult? _searchResult = null;
|
private YandexSearchResult? _searchResult = null;
|
||||||
|
|
||||||
|
/********************************
|
||||||
|
* Вкладка добавления треков
|
||||||
|
*********************************/
|
||||||
|
/// <summary>Признак, что альбом в фаворитах.</summary>
|
||||||
|
private bool _isFavorite;
|
||||||
|
/// <summary>Загрузка признака "фаворит".</summary>
|
||||||
|
private bool _favoriteLoading;
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
{
|
{
|
||||||
var authState = await AuthProvider.GetAuthenticationStateAsync();
|
var authState = await AuthProvider.GetAuthenticationStateAsync();
|
||||||
@@ -392,6 +455,7 @@
|
|||||||
_activeMobileTab = 0;
|
_activeMobileTab = 0;
|
||||||
|
|
||||||
await ConfigurePermissions();
|
await ConfigurePermissions();
|
||||||
|
await CheckFavoriteStatus();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -643,4 +707,91 @@
|
|||||||
throw new ArgumentException("Unsupported URL pattern");
|
throw new ArgumentException("Unsupported URL pattern");
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region Избранное / Фаворит
|
||||||
|
/// <summary>Установка галочки "избранное"</summary>
|
||||||
|
private async Task CheckFavoriteStatus()
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(Token)) return;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var response = await Http.GetFromJsonAsync<ApiResponse<bool>>($"/api/favorites/{Token}/check");
|
||||||
|
if (response?.Success == true)
|
||||||
|
_isFavorite = response.Data;
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task ToggleFavorite()
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(Token)) return;
|
||||||
|
|
||||||
|
if (!_isAuthenticated)
|
||||||
|
{
|
||||||
|
Snackbar.Add("Добавление в избранное только авторизованным пользователям", Severity.Warning);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_favoriteLoading = true;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (_isFavorite)
|
||||||
|
{
|
||||||
|
var response = await Http.DeleteAsync($"/api/favorites/{Token}");
|
||||||
|
if (response.IsSuccessStatusCode)
|
||||||
|
{
|
||||||
|
_isFavorite = false;
|
||||||
|
Snackbar.Add("Плейлист удалён из избранного", Severity.Success);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Snackbar.Add("Ошибка удаления из избранного", Severity.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var response = await Http.PostAsync($"/api/favorites/{Token}", 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Настройка доступов к плейлисту
|
||||||
|
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), Token },
|
||||||
|
{ nameof(PermissionsDialog.InitialPermissions), initialPermissions }
|
||||||
|
};
|
||||||
|
var dialog = await DialogService.ShowAsync<PermissionsDialog>("Настройки доступа", parameters);
|
||||||
|
var result = await dialog.Result;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user