Улучшена адаптивность для телефонов. Добавлен новый ContextActionBarService
This commit is contained in:
@@ -11,7 +11,7 @@
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
<p role="alert">You are not authorized to access this resource.</p>
|
<p role="alert">У вас нет прав доступа к этому ресурсу.</p>
|
||||||
}
|
}
|
||||||
</NotAuthorized>
|
</NotAuthorized>
|
||||||
</AuthorizeRouteView>
|
</AuthorizeRouteView>
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
@implements IDisposable
|
||||||
|
@inject ContextualActionBarService ContextualActionBarService
|
||||||
|
|
||||||
|
@code {
|
||||||
|
[Parameter] public bool Bottom { get; set; } = false;
|
||||||
|
[Parameter] public RenderFragment? ChildContent { get; set; }
|
||||||
|
|
||||||
|
protected override void OnParametersSet()
|
||||||
|
{
|
||||||
|
bool isChanged = false;
|
||||||
|
|
||||||
|
if (ContextualActionBarService.Content != ChildContent)
|
||||||
|
{
|
||||||
|
ContextualActionBarService.Content = ChildContent;
|
||||||
|
isChanged = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ContextualActionBarService.Bottom != Bottom)
|
||||||
|
{
|
||||||
|
ContextualActionBarService.Bottom = Bottom;
|
||||||
|
isChanged = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isChanged) ContextualActionBarService.ChangeParameters();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
ContextualActionBarService.Content = null;
|
||||||
|
ContextualActionBarService.Bottom = null;
|
||||||
|
ContextualActionBarService.ChangeParameters();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
@inherits LayoutComponentBase
|
@inherits LayoutComponentBase
|
||||||
@inject PwaUpdateService PwaUpdateService
|
@inject PwaUpdateService PwaUpdateService
|
||||||
@inject IJSRuntime JSRuntime
|
@inject IJSRuntime JSRuntime
|
||||||
|
@inject ContextualActionBarService ContextualActionBarService
|
||||||
|
|
||||||
<MudThemeProvider Theme="@_theme" IsDarkMode="_isDarkMode" />
|
<MudThemeProvider Theme="@_theme" IsDarkMode="_isDarkMode" />
|
||||||
<MudPopoverProvider />
|
<MudPopoverProvider />
|
||||||
@@ -9,32 +10,36 @@
|
|||||||
<MudSnackbarProvider />
|
<MudSnackbarProvider />
|
||||||
|
|
||||||
<MudLayout>
|
<MudLayout>
|
||||||
<MudAppBar Elevation="1">
|
<MudAppBar Elevation="1" Contextual Bottom = "@_actionBarBottom" Fixed>
|
||||||
<MudIconButton Icon="@Icons.Material.Filled.Menu" Color="Color.Inherit" Edge="Edge.Start" OnClick="@DrawerToggle" />
|
<MudIconButton Icon="@Icons.Material.Filled.Menu" Color="Color.Inherit" Edge="Edge.Start" OnClick="@DrawerToggle" />
|
||||||
<MudSpacer />
|
@if (_actionBarContent != null)
|
||||||
<LoginDisplay />
|
{
|
||||||
<MudIconButton Icon="@(DarkLightModeButtonIcon)" Color="Color.Inherit" OnClick="@DarkModeToggle" Class="ml-2" />
|
@_actionBarContent
|
||||||
<MudLink Href="https://git.frigat.duckdns.org/FrigaT/PlaylistShared" Target="_blank" Color="Color.Inherit" Underline="Underline.None" Class="ml-4">
|
}
|
||||||
<MudIcon Icon="@Icons.Custom.Brands.GitHub" Size="Size.Small" Class="mr-1" /> Git
|
else
|
||||||
</MudLink>
|
{
|
||||||
|
<MudSpacer />
|
||||||
|
<LoginDisplay />
|
||||||
|
<MudIconButton Icon="@(DarkLightModeButtonIcon)" Color="Color.Inherit" OnClick="@DarkModeToggle" Class="ml-2" />
|
||||||
|
<MudLink Href="https://git.frigat.duckdns.org/FrigaT/PlaylistShared" Target="_blank" Color="Color.Inherit" Underline="Underline.None" Class="ml-4">
|
||||||
|
<MudIcon Icon="@Icons.Custom.Brands.GitHub" Size="Size.Small" Class="mr-1" /> Git
|
||||||
|
</MudLink>
|
||||||
|
}
|
||||||
</MudAppBar>
|
</MudAppBar>
|
||||||
|
|
||||||
<MudDrawer @bind-Open="_drawerOpen" ClipMode="DrawerClipMode.Always" Elevation="2">
|
<MudDrawer @bind-Open="_drawerOpen" ClipMode="DrawerClipMode.Always" Elevation="2">
|
||||||
<NavMenu />
|
<NavMenu />
|
||||||
</MudDrawer>
|
</MudDrawer>
|
||||||
|
|
||||||
<MudMainContent Class="pt-16 d-flex flex-column" Style="height: 100vh;">
|
<MudMainContent Class="@("d-flex flex-column" + (_actionBarBottom ? " pt-0 pb-16" : ""))" Style="height: 100dvh;">
|
||||||
<MudItem Class="flex-grow-1 overflow-y-auto">
|
@Body
|
||||||
@Body
|
|
||||||
</MudItem>
|
|
||||||
|
|
||||||
<MudItem>
|
|
||||||
<AudioPlayer />
|
|
||||||
</MudItem>
|
|
||||||
</MudMainContent>
|
</MudMainContent>
|
||||||
</MudLayout>
|
</MudLayout>
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
|
private RenderFragment? _actionBarContent;
|
||||||
|
private bool _actionBarBottom = false;
|
||||||
|
|
||||||
private bool _drawerOpen = true;
|
private bool _drawerOpen = true;
|
||||||
private bool _isDarkMode = true;
|
private bool _isDarkMode = true;
|
||||||
private MudTheme? _theme;
|
private MudTheme? _theme;
|
||||||
@@ -51,6 +56,8 @@
|
|||||||
PaletteDark = _darkPalette,
|
PaletteDark = _darkPalette,
|
||||||
LayoutProperties = new LayoutProperties()
|
LayoutProperties = new LayoutProperties()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ContextualActionBarService.OnChanged += OnContextualChangedHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||||
@@ -62,6 +69,13 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnContextualChangedHandler()
|
||||||
|
{
|
||||||
|
_actionBarContent = ContextualActionBarService.Content;
|
||||||
|
_actionBarBottom = ContextualActionBarService.Bottom ?? false;
|
||||||
|
StateHasChanged();
|
||||||
|
}
|
||||||
|
|
||||||
private void DrawerToggle()
|
private void DrawerToggle()
|
||||||
{
|
{
|
||||||
_drawerOpen = !_drawerOpen;
|
_drawerOpen = !_drawerOpen;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
<PageTitle>@_playlist?.Title - Playlist Share</PageTitle>
|
<PageTitle>@_playlist?.Title - Playlist Share</PageTitle>
|
||||||
|
|
||||||
@using PlaylistShared.Pwa.Components.Common
|
@using PlaylistShared.Pwa.Components.Common
|
||||||
|
@using PlaylistShared.Pwa.Components.Global
|
||||||
@using PlaylistShared.Pwa.Components.SharedPlaylist
|
@using PlaylistShared.Pwa.Components.SharedPlaylist
|
||||||
@using PlaylistShared.Pwa.Components.SharedPlaylist.Cards
|
@using PlaylistShared.Pwa.Components.SharedPlaylist.Cards
|
||||||
@using PlaylistShared.Shared.DTO
|
@using PlaylistShared.Shared.DTO
|
||||||
@@ -16,60 +17,73 @@
|
|||||||
@inject IDialogService DialogService
|
@inject IDialogService DialogService
|
||||||
|
|
||||||
<MudContainer MaxWidth="MaxWidth.ExtraLarge" Class="pa-1" Style="height: 100%;">
|
<MudContainer MaxWidth="MaxWidth.ExtraLarge" Class="pa-1" Style="height: 100%;">
|
||||||
@* --- ВЕРСИЯ ДЛЯ ПК (сетка) --- *@
|
<MudStack Style="height: 100%;" StretchItems="StretchItems.Start" Spacing="2">
|
||||||
<MudHidden Breakpoint="Breakpoint.MdAndUp" Invert>
|
@*Первый элемент растянется на всю высоту*@
|
||||||
<MudGrid Spacing="2" Class="flex-grow-1 pt-2" Style="height: 100%;">
|
<MudItem Style="min-height: 0; height: 100%;">
|
||||||
<MudItem xs="12" md="6" Style="height: 100%;">
|
|
||||||
@PlaylistCardContent
|
|
||||||
</MudItem>
|
|
||||||
|
|
||||||
@if (_canAdd)
|
@* --- ВЕРСИЯ ДЛЯ ПК (сетка) --- *@
|
||||||
{
|
<MudHidden Breakpoint="Breakpoint.MdAndUp" Invert>
|
||||||
<MudItem xs="12" md="6" Style="height: 100%;">
|
<MudGrid Spacing="2" Class="flex-grow-1 pt-2" Style="height: 100%;">
|
||||||
@AddTrackCardContent
|
<MudItem xs="12" md="6" Style="height: 100%; overflow-y: auto;">
|
||||||
</MudItem>
|
|
||||||
}
|
|
||||||
</MudGrid>
|
|
||||||
</MudHidden>
|
|
||||||
|
|
||||||
@* --- ВЕРСИЯ ДЛЯ МОБИЛОК (вкладки внизу) --- *@
|
|
||||||
<MudHidden Breakpoint="Breakpoint.SmAndDown" Invert>
|
|
||||||
<div class="d-flex flex-column pa-0 ma-0" style="height: 100%; 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="flex-grow-1 overflow-auto pb-1">
|
|
||||||
@PlaylistCardContent
|
@PlaylistCardContent
|
||||||
</div>
|
</MudItem>
|
||||||
</div>
|
|
||||||
|
|
||||||
@if (_canAdd)
|
@if (_canAdd)
|
||||||
{
|
{
|
||||||
<div class="@(_activeMobileTab == 1 ? "d-flex" : "d-none") flex-column" style="height: 100%;">
|
<MudItem xs="12" md="6" Style="height: 100%; overflow-y: auto;">
|
||||||
<div class="flex-grow-1 overflow-auto pb-1">
|
@AddTrackCardContent
|
||||||
@AddTrackCardContent
|
</MudItem>
|
||||||
</div>
|
}
|
||||||
</div>
|
</MudGrid>
|
||||||
}
|
<ContextualBarContent />
|
||||||
</div>
|
</MudHidden>
|
||||||
|
|
||||||
@* Кастомная панель навигации внизу *@
|
@* --- ВЕРСИЯ ДЛЯ МОБИЛОК (вкладки внизу) --- *@
|
||||||
@if (_canAdd)
|
<MudHidden Breakpoint="Breakpoint.SmAndDown" Invert>
|
||||||
{
|
<div class="d-flex flex-column pa-0 ma-0" style="height: 100%; min-height: 0;">
|
||||||
<MudPaper Elevation="0" Class="py-1">
|
|
||||||
<MudNavMenu Margin="Margin.None" Class="d-flex flex-row justify-space-around">
|
@* Область контента: оба компонента здесь всегда *@
|
||||||
<MudIconButton Icon="@Icons.Material.Filled.LibraryMusic"
|
<div class="flex-grow-1 relative pa-0" style="min-height: 0;">
|
||||||
Color="@(_activeMobileTab == 0 ? Color.Primary : Color.Default)"
|
<div class="@(_activeMobileTab == 0 ? "d-flex" : "d-none") flex-column" style="height: 100%;">
|
||||||
OnClick="() => _activeMobileTab = 0" />
|
<div class="flex-grow-1 overflow-auto pb-1">
|
||||||
|
@PlaylistCardContent
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@if (_canAdd)
|
||||||
|
{
|
||||||
|
<div class="@(_activeMobileTab == 1 ? "d-flex" : "d-none") flex-column" style="height: 100%;">
|
||||||
|
<div class="flex-grow-1 overflow-auto pb-1">
|
||||||
|
@AddTrackCardContent
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@* Кастомная панель навигации внизу *@
|
||||||
|
<ContextualBarContent Bottom>
|
||||||
|
<MudNavMenu Margin="Margin.None" Class="d-flex flex-row justify-space-around">
|
||||||
|
<MudIconButton Icon="@Icons.Material.Filled.LibraryMusic"
|
||||||
|
Color="@(_activeMobileTab == 0 ? Color.Primary : Color.Default)"
|
||||||
|
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>
|
}
|
||||||
</MudPaper>
|
</MudNavMenu>
|
||||||
}
|
|
||||||
</div>
|
</ContextualBarContent>
|
||||||
</MudHidden>
|
</div>
|
||||||
|
</MudHidden>
|
||||||
|
</MudItem>
|
||||||
|
|
||||||
|
@*Второй элемент - плеер. Привязан к нижней части контейнера*@
|
||||||
|
<MudItem>
|
||||||
|
<AudioPlayer />
|
||||||
|
</MudItem>
|
||||||
|
</MudStack>
|
||||||
</MudContainer>
|
</MudContainer>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
@@ -97,7 +111,7 @@
|
|||||||
private RenderFragment PlaylistCardContent => __builder =>
|
private RenderFragment PlaylistCardContent => __builder =>
|
||||||
{
|
{
|
||||||
<MudCard Elevation="0" Class="d-flex flex-column" Style="height: 100%;">
|
<MudCard Elevation="0" Class="d-flex flex-column" Style="height: 100%;">
|
||||||
<MudCardHeader>
|
<MudCardHeader Class="py-0">
|
||||||
<CardHeaderContent>
|
<CardHeaderContent>
|
||||||
@if(_loading)
|
@if(_loading)
|
||||||
{
|
{
|
||||||
@@ -113,7 +127,7 @@
|
|||||||
</CardHeaderActions>
|
</CardHeaderActions>
|
||||||
</MudCardHeader>
|
</MudCardHeader>
|
||||||
|
|
||||||
<MudCardContent Class="flex-grow-1 overflow-auto flex-column">
|
<MudCardContent Class="flex-grow-1 overflow-auto flex-column py-0">
|
||||||
@if (_loading || _tracksLoading)
|
@if (_loading || _tracksLoading)
|
||||||
{
|
{
|
||||||
<TrackItemSkeleton />
|
<TrackItemSkeleton />
|
||||||
@@ -150,8 +164,8 @@
|
|||||||
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>
|
<MudCardHeader Class="py-0">
|
||||||
<MudStack Style="width: 100%;">
|
<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"
|
||||||
@bind-Value:after="OnSearchQueryChanged"
|
@bind-Value:after="OnSearchQueryChanged"
|
||||||
@@ -177,7 +191,7 @@
|
|||||||
</MudStack>
|
</MudStack>
|
||||||
</MudCardHeader>
|
</MudCardHeader>
|
||||||
|
|
||||||
<MudCardContent Class="flex-grow-1 overflow-auto flex-column">
|
<MudCardContent Class="flex-grow-1 overflow-auto flex-column py-0">
|
||||||
@if (_isSearching)
|
@if (_isSearching)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ internal class Program
|
|||||||
builder.Services.AddScoped<PlayerStorage>();
|
builder.Services.AddScoped<PlayerStorage>();
|
||||||
builder.Services.AddScoped<AuthStateProvider>();
|
builder.Services.AddScoped<AuthStateProvider>();
|
||||||
builder.Services.AddScoped<AuthenticationStateProvider>(sp => sp.GetRequiredService<AuthStateProvider>());
|
builder.Services.AddScoped<AuthenticationStateProvider>(sp => sp.GetRequiredService<AuthStateProvider>());
|
||||||
|
builder.Services.AddScoped<ContextualActionBarService>();
|
||||||
builder.Services.AddScoped<ApiClient>();
|
builder.Services.AddScoped<ApiClient>();
|
||||||
builder.Services.AddScoped<IAudioPlayerService, AudioPlayerService>();
|
builder.Services.AddScoped<IAudioPlayerService, AudioPlayerService>();
|
||||||
|
|
||||||
|
|||||||
18
PlaylistShared.Pwa/Services/ContextualActionBarService.cs
Normal file
18
PlaylistShared.Pwa/Services/ContextualActionBarService.cs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
using Microsoft.AspNetCore.Components;
|
||||||
|
|
||||||
|
namespace PlaylistShared.Pwa.Services;
|
||||||
|
|
||||||
|
public class ContextualActionBarService
|
||||||
|
{
|
||||||
|
// Событие, которое будет вызываться при изменении содержимого панели
|
||||||
|
public event Action? OnChanged;
|
||||||
|
|
||||||
|
public RenderFragment? Content { get; set; } = null;
|
||||||
|
|
||||||
|
public bool? Bottom { get; set; }
|
||||||
|
|
||||||
|
public void ChangeParameters()
|
||||||
|
{
|
||||||
|
OnChanged?.Invoke();
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user