Front End Audio Player Always Available
This commit is contained in:
@@ -1,12 +1,14 @@
|
|||||||
<MudStack Row AlignItems="AlignItems.Center" Spacing="3" Class="mx-3">
|
<NavLink href="@Href" Match="@(Match ?? NavLinkMatch.Prefix)" class="nav-menu-item">
|
||||||
@if (Icon != null)
|
<div class="nav-item-content">
|
||||||
{
|
@if (Icon != null)
|
||||||
<MudIcon Icon="@Icon" />
|
|
||||||
}
|
|
||||||
<NavLink href="@Href" Match="@(Match ?? NavLinkMatch.Prefix)">
|
|
||||||
@if (ChildContent != null)
|
|
||||||
{
|
{
|
||||||
@ChildContent
|
<MudIcon Icon="@Icon" class="nav-item-icon" />
|
||||||
}
|
}
|
||||||
</NavLink>
|
<span class="nav-item-text">
|
||||||
</MudStack>
|
@if (ChildContent != null)
|
||||||
|
{
|
||||||
|
@ChildContent
|
||||||
|
}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</NavLink>
|
||||||
@@ -1 +1,71 @@
|
|||||||
|
/* Navigation menu item styling */
|
||||||
|
.nav-menu-item {
|
||||||
|
display: block;
|
||||||
|
padding: 8px 16px;
|
||||||
|
margin: 4px 8px;
|
||||||
|
border-radius: 8px;
|
||||||
|
text-decoration: none;
|
||||||
|
color: inherit;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-item-content {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
margin: 0 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-item-icon {
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-item-text {
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 14px;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hover state */
|
||||||
|
.nav-menu-item:hover {
|
||||||
|
background-color: rgba(138, 43, 226, 0.08);
|
||||||
|
color: #8A2BE2;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-menu-item:hover .nav-item-content {
|
||||||
|
color: var(--mud-palette-tertiary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-menu-item:hover .nav-item-text {
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Active state */
|
||||||
|
.nav-menu-item.active {
|
||||||
|
background-color: rgba(138, 43, 226, 0.12);
|
||||||
|
color: var(--mud-palette-primary);
|
||||||
|
border-left: 4px solid #8A2BE2;
|
||||||
|
padding-left: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-menu-item.active .nav-item-content {
|
||||||
|
color: var(--mud-palette-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-menu-item.active .nav-item-icon {
|
||||||
|
color: var(--mud-palette-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-menu-item.active .nav-item-text {
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Focus state */
|
||||||
|
.nav-menu-item:focus {
|
||||||
|
outline: 2px solid #8A2BE2;
|
||||||
|
outline-offset: 2px;
|
||||||
|
}
|
||||||
@@ -1,55 +1,87 @@
|
|||||||
<MudPaper MaxWidth="1600px" Square="true">
|
@if (_isMinimized)
|
||||||
<MudStack Row AlignItems="AlignItems.Center" Spacing="4" Class="px-4 py-2">
|
{
|
||||||
<MudStack Class="pb-2">
|
<div class="deepdrft-minimized-player-dock">
|
||||||
<MudStack Row AlignItems="AlignItems.Center">
|
<MudIconButton Icon="@GetPlayIcon()"
|
||||||
<MudIconButton Icon="@GetPlayIcon()"
|
Color="Color.Primary"
|
||||||
Color="Color.Primary"
|
Size="Size.Large"
|
||||||
Size="Size.Large"
|
Class="deepdrft-minimized-player-button"
|
||||||
OnClick="@TogglePlayPause"
|
OnClick="@ToggleMinimized" />
|
||||||
Disabled="!IsLoaded"/>
|
</div>
|
||||||
@if (IsLoaded)
|
}
|
||||||
{
|
else
|
||||||
<MudIconButton Icon="Icons.Material.Filled.Stop"
|
{
|
||||||
Color="Color.Primary"
|
@* Full-width outer container *@
|
||||||
OnClick="@Stop"
|
<div class="deepdrft-player-outer-container">
|
||||||
Disabled="!IsLoaded"/>
|
<MudContainer MaxWidth="MaxWidth.Large" Class="deepdrft-player-inner-container">
|
||||||
}
|
<div class="deepdrft-audio-player-bar">
|
||||||
</MudStack>
|
<div class="deepdrft-audio-player-content">
|
||||||
<MudStack Row AlignItems="AlignItems.Center">
|
|
||||||
<MudText Typo="Typo.body2" Class="font-monospace deepdrft-audio-time">
|
|
||||||
@FormatTime(CurrentTime) / @(Duration.HasValue ? FormatTime(Duration.Value) : "--:--")
|
|
||||||
</MudText>
|
|
||||||
@if (!IsLoaded)
|
|
||||||
{
|
|
||||||
<MudProgressCircular Color="Color.Tertiary" Value="@LoadProgress" Size="Size.Small"/>
|
|
||||||
}
|
|
||||||
</MudStack>
|
|
||||||
</MudStack>
|
|
||||||
|
|
||||||
<MudSlider T="double"
|
@* Controls section *@
|
||||||
Min="0"
|
<div class="deepdrft-audio-controls-section">
|
||||||
Max="@(Duration ?? 0D)"
|
<div class="deepdrft-audio-buttons-row">
|
||||||
Step="0.1"
|
<MudIconButton Icon="@GetPlayIcon()"
|
||||||
Value="@CurrentTime"
|
Color="Color.Primary"
|
||||||
ValueChanged="@OnSeek"
|
Size="Size.Large"
|
||||||
Disabled="!IsLoaded"
|
OnClick="@TogglePlayPause"
|
||||||
Class="deepdrft-audio-slider-seek"/>
|
Disabled="!IsLoaded"/>
|
||||||
|
@if (IsLoaded)
|
||||||
|
{
|
||||||
|
<MudIconButton Icon="@Icons.Material.Filled.Stop"
|
||||||
|
Color="Color.Primary"
|
||||||
|
OnClick="@Stop"/>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="deepdrft-audio-controls">
|
<div class="deepdrft-audio-info-row">
|
||||||
<MudIcon Icon="@GetVolumeIcon()" Class="deepdrft-audio-volume-icon"/>
|
<MudText Typo="Typo.body2" Class="font-monospace deepdrft-audio-time">
|
||||||
<MudSlider T="double"
|
@FormatTime(CurrentTime) / @(Duration.HasValue ? FormatTime(Duration.Value) : "--:--")
|
||||||
Min="0"
|
</MudText>
|
||||||
Max="1"
|
@if (!IsLoaded)
|
||||||
Step="0.01"
|
{
|
||||||
Value="@Volume"
|
<MudProgressCircular Color="Color.Tertiary" Value="@LoadProgress" Size="Size.Small"/>
|
||||||
ValueChanged="@OnVolumeChange"
|
}
|
||||||
Class="deepdrft-audio-slider"/>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</MudStack>
|
|
||||||
@if (!string.IsNullOrEmpty(ErrorMessage))
|
@* Seek slider *@
|
||||||
{
|
<MudSlider T="double"
|
||||||
<MudAlert Severity="Severity.Error" ShowCloseIcon="true" CloseIconClicked="ClearError">
|
Min="0"
|
||||||
@ErrorMessage
|
Max="@(Duration ?? 0D)"
|
||||||
</MudAlert>
|
Step="0.1"
|
||||||
}
|
Value="@CurrentTime"
|
||||||
</MudPaper>
|
ValueChanged="@OnSeek"
|
||||||
|
Disabled="!IsLoaded"
|
||||||
|
Class="deepdrft-audio-seek-slider"/>
|
||||||
|
|
||||||
|
@* Volume section *@
|
||||||
|
<div class="deepdrft-audio-volume-section">
|
||||||
|
<MudIcon Icon="@GetVolumeIcon()" Class="deepdrft-audio-volume-icon"/>
|
||||||
|
<MudSlider T="double"
|
||||||
|
Min="0"
|
||||||
|
Max="1"
|
||||||
|
Step="0.01"
|
||||||
|
Value="@Volume"
|
||||||
|
ValueChanged="@OnVolumeChange"
|
||||||
|
Class="deepdrft-audio-volume-slider"/>
|
||||||
|
</div>
|
||||||
|
<div class="deepdrft-audio-minimize-section">
|
||||||
|
<MudIconButton Icon="@Icons.Material.Filled.Minimize"
|
||||||
|
Color="Color.Secondary"
|
||||||
|
Size="Size.Small"
|
||||||
|
OnClick="@ToggleMinimized"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@if (!string.IsNullOrEmpty(ErrorMessage))
|
||||||
|
{
|
||||||
|
<MudAlert Severity="Severity.Error" ShowCloseIcon="true" CloseIconClicked="ClearError" Class="ma-2">
|
||||||
|
@ErrorMessage
|
||||||
|
</MudAlert>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</MudContainer>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@* Spacer div to maintain layout spacing *@
|
||||||
|
<div class="deepdrft-player-spacer"></div>
|
||||||
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ public partial class AudioPlayerBar : ComponentBase
|
|||||||
{
|
{
|
||||||
[CascadingParameter] public required IPlayerService PlayerService { get; set; }
|
[CascadingParameter] public required IPlayerService PlayerService { get; set; }
|
||||||
[Parameter] public bool ShowLoadProgress { get; set; } = true;
|
[Parameter] public bool ShowLoadProgress { get; set; } = true;
|
||||||
|
private bool _isMinimized = true;
|
||||||
|
|
||||||
private bool IsLoaded => PlayerService.IsLoaded;
|
private bool IsLoaded => PlayerService.IsLoaded;
|
||||||
private bool IsPlaying => PlayerService.IsPlaying;
|
private bool IsPlaying => PlayerService.IsPlaying;
|
||||||
@@ -70,4 +71,10 @@ public partial class AudioPlayerBar : ComponentBase
|
|||||||
PlayerService.ClearError();
|
PlayerService.ClearError();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ToggleMinimized()
|
||||||
|
{
|
||||||
|
_isMinimized = !_isMinimized;
|
||||||
|
StateHasChanged();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,196 @@
|
|||||||
|
/* AudioPlayerBar Component - Scoped Styles */
|
||||||
|
|
||||||
|
/* Outer container - full width, fixed to bottom */
|
||||||
|
.deepdrft-player-outer-container {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
width: 100%;
|
||||||
|
z-index: 1200;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Inner container wrapper */
|
||||||
|
.deepdrft-player-inner-container {
|
||||||
|
padding: 1rem;
|
||||||
|
padding-bottom: 1.5rem;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Player bar with rounded corners and semi-opaque background */
|
||||||
|
.deepdrft-audio-player-bar {
|
||||||
|
position: relative;
|
||||||
|
background: rgba(var(--mud-palette-surface-rgb), 0.75);
|
||||||
|
backdrop-filter: blur(12px);
|
||||||
|
-webkit-backdrop-filter: blur(12px);
|
||||||
|
border-radius: 1rem;
|
||||||
|
border: 1px solid rgba(var(--mud-palette-divider-rgb), 0.9);
|
||||||
|
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
color: var(--mud-palette-text-primary);
|
||||||
|
overflow: hidden;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Spacer div to maintain layout spacing */
|
||||||
|
.deepdrft-player-spacer {
|
||||||
|
height: 140px;
|
||||||
|
width: 100%;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Minimized floating dock */
|
||||||
|
.deepdrft-minimized-player-dock {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 60px;
|
||||||
|
right: 60px;
|
||||||
|
z-index: 1300;
|
||||||
|
width: 60px;
|
||||||
|
height: 60px;
|
||||||
|
border-radius: 50%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
background: linear-gradient(135deg,
|
||||||
|
rgba(var(--mud-palette-primary-rgb), 0.95) 0%,
|
||||||
|
rgba(var(--mud-palette-secondary-rgb), 0.9) 50%,
|
||||||
|
rgba(var(--mud-palette-tertiary-rgb), 0.95) 100%
|
||||||
|
);
|
||||||
|
backdrop-filter: blur(15px);
|
||||||
|
border: 2px solid rgba(var(--mud-palette-secondary-rgb), 0.7);
|
||||||
|
box-shadow: 0 4px 20px rgba(var(--mud-palette-primary-rgb), 0.6),
|
||||||
|
0 2px 10px rgba(0, 0, 0, 0.3);
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.deepdrft-minimized-player-dock:hover {
|
||||||
|
transform: scale(1.1);
|
||||||
|
box-shadow: 0 6px 25px rgba(var(--mud-palette-primary-rgb), 0.8),
|
||||||
|
0 3px 15px rgba(0, 0, 0, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
.deepdrft-minimized-player-button {
|
||||||
|
border-radius: 50%;
|
||||||
|
background: transparent !important;
|
||||||
|
color: white;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
box-shadow: none !important;
|
||||||
|
border: none !important;
|
||||||
|
width: 48px !important;
|
||||||
|
height: 48px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Layout containers */
|
||||||
|
.deepdrft-audio-player-content {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.75rem;
|
||||||
|
padding: 0.75rem 1.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.deepdrft-audio-controls-section {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.25rem;
|
||||||
|
min-width: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.deepdrft-audio-buttons-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.deepdrft-audio-info-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.75rem;
|
||||||
|
margin-top: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.deepdrft-audio-volume-section {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.25rem;
|
||||||
|
width: 140px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.deepdrft-audio-minimize-section {
|
||||||
|
position: absolute;
|
||||||
|
top: 0.5rem;
|
||||||
|
right: 0.5rem;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Control elements */
|
||||||
|
.deepdrft-audio-seek-slider {
|
||||||
|
flex: 1;
|
||||||
|
margin-right: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.deepdrft-audio-volume-slider {
|
||||||
|
width: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.deepdrft-audio-time {
|
||||||
|
min-width: 120px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.deepdrft-audio-volume-icon {
|
||||||
|
margin-right: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Mobile responsiveness */
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.deepdrft-minimized-player-dock {
|
||||||
|
bottom: 15px;
|
||||||
|
right: 15px;
|
||||||
|
width: 56px;
|
||||||
|
height: 56px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.deepdrft-minimized-player-button {
|
||||||
|
width: 44px !important;
|
||||||
|
height: 44px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.deepdrft-player-inner-container {
|
||||||
|
padding: 0.75rem;
|
||||||
|
padding-bottom: 1.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.deepdrft-audio-player-bar {
|
||||||
|
border-radius: 1rem;
|
||||||
|
margin-bottom: 1.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.deepdrft-audio-player-content {
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.5rem;
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.deepdrft-audio-controls-section {
|
||||||
|
align-items: center;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.deepdrft-audio-seek-slider {
|
||||||
|
margin-right: 0;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.deepdrft-audio-volume-section {
|
||||||
|
width: 100%;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.deepdrft-player-spacer {
|
||||||
|
height: 160px;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,3 @@
|
|||||||
@using DeepDrftWeb.Client.Services
|
<CascadingValue Value="@(PlayerService)" IsFixed="true">
|
||||||
|
|
||||||
<CascadingValue Value="@(PlayerService)" IsFixed="true">
|
|
||||||
@ChildContent
|
@ChildContent
|
||||||
</CascadingValue>
|
</CascadingValue>
|
||||||
@@ -13,14 +13,6 @@ public partial class AudioPlayerService : ComponentBase
|
|||||||
|
|
||||||
[Parameter] public RenderFragment? ChildContent { get; set; }
|
[Parameter] public RenderFragment? ChildContent { get; set; }
|
||||||
|
|
||||||
protected override void OnInitialized()
|
|
||||||
{
|
|
||||||
base.OnInitialized();
|
|
||||||
|
|
||||||
// PlayerService is already created as a field, so it's immediately available to cascading components
|
|
||||||
// It will be in uninitialized state until OnAfterRenderAsync when AudioPlaybackEngine is ready
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||||
{
|
{
|
||||||
if (firstRender)
|
if (firstRender)
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
<MudLayout>
|
<MudLayout>
|
||||||
<AudioPlayerService>
|
<AudioPlayerService>
|
||||||
@* <MudThemeManagerButton OnClick="@((e) => OpenThemeManager(true))" /> *@
|
@* <MudThemeManagerButton OnClick="@((e) => OpenThemeManager(true))" /> *@
|
||||||
<MudThemeManager Open="_themeManagerOpen" OpenChanged="OpenThemeManager" Theme="_themeManager" ThemeChanged="UpdateTheme" />
|
@* <MudThemeManager Open="_themeManagerOpen" OpenChanged="OpenThemeManager" Theme="_themeManager" ThemeChanged="UpdateTheme" /> *@
|
||||||
<MudAppBar Elevation="_themeManager.AppBarElevation">
|
<MudAppBar Elevation="_themeManager.AppBarElevation">
|
||||||
<MudAvatar Class="mr-2">
|
<MudAvatar Class="mr-2">
|
||||||
<MudImage Src="img/deepdrft-logo.jpg"></MudImage>
|
<MudImage Src="img/deepdrft-logo.jpg"></MudImage>
|
||||||
@@ -16,10 +16,12 @@
|
|||||||
<NavMenu />
|
<NavMenu />
|
||||||
<MudSpacer/>
|
<MudSpacer/>
|
||||||
<MudIconButton Icon="@(DarkLightModeButtonIcon)" Color="Color.Inherit" OnClick="@DarkModeToggle"/>
|
<MudIconButton Icon="@(DarkLightModeButtonIcon)" Color="Color.Inherit" OnClick="@DarkModeToggle"/>
|
||||||
<MudIconButton Icon="@Icons.Material.Filled.MoreVert" Color="Color.Inherit" Edge="Edge.End"/>
|
@* <MudIconButton Icon="@Icons.Material.Filled.MoreVert" Color="Color.Inherit" Edge="Edge.End"/> *@
|
||||||
</MudAppBar>
|
</MudAppBar>
|
||||||
<MudMainContent Class="pt-16 pa-4" Style="min-height: 100vh">
|
<MudMainContent Class="pt-16 deepdrft-layout-with-overlay-player">
|
||||||
@Body
|
<MudContainer MaxWidth="MaxWidth.False" Class="pa-4">
|
||||||
|
@Body
|
||||||
|
</MudContainer>
|
||||||
<AudioPlayerBar />
|
<AudioPlayerBar />
|
||||||
</MudMainContent>
|
</MudMainContent>
|
||||||
</AudioPlayerService>
|
</AudioPlayerService>
|
||||||
|
|||||||
@@ -33,12 +33,6 @@
|
|||||||
<Folder Include="wwwroot\js\" />
|
<Folder Include="wwwroot\js\" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<TypeScriptCompile Include="Interop\webaudio.ts">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
</TypeScriptCompile>
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<!-- Prevent TypeScript compilation issues during publish -->
|
<!-- Prevent TypeScript compilation issues during publish -->
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TypeScriptCompileOnSaveEnabled>false</TypeScriptCompileOnSaveEnabled>
|
<TypeScriptCompileOnSaveEnabled>false</TypeScriptCompileOnSaveEnabled>
|
||||||
|
|||||||
@@ -293,29 +293,28 @@ body, p, span, div,
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Audio Player Layout */
|
|
||||||
.deepdrft-audio-controls {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
width: 140px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.deepdrft-audio-time {
|
/* Layout with overlay audio player - Global layout class */
|
||||||
min-width: 120px;
|
/*.deepdrft-layout-with-overlay-player {*/
|
||||||
}
|
/* position: relative;*/
|
||||||
|
/* min-height: calc(100vh - 64px);*/
|
||||||
|
/* padding-bottom: 160px; !* Increased space for overlay player *!*/
|
||||||
|
/*}*/
|
||||||
|
|
||||||
.deepdrft-audio-volume-icon {
|
/*!* Audio player overlay positioning - Global positioning *!*/
|
||||||
margin-right: 4px;
|
/*.deepdrft-layout-with-overlay-player > .AudioPlayerBar,*/
|
||||||
}
|
/*.deepdrft-layout-with-overlay-player > *:last-child {*/
|
||||||
|
/* position: fixed;*/
|
||||||
|
/* bottom: 0;*/
|
||||||
|
/* left: 0;*/
|
||||||
|
/* right: 0;*/
|
||||||
|
/* z-index: 1000;*/
|
||||||
|
/* pointer-events: none;*/
|
||||||
|
/*}*/
|
||||||
|
|
||||||
.deepdrft-audio-slider {
|
/*.deepdrft-layout-with-overlay-player > *:last-child > * {*/
|
||||||
flex: 1;
|
/* pointer-events: auto;*/
|
||||||
}
|
/*}*/
|
||||||
|
|
||||||
.deepdrft-audio-slider-seek {
|
|
||||||
flex: 1;
|
|
||||||
margin-right: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Responsive Utilities */
|
/* Responsive Utilities */
|
||||||
@media (max-width: 768px) {
|
@media (max-width: 768px) {
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ ssh-add /c/.ssh/deepdrft_ed25519
|
|||||||
|
|
||||||
CONTENT_PROJ="DeepDrftContent"
|
CONTENT_PROJ="DeepDrftContent"
|
||||||
WEB_PROJ="DeepDrftWeb"
|
WEB_PROJ="DeepDrftWeb"
|
||||||
|
WEB_SERVICES_PROJ="DeepDrftWeb.Services"
|
||||||
CONTENT_APP="deepdrft-content.tar.gz"
|
CONTENT_APP="deepdrft-content.tar.gz"
|
||||||
WEB_APP="deepdrft-web.tar.gz"
|
WEB_APP="deepdrft-web.tar.gz"
|
||||||
|
|
||||||
@@ -16,15 +17,15 @@ WEB_MIG="deepdrft-migrations.sql"
|
|||||||
REMOTE="deepdrft@dch5.snailbird.net"
|
REMOTE="deepdrft@dch5.snailbird.net"
|
||||||
WEB_APPROOT="/deepdrft/web"
|
WEB_APPROOT="/deepdrft/web"
|
||||||
|
|
||||||
LATEST_MIGRATION=$(dotnet ef migrations list --project $WEB_PROJ --context DeepDrftContext --no-build | tail -1)
|
LATEST_MIGRATION=$(dotnet ef migrations list --project $WEB_SERVICES_PROJ --context DeepDrftContext --no-build | tail -1)
|
||||||
REMOTE_MIGRATION=$(ssh $REMOTE "sqlite3 $WEB_APPROOT/Database/deepdrft.db 'SELECT MigrationId FROM __EFMigrationsHistory ORDER BY MigrationId DESC LIMIT 1;'" 2>/dev/null || echo "")
|
REMOTE_MIGRATION=$(ssh $REMOTE "sqlite3 $WEB_APPROOT/Database/deepdrft.db 'SELECT MigrationId FROM __EFMigrationsHistory ORDER BY MigrationId DESC LIMIT 1;'" 2>/dev/null || echo "")
|
||||||
|
|
||||||
if [ "$LATEST_MIGRATION" != "$REMOTE_MIGRATION" ]; then
|
if [ "$LATEST_MIGRATION" != "$REMOTE_MIGRATION" ]; then
|
||||||
echo "Generating migration script from $REMOTE_MIGRATION to $LATEST_MIGRATION..."
|
echo "Generating migration script from $REMOTE_MIGRATION to $LATEST_MIGRATION..."
|
||||||
if [ -z "$REMOTE_MIGRATION" ]; then
|
if [ -z "$REMOTE_MIGRATION" ]; then
|
||||||
dotnet ef migrations script --project $WEB_PROJ --context DeepDrftContext --output $WEB_MIG --verbose --no-build
|
dotnet ef migrations script --project $WEB_SERVICES_PROJ --context DeepDrftContext --output $WEB_MIG --verbose --no-build
|
||||||
else
|
else
|
||||||
dotnet ef migrations script $REMOTE_MIGRATION --project $WEB_PROJ --context DeepDrftContext --output $WEB_MIG --verbose --no-build
|
dotnet ef migrations script $REMOTE_MIGRATION --project $WEB_SERVICES_PROJ --context DeepDrftContext --output $WEB_MIG --verbose --no-build
|
||||||
fi
|
fi
|
||||||
APPLY_MIGRATIONS=true
|
APPLY_MIGRATIONS=true
|
||||||
else
|
else
|
||||||
|
|||||||
Reference in New Issue
Block a user