Улучшен плеер

This commit is contained in:
FrigaT
2026-04-14 06:52:38 +03:00
parent fd3ed2f317
commit 4b3036364b
9 changed files with 55 additions and 26 deletions

View File

@@ -6,7 +6,7 @@
<MudCard> <MudCard>
<MudCardHeader> <MudCardHeader>
<CardHeaderContent> <CardHeaderContent>
<MudText Typo="Typo.h4" GutterBottom>🎵 PlaylistShared</MudText> <MudText Typo="Typo.h4" GutterBottom>🎵 Playlist share</MudText>
<MudText Typo="Typo.body1">Делитесь плейлистами Яндекс.Музыки с друзьями и управляйте треками вместе!</MudText> <MudText Typo="Typo.body1">Делитесь плейлистами Яндекс.Музыки с друзьями и управляйте треками вместе!</MudText>
</CardHeaderContent> </CardHeaderContent>
</MudCardHeader> </MudCardHeader>
@@ -20,7 +20,7 @@
<MudText Typo="Typo.h6" GutterBottom>1⃣ Регистрация и вход</MudText> <MudText Typo="Typo.h6" GutterBottom>1⃣ Регистрация и вход</MudText>
<MudText Typo="Typo.body2" Class="mb-2"> <MudText Typo="Typo.body2" Class="mb-2">
• Нажмите <MudLink Href="/register" Style="font-weight:bold;">«Регистрация»</MudLink> и создайте аккаунт.<br /> • Нажмите <MudLink Href="/register" Style="font-weight:bold;">«Регистрация»</MudLink> и создайте аккаунт.<br />
• Или войдите через <MudLink Href="/login" Style="font-weight:bold;">вход</MudLink>, если уже зарегистрированы. • Или <MudLink Href="/login" Style="font-weight:bold;">войдите</MudLink> в систему, если уже зарегистрированы.
</MudText> </MudText>
</MudPaper> </MudPaper>
</MudItem> </MudItem>

View File

@@ -29,7 +29,7 @@
} }
else else
{ {
<MudTable Items="@FilteredPlaylists" Hover="true" Breakpoint="Breakpoint.Sm"> <MudTable Items="@FilteredPlaylists">
<HeaderContent> <HeaderContent>
<MudTh>Название</MudTh> <MudTh>Название</MudTh>
<MudTh>Треков</MudTh> <MudTh>Треков</MudTh>
@@ -37,9 +37,9 @@
<MudTh></MudTh> <MudTh></MudTh>
</HeaderContent> </HeaderContent>
<RowTemplate> <RowTemplate>
<MudTd><MudText>@context.Title</MudText></MudTd> <MudTd DataLabel="Название"><MudText>@context.Title</MudText></MudTd>
<MudTd>@context.TrackCount</MudTd> <MudTd DataLabel="Треков">@context.TrackCount</MudTd>
<MudTd> <MudTd DataLabel="Статус">
<!-- Явно указываем T="string" для MudChip --> <!-- Явно указываем T="string" для MudChip -->
@if (context.IsShared) @if (context.IsShared)
{ {

View File

@@ -112,10 +112,11 @@
} }
<!-- Список треков --> <!-- Список треков -->
<div style="display: flex; justify-content: space-between; align-items: center;"> <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px;">
<MudText Typo="Typo.h6" GutterBottom>Треки</MudText> <MudText Typo="Typo.h6">Треки</MudText>
<MudIconButton Icon="@Icons.Material.Filled.Refresh" OnClick="LoadTracks" Disabled="_tracksLoading" Size="Size.Small" /> <MudIconButton Icon="@Icons.Material.Filled.Refresh" OnClick="LoadTracks" Disabled="_tracksLoading" Size="Size.Medium" />
</div> </div>
@if (_tracksLoading) @if (_tracksLoading)
{ {
<MudProgressCircular Indeterminate /> <MudProgressCircular Indeterminate />
@@ -126,7 +127,7 @@
} }
else else
{ {
<MudTable Items="@_tracks" Hover="true" Breakpoint="Breakpoint.Sm"> <MudTable Items="@_tracks">
<HeaderContent> <HeaderContent>
<MudTh>#</MudTh> <MudTh>#</MudTh>
<MudTh>Обложка</MudTh> <MudTh>Обложка</MudTh>
@@ -139,50 +140,52 @@
} }
</HeaderContent> </HeaderContent>
<RowTemplate> <RowTemplate>
<MudTd>@context.Index</MudTd> <MudTd DataLabel="#" Style="font-weight: normal;">@context.Index</MudTd>
<MudTd> <MudTd DataLabel="Обложка">
@if (!string.IsNullOrEmpty(context.CoverUri)) @if (!string.IsNullOrEmpty(context.CoverUri))
{ {
<TrackCoverWithPlay CoverUrl="@context.CoverUri" <TrackCoverWithPlay CoverUrl="@context.CoverUri"
TrackId="@context.Id" TrackId="@context.Id"
Width="50" Width="50" Height="50"
Height="50"
IsPlaying="@(_currentTrackId == context.Id && _isPlaying)" IsPlaying="@(_currentTrackId == context.Id && _isPlaying)"
OnPlay="PlayTrack" /> OnPlay="PlayTrack" />
} }
</MudTd> </MudTd>
<MudTd> <MudTd DataLabel="Название">
<MudLink Href="@($"https://music.yandex.ru/track/{context.Id}")" <MudLink Href="@($"https://music.yandex.ru/track/{context.Id}")" Target="_blank" Underline="Underline.Hover">
Target="_blank"
Underline="Underline.Hover"
Style="cursor: pointer; display: inline-flex; align-items: center;">
@context.Title @context.Title
<MudIcon Icon="@Icons.Material.Filled.OpenInNew" Size="Size.Small" Class="ml-1" /> <MudIcon Icon="@Icons.Material.Filled.OpenInNew" Size="Size.Small" Class="ml-1" />
</MudLink> </MudLink>
</MudTd> </MudTd>
<MudTd>@string.Join(", ", context.Artists)</MudTd> <MudTd DataLabel="Исполнитель">@string.Join(", ", context.Artists)</MudTd>
<MudTd>@FormatDuration(context.DurationMs)</MudTd> <MudTd DataLabel="Длительность">@FormatDuration(context.DurationMs)</MudTd>
@if (_canRemove) @if (_canRemove)
{ {
<MudTd> <MudTd DataLabel="">
<MudIconButton Icon="@Icons.Material.Filled.Delete" Color="Color.Error" OnClick="() => RemoveTrack(context)" /> <MudIconButton Icon="@Icons.Material.Filled.Delete" Color="Color.Error" OnClick="() => RemoveTrack(context)" />
</MudTd> </MudTd>
} }
</RowTemplate> </RowTemplate>
</MudTable> </MudTable>
<AudioPlayer @ref="_audioPlayer" OnTrackEnded="OnTrackEnded" />
} }
</MudCardContent> </MudCardContent>
</MudCard> </MudCard>
} }
<!-- Фиксированный плеер внизу -->
<div class="fixed-player" style="display: @(_isPlayerVisible ? "block" : "none");">
<AudioPlayer @ref="_audioPlayer" OnTrackEnded="OnTrackEnded" />
</div>
</MudContainer> </MudContainer>
@code { @code {
[Parameter] public string Token { get; set; } [Parameter] public string Token { get; set; }
private AudioPlayer? _audioPlayer; private AudioPlayer? _audioPlayer;
private string? _currentTrackId { get; set; } private string? _currentTrackId { get; set; }
private bool _isPlaying = false; private bool _isPlaying = false;
private bool _isPlayerVisible = false;
private SharedPlaylistDto? _playlist; private SharedPlaylistDto? _playlist;
private bool _loading = true; private bool _loading = true;
@@ -436,6 +439,8 @@
await _audioPlayer.LoadAndPlayAsync(trackId); await _audioPlayer.LoadAndPlayAsync(trackId);
_isPlaying = true; _isPlaying = true;
} }
_isPlayerVisible = true;
} }
private async Task OnTrackEnded() private async Task OnTrackEnded()

View File

@@ -123,3 +123,27 @@ code {
transition: opacity 0.2s ease; transition: opacity 0.2s ease;
cursor: pointer; cursor: pointer;
} }
/* Фиксированный плеер внизу */
.fixed-player {
position: sticky;
display: flex;
bottom: 0;
width: 100%;
right: 0;
justify-content: center;
background-color: var(--mud-palette-background);
box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.1);
}
/* Отступ снизу, когда плеер виден */
.page-with-player {
padding-bottom: 80px; /* Высота плеера (подберите под свою тему) */
}
/* На мобильных устройствах можно уменьшить отступ */
@media (max-width: 600px) {
.page-with-player {
padding-bottom: 100px; /* если плеер выше на мобильных */
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.6 KiB

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 172 KiB

View File

@@ -4,7 +4,7 @@
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>PlaylistShared.Pwa</title> <title>Playlist Share</title>
<base href="/" /> <base href="/" />
<link rel="preload" id="webassembly" /> <link rel="preload" id="webassembly" />
<link href="https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100..900;1,100..900&display=swap" rel="stylesheet" /> <link href="https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100..900;1,100..900&display=swap" rel="stylesheet" />

View File

@@ -1,5 +1,5 @@
{ {
"name": "Playlist Shared", "name": "Playlist Share",
"short_name": "PlaylistShare", "short_name": "PlaylistShare",
"id": "./", "id": "./",
"start_url": "./", "start_url": "./",