mirror of
https://github.com/jayfunc/BetterLyrics.git
synced 2026-01-12 19:24:55 +08:00
Compare commits
21 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
94e76a6ac9 | ||
|
|
516d388009 | ||
|
|
ad33eed57c | ||
|
|
64bf2dc3d9 | ||
|
|
b86e4a3d12 | ||
|
|
411506b9cd | ||
|
|
f681b43e96 | ||
|
|
133acf5592 | ||
|
|
cbaa81b9bb | ||
|
|
b834be49ce | ||
|
|
8abe6d7f01 | ||
|
|
8a73ba9e6a | ||
|
|
49a090b0c7 | ||
|
|
a47dd67056 | ||
|
|
900ecc9776 | ||
|
|
464742d7c5 | ||
|
|
5f3aad4e99 | ||
|
|
7b6eca6ff6 | ||
|
|
9fcb1ac869 | ||
|
|
74ebda2b6d | ||
|
|
e194dfaa70 |
@@ -12,7 +12,7 @@
|
|||||||
<Identity
|
<Identity
|
||||||
Name="37412.BetterLyrics"
|
Name="37412.BetterLyrics"
|
||||||
Publisher="CN=E1428B0E-DC1D-4EA4-ACB1-4556569D5BA9"
|
Publisher="CN=E1428B0E-DC1D-4EA4-ACB1-4556569D5BA9"
|
||||||
Version="1.0.46.0" />
|
Version="1.0.56.0" />
|
||||||
|
|
||||||
<mp:PhoneIdentity PhoneProductId="ca4a4830-fc19-40d9-b823-53e2bff3d816" PhonePublisherId="00000000-0000-0000-0000-000000000000"/>
|
<mp:PhoneIdentity PhoneProductId="ca4a4830-fc19-40d9-b823-53e2bff3d816" PhonePublisherId="00000000-0000-0000-0000-000000000000"/>
|
||||||
|
|
||||||
|
|||||||
@@ -10,10 +10,10 @@
|
|||||||
<Application.Resources>
|
<Application.Resources>
|
||||||
<ResourceDictionary>
|
<ResourceDictionary>
|
||||||
<ResourceDictionary.MergedDictionaries>
|
<ResourceDictionary.MergedDictionaries>
|
||||||
|
<!-- Merged dictionaries here -->
|
||||||
<XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls" />
|
<XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls" />
|
||||||
<ResourceDictionary Source="ms-appx:///CommunityToolkit.WinUI.Controls.SettingsControls/SettingsExpander/SettingsExpander.xaml" />
|
<ResourceDictionary Source="ms-appx:///CommunityToolkit.WinUI.Controls.SettingsControls/SettingsExpander/SettingsExpander.xaml" />
|
||||||
<ResourceDictionary Source="ms-appx:///CommunityToolkit.WinUI.Controls.Segmented/Segmented/Segmented.xaml" />
|
<ResourceDictionary Source="ms-appx:///CommunityToolkit.WinUI.Controls.Segmented/Segmented/Segmented.xaml" />
|
||||||
<!-- Other merged dictionaries here -->
|
|
||||||
</ResourceDictionary.MergedDictionaries>
|
</ResourceDictionary.MergedDictionaries>
|
||||||
|
|
||||||
<!-- Theme -->
|
<!-- Theme -->
|
||||||
@@ -53,6 +53,9 @@
|
|||||||
<converter:SecondsToFormattedTimeConverter x:Key="SecondsToFormattedTimeConverter" />
|
<converter:SecondsToFormattedTimeConverter x:Key="SecondsToFormattedTimeConverter" />
|
||||||
<converter:MediaSourceProviderToLogoUriConverter x:Key="MediaSourceProviderToLogoUriConverter" />
|
<converter:MediaSourceProviderToLogoUriConverter x:Key="MediaSourceProviderToLogoUriConverter" />
|
||||||
<converter:MediaSourceProviderToDisplayedNameConverter x:Key="MediaSourceProviderToDisplayedNameConverter" />
|
<converter:MediaSourceProviderToDisplayedNameConverter x:Key="MediaSourceProviderToDisplayedNameConverter" />
|
||||||
|
<converter:FPSToTimeSpanConverter x:Key="FPSToTimeSpanConverter" />
|
||||||
|
<converter:ShortcutToStringConverter x:Key="ShortcutToStringConverter" />
|
||||||
|
|
||||||
<converters:BoolToVisibilityConverter x:Key="BoolToVisibilityConverter" />
|
<converters:BoolToVisibilityConverter x:Key="BoolToVisibilityConverter" />
|
||||||
<converters:BoolNegationConverter x:Key="BoolNegationConverter" />
|
<converters:BoolNegationConverter x:Key="BoolNegationConverter" />
|
||||||
<converters:ColorToDisplayNameConverter x:Key="ColorToDisplayNameConverter" />
|
<converters:ColorToDisplayNameConverter x:Key="ColorToDisplayNameConverter" />
|
||||||
@@ -308,6 +311,18 @@
|
|||||||
<Setter Property="Padding" Value="0,0,0,36" />
|
<Setter Property="Padding" Value="0,0,0,36" />
|
||||||
</Style>
|
</Style>
|
||||||
|
|
||||||
|
<Style
|
||||||
|
x:Key="FlyoutPageStyle"
|
||||||
|
BasedOn="{StaticResource DefaultFlyoutPresenterStyle}"
|
||||||
|
TargetType="FlyoutPresenter">
|
||||||
|
<Setter Property="Opacity" Value="0.9" />
|
||||||
|
<Setter Property="MinWidth" Value="850" />
|
||||||
|
<Setter Property="Padding" Value="0" />
|
||||||
|
<Setter Property="ScrollViewer.VerticalScrollMode" Value="Disabled" />
|
||||||
|
<Setter Property="ScrollViewer.HorizontalScrollMode" Value="Disabled" />
|
||||||
|
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Hidden" />
|
||||||
|
</Style>
|
||||||
|
|
||||||
<StaticResource x:Key="ToggleButtonBackgroundChecked" ResourceKey="TextFillColorPrimaryBrush" />
|
<StaticResource x:Key="ToggleButtonBackgroundChecked" ResourceKey="TextFillColorPrimaryBrush" />
|
||||||
<StaticResource x:Key="ToggleButtonBackgroundCheckedPointerOver" ResourceKey="TextFillColorPrimaryBrush" />
|
<StaticResource x:Key="ToggleButtonBackgroundCheckedPointerOver" ResourceKey="TextFillColorPrimaryBrush" />
|
||||||
<StaticResource x:Key="ToggleButtonBackgroundCheckedPressed" ResourceKey="TextFillColorPrimaryBrush" />
|
<StaticResource x:Key="ToggleButtonBackgroundCheckedPressed" ResourceKey="TextFillColorPrimaryBrush" />
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ using BetterLyrics.WinUI3.Services;
|
|||||||
using BetterLyrics.WinUI3.Services.AlbumArtSearchService;
|
using BetterLyrics.WinUI3.Services.AlbumArtSearchService;
|
||||||
using BetterLyrics.WinUI3.Services.LastFMService;
|
using BetterLyrics.WinUI3.Services.LastFMService;
|
||||||
using BetterLyrics.WinUI3.Services.LibWatcherService;
|
using BetterLyrics.WinUI3.Services.LibWatcherService;
|
||||||
|
using BetterLyrics.WinUI3.Services.LiveStatesService;
|
||||||
using BetterLyrics.WinUI3.Services.LyricsSearchService;
|
using BetterLyrics.WinUI3.Services.LyricsSearchService;
|
||||||
using BetterLyrics.WinUI3.Services.MediaSessionsService;
|
using BetterLyrics.WinUI3.Services.MediaSessionsService;
|
||||||
using BetterLyrics.WinUI3.Services.SettingsService;
|
using BetterLyrics.WinUI3.Services.SettingsService;
|
||||||
@@ -84,13 +85,6 @@ namespace BetterLyrics.WinUI3
|
|||||||
protected override void OnLaunched(LaunchActivatedEventArgs args)
|
protected override void OnLaunched(LaunchActivatedEventArgs args)
|
||||||
{
|
{
|
||||||
WindowHelper.OpenWindow<LyricsWindow>();
|
WindowHelper.OpenWindow<LyricsWindow>();
|
||||||
|
|
||||||
var lyricsWindow = WindowHelper.GetWindowByWindowType<LyricsWindow>();
|
|
||||||
if (lyricsWindow != null)
|
|
||||||
{
|
|
||||||
lyricsWindow.ViewModel.InitLockHotKey();
|
|
||||||
lyricsWindow.AutoSelectLyricsMode();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void ConfigureServices()
|
private static void ConfigureServices()
|
||||||
@@ -109,6 +103,7 @@ namespace BetterLyrics.WinUI3
|
|||||||
loggingBuilder.AddSerilog();
|
loggingBuilder.AddSerilog();
|
||||||
})
|
})
|
||||||
// Services
|
// Services
|
||||||
|
.AddSingleton<ILiveStatesService, LiveStatesService>()
|
||||||
.AddSingleton<ISettingsService, SettingsService>()
|
.AddSingleton<ISettingsService, SettingsService>()
|
||||||
.AddSingleton<IMediaSessionsService, MediaSessionsService>()
|
.AddSingleton<IMediaSessionsService, MediaSessionsService>()
|
||||||
.AddSingleton<IAlbumArtSearchService, AlbumArtSearchService>()
|
.AddSingleton<IAlbumArtSearchService, AlbumArtSearchService>()
|
||||||
|
|||||||
BIN
BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/Cover.jpg
Normal file
BIN
BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/Cover.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 84 KiB |
@@ -26,10 +26,10 @@
|
|||||||
<None Remove="Controls\AllLyricsSettingsControl.xaml" />
|
<None Remove="Controls\AllLyricsSettingsControl.xaml" />
|
||||||
<None Remove="Controls\AppSettingsControl.xaml" />
|
<None Remove="Controls\AppSettingsControl.xaml" />
|
||||||
<None Remove="Controls\ExtendedSlider.xaml" />
|
<None Remove="Controls\ExtendedSlider.xaml" />
|
||||||
<None Remove="Controls\LyricsBavkgroundSettingsControl.xaml" />
|
|
||||||
<None Remove="Controls\LyricsSettingsControl.xaml" />
|
<None Remove="Controls\LyricsSettingsControl.xaml" />
|
||||||
<None Remove="Controls\MediaSettingsControl.xaml" />
|
<None Remove="Controls\MediaSettingsControl.xaml" />
|
||||||
<None Remove="Controls\PlaybackSettingsControl.xaml" />
|
<None Remove="Controls\PlaybackSettingsControl.xaml" />
|
||||||
|
<None Remove="Controls\ShortcutTextBox.xaml" />
|
||||||
<None Remove="Controls\SystemTray.xaml" />
|
<None Remove="Controls\SystemTray.xaml" />
|
||||||
<None Remove="Views\MusicGalleryPage.xaml" />
|
<None Remove="Views\MusicGalleryPage.xaml" />
|
||||||
<None Remove="Views\MusicGalleryWindow.xaml" />
|
<None Remove="Views\MusicGalleryWindow.xaml" />
|
||||||
@@ -60,6 +60,7 @@
|
|||||||
<PackageReference Include="CommunityToolkit.WinUI.Media" Version="8.2.250402" />
|
<PackageReference Include="CommunityToolkit.WinUI.Media" Version="8.2.250402" />
|
||||||
<PackageReference Include="Dubya.WindowsMediaController" Version="2.5.5" />
|
<PackageReference Include="Dubya.WindowsMediaController" Version="2.5.5" />
|
||||||
<PackageReference Include="H.NotifyIcon.WinUI" Version="2.3.0" />
|
<PackageReference Include="H.NotifyIcon.WinUI" Version="2.3.0" />
|
||||||
|
<PackageReference Include="Hqub.Last.fm" Version="2.5.1" />
|
||||||
<PackageReference Include="Lyricify.Lyrics.Helper-NativeAot" Version="0.1.4-alpha.5" />
|
<PackageReference Include="Lyricify.Lyrics.Helper-NativeAot" Version="0.1.4-alpha.5" />
|
||||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="9.0.8" />
|
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="9.0.8" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="9.0.8" />
|
<PackageReference Include="Microsoft.Extensions.Logging" Version="9.0.8" />
|
||||||
@@ -86,11 +87,6 @@
|
|||||||
<PackageReference Include="WinUIEx" Version="2.6.0" />
|
<PackageReference Include="WinUIEx" Version="2.6.0" />
|
||||||
<PackageReference Include="z440.atl.core" Version="7.2.0" />
|
<PackageReference Include="z440.atl.core" Version="7.2.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
|
||||||
<Reference Include="Hqub.Lastfm">
|
|
||||||
<HintPath>..\..\..\Last.fm\src\Hqub.Lastfm\bin\Release\netstandard2.0\Hqub.Lastfm.dll</HintPath>
|
|
||||||
</Reference>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Page Update="Rendering\InAppLyricsRenderer.xaml">
|
<Page Update="Rendering\InAppLyricsRenderer.xaml">
|
||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
@@ -185,6 +181,11 @@
|
|||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Page Update="Controls\ShortcutTextBox.xaml">
|
||||||
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
</Page>
|
||||||
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Page Update="Controls\ExtendedSlider.xaml">
|
<Page Update="Controls\ExtendedSlider.xaml">
|
||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
@@ -216,7 +217,7 @@
|
|||||||
</Page>
|
</Page>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Page Update="Controls\LyricsBavkgroundSettingsControl.xaml">
|
<Page Update="Controls\LyricsBackgroundSettingsControl.xaml">
|
||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
</Page>
|
</Page>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
<TextBlock x:Uid="SettingsPageAlbumArt" Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" />
|
<TextBlock x:Uid="SettingsPageAlbumArt" Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" />
|
||||||
|
|
||||||
<controls:SettingsCard x:Uid="SettingsPageAlbumRadius" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
<controls:SettingsCard x:Uid="SettingsPageAlbumRadius" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||||
<local:ExtendedSlider
|
<local:ExtendedSlider
|
||||||
Default="12"
|
Default="12"
|
||||||
Frequency="1"
|
Frequency="1"
|
||||||
@@ -27,6 +27,15 @@
|
|||||||
Value="{x:Bind ViewModel.AppSettings.AlbumArtLayoutSettings.CoverImageRadius, Mode=TwoWay}" />
|
Value="{x:Bind ViewModel.AppSettings.AlbumArtLayoutSettings.CoverImageRadius, Mode=TwoWay}" />
|
||||||
</controls:SettingsCard>
|
</controls:SettingsCard>
|
||||||
|
|
||||||
|
<controls:SettingsCard x:Uid="SettingsPageAlbumShadowAmount" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||||
|
<local:ExtendedSlider
|
||||||
|
Default="12"
|
||||||
|
Frequency="1"
|
||||||
|
Maximum="64"
|
||||||
|
Minimum="0"
|
||||||
|
Value="{x:Bind ViewModel.AppSettings.AlbumArtLayoutSettings.CoverImageShadowAmount, Mode=TwoWay}" />
|
||||||
|
</controls:SettingsCard>
|
||||||
|
|
||||||
<TextBlock x:Uid="SettingsPageSongInfo" Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" />
|
<TextBlock x:Uid="SettingsPageSongInfo" Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" />
|
||||||
|
|
||||||
<controls:SettingsCard x:Uid="SettingsPageSongInfoAlignment" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
<controls:SettingsCard x:Uid="SettingsPageSongInfoAlignment" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||||
|
|||||||
@@ -21,16 +21,20 @@
|
|||||||
<controls:Case Value="Dock">
|
<controls:Case Value="Dock">
|
||||||
<uc:LyricsSettingsControl LyricsEffectSettings="{x:Bind ViewModel.AppSettings.DockLyricsEffectSettings, Mode=OneWay}" LyricsStyleSettings="{x:Bind ViewModel.AppSettings.DockLyricsStyleSettings, Mode=OneWay}" />
|
<uc:LyricsSettingsControl LyricsEffectSettings="{x:Bind ViewModel.AppSettings.DockLyricsEffectSettings, Mode=OneWay}" LyricsStyleSettings="{x:Bind ViewModel.AppSettings.DockLyricsStyleSettings, Mode=OneWay}" />
|
||||||
</controls:Case>
|
</controls:Case>
|
||||||
|
<controls:Case Value="PictureInPicture">
|
||||||
|
<uc:LyricsSettingsControl LyricsEffectSettings="{x:Bind ViewModel.AppSettings.PictureInPictureLyricsEffectSettings, Mode=OneWay}" LyricsStyleSettings="{x:Bind ViewModel.AppSettings.PictureInPictureLyricsStyleSettings, Mode=OneWay}" />
|
||||||
|
</controls:Case>
|
||||||
</controls:SwitchPresenter>
|
</controls:SwitchPresenter>
|
||||||
<controls:Segmented
|
<controls:Segmented
|
||||||
x:Name="LyricsSettingsSegmentedControl"
|
x:Name="LyricsSettingsSegmentedControl"
|
||||||
Margin="36,36,36,0"
|
Margin="36,36,36,0"
|
||||||
HorizontalAlignment="Stretch"
|
HorizontalAlignment="Stretch"
|
||||||
VerticalAlignment="Top"
|
VerticalAlignment="Top"
|
||||||
SelectedIndex="0">
|
SelectedIndex="{x:Bind ViewModel.SelectedTabIndex, Mode=OneWay}">
|
||||||
<controls:SegmentedItem x:Uid="AllLyricsSettingsControlStandard" Tag="Standard" />
|
<controls:SegmentedItem x:Uid="AllLyricsSettingsControlStandard" Tag="Standard" />
|
||||||
<controls:SegmentedItem x:Uid="AllLyricsSettingsControlDesktop" Tag="Desktop" />
|
|
||||||
<controls:SegmentedItem x:Uid="AllLyricsSettingsControlDock" Tag="Dock" />
|
<controls:SegmentedItem x:Uid="AllLyricsSettingsControlDock" Tag="Dock" />
|
||||||
|
<controls:SegmentedItem x:Uid="AllLyricsSettingsControlDesktop" Tag="Desktop" />
|
||||||
|
<controls:SegmentedItem x:Uid="AllLyricsSettingsControlPictureInPicture" Tag="PictureInPicture" />
|
||||||
</controls:Segmented>
|
</controls:Segmented>
|
||||||
</Grid>
|
</Grid>
|
||||||
</UserControl>
|
</UserControl>
|
||||||
|
|||||||
@@ -55,6 +55,7 @@
|
|||||||
<ComboBoxItem x:Uid="SettingsPageAutoStartInAppLyrics" />
|
<ComboBoxItem x:Uid="SettingsPageAutoStartInAppLyrics" />
|
||||||
<ComboBoxItem x:Uid="SettingsPageAutoStartDockLyrics" />
|
<ComboBoxItem x:Uid="SettingsPageAutoStartDockLyrics" />
|
||||||
<ComboBoxItem x:Uid="SettingsPageAutoStartDesktopLyrics" />
|
<ComboBoxItem x:Uid="SettingsPageAutoStartDesktopLyrics" />
|
||||||
|
<ComboBoxItem x:Uid="SettingsPageAutoStartPIPLyrics" />
|
||||||
</ComboBox>
|
</ComboBox>
|
||||||
</controls:SettingsCard>
|
</controls:SettingsCard>
|
||||||
|
|
||||||
@@ -70,55 +71,62 @@
|
|||||||
<ToggleSwitch IsOn="{x:Bind ViewModel.AppSettings.GeneralSettings.IsDragEverywhereEnabled, Mode=TwoWay}" />
|
<ToggleSwitch IsOn="{x:Bind ViewModel.AppSettings.GeneralSettings.IsDragEverywhereEnabled, Mode=TwoWay}" />
|
||||||
</controls:SettingsCard>
|
</controls:SettingsCard>
|
||||||
|
|
||||||
|
<controls:SettingsCard x:Uid="SettingsPageExitOnLyricsWindowClosed" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||||
|
<ToggleSwitch IsOn="{x:Bind ViewModel.AppSettings.GeneralSettings.ExitOnLyricsWindowClosed, Mode=TwoWay}" />
|
||||||
|
</controls:SettingsCard>
|
||||||
|
|
||||||
|
<!-- Standard mode -->
|
||||||
|
|
||||||
|
<TextBlock x:Uid="SettingsPageAppStandard" Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" />
|
||||||
|
|
||||||
|
<controls:SettingsCard x:Uid="SettingsPageDisplayTypeSwitcher" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||||
|
<ComboBox SelectedIndex="{x:Bind ViewModel.AppSettings.StandardModeSettings.LyricsDisplayType, Mode=TwoWay, Converter={StaticResource EnumToIntConverter}}">
|
||||||
|
<ComboBoxItem x:Uid="MainPageAlbumArtOnly" />
|
||||||
|
<ComboBoxItem x:Uid="MainPageLyriscOnly" />
|
||||||
|
<ComboBoxItem x:Uid="MainPageSplitView" />
|
||||||
|
</ComboBox>
|
||||||
|
</controls:SettingsCard>
|
||||||
|
|
||||||
<!-- Desktop mode -->
|
<!-- Desktop mode -->
|
||||||
|
|
||||||
<TextBlock x:Uid="SettingsPageAppDesktop" Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" />
|
<TextBlock x:Uid="SettingsPageAppDesktop" Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" />
|
||||||
|
|
||||||
|
<controls:SettingsCard x:Uid="SettingsPageToggleHotKey" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||||
|
<local:ShortcutTextBox Shortcut="{x:Bind ViewModel.AppSettings.DesktopModeSettings.ToggleShortcut, Mode=TwoWay}" />
|
||||||
|
</controls:SettingsCard>
|
||||||
|
|
||||||
|
<controls:SettingsCard x:Uid="SettingsPageDisplayTypeSwitcher" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||||
|
<ComboBox SelectedIndex="{x:Bind ViewModel.AppSettings.DesktopModeSettings.LyricsDisplayType, Mode=TwoWay, Converter={StaticResource EnumToIntConverter}}">
|
||||||
|
<ComboBoxItem x:Uid="MainPageAlbumArtOnly" />
|
||||||
|
<ComboBoxItem x:Uid="MainPageLyriscOnly" />
|
||||||
|
<ComboBoxItem x:Uid="MainPageSplitView" />
|
||||||
|
</ComboBox>
|
||||||
|
</controls:SettingsCard>
|
||||||
|
|
||||||
<controls:SettingsCard x:Uid="SettingsPageAutoLock" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
<controls:SettingsCard x:Uid="SettingsPageAutoLock" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||||
<ToggleSwitch IsOn="{x:Bind ViewModel.AppSettings.DesktopModeSettings.AutoLockOnDesktopMode, Mode=TwoWay}" />
|
<ToggleSwitch IsOn="{x:Bind ViewModel.AppSettings.DesktopModeSettings.AutoLockOnDesktopMode, Mode=TwoWay}" />
|
||||||
</controls:SettingsCard>
|
</controls:SettingsCard>
|
||||||
|
|
||||||
<controls:SettingsCard x:Uid="SettingsPageLockHotKey" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
<controls:SettingsCard x:Uid="SettingsPageLockHotKey" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||||
<StackPanel Orientation="Horizontal" Spacing="6">
|
<local:ShortcutTextBox Shortcut="{x:Bind ViewModel.AppSettings.DesktopModeSettings.LockShortcut, Mode=TwoWay}" />
|
||||||
<TextBlock
|
|
||||||
Margin="0,0,0,2"
|
|
||||||
VerticalAlignment="Center"
|
|
||||||
Text="Ctrl + Alt + " />
|
|
||||||
<ComboBox SelectedIndex="{x:Bind ViewModel.AppSettings.DesktopModeSettings.LockHotKeyIndex, Mode=TwoWay}">
|
|
||||||
<ComboBoxItem Content="A" />
|
|
||||||
<ComboBoxItem Content="B" />
|
|
||||||
<ComboBoxItem Content="C" />
|
|
||||||
<ComboBoxItem Content="D" />
|
|
||||||
<ComboBoxItem Content="E" />
|
|
||||||
<ComboBoxItem Content="F" />
|
|
||||||
<ComboBoxItem Content="G" />
|
|
||||||
<ComboBoxItem Content="H" />
|
|
||||||
<ComboBoxItem Content="I" />
|
|
||||||
<ComboBoxItem Content="J" />
|
|
||||||
<ComboBoxItem Content="K" />
|
|
||||||
<ComboBoxItem Content="L" />
|
|
||||||
<ComboBoxItem Content="M" />
|
|
||||||
<ComboBoxItem Content="N" />
|
|
||||||
<ComboBoxItem Content="O" />
|
|
||||||
<ComboBoxItem Content="P" />
|
|
||||||
<ComboBoxItem Content="Q" />
|
|
||||||
<ComboBoxItem Content="R" />
|
|
||||||
<ComboBoxItem Content="S" />
|
|
||||||
<ComboBoxItem Content="T" />
|
|
||||||
<ComboBoxItem Content="U" />
|
|
||||||
<ComboBoxItem Content="V" />
|
|
||||||
<ComboBoxItem Content="W" />
|
|
||||||
<ComboBoxItem Content="X" />
|
|
||||||
<ComboBoxItem Content="Y" />
|
|
||||||
<ComboBoxItem Content="Z" />
|
|
||||||
</ComboBox>
|
|
||||||
</StackPanel>
|
|
||||||
</controls:SettingsCard>
|
</controls:SettingsCard>
|
||||||
|
|
||||||
<!-- Dock mode -->
|
<!-- Dock mode -->
|
||||||
|
|
||||||
<TextBlock x:Uid="SettingsPageAppDock" Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" />
|
<TextBlock x:Uid="SettingsPageAppDock" Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" />
|
||||||
|
|
||||||
|
<controls:SettingsCard x:Uid="SettingsPageToggleHotKey" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||||
|
<local:ShortcutTextBox Shortcut="{x:Bind ViewModel.AppSettings.DockModeSettings.ToggleShortcut, Mode=TwoWay}" />
|
||||||
|
</controls:SettingsCard>
|
||||||
|
|
||||||
|
<controls:SettingsCard x:Uid="SettingsPageDisplayTypeSwitcher" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||||
|
<ComboBox SelectedIndex="{x:Bind ViewModel.AppSettings.DockModeSettings.LyricsDisplayType, Mode=TwoWay, Converter={StaticResource EnumToIntConverter}}">
|
||||||
|
<ComboBoxItem x:Uid="MainPageAlbumArtOnly" />
|
||||||
|
<ComboBoxItem x:Uid="MainPageLyriscOnly" />
|
||||||
|
<ComboBoxItem x:Uid="MainPageSplitView" />
|
||||||
|
</ComboBox>
|
||||||
|
</controls:SettingsCard>
|
||||||
|
|
||||||
<controls:SettingsCard x:Uid="SettingsPageDockMonitor" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
<controls:SettingsCard x:Uid="SettingsPageDockMonitor" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||||
<StackPanel Orientation="Horizontal" Spacing="6">
|
<StackPanel Orientation="Horizontal" Spacing="6">
|
||||||
<ComboBox ItemsSource="{x:Bind ViewModel.MonitorDeviceNames, Mode=OneWay}" SelectedItem="{x:Bind ViewModel.AppSettings.DockModeSettings.DockMonitorDeviceName, Mode=TwoWay}" />
|
<ComboBox ItemsSource="{x:Bind ViewModel.MonitorDeviceNames, Mode=OneWay}" SelectedItem="{x:Bind ViewModel.AppSettings.DockModeSettings.DockMonitorDeviceName, Mode=TwoWay}" />
|
||||||
@@ -148,6 +156,38 @@
|
|||||||
</ComboBox>
|
</ComboBox>
|
||||||
</controls:SettingsCard>
|
</controls:SettingsCard>
|
||||||
|
|
||||||
|
<!-- Picture in picture mode -->
|
||||||
|
|
||||||
|
<TextBlock x:Uid="SettingsPageAppPictureInPicture" Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" />
|
||||||
|
|
||||||
|
<controls:SettingsCard x:Uid="SettingsPageToggleHotKey" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||||
|
<local:ShortcutTextBox Shortcut="{x:Bind ViewModel.AppSettings.PictureInPictureModeSettings.ToggleShortcut, Mode=TwoWay}" />
|
||||||
|
</controls:SettingsCard>
|
||||||
|
|
||||||
|
<controls:SettingsCard x:Uid="SettingsPageDisplayTypeSwitcher" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||||
|
<ComboBox SelectedIndex="{x:Bind ViewModel.AppSettings.PictureInPictureModeSettings.LyricsDisplayType, Mode=TwoWay, Converter={StaticResource EnumToIntConverter}}">
|
||||||
|
<ComboBoxItem x:Uid="MainPageAlbumArtOnly" />
|
||||||
|
<ComboBoxItem x:Uid="MainPageLyriscOnly" />
|
||||||
|
<ComboBoxItem x:Uid="MainPageSplitView" />
|
||||||
|
</ComboBox>
|
||||||
|
</controls:SettingsCard>
|
||||||
|
|
||||||
|
<!-- Playback shortcut -->
|
||||||
|
|
||||||
|
<TextBlock x:Uid="SettingsPagePlaybackShortcut" Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" />
|
||||||
|
|
||||||
|
<controls:SettingsCard x:Uid="SettingsPagePlayOrPauseSongHotKey" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||||
|
<local:ShortcutTextBox Shortcut="{x:Bind ViewModel.AppSettings.GeneralSettings.PlayOrPauseShortcut, Mode=TwoWay}" />
|
||||||
|
</controls:SettingsCard>
|
||||||
|
|
||||||
|
<controls:SettingsCard x:Uid="SettingsPageNextSongHotKey" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||||
|
<local:ShortcutTextBox Shortcut="{x:Bind ViewModel.AppSettings.GeneralSettings.NextSongShortcut, Mode=TwoWay}" />
|
||||||
|
</controls:SettingsCard>
|
||||||
|
|
||||||
|
<controls:SettingsCard x:Uid="SettingsPagePreviousSongHotKey" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||||
|
<local:ShortcutTextBox Shortcut="{x:Bind ViewModel.AppSettings.GeneralSettings.PreviousSongShortcut, Mode=TwoWay}" />
|
||||||
|
</controls:SettingsCard>
|
||||||
|
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Grid>
|
</Grid>
|
||||||
</ScrollViewer>
|
</ScrollViewer>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8" ?>
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
<UserControl
|
<UserControl
|
||||||
x:Class="BetterLyrics.WinUI3.Controls.LyricsBavkgroundSettingsControl"
|
x:Class="BetterLyrics.WinUI3.Controls.LyricsBackgroundSettingsControl"
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:controls="using:CommunityToolkit.WinUI.Controls"
|
xmlns:controls="using:CommunityToolkit.WinUI.Controls"
|
||||||
@@ -25,7 +25,7 @@
|
|||||||
</ComboBox>
|
</ComboBox>
|
||||||
</controls:SettingsCard>
|
</controls:SettingsCard>
|
||||||
|
|
||||||
<controls:SettingsCard x:Uid="SettingsPageLyricsPureColorBgOpacity" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
<controls:SettingsCard x:Uid="SettingsPageLyricsPureColorBgOpacity" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||||
<uc:ExtendedSlider
|
<uc:ExtendedSlider
|
||||||
Default="100"
|
Default="100"
|
||||||
Frequency="1"
|
Frequency="1"
|
||||||
@@ -35,7 +35,7 @@
|
|||||||
Value="{x:Bind ViewModel.AppSettings.LyricsBackgroundSettings.PureColorOverlayOpacity, Mode=TwoWay}" />
|
Value="{x:Bind ViewModel.AppSettings.LyricsBackgroundSettings.PureColorOverlayOpacity, Mode=TwoWay}" />
|
||||||
</controls:SettingsCard>
|
</controls:SettingsCard>
|
||||||
|
|
||||||
<controls:SettingsCard x:Uid="SettingsPageLyricsBackgroundOpacity" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
<controls:SettingsCard x:Uid="SettingsPageLyricsBackgroundOpacity" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||||
<uc:ExtendedSlider
|
<uc:ExtendedSlider
|
||||||
Default="100"
|
Default="100"
|
||||||
Frequency="1"
|
Frequency="1"
|
||||||
@@ -64,7 +64,7 @@
|
|||||||
Value="{x:Bind ViewModel.AppSettings.LyricsBackgroundSettings.CoverOverlayBlurAmount, Mode=TwoWay}" />
|
Value="{x:Bind ViewModel.AppSettings.LyricsBackgroundSettings.CoverOverlayBlurAmount, Mode=TwoWay}" />
|
||||||
</controls:SettingsCard>
|
</controls:SettingsCard>
|
||||||
|
|
||||||
<controls:SettingsCard x:Uid="SettingsPageBackgroundAcrylicEffectAmount" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
<controls:SettingsCard x:Uid="SettingsPageBackgroundAcrylicEffectAmount" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||||
<uc:ExtendedSlider
|
<uc:ExtendedSlider
|
||||||
Default="0"
|
Default="0"
|
||||||
Frequency="1"
|
Frequency="1"
|
||||||
@@ -20,11 +20,11 @@ using Windows.Foundation.Collections;
|
|||||||
|
|
||||||
namespace BetterLyrics.WinUI3.Controls
|
namespace BetterLyrics.WinUI3.Controls
|
||||||
{
|
{
|
||||||
public sealed partial class LyricsBavkgroundSettingsControl : UserControl
|
public sealed partial class LyricsBackgroundSettingsControl : UserControl
|
||||||
{
|
{
|
||||||
public LyricsBackgroundSettingsControlViewModel ViewModel => (LyricsBackgroundSettingsControlViewModel)DataContext;
|
public LyricsBackgroundSettingsControlViewModel ViewModel => (LyricsBackgroundSettingsControlViewModel)DataContext;
|
||||||
|
|
||||||
public LyricsBavkgroundSettingsControl()
|
public LyricsBackgroundSettingsControl()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
DataContext = Ioc.Default.GetRequiredService<LyricsBackgroundSettingsControlViewModel>();
|
DataContext = Ioc.Default.GetRequiredService<LyricsBackgroundSettingsControlViewModel>();
|
||||||
@@ -29,7 +29,7 @@
|
|||||||
</controls:SettingsCard>
|
</controls:SettingsCard>
|
||||||
|
|
||||||
<controls:SettingsCard x:Uid="SettingsPageLyricsFontFamily" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
<controls:SettingsCard x:Uid="SettingsPageLyricsFontFamily" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||||
<ComboBox ItemsSource="{x:Bind SystemFontNames, Mode=OneWay}" SelectedIndex="{x:Bind LyricsStyleSettings.SelectedFontFamilyIndex, Mode=TwoWay}">
|
<ComboBox ItemsSource="{x:Bind SystemFontNames, Mode=OneWay}" SelectedItem="{x:Bind LyricsStyleSettings.LyricsFontFamily, Mode=TwoWay}">
|
||||||
<ComboBox.ItemTemplate>
|
<ComboBox.ItemTemplate>
|
||||||
<DataTemplate>
|
<DataTemplate>
|
||||||
<TextBlock Text="{Binding}" />
|
<TextBlock Text="{Binding}" />
|
||||||
@@ -54,7 +54,7 @@
|
|||||||
</ComboBox>
|
</ComboBox>
|
||||||
</controls:SettingsCard>
|
</controls:SettingsCard>
|
||||||
|
|
||||||
<controls:SettingsCard x:Uid="SettingsPageLyricsBgFontOpacity" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
<controls:SettingsCard x:Uid="SettingsPageLyricsBgFontOpacity" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||||
<local:ExtendedSlider
|
<local:ExtendedSlider
|
||||||
Default="30"
|
Default="30"
|
||||||
Frequency="1"
|
Frequency="1"
|
||||||
@@ -195,7 +195,7 @@
|
|||||||
Value="{x:Bind LyricsStyleSettings.LyricsLineSpacingFactor, Mode=TwoWay}" />
|
Value="{x:Bind LyricsStyleSettings.LyricsLineSpacingFactor, Mode=TwoWay}" />
|
||||||
</controls:SettingsCard>
|
</controls:SettingsCard>
|
||||||
|
|
||||||
<controls:SettingsCard x:Uid="SettingsPageLyricsTranslationSeparator" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
<controls:SettingsCard x:Uid="SettingsPageLyricsTranslationSeparator" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||||
<StackPanel Orientation="Horizontal" Spacing="6">
|
<StackPanel Orientation="Horizontal" Spacing="6">
|
||||||
<TextBox AcceptsReturn="True" Text="{x:Bind LyricsStyleSettings.LyricsTranslationSeparator, Mode=TwoWay}" />
|
<TextBox AcceptsReturn="True" Text="{x:Bind LyricsStyleSettings.LyricsTranslationSeparator, Mode=TwoWay}" />
|
||||||
<Button Content="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, FontSize=12, Glyph=}" Style="{StaticResource GhostButtonStyle}" />
|
<Button Content="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, FontSize=12, Glyph=}" Style="{StaticResource GhostButtonStyle}" />
|
||||||
@@ -209,7 +209,7 @@
|
|||||||
Style="{StaticResource SettingsSectionHeaderTextBlockStyle}"
|
Style="{StaticResource SettingsSectionHeaderTextBlockStyle}"
|
||||||
Text="Effect" />
|
Text="Effect" />
|
||||||
|
|
||||||
<controls:SettingsCard x:Uid="SettingsPageLyricsVerticalEdgeOpacity" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
<controls:SettingsCard x:Uid="SettingsPageLyricsVerticalEdgeOpacity" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||||
<local:ExtendedSlider
|
<local:ExtendedSlider
|
||||||
x:Uid="SettingsPageLyricsVerticalEdgeOpacitySlider"
|
x:Uid="SettingsPageLyricsVerticalEdgeOpacitySlider"
|
||||||
Default="0"
|
Default="0"
|
||||||
@@ -230,14 +230,78 @@
|
|||||||
Value="{x:Bind LyricsEffectSettings.LyricsBlurAmount, Mode=TwoWay}" />
|
Value="{x:Bind LyricsEffectSettings.LyricsBlurAmount, Mode=TwoWay}" />
|
||||||
</controls:SettingsCard>
|
</controls:SettingsCard>
|
||||||
|
|
||||||
<controls:SettingsCard x:Uid="SettingsPageLyricsHighlightScope" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
<controls:SettingsCard x:Uid="SettingsPageLyricsLineFade" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||||
|
<ToggleSwitch IsOn="{x:Bind LyricsEffectSettings.IsLyricsLineFadeEnabled, Mode=TwoWay}" />
|
||||||
|
</controls:SettingsCard>
|
||||||
|
|
||||||
|
<!-- 译文高亮 -->
|
||||||
|
<controls:SettingsExpander
|
||||||
|
x:Uid="SettingsPageLyricsTranslationHighlight"
|
||||||
|
HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
|
||||||
|
Glyph=}"
|
||||||
|
IsExpanded="True">
|
||||||
|
<controls:SettingsExpander.Items>
|
||||||
|
<controls:SettingsCard x:Uid="SettingsPageAmount">
|
||||||
|
<local:ExtendedSlider
|
||||||
|
Default="60"
|
||||||
|
Frequency="5"
|
||||||
|
Maximum="100"
|
||||||
|
Minimum="0"
|
||||||
|
Value="{x:Bind LyricsEffectSettings.LyricsTranslationHighlightAmount, Mode=TwoWay}" />
|
||||||
|
</controls:SettingsCard>
|
||||||
|
</controls:SettingsExpander.Items>
|
||||||
|
</controls:SettingsExpander>
|
||||||
|
|
||||||
|
<!-- 原文高亮 -->
|
||||||
|
<controls:SettingsExpander
|
||||||
|
x:Uid="SettingsPageLyricsHighlightScope"
|
||||||
|
HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
|
||||||
|
Glyph=}"
|
||||||
|
IsExpanded="True">
|
||||||
<ComboBox SelectedIndex="{x:Bind LyricsEffectSettings.LyricsHighlightScope, Mode=TwoWay, Converter={StaticResource EnumToIntConverter}}">
|
<ComboBox SelectedIndex="{x:Bind LyricsEffectSettings.LyricsHighlightScope, Mode=TwoWay, Converter={StaticResource EnumToIntConverter}}">
|
||||||
<ComboBoxItem x:Uid="SettingsPageLyricsRendingScopeCurrentChar" />
|
<ComboBoxItem x:Uid="SettingsPageLyricsRendingScopeCurrentChar" />
|
||||||
<ComboBoxItem x:Uid="SettingsPageLyricsRendingScopeLineStartToCurrentChar" />
|
<ComboBoxItem x:Uid="SettingsPageLyricsRendingScopeLineStartToCurrentChar" />
|
||||||
<ComboBoxItem x:Uid="SettingsPageLyricsRendingScopeCurrentLine" />
|
<ComboBoxItem x:Uid="SettingsPageLyricsRendingScopeCurrentLine" />
|
||||||
</ComboBox>
|
</ComboBox>
|
||||||
</controls:SettingsCard>
|
<controls:SettingsExpander.Items>
|
||||||
|
<controls:SettingsCard x:Uid="SettingsPageAmount">
|
||||||
|
<local:ExtendedSlider
|
||||||
|
Default="100"
|
||||||
|
Frequency="5"
|
||||||
|
Maximum="100"
|
||||||
|
Minimum="0"
|
||||||
|
Value="{x:Bind LyricsEffectSettings.LyricsHighlightAmount, Mode=TwoWay}" />
|
||||||
|
</controls:SettingsCard>
|
||||||
|
</controls:SettingsExpander.Items>
|
||||||
|
</controls:SettingsExpander>
|
||||||
|
|
||||||
|
<!-- 阴影 -->
|
||||||
|
<controls:SettingsExpander
|
||||||
|
x:Uid="SettingsPageLyricsShadow"
|
||||||
|
HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
|
||||||
|
Glyph=}"
|
||||||
|
IsExpanded="{x:Bind LyricsEffectSettings.IsLyricsShadowEnabled, Mode=OneWay}">
|
||||||
|
<ToggleSwitch IsOn="{x:Bind LyricsEffectSettings.IsLyricsShadowEnabled, Mode=TwoWay}" />
|
||||||
|
<controls:SettingsExpander.Items>
|
||||||
|
<controls:SettingsCard x:Uid="SettingsPageScope" IsEnabled="{x:Bind LyricsEffectSettings.IsLyricsShadowEnabled, Mode=OneWay}">
|
||||||
|
<ComboBox SelectedIndex="{x:Bind LyricsEffectSettings.LyricsShadowScope, Mode=TwoWay, Converter={StaticResource EnumToIntConverter}}">
|
||||||
|
<ComboBoxItem x:Uid="SettingsPageLyricsRendingScopeCurrentChar" />
|
||||||
|
<ComboBoxItem x:Uid="SettingsPageLyricsRendingScopeLineStartToCurrentChar" />
|
||||||
|
<ComboBoxItem x:Uid="SettingsPageLyricsRendingScopeCurrentLine" />
|
||||||
|
</ComboBox>
|
||||||
|
</controls:SettingsCard>
|
||||||
|
<controls:SettingsCard x:Uid="SettingsPageAmount" IsEnabled="{x:Bind LyricsEffectSettings.IsLyricsShadowEnabled, Mode=OneWay}">
|
||||||
|
<local:ExtendedSlider
|
||||||
|
Default="8"
|
||||||
|
Frequency="1"
|
||||||
|
Maximum="20"
|
||||||
|
Minimum="1"
|
||||||
|
Value="{x:Bind LyricsEffectSettings.LyricsShadowAmount, Mode=TwoWay}" />
|
||||||
|
</controls:SettingsCard>
|
||||||
|
</controls:SettingsExpander.Items>
|
||||||
|
</controls:SettingsExpander>
|
||||||
|
|
||||||
|
<!-- 辉光效果 -->
|
||||||
<controls:SettingsExpander
|
<controls:SettingsExpander
|
||||||
x:Uid="SettingsPageLyricsGlowEffect"
|
x:Uid="SettingsPageLyricsGlowEffect"
|
||||||
HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
|
HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
|
||||||
@@ -252,17 +316,42 @@
|
|||||||
<ComboBoxItem x:Uid="SettingsPageLyricsRendingScopeCurrentLine" />
|
<ComboBoxItem x:Uid="SettingsPageLyricsRendingScopeCurrentLine" />
|
||||||
</ComboBox>
|
</ComboBox>
|
||||||
</controls:SettingsCard>
|
</controls:SettingsCard>
|
||||||
|
<controls:SettingsCard x:Uid="SettingsPageAmount" IsEnabled="{x:Bind LyricsEffectSettings.IsLyricsGlowEffectEnabled, Mode=OneWay}">
|
||||||
|
<local:ExtendedSlider
|
||||||
|
Default="8"
|
||||||
|
Frequency="1"
|
||||||
|
Maximum="20"
|
||||||
|
Minimum="1"
|
||||||
|
Value="{x:Bind LyricsEffectSettings.LyricsGlowEffectAmount, Mode=TwoWay}" />
|
||||||
|
</controls:SettingsCard>
|
||||||
</controls:SettingsExpander.Items>
|
</controls:SettingsExpander.Items>
|
||||||
</controls:SettingsExpander>
|
</controls:SettingsExpander>
|
||||||
|
|
||||||
<controls:SettingsCard x:Uid="SettingsPageLyricsFloatAnimation" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
<!-- 浮动动画 -->
|
||||||
|
<controls:SettingsExpander
|
||||||
|
x:Uid="SettingsPageLyricsFloatAnimation"
|
||||||
|
HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
|
||||||
|
Glyph=}"
|
||||||
|
IsExpanded="True">
|
||||||
<ToggleSwitch IsOn="{x:Bind LyricsEffectSettings.IsLyricsFloatAnimationEnabled, Mode=TwoWay}" />
|
<ToggleSwitch IsOn="{x:Bind LyricsEffectSettings.IsLyricsFloatAnimationEnabled, Mode=TwoWay}" />
|
||||||
</controls:SettingsCard>
|
<controls:SettingsExpander.Items>
|
||||||
|
<controls:SettingsCard x:Uid="SettingsPageAmount" IsEnabled="{x:Bind LyricsEffectSettings.IsLyricsGlowEffectEnabled, Mode=OneWay}">
|
||||||
|
<local:ExtendedSlider
|
||||||
|
Default="1"
|
||||||
|
Frequency="1"
|
||||||
|
Maximum="4"
|
||||||
|
Minimum="1"
|
||||||
|
Value="{x:Bind LyricsEffectSettings.LyricsFloatAmount, Mode=TwoWay}" />
|
||||||
|
</controls:SettingsCard>
|
||||||
|
</controls:SettingsExpander.Items>
|
||||||
|
</controls:SettingsExpander>
|
||||||
|
|
||||||
|
<!-- 扇形歌词 -->
|
||||||
<controls:SettingsCard x:Uid="SettingsPageFan" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
<controls:SettingsCard x:Uid="SettingsPageFan" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||||
<ToggleSwitch IsOn="{x:Bind LyricsEffectSettings.IsFanLyricsEnabled, Mode=TwoWay}" />
|
<ToggleSwitch IsOn="{x:Bind LyricsEffectSettings.IsFanLyricsEnabled, Mode=TwoWay}" />
|
||||||
</controls:SettingsCard>
|
</controls:SettingsCard>
|
||||||
|
|
||||||
|
<!-- 滚动动画 -->
|
||||||
<controls:SettingsExpander
|
<controls:SettingsExpander
|
||||||
x:Uid="SettingsPageScrollEasing"
|
x:Uid="SettingsPageScrollEasing"
|
||||||
HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
|
HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
|
||||||
@@ -285,7 +374,6 @@
|
|||||||
<controls:SettingsExpander.Items>
|
<controls:SettingsExpander.Items>
|
||||||
<controls:SettingsCard x:Uid="SettingsPageScrollTopDuration">
|
<controls:SettingsCard x:Uid="SettingsPageScrollTopDuration">
|
||||||
<local:ExtendedSlider
|
<local:ExtendedSlider
|
||||||
x:Uid="SettingsPageLyricsScrollTopDurationExtendedSlider"
|
|
||||||
Default="500"
|
Default="500"
|
||||||
Frequency="50"
|
Frequency="50"
|
||||||
Maximum="1000"
|
Maximum="1000"
|
||||||
@@ -295,7 +383,6 @@
|
|||||||
</controls:SettingsCard>
|
</controls:SettingsCard>
|
||||||
<controls:SettingsCard x:Uid="SettingsPageScrollDuration">
|
<controls:SettingsCard x:Uid="SettingsPageScrollDuration">
|
||||||
<local:ExtendedSlider
|
<local:ExtendedSlider
|
||||||
x:Uid="SettingsPageLyricsScrollDurationExtendedSlider"
|
|
||||||
Default="500"
|
Default="500"
|
||||||
Frequency="50"
|
Frequency="50"
|
||||||
Maximum="1000"
|
Maximum="1000"
|
||||||
@@ -305,7 +392,6 @@
|
|||||||
</controls:SettingsCard>
|
</controls:SettingsCard>
|
||||||
<controls:SettingsCard x:Uid="SettingsPageScrollBottomDuration">
|
<controls:SettingsCard x:Uid="SettingsPageScrollBottomDuration">
|
||||||
<local:ExtendedSlider
|
<local:ExtendedSlider
|
||||||
x:Uid="SettingsPageLyricsScrollBottomDurationExtendedSlider"
|
|
||||||
Default="500"
|
Default="500"
|
||||||
Frequency="50"
|
Frequency="50"
|
||||||
Maximum="1000"
|
Maximum="1000"
|
||||||
@@ -313,6 +399,24 @@
|
|||||||
Unit="ms"
|
Unit="ms"
|
||||||
Value="{x:Bind LyricsEffectSettings.LyricsScrollBottomDuration, Mode=TwoWay}" />
|
Value="{x:Bind LyricsEffectSettings.LyricsScrollBottomDuration, Mode=TwoWay}" />
|
||||||
</controls:SettingsCard>
|
</controls:SettingsCard>
|
||||||
|
<controls:SettingsCard x:Uid="SettingsPageScrollTopDelay">
|
||||||
|
<local:ExtendedSlider
|
||||||
|
Default="0"
|
||||||
|
Frequency="50"
|
||||||
|
Maximum="2000"
|
||||||
|
Minimum="0"
|
||||||
|
Unit="ms"
|
||||||
|
Value="{x:Bind LyricsEffectSettings.LyricsScrollTopDelay, Mode=TwoWay}" />
|
||||||
|
</controls:SettingsCard>
|
||||||
|
<controls:SettingsCard x:Uid="SettingsPageScrollBottomDelay">
|
||||||
|
<local:ExtendedSlider
|
||||||
|
Default="0"
|
||||||
|
Frequency="50"
|
||||||
|
Maximum="2000"
|
||||||
|
Minimum="0"
|
||||||
|
Unit="ms"
|
||||||
|
Value="{x:Bind LyricsEffectSettings.LyricsScrollBottomDelay, Mode=TwoWay}" />
|
||||||
|
</controls:SettingsCard>
|
||||||
</controls:SettingsExpander.Items>
|
</controls:SettingsExpander.Items>
|
||||||
</controls:SettingsExpander>
|
</controls:SettingsExpander>
|
||||||
|
|
||||||
|
|||||||
@@ -14,71 +14,74 @@
|
|||||||
<Grid>
|
<Grid>
|
||||||
<ScrollViewer Style="{StaticResource SettingsScrollViewerStyle}">
|
<ScrollViewer Style="{StaticResource SettingsScrollViewerStyle}">
|
||||||
<Grid Style="{StaticResource SettingsGridStyle}">
|
<Grid Style="{StaticResource SettingsGridStyle}">
|
||||||
<StackPanel Spacing="{StaticResource SettingsCardSpacing}">
|
<StackPanel>
|
||||||
|
|
||||||
<TextBlock Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" />
|
<TextBlock Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" />
|
||||||
<controls:SettingsExpander
|
|
||||||
x:Uid="SettingsPageMusicLib"
|
<controls:SettingsCard x:Uid="SettingsPageMusicLib" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}" />
|
||||||
HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
|
|
||||||
Glyph=}"
|
<InfoBar
|
||||||
IsExpanded="True"
|
x:Uid="SettingsPageRemoveInfo"
|
||||||
ItemsSource="{x:Bind ViewModel.AppSettings.LocalMediaFolders, Mode=OneWay}">
|
BorderThickness="0"
|
||||||
<controls:SettingsExpander.ItemTemplate>
|
CornerRadius="0"
|
||||||
|
IsClosable="False"
|
||||||
|
IsOpen="True"
|
||||||
|
Severity="Success">
|
||||||
|
<interactivity:Interaction.Behaviors>
|
||||||
|
<interactivity:DataTriggerBehavior
|
||||||
|
Binding="{x:Bind ViewModel.AppSettings.LocalMediaFolders.Count, Mode=OneWay}"
|
||||||
|
ComparisonCondition="Equal"
|
||||||
|
Value="0">
|
||||||
|
<interactivity:ChangePropertyAction PropertyName="Visibility" Value="Collapsed" />
|
||||||
|
</interactivity:DataTriggerBehavior>
|
||||||
|
<interactivity:DataTriggerBehavior
|
||||||
|
Binding="{x:Bind ViewModel.AppSettings.LocalMediaFolders.Count, Mode=OneWay}"
|
||||||
|
ComparisonCondition="NotEqual"
|
||||||
|
Value="0">
|
||||||
|
<interactivity:ChangePropertyAction PropertyName="Visibility" Value="Visible" />
|
||||||
|
</interactivity:DataTriggerBehavior>
|
||||||
|
</interactivity:Interaction.Behaviors>
|
||||||
|
</InfoBar>
|
||||||
|
|
||||||
|
<ListView
|
||||||
|
ItemContainerStyle="{StaticResource ListViewStretchedItemContainerStyle}"
|
||||||
|
ItemsSource="{x:Bind ViewModel.AppSettings.LocalMediaFolders, Mode=OneWay}"
|
||||||
|
SelectionMode="None">
|
||||||
|
<ListView.ItemTemplate>
|
||||||
<DataTemplate>
|
<DataTemplate>
|
||||||
<controls:SettingsCard>
|
<controls:SettingsExpander>
|
||||||
<controls:SettingsCard.Header>
|
<controls:SettingsExpander.Header>
|
||||||
<HyperlinkButton
|
<HyperlinkButton
|
||||||
Click="LocalFolderHyperlinkButton_Click"
|
Click="LocalFolderHyperlinkButton_Click"
|
||||||
Content="{Binding Path, Mode=OneWay}"
|
Content="{Binding Path, Mode=OneWay}"
|
||||||
Tag="{Binding Path, Mode=OneWay}" />
|
Tag="{Binding Path, Mode=OneWay}" />
|
||||||
</controls:SettingsCard.Header>
|
</controls:SettingsExpander.Header>
|
||||||
<StackPanel Orientation="Horizontal">
|
<ToggleSwitch IsOn="{Binding IsEnabled, Mode=TwoWay}" />
|
||||||
<HyperlinkButton
|
<controls:SettingsExpander.Items>
|
||||||
x:Uid="SettingsPageRemovePath"
|
<controls:SettingsCard>
|
||||||
Click="SettingsPageRemovePathButton_Click"
|
<controls:SettingsCard.Header>
|
||||||
Tag="{Binding}" />
|
<HyperlinkButton
|
||||||
<ToggleSwitch DataContext="{Binding}" IsOn="{Binding IsEnabled, Mode=TwoWay}" />
|
x:Uid="SettingsPageRemovePath"
|
||||||
</StackPanel>
|
Click="SettingsPageRemovePathButton_Click"
|
||||||
</controls:SettingsCard>
|
Tag="{Binding}" />
|
||||||
|
</controls:SettingsCard.Header>
|
||||||
|
</controls:SettingsCard>
|
||||||
|
<controls:SettingsCard x:Uid="SettingsPageMusicLibRealTimeWatch">
|
||||||
|
<ToggleSwitch IsOn="{Binding IsRealTimeWatchEnabled, Mode=TwoWay}" />
|
||||||
|
</controls:SettingsCard>
|
||||||
|
</controls:SettingsExpander.Items>
|
||||||
|
</controls:SettingsExpander>
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
</controls:SettingsExpander.ItemTemplate>
|
</ListView.ItemTemplate>
|
||||||
<controls:SettingsExpander.ItemsHeader>
|
</ListView>
|
||||||
<InfoBar
|
|
||||||
x:Uid="SettingsPageRemoveInfo"
|
|
||||||
BorderThickness="0"
|
|
||||||
CornerRadius="0"
|
|
||||||
IsClosable="False"
|
|
||||||
IsOpen="True"
|
|
||||||
Severity="Success">
|
|
||||||
|
|
||||||
<interactivity:Interaction.Behaviors>
|
<controls:SettingsCard x:Uid="SettingsPageAddFolder" Style="{StaticResource DefaultSettingsExpanderItemStyle}">
|
||||||
|
<Button
|
||||||
|
x:Uid="SettingsPageAddFolderButton"
|
||||||
|
Command="{x:Bind ViewModel.SelectAndAddFolderCommand}"
|
||||||
|
CommandParameter="{Binding ElementName=RootGrid}" />
|
||||||
|
</controls:SettingsCard>
|
||||||
|
|
||||||
<interactivity:DataTriggerBehavior
|
|
||||||
Binding="{x:Bind ViewModel.AppSettings.LocalMediaFolders.Count, Mode=OneWay}"
|
|
||||||
ComparisonCondition="Equal"
|
|
||||||
Value="0">
|
|
||||||
<interactivity:ChangePropertyAction PropertyName="Visibility" Value="Collapsed" />
|
|
||||||
</interactivity:DataTriggerBehavior>
|
|
||||||
<interactivity:DataTriggerBehavior
|
|
||||||
Binding="{x:Bind ViewModel.AppSettings.LocalMediaFolders.Count, Mode=OneWay}"
|
|
||||||
ComparisonCondition="NotEqual"
|
|
||||||
Value="0">
|
|
||||||
<interactivity:ChangePropertyAction PropertyName="Visibility" Value="Visible" />
|
|
||||||
</interactivity:DataTriggerBehavior>
|
|
||||||
|
|
||||||
</interactivity:Interaction.Behaviors>
|
|
||||||
|
|
||||||
</InfoBar>
|
|
||||||
</controls:SettingsExpander.ItemsHeader>
|
|
||||||
<controls:SettingsExpander.ItemsFooter>
|
|
||||||
<controls:SettingsCard x:Uid="SettingsPageAddFolder" Style="{StaticResource DefaultSettingsExpanderItemStyle}">
|
|
||||||
<Button
|
|
||||||
x:Uid="SettingsPageAddFolderButton"
|
|
||||||
Command="{x:Bind ViewModel.SelectAndAddFolderCommand}"
|
|
||||||
CommandParameter="{Binding ElementName=RootGrid}" />
|
|
||||||
</controls:SettingsCard>
|
|
||||||
</controls:SettingsExpander.ItemsFooter>
|
|
||||||
</controls:SettingsExpander>
|
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Grid>
|
</Grid>
|
||||||
</ScrollViewer>
|
</ScrollViewer>
|
||||||
|
|||||||
@@ -18,31 +18,6 @@
|
|||||||
<ColumnDefinition Width="*" />
|
<ColumnDefinition Width="*" />
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
<Grid Grid.Column="0">
|
<Grid Grid.Column="0">
|
||||||
<NavigationView
|
|
||||||
VerticalAlignment="Top"
|
|
||||||
Background="Transparent"
|
|
||||||
IsBackButtonVisible="Collapsed"
|
|
||||||
IsBackEnabled="False"
|
|
||||||
IsSettingsVisible="False"
|
|
||||||
MenuItemsSource="{x:Bind ViewModel.AppSettings.MediaSourceProvidersInfo, Mode=OneWay}"
|
|
||||||
PaneDisplayMode="Top"
|
|
||||||
SelectedItem="{x:Bind ViewModel.SelectedMediaSourceProvider, Mode=TwoWay}">
|
|
||||||
<NavigationView.MenuItemTemplate>
|
|
||||||
<DataTemplate x:DataType="models:MediaSourceProviderInfo">
|
|
||||||
<NavigationViewItem>
|
|
||||||
<NavigationViewItem.Icon>
|
|
||||||
<ImageIcon Source="{Binding Provider, Converter={StaticResource MediaSourceProviderToLogoUriConverter}, Mode=OneWay}" />
|
|
||||||
</NavigationViewItem.Icon>
|
|
||||||
<NavigationViewItem.Content>
|
|
||||||
<TextBlock
|
|
||||||
MaxWidth="200"
|
|
||||||
Text="{Binding Provider, Converter={StaticResource MediaSourceProviderToDisplayedNameConverter}, Mode=OneWay}"
|
|
||||||
TextWrapping="Wrap" />
|
|
||||||
</NavigationViewItem.Content>
|
|
||||||
</NavigationViewItem>
|
|
||||||
</DataTemplate>
|
|
||||||
</NavigationView.MenuItemTemplate>
|
|
||||||
</NavigationView>
|
|
||||||
<ScrollViewer Margin="0,72,0,0" Style="{StaticResource SettingsScrollViewerStyle}">
|
<ScrollViewer Margin="0,72,0,0" Style="{StaticResource SettingsScrollViewerStyle}">
|
||||||
<Grid Style="{StaticResource SettingsGridStyle}">
|
<Grid Style="{StaticResource SettingsGridStyle}">
|
||||||
<StackPanel Spacing="{StaticResource SettingsCardSpacing}">
|
<StackPanel Spacing="{StaticResource SettingsCardSpacing}">
|
||||||
@@ -143,6 +118,31 @@
|
|||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Grid>
|
</Grid>
|
||||||
</ScrollViewer>
|
</ScrollViewer>
|
||||||
|
<ListView
|
||||||
|
VerticalAlignment="Top"
|
||||||
|
ItemsSource="{x:Bind ViewModel.AppSettings.MediaSourceProvidersInfo, Mode=OneWay}"
|
||||||
|
ScrollViewer.HorizontalScrollBarVisibility="Auto"
|
||||||
|
ScrollViewer.HorizontalScrollMode="Enabled"
|
||||||
|
ScrollViewer.VerticalScrollBarVisibility="Disabled"
|
||||||
|
ScrollViewer.VerticalScrollMode="Disabled"
|
||||||
|
SelectedItem="{x:Bind ViewModel.SelectedMediaSourceProvider, Mode=TwoWay}">
|
||||||
|
<ListView.ItemsPanel>
|
||||||
|
<ItemsPanelTemplate>
|
||||||
|
<ItemsStackPanel Orientation="Horizontal" />
|
||||||
|
</ItemsPanelTemplate>
|
||||||
|
</ListView.ItemsPanel>
|
||||||
|
<ListView.ItemTemplate>
|
||||||
|
<DataTemplate x:DataType="models:MediaSourceProviderInfo">
|
||||||
|
<StackPanel Orientation="Horizontal" Spacing="6">
|
||||||
|
<ImageIcon Height="16" Source="{Binding Provider, Converter={StaticResource MediaSourceProviderToLogoUriConverter}, Mode=OneWay}" />
|
||||||
|
<TextBlock
|
||||||
|
MaxWidth="200"
|
||||||
|
Text="{Binding Provider, Converter={StaticResource MediaSourceProviderToDisplayedNameConverter}, Mode=OneWay}"
|
||||||
|
TextWrapping="Wrap" />
|
||||||
|
</StackPanel>
|
||||||
|
</DataTemplate>
|
||||||
|
</ListView.ItemTemplate>
|
||||||
|
</ListView>
|
||||||
<interactivity:Interaction.Behaviors>
|
<interactivity:Interaction.Behaviors>
|
||||||
<interactivity:DataTriggerBehavior
|
<interactivity:DataTriggerBehavior
|
||||||
Binding="{x:Bind ViewModel.AppSettings.MediaSourceProvidersInfo.Count, Mode=OneWay}"
|
Binding="{x:Bind ViewModel.AppSettings.MediaSourceProvidersInfo.Count, Mode=OneWay}"
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<UserControl
|
||||||
|
x:Class="BetterLyrics.WinUI3.Controls.ShortcutTextBox"
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:local="using:BetterLyrics.WinUI3.Controls"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:ui="using:CommunityToolkit.WinUI"
|
||||||
|
mc:Ignorable="d">
|
||||||
|
|
||||||
|
<Grid>
|
||||||
|
<StackPanel Orientation="Horizontal">
|
||||||
|
<TextBox
|
||||||
|
x:Name="TextBox"
|
||||||
|
IsReadOnly="True"
|
||||||
|
KeyDown="TextBox_KeyDown"
|
||||||
|
Loaded="TextBox_Loaded" />
|
||||||
|
<Button
|
||||||
|
Margin="3,0,0,0"
|
||||||
|
HorizontalAlignment="Right"
|
||||||
|
Click="ClearButton_Click"
|
||||||
|
Content="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
|
||||||
|
FontSize=12,
|
||||||
|
Glyph=}"
|
||||||
|
Style="{StaticResource GhostButtonStyle}" />
|
||||||
|
<Button
|
||||||
|
Margin="3,0,0,0"
|
||||||
|
HorizontalAlignment="Right"
|
||||||
|
Click="CheckButton_Click"
|
||||||
|
Content="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
|
||||||
|
FontSize=12,
|
||||||
|
Glyph=}"
|
||||||
|
Style="{StaticResource GhostButtonStyle}" />
|
||||||
|
</StackPanel>
|
||||||
|
</Grid>
|
||||||
|
</UserControl>
|
||||||
@@ -0,0 +1,113 @@
|
|||||||
|
using BetterLyrics.WinUI3.Helper;
|
||||||
|
using Microsoft.UI.Input;
|
||||||
|
using Microsoft.UI.Xaml;
|
||||||
|
using Microsoft.UI.Xaml.Controls;
|
||||||
|
using Microsoft.UI.Xaml.Controls.Primitives;
|
||||||
|
using Microsoft.UI.Xaml.Data;
|
||||||
|
using Microsoft.UI.Xaml.Input;
|
||||||
|
using Microsoft.UI.Xaml.Media;
|
||||||
|
using Microsoft.UI.Xaml.Navigation;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Runtime.InteropServices.WindowsRuntime;
|
||||||
|
using Windows.Foundation;
|
||||||
|
using Windows.Foundation.Collections;
|
||||||
|
using Windows.UI.Core;
|
||||||
|
|
||||||
|
// To learn more about WinUI, the WinUI project structure,
|
||||||
|
// and more about our project templates, see: http://aka.ms/winui-project-info.
|
||||||
|
|
||||||
|
namespace BetterLyrics.WinUI3.Controls
|
||||||
|
{
|
||||||
|
public sealed partial class ShortcutTextBox : UserControl
|
||||||
|
{
|
||||||
|
public ShortcutTextBox()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static readonly DependencyProperty ShortcutProperty =
|
||||||
|
DependencyProperty.Register(nameof(Shortcut), typeof(List<string>), typeof(ShortcutTextBox), new PropertyMetadata(default));
|
||||||
|
|
||||||
|
public List<string> Shortcut
|
||||||
|
{
|
||||||
|
get => (List<string>)GetValue(ShortcutProperty);
|
||||||
|
set => SetValue(ShortcutProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void TextBox_KeyDown(object sender, KeyRoutedEventArgs e)
|
||||||
|
{
|
||||||
|
List<string> shortcut = [];
|
||||||
|
|
||||||
|
bool ctrl = InputKeyboardSource.GetKeyStateForCurrentThread(Windows.System.VirtualKey.Control).HasFlag(CoreVirtualKeyStates.Down);
|
||||||
|
bool shift = InputKeyboardSource.GetKeyStateForCurrentThread(Windows.System.VirtualKey.Shift).HasFlag(CoreVirtualKeyStates.Down);
|
||||||
|
bool alt = InputKeyboardSource.GetKeyStateForCurrentThread(Windows.System.VirtualKey.Menu).HasFlag(CoreVirtualKeyStates.Down);
|
||||||
|
bool win = InputKeyboardSource.GetKeyStateForCurrentThread(Windows.System.VirtualKey.LeftWindows).HasFlag(CoreVirtualKeyStates.Down) ||
|
||||||
|
InputKeyboardSource.GetKeyStateForCurrentThread(Windows.System.VirtualKey.RightWindows).HasFlag(CoreVirtualKeyStates.Down);
|
||||||
|
|
||||||
|
if (ctrl)
|
||||||
|
{
|
||||||
|
shortcut.Add("Ctrl");
|
||||||
|
}
|
||||||
|
if (shift)
|
||||||
|
{
|
||||||
|
shortcut.Add("Shift");
|
||||||
|
}
|
||||||
|
if (alt)
|
||||||
|
{
|
||||||
|
shortcut.Add("Alt");
|
||||||
|
}
|
||||||
|
if (win)
|
||||||
|
{
|
||||||
|
shortcut.Add("Win");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e.Key != Windows.System.VirtualKey.Control &&
|
||||||
|
e.Key != Windows.System.VirtualKey.Shift &&
|
||||||
|
e.Key != Windows.System.VirtualKey.Menu &&
|
||||||
|
e.Key != Windows.System.VirtualKey.LeftWindows &&
|
||||||
|
e.Key != Windows.System.VirtualKey.RightWindows)
|
||||||
|
{
|
||||||
|
shortcut.Add(e.Key.ToString());
|
||||||
|
}
|
||||||
|
Shortcut = shortcut;
|
||||||
|
|
||||||
|
UpdateTextBox();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateTextBox()
|
||||||
|
{
|
||||||
|
TextBox.Text = string.Join(" + ", Shortcut);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void TextBox_Loaded(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
UpdateTextBox();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ClearButton_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
Shortcut = [];
|
||||||
|
UpdateTextBox();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CheckButton_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
bool registered = GlobalHotKeyHelper.IsHotKeyRegistered(Shortcut);
|
||||||
|
if (registered)
|
||||||
|
{
|
||||||
|
App.Current.SettingsWindowNotificationPanel?.Notify(
|
||||||
|
App.ResourceLoader!.GetString("SettingsPageShortcutRegSuccessInfo"),
|
||||||
|
InfoBarSeverity.Success);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
App.Current.SettingsWindowNotificationPanel?.Notify(
|
||||||
|
App.ResourceLoader!.GetString("SettingsPageShortcutRegFailInfo"),
|
||||||
|
InfoBarSeverity.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,9 +14,9 @@
|
|||||||
x:Name="TrayIcon"
|
x:Name="TrayIcon"
|
||||||
x:FieldModifier="public"
|
x:FieldModifier="public"
|
||||||
ContextMenuMode="SecondWindow"
|
ContextMenuMode="SecondWindow"
|
||||||
DoubleClickCommand="{x:Bind ViewModel.OpenLyricsWindowCommand}"
|
DoubleClickCommand="{x:Bind ViewModel.OpenLyricsCommand}"
|
||||||
IconSource="ms-appx:///Assets/Logo.ico"
|
IconSource="ms-appx:///Assets/Logo.ico"
|
||||||
LeftClickCommand="{x:Bind ViewModel.OpenLyricsWindowCommand}"
|
LeftClickCommand="{x:Bind ViewModel.OpenLyricsCommand}"
|
||||||
NoLeftClickDelay="True"
|
NoLeftClickDelay="True"
|
||||||
ToolTipText="{x:Bind ViewModel.ToolTipText, Mode=OneWay}">
|
ToolTipText="{x:Bind ViewModel.ToolTipText, Mode=OneWay}">
|
||||||
<tb:TaskbarIcon.ContextFlyout>
|
<tb:TaskbarIcon.ContextFlyout>
|
||||||
@@ -24,15 +24,49 @@
|
|||||||
AreOpenCloseAnimationsEnabled="True"
|
AreOpenCloseAnimationsEnabled="True"
|
||||||
LightDismissOverlayMode="On"
|
LightDismissOverlayMode="On"
|
||||||
ShowMode="TransientWithDismissOnPointerMoveAway">
|
ShowMode="TransientWithDismissOnPointerMoveAway">
|
||||||
<MenuFlyoutItem x:Uid="SystemTrayMusicGallery" Command="{x:Bind ViewModel.OpenMusicGalleryCommand}" />
|
<MenuFlyout.MenuFlyoutPresenterStyle>
|
||||||
<MenuFlyoutItem x:Uid="SystemTraySettings" Command="{x:Bind ViewModel.OpenSettingsCommand}" />
|
<Style BasedOn="{StaticResource DefaultMenuFlyoutPresenterStyle}" TargetType="MenuFlyoutPresenter">
|
||||||
<MenuFlyoutItem x:Uid="SystemTrayResetWindowPosition" Command="{x:Bind ViewModel.ResetWindowPositionCommand}" />
|
<Setter Property="MinWidth" Value="600" />
|
||||||
<MenuFlyoutItem x:Uid="SystemTrayRestart" Command="{x:Bind ViewModel.RestartAppCommand}" />
|
</Style>
|
||||||
<MenuFlyoutItem x:Uid="SystemTrayExit" Command="{x:Bind ViewModel.ExitAppCommand}" />
|
</MenuFlyout.MenuFlyoutPresenterStyle>
|
||||||
|
<MenuFlyoutItem
|
||||||
|
x:Uid="SystemTrayLyrics"
|
||||||
|
Command="{x:Bind ViewModel.OpenLyricsCommand}"
|
||||||
|
Icon="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
|
||||||
|
Glyph=}" />
|
||||||
|
<MenuFlyoutItem
|
||||||
|
x:Uid="SystemTrayMusicGallery"
|
||||||
|
Command="{x:Bind ViewModel.OpenMusicGalleryCommand}"
|
||||||
|
Icon="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
|
||||||
|
Glyph=}" />
|
||||||
|
<MenuFlyoutItem
|
||||||
|
x:Uid="SystemTraySettings"
|
||||||
|
Command="{x:Bind ViewModel.OpenSettingsCommand}"
|
||||||
|
Icon="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
|
||||||
|
Glyph=}" />
|
||||||
|
<MenuFlyoutSeparator />
|
||||||
|
<MenuFlyoutItem
|
||||||
|
x:Uid="SystemTrayResetWindowPosition"
|
||||||
|
Command="{x:Bind ViewModel.ResetWindowPositionCommand}"
|
||||||
|
Icon="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
|
||||||
|
Glyph=}" />
|
||||||
<MenuFlyoutItem
|
<MenuFlyoutItem
|
||||||
x:Uid="SystemTrayUnlock"
|
x:Uid="SystemTrayUnlock"
|
||||||
Command="{x:Bind ViewModel.UnlockWindowCommand}"
|
Command="{x:Bind ViewModel.UnlockWindowCommand}"
|
||||||
|
Icon="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
|
||||||
|
Glyph=}"
|
||||||
Visibility="{x:Bind ViewModel.IsLyricsWindowLocked, Mode=OneWay, Converter={StaticResource BoolToVisibilityConverter}}" />
|
Visibility="{x:Bind ViewModel.IsLyricsWindowLocked, Mode=OneWay, Converter={StaticResource BoolToVisibilityConverter}}" />
|
||||||
|
<MenuFlyoutSeparator />
|
||||||
|
<MenuFlyoutItem
|
||||||
|
x:Uid="SystemTrayRestart"
|
||||||
|
Command="{x:Bind ViewModel.RestartAppCommand}"
|
||||||
|
Icon="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
|
||||||
|
Glyph=}" />
|
||||||
|
<MenuFlyoutItem
|
||||||
|
x:Uid="SystemTrayExit"
|
||||||
|
Command="{x:Bind ViewModel.ExitAppCommand}"
|
||||||
|
Icon="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
|
||||||
|
Glyph=}" />
|
||||||
</MenuFlyout>
|
</MenuFlyout>
|
||||||
</tb:TaskbarIcon.ContextFlyout>
|
</tb:TaskbarIcon.ContextFlyout>
|
||||||
</tb:TaskbarIcon>
|
</tb:TaskbarIcon>
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
using Microsoft.UI.Xaml.Data;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace BetterLyrics.WinUI3.Converter
|
||||||
|
{
|
||||||
|
public class FPSToTimeSpanConverter : IValueConverter
|
||||||
|
{
|
||||||
|
public object Convert(object value, Type targetType, object parameter, string language)
|
||||||
|
{
|
||||||
|
if (value is int fps)
|
||||||
|
{
|
||||||
|
return TimeSpan.FromSeconds(1.0 / fps);
|
||||||
|
}
|
||||||
|
return TimeSpan.FromSeconds(1.0 / 60);
|
||||||
|
}
|
||||||
|
|
||||||
|
public object ConvertBack(object value, Type targetType, object parameter, string language)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
using Microsoft.UI.Xaml.Data;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace BetterLyrics.WinUI3.Converter
|
||||||
|
{
|
||||||
|
public class ShortcutToStringConverter : IValueConverter
|
||||||
|
{
|
||||||
|
public object Convert(object value, Type targetType, object parameter, string language)
|
||||||
|
{
|
||||||
|
if (value is List<string> shortcut)
|
||||||
|
{
|
||||||
|
return string.Join(" + ", shortcut);
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public object ConvertBack(object value, Type targetType, object parameter, string language)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,10 +2,11 @@
|
|||||||
|
|
||||||
namespace BetterLyrics.WinUI3.Enums
|
namespace BetterLyrics.WinUI3.Enums
|
||||||
{
|
{
|
||||||
public enum AutoStartWindowType
|
public enum LyricsWindowMode
|
||||||
{
|
{
|
||||||
StandardMode,
|
StandardMode,
|
||||||
DockMode,
|
DockMode,
|
||||||
DesktopMode,
|
DesktopMode,
|
||||||
|
PictureInPictureMode,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
19
BetterLyrics.WinUI3/BetterLyrics.WinUI3/Enums/ShortcutID.cs
Normal file
19
BetterLyrics.WinUI3/BetterLyrics.WinUI3/Enums/ShortcutID.cs
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace BetterLyrics.WinUI3.Enums
|
||||||
|
{
|
||||||
|
public enum ShortcutID
|
||||||
|
{
|
||||||
|
DesktopLock,
|
||||||
|
DesktopToggle,
|
||||||
|
DockToggle,
|
||||||
|
PictureInPictureToggle,
|
||||||
|
PlayOrPauseSong,
|
||||||
|
NextSong,
|
||||||
|
PreviousSong,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
using BetterLyrics.WinUI3.Models;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace BetterLyrics.WinUI3.Events
|
||||||
|
{
|
||||||
|
public class LyricsChangedEventArgs(LyricsData? lyricsData) : EventArgs
|
||||||
|
{
|
||||||
|
public LyricsData? LyricsData { get; } = lyricsData;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,11 +1,19 @@
|
|||||||
using Microsoft.Graphics.Canvas.Brushes;
|
using BetterLyrics.WinUI3.Enums;
|
||||||
|
using BetterLyrics.WinUI3.Models;
|
||||||
|
using Microsoft.Graphics.Canvas;
|
||||||
|
using Microsoft.Graphics.Canvas.Brushes;
|
||||||
|
using Microsoft.Graphics.Canvas.Effects;
|
||||||
|
using Microsoft.Graphics.Canvas.Text;
|
||||||
using Microsoft.Graphics.Canvas.UI.Xaml;
|
using Microsoft.Graphics.Canvas.UI.Xaml;
|
||||||
|
using Microsoft.UI;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Windows.Foundation;
|
||||||
|
using Windows.Graphics.Effects;
|
||||||
using Windows.UI;
|
using Windows.UI;
|
||||||
|
|
||||||
namespace BetterLyrics.WinUI3.Helper
|
namespace BetterLyrics.WinUI3.Helper
|
||||||
@@ -29,5 +37,316 @@ namespace BetterLyrics.WinUI3.Helper
|
|||||||
EndPoint = new Vector2((float)(startX + width), 0),
|
EndPoint = new Vector2((float)(startX + width), 0),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 背景层
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="lyricsLayerOpacity">_lyricsOpacityTransition.Value</param>
|
||||||
|
public static OpacityEffect CreateBackgroundEffect(LyricsLine lyricsLine, CanvasCommandList backgroundFontEffect, double lyricsLayerOpacity)
|
||||||
|
{
|
||||||
|
if (lyricsLine.BlurAmountTransition.Value == 0)
|
||||||
|
{
|
||||||
|
return new OpacityEffect
|
||||||
|
{
|
||||||
|
Source = backgroundFontEffect,
|
||||||
|
Opacity = (float)(lyricsLine.OpacityTransition.Value * lyricsLayerOpacity),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return new OpacityEffect
|
||||||
|
{
|
||||||
|
Source = new GaussianBlurEffect
|
||||||
|
{
|
||||||
|
Source = backgroundFontEffect,
|
||||||
|
BlurAmount = (float)lyricsLine.BlurAmountTransition.Value,
|
||||||
|
BorderMode = EffectBorderMode.Soft,
|
||||||
|
Optimization = EffectOptimization.Speed,
|
||||||
|
},
|
||||||
|
Opacity = (float)(lyricsLine.OpacityTransition.Value * lyricsLayerOpacity),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CanvasCommandList CreateFontEffect(LyricsLine lyricsLine, ICanvasAnimatedControl control, Color strokeColor, int strokeWidth, Color fontColor)
|
||||||
|
{
|
||||||
|
CanvasCommandList list = new(control);
|
||||||
|
using var ds = list.CreateDrawingSession();
|
||||||
|
if (strokeWidth > 0)
|
||||||
|
{
|
||||||
|
ds.DrawGeometry(lyricsLine.TextGeometry, lyricsLine.Position, strokeColor, strokeWidth); // 描边
|
||||||
|
}
|
||||||
|
ds.FillGeometry(lyricsLine.TextGeometry, lyricsLine.Position, fontColor); // 填充
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 创建辉光效果层
|
||||||
|
/// 仅需在布局重构 (Relayout) 时调用
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="lineRenderingType">_lyricsGlowEffectScope</param>
|
||||||
|
/// <param name="glowEffectAmount">_lyricsGlowEffectAmount</param>
|
||||||
|
public static GaussianBlurEffect CreateForegroundBlurEffect(CanvasCommandList foregroundFontEffect, IGraphicsEffectSource mask, double glowEffectAmount)
|
||||||
|
{
|
||||||
|
return new GaussianBlurEffect
|
||||||
|
{
|
||||||
|
Source = new AlphaMaskEffect
|
||||||
|
{
|
||||||
|
Source = foregroundFontEffect,
|
||||||
|
AlphaMask = mask,
|
||||||
|
},
|
||||||
|
BlurAmount = (float)glowEffectAmount,
|
||||||
|
Optimization = EffectOptimization.Speed,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CanvasCommandList CreateCharMask(ICanvasAnimatedControl control, LyricsLine lyricsLine, int charStartIndex, int charLength, double charProgress)
|
||||||
|
{
|
||||||
|
var mask = new CanvasCommandList(control);
|
||||||
|
using var ds = mask.CreateDrawingSession();
|
||||||
|
|
||||||
|
if (lyricsLine.CanvasTextLayout == null)
|
||||||
|
{
|
||||||
|
return mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
var highlightRegion = lyricsLine.CanvasTextLayout.GetCharacterRegions(charStartIndex, charLength).FirstOrDefault();
|
||||||
|
|
||||||
|
double highlightTotalWidth = (double)highlightRegion.LayoutBounds.Width;
|
||||||
|
// Draw the highlight for the current character
|
||||||
|
double highlightWidth = highlightTotalWidth * charProgress;
|
||||||
|
|
||||||
|
double fadingWidth = (double)highlightRegion.LayoutBounds.Height / 2;
|
||||||
|
|
||||||
|
// Rects
|
||||||
|
var highlightRect = new Rect(
|
||||||
|
highlightRegion.LayoutBounds.X,
|
||||||
|
highlightRegion.LayoutBounds.Y + lyricsLine.Position.Y,
|
||||||
|
highlightWidth,
|
||||||
|
highlightRegion.LayoutBounds.Height
|
||||||
|
);
|
||||||
|
|
||||||
|
var fadeInRect = new Rect(
|
||||||
|
highlightRect.Right - fadingWidth,
|
||||||
|
highlightRegion.LayoutBounds.Y + lyricsLine.Position.Y,
|
||||||
|
fadingWidth,
|
||||||
|
highlightRegion.LayoutBounds.Height
|
||||||
|
);
|
||||||
|
var fadeOutRect = new Rect(
|
||||||
|
highlightRect.Right,
|
||||||
|
highlightRegion.LayoutBounds.Y + lyricsLine.Position.Y,
|
||||||
|
fadingWidth,
|
||||||
|
highlightRegion.LayoutBounds.Height
|
||||||
|
);
|
||||||
|
|
||||||
|
// Brushes
|
||||||
|
using var fadeInBrush = CanvasHelper.CreateHorizontalFillBrush(
|
||||||
|
control,
|
||||||
|
[(0f, 0f), (1f, 1f)],
|
||||||
|
(double)highlightRect.Right - fadingWidth,
|
||||||
|
fadingWidth
|
||||||
|
);
|
||||||
|
using var fadeOutBrush = CanvasHelper.CreateHorizontalFillBrush(
|
||||||
|
control,
|
||||||
|
[(0f, 1f), (1f, 0f)],
|
||||||
|
(double)highlightRect.Right,
|
||||||
|
fadingWidth
|
||||||
|
);
|
||||||
|
|
||||||
|
ds.FillRectangle(fadeInRect, fadeInBrush);
|
||||||
|
ds.FillRectangle(fadeOutRect, fadeOutBrush);
|
||||||
|
|
||||||
|
return mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CanvasCommandList CreateLineStartToCharMask(ICanvasAnimatedControl control, LyricsLine lyricsLine, int charStartIndex, int charLength, double charProgress, bool fade)
|
||||||
|
{
|
||||||
|
var mask = new CanvasCommandList(control);
|
||||||
|
|
||||||
|
if (lyricsLine.CanvasTextLayout == null)
|
||||||
|
{
|
||||||
|
return mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
using var ds = mask.CreateDrawingSession();
|
||||||
|
|
||||||
|
var regions = lyricsLine.CanvasTextLayout.GetCharacterRegions(0, charStartIndex);
|
||||||
|
var highlightRegion = lyricsLine.CanvasTextLayout
|
||||||
|
.GetCharacterRegions(charStartIndex, charLength)
|
||||||
|
.FirstOrDefault();
|
||||||
|
if (regions.Length > 0)
|
||||||
|
{
|
||||||
|
// Draw the mask for the current line
|
||||||
|
for (int j = 0; j < regions.Length; j++)
|
||||||
|
{
|
||||||
|
var region = regions[j];
|
||||||
|
var rect = new Rect(
|
||||||
|
region.LayoutBounds.X,
|
||||||
|
region.LayoutBounds.Y + lyricsLine.Position.Y,
|
||||||
|
region.LayoutBounds.Width,
|
||||||
|
region.LayoutBounds.Height
|
||||||
|
);
|
||||||
|
ds.FillRectangle(rect, Color.FromArgb(255, 128, 128, 128));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
double highlightTotalWidth = (double)highlightRegion.LayoutBounds.Width;
|
||||||
|
// Draw the highlight for the current character
|
||||||
|
double highlightWidth = highlightTotalWidth * charProgress;
|
||||||
|
|
||||||
|
double fadingWidth = (double)highlightRegion.LayoutBounds.Height / 2;
|
||||||
|
|
||||||
|
// Rects
|
||||||
|
var highlightRect = new Rect(
|
||||||
|
highlightRegion.LayoutBounds.X,
|
||||||
|
highlightRegion.LayoutBounds.Y + lyricsLine.Position.Y,
|
||||||
|
highlightWidth,
|
||||||
|
highlightRegion.LayoutBounds.Height
|
||||||
|
);
|
||||||
|
|
||||||
|
var fadeInRect = new Rect(
|
||||||
|
highlightRect.Right - fadingWidth,
|
||||||
|
highlightRegion.LayoutBounds.Y + lyricsLine.Position.Y,
|
||||||
|
fadingWidth,
|
||||||
|
highlightRegion.LayoutBounds.Height
|
||||||
|
);
|
||||||
|
|
||||||
|
ds.FillRectangle(highlightRect, Color.FromArgb(255, 128, 128, 128));
|
||||||
|
|
||||||
|
if (fade)
|
||||||
|
{
|
||||||
|
var fadeOutRect = new Rect(
|
||||||
|
highlightRect.Right,
|
||||||
|
highlightRegion.LayoutBounds.Y + lyricsLine.Position.Y,
|
||||||
|
fadingWidth,
|
||||||
|
highlightRegion.LayoutBounds.Height
|
||||||
|
);
|
||||||
|
using var fadeOutBrush = CreateHorizontalFillBrush(
|
||||||
|
control,
|
||||||
|
[(0f, 1f), (1f, 0f)],
|
||||||
|
(double)highlightRect.Right,
|
||||||
|
fadingWidth
|
||||||
|
);
|
||||||
|
ds.FillRectangle(fadeOutRect, fadeOutBrush);
|
||||||
|
}
|
||||||
|
|
||||||
|
return mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CanvasCommandList CreateLineMask(ICanvasAnimatedControl control, LyricsLine lyricsLine)
|
||||||
|
{
|
||||||
|
var mask = new CanvasCommandList(control);
|
||||||
|
using var ds = mask.CreateDrawingSession();
|
||||||
|
|
||||||
|
if (lyricsLine.CanvasTextLayout == null)
|
||||||
|
{
|
||||||
|
return mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
var regions = lyricsLine.CanvasTextLayout.GetCharacterRegions(0, lyricsLine.OriginalText.Length);
|
||||||
|
if (regions.Length > 0)
|
||||||
|
{
|
||||||
|
for (int j = 0; j < regions.Length; j++)
|
||||||
|
{
|
||||||
|
var region = regions[j];
|
||||||
|
var rect = new Rect(
|
||||||
|
region.LayoutBounds.X,
|
||||||
|
region.LayoutBounds.Y + lyricsLine.Position.Y,
|
||||||
|
region.LayoutBounds.Width,
|
||||||
|
region.LayoutBounds.Height
|
||||||
|
);
|
||||||
|
ds.FillRectangle(rect, Colors.White);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CanvasCommandList CreateTranslationHighlightMask(ICanvasAnimatedControl control, LyricsLine lyricsLine)
|
||||||
|
{
|
||||||
|
var mask = new CanvasCommandList(control);
|
||||||
|
using var ds = mask.CreateDrawingSession();
|
||||||
|
|
||||||
|
if (lyricsLine.CanvasTextLayout == null)
|
||||||
|
{
|
||||||
|
return mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
var regions = lyricsLine.CanvasTextLayout.GetCharacterRegions(lyricsLine.OriginalText.Length, lyricsLine.DisplayedText.Length - lyricsLine.OriginalText.Length);
|
||||||
|
if (regions.Length > 0)
|
||||||
|
{
|
||||||
|
for (int j = 0; j < regions.Length; j++)
|
||||||
|
{
|
||||||
|
var region = regions[j];
|
||||||
|
var rect = new Rect(
|
||||||
|
region.LayoutBounds.X,
|
||||||
|
region.LayoutBounds.Y + lyricsLine.Position.Y,
|
||||||
|
region.LayoutBounds.Width,
|
||||||
|
region.LayoutBounds.Height
|
||||||
|
);
|
||||||
|
ds.FillRectangle(rect, Colors.White);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 创建高亮效果层
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="control"></param>
|
||||||
|
/// <param name="lineRenderingType"></param>
|
||||||
|
public static OpacityEffect CreateForegroundHighlightEffect(CanvasCommandList foregroundFontEffect, IGraphicsEffectSource mask, double opacity)
|
||||||
|
{
|
||||||
|
return new OpacityEffect
|
||||||
|
{
|
||||||
|
Source = new AlphaMaskEffect
|
||||||
|
{
|
||||||
|
Source = foregroundFontEffect,
|
||||||
|
AlphaMask = mask,
|
||||||
|
},
|
||||||
|
Opacity = (float)opacity,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ShadowEffect CreateForegroundShadowEffect(CanvasCommandList foregroundFontEffect, IGraphicsEffectSource mask, Color shadowColor, double shadowAmount)
|
||||||
|
{
|
||||||
|
return new ShadowEffect
|
||||||
|
{
|
||||||
|
Source = new AlphaMaskEffect
|
||||||
|
{
|
||||||
|
Source = foregroundFontEffect,
|
||||||
|
AlphaMask = mask,
|
||||||
|
},
|
||||||
|
ShadowColor = shadowColor,
|
||||||
|
BlurAmount = (float)shadowAmount,
|
||||||
|
Optimization = EffectOptimization.Speed,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static OpacityEffect CreateForegroundTranslationEffect(CanvasCommandList foregroundFontEffect, IGraphicsEffectSource mask, double opacity)
|
||||||
|
{
|
||||||
|
return new OpacityEffect
|
||||||
|
{
|
||||||
|
Source = new AlphaMaskEffect
|
||||||
|
{
|
||||||
|
Source = foregroundFontEffect,
|
||||||
|
AlphaMask = mask,
|
||||||
|
},
|
||||||
|
Opacity = (float)opacity,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IGraphicsEffectSource GetAlphaMask(ICanvasAnimatedControl control, IGraphicsEffectSource charMask, IGraphicsEffectSource lineStartToCharMask, IGraphicsEffectSource lineMask, LineRenderingType lineRenderingType)
|
||||||
|
{
|
||||||
|
var result = lineRenderingType switch
|
||||||
|
{
|
||||||
|
LineRenderingType.CurrentChar => charMask,
|
||||||
|
LineRenderingType.LineStartToCurrentChar => lineStartToCharMask,
|
||||||
|
LineRenderingType.CurrentLine => lineMask,
|
||||||
|
_ => new CanvasCommandList(control),
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,47 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace BetterLyrics.WinUI3.Helper
|
||||||
|
{
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace BetterLyrics.WinUI3.Helper
|
||||||
|
{
|
||||||
|
public class DirectoryHelper
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 递归查找指定文件夹下所有文件(包括子文件夹)。
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="folderPath">要查找的文件夹路径</param>
|
||||||
|
/// <returns>所有文件的完整路径列表</returns>
|
||||||
|
public static List<string> GetAllFiles(string folderPath, string searchPattern = "*")
|
||||||
|
{
|
||||||
|
var files = new List<string>();
|
||||||
|
if (!Directory.Exists(folderPath))
|
||||||
|
return files;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
files.AddRange(Directory.GetFiles(folderPath, searchPattern));
|
||||||
|
foreach (var dir in Directory.GetDirectories(folderPath))
|
||||||
|
{
|
||||||
|
files.AddRange(GetAllFiles(dir, searchPattern));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
// 可根据需要处理异常,如权限不足等
|
||||||
|
}
|
||||||
|
return files;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -24,6 +24,11 @@ namespace BetterLyrics.WinUI3.Helper
|
|||||||
private static readonly Dictionary<IntPtr, RECT> _originalPositions = [];
|
private static readonly Dictionary<IntPtr, RECT> _originalPositions = [];
|
||||||
private static readonly Dictionary<IntPtr, WindowStyle> _originalWindowStyle = [];
|
private static readonly Dictionary<IntPtr, WindowStyle> _originalWindowStyle = [];
|
||||||
|
|
||||||
|
public static bool IsEnabled(IntPtr hwnd)
|
||||||
|
{
|
||||||
|
return _registered.Contains(hwnd);
|
||||||
|
}
|
||||||
|
|
||||||
public static void Disable(Window window)
|
public static void Disable(Window window)
|
||||||
{
|
{
|
||||||
IntPtr hwnd = WindowNative.GetWindowHandle(window);
|
IntPtr hwnd = WindowNative.GetWindowHandle(window);
|
||||||
|
|||||||
@@ -2,7 +2,9 @@
|
|||||||
|
|
||||||
using BetterLyrics.WinUI3.Enums;
|
using BetterLyrics.WinUI3.Enums;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using Ude;
|
using Ude;
|
||||||
|
|
||||||
@@ -78,5 +80,13 @@ namespace BetterLyrics.WinUI3.Helper
|
|||||||
|| normFileName == normQ2 + normQ1;
|
|| normFileName == normQ2 + normQ1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static readonly string[] MusicExtensions = {
|
||||||
|
".mp3", ".aac", ".m4a", ".ogg", ".opus", ".wma", ".amr",
|
||||||
|
".flac", ".alac", ".ape", ".wv", ".tak",
|
||||||
|
".wav", ".aiff", ".aif", ".pcm", ".cda", ".dsf", ".dff", ".au", ".snd",
|
||||||
|
".mid", ".midi", ".mod", ".xm", ".it", ".s3m"
|
||||||
|
};
|
||||||
|
|
||||||
|
public static string MusicSearchPattern => string.Join("|", MusicExtensions.Select(x => $"*{x}"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,10 +11,6 @@ namespace BetterLyrics.WinUI3.Helper
|
|||||||
{
|
{
|
||||||
public static class FontHelper
|
public static class FontHelper
|
||||||
{
|
{
|
||||||
private static readonly ISettingsService _settingsService = Ioc.Default.GetRequiredService<ISettingsService>();
|
|
||||||
|
|
||||||
public static string[] SystemFontFamilies => CanvasTextFormat.GetSystemFontFamilies();
|
public static string[] SystemFontFamilies => CanvasTextFormat.GetSystemFontFamilies();
|
||||||
|
|
||||||
public static string GetUserPreferredFontFamily() => SystemFontFamilies.ElementAtOrDefault(_settingsService.AppSettings.StandardLyricsStyleSettings.SelectedFontFamilyIndex) ?? "Segoe UI";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Microsoft.UI.Xaml;
|
using BetterLyrics.WinUI3.Enums;
|
||||||
|
using Microsoft.UI.Xaml;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@@ -12,30 +13,92 @@ namespace BetterLyrics.WinUI3.Helper
|
|||||||
{
|
{
|
||||||
public class GlobalHotKeyHelper
|
public class GlobalHotKeyHelper
|
||||||
{
|
{
|
||||||
private static Dictionary<int, Action> _hotKeyActions = [];
|
private static Dictionary<int, Action> _actions = [];
|
||||||
private static int _nextId = 0;
|
private static Dictionary<int, List<string>> _keys = [];
|
||||||
|
|
||||||
public static void RegisterHotKey(Window window, User32.HotKeyModifiers modifiers, uint key, Action action)
|
/// <summary>
|
||||||
|
/// Register a global hotkey for a specific window type
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">Target window type</typeparam>
|
||||||
|
/// <param name="id"></param>
|
||||||
|
/// <param name="keys"></param>
|
||||||
|
/// <param name="action"></param>
|
||||||
|
private static void RegisterHotKey<T>(ShortcutID id, List<string> keys, Action action)
|
||||||
{
|
{
|
||||||
|
if (keys.Count == 0) return;
|
||||||
|
|
||||||
|
var window = WindowHelper.GetWindowByWindowType<T>();
|
||||||
|
if (window == null) return;
|
||||||
|
|
||||||
HWND hwnd = WindowNative.GetWindowHandle(window);
|
HWND hwnd = WindowNative.GetWindowHandle(window);
|
||||||
int id = _nextId++;
|
User32.HotKeyModifiers modifiers = User32.HotKeyModifiers.MOD_NONE;
|
||||||
User32.RegisterHotKey(hwnd, id, modifiers, key);
|
VirtualKey key = VirtualKey.None;
|
||||||
_hotKeyActions[id] = action;
|
foreach (var item in keys)
|
||||||
|
{
|
||||||
|
if (item == "Ctrl")
|
||||||
|
{
|
||||||
|
modifiers |= User32.HotKeyModifiers.MOD_CONTROL;
|
||||||
|
}
|
||||||
|
else if (item == "Shift")
|
||||||
|
{
|
||||||
|
modifiers |= User32.HotKeyModifiers.MOD_SHIFT;
|
||||||
|
}
|
||||||
|
else if (item == "Alt")
|
||||||
|
{
|
||||||
|
modifiers |= User32.HotKeyModifiers.MOD_ALT;
|
||||||
|
}
|
||||||
|
else if (item == "Win")
|
||||||
|
{
|
||||||
|
modifiers |= User32.HotKeyModifiers.MOD_WIN;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
key = (VirtualKey)Enum.Parse(typeof(VirtualKey), item, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bool success = User32.RegisterHotKey(hwnd, (int)id, modifiers, (uint)key);
|
||||||
|
if (success)
|
||||||
|
{
|
||||||
|
_actions[(int)id] = action;
|
||||||
|
_keys[(int)id] = keys;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void UnregisterAllHotKeys(Window window)
|
private static void UnregisterHotKey<T>(ShortcutID id)
|
||||||
{
|
{
|
||||||
|
var window = WindowHelper.GetWindowByWindowType<T>();
|
||||||
|
if (window == null) return;
|
||||||
|
|
||||||
HWND hwnd = WindowNative.GetWindowHandle(window);
|
HWND hwnd = WindowNative.GetWindowHandle(window);
|
||||||
foreach (var id in _hotKeyActions.Keys.ToList())
|
User32.UnregisterHotKey(hwnd, (int)id);
|
||||||
{
|
_actions.Remove((int)id);
|
||||||
User32.UnregisterHotKey(hwnd, id);
|
_keys.Remove((int)id);
|
||||||
_hotKeyActions.Remove(id);
|
}
|
||||||
}
|
|
||||||
|
public static void UpdateHotKey<T>(ShortcutID id, List<string> keys, Action action)
|
||||||
|
{
|
||||||
|
UnregisterHotKey<T>(id);
|
||||||
|
RegisterHotKey<T>(id, keys, action);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool IsHotKeyRegistered(ShortcutID id)
|
||||||
|
{
|
||||||
|
return _actions.ContainsKey((int)id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool IsHotKeyRegistered(List<string> keys)
|
||||||
|
{
|
||||||
|
return _keys.ContainsValue(keys);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool TryInvokeAction(ShortcutID id)
|
||||||
|
{
|
||||||
|
return TryInvokeAction((int)id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool TryInvokeAction(int id)
|
public static bool TryInvokeAction(int id)
|
||||||
{
|
{
|
||||||
if (_hotKeyActions.TryGetValue(id, out var action))
|
if (_actions.TryGetValue(id, out var action))
|
||||||
{
|
{
|
||||||
action?.Invoke();
|
action?.Invoke();
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -177,7 +177,7 @@ namespace BetterLyrics.WinUI3.Helper
|
|||||||
square.Mutate(ctx => ctx.DrawImage(image, new Point(offsetX, offsetY), 1f));
|
square.Mutate(ctx => ctx.DrawImage(image, new Point(offsetX, offsetY), 1f));
|
||||||
|
|
||||||
using var ms = new MemoryStream();
|
using var ms = new MemoryStream();
|
||||||
square.Save(ms, new JpegEncoder());
|
square.Save(ms, new PngEncoder());
|
||||||
return ms.ToArray();
|
return ms.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ using Lyricify.Lyrics.Helpers.General;
|
|||||||
using NTextCat;
|
using NTextCat;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using TinyPinyin;
|
using TinyPinyin;
|
||||||
@@ -16,7 +17,6 @@ namespace BetterLyrics.WinUI3.Services
|
|||||||
{
|
{
|
||||||
private static readonly RankedLanguageIdentifierFactory _factory = new();
|
private static readonly RankedLanguageIdentifierFactory _factory = new();
|
||||||
private static readonly RankedLanguageIdentifier _identifier;
|
private static readonly RankedLanguageIdentifier _identifier;
|
||||||
private static readonly ISettingsService _settingsService = Ioc.Default.GetRequiredService<ISettingsService>();
|
|
||||||
|
|
||||||
public static List<Models.LanguageInfo> SupportedTargetLanguages =>
|
public static List<Models.LanguageInfo> SupportedTargetLanguages =>
|
||||||
[
|
[
|
||||||
@@ -58,6 +58,11 @@ namespace BetterLyrics.WinUI3.Services
|
|||||||
_identifier = _factory.Load(PathHelper.LanguageProfilePath);
|
_identifier = _factory.Load(PathHelper.LanguageProfilePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static string SimplifiedChineseOrTraditionalChinese(string text)
|
||||||
|
{
|
||||||
|
return text == ChineseConverter.ConvertToSimplifiedChinese(text) ? "zh-Hans" : "zh-Hant";
|
||||||
|
}
|
||||||
|
|
||||||
public static string? DetectLanguageCode(string? text)
|
public static string? DetectLanguageCode(string? text)
|
||||||
{
|
{
|
||||||
if (text == null) return null;
|
if (text == null) return null;
|
||||||
@@ -67,9 +72,9 @@ namespace BetterLyrics.WinUI3.Services
|
|||||||
code = code switch
|
code = code switch
|
||||||
{
|
{
|
||||||
"simple" => "en",
|
"simple" => "en",
|
||||||
"zh_classical" => "zh-Hant",
|
"zh_classical" => SimplifiedChineseOrTraditionalChinese(text),
|
||||||
"zh_yue" => "zh-Hant",
|
"zh_yue" => SimplifiedChineseOrTraditionalChinese(text),
|
||||||
"zh" => "zh-Hans",
|
"zh" => SimplifiedChineseOrTraditionalChinese(text),
|
||||||
_ => code
|
_ => code
|
||||||
};
|
};
|
||||||
return code;
|
return code;
|
||||||
@@ -99,11 +104,6 @@ namespace BetterLyrics.WinUI3.Services
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string GetUserTargetLanguageCode()
|
|
||||||
{
|
|
||||||
return SupportedTargetLanguages[_settingsService.AppSettings.TranslationSettings.SelectedTargetLanguageIndex].Code;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int GetDefaultTargetLanguageIndex()
|
public static int GetDefaultTargetLanguageIndex()
|
||||||
{
|
{
|
||||||
int found = SupportedTargetLanguages.FindIndex(x => ApplicationLanguages.Languages.FirstOrDefault()?.Contains(x.Code) == true);
|
int found = SupportedTargetLanguages.FindIndex(x => ApplicationLanguages.Languages.FirstOrDefault()?.Contains(x.Code) == true);
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using Nito.AsyncEx;
|
using System;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
@@ -10,33 +9,25 @@ namespace BetterLyrics.WinUI3.Helper
|
|||||||
{
|
{
|
||||||
public class LatestOnlyTaskRunner
|
public class LatestOnlyTaskRunner
|
||||||
{
|
{
|
||||||
private readonly AsyncLock _mutex = new();
|
private CancellationTokenSource? _cts;
|
||||||
private CancellationTokenSource _cts;
|
|
||||||
|
|
||||||
public async Task RunAsync(Func<CancellationToken, Task> action)
|
public async Task RunAsync(Func<CancellationToken, Task> taskFactory)
|
||||||
{
|
{
|
||||||
CancellationTokenSource oldCts;
|
_cts?.Cancel();
|
||||||
|
_cts?.Dispose();
|
||||||
|
|
||||||
// 使用 AsyncLock 保证线程安全
|
_cts = new CancellationTokenSource();
|
||||||
using (await _mutex.LockAsync())
|
var token = _cts.Token;
|
||||||
{
|
|
||||||
// 取消旧的
|
|
||||||
oldCts = _cts;
|
|
||||||
_cts = new CancellationTokenSource();
|
|
||||||
}
|
|
||||||
|
|
||||||
oldCts?.Cancel();
|
|
||||||
oldCts?.Dispose();
|
|
||||||
|
|
||||||
CancellationToken token = _cts.Token;
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await action(token);
|
await taskFactory(token);
|
||||||
}
|
}
|
||||||
catch (OperationCanceledException)
|
catch (OperationCanceledException)
|
||||||
{
|
{
|
||||||
// 可以选择忽略取消异常
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
using BetterLyrics.WinUI3.Enums;
|
using BetterLyrics.WinUI3.Enums;
|
||||||
using BetterLyrics.WinUI3.Models;
|
using BetterLyrics.WinUI3.Models;
|
||||||
using BetterLyrics.WinUI3.Services;
|
using BetterLyrics.WinUI3.Services;
|
||||||
|
using Lyricify.Lyrics.Helpers.General;
|
||||||
using Lyricify.Lyrics.Models;
|
using Lyricify.Lyrics.Models;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@@ -47,10 +48,57 @@ namespace BetterLyrics.WinUI3.Helper
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
FillChineseLyricsData();
|
||||||
_lyricsDataArr.Add(new LyricsData()); // 为机翻预留
|
_lyricsDataArr.Add(new LyricsData()); // 为机翻预留
|
||||||
return _lyricsDataArr;
|
return _lyricsDataArr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void FillChineseLyricsData()
|
||||||
|
{
|
||||||
|
var simplifiedChinese = _lyricsDataArr.Where(x => x.LanguageCode == "zh-Hans").FirstOrDefault();
|
||||||
|
var traditionalChinese = _lyricsDataArr.Where(x => x.LanguageCode == "zh-Hant").FirstOrDefault();
|
||||||
|
if (simplifiedChinese != null && traditionalChinese == null)
|
||||||
|
{
|
||||||
|
// 如果没有繁体中文歌词,则将简体中文歌词转换为繁体中文
|
||||||
|
_lyricsDataArr.Add(new LyricsData
|
||||||
|
{
|
||||||
|
LyricsLines = simplifiedChinese.LyricsLines.Select(line => new LyricsLine
|
||||||
|
{
|
||||||
|
StartMs = line.StartMs,
|
||||||
|
EndMs = line.EndMs,
|
||||||
|
OriginalText = ChineseConverter.ConvertToTraditionalChinese(line.OriginalText),
|
||||||
|
LyricsChars = line.LyricsChars.Select(c => new LyricsChar
|
||||||
|
{
|
||||||
|
StartMs = c.StartMs,
|
||||||
|
EndMs = c.EndMs,
|
||||||
|
Text = ChineseConverter.ConvertToTraditionalChinese(c.Text),
|
||||||
|
StartIndex = c.StartIndex
|
||||||
|
}).ToList()
|
||||||
|
}).ToList()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else if (traditionalChinese != null && simplifiedChinese == null)
|
||||||
|
{
|
||||||
|
// 如果没有简体中文歌词,则将繁体中文歌词转换为简体中文
|
||||||
|
_lyricsDataArr.Add(new LyricsData
|
||||||
|
{
|
||||||
|
LyricsLines = traditionalChinese.LyricsLines.Select(line => new LyricsLine
|
||||||
|
{
|
||||||
|
StartMs = line.StartMs,
|
||||||
|
EndMs = line.EndMs,
|
||||||
|
OriginalText = ChineseConverter.ConvertToSimplifiedChinese(line.OriginalText),
|
||||||
|
LyricsChars = line.LyricsChars.Select(c => new LyricsChar
|
||||||
|
{
|
||||||
|
StartMs = c.StartMs,
|
||||||
|
EndMs = c.EndMs,
|
||||||
|
Text = ChineseConverter.ConvertToSimplifiedChinese(c.Text),
|
||||||
|
StartIndex = c.StartIndex
|
||||||
|
}).ToList()
|
||||||
|
}).ToList()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void ParseLrc(string raw)
|
private void ParseLrc(string raw)
|
||||||
{
|
{
|
||||||
var lines = raw.Split(["\r\n", "\n"], StringSplitOptions.RemoveEmptyEntries);
|
var lines = raw.Split(["\r\n", "\n"], StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
|||||||
@@ -1,17 +1,9 @@
|
|||||||
// 2025/6/23 by Zhe Fang
|
// 2025/6/23 by Zhe Fang
|
||||||
|
|
||||||
|
using Windows.ApplicationModel;
|
||||||
|
|
||||||
namespace BetterLyrics.WinUI3.Helper
|
namespace BetterLyrics.WinUI3.Helper
|
||||||
{
|
{
|
||||||
using BetterLyrics.WinUI3.Models;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Windows.ApplicationModel;
|
|
||||||
using Windows.Storage;
|
|
||||||
using Windows.Storage.FileProperties;
|
|
||||||
|
|
||||||
public static class MetadataHelper
|
public static class MetadataHelper
|
||||||
{
|
{
|
||||||
public static string AppVersion
|
public static string AppVersion
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Windows.Foundation;
|
||||||
|
using Windows.Graphics;
|
||||||
|
|
||||||
|
namespace BetterLyrics.WinUI3.Helper
|
||||||
|
{
|
||||||
|
public static class PointHelper
|
||||||
|
{
|
||||||
|
public static PointInt32 ToPointInt32(this Point point)
|
||||||
|
{
|
||||||
|
return new PointInt32((int)point.X, (int)point.Y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
// 2025/6/23 by Zhe Fang
|
// 2025/6/23 by Zhe Fang
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
|
||||||
using BetterLyrics.WinUI3.Enums;
|
using BetterLyrics.WinUI3.Enums;
|
||||||
|
|
||||||
namespace BetterLyrics.WinUI3.Helper
|
namespace BetterLyrics.WinUI3.Helper
|
||||||
@@ -11,6 +10,8 @@ namespace BetterLyrics.WinUI3.Helper
|
|||||||
{
|
{
|
||||||
private T _currentValue;
|
private T _currentValue;
|
||||||
private double _durationSeconds;
|
private double _durationSeconds;
|
||||||
|
private double _delaySeconds;
|
||||||
|
private double _delayRemaining;
|
||||||
private EasingType? _easingType;
|
private EasingType? _easingType;
|
||||||
private Func<T, T, double, T> _interpolator;
|
private Func<T, T, double, T> _interpolator;
|
||||||
private bool _isTransitioning;
|
private bool _isTransitioning;
|
||||||
@@ -19,18 +20,21 @@ namespace BetterLyrics.WinUI3.Helper
|
|||||||
private T _targetValue;
|
private T _targetValue;
|
||||||
|
|
||||||
public double DurationSeconds => _durationSeconds;
|
public double DurationSeconds => _durationSeconds;
|
||||||
|
public double DelaySeconds => _delaySeconds;
|
||||||
|
|
||||||
public bool IsTransitioning => _isTransitioning;
|
public bool IsTransitioning => _isTransitioning;
|
||||||
public T Value => _currentValue;
|
public T Value => _currentValue;
|
||||||
public T TargetValue => _targetValue;
|
public T TargetValue => _targetValue;
|
||||||
public EasingType? EasingType => _easingType;
|
public EasingType? EasingType => _easingType;
|
||||||
|
|
||||||
public ValueTransition(T initialValue, double durationSeconds, Func<T, T, double, T>? interpolator = null, EasingType? easingType = null)
|
public ValueTransition(T initialValue, double durationSeconds, Func<T, T, double, T>? interpolator = null, EasingType? easingType = null, double delaySeconds = 0)
|
||||||
{
|
{
|
||||||
_currentValue = initialValue;
|
_currentValue = initialValue;
|
||||||
_startValue = initialValue;
|
_startValue = initialValue;
|
||||||
_targetValue = initialValue;
|
_targetValue = initialValue;
|
||||||
_durationSeconds = durationSeconds;
|
_durationSeconds = durationSeconds;
|
||||||
|
_delaySeconds = delaySeconds;
|
||||||
|
_delayRemaining = 0;
|
||||||
_progress = 1f;
|
_progress = 1f;
|
||||||
_isTransitioning = false;
|
_isTransitioning = false;
|
||||||
|
|
||||||
@@ -46,7 +50,7 @@ namespace BetterLyrics.WinUI3.Helper
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_easingType = Enums.EasingType.Linear;
|
_easingType = Enums.EasingType.EaseInOutQuad;
|
||||||
_interpolator = GetInterpolatorByEasingType(_easingType.Value);
|
_interpolator = GetInterpolatorByEasingType(_easingType.Value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -58,12 +62,18 @@ namespace BetterLyrics.WinUI3.Helper
|
|||||||
_durationSeconds = seconds;
|
_durationSeconds = seconds;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SetDelay(double seconds)
|
||||||
|
{
|
||||||
|
_delaySeconds = seconds;
|
||||||
|
}
|
||||||
|
|
||||||
private void JumpTo(T value)
|
private void JumpTo(T value)
|
||||||
{
|
{
|
||||||
_currentValue = value;
|
_currentValue = value;
|
||||||
_startValue = value;
|
_startValue = value;
|
||||||
_targetValue = value;
|
_targetValue = value;
|
||||||
_progress = 1f;
|
_progress = 1f;
|
||||||
|
_delayRemaining = 0;
|
||||||
_isTransitioning = false;
|
_isTransitioning = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,6 +83,7 @@ namespace BetterLyrics.WinUI3.Helper
|
|||||||
_startValue = value;
|
_startValue = value;
|
||||||
_targetValue = value;
|
_targetValue = value;
|
||||||
_progress = 0f;
|
_progress = 0f;
|
||||||
|
_delayRemaining = 0;
|
||||||
_isTransitioning = false;
|
_isTransitioning = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -89,6 +100,7 @@ namespace BetterLyrics.WinUI3.Helper
|
|||||||
_startValue = _currentValue;
|
_startValue = _currentValue;
|
||||||
_targetValue = targetValue;
|
_targetValue = targetValue;
|
||||||
_progress = 0f;
|
_progress = 0f;
|
||||||
|
_delayRemaining = _delaySeconds;
|
||||||
_isTransitioning = true;
|
_isTransitioning = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -103,7 +115,24 @@ namespace BetterLyrics.WinUI3.Helper
|
|||||||
{
|
{
|
||||||
if (!_isTransitioning) return;
|
if (!_isTransitioning) return;
|
||||||
|
|
||||||
_progress += (double)(elapsedTime / TimeSpan.FromSeconds(_durationSeconds));
|
if (_delayRemaining > 0)
|
||||||
|
{
|
||||||
|
double consume = Math.Min(_delayRemaining, elapsedTime.TotalSeconds);
|
||||||
|
_delayRemaining -= consume;
|
||||||
|
if (_delayRemaining > 0)
|
||||||
|
return;
|
||||||
|
elapsedTime = TimeSpan.FromSeconds(elapsedTime.TotalSeconds - consume);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_durationSeconds <= 0)
|
||||||
|
{
|
||||||
|
_progress = 1f;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_progress += elapsedTime.TotalSeconds / _durationSeconds;
|
||||||
|
}
|
||||||
|
|
||||||
if (_progress >= 1f)
|
if (_progress >= 1f)
|
||||||
{
|
{
|
||||||
_progress = 1f;
|
_progress = 1f;
|
||||||
@@ -178,4 +207,4 @@ namespace BetterLyrics.WinUI3.Helper
|
|||||||
_interpolator = GetInterpolatorByEasingType(easingType);
|
_interpolator = GetInterpolatorByEasingType(easingType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -18,6 +18,10 @@ namespace BetterLyrics.WinUI3.Helper
|
|||||||
|
|
||||||
public static void CloseWindow<T>()
|
public static void CloseWindow<T>()
|
||||||
{
|
{
|
||||||
|
if (typeof(T) == typeof(LyricsWindow))
|
||||||
|
{
|
||||||
|
EnsureDockModeReleased();
|
||||||
|
}
|
||||||
var window = _activeWindows.Find(w => w is T);
|
var window = _activeWindows.Find(w => w is T);
|
||||||
if (window is Window w)
|
if (window is Window w)
|
||||||
{
|
{
|
||||||
@@ -60,10 +64,31 @@ namespace BetterLyrics.WinUI3.Helper
|
|||||||
throw new ArgumentException("Unsupported window type", nameof(T));
|
throw new ArgumentException("Unsupported window type", nameof(T));
|
||||||
}
|
}
|
||||||
TrackWindow(window);
|
TrackWindow(window);
|
||||||
|
var castedWindow = (Window)window;
|
||||||
|
castedWindow.Restore();
|
||||||
|
castedWindow.Activate();
|
||||||
|
|
||||||
|
if (typeof(T) == typeof(LyricsWindow))
|
||||||
|
{
|
||||||
|
var lyricsWindow = (LyricsWindow)window;
|
||||||
|
lyricsWindow.ViewModel.InitShortcuts();
|
||||||
|
lyricsWindow.AutoSelectLyricsMode();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var castedWindow = (Window)window;
|
||||||
|
if (typeof(T) == typeof(LyricsWindow))
|
||||||
|
{
|
||||||
|
var lyricsWindow = (LyricsWindow)window;
|
||||||
|
lyricsWindow.Show();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
castedWindow.Restore();
|
||||||
|
castedWindow.Activate();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
var castedWindow = (Window)window;
|
|
||||||
castedWindow.Restore();
|
|
||||||
castedWindow.Activate();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void RestartApp(string args = "")
|
public static void RestartApp(string args = "")
|
||||||
@@ -88,12 +113,17 @@ namespace BetterLyrics.WinUI3.Helper
|
|||||||
|
|
||||||
public static void ExitApp()
|
public static void ExitApp()
|
||||||
{
|
{
|
||||||
LyricsWindow? lyricsWindow = WindowHelper.GetWindowByWindowType<LyricsWindow>();
|
EnsureDockModeReleased();
|
||||||
|
Environment.Exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void EnsureDockModeReleased()
|
||||||
|
{
|
||||||
|
LyricsWindow? lyricsWindow = GetWindowByWindowType<LyricsWindow>();
|
||||||
if (lyricsWindow != null)
|
if (lyricsWindow != null)
|
||||||
{
|
{
|
||||||
DockModeHelper.Disable(lyricsWindow);
|
DockModeHelper.Disable(lyricsWindow);
|
||||||
}
|
}
|
||||||
Environment.Exit(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void TrackWindow(object window)
|
private static void TrackWindow(object window)
|
||||||
|
|||||||
39
BetterLyrics.WinUI3/BetterLyrics.WinUI3/Models/LiveStates.cs
Normal file
39
BetterLyrics.WinUI3/BetterLyrics.WinUI3/Models/LiveStates.cs
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
using BetterLyrics.WinUI3.Enums;
|
||||||
|
using BetterLyrics.WinUI3.Models.Settings;
|
||||||
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace BetterLyrics.WinUI3.Models
|
||||||
|
{
|
||||||
|
public partial class LiveStates : ObservableRecipient
|
||||||
|
{
|
||||||
|
[ObservableProperty][NotifyPropertyChangedRecipients] public partial LyricsWindowMode CurrentLyricsWindowMode { get; set; }
|
||||||
|
[ObservableProperty][NotifyPropertyChangedRecipients] public partial LyricsDisplayType CurrentLyricsDisplayType { get; set; }
|
||||||
|
[ObservableProperty][NotifyPropertyChangedRecipients] public partial LyricsStyleSettings CurrentLyricsStyleSettings { get; set; }
|
||||||
|
[ObservableProperty][NotifyPropertyChangedRecipients] public partial LyricsEffectSettings CurrentLyricsEffectSettings { get; set; }
|
||||||
|
|
||||||
|
public LiveStates(AppSettings appSettings)
|
||||||
|
{
|
||||||
|
CurrentLyricsWindowMode = LyricsWindowMode.StandardMode;
|
||||||
|
CurrentLyricsDisplayType = appSettings.StandardModeSettings.LyricsDisplayType;
|
||||||
|
CurrentLyricsStyleSettings = appSettings.StandardLyricsStyleSettings;
|
||||||
|
CurrentLyricsEffectSettings = appSettings.StandardLyricsEffectSettings;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ToggleLyricsWindowMode(LyricsWindowMode mode)
|
||||||
|
{
|
||||||
|
if (CurrentLyricsWindowMode == mode)
|
||||||
|
{
|
||||||
|
CurrentLyricsWindowMode = LyricsWindowMode.StandardMode;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CurrentLyricsWindowMode = mode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,15 +6,15 @@ namespace BetterLyrics.WinUI3.Models
|
|||||||
{
|
{
|
||||||
public partial class LocalMediaFolder : ObservableRecipient
|
public partial class LocalMediaFolder : ObservableRecipient
|
||||||
{
|
{
|
||||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsEnabled { get; set; }
|
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsEnabled { get; set; } = true;
|
||||||
|
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsRealTimeWatchEnabled { get; set; } = false;
|
||||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial string Path { get; set; }
|
[ObservableProperty][NotifyPropertyChangedRecipients] public partial string Path { get; set; }
|
||||||
|
|
||||||
public LocalMediaFolder() { }
|
public LocalMediaFolder() { }
|
||||||
|
|
||||||
public LocalMediaFolder(string path, bool isEnabled)
|
public LocalMediaFolder(string path)
|
||||||
{
|
{
|
||||||
Path = path;
|
Path = path;
|
||||||
IsEnabled = isEnabled;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,23 +36,7 @@ namespace BetterLyrics.WinUI3.Models
|
|||||||
|
|
||||||
if (transLine != null)
|
if (transLine != null)
|
||||||
{
|
{
|
||||||
if (translationData.LanguageCode?.StartsWith("zh") == true)
|
line.DisplayedText = $"{line.OriginalText}{separator}{transLine.OriginalText}";
|
||||||
{
|
|
||||||
string tmp = "";
|
|
||||||
if (LanguageHelper.GetUserTargetLanguageCode() == "zh-Hant")
|
|
||||||
{
|
|
||||||
tmp = ChineseConverter.ConvertToTraditionalChinese(transLine.OriginalText);
|
|
||||||
}
|
|
||||||
else if (LanguageHelper.GetUserTargetLanguageCode() == "zh-Hans")
|
|
||||||
{
|
|
||||||
tmp = ChineseConverter.ConvertToSimplifiedChinese(transLine.OriginalText);
|
|
||||||
}
|
|
||||||
line.DisplayedText = $"{line.OriginalText}{separator}{tmp}";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
line.DisplayedText = $"{line.OriginalText}{separator}{transLine.OriginalText}";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -25,32 +25,32 @@ namespace BetterLyrics.WinUI3.Models
|
|||||||
public ValueTransition<double> AngleTransition { get; set; } = new(
|
public ValueTransition<double> AngleTransition { get; set; } = new(
|
||||||
initialValue: 0,
|
initialValue: 0,
|
||||||
durationSeconds: _animationDuration,
|
durationSeconds: _animationDuration,
|
||||||
easingType: EasingType.EaseInOutSine
|
easingType: EasingType.EaseInOutQuad
|
||||||
);
|
);
|
||||||
public ValueTransition<double> BlurAmountTransition { get; set; } = new(
|
public ValueTransition<double> BlurAmountTransition { get; set; } = new(
|
||||||
initialValue: 0,
|
initialValue: 0,
|
||||||
durationSeconds: _animationDuration,
|
durationSeconds: _animationDuration,
|
||||||
easingType: EasingType.EaseInOutSine
|
easingType: EasingType.EaseInOutQuad
|
||||||
);
|
);
|
||||||
public ValueTransition<double> HighlightOpacityTransition { get; set; } = new(
|
public ValueTransition<double> HighlightOpacityTransition { get; set; } = new(
|
||||||
initialValue: 0,
|
initialValue: 0,
|
||||||
durationSeconds: _animationDuration,
|
durationSeconds: _animationDuration,
|
||||||
easingType: EasingType.EaseInOutSine
|
easingType: EasingType.EaseInOutQuad
|
||||||
);
|
);
|
||||||
public ValueTransition<double> OpacityTransition { get; set; } = new(
|
public ValueTransition<double> OpacityTransition { get; set; } = new(
|
||||||
initialValue: 0,
|
initialValue: 0,
|
||||||
durationSeconds: _animationDuration,
|
durationSeconds: _animationDuration,
|
||||||
easingType: EasingType.EaseInOutSine
|
easingType: EasingType.EaseInOutQuad
|
||||||
);
|
);
|
||||||
public ValueTransition<double> ScaleTransition { get; set; } = new(
|
public ValueTransition<double> ScaleTransition { get; set; } = new(
|
||||||
initialValue: 0.75,
|
initialValue: 0.75,
|
||||||
durationSeconds: _animationDuration,
|
durationSeconds: _animationDuration,
|
||||||
easingType: EasingType.EaseInOutSine
|
easingType: EasingType.EaseInOutQuad
|
||||||
);
|
);
|
||||||
public ValueTransition<double> YOffsetTransition { get; set; } = new(
|
public ValueTransition<double> YOffsetTransition { get; set; } = new(
|
||||||
initialValue: 0,
|
initialValue: 0,
|
||||||
durationSeconds: 0.5,
|
durationSeconds: 0.5,
|
||||||
easingType: EasingType.EaseInOutSine
|
easingType: EasingType.EaseInOutQuad
|
||||||
);
|
);
|
||||||
|
|
||||||
public CanvasTextLayout? CanvasTextLayout { get; private set; }
|
public CanvasTextLayout? CanvasTextLayout { get; private set; }
|
||||||
@@ -69,39 +69,6 @@ namespace BetterLyrics.WinUI3.Models
|
|||||||
|
|
||||||
public CanvasGeometry? TextGeometry { get; private set; }
|
public CanvasGeometry? TextGeometry { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 背景文字层(底字)
|
|
||||||
/// </summary>
|
|
||||||
public CanvasCommandList? BackgroundFontEffect { get; private set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 背景层
|
|
||||||
/// </summary>
|
|
||||||
public OpacityEffect? BackgroundEffect { get; private set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 辉光层
|
|
||||||
/// </summary>
|
|
||||||
public GaussianBlurEffect? ForegroundBlurEffect { get; private set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 高亮层
|
|
||||||
/// </summary>
|
|
||||||
public AlphaMaskEffect? ForegroundHighlightEffect { get; private set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 前景文字层
|
|
||||||
/// </summary>
|
|
||||||
public CanvasCommandList? ForegroundFontEffect { get; private set; }
|
|
||||||
|
|
||||||
public CanvasCommandList? ComposedLineEffect { get; private set; }
|
|
||||||
|
|
||||||
public CanvasCommandList? CurrentCharMask { get; private set; }
|
|
||||||
public CanvasCommandList? LineStartToCurrentCharMask { get; private set; }
|
|
||||||
public CanvasCommandList? CurrentLineMask { get; private set; }
|
|
||||||
|
|
||||||
public CanvasCommandList? PlaceholderEffect { get; private set; }
|
|
||||||
|
|
||||||
public void UpdateCenterPosition(double maxWidth, TextAlignmentType type)
|
public void UpdateCenterPosition(double maxWidth, TextAlignmentType type)
|
||||||
{
|
{
|
||||||
if (CanvasTextLayout == null)
|
if (CanvasTextLayout == null)
|
||||||
@@ -118,10 +85,15 @@ namespace BetterLyrics.WinUI3.Models
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RecreateTextLayout(ICanvasAnimatedControl control, CanvasTextFormat textFormat, double maxWidth, double maxHeight, TextAlignmentType type)
|
public void DisposeTextLayout()
|
||||||
{
|
{
|
||||||
CanvasTextLayout?.Dispose();
|
CanvasTextLayout?.Dispose();
|
||||||
CanvasTextLayout = null;
|
CanvasTextLayout = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RecreateTextLayout(ICanvasAnimatedControl control, CanvasTextFormat textFormat, double maxWidth, double maxHeight, TextAlignmentType type)
|
||||||
|
{
|
||||||
|
DisposeTextLayout();
|
||||||
CanvasTextLayout = new CanvasTextLayout(control, DisplayedText, textFormat, (float)maxWidth, (float)maxHeight);
|
CanvasTextLayout = new CanvasTextLayout(control, DisplayedText, textFormat, (float)maxWidth, (float)maxHeight);
|
||||||
CanvasTextLayout.HorizontalAlignment = type.ToCanvasHorizontalAlignment();
|
CanvasTextLayout.HorizontalAlignment = type.ToCanvasHorizontalAlignment();
|
||||||
}
|
}
|
||||||
@@ -141,392 +113,5 @@ namespace BetterLyrics.WinUI3.Models
|
|||||||
}
|
}
|
||||||
TextGeometry = CanvasGeometry.CreateText(CanvasTextLayout);
|
TextGeometry = CanvasGeometry.CreateText(CanvasTextLayout);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DisposeFontEffects()
|
|
||||||
{
|
|
||||||
BackgroundFontEffect?.Dispose();
|
|
||||||
BackgroundFontEffect = null;
|
|
||||||
ForegroundFontEffect?.Dispose();
|
|
||||||
ForegroundFontEffect = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void RecreateFontEffect(ICanvasAnimatedControl control, Color strokeColor, int strokeWidth, Color bgFontColor, Color fgFontColor)
|
|
||||||
{
|
|
||||||
DisposeFontEffects();
|
|
||||||
if (TextGeometry == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
BackgroundFontEffect = new CanvasCommandList(control);
|
|
||||||
using var bgFontEffectDs = BackgroundFontEffect.CreateDrawingSession();
|
|
||||||
ForegroundFontEffect = new CanvasCommandList(control);
|
|
||||||
using var fgFontEffectDs = ForegroundFontEffect.CreateDrawingSession();
|
|
||||||
// 大于 0 才描边,避免不必要的资源浪费
|
|
||||||
if (strokeWidth > 0)
|
|
||||||
{
|
|
||||||
bgFontEffectDs.DrawGeometry(TextGeometry, Position, strokeColor, strokeWidth); // 描边
|
|
||||||
fgFontEffectDs.DrawGeometry(TextGeometry, Position, strokeColor, strokeWidth); // 描边
|
|
||||||
}
|
|
||||||
bgFontEffectDs.FillGeometry(TextGeometry, Position, bgFontColor); // 填充
|
|
||||||
fgFontEffectDs.FillGeometry(TextGeometry, Position, fgFontColor); // 填充
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 背景层
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="lyricsLayerOpacity">_lyricsOpacityTransition.Value</param>
|
|
||||||
public void RecreateBackgroundEffect(double lyricsLayerOpacity)
|
|
||||||
{
|
|
||||||
BackgroundEffect?.Dispose();
|
|
||||||
BackgroundEffect = null;
|
|
||||||
if (BackgroundFontEffect == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
BackgroundEffect = new OpacityEffect
|
|
||||||
{
|
|
||||||
Source = new GaussianBlurEffect
|
|
||||||
{
|
|
||||||
Source = BackgroundFontEffect,
|
|
||||||
BlurAmount = (float)BlurAmountTransition.Value,
|
|
||||||
BorderMode = EffectBorderMode.Soft,
|
|
||||||
Optimization = EffectOptimization.Speed,
|
|
||||||
},
|
|
||||||
Opacity = (float)(OpacityTransition.Value * lyricsLayerOpacity),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public void UpdateBackgroundEffect(double lyricsLayerOpacity)
|
|
||||||
{
|
|
||||||
BackgroundEffect?.Opacity = (float)(OpacityTransition.Value * lyricsLayerOpacity);
|
|
||||||
GaussianBlurEffect? blurEffect = (GaussianBlurEffect?)(BackgroundEffect?.Source);
|
|
||||||
blurEffect?.BlurAmount = (float)BlurAmountTransition.Value;
|
|
||||||
}
|
|
||||||
|
|
||||||
private IGraphicsEffectSource GetAlphaMask(ICanvasAnimatedControl control, LineRenderingType lineRenderingType)
|
|
||||||
{
|
|
||||||
if (PlaceholderEffect == null)
|
|
||||||
{
|
|
||||||
RecreatePlaceholder(control);
|
|
||||||
}
|
|
||||||
|
|
||||||
var result = lineRenderingType switch
|
|
||||||
{
|
|
||||||
LineRenderingType.CurrentChar => CurrentCharMask,
|
|
||||||
LineRenderingType.LineStartToCurrentChar => LineStartToCurrentCharMask,
|
|
||||||
// Here, cuz AlphaMask only takes care of alpha channel
|
|
||||||
// so ForegroundFontEffect can be a mask for CurrentLine
|
|
||||||
// And we don't need to create a new mask for CurrentLine
|
|
||||||
LineRenderingType.CurrentLine => CurrentLineMask,
|
|
||||||
_ => PlaceholderEffect
|
|
||||||
};
|
|
||||||
return result ?? PlaceholderEffect!;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 销毁并重新创建辉光效果层
|
|
||||||
/// 仅需在布局重构 (Relayout) 时调用
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="lineRenderingType">_lyricsGlowEffectScope</param>
|
|
||||||
/// <param name="glowEffectAmount">_lyricsGlowEffectAmount</param>
|
|
||||||
public void RecreateForegroundBlurEffect(ICanvasAnimatedControl control, LineRenderingType lineRenderingType, double glowEffectAmount)
|
|
||||||
{
|
|
||||||
ForegroundBlurEffect?.Dispose();
|
|
||||||
ForegroundBlurEffect = null;
|
|
||||||
if (ForegroundFontEffect == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var mask = GetAlphaMask(control, lineRenderingType);
|
|
||||||
if (mask == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ForegroundBlurEffect = new GaussianBlurEffect
|
|
||||||
{
|
|
||||||
Source = new AlphaMaskEffect
|
|
||||||
{
|
|
||||||
Source = ForegroundFontEffect,
|
|
||||||
AlphaMask = mask,
|
|
||||||
},
|
|
||||||
BlurAmount = (float)glowEffectAmount,
|
|
||||||
Optimization = EffectOptimization.Speed,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 仅当前行需要调用此方法(每次 Update 都调用一次)
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="control"></param>
|
|
||||||
/// <param name="lineRenderingType"></param>
|
|
||||||
/// <param name="glowEffectAmount"></param>
|
|
||||||
public void UpdateForegroundBlurEffect(ICanvasAnimatedControl control, LineRenderingType lineRenderingType, double glowEffectAmount)
|
|
||||||
{
|
|
||||||
if (ForegroundBlurEffect == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (ForegroundFontEffect == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var mask = GetAlphaMask(control, lineRenderingType);
|
|
||||||
if (mask == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ForegroundBlurEffect.BlurAmount = (float)glowEffectAmount;
|
|
||||||
var alphaMaskEffect = (AlphaMaskEffect)ForegroundBlurEffect.Source;
|
|
||||||
alphaMaskEffect.Source = ForegroundFontEffect;
|
|
||||||
alphaMaskEffect.AlphaMask = mask;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 销毁并重新创建高亮效果层
|
|
||||||
/// 仅需在布局重构 (Relayout) 时调用
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="control"></param>
|
|
||||||
/// <param name="lineRenderingType"></param>
|
|
||||||
public void RecreateForegroundHighlightEffect(ICanvasAnimatedControl control, LineRenderingType lineRenderingType)
|
|
||||||
{
|
|
||||||
ForegroundHighlightEffect?.Dispose();
|
|
||||||
ForegroundHighlightEffect = null;
|
|
||||||
|
|
||||||
if (ForegroundFontEffect == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var mask = GetAlphaMask(control, lineRenderingType);
|
|
||||||
if (mask == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ForegroundHighlightEffect = new AlphaMaskEffect
|
|
||||||
{
|
|
||||||
Source = ForegroundFontEffect,
|
|
||||||
AlphaMask = mask,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 仅当前行需要调用此方法(每次 Update 都调用一次)
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="control"></param>
|
|
||||||
/// <param name="lineRenderingType"></param>
|
|
||||||
public void UpdateForegroundHighlightEffect(ICanvasAnimatedControl control, LineRenderingType lineRenderingType)
|
|
||||||
{
|
|
||||||
if (ForegroundHighlightEffect == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ForegroundFontEffect == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var mask = GetAlphaMask(control, lineRenderingType);
|
|
||||||
if (mask == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ForegroundHighlightEffect.Source = ForegroundFontEffect;
|
|
||||||
ForegroundHighlightEffect.AlphaMask = mask;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 仅当前播放行需要调用此方法(每次 Update 都调用一次)
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="control"></param>
|
|
||||||
/// <param name="playingLineIndex"></param>
|
|
||||||
/// <param name="charStartIndex"></param>
|
|
||||||
/// <param name="charLength"></param>
|
|
||||||
/// <param name="charProgress"></param>
|
|
||||||
public void RecreateCurrentCharMask(ICanvasAnimatedControl control, int charStartIndex, int charLength, double charProgress)
|
|
||||||
{
|
|
||||||
CurrentCharMask?.Dispose();
|
|
||||||
CurrentCharMask = null;
|
|
||||||
CurrentCharMask = new CanvasCommandList(control);
|
|
||||||
|
|
||||||
if (CanvasTextLayout == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
using var ds = CurrentCharMask.CreateDrawingSession();
|
|
||||||
|
|
||||||
var highlightRegion = CanvasTextLayout
|
|
||||||
.GetCharacterRegions(charStartIndex, charLength)
|
|
||||||
.FirstOrDefault();
|
|
||||||
|
|
||||||
double highlightTotalWidth = (double)highlightRegion.LayoutBounds.Width;
|
|
||||||
// Draw the highlight for the current character
|
|
||||||
double highlightWidth = highlightTotalWidth * charProgress;
|
|
||||||
|
|
||||||
double fadingWidth = (double)highlightRegion.LayoutBounds.Height / 2;
|
|
||||||
|
|
||||||
// Rects
|
|
||||||
var highlightRect = new Rect(
|
|
||||||
highlightRegion.LayoutBounds.X,
|
|
||||||
highlightRegion.LayoutBounds.Y + Position.Y,
|
|
||||||
highlightWidth,
|
|
||||||
highlightRegion.LayoutBounds.Height
|
|
||||||
);
|
|
||||||
|
|
||||||
var fadeInRect = new Rect(
|
|
||||||
highlightRect.Right - fadingWidth,
|
|
||||||
highlightRegion.LayoutBounds.Y + Position.Y,
|
|
||||||
fadingWidth,
|
|
||||||
highlightRegion.LayoutBounds.Height
|
|
||||||
);
|
|
||||||
var fadeOutRect = new Rect(
|
|
||||||
highlightRect.Right,
|
|
||||||
highlightRegion.LayoutBounds.Y + Position.Y,
|
|
||||||
fadingWidth,
|
|
||||||
highlightRegion.LayoutBounds.Height
|
|
||||||
);
|
|
||||||
|
|
||||||
// Brushes
|
|
||||||
using var fadeInBrush = CanvasHelper.CreateHorizontalFillBrush(
|
|
||||||
control,
|
|
||||||
[(0f, 0f), (1f, 1f)],
|
|
||||||
(double)highlightRect.Right - fadingWidth,
|
|
||||||
fadingWidth
|
|
||||||
);
|
|
||||||
using var fadeOutBrush = CanvasHelper.CreateHorizontalFillBrush(
|
|
||||||
control,
|
|
||||||
[(0f, 1f), (1f, 0f)],
|
|
||||||
(double)highlightRect.Right,
|
|
||||||
fadingWidth
|
|
||||||
);
|
|
||||||
|
|
||||||
ds.FillRectangle(fadeInRect, fadeInBrush);
|
|
||||||
ds.FillRectangle(fadeOutRect, fadeOutBrush);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 仅当前播放行需要调用此方法(每次 Update 都调用一次)
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="control"></param>
|
|
||||||
/// <param name="playingLineIndex"></param>
|
|
||||||
/// <param name="charStartIndex"></param>
|
|
||||||
/// <param name="charLength"></param>
|
|
||||||
/// <param name="charProgress"></param>
|
|
||||||
public void RecreateLineStartToCurrentCharMask(ICanvasAnimatedControl control, int charStartIndex, int charLength, double charProgress)
|
|
||||||
{
|
|
||||||
LineStartToCurrentCharMask?.Dispose();
|
|
||||||
LineStartToCurrentCharMask = null;
|
|
||||||
LineStartToCurrentCharMask = new CanvasCommandList(control);
|
|
||||||
|
|
||||||
if (CanvasTextLayout == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
using var ds = LineStartToCurrentCharMask.CreateDrawingSession();
|
|
||||||
|
|
||||||
var regions = CanvasTextLayout.GetCharacterRegions(0, charStartIndex);
|
|
||||||
var highlightRegion = CanvasTextLayout
|
|
||||||
.GetCharacterRegions(charStartIndex, charLength)
|
|
||||||
.FirstOrDefault();
|
|
||||||
if (regions.Length > 0)
|
|
||||||
{
|
|
||||||
// Draw the mask for the current line
|
|
||||||
for (int j = 0; j < regions.Length; j++)
|
|
||||||
{
|
|
||||||
var region = regions[j];
|
|
||||||
var rect = new Rect(
|
|
||||||
region.LayoutBounds.X,
|
|
||||||
region.LayoutBounds.Y + Position.Y,
|
|
||||||
region.LayoutBounds.Width,
|
|
||||||
region.LayoutBounds.Height
|
|
||||||
);
|
|
||||||
ds.FillRectangle(rect, Color.FromArgb(255, 128, 128, 128));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
double highlightTotalWidth = (double)highlightRegion.LayoutBounds.Width;
|
|
||||||
// Draw the highlight for the current character
|
|
||||||
double highlightWidth = highlightTotalWidth * charProgress;
|
|
||||||
|
|
||||||
double fadingWidth = (double)highlightRegion.LayoutBounds.Height / 2;
|
|
||||||
|
|
||||||
// Rects
|
|
||||||
var highlightRect = new Rect(
|
|
||||||
highlightRegion.LayoutBounds.X,
|
|
||||||
highlightRegion.LayoutBounds.Y + Position.Y,
|
|
||||||
highlightWidth,
|
|
||||||
highlightRegion.LayoutBounds.Height
|
|
||||||
);
|
|
||||||
|
|
||||||
var fadeInRect = new Rect(
|
|
||||||
highlightRect.Right - fadingWidth,
|
|
||||||
highlightRegion.LayoutBounds.Y + Position.Y,
|
|
||||||
fadingWidth,
|
|
||||||
highlightRegion.LayoutBounds.Height
|
|
||||||
);
|
|
||||||
var fadeOutRect = new Rect(
|
|
||||||
highlightRect.Right,
|
|
||||||
highlightRegion.LayoutBounds.Y + Position.Y,
|
|
||||||
fadingWidth,
|
|
||||||
highlightRegion.LayoutBounds.Height
|
|
||||||
);
|
|
||||||
|
|
||||||
// Brushes
|
|
||||||
using var fadeOutBrush = CanvasHelper.CreateHorizontalFillBrush(
|
|
||||||
control,
|
|
||||||
[(0f, 1f), (1f, 0f)],
|
|
||||||
(double)highlightRect.Right,
|
|
||||||
fadingWidth
|
|
||||||
);
|
|
||||||
|
|
||||||
ds.FillRectangle(highlightRect, Color.FromArgb(255, 128, 128, 128));
|
|
||||||
ds.FillRectangle(fadeOutRect, fadeOutBrush);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 重建当前行遮罩
|
|
||||||
/// 仅需在布局重构 (Relayout) 时调用
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="control"></param>
|
|
||||||
public void RecreateCurrentLineMask(ICanvasAnimatedControl control)
|
|
||||||
{
|
|
||||||
CurrentLineMask?.Dispose();
|
|
||||||
CurrentLineMask = null;
|
|
||||||
|
|
||||||
if (CanvasTextLayout == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
CurrentLineMask = new CanvasCommandList(control);
|
|
||||||
using var ds = CurrentLineMask.CreateDrawingSession();
|
|
||||||
|
|
||||||
var regions = CanvasTextLayout.GetCharacterRegions(0, OriginalText.Length);
|
|
||||||
if (regions.Length > 0)
|
|
||||||
{
|
|
||||||
for (int j = 0; j < regions.Length; j++)
|
|
||||||
{
|
|
||||||
var region = regions[j];
|
|
||||||
var rect = new Rect(
|
|
||||||
region.LayoutBounds.X,
|
|
||||||
region.LayoutBounds.Y + Position.Y,
|
|
||||||
region.LayoutBounds.Width,
|
|
||||||
region.LayoutBounds.Height
|
|
||||||
);
|
|
||||||
ds.FillRectangle(rect, Colors.White);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void RecreatePlaceholder(ICanvasAnimatedControl control)
|
|
||||||
{
|
|
||||||
PlaceholderEffect?.Dispose();
|
|
||||||
PlaceholderEffect = null;
|
|
||||||
PlaceholderEffect = new CanvasCommandList(control);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,8 +40,8 @@ namespace BetterLyrics.WinUI3.Models
|
|||||||
PositionOffset = 1000;
|
PositionOffset = 1000;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
// 设置 100 以防不必要的重复同步
|
// 设置 300 以防不必要的重复同步
|
||||||
TimelineSyncThreshold = 100;
|
TimelineSyncThreshold = 300;
|
||||||
PositionOffset = 0;
|
PositionOffset = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
using BetterLyrics.WinUI3.Enums;
|
||||||
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace BetterLyrics.WinUI3.Models.Settings
|
||||||
|
{
|
||||||
|
public partial class AdvancedSettings : ObservableRecipient
|
||||||
|
{
|
||||||
|
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsFixedTimeStep { get; set; } = false;
|
||||||
|
[ObservableProperty][NotifyPropertyChangedRecipients] public partial int FPS { get; set; } = 60;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -12,6 +12,7 @@ namespace BetterLyrics.WinUI3.Models.Settings
|
|||||||
{
|
{
|
||||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial TextAlignmentType SongInfoAlignmentType { get; set; } = TextAlignmentType.Left;
|
[ObservableProperty][NotifyPropertyChangedRecipients] public partial TextAlignmentType SongInfoAlignmentType { get; set; } = TextAlignmentType.Left;
|
||||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial int CoverImageRadius { get; set; } = 12; // 12 % of the cover image size
|
[ObservableProperty][NotifyPropertyChangedRecipients] public partial int CoverImageRadius { get; set; } = 12; // 12 % of the cover image size
|
||||||
|
[ObservableProperty][NotifyPropertyChangedRecipients] public partial int CoverImageShadowAmount { get; set; } = 12;
|
||||||
|
|
||||||
public AlbumArtLayoutSettings() { }
|
public AlbumArtLayoutSettings() { }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,23 +9,28 @@ namespace BetterLyrics.WinUI3.Models.Settings
|
|||||||
public partial class AppSettings : ObservableRecipient
|
public partial class AppSettings : ObservableRecipient
|
||||||
{
|
{
|
||||||
public string Version { get; set; } = Helper.MetadataHelper.AppVersion;
|
public string Version { get; set; } = Helper.MetadataHelper.AppVersion;
|
||||||
|
|
||||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial LyricsStyleSettings StandardLyricsStyleSettings { get; set; } = new LyricsStyleSettings(32, TextAlignmentType.Left, 0);
|
[ObservableProperty][NotifyPropertyChangedRecipients] public partial LyricsStyleSettings StandardLyricsStyleSettings { get; set; } = new LyricsStyleSettings(32, TextAlignmentType.Left, 0);
|
||||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial LyricsStyleSettings DesktopLyricsStyleSettings { get; set; } = new LyricsStyleSettings(28, TextAlignmentType.Center, 2);
|
[ObservableProperty][NotifyPropertyChangedRecipients] public partial LyricsStyleSettings DesktopLyricsStyleSettings { get; set; } = new LyricsStyleSettings(28, TextAlignmentType.Center, 2);
|
||||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial LyricsStyleSettings DockLyricsStyleSettings { get; set; } = new LyricsStyleSettings(16, TextAlignmentType.Center, 0);
|
[ObservableProperty][NotifyPropertyChangedRecipients] public partial LyricsStyleSettings DockLyricsStyleSettings { get; set; } = new LyricsStyleSettings(16, TextAlignmentType.Center, 0);
|
||||||
|
[ObservableProperty][NotifyPropertyChangedRecipients] public partial LyricsStyleSettings PictureInPictureLyricsStyleSettings { get; set; } = new LyricsStyleSettings(28, TextAlignmentType.Left, 0);
|
||||||
|
|
||||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial LyricsEffectSettings StandardLyricsEffectSettings { get; set; } = new LyricsEffectSettings(100, 500, 1000, EasingType.EaseInOutSine);
|
[ObservableProperty][NotifyPropertyChangedRecipients] public partial LyricsEffectSettings StandardLyricsEffectSettings { get; set; } = new LyricsEffectSettings(100, 500, 1000, EasingType.EaseInOutQuad);
|
||||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial LyricsEffectSettings DesktopLyricsEffectSettings { get; set; } = new LyricsEffectSettings(500, 500, 500, EasingType.EaseInOutSine);
|
[ObservableProperty][NotifyPropertyChangedRecipients] public partial LyricsEffectSettings DesktopLyricsEffectSettings { get; set; } = new LyricsEffectSettings(500, 500, 500, EasingType.EaseInOutQuad);
|
||||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial LyricsEffectSettings DockLyricsEffectSettings { get; set; } = new LyricsEffectSettings(500, 500, 500, EasingType.EaseInOutSine);
|
[ObservableProperty][NotifyPropertyChangedRecipients] public partial LyricsEffectSettings DockLyricsEffectSettings { get; set; } = new LyricsEffectSettings(500, 500, 500, EasingType.EaseInOutQuad);
|
||||||
|
[ObservableProperty][NotifyPropertyChangedRecipients] public partial LyricsEffectSettings PictureInPictureLyricsEffectSettings { get; set; } = new LyricsEffectSettings(500, 500, 500, EasingType.EaseInOutQuad);
|
||||||
|
|
||||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial StandardModeSettings StandardModeSettings { get; set; } = new StandardModeSettings();
|
[ObservableProperty][NotifyPropertyChangedRecipients] public partial StandardModeSettings StandardModeSettings { get; set; } = new StandardModeSettings();
|
||||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial DesktopModeSettings DesktopModeSettings { get; set; } = new DesktopModeSettings();
|
[ObservableProperty][NotifyPropertyChangedRecipients] public partial DesktopModeSettings DesktopModeSettings { get; set; } = new DesktopModeSettings();
|
||||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial DockModeSettings DockModeSettings { get; set; } = new DockModeSettings();
|
[ObservableProperty][NotifyPropertyChangedRecipients] public partial DockModeSettings DockModeSettings { get; set; } = new DockModeSettings();
|
||||||
|
[ObservableProperty][NotifyPropertyChangedRecipients] public partial PictureInPictureModeSettings PictureInPictureModeSettings { get; set; } = new PictureInPictureModeSettings();
|
||||||
|
|
||||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial LyricsBackgroundSettings LyricsBackgroundSettings { get; set; } = new LyricsBackgroundSettings();
|
[ObservableProperty][NotifyPropertyChangedRecipients] public partial LyricsBackgroundSettings LyricsBackgroundSettings { get; set; } = new LyricsBackgroundSettings();
|
||||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial AlbumArtLayoutSettings AlbumArtLayoutSettings { get; set; } = new AlbumArtLayoutSettings();
|
[ObservableProperty][NotifyPropertyChangedRecipients] public partial AlbumArtLayoutSettings AlbumArtLayoutSettings { get; set; } = new AlbumArtLayoutSettings();
|
||||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial TranslationSettings TranslationSettings { get; set; } = new TranslationSettings();
|
[ObservableProperty][NotifyPropertyChangedRecipients] public partial TranslationSettings TranslationSettings { get; set; } = new TranslationSettings();
|
||||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial GeneralSettings GeneralSettings { get; set; } = new GeneralSettings();
|
[ObservableProperty][NotifyPropertyChangedRecipients] public partial GeneralSettings GeneralSettings { get; set; } = new GeneralSettings();
|
||||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial MusicGallerySettings MusicGallerySettings { get; set; } = new MusicGallerySettings();
|
[ObservableProperty][NotifyPropertyChangedRecipients] public partial MusicGallerySettings MusicGallerySettings { get; set; } = new MusicGallerySettings();
|
||||||
|
[ObservableProperty][NotifyPropertyChangedRecipients] public partial AdvancedSettings AdvancedSettings { get; set; } = new AdvancedSettings();
|
||||||
|
|
||||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial FullyObservableCollection<LocalMediaFolder> LocalMediaFolders { get; set; } = [];
|
[ObservableProperty][NotifyPropertyChangedRecipients] public partial FullyObservableCollection<LocalMediaFolder> LocalMediaFolders { get; set; } = [];
|
||||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial FullyObservableCollection<MediaSourceProviderInfo> MediaSourceProvidersInfo { get; set; } = [];
|
[ObservableProperty][NotifyPropertyChangedRecipients] public partial FullyObservableCollection<MediaSourceProviderInfo> MediaSourceProvidersInfo { get; set; } = [];
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
using BetterLyrics.WinUI3.Enums;
|
||||||
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace BetterLyrics.WinUI3.Models.Settings
|
||||||
|
{
|
||||||
|
public partial class BaseModeSettings : ObservableRecipient
|
||||||
|
{
|
||||||
|
[ObservableProperty][NotifyPropertyChangedRecipients] public partial LyricsDisplayType LyricsDisplayType { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,12 +9,16 @@ using Windows.Graphics;
|
|||||||
|
|
||||||
namespace BetterLyrics.WinUI3.Models.Settings
|
namespace BetterLyrics.WinUI3.Models.Settings
|
||||||
{
|
{
|
||||||
public partial class DesktopModeSettings : ObservableRecipient
|
public partial class DesktopModeSettings : BaseModeSettings
|
||||||
{
|
{
|
||||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial Rect WindowBounds { get; set; } = new Rect(100, 100, 400, 200);
|
[ObservableProperty][NotifyPropertyChangedRecipients] public partial Rect WindowBounds { get; set; } = new Rect(100, 100, 400, 200);
|
||||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool AutoLockOnDesktopMode { get; set; } = false;
|
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool AutoLockOnDesktopMode { get; set; } = false;
|
||||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial int LockHotKeyIndex { get; set; } = 'U' - 'A'; // Default to 'U' key
|
[ObservableProperty][NotifyPropertyChangedRecipients] public partial List<string> LockShortcut { get; set; } = new List<string>() { "Ctrl", "Alt", "U" };
|
||||||
|
[ObservableProperty][NotifyPropertyChangedRecipients] public partial List<string> ToggleShortcut { get; set; } = new List<string>() { "Ctrl", "Alt", "D" };
|
||||||
|
|
||||||
public DesktopModeSettings() { }
|
public DesktopModeSettings()
|
||||||
|
{
|
||||||
|
LyricsDisplayType = Enums.LyricsDisplayType.LyricsOnly;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,12 +9,16 @@ using System.Threading.Tasks;
|
|||||||
|
|
||||||
namespace BetterLyrics.WinUI3.Models.Settings
|
namespace BetterLyrics.WinUI3.Models.Settings
|
||||||
{
|
{
|
||||||
public partial class DockModeSettings : ObservableRecipient
|
public partial class DockModeSettings : BaseModeSettings
|
||||||
{
|
{
|
||||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial DockPlacement DockPlacement { get; set; } = DockPlacement.Top;
|
[ObservableProperty][NotifyPropertyChangedRecipients] public partial DockPlacement DockPlacement { get; set; } = DockPlacement.Top;
|
||||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial int DockWindowHeight { get; set; } = 64;
|
[ObservableProperty][NotifyPropertyChangedRecipients] public partial int DockWindowHeight { get; set; } = 64;
|
||||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial string DockMonitorDeviceName { get; set; } = MonitorHelper.GetPrimaryMonitorDeviceName();
|
[ObservableProperty][NotifyPropertyChangedRecipients] public partial string DockMonitorDeviceName { get; set; } = MonitorHelper.GetPrimaryMonitorDeviceName();
|
||||||
|
[ObservableProperty][NotifyPropertyChangedRecipients] public partial List<string> ToggleShortcut { get; set; } = new List<string> { "Ctrl", "Shift", "D" };
|
||||||
public DockModeSettings() { }
|
|
||||||
|
public DockModeSettings()
|
||||||
|
{
|
||||||
|
LyricsDisplayType = LyricsDisplayType.LyricsOnly;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,14 +10,17 @@ namespace BetterLyrics.WinUI3.Models.Settings
|
|||||||
{
|
{
|
||||||
public partial class GeneralSettings : ObservableRecipient
|
public partial class GeneralSettings : ObservableRecipient
|
||||||
{
|
{
|
||||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial AutoStartWindowType AutoStartWindowType { get; set; } = AutoStartWindowType.StandardMode;
|
[ObservableProperty][NotifyPropertyChangedRecipients] public partial LyricsWindowMode AutoStartWindowType { get; set; } = LyricsWindowMode.StandardMode;
|
||||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial Language Language { get; set; } = Language.FollowSystem;
|
[ObservableProperty][NotifyPropertyChangedRecipients] public partial Language Language { get; set; } = Language.FollowSystem;
|
||||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IgnoreFullscreenWindow { get; set; } = false;
|
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IgnoreFullscreenWindow { get; set; } = false;
|
||||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial string LXMusicServer { get; set; } = string.Empty;
|
[ObservableProperty][NotifyPropertyChangedRecipients] public partial string LXMusicServer { get; set; } = string.Empty;
|
||||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool HideWindowWhenNotPlaying { get; set; } = true;
|
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool HideWindowWhenNotPlaying { get; set; } = true;
|
||||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsDragEverywhereEnabled { get; set; } = false;
|
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsDragEverywhereEnabled { get; set; } = false;
|
||||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial LyricsDisplayType DisplayType { get; set; } = LyricsDisplayType.SplitView;
|
|
||||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsImmersiveMode { get; set; } = false;
|
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsImmersiveMode { get; set; } = false;
|
||||||
|
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool ExitOnLyricsWindowClosed { get; set; } = true;
|
||||||
|
[ObservableProperty][NotifyPropertyChangedRecipients] public partial List<string> PlayOrPauseShortcut { get; set; } = new List<string> { "Ctrl", "Alt", "P" };
|
||||||
|
[ObservableProperty][NotifyPropertyChangedRecipients] public partial List<string> NextSongShortcut { get; set; } = new List<string> { "Ctrl", "Alt", "Right" };
|
||||||
|
[ObservableProperty][NotifyPropertyChangedRecipients] public partial List<string> PreviousSongShortcut { get; set; } = new List<string> { "Ctrl", "Alt", "Left" };
|
||||||
|
|
||||||
public GeneralSettings() { }
|
public GeneralSettings() { }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,18 +11,36 @@ namespace BetterLyrics.WinUI3.Models.Settings
|
|||||||
public partial class LyricsEffectSettings : ObservableRecipient
|
public partial class LyricsEffectSettings : ObservableRecipient
|
||||||
{
|
{
|
||||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial int LyricsBlurAmount { get; set; } = 5;
|
[ObservableProperty][NotifyPropertyChangedRecipients] public partial int LyricsBlurAmount { get; set; } = 5;
|
||||||
|
|
||||||
|
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsLyricsLineFadeEnabled { get; set; } = false;
|
||||||
|
|
||||||
|
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsLyricsGlowEffectEnabled { get; set; } = true;
|
||||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial LineRenderingType LyricsGlowEffectScope { get; set; } = LineRenderingType.CurrentChar;
|
[ObservableProperty][NotifyPropertyChangedRecipients] public partial LineRenderingType LyricsGlowEffectScope { get; set; } = LineRenderingType.CurrentChar;
|
||||||
|
[ObservableProperty][NotifyPropertyChangedRecipients] public partial int LyricsGlowEffectAmount { get; set; } = 8;
|
||||||
|
|
||||||
|
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsLyricsShadowEnabled { get; set; } = false;
|
||||||
|
[ObservableProperty][NotifyPropertyChangedRecipients] public partial LineRenderingType LyricsShadowScope { get; set; } = LineRenderingType.LineStartToCurrentChar;
|
||||||
|
[ObservableProperty][NotifyPropertyChangedRecipients] public partial int LyricsShadowAmount { get; set; } = 8;
|
||||||
|
|
||||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial LineRenderingType LyricsHighlightScope { get; set; } = LineRenderingType.LineStartToCurrentChar;
|
[ObservableProperty][NotifyPropertyChangedRecipients] public partial LineRenderingType LyricsHighlightScope { get; set; } = LineRenderingType.LineStartToCurrentChar;
|
||||||
|
[ObservableProperty][NotifyPropertyChangedRecipients] public partial int LyricsHighlightAmount { get; set; } = 100; // 100% 是上界
|
||||||
|
|
||||||
|
[ObservableProperty][NotifyPropertyChangedRecipients] public partial int LyricsTranslationHighlightAmount { get; set; } = 60; // 100% 是上界
|
||||||
|
|
||||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsLyricsFloatAnimationEnabled { get; set; } = true;
|
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsLyricsFloatAnimationEnabled { get; set; } = true;
|
||||||
|
[ObservableProperty][NotifyPropertyChangedRecipients] public partial int LyricsFloatAmount { get; set; } = 1;
|
||||||
|
|
||||||
|
[ObservableProperty][NotifyPropertyChangedRecipients] public partial EasingType LyricsScrollEasingType { get; set; }
|
||||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial int LyricsScrollDuration { get; set; }
|
[ObservableProperty][NotifyPropertyChangedRecipients] public partial int LyricsScrollDuration { get; set; }
|
||||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial int LyricsScrollTopDuration { get; set; }
|
[ObservableProperty][NotifyPropertyChangedRecipients] public partial int LyricsScrollTopDuration { get; set; }
|
||||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial int LyricsScrollBottomDuration { get; set; }
|
[ObservableProperty][NotifyPropertyChangedRecipients] public partial int LyricsScrollBottomDuration { get; set; }
|
||||||
|
[ObservableProperty][NotifyPropertyChangedRecipients] public partial int LyricsScrollTopDelay { get; set; } = 0;
|
||||||
|
[ObservableProperty][NotifyPropertyChangedRecipients] public partial int LyricsScrollBottomDelay { get; set; } = 0;
|
||||||
|
|
||||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial int LyricsVerticalEdgeOpacity { get; set; } = 0; // 0% opacity
|
[ObservableProperty][NotifyPropertyChangedRecipients] public partial int LyricsVerticalEdgeOpacity { get; set; } = 0; // 0% opacity
|
||||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsFanLyricsEnabled { get; set; } = false;
|
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsFanLyricsEnabled { get; set; } = false;
|
||||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsLyricsGlowEffectEnabled { get; set; } = true;
|
|
||||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial EasingType LyricsScrollEasingType { get; set; }
|
|
||||||
|
|
||||||
public LyricsEffectSettings(int lyricsScrollTopDuration, int lyricsScrollDuration, int lyricsScrollBottomDuration, EasingType lyricsScrollEasingType)
|
public LyricsEffectSettings(int lyricsScrollTopDuration, int lyricsScrollDuration, int lyricsScrollBottomDuration, EasingType lyricsScrollEasingType)
|
||||||
{
|
{
|
||||||
LyricsScrollTopDuration = lyricsScrollTopDuration;
|
LyricsScrollTopDuration = lyricsScrollTopDuration;
|
||||||
LyricsScrollDuration = lyricsScrollDuration;
|
LyricsScrollDuration = lyricsScrollDuration;
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ namespace BetterLyrics.WinUI3.Models.Settings
|
|||||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial double LyricsLineSpacingFactor { get; set; } = 0.5;
|
[ObservableProperty][NotifyPropertyChangedRecipients] public partial double LyricsLineSpacingFactor { get; set; } = 0.5;
|
||||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial string LyricsTranslationSeparator { get; set; } = StringHelper.NewLine;
|
[ObservableProperty][NotifyPropertyChangedRecipients] public partial string LyricsTranslationSeparator { get; set; } = StringHelper.NewLine;
|
||||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial string LyricsFontFamily { get; set; } = FontHelper.SystemFontFamilies.FirstOrDefault() ?? "";
|
[ObservableProperty][NotifyPropertyChangedRecipients] public partial string LyricsFontFamily { get; set; } = FontHelper.SystemFontFamilies.FirstOrDefault() ?? "";
|
||||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial int SelectedFontFamilyIndex { get; set; } = 0;
|
|
||||||
|
|
||||||
public LyricsStyleSettings() { }
|
public LyricsStyleSettings() { }
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Windows.Foundation;
|
||||||
|
|
||||||
|
namespace BetterLyrics.WinUI3.Models.Settings
|
||||||
|
{
|
||||||
|
public partial class PictureInPictureModeSettings : BaseModeSettings
|
||||||
|
{
|
||||||
|
[ObservableProperty][NotifyPropertyChangedRecipients] public partial Point WindowPosition { get; set; } = new Point(100, 100);
|
||||||
|
[ObservableProperty][NotifyPropertyChangedRecipients] public partial List<string> ToggleShortcut { get; set; } = new List<string>() { "Ctrl", "Shift", "P" };
|
||||||
|
|
||||||
|
public PictureInPictureModeSettings()
|
||||||
|
{
|
||||||
|
LyricsDisplayType = Enums.LyricsDisplayType.SplitView;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
using BetterLyrics.WinUI3.Enums;
|
||||||
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@@ -9,10 +10,14 @@ using Windows.Graphics;
|
|||||||
|
|
||||||
namespace BetterLyrics.WinUI3.Models.Settings
|
namespace BetterLyrics.WinUI3.Models.Settings
|
||||||
{
|
{
|
||||||
public partial class StandardModeSettings : ObservableRecipient
|
public partial class StandardModeSettings : BaseModeSettings
|
||||||
{
|
{
|
||||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial Rect WindowBounds { get; set; } = new Rect(100, 100, 1000, 600);
|
[ObservableProperty][NotifyPropertyChangedRecipients] public partial Rect WindowBounds { get; set; } = new Rect(100, 100, 1000, 600);
|
||||||
|
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsMaximized { get; set; } = false;
|
||||||
public StandardModeSettings() { }
|
|
||||||
|
public StandardModeSettings()
|
||||||
|
{
|
||||||
|
LyricsDisplayType = LyricsDisplayType.SplitView;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
xmlns:interactivity="using:Microsoft.Xaml.Interactivity"
|
xmlns:interactivity="using:Microsoft.Xaml.Interactivity"
|
||||||
xmlns:local="using:BetterLyrics.WinUI3.Renderer"
|
xmlns:local="using:BetterLyrics.WinUI3.Renderer"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
Unloaded="LyricsCanvas_Unloaded"
|
||||||
mc:Ignorable="d">
|
mc:Ignorable="d">
|
||||||
|
|
||||||
<Grid>
|
<Grid>
|
||||||
@@ -15,15 +16,5 @@
|
|||||||
x:Name="LyricsCanvas"
|
x:Name="LyricsCanvas"
|
||||||
Draw="LyricsCanvas_Draw"
|
Draw="LyricsCanvas_Draw"
|
||||||
Update="LyricsCanvas_Update" />
|
Update="LyricsCanvas_Update" />
|
||||||
<Grid
|
|
||||||
Margin="36"
|
|
||||||
HorizontalAlignment="Right"
|
|
||||||
VerticalAlignment="Top"
|
|
||||||
Visibility="{x:Bind ViewModel.IsTranslating, Mode=OneWay, Converter={StaticResource BoolToVisibilityConverter}}">
|
|
||||||
<FontIcon
|
|
||||||
x:Name="RotatingIcon"
|
|
||||||
FontFamily="{StaticResource IconFontFamily}"
|
|
||||||
Glyph="" />
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
</Grid>
|
||||||
</UserControl>
|
</UserControl>
|
||||||
|
|||||||
@@ -25,5 +25,11 @@ namespace BetterLyrics.WinUI3.Renderer
|
|||||||
{
|
{
|
||||||
ViewModel.Update(sender, args);
|
ViewModel.Update(sender, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void LyricsCanvas_Unloaded(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
LyricsCanvas.RemoveFromVisualTree();
|
||||||
|
LyricsCanvas = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using ATL;
|
using ATL;
|
||||||
using BetterLyrics.WinUI3.Enums;
|
using BetterLyrics.WinUI3.Enums;
|
||||||
using BetterLyrics.WinUI3.Helper;
|
using BetterLyrics.WinUI3.Helper;
|
||||||
|
using BetterLyrics.WinUI3.Helper.BetterLyrics.WinUI3.Helper;
|
||||||
using BetterLyrics.WinUI3.Services.SettingsService;
|
using BetterLyrics.WinUI3.Services.SettingsService;
|
||||||
using CommunityToolkit.Mvvm.DependencyInjection;
|
using CommunityToolkit.Mvvm.DependencyInjection;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
@@ -30,37 +31,49 @@ namespace BetterLyrics.WinUI3.Services.AlbumArtSearchService
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async Task<byte[]?> SearchAsync(string mediaSessionId, string title, string artist, string album, byte[]? bytesFromSMTC = null)
|
public async Task<byte[]?> SearchAsync(string mediaSessionId, string title, string artist, string album, byte[]? bytesFromSMTC = null)
|
||||||
|
{
|
||||||
|
return await Task.Run(async () => await SearchAsyncCore(mediaSessionId, title, artist, album, bytesFromSMTC));
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<byte[]?> SearchAsyncCore(string mediaSessionId, string title, string artist, string album, byte[]? bytesFromSMTC = null)
|
||||||
{
|
{
|
||||||
byte[]? result = null;
|
byte[]? result = null;
|
||||||
|
|
||||||
foreach (var provider in _settingsService.AppSettings.MediaSourceProvidersInfo.Where(x => x.Provider == mediaSessionId).FirstOrDefault()?.AlbumArtSearchProvidersInfo ?? [])
|
try
|
||||||
{
|
{
|
||||||
if (!provider.IsEnabled)
|
foreach (var provider in _settingsService.AppSettings.MediaSourceProvidersInfo.Where(x => x.Provider == mediaSessionId).FirstOrDefault()?.AlbumArtSearchProvidersInfo ?? [])
|
||||||
{
|
{
|
||||||
continue;
|
if (!provider.IsEnabled)
|
||||||
}
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
switch (provider.Provider)
|
switch (provider.Provider)
|
||||||
{
|
{
|
||||||
case AlbumArtSearchProvider.Local:
|
case AlbumArtSearchProvider.Local:
|
||||||
result = SearchFile(artist, title);
|
result = SearchFile(artist, title);
|
||||||
break;
|
break;
|
||||||
case AlbumArtSearchProvider.SMTC:
|
case AlbumArtSearchProvider.SMTC:
|
||||||
result = bytesFromSMTC;
|
result = bytesFromSMTC;
|
||||||
break;
|
break;
|
||||||
case AlbumArtSearchProvider.iTunes:
|
case AlbumArtSearchProvider.iTunes:
|
||||||
foreach (string countryCode in new List<string>() { "us", "cn", "jp", "kr" })
|
foreach (string countryCode in new List<string>() { "us", "cn", "jp", "kr" })
|
||||||
{
|
{
|
||||||
result = await SearchiTunesAsync(artist, album, title, countryCode);
|
result = await SearchiTunesAsync(artist, album, title, countryCode);
|
||||||
if (result != null) break;
|
if (result != null) break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result != null) return result;
|
if (result != null) return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,15 +83,18 @@ namespace BetterLyrics.WinUI3.Services.AlbumArtSearchService
|
|||||||
{
|
{
|
||||||
if (Directory.Exists(folder.Path) && folder.IsEnabled)
|
if (Directory.Exists(folder.Path) && folder.IsEnabled)
|
||||||
{
|
{
|
||||||
foreach (var file in Directory.GetFiles(folder.Path, $"*.*", SearchOption.AllDirectories))
|
foreach (var file in DirectoryHelper.GetAllFiles(folder.Path))
|
||||||
{
|
{
|
||||||
if (FileHelper.IsSwitchableNormalizedMatch(Path.GetFileNameWithoutExtension(file), title, artist))
|
if (FileHelper.MusicExtensions.Contains(Path.GetExtension(file)))
|
||||||
{
|
{
|
||||||
Track track = new(file);
|
Track track = new(file);
|
||||||
var bytes = track.EmbeddedPictures.FirstOrDefault()?.PictureData;
|
if ((track.Title == title && track.Artist == artist) || FileHelper.IsSwitchableNormalizedMatch(Path.GetFileNameWithoutExtension(file), artist, title))
|
||||||
if (bytes != null)
|
|
||||||
{
|
{
|
||||||
return bytes;
|
var bytes = track.EmbeddedPictures.FirstOrDefault()?.PictureData;
|
||||||
|
if (bytes != null)
|
||||||
|
{
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ namespace BetterLyrics.WinUI3.Services.LibWatcherService
|
|||||||
// 移除不再监听的
|
// 移除不再监听的
|
||||||
foreach (var key in _watchers.Keys.ToList())
|
foreach (var key in _watchers.Keys.ToList())
|
||||||
{
|
{
|
||||||
if (!folders.Any(x => x.Path == key && x.IsEnabled))
|
if (!folders.Any(x => x.Path == key && x.IsEnabled && x.IsRealTimeWatchEnabled))
|
||||||
{
|
{
|
||||||
_watchers[key].Dispose();
|
_watchers[key].Dispose();
|
||||||
_watchers.Remove(key);
|
_watchers.Remove(key);
|
||||||
@@ -62,11 +62,7 @@ namespace BetterLyrics.WinUI3.Services.LibWatcherService
|
|||||||
// 添加新的监听
|
// 添加新的监听
|
||||||
foreach (var folder in folders)
|
foreach (var folder in folders)
|
||||||
{
|
{
|
||||||
if (
|
if (!_watchers.ContainsKey(folder.Path) && Directory.Exists(folder.Path) && folder.IsEnabled && folder.IsRealTimeWatchEnabled)
|
||||||
!_watchers.ContainsKey(folder.Path)
|
|
||||||
&& Directory.Exists(folder.Path)
|
|
||||||
&& folder.IsEnabled
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var watcher = new FileSystemWatcher(folder.Path)
|
var watcher = new FileSystemWatcher(folder.Path)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
using BetterLyrics.WinUI3.Models;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace BetterLyrics.WinUI3.Services.LiveStatesService
|
||||||
|
{
|
||||||
|
public interface ILiveStatesService
|
||||||
|
{
|
||||||
|
LiveStates LiveStates { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,110 @@
|
|||||||
|
using BetterLyrics.WinUI3.Enums;
|
||||||
|
using BetterLyrics.WinUI3.Models;
|
||||||
|
using BetterLyrics.WinUI3.Models.Settings;
|
||||||
|
using BetterLyrics.WinUI3.Services.SettingsService;
|
||||||
|
using BetterLyrics.WinUI3.ViewModels;
|
||||||
|
using CommunityToolkit.Mvvm.Messaging;
|
||||||
|
using CommunityToolkit.Mvvm.Messaging.Messages;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace BetterLyrics.WinUI3.Services.LiveStatesService
|
||||||
|
{
|
||||||
|
public class LiveStatesService : BaseViewModel, ILiveStatesService,
|
||||||
|
IRecipient<PropertyChangedMessage<LyricsWindowMode>>,
|
||||||
|
IRecipient<PropertyChangedMessage<LyricsDisplayType>>
|
||||||
|
{
|
||||||
|
private readonly ISettingsService _settingsService;
|
||||||
|
|
||||||
|
public LiveStates LiveStates { get; set; }
|
||||||
|
|
||||||
|
public LiveStatesService(ISettingsService settingsService)
|
||||||
|
{
|
||||||
|
_settingsService = settingsService;
|
||||||
|
|
||||||
|
LiveStates = new LiveStates(_settingsService.AppSettings);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Receive(PropertyChangedMessage<LyricsWindowMode> message)
|
||||||
|
{
|
||||||
|
if (message.Sender is LiveStates)
|
||||||
|
{
|
||||||
|
if (message.PropertyName == nameof(LiveStates.CurrentLyricsWindowMode))
|
||||||
|
{
|
||||||
|
switch (message.NewValue)
|
||||||
|
{
|
||||||
|
case LyricsWindowMode.StandardMode:
|
||||||
|
LiveStates.CurrentLyricsStyleSettings = _settingsService.AppSettings.StandardLyricsStyleSettings;
|
||||||
|
LiveStates.CurrentLyricsEffectSettings = _settingsService.AppSettings.StandardLyricsEffectSettings;
|
||||||
|
LiveStates.CurrentLyricsDisplayType = _settingsService.AppSettings.StandardModeSettings.LyricsDisplayType;
|
||||||
|
break;
|
||||||
|
case LyricsWindowMode.DockMode:
|
||||||
|
LiveStates.CurrentLyricsStyleSettings = _settingsService.AppSettings.DockLyricsStyleSettings;
|
||||||
|
LiveStates.CurrentLyricsEffectSettings = _settingsService.AppSettings.DockLyricsEffectSettings;
|
||||||
|
LiveStates.CurrentLyricsDisplayType = _settingsService.AppSettings.DockModeSettings.LyricsDisplayType;
|
||||||
|
break;
|
||||||
|
case LyricsWindowMode.DesktopMode:
|
||||||
|
LiveStates.CurrentLyricsStyleSettings = _settingsService.AppSettings.DesktopLyricsStyleSettings;
|
||||||
|
LiveStates.CurrentLyricsEffectSettings = _settingsService.AppSettings.DesktopLyricsEffectSettings;
|
||||||
|
LiveStates.CurrentLyricsDisplayType = _settingsService.AppSettings.DesktopModeSettings.LyricsDisplayType;
|
||||||
|
break;
|
||||||
|
case LyricsWindowMode.PictureInPictureMode:
|
||||||
|
LiveStates.CurrentLyricsStyleSettings = _settingsService.AppSettings.PictureInPictureLyricsStyleSettings;
|
||||||
|
LiveStates.CurrentLyricsEffectSettings = _settingsService.AppSettings.PictureInPictureLyricsEffectSettings;
|
||||||
|
LiveStates.CurrentLyricsDisplayType = _settingsService.AppSettings.PictureInPictureModeSettings.LyricsDisplayType;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Receive(PropertyChangedMessage<LyricsDisplayType> message)
|
||||||
|
{
|
||||||
|
if (message.Sender is StandardModeSettings)
|
||||||
|
{
|
||||||
|
if (message.PropertyName == nameof(StandardModeSettings.LyricsDisplayType))
|
||||||
|
{
|
||||||
|
if (LiveStates.CurrentLyricsWindowMode == LyricsWindowMode.StandardMode)
|
||||||
|
{
|
||||||
|
LiveStates.CurrentLyricsDisplayType = message.NewValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (message.Sender is DockModeSettings)
|
||||||
|
{
|
||||||
|
if (message.PropertyName == nameof(DockModeSettings.LyricsDisplayType))
|
||||||
|
{
|
||||||
|
if (LiveStates.CurrentLyricsWindowMode == LyricsWindowMode.DockMode)
|
||||||
|
{
|
||||||
|
LiveStates.CurrentLyricsDisplayType = message.NewValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (message.Sender is DesktopModeSettings)
|
||||||
|
{
|
||||||
|
if (message.PropertyName == nameof(DesktopModeSettings.LyricsDisplayType))
|
||||||
|
{
|
||||||
|
if (LiveStates.CurrentLyricsWindowMode == LyricsWindowMode.DesktopMode)
|
||||||
|
{
|
||||||
|
LiveStates.CurrentLyricsDisplayType = message.NewValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (message.Sender is PictureInPictureModeSettings)
|
||||||
|
{
|
||||||
|
if (message.PropertyName == nameof(PictureInPictureModeSettings.LyricsDisplayType))
|
||||||
|
{
|
||||||
|
if (LiveStates.CurrentLyricsWindowMode == LyricsWindowMode.PictureInPictureMode)
|
||||||
|
{
|
||||||
|
LiveStates.CurrentLyricsDisplayType = message.NewValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@
|
|||||||
using ATL;
|
using ATL;
|
||||||
using BetterLyrics.WinUI3.Enums;
|
using BetterLyrics.WinUI3.Enums;
|
||||||
using BetterLyrics.WinUI3.Helper;
|
using BetterLyrics.WinUI3.Helper;
|
||||||
|
using BetterLyrics.WinUI3.Helper.BetterLyrics.WinUI3.Helper;
|
||||||
using BetterLyrics.WinUI3.Services.SettingsService;
|
using BetterLyrics.WinUI3.Services.SettingsService;
|
||||||
using CommunityToolkit.Mvvm.DependencyInjection;
|
using CommunityToolkit.Mvvm.DependencyInjection;
|
||||||
using Lyricify.Lyrics.Providers.Web.Kugou;
|
using Lyricify.Lyrics.Providers.Web.Kugou;
|
||||||
@@ -87,6 +88,11 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async Task<(string?, LyricsSearchProvider?)> SearchAsync(string mediaSessionId, string title, string artist, string album, double durationMs, CancellationToken token)
|
public async Task<(string?, LyricsSearchProvider?)> SearchAsync(string mediaSessionId, string title, string artist, string album, double durationMs, CancellationToken token)
|
||||||
|
{
|
||||||
|
return await Task.Run(async () => await SearchAsyncCore(mediaSessionId, title, artist, album, durationMs, token), token);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<(string?, LyricsSearchProvider?)> SearchAsyncCore(string mediaSessionId, string title, string artist, string album, double durationMs, CancellationToken token)
|
||||||
{
|
{
|
||||||
_logger.LogInformation("Searching img for: {Title} - {Artist} (Album: {Album}, Duration: {DurationMs}ms)", title, artist, album, durationMs);
|
_logger.LogInformation("Searching img for: {Title} - {Artist} (Album: {Album}, Duration: {DurationMs}ms)", title, artist, album, durationMs);
|
||||||
|
|
||||||
@@ -173,17 +179,23 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
|
|||||||
{
|
{
|
||||||
if (Directory.Exists(folder.Path) && folder.IsEnabled)
|
if (Directory.Exists(folder.Path) && folder.IsEnabled)
|
||||||
{
|
{
|
||||||
foreach (var file in Directory.GetFiles(folder.Path, $"*{format.ToFileExtension()}", SearchOption.AllDirectories))
|
try
|
||||||
{
|
{
|
||||||
if (FileHelper.IsSwitchableNormalizedMatch(Path.GetFileNameWithoutExtension(file), title, artist))
|
foreach (var file in DirectoryHelper.GetAllFiles(folder.Path, $"*{format.ToFileExtension()}"))
|
||||||
{
|
{
|
||||||
string? raw = await File.ReadAllTextAsync(file, FileHelper.GetEncoding(file));
|
if (FileHelper.IsSwitchableNormalizedMatch(Path.GetFileNameWithoutExtension(file), title, artist))
|
||||||
if (raw != null)
|
|
||||||
{
|
{
|
||||||
return raw;
|
string? raw = await File.ReadAllTextAsync(file, FileHelper.GetEncoding(file));
|
||||||
|
if (raw != null)
|
||||||
|
{
|
||||||
|
return raw;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@@ -195,24 +207,23 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
|
|||||||
{
|
{
|
||||||
if (Directory.Exists(folder.Path) && folder.IsEnabled)
|
if (Directory.Exists(folder.Path) && folder.IsEnabled)
|
||||||
{
|
{
|
||||||
foreach (var file in Directory.GetFiles(folder.Path, $"*.*", SearchOption.AllDirectories))
|
foreach (var file in DirectoryHelper.GetAllFiles(folder.Path))
|
||||||
{
|
{
|
||||||
if (FileHelper.IsSwitchableNormalizedMatch(Path.GetFileNameWithoutExtension(file), title, artist))
|
if (FileHelper.MusicExtensions.Contains(Path.GetExtension(file)))
|
||||||
{
|
{
|
||||||
try
|
var track = new Track(file);
|
||||||
|
if ((track.Title == title && track.Artist == artist) || FileHelper.IsSwitchableNormalizedMatch(Path.GetFileNameWithoutExtension(file), title, artist))
|
||||||
{
|
{
|
||||||
var plain = TagLib.File.Create(file).Tag.Lyrics;
|
var plain = TagLib.File.Create(file).Tag.Lyrics;
|
||||||
if (plain != null && plain != string.Empty)
|
if (!plain.IsNullOrEmpty())
|
||||||
{
|
{
|
||||||
return plain;
|
return plain;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception) { }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
// 2025/6/23 by Zhe Fang
|
// 2025/6/23 by Zhe Fang
|
||||||
|
|
||||||
using System;
|
using BetterLyrics.WinUI3.Enums;
|
||||||
using System.Threading.Tasks;
|
|
||||||
using BetterLyrics.WinUI3.Events;
|
using BetterLyrics.WinUI3.Events;
|
||||||
using BetterLyrics.WinUI3.Models;
|
using BetterLyrics.WinUI3.Models;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using TagLib.Riff;
|
||||||
|
|
||||||
namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||||
{
|
{
|
||||||
@@ -12,7 +15,8 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
|||||||
event EventHandler<IsPlayingChangedEventArgs>? IsPlayingChanged;
|
event EventHandler<IsPlayingChangedEventArgs>? IsPlayingChanged;
|
||||||
event EventHandler<TimelineChangedEventArgs>? TimelineChanged;
|
event EventHandler<TimelineChangedEventArgs>? TimelineChanged;
|
||||||
event EventHandler<SongInfoChangedEventArgs>? SongInfoChanged;
|
event EventHandler<SongInfoChangedEventArgs>? SongInfoChanged;
|
||||||
event EventHandler<AlbumArtChangedEventArgs>? AlbumArtChangedChanged;
|
event EventHandler<AlbumArtChangedEventArgs>? AlbumArtChanged;
|
||||||
|
event EventHandler<LyricsChangedEventArgs>? LyricsChanged;
|
||||||
event EventHandler<MediaSourceProvidersInfoEventArgs>? MediaSourceProvidersInfoChanged;
|
event EventHandler<MediaSourceProvidersInfoEventArgs>? MediaSourceProvidersInfoChanged;
|
||||||
|
|
||||||
Task PlayAsync();
|
Task PlayAsync();
|
||||||
@@ -26,5 +30,8 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
|||||||
bool IsPlaying { get; }
|
bool IsPlaying { get; }
|
||||||
SongInfo? SongInfo { get; }
|
SongInfo? SongInfo { get; }
|
||||||
TimeSpan Position { get; }
|
TimeSpan Position { get; }
|
||||||
|
|
||||||
|
LyricsSearchProvider? LyricsSearchProvider { get; }
|
||||||
|
TranslationSearchProvider? TranslationSearchProvider { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,69 @@
|
|||||||
|
using BetterLyrics.WinUI3.Events;
|
||||||
|
using BetterLyrics.WinUI3.Helper;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Microsoft.UI.Dispatching;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Runtime.InteropServices.WindowsRuntime;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Windows.Graphics.Imaging;
|
||||||
|
using Windows.Storage.Streams;
|
||||||
|
|
||||||
|
namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||||
|
{
|
||||||
|
public partial class MediaSessionsService : IMediaSessionsService
|
||||||
|
{
|
||||||
|
private readonly LatestOnlyTaskRunner _albumArtRefreshRunner = new();
|
||||||
|
|
||||||
|
public event EventHandler<AlbumArtChangedEventArgs>? AlbumArtChanged;
|
||||||
|
|
||||||
|
private void UpdateAlbumArt()
|
||||||
|
{
|
||||||
|
_albumArtRefreshRunner.RunAsync(RefreshArtAlbum);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task RefreshArtAlbum(CancellationToken token)
|
||||||
|
{
|
||||||
|
if (_cachedSongInfo == null)
|
||||||
|
{
|
||||||
|
_logger.LogWarning("Cached song info is null, cannot update album art.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[]? bytes = await _albumArtSearchService.SearchAsync(
|
||||||
|
SongInfo?.SourceAppUserModelId ?? "",
|
||||||
|
_cachedSongInfo.Title,
|
||||||
|
_cachedSongInfo.Artist,
|
||||||
|
_cachedSongInfo?.Album ?? string.Empty,
|
||||||
|
_SMTCAlbumArtBytes
|
||||||
|
);
|
||||||
|
token.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
|
if (bytes == null)
|
||||||
|
{
|
||||||
|
bytes = await ImageHelper.CreateTextPlaceholderBytesAsync(500, 500);
|
||||||
|
token.ThrowIfCancellationRequested();
|
||||||
|
}
|
||||||
|
|
||||||
|
bytes = ImageHelper.MakeSquareWithThemeColor(bytes);
|
||||||
|
|
||||||
|
using var stream = new InMemoryRandomAccessStream();
|
||||||
|
await stream.WriteAsync(bytes.AsBuffer());
|
||||||
|
token.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
|
var decoder = await BitmapDecoder.CreateAsync(stream);
|
||||||
|
token.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
|
var albumArtSwBitmap = await decoder.GetSoftwareBitmapAsync(BitmapPixelFormat.Rgba16, BitmapAlphaMode.Premultiplied);
|
||||||
|
token.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
|
var albumArtLightAccentColor = ImageHelper.GetAccentColorsFromByte(bytes, 1, false).FirstOrDefault();
|
||||||
|
var albumArtDarkAccentColor = ImageHelper.GetAccentColorsFromByte(bytes, 1, true).FirstOrDefault();
|
||||||
|
|
||||||
|
AlbumArtChanged?.Invoke(this, new AlbumArtChangedEventArgs(null, albumArtSwBitmap, albumArtLightAccentColor, albumArtDarkAccentColor));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,227 @@
|
|||||||
|
using BetterLyrics.WinUI3.Enums;
|
||||||
|
using BetterLyrics.WinUI3.Events;
|
||||||
|
using BetterLyrics.WinUI3.Helper;
|
||||||
|
using BetterLyrics.WinUI3.Models;
|
||||||
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Vanara.PInvoke;
|
||||||
|
|
||||||
|
namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||||
|
{
|
||||||
|
public partial class MediaSessionsService : IMediaSessionsService
|
||||||
|
{
|
||||||
|
private LatestOnlyTaskRunner _refreshLyricsRunner = new();
|
||||||
|
private LatestOnlyTaskRunner _showTranslationsRunner = new();
|
||||||
|
|
||||||
|
private int _langIndex = 0;
|
||||||
|
private List<LyricsData> _lyricsDataArr = [];
|
||||||
|
|
||||||
|
private LyricsData? CurrentLyricsData => _lyricsDataArr.ElementAtOrDefault(_langIndex);
|
||||||
|
|
||||||
|
public event EventHandler<LyricsChangedEventArgs>? LyricsChanged;
|
||||||
|
|
||||||
|
[ObservableProperty][NotifyPropertyChangedRecipients] public partial LyricsSearchProvider? LyricsSearchProvider { get; set; }
|
||||||
|
|
||||||
|
[ObservableProperty][NotifyPropertyChangedRecipients] public partial TranslationSearchProvider? TranslationSearchProvider { get; set; }
|
||||||
|
|
||||||
|
[ObservableProperty] public partial bool IsTranslating { get; set; } = false;
|
||||||
|
|
||||||
|
private void UpdateTranslations()
|
||||||
|
{
|
||||||
|
TranslationSearchProvider = null;
|
||||||
|
_lyricsDataArr.ElementAtOrDefault(0)?.SetDisplayedTextInOriginalText();
|
||||||
|
LyricsChanged?.Invoke(this, new LyricsChangedEventArgs(CurrentLyricsData));
|
||||||
|
IsTranslating = true;
|
||||||
|
|
||||||
|
if (_settingsService.AppSettings.TranslationSettings.IsTranslationEnabled)
|
||||||
|
{
|
||||||
|
_showTranslationsRunner.RunAsync(async token =>
|
||||||
|
{
|
||||||
|
await SetDisplayedAlongWithTranslationsAsync(token);
|
||||||
|
IsTranslating = false;
|
||||||
|
LyricsChanged?.Invoke(this, new LyricsChangedEventArgs(CurrentLyricsData));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_lyricsDataArr.ElementAtOrDefault(0)?.SetDisplayedTextInOriginalText();
|
||||||
|
_langIndex = 0;
|
||||||
|
IsTranslating = false;
|
||||||
|
LyricsChanged?.Invoke(this, new LyricsChangedEventArgs(CurrentLyricsData));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task SetDisplayedAlongWithTranslationsAsync(CancellationToken token)
|
||||||
|
{
|
||||||
|
_logger.LogInformation("Showing translation for lyrics...");
|
||||||
|
string targetLangCode = LanguageHelper.SupportedTargetLanguages[_settingsService.AppSettings.TranslationSettings.SelectedTargetLanguageIndex].Code;
|
||||||
|
_logger.LogInformation("Target language code: {TargetLangCode}", targetLangCode);
|
||||||
|
string? originalText = _lyricsDataArr.FirstOrDefault()?.WrappedOriginalText;
|
||||||
|
if (originalText == null) return;
|
||||||
|
|
||||||
|
string? originalLangCode = LanguageHelper.DetectLanguageCode(originalText);
|
||||||
|
_logger.LogInformation("Original language code: {OriginalLangCode}", originalLangCode ?? "null");
|
||||||
|
|
||||||
|
if (originalLangCode == targetLangCode)
|
||||||
|
{
|
||||||
|
_logger.LogInformation("Original lyrics already in target language: {TargetLangCode}", targetLangCode);
|
||||||
|
|
||||||
|
_lyricsDataArr[0].SetDisplayedTextInOriginalText();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Try get translation from itself first
|
||||||
|
int found = _translateService.SearchTranslatedLyricsItself(_lyricsDataArr);
|
||||||
|
if (found >= 0)
|
||||||
|
{
|
||||||
|
_logger.LogInformation("Found translation in lyrics data at index {FoundIndex}", found);
|
||||||
|
if (_settingsService.AppSettings.TranslationSettings.ShowTranslationOnly)
|
||||||
|
{
|
||||||
|
_lyricsDataArr[found].SetDisplayedTextInOriginalText();
|
||||||
|
_langIndex = found;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_lyricsDataArr[0].SetDisplayedTextAlongWith(_lyricsDataArr[found], _liveStatesService.LiveStates.CurrentLyricsStyleSettings.LyricsTranslationSeparator, 50);
|
||||||
|
_langIndex = 0;
|
||||||
|
TranslationSearchProvider = LyricsSearchProvider.ToTranslationSearchProvider();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (_settingsService.AppSettings.TranslationSettings.IsLibreTranslateEnabled)
|
||||||
|
{
|
||||||
|
_logger.LogInformation("LibreTranslate is enabled, trying to translate lyrics...");
|
||||||
|
string translated = string.Empty;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
translated = await _translateService.TranslateTextAsync(originalText, targetLangCode, token);
|
||||||
|
if (token.IsCancellationRequested) return;
|
||||||
|
if (translated == string.Empty) return;
|
||||||
|
|
||||||
|
if (_settingsService.AppSettings.TranslationSettings.ShowTranslationOnly)
|
||||||
|
{
|
||||||
|
_lyricsDataArr[^1] = _lyricsDataArr[0].CreateLyricsDataFrom(translated);
|
||||||
|
_lyricsDataArr[^1].SetDisplayedTextInOriginalText();
|
||||||
|
_langIndex = _lyricsDataArr.Count - 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_lyricsDataArr[0].SetDisplayedTextAlongWith(translated, _liveStatesService.LiveStates.CurrentLyricsStyleSettings.LyricsTranslationSeparator);
|
||||||
|
_langIndex = 0;
|
||||||
|
}
|
||||||
|
TranslationSearchProvider = Enums.TranslationSearchProvider.LibreTranslate;
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
App.Current.LyricsWindowNotificationPanel?.Notify(App.ResourceLoader?.GetString("LibreTranslateFailed")!, Microsoft.UI.Xaml.Controls.InfoBarSeverity.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task RefreshLyricsAsync(CancellationToken token)
|
||||||
|
{
|
||||||
|
_logger.LogInformation("Refreshing lyrics...");
|
||||||
|
|
||||||
|
LyricsSearchProvider = null;
|
||||||
|
_lyricsDataArr = [LyricsData.GetLoadingPlaceholder()];
|
||||||
|
|
||||||
|
LyricsChanged?.Invoke(this, new LyricsChangedEventArgs(CurrentLyricsData));
|
||||||
|
|
||||||
|
string? lyricsRaw = null;
|
||||||
|
LyricsSearchProvider? lyricsSearchProvider = null;
|
||||||
|
LyricsSearchProvider = lyricsSearchProvider;
|
||||||
|
|
||||||
|
if (SongInfo != null)
|
||||||
|
{
|
||||||
|
_logger.LogInformation("Searching lyrics for: Title={Title}, Artist={Artist}, Album={Album}, DurationMs={DurationMs}",
|
||||||
|
SongInfo.Title, SongInfo.Artist, SongInfo.Album, SongInfo.DurationMs);
|
||||||
|
(lyricsRaw, lyricsSearchProvider) = await _lyrcsSearchService.SearchAsync(
|
||||||
|
SongInfo.SourceAppUserModelId ?? "",
|
||||||
|
SongInfo.Title,
|
||||||
|
SongInfo.Artist,
|
||||||
|
SongInfo.Album ?? "",
|
||||||
|
SongInfo.DurationMs ?? 0,
|
||||||
|
token
|
||||||
|
);
|
||||||
|
LyricsSearchProvider = lyricsSearchProvider;
|
||||||
|
_logger.LogInformation("Lyrics was found? {Found}, Provider: {LyricsSearchProvider}", lyricsRaw != null, LyricsSearchProvider?.ToString() ?? "null");
|
||||||
|
token.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
|
_lyricsDataArr = new LyricsParser().Parse(lyricsRaw, (int?)SongInfo?.DurationMs);
|
||||||
|
FillTranslationFromCache(LyricsSearchProvider);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_logger.LogWarning("SongInfo is null, cannot search lyrics.");
|
||||||
|
}
|
||||||
|
|
||||||
|
_logger.LogInformation("Parsed lyrics: {MultiLangLyricsCount} languages", _lyricsDataArr.Count);
|
||||||
|
|
||||||
|
// This ensures that original lyrics are always shown while waiting for translations
|
||||||
|
_lyricsDataArr[0].SetDisplayedTextInOriginalText();
|
||||||
|
LyricsChanged?.Invoke(this, new LyricsChangedEventArgs(CurrentLyricsData));
|
||||||
|
|
||||||
|
UpdateTranslations();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void FillTranslationFromCache(LyricsSearchProvider? provider)
|
||||||
|
{
|
||||||
|
string? translationRaw = null;
|
||||||
|
switch (provider)
|
||||||
|
{
|
||||||
|
case Enums.LyricsSearchProvider.QQ:
|
||||||
|
translationRaw = Helper.FileHelper.ReadLyricsCache(SongInfo!.Title, SongInfo.Artist, LyricsFormat.Lrc, Helper.PathHelper.QQTranslationCacheDirectory);
|
||||||
|
break;
|
||||||
|
case Enums.LyricsSearchProvider.Kugou:
|
||||||
|
break;
|
||||||
|
case Enums.LyricsSearchProvider.Netease:
|
||||||
|
translationRaw = Helper.FileHelper.ReadLyricsCache(SongInfo!.Title, SongInfo.Artist, LyricsFormat.Lrc, Helper.PathHelper.NeteaseTranslationCacheDirectory);
|
||||||
|
break;
|
||||||
|
case Enums.LyricsSearchProvider.LrcLib:
|
||||||
|
break;
|
||||||
|
case Enums.LyricsSearchProvider.AmllTtmlDb:
|
||||||
|
break;
|
||||||
|
case Enums.LyricsSearchProvider.LocalMusicFile:
|
||||||
|
break;
|
||||||
|
case Enums.LyricsSearchProvider.LocalLrcFile:
|
||||||
|
break;
|
||||||
|
case Enums.LyricsSearchProvider.LocalEslrcFile:
|
||||||
|
break;
|
||||||
|
case Enums.LyricsSearchProvider.LocalTtmlFile:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (translationRaw != null)
|
||||||
|
{
|
||||||
|
var translationData = new LyricsParser().Parse(translationRaw, (int?)SongInfo?.DurationMs);
|
||||||
|
if (provider == Enums.LyricsSearchProvider.QQ)
|
||||||
|
{
|
||||||
|
foreach (var data in translationData)
|
||||||
|
{
|
||||||
|
foreach (var item in data.LyricsLines)
|
||||||
|
{
|
||||||
|
if (item.OriginalText == "//")
|
||||||
|
{
|
||||||
|
item.OriginalText = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_lyricsDataArr = _lyricsDataArr.Concat(translationData).ToList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateLyrics()
|
||||||
|
{
|
||||||
|
_refreshLyricsRunner.RunAsync(RefreshLyricsAsync);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,8 +8,13 @@ using BetterLyrics.WinUI3.Models;
|
|||||||
using BetterLyrics.WinUI3.Models.Settings;
|
using BetterLyrics.WinUI3.Models.Settings;
|
||||||
using BetterLyrics.WinUI3.Services.AlbumArtSearchService;
|
using BetterLyrics.WinUI3.Services.AlbumArtSearchService;
|
||||||
using BetterLyrics.WinUI3.Services.LastFMService;
|
using BetterLyrics.WinUI3.Services.LastFMService;
|
||||||
|
using BetterLyrics.WinUI3.Services.LibWatcherService;
|
||||||
|
using BetterLyrics.WinUI3.Services.LiveStatesService;
|
||||||
|
using BetterLyrics.WinUI3.Services.LyricsSearchService;
|
||||||
using BetterLyrics.WinUI3.Services.SettingsService;
|
using BetterLyrics.WinUI3.Services.SettingsService;
|
||||||
|
using BetterLyrics.WinUI3.Services.TranslateService;
|
||||||
using BetterLyrics.WinUI3.ViewModels;
|
using BetterLyrics.WinUI3.ViewModels;
|
||||||
|
using BetterLyrics.WinUI3.Views;
|
||||||
using CommunityToolkit.Mvvm.DependencyInjection;
|
using CommunityToolkit.Mvvm.DependencyInjection;
|
||||||
using CommunityToolkit.Mvvm.Messaging;
|
using CommunityToolkit.Mvvm.Messaging;
|
||||||
using CommunityToolkit.Mvvm.Messaging.Messages;
|
using CommunityToolkit.Mvvm.Messaging.Messages;
|
||||||
@@ -35,12 +40,18 @@ using WindowsMediaController;
|
|||||||
namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||||
{
|
{
|
||||||
public partial class MediaSessionsService : BaseViewModel, IMediaSessionsService,
|
public partial class MediaSessionsService : BaseViewModel, IMediaSessionsService,
|
||||||
|
IRecipient<PropertyChangedMessage<int>>,
|
||||||
IRecipient<PropertyChangedMessage<bool>>,
|
IRecipient<PropertyChangedMessage<bool>>,
|
||||||
IRecipient<PropertyChangedMessage<FullyObservableCollection<AlbumArtSearchProviderInfo>>>
|
IRecipient<PropertyChangedMessage<string>>,
|
||||||
|
IRecipient<PropertyChangedMessage<List<string>>>
|
||||||
{
|
{
|
||||||
private readonly IAlbumArtSearchService _albumArtSearchService;
|
private readonly IAlbumArtSearchService _albumArtSearchService;
|
||||||
private readonly ILogger<MediaSessionsService> _logger;
|
private readonly ILyricsSearchService _lyrcsSearchService;
|
||||||
|
private readonly ITranslateService _translateService;
|
||||||
private readonly ISettingsService _settingsService;
|
private readonly ISettingsService _settingsService;
|
||||||
|
private readonly ILibWatcherService _libWatcherService;
|
||||||
|
private readonly ILiveStatesService _liveStatesService;
|
||||||
|
private readonly ILogger<MediaSessionsService> _logger;
|
||||||
|
|
||||||
private double _lxMusicPositionSeconds = 0;
|
private double _lxMusicPositionSeconds = 0;
|
||||||
private double _lxMusicDurationSeconds = 0;
|
private double _lxMusicDurationSeconds = 0;
|
||||||
@@ -52,28 +63,92 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
|||||||
|
|
||||||
private readonly MediaManager _mediaManager = new();
|
private readonly MediaManager _mediaManager = new();
|
||||||
|
|
||||||
private readonly LatestOnlyTaskRunner _albumArtRefreshRunner = new();
|
|
||||||
private readonly LatestOnlyTaskRunner _onAnyMediaPropertyChangedRunner = new();
|
|
||||||
|
|
||||||
private SongInfo? _cachedSongInfo;
|
private SongInfo? _cachedSongInfo;
|
||||||
private byte[]? _SMTCAlbumArtBytes = null;
|
private byte[]? _SMTCAlbumArtBytes = null;
|
||||||
private int _targetAlbumArtSize = 500;
|
|
||||||
|
|
||||||
public event EventHandler<IsPlayingChangedEventArgs>? IsPlayingChanged;
|
public event EventHandler<IsPlayingChangedEventArgs>? IsPlayingChanged;
|
||||||
public event EventHandler<TimelineChangedEventArgs>? TimelineChanged;
|
public event EventHandler<TimelineChangedEventArgs>? TimelineChanged;
|
||||||
public event EventHandler<SongInfoChangedEventArgs>? SongInfoChanged;
|
public event EventHandler<SongInfoChangedEventArgs>? SongInfoChanged;
|
||||||
public event EventHandler<AlbumArtChangedEventArgs>? AlbumArtChangedChanged;
|
|
||||||
public event EventHandler<MediaSourceProvidersInfoEventArgs>? MediaSourceProvidersInfoChanged;
|
public event EventHandler<MediaSourceProvidersInfoEventArgs>? MediaSourceProvidersInfoChanged;
|
||||||
|
|
||||||
public MediaSessionsService(ISettingsService settingsService, IAlbumArtSearchService albumArtSearchService)
|
public bool IsPlaying => _cachedIsPlaying;
|
||||||
|
public SongInfo? SongInfo => _cachedSongInfo;
|
||||||
|
public TimeSpan Position => _cachedPosition;
|
||||||
|
|
||||||
|
public MediaSessionsService(
|
||||||
|
ISettingsService settingsService,
|
||||||
|
IAlbumArtSearchService albumArtSearchService,
|
||||||
|
ILyricsSearchService musicSearchService,
|
||||||
|
ILibWatcherService libWatcherService,
|
||||||
|
ILiveStatesService liveStatesService,
|
||||||
|
ITranslateService libreTranslateService)
|
||||||
{
|
{
|
||||||
_settingsService = settingsService;
|
_settingsService = settingsService;
|
||||||
_albumArtSearchService = albumArtSearchService;
|
_albumArtSearchService = albumArtSearchService;
|
||||||
|
_lyrcsSearchService = musicSearchService;
|
||||||
|
_libWatcherService = libWatcherService;
|
||||||
|
_translateService = libreTranslateService;
|
||||||
|
_liveStatesService = liveStatesService;
|
||||||
_logger = Ioc.Default.GetRequiredService<ILogger<MediaSessionsService>>();
|
_logger = Ioc.Default.GetRequiredService<ILogger<MediaSessionsService>>();
|
||||||
|
|
||||||
_settingsService.AppSettings.MediaSourceProvidersInfo.ItemPropertyChanged += MediaSourceProvidersInfo_ItemPropertyChanged;
|
_settingsService.AppSettings.MediaSourceProvidersInfo.ItemPropertyChanged += MediaSourceProvidersInfo_ItemPropertyChanged;
|
||||||
|
_settingsService.AppSettings.LocalMediaFolders.CollectionChanged += LocalMediaFolders_CollectionChanged;
|
||||||
|
_settingsService.AppSettings.LocalMediaFolders.ItemPropertyChanged += LocalMediaFolders_ItemPropertyChanged;
|
||||||
|
|
||||||
|
_libWatcherService.MusicLibraryFilesChanged += LibWatcherService_MusicLibraryFilesChanged;
|
||||||
|
|
||||||
InitMediaManager();
|
InitMediaManager();
|
||||||
|
InitPlaybackShortcuts();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InitPlaybackShortcuts()
|
||||||
|
{
|
||||||
|
UpdatePlayOrPauseSongShortcut();
|
||||||
|
UpdatePreviousSongShortcut();
|
||||||
|
UpdateNextSongShortcut();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdatePlayOrPauseSongShortcut()
|
||||||
|
{
|
||||||
|
GlobalHotKeyHelper.UpdateHotKey<LyricsWindow>(ShortcutID.PlayOrPauseSong, _settingsService.AppSettings.GeneralSettings.PlayOrPauseShortcut, () =>
|
||||||
|
{
|
||||||
|
if (_cachedIsPlaying)
|
||||||
|
{
|
||||||
|
_ = PauseAsync();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_ = PlayAsync();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdatePreviousSongShortcut()
|
||||||
|
{
|
||||||
|
GlobalHotKeyHelper.UpdateHotKey<LyricsWindow>(ShortcutID.PreviousSong, _settingsService.AppSettings.GeneralSettings.PreviousSongShortcut, () =>
|
||||||
|
{
|
||||||
|
_ = PreviousAsync();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateNextSongShortcut()
|
||||||
|
{
|
||||||
|
GlobalHotKeyHelper.UpdateHotKey<LyricsWindow>(ShortcutID.NextSong, _settingsService.AppSettings.GeneralSettings.NextSongShortcut, () =>
|
||||||
|
{
|
||||||
|
_ = NextAsync();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LocalMediaFolders_ItemPropertyChanged(object? sender, ItemPropertyChangedEventArgs e)
|
||||||
|
{
|
||||||
|
UpdateAlbumArt();
|
||||||
|
UpdateLyrics();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LocalMediaFolders_CollectionChanged(object? sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
|
||||||
|
{
|
||||||
|
UpdateAlbumArt();
|
||||||
|
UpdateLyrics();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void MediaSourceProvidersInfo_ItemPropertyChanged(object? sender, ItemPropertyChangedEventArgs e)
|
private void MediaSourceProvidersInfo_ItemPropertyChanged(object? sender, ItemPropertyChangedEventArgs e)
|
||||||
@@ -81,19 +156,21 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
|||||||
switch (e.PropertyName)
|
switch (e.PropertyName)
|
||||||
{
|
{
|
||||||
case nameof(MediaSourceProviderInfo.AlbumArtSearchProvidersInfo):
|
case nameof(MediaSourceProviderInfo.AlbumArtSearchProvidersInfo):
|
||||||
_ = _albumArtRefreshRunner.RunAsync(async tokne =>
|
UpdateAlbumArt();
|
||||||
{
|
break;
|
||||||
await UpdateAlbumArtRelated(tokne);
|
case nameof(MediaSourceProviderInfo.LyricsSearchProvidersInfo):
|
||||||
});
|
UpdateLyrics();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsPlaying => _cachedIsPlaying;
|
private void LibWatcherService_MusicLibraryFilesChanged(object? sender, LibChangedEventArgs e)
|
||||||
public SongInfo? SongInfo => _cachedSongInfo;
|
{
|
||||||
public TimeSpan Position => _cachedPosition;
|
UpdateAlbumArt();
|
||||||
|
UpdateLyrics();
|
||||||
|
}
|
||||||
|
|
||||||
private bool IsMediaSourceEnabled(string id)
|
private bool IsMediaSourceEnabled(string id)
|
||||||
{
|
{
|
||||||
@@ -110,18 +187,16 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
|||||||
_mediaManager.OnAnyTimelinePropertyChanged += MediaManager_OnAnyTimelinePropertyChanged;
|
_mediaManager.OnAnyTimelinePropertyChanged += MediaManager_OnAnyTimelinePropertyChanged;
|
||||||
|
|
||||||
_mediaManager.Start();
|
_mediaManager.Start();
|
||||||
Task.Run(() =>
|
|
||||||
{
|
MediaManager_OnFocusedSessionChanged(null);
|
||||||
MediaManager_OnFocusedSessionChanged(null);
|
_mediaManager.CurrentMediaSessions.ToList().ForEach(x => RecordMediaSourceProviderInfo(x.Value));
|
||||||
_mediaManager.CurrentMediaSessions.ToList().ForEach(x => RecordMediaSourceProviderInfo(x.Value));
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void MediaManager_OnFocusedSessionChanged(MediaManager.MediaSession? mediaSession)
|
private void MediaManager_OnFocusedSessionChanged(MediaManager.MediaSession? mediaSession)
|
||||||
{
|
{
|
||||||
if (!_mediaManager.IsStarted) return;
|
if (!_mediaManager.IsStarted) return;
|
||||||
|
|
||||||
SendFocusedMessagesAsync().ConfigureAwait(false);
|
SendFocusedMessagesAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void MediaManager_OnAnyTimelinePropertyChanged(MediaManager.MediaSession mediaSession, GlobalSystemMediaTransportControlsSessionTimelineProperties timelineProperties)
|
private void MediaManager_OnAnyTimelinePropertyChanged(MediaManager.MediaSession mediaSession, GlobalSystemMediaTransportControlsSessionTimelineProperties timelineProperties)
|
||||||
@@ -153,51 +228,51 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
|||||||
|
|
||||||
private void MediaManager_OnAnyPlaybackStateChanged(MediaManager.MediaSession mediaSession, GlobalSystemMediaTransportControlsSessionPlaybackInfo playbackInfo)
|
private void MediaManager_OnAnyPlaybackStateChanged(MediaManager.MediaSession mediaSession, GlobalSystemMediaTransportControlsSessionPlaybackInfo playbackInfo)
|
||||||
{
|
{
|
||||||
if (!_mediaManager.IsStarted) return;
|
|
||||||
if (mediaSession == null) return;
|
|
||||||
|
|
||||||
var focusedSession = _mediaManager.GetFocusedSession();
|
|
||||||
|
|
||||||
//RecordMediaSourceProviderInfo(mediaSession);
|
|
||||||
if (mediaSession != focusedSession) return;
|
|
||||||
|
|
||||||
if (!IsMediaSourceEnabled(mediaSession.Id))
|
|
||||||
{
|
|
||||||
_cachedIsPlaying = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_cachedIsPlaying = playbackInfo.PlaybackStatus switch
|
|
||||||
{
|
|
||||||
GlobalSystemMediaTransportControlsSessionPlaybackStatus.Playing => true,
|
|
||||||
_ => false,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
_dispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, () =>
|
_dispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, () =>
|
||||||
{
|
{
|
||||||
|
if (!_mediaManager.IsStarted) return;
|
||||||
|
if (mediaSession == null) return;
|
||||||
|
|
||||||
|
var focusedSession = _mediaManager.GetFocusedSession();
|
||||||
|
|
||||||
|
//RecordMediaSourceProviderInfo(mediaSession);
|
||||||
|
if (mediaSession != focusedSession) return;
|
||||||
|
|
||||||
|
if (!IsMediaSourceEnabled(mediaSession.Id))
|
||||||
|
{
|
||||||
|
_cachedIsPlaying = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_cachedIsPlaying = playbackInfo.PlaybackStatus switch
|
||||||
|
{
|
||||||
|
GlobalSystemMediaTransportControlsSessionPlaybackStatus.Playing => true,
|
||||||
|
_ => false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
IsPlayingChanged?.Invoke(this, new IsPlayingChangedEventArgs(_cachedIsPlaying));
|
IsPlayingChanged?.Invoke(this, new IsPlayingChangedEventArgs(_cachedIsPlaying));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void MediaManager_OnAnyMediaPropertyChanged(MediaManager.MediaSession mediaSession, GlobalSystemMediaTransportControlsSessionMediaProperties mediaProperties)
|
private void MediaManager_OnAnyMediaPropertyChanged(MediaManager.MediaSession mediaSession, GlobalSystemMediaTransportControlsSessionMediaProperties mediaProperties)
|
||||||
{
|
{
|
||||||
if (!_mediaManager.IsStarted) return;
|
_dispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, async () =>
|
||||||
if (mediaSession == null) return;
|
|
||||||
|
|
||||||
string id = mediaSession.Id;
|
|
||||||
|
|
||||||
var focusedSession = _mediaManager.GetFocusedSession();
|
|
||||||
|
|
||||||
//RecordMediaSourceProviderInfo(mediaSession);
|
|
||||||
if (mediaSession != focusedSession) return;
|
|
||||||
|
|
||||||
if (!IsMediaSourceEnabled(id))
|
|
||||||
{
|
{
|
||||||
_cachedSongInfo = null;
|
if (!_mediaManager.IsStarted) return;
|
||||||
|
if (mediaSession == null) return;
|
||||||
|
|
||||||
_onAnyMediaPropertyChangedRunner.RunAsync(async token =>
|
string id = mediaSession.Id;
|
||||||
|
|
||||||
|
var focusedSession = _mediaManager.GetFocusedSession();
|
||||||
|
|
||||||
|
//RecordMediaSourceProviderInfo(mediaSession);
|
||||||
|
if (mediaSession != focusedSession) return;
|
||||||
|
|
||||||
|
if (!IsMediaSourceEnabled(id))
|
||||||
{
|
{
|
||||||
|
_cachedSongInfo = null;
|
||||||
|
|
||||||
_logger.LogInformation("Media properties changed: Title: {Title}, Artist: {Artist}, Album: {Album}",
|
_logger.LogInformation("Media properties changed: Title: {Title}, Artist: {Artist}, Album: {Album}",
|
||||||
mediaProperties.Title, mediaProperties.Artist, mediaProperties.AlbumTitle);
|
mediaProperties.Title, mediaProperties.Artist, mediaProperties.AlbumTitle);
|
||||||
|
|
||||||
@@ -207,45 +282,26 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
|||||||
}
|
}
|
||||||
|
|
||||||
_SMTCAlbumArtBytes = null;
|
_SMTCAlbumArtBytes = null;
|
||||||
|
}
|
||||||
await _albumArtRefreshRunner.RunAsync(async tokne =>
|
else
|
||||||
{
|
|
||||||
await UpdateAlbumArtRelated(tokne);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!token.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
_dispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, () =>
|
|
||||||
{
|
|
||||||
SongInfoChanged?.Invoke(this, new SongInfoChangedEventArgs(_cachedSongInfo));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_dispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, () =>
|
|
||||||
{
|
{
|
||||||
var currentMediaSourceProviderInfo = GetCurrentMediaSourceProviderInfo();
|
var currentMediaSourceProviderInfo = GetCurrentMediaSourceProviderInfo();
|
||||||
if (currentMediaSourceProviderInfo?.ResetPositionOffsetOnSongChanged == true)
|
if (currentMediaSourceProviderInfo?.ResetPositionOffsetOnSongChanged == true)
|
||||||
{
|
{
|
||||||
currentMediaSourceProviderInfo?.PositionOffset = 0;
|
currentMediaSourceProviderInfo?.PositionOffset = 0;
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
|
||||||
_cachedSongInfo = new SongInfo
|
_cachedSongInfo = new SongInfo
|
||||||
{
|
{
|
||||||
Title = mediaProperties.Title,
|
Title = mediaProperties.Title,
|
||||||
Artist = mediaProperties.Artist,
|
Artist = mediaProperties.Artist,
|
||||||
Album = mediaProperties.AlbumTitle,
|
Album = mediaProperties.AlbumTitle,
|
||||||
DurationMs = mediaSession.ControlSession.GetTimelineProperties().EndTime.TotalMilliseconds,
|
DurationMs = mediaSession.ControlSession.GetTimelineProperties().EndTime.TotalMilliseconds,
|
||||||
SourceAppUserModelId = id,
|
SourceAppUserModelId = id,
|
||||||
};
|
};
|
||||||
|
|
||||||
_cachedSongInfo.Duration = (int)(_cachedSongInfo.DurationMs / 1000f);
|
_cachedSongInfo.Duration = (int)(_cachedSongInfo.DurationMs / 1000f);
|
||||||
|
|
||||||
_onAnyMediaPropertyChangedRunner.RunAsync(async token =>
|
|
||||||
{
|
|
||||||
_logger.LogInformation("Media properties changed: Title: {Title}, Artist: {Artist}, Album: {Album}",
|
_logger.LogInformation("Media properties changed: Title: {Title}, Artist: {Artist}, Album: {Album}",
|
||||||
mediaProperties.Title, mediaProperties.Artist, mediaProperties.AlbumTitle);
|
mediaProperties.Title, mediaProperties.Artist, mediaProperties.AlbumTitle);
|
||||||
|
|
||||||
@@ -266,21 +322,12 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
|||||||
{
|
{
|
||||||
_SMTCAlbumArtBytes = null;
|
_SMTCAlbumArtBytes = null;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
await _albumArtRefreshRunner.RunAsync(async tokne =>
|
SongInfoChanged?.Invoke(this, new SongInfoChangedEventArgs(_cachedSongInfo));
|
||||||
{
|
UpdateAlbumArt();
|
||||||
await UpdateAlbumArtRelated(tokne);
|
UpdateLyrics();
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!token.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
_dispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, () =>
|
|
||||||
{
|
|
||||||
SongInfoChanged?.Invoke(this, new SongInfoChangedEventArgs(_cachedSongInfo));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void MediaManager_OnAnySessionClosed(MediaManager.MediaSession mediaSession)
|
private void MediaManager_OnAnySessionClosed(MediaManager.MediaSession mediaSession)
|
||||||
@@ -344,51 +391,6 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
|||||||
MediaManager_OnAnyPlaybackStateChanged(focusedSession, focusedSession.ControlSession.GetPlaybackInfo());
|
MediaManager_OnAnyPlaybackStateChanged(focusedSession, focusedSession.ControlSession.GetPlaybackInfo());
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task UpdateAlbumArtRelated(CancellationToken token)
|
|
||||||
{
|
|
||||||
if (_cachedSongInfo == null)
|
|
||||||
{
|
|
||||||
_logger.LogWarning("Cached song info is null, cannot update album art.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
byte[]? bytes = await _albumArtSearchService.SearchAsync(
|
|
||||||
SongInfo?.SourceAppUserModelId ?? "",
|
|
||||||
_cachedSongInfo.Title,
|
|
||||||
_cachedSongInfo.Artist,
|
|
||||||
_cachedSongInfo?.Album ?? string.Empty,
|
|
||||||
_SMTCAlbumArtBytes
|
|
||||||
);
|
|
||||||
token.ThrowIfCancellationRequested();
|
|
||||||
|
|
||||||
if (bytes == null)
|
|
||||||
{
|
|
||||||
bytes = await ImageHelper.CreateTextPlaceholderBytesAsync(_targetAlbumArtSize, _targetAlbumArtSize);
|
|
||||||
token.ThrowIfCancellationRequested();
|
|
||||||
}
|
|
||||||
|
|
||||||
bytes = ImageHelper.Resize(bytes, _targetAlbumArtSize);
|
|
||||||
bytes = ImageHelper.MakeSquareWithThemeColor(bytes);
|
|
||||||
|
|
||||||
using var stream = new InMemoryRandomAccessStream();
|
|
||||||
await stream.WriteAsync(bytes.AsBuffer());
|
|
||||||
token.ThrowIfCancellationRequested();
|
|
||||||
|
|
||||||
var decoder = await BitmapDecoder.CreateAsync(stream);
|
|
||||||
token.ThrowIfCancellationRequested();
|
|
||||||
|
|
||||||
var albumArtSwBitmap = await decoder.GetSoftwareBitmapAsync(BitmapPixelFormat.Rgba8, BitmapAlphaMode.Premultiplied);
|
|
||||||
token.ThrowIfCancellationRequested();
|
|
||||||
|
|
||||||
var albumArtLightAccentColor = ImageHelper.GetAccentColorsFromByte(bytes, 1, false).FirstOrDefault();
|
|
||||||
var albumArtDarkAccentColor = ImageHelper.GetAccentColorsFromByte(bytes, 1, true).FirstOrDefault();
|
|
||||||
|
|
||||||
_dispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, () =>
|
|
||||||
{
|
|
||||||
AlbumArtChangedChanged?.Invoke(this, new AlbumArtChangedEventArgs(null, albumArtSwBitmap, albumArtLightAccentColor, albumArtDarkAccentColor));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void StartSSE()
|
private void StartSSE()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -421,7 +423,7 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
|||||||
|
|
||||||
private void Sse_Disconnected(object sender, DisconnectEventArgs e)
|
private void Sse_Disconnected(object sender, DisconnectEventArgs e)
|
||||||
{
|
{
|
||||||
Task.Run(async () =>
|
_dispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, async () =>
|
||||||
{
|
{
|
||||||
await Task.Delay(e.ReconnectDelay);
|
await Task.Delay(e.ReconnectDelay);
|
||||||
if (_sse != null && !_sse.IsDisposed) _sse.Start();
|
if (_sse != null && !_sse.IsDisposed) _sse.Start();
|
||||||
@@ -430,25 +432,26 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
|||||||
|
|
||||||
private void Sse_MessageReceived(object sender, EventSourceMessageEventArgs e)
|
private void Sse_MessageReceived(object sender, EventSourceMessageEventArgs e)
|
||||||
{
|
{
|
||||||
if (_cachedSongInfo?.SourceAppUserModelId == Constants.PlayerID.LXMusic)
|
_dispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, () =>
|
||||||
{
|
{
|
||||||
var data = JsonSerializer.Deserialize(e.Message, Serialization.SourceGenerationContext.Default.JsonElement);
|
if (_cachedSongInfo?.SourceAppUserModelId == Constants.PlayerID.LXMusic)
|
||||||
if (data.ValueKind == JsonValueKind.Number)
|
|
||||||
{
|
{
|
||||||
if (e.Event == "progress")
|
var data = JsonSerializer.Deserialize(e.Message, Serialization.SourceGenerationContext.Default.JsonElement);
|
||||||
{
|
if (data.ValueKind == JsonValueKind.Number)
|
||||||
_lxMusicPositionSeconds = data.GetDouble();
|
|
||||||
}
|
|
||||||
else if (e.Event == "duration")
|
|
||||||
{
|
|
||||||
_lxMusicDurationSeconds = data.GetDouble();
|
|
||||||
}
|
|
||||||
_dispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, () =>
|
|
||||||
{
|
{
|
||||||
|
if (e.Event == "progress")
|
||||||
|
{
|
||||||
|
_lxMusicPositionSeconds = data.GetDouble();
|
||||||
|
}
|
||||||
|
else if (e.Event == "duration")
|
||||||
|
{
|
||||||
|
_lxMusicDurationSeconds = data.GetDouble();
|
||||||
|
}
|
||||||
|
|
||||||
TimelineChanged?.Invoke(this, new TimelineChangedEventArgs(TimeSpan.FromSeconds(_lxMusicPositionSeconds), TimeSpan.FromSeconds(_lxMusicDurationSeconds)));
|
TimelineChanged?.Invoke(this, new TimelineChangedEventArgs(TimeSpan.FromSeconds(_lxMusicPositionSeconds), TimeSpan.FromSeconds(_lxMusicDurationSeconds)));
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task PlayAsync()
|
public async Task PlayAsync()
|
||||||
@@ -501,7 +504,7 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
|||||||
return _settingsService.AppSettings.MediaSourceProvidersInfo.Where(x => x.Provider == _cachedSongInfo?.SourceAppUserModelId)?.FirstOrDefault();
|
return _settingsService.AppSettings.MediaSourceProvidersInfo.Where(x => x.Provider == _cachedSongInfo?.SourceAppUserModelId)?.FirstOrDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async void Receive(PropertyChangedMessage<bool> message)
|
public void Receive(PropertyChangedMessage<bool> message)
|
||||||
{
|
{
|
||||||
if (message.Sender is MediaSourceProviderInfo)
|
if (message.Sender is MediaSourceProviderInfo)
|
||||||
{
|
{
|
||||||
@@ -510,20 +513,63 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
|||||||
MediaManager_OnFocusedSessionChanged(null);
|
MediaManager_OnFocusedSessionChanged(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (message.Sender is AlbumArtSearchProviderInfo)
|
else if (message.Sender is TranslationSettings)
|
||||||
{
|
{
|
||||||
if (message.PropertyName == nameof(AlbumArtSearchProviderInfo.IsEnabled))
|
if (message.PropertyName == nameof(TranslationSettings.IsLibreTranslateEnabled))
|
||||||
{
|
{
|
||||||
await _albumArtRefreshRunner.RunAsync(async tokne =>
|
UpdateTranslations();
|
||||||
{
|
}
|
||||||
await UpdateAlbumArtRelated(tokne);
|
else if (message.PropertyName == nameof(TranslationSettings.IsTranslationEnabled))
|
||||||
});
|
{
|
||||||
|
UpdateTranslations();
|
||||||
|
}
|
||||||
|
else if (message.PropertyName == nameof(TranslationSettings.ShowTranslationOnly))
|
||||||
|
{
|
||||||
|
UpdateTranslations();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Receive(PropertyChangedMessage<FullyObservableCollection<AlbumArtSearchProviderInfo>> message)
|
public void Receive(PropertyChangedMessage<List<string>> message)
|
||||||
{
|
{
|
||||||
|
if (message.Sender is GeneralSettings)
|
||||||
|
{
|
||||||
|
if (message.PropertyName == nameof(GeneralSettings.PlayOrPauseShortcut))
|
||||||
|
{
|
||||||
|
UpdatePlayOrPauseSongShortcut();
|
||||||
|
}
|
||||||
|
else if (message.PropertyName == nameof(GeneralSettings.PreviousSongShortcut))
|
||||||
|
{
|
||||||
|
UpdatePreviousSongShortcut();
|
||||||
|
}
|
||||||
|
else if (message.PropertyName == nameof(GeneralSettings.NextSongShortcut))
|
||||||
|
{
|
||||||
|
UpdateNextSongShortcut();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Receive(PropertyChangedMessage<int> message)
|
||||||
|
{
|
||||||
|
if (message.Sender is TranslationSettings)
|
||||||
|
{
|
||||||
|
if (message.PropertyName == nameof(TranslationSettings.SelectedTargetLanguageIndex))
|
||||||
|
{
|
||||||
|
_logger.LogInformation("Target language index changed: {Index}", _settingsService.AppSettings.TranslationSettings.SelectedTargetLanguageIndex);
|
||||||
|
UpdateTranslations();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Receive(PropertyChangedMessage<string> message)
|
||||||
|
{
|
||||||
|
if (message.Sender is LyricsStyleSettings)
|
||||||
|
{
|
||||||
|
if (message.PropertyName == nameof(LyricsStyleSettings.LyricsTranslationSeparator))
|
||||||
|
{
|
||||||
|
UpdateTranslations();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,20 +32,24 @@ namespace BetterLyrics.WinUI3.Services.SettingsService
|
|||||||
AppSettings.StandardModeSettings.PropertyChanged += AppSettings_PropertyChanged;
|
AppSettings.StandardModeSettings.PropertyChanged += AppSettings_PropertyChanged;
|
||||||
AppSettings.DesktopModeSettings.PropertyChanged += AppSettings_PropertyChanged;
|
AppSettings.DesktopModeSettings.PropertyChanged += AppSettings_PropertyChanged;
|
||||||
AppSettings.DockModeSettings.PropertyChanged += AppSettings_PropertyChanged;
|
AppSettings.DockModeSettings.PropertyChanged += AppSettings_PropertyChanged;
|
||||||
|
AppSettings.PictureInPictureModeSettings.PropertyChanged += AppSettings_PropertyChanged;
|
||||||
|
|
||||||
AppSettings.StandardLyricsStyleSettings.PropertyChanged += AppSettings_PropertyChanged;
|
AppSettings.StandardLyricsStyleSettings.PropertyChanged += AppSettings_PropertyChanged;
|
||||||
AppSettings.DesktopLyricsStyleSettings.PropertyChanged += AppSettings_PropertyChanged;
|
AppSettings.DesktopLyricsStyleSettings.PropertyChanged += AppSettings_PropertyChanged;
|
||||||
AppSettings.DockLyricsStyleSettings.PropertyChanged += AppSettings_PropertyChanged;
|
AppSettings.DockLyricsStyleSettings.PropertyChanged += AppSettings_PropertyChanged;
|
||||||
|
AppSettings.PictureInPictureLyricsStyleSettings.PropertyChanged += AppSettings_PropertyChanged;
|
||||||
|
|
||||||
AppSettings.StandardLyricsEffectSettings.PropertyChanged += AppSettings_PropertyChanged;
|
AppSettings.StandardLyricsEffectSettings.PropertyChanged += AppSettings_PropertyChanged;
|
||||||
AppSettings.DesktopLyricsEffectSettings.PropertyChanged += AppSettings_PropertyChanged;
|
AppSettings.DesktopLyricsEffectSettings.PropertyChanged += AppSettings_PropertyChanged;
|
||||||
AppSettings.DockLyricsEffectSettings.PropertyChanged += AppSettings_PropertyChanged;
|
AppSettings.DockLyricsEffectSettings.PropertyChanged += AppSettings_PropertyChanged;
|
||||||
|
AppSettings.PictureInPictureLyricsEffectSettings.PropertyChanged += AppSettings_PropertyChanged;
|
||||||
|
|
||||||
AppSettings.LyricsBackgroundSettings.PropertyChanged += AppSettings_PropertyChanged;
|
AppSettings.LyricsBackgroundSettings.PropertyChanged += AppSettings_PropertyChanged;
|
||||||
AppSettings.AlbumArtLayoutSettings.PropertyChanged += AppSettings_PropertyChanged;
|
AppSettings.AlbumArtLayoutSettings.PropertyChanged += AppSettings_PropertyChanged;
|
||||||
AppSettings.TranslationSettings.PropertyChanged += AppSettings_PropertyChanged;
|
AppSettings.TranslationSettings.PropertyChanged += AppSettings_PropertyChanged;
|
||||||
AppSettings.GeneralSettings.PropertyChanged += AppSettings_PropertyChanged;
|
AppSettings.GeneralSettings.PropertyChanged += AppSettings_PropertyChanged;
|
||||||
AppSettings.MusicGallerySettings.PropertyChanged += AppSettings_PropertyChanged;
|
AppSettings.MusicGallerySettings.PropertyChanged += AppSettings_PropertyChanged;
|
||||||
|
AppSettings.AdvancedSettings.PropertyChanged += AppSettings_PropertyChanged;
|
||||||
|
|
||||||
AppSettings.MediaSourceProvidersInfo.CollectionChanged += AppSettings_CollectionChanged;
|
AppSettings.MediaSourceProvidersInfo.CollectionChanged += AppSettings_CollectionChanged;
|
||||||
AppSettings.MediaSourceProvidersInfo.ItemPropertyChanged += AppSettings_ItemPropertyChanged;
|
AppSettings.MediaSourceProvidersInfo.ItemPropertyChanged += AppSettings_ItemPropertyChanged;
|
||||||
@@ -53,6 +57,8 @@ namespace BetterLyrics.WinUI3.Services.SettingsService
|
|||||||
AppSettings.LocalMediaFolders.CollectionChanged += AppSettings_CollectionChanged;
|
AppSettings.LocalMediaFolders.CollectionChanged += AppSettings_CollectionChanged;
|
||||||
AppSettings.LocalMediaFolders.ItemPropertyChanged += AppSettings_ItemPropertyChanged;
|
AppSettings.LocalMediaFolders.ItemPropertyChanged += AppSettings_ItemPropertyChanged;
|
||||||
|
|
||||||
|
AppSettings.Version = MetadataHelper.AppVersion;
|
||||||
|
|
||||||
EnsureMediaSourceProvidersInfo();
|
EnsureMediaSourceProvidersInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ namespace BetterLyrics.WinUI3.Services.TranslateService
|
|||||||
{
|
{
|
||||||
public interface ITranslateService
|
public interface ITranslateService
|
||||||
{
|
{
|
||||||
Task<string> TranslateTextAsync(string text, string targetLangCode, CancellationToken? token);
|
Task<string> TranslateTextAsync(string text, string targetLangCode, CancellationToken token);
|
||||||
|
|
||||||
int SearchTranslatedLyricsItself(List<LyricsData> lyricsDataArr);
|
int SearchTranslatedLyricsItself(List<LyricsData> lyricsDataArr);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,8 +3,6 @@ using BetterLyrics.WinUI3.Models;
|
|||||||
using BetterLyrics.WinUI3.Serialization;
|
using BetterLyrics.WinUI3.Serialization;
|
||||||
using BetterLyrics.WinUI3.Services.SettingsService;
|
using BetterLyrics.WinUI3.Services.SettingsService;
|
||||||
using BetterLyrics.WinUI3.ViewModels;
|
using BetterLyrics.WinUI3.ViewModels;
|
||||||
using Lyricify.Lyrics.Helpers.General;
|
|
||||||
using Microsoft.UI.Dispatching;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@@ -27,7 +25,7 @@ namespace BetterLyrics.WinUI3.Services.TranslateService
|
|||||||
_httpClient = new HttpClient();
|
_httpClient = new HttpClient();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<string> TranslateTextAsync(string text, string targetLangCode, CancellationToken? token)
|
public async Task<string> TranslateTextAsync(string text, string targetLangCode, CancellationToken token)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(text))
|
if (string.IsNullOrWhiteSpace(text))
|
||||||
{
|
{
|
||||||
@@ -39,14 +37,6 @@ namespace BetterLyrics.WinUI3.Services.TranslateService
|
|||||||
{
|
{
|
||||||
return text; // No translation needed
|
return text; // No translation needed
|
||||||
}
|
}
|
||||||
else if (originalLangCode == "zh-Hant" && targetLangCode == "zh-Hans")
|
|
||||||
{
|
|
||||||
return ChineseConverter.ConvertToSimplifiedChinese(text);
|
|
||||||
}
|
|
||||||
else if (originalLangCode == "zh-Hans" && targetLangCode == "zh-Hant")
|
|
||||||
{
|
|
||||||
return ChineseConverter.ConvertToTraditionalChinese(text);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(_settingsService.AppSettings.TranslationSettings.LibreTranslateServer))
|
if (string.IsNullOrEmpty(_settingsService.AppSettings.TranslationSettings.LibreTranslateServer))
|
||||||
{
|
{
|
||||||
@@ -59,12 +49,10 @@ namespace BetterLyrics.WinUI3.Services.TranslateService
|
|||||||
new("q", text),
|
new("q", text),
|
||||||
new("source", originalLangCode),
|
new("source", originalLangCode),
|
||||||
new("target", targetLangCode),
|
new("target", targetLangCode),
|
||||||
]));
|
]), token);
|
||||||
token?.ThrowIfCancellationRequested();
|
|
||||||
|
|
||||||
response.EnsureSuccessStatusCode();
|
response.EnsureSuccessStatusCode();
|
||||||
var json = await response.Content.ReadAsStringAsync();
|
var json = await response.Content.ReadAsStringAsync(token);
|
||||||
token?.ThrowIfCancellationRequested();
|
|
||||||
|
|
||||||
var result = System.Text.Json.JsonSerializer.Deserialize(json, SourceGenerationContext.Default.TranslateResponse);
|
var result = System.Text.Json.JsonSerializer.Deserialize(json, SourceGenerationContext.Default.TranslateResponse);
|
||||||
return result?.TranslatedText ?? string.Empty;
|
return result?.TranslatedText ?? string.Empty;
|
||||||
@@ -72,12 +60,12 @@ namespace BetterLyrics.WinUI3.Services.TranslateService
|
|||||||
|
|
||||||
public int SearchTranslatedLyricsItself(List<LyricsData> lyricsDataArr)
|
public int SearchTranslatedLyricsItself(List<LyricsData> lyricsDataArr)
|
||||||
{
|
{
|
||||||
string targetLangCode = LanguageHelper.GetUserTargetLanguageCode().Substring(0, 2);
|
string targetLangCode = LanguageHelper.SupportedTargetLanguages[_settingsService.AppSettings.TranslationSettings.SelectedTargetLanguageIndex].Code;
|
||||||
if (lyricsDataArr.Count > 1)
|
if (lyricsDataArr.Count > 1)
|
||||||
{
|
{
|
||||||
for (int i = 1; i < lyricsDataArr.Count; i++)
|
for (int i = 1; i < lyricsDataArr.Count; i++)
|
||||||
{
|
{
|
||||||
if (lyricsDataArr[i].LanguageCode?.Substring(0, 2) == targetLangCode)
|
if (lyricsDataArr[i].LanguageCode == targetLangCode)
|
||||||
{
|
{
|
||||||
return i; // Translation lyrics data found
|
return i; // Translation lyrics data found
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -129,6 +129,9 @@
|
|||||||
<data name="AllLyricsSettingsControlDock.Content" xml:space="preserve">
|
<data name="AllLyricsSettingsControlDock.Content" xml:space="preserve">
|
||||||
<value>Dock mode</value>
|
<value>Dock mode</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="AllLyricsSettingsControlPictureInPicture.Content" xml:space="preserve">
|
||||||
|
<value>Picture-in-picture mode</value>
|
||||||
|
</data>
|
||||||
<data name="AllLyricsSettingsControlStandard.Content" xml:space="preserve">
|
<data name="AllLyricsSettingsControlStandard.Content" xml:space="preserve">
|
||||||
<value>Standard</value>
|
<value>Standard</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -147,9 +150,6 @@
|
|||||||
<data name="BaseWindowMiniFlyoutItem.Text" xml:space="preserve">
|
<data name="BaseWindowMiniFlyoutItem.Text" xml:space="preserve">
|
||||||
<value>Picture-in-picture mode</value>
|
<value>Picture-in-picture mode</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="BaseWindowUnMiniFlyoutItem.Text" xml:space="preserve">
|
|
||||||
<value>Exit picture-in-picture mode</value>
|
|
||||||
</data>
|
|
||||||
<data name="Cancel" xml:space="preserve">
|
<data name="Cancel" xml:space="preserve">
|
||||||
<value>Cancel</value>
|
<value>Cancel</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -175,7 +175,7 @@
|
|||||||
<value>Dock mode</value>
|
<value>Dock mode</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="HostWindowLockToolTip.Text" xml:space="preserve">
|
<data name="HostWindowLockToolTip.Text" xml:space="preserve">
|
||||||
<value>To unlock after locking, go to the system tray to unlock or press</value>
|
<value>Lock</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="HostWindowMoreButtonToolTip.Content" xml:space="preserve">
|
<data name="HostWindowMoreButtonToolTip.Content" xml:space="preserve">
|
||||||
<value>More</value>
|
<value>More</value>
|
||||||
@@ -216,12 +216,12 @@
|
|||||||
<data name="LyricsNotFound" xml:space="preserve">
|
<data name="LyricsNotFound" xml:space="preserve">
|
||||||
<value>Lyrics not found</value>
|
<value>Lyrics not found</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LyricsPageDisplayTypeButtonToolTip.Content" xml:space="preserve">
|
|
||||||
<value>Display type</value>
|
|
||||||
</data>
|
|
||||||
<data name="LyricsPageLyricsProviderPrefix.Header" xml:space="preserve">
|
<data name="LyricsPageLyricsProviderPrefix.Header" xml:space="preserve">
|
||||||
<value>Lyrics provider</value>
|
<value>Lyrics provider</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="LyricsPageLyricsSettingsButtonToolTip.Content" xml:space="preserve">
|
||||||
|
<value>Lyrics style and effect quick settings</value>
|
||||||
|
</data>
|
||||||
<data name="LyricsPagePlaybackSourceButtonToolTip.Content" xml:space="preserve">
|
<data name="LyricsPagePlaybackSourceButtonToolTip.Content" xml:space="preserve">
|
||||||
<value>Play source shortcut settings</value>
|
<value>Play source shortcut settings</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -270,9 +270,6 @@
|
|||||||
<data name="MainPageDesktopLyricsToggler.ToolTipService.ToolTip" xml:space="preserve">
|
<data name="MainPageDesktopLyricsToggler.ToolTipService.ToolTip" xml:space="preserve">
|
||||||
<value>Switch to desktop lyrics mode</value>
|
<value>Switch to desktop lyrics mode</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="MainPageDisplayTypeSwitcher.ToolTipService.ToolTip" xml:space="preserve">
|
|
||||||
<value>Change display type</value>
|
|
||||||
</data>
|
|
||||||
<data name="MainPageEnterImmersiveModeHint" xml:space="preserve">
|
<data name="MainPageEnterImmersiveModeHint" xml:space="preserve">
|
||||||
<value>Hover back again to show the toggle button</value>
|
<value>Hover back again to show the toggle button</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -433,9 +430,15 @@ If you encounter any problems, please go to the Settings page, About tab, and vi
|
|||||||
<data name="SettingsPageAlbumRadius.Header" xml:space="preserve">
|
<data name="SettingsPageAlbumRadius.Header" xml:space="preserve">
|
||||||
<value>Corner radius</value>
|
<value>Corner radius</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPageAlbumShadowAmount.Header" xml:space="preserve">
|
||||||
|
<value>How much the shadows are spreading</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageAlbumStyle.Content" xml:space="preserve">
|
<data name="SettingsPageAlbumStyle.Content" xml:space="preserve">
|
||||||
<value>Album art area style</value>
|
<value>Album art area style</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPageAmount.Header" xml:space="preserve">
|
||||||
|
<value>Amount</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageApp.Content" xml:space="preserve">
|
<data name="SettingsPageApp.Content" xml:space="preserve">
|
||||||
<value>App appearance and behavior</value>
|
<value>App appearance and behavior</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -451,6 +454,12 @@ If you encounter any problems, please go to the Settings page, About tab, and vi
|
|||||||
<data name="SettingsPageAppDock.Text" xml:space="preserve">
|
<data name="SettingsPageAppDock.Text" xml:space="preserve">
|
||||||
<value>Dock mode</value>
|
<value>Dock mode</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPageAppPictureInPicture.Text" xml:space="preserve">
|
||||||
|
<value>Picture-in-picture mode</value>
|
||||||
|
</data>
|
||||||
|
<data name="SettingsPageAppStandard.Text" xml:space="preserve">
|
||||||
|
<value>Standard</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageAutoLock.Header" xml:space="preserve">
|
<data name="SettingsPageAutoLock.Header" xml:space="preserve">
|
||||||
<value>Auto-lock when activating desktop mode</value>
|
<value>Auto-lock when activating desktop mode</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -466,6 +475,9 @@ If you encounter any problems, please go to the Settings page, About tab, and vi
|
|||||||
<data name="SettingsPageAutoStartInAppLyrics.Content" xml:space="preserve">
|
<data name="SettingsPageAutoStartInAppLyrics.Content" xml:space="preserve">
|
||||||
<value>Activate standard mode</value>
|
<value>Activate standard mode</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPageAutoStartPIPLyrics.Content" xml:space="preserve">
|
||||||
|
<value>Start Picture-in-Picture Mode</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageAutoStartWindow.Header" xml:space="preserve">
|
<data name="SettingsPageAutoStartWindow.Header" xml:space="preserve">
|
||||||
<value>When starting the app</value>
|
<value>When starting the app</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -502,6 +514,9 @@ If you encounter any problems, please go to the Settings page, About tab, and vi
|
|||||||
<data name="SettingsPageDiscord.Header" xml:space="preserve">
|
<data name="SettingsPageDiscord.Header" xml:space="preserve">
|
||||||
<value>Discord</value>
|
<value>Discord</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPageDisplayTypeSwitcher.Header" xml:space="preserve">
|
||||||
|
<value>Lyrics album layout mode</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageDockMonitor.Header" xml:space="preserve">
|
<data name="SettingsPageDockMonitor.Header" xml:space="preserve">
|
||||||
<value>Target monitor</value>
|
<value>Target monitor</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -559,6 +574,9 @@ If you encounter any problems, please go to the Settings page, About tab, and vi
|
|||||||
<data name="SettingsPageEN.Content" xml:space="preserve">
|
<data name="SettingsPageEN.Content" xml:space="preserve">
|
||||||
<value>English</value>
|
<value>English</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPageExitOnLyricsWindowClosed.Header" xml:space="preserve">
|
||||||
|
<value>Exit the program when you close the lyrics window</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageExportSettingsButton.Content" xml:space="preserve">
|
<data name="SettingsPageExportSettingsButton.Content" xml:space="preserve">
|
||||||
<value>Export settings</value>
|
<value>Export settings</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -571,9 +589,15 @@ If you encounter any problems, please go to the Settings page, About tab, and vi
|
|||||||
<data name="SettingsPageFAQ.Header" xml:space="preserve">
|
<data name="SettingsPageFAQ.Header" xml:space="preserve">
|
||||||
<value>Frequently asked questions</value>
|
<value>Frequently asked questions</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPageFixedTimeStep.Header" xml:space="preserve">
|
||||||
|
<value>Fixed time step rendering</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageFollowSystem.Content" xml:space="preserve">
|
<data name="SettingsPageFollowSystem.Content" xml:space="preserve">
|
||||||
<value>Follow system</value>
|
<value>Follow system</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPageFPS.Header" xml:space="preserve">
|
||||||
|
<value>Rendering frame rate</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageGitHub.ActionIconToolTip" xml:space="preserve">
|
<data name="SettingsPageGitHub.ActionIconToolTip" xml:space="preserve">
|
||||||
<value>Open in new window</value>
|
<value>Open in new window</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -755,7 +779,7 @@ If you encounter any problems, please go to the Settings page, About tab, and vi
|
|||||||
<value>Glow effect</value>
|
<value>Glow effect</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SettingsPageLyricsHighlightScope.Header" xml:space="preserve">
|
<data name="SettingsPageLyricsHighlightScope.Header" xml:space="preserve">
|
||||||
<value>Highlight scope</value>
|
<value>Original highlight range</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SettingsPageLyricsLeft.Content" xml:space="preserve">
|
<data name="SettingsPageLyricsLeft.Content" xml:space="preserve">
|
||||||
<value>Left</value>
|
<value>Left</value>
|
||||||
@@ -763,6 +787,9 @@ If you encounter any problems, please go to the Settings page, About tab, and vi
|
|||||||
<data name="SettingsPageLyricsLight.Content" xml:space="preserve">
|
<data name="SettingsPageLyricsLight.Content" xml:space="preserve">
|
||||||
<value>Light</value>
|
<value>Light</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPageLyricsLineFade.Header" xml:space="preserve">
|
||||||
|
<value>Play area edge gradient</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageLyricsLineSpacingFactor.Header" xml:space="preserve">
|
<data name="SettingsPageLyricsLineSpacingFactor.Header" xml:space="preserve">
|
||||||
<value>Line spacing</value>
|
<value>Line spacing</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -799,6 +826,9 @@ If you encounter any problems, please go to the Settings page, About tab, and vi
|
|||||||
<data name="SettingsPageLyricsSemiLight.Content" xml:space="preserve">
|
<data name="SettingsPageLyricsSemiLight.Content" xml:space="preserve">
|
||||||
<value>Semi Light</value>
|
<value>Semi Light</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPageLyricsShadow.Header" xml:space="preserve">
|
||||||
|
<value>Shadows</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageLyricsStrokeFontColor.Header" xml:space="preserve">
|
<data name="SettingsPageLyricsStrokeFontColor.Header" xml:space="preserve">
|
||||||
<value>Lyrics stroke color</value>
|
<value>Lyrics stroke color</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -814,6 +844,9 @@ If you encounter any problems, please go to the Settings page, About tab, and vi
|
|||||||
<data name="SettingsPageLyricsTimelineThreshold.Header" xml:space="preserve">
|
<data name="SettingsPageLyricsTimelineThreshold.Header" xml:space="preserve">
|
||||||
<value>Lyrics timeline sync threshold</value>
|
<value>Lyrics timeline sync threshold</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPageLyricsTranslationHighlight.Header" xml:space="preserve">
|
||||||
|
<value>Translation Highlight</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageLyricsTranslationSeparator.Header" xml:space="preserve">
|
<data name="SettingsPageLyricsTranslationSeparator.Header" xml:space="preserve">
|
||||||
<value>Source and translation separator</value>
|
<value>Source and translation separator</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -841,6 +874,12 @@ If you encounter any problems, please go to the Settings page, About tab, and vi
|
|||||||
<data name="SettingsPageMusicLib.Header" xml:space="preserve">
|
<data name="SettingsPageMusicLib.Header" xml:space="preserve">
|
||||||
<value>Local media library</value>
|
<value>Local media library</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPageMusicLibRealTimeWatch.Header" xml:space="preserve">
|
||||||
|
<value>Listen to file changes in real time</value>
|
||||||
|
</data>
|
||||||
|
<data name="SettingsPageNextSongHotKey.Header" xml:space="preserve">
|
||||||
|
<value>Next track shortcut keys</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageNoBackdrop.Content" xml:space="preserve">
|
<data name="SettingsPageNoBackdrop.Content" xml:space="preserve">
|
||||||
<value>None</value>
|
<value>None</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -865,9 +904,18 @@ If you encounter any problems, please go to the Settings page, About tab, and vi
|
|||||||
<data name="SettingsPagePlaybackNotFound.Text" xml:space="preserve">
|
<data name="SettingsPagePlaybackNotFound.Text" xml:space="preserve">
|
||||||
<value>No playback source captured</value>
|
<value>No playback source captured</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPagePlaybackShortcut.Text" xml:space="preserve">
|
||||||
|
<value>Play</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPagePlayingMockMusicButton.Content" xml:space="preserve">
|
<data name="SettingsPagePlayingMockMusicButton.Content" xml:space="preserve">
|
||||||
<value>Play "Cut To The Feeling" on "soundcloud.com"</value>
|
<value>Play "Cut To The Feeling" on "soundcloud.com"</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPagePlayOrPauseSongHotKey.Header" xml:space="preserve">
|
||||||
|
<value>Play and Pause Shortcuts</value>
|
||||||
|
</data>
|
||||||
|
<data name="SettingsPagePreviousSongHotKey.Header" xml:space="preserve">
|
||||||
|
<value>Shortcut keys for the previous track</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageQQGroup.Header" xml:space="preserve">
|
<data name="SettingsPageQQGroup.Header" xml:space="preserve">
|
||||||
<value>QQ feedback & chat group</value>
|
<value>QQ feedback & chat group</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -889,17 +937,23 @@ If you encounter any problems, please go to the Settings page, About tab, and vi
|
|||||||
<data name="SettingsPageScope.Header" xml:space="preserve">
|
<data name="SettingsPageScope.Header" xml:space="preserve">
|
||||||
<value>Scope</value>
|
<value>Scope</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPageScrollBottomDelay.Header" xml:space="preserve">
|
||||||
|
<value>Tail line delay</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageScrollBottomDuration.Header" xml:space="preserve">
|
<data name="SettingsPageScrollBottomDuration.Header" xml:space="preserve">
|
||||||
<value>Lyrics scrolling animation duration (Last line)</value>
|
<value>Final line duration</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SettingsPageScrollDuration.Header" xml:space="preserve">
|
<data name="SettingsPageScrollDuration.Header" xml:space="preserve">
|
||||||
<value>Lyrics scrolling animation duration (Current line)</value>
|
<value>Current line duration</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SettingsPageScrollEasing.Header" xml:space="preserve">
|
<data name="SettingsPageScrollEasing.Header" xml:space="preserve">
|
||||||
<value>Lyrics scrolling animation type</value>
|
<value>Lyrics scrolling animation type</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPageScrollTopDelay.Header" xml:space="preserve">
|
||||||
|
<value>First line delay</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageScrollTopDuration.Header" xml:space="preserve">
|
<data name="SettingsPageScrollTopDuration.Header" xml:space="preserve">
|
||||||
<value>Lyrics scrolling animation duration (First line)</value>
|
<value>The duration of the first line</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SettingsPageServerTestButton.Content" xml:space="preserve">
|
<data name="SettingsPageServerTestButton.Content" xml:space="preserve">
|
||||||
<value>Test server</value>
|
<value>Test server</value>
|
||||||
@@ -913,6 +967,12 @@ If you encounter any problems, please go to the Settings page, About tab, and vi
|
|||||||
<data name="SettingsPageSettingsManager.Header" xml:space="preserve">
|
<data name="SettingsPageSettingsManager.Header" xml:space="preserve">
|
||||||
<value>Settings manager</value>
|
<value>Settings manager</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPageShortcutRegFailInfo" xml:space="preserve">
|
||||||
|
<value>This hotkey was not successfully registered</value>
|
||||||
|
</data>
|
||||||
|
<data name="SettingsPageShortcutRegSuccessInfo" xml:space="preserve">
|
||||||
|
<value>This hotkey has been successfully registered</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageSliderPrefix.Text" xml:space="preserve">
|
<data name="SettingsPageSliderPrefix.Text" xml:space="preserve">
|
||||||
<value>Current value: </value>
|
<value>Current value: </value>
|
||||||
</data>
|
</data>
|
||||||
@@ -952,6 +1012,9 @@ If you encounter any problems, please go to the Settings page, About tab, and vi
|
|||||||
<data name="SettingsPageTitleBarType.Header" xml:space="preserve">
|
<data name="SettingsPageTitleBarType.Header" xml:space="preserve">
|
||||||
<value>Title bar size</value>
|
<value>Title bar size</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPageToggleHotKey.Header" xml:space="preserve">
|
||||||
|
<value>Switch in and cut out shortcut keys</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageTranslation.Text" xml:space="preserve">
|
<data name="SettingsPageTranslation.Text" xml:space="preserve">
|
||||||
<value>Lyrics translation</value>
|
<value>Lyrics translation</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -970,6 +1033,9 @@ If you encounter any problems, please go to the Settings page, About tab, and vi
|
|||||||
<data name="SystemTrayExit.Text" xml:space="preserve">
|
<data name="SystemTrayExit.Text" xml:space="preserve">
|
||||||
<value>Exit</value>
|
<value>Exit</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SystemTrayLyrics.Text" xml:space="preserve">
|
||||||
|
<value>Open the lyrics window</value>
|
||||||
|
</data>
|
||||||
<data name="SystemTrayMusicGallery.Text" xml:space="preserve">
|
<data name="SystemTrayMusicGallery.Text" xml:space="preserve">
|
||||||
<value>Open music gallery</value>
|
<value>Open music gallery</value>
|
||||||
</data>
|
</data>
|
||||||
|
|||||||
@@ -129,6 +129,9 @@
|
|||||||
<data name="AllLyricsSettingsControlDock.Content" xml:space="preserve">
|
<data name="AllLyricsSettingsControlDock.Content" xml:space="preserve">
|
||||||
<value>ドックモード</value>
|
<value>ドックモード</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="AllLyricsSettingsControlPictureInPicture.Content" xml:space="preserve">
|
||||||
|
<value>ピクチャーインピクチャーモード</value>
|
||||||
|
</data>
|
||||||
<data name="AllLyricsSettingsControlStandard.Content" xml:space="preserve">
|
<data name="AllLyricsSettingsControlStandard.Content" xml:space="preserve">
|
||||||
<value>標準モード</value>
|
<value>標準モード</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -147,9 +150,6 @@
|
|||||||
<data name="BaseWindowMiniFlyoutItem.Text" xml:space="preserve">
|
<data name="BaseWindowMiniFlyoutItem.Text" xml:space="preserve">
|
||||||
<value>ピクチャーインピクチャーモード</value>
|
<value>ピクチャーインピクチャーモード</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="BaseWindowUnMiniFlyoutItem.Text" xml:space="preserve">
|
|
||||||
<value>ピクチャーインピクチャーモードを終了します</value>
|
|
||||||
</data>
|
|
||||||
<data name="Cancel" xml:space="preserve">
|
<data name="Cancel" xml:space="preserve">
|
||||||
<value>キャンセル</value>
|
<value>キャンセル</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -175,7 +175,7 @@
|
|||||||
<value>ドックモード</value>
|
<value>ドックモード</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="HostWindowLockToolTip.Text" xml:space="preserve">
|
<data name="HostWindowLockToolTip.Text" xml:space="preserve">
|
||||||
<value>ロック後にロックを解除するには、システムトレイに移動してロックを解除または押します</value>
|
<value>ロック</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="HostWindowMoreButtonToolTip.Content" xml:space="preserve">
|
<data name="HostWindowMoreButtonToolTip.Content" xml:space="preserve">
|
||||||
<value>もっと</value>
|
<value>もっと</value>
|
||||||
@@ -216,12 +216,12 @@
|
|||||||
<data name="LyricsNotFound" xml:space="preserve">
|
<data name="LyricsNotFound" xml:space="preserve">
|
||||||
<value>歌詞が見つかりません</value>
|
<value>歌詞が見つかりません</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LyricsPageDisplayTypeButtonToolTip.Content" xml:space="preserve">
|
|
||||||
<value>表示タイプ</value>
|
|
||||||
</data>
|
|
||||||
<data name="LyricsPageLyricsProviderPrefix.Header" xml:space="preserve">
|
<data name="LyricsPageLyricsProviderPrefix.Header" xml:space="preserve">
|
||||||
<value>歌詞プロバイダー</value>
|
<value>歌詞プロバイダー</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="LyricsPageLyricsSettingsButtonToolTip.Content" xml:space="preserve">
|
||||||
|
<value>歌詞スタイルと効果クイック設定</value>
|
||||||
|
</data>
|
||||||
<data name="LyricsPagePlaybackSourceButtonToolTip.Content" xml:space="preserve">
|
<data name="LyricsPagePlaybackSourceButtonToolTip.Content" xml:space="preserve">
|
||||||
<value>再生ソースクイック設定</value>
|
<value>再生ソースクイック設定</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -270,9 +270,6 @@
|
|||||||
<data name="MainPageDesktopLyricsToggler.ToolTipService.ToolTip" xml:space="preserve">
|
<data name="MainPageDesktopLyricsToggler.ToolTipService.ToolTip" xml:space="preserve">
|
||||||
<value>デスクトップ歌詞モードに切り替えます</value>
|
<value>デスクトップ歌詞モードに切り替えます</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="MainPageDisplayTypeSwitcher.ToolTipService.ToolTip" xml:space="preserve">
|
|
||||||
<value>表示タイプを変更します</value>
|
|
||||||
</data>
|
|
||||||
<data name="MainPageEnterImmersiveModeHint" xml:space="preserve">
|
<data name="MainPageEnterImmersiveModeHint" xml:space="preserve">
|
||||||
<value>再びホバリングして、トグルボタンを表示します</value>
|
<value>再びホバリングして、トグルボタンを表示します</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -433,9 +430,15 @@
|
|||||||
<data name="SettingsPageAlbumRadius.Header" xml:space="preserve">
|
<data name="SettingsPageAlbumRadius.Header" xml:space="preserve">
|
||||||
<value>コーナー半径</value>
|
<value>コーナー半径</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPageAlbumShadowAmount.Header" xml:space="preserve">
|
||||||
|
<value>影がどれだけ広がっているか</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageAlbumStyle.Content" xml:space="preserve">
|
<data name="SettingsPageAlbumStyle.Content" xml:space="preserve">
|
||||||
<value>アルバムエリアスタイル</value>
|
<value>アルバムエリアスタイル</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPageAmount.Header" xml:space="preserve">
|
||||||
|
<value>量</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageApp.Content" xml:space="preserve">
|
<data name="SettingsPageApp.Content" xml:space="preserve">
|
||||||
<value>アプリの外観と動作</value>
|
<value>アプリの外観と動作</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -451,6 +454,12 @@
|
|||||||
<data name="SettingsPageAppDock.Text" xml:space="preserve">
|
<data name="SettingsPageAppDock.Text" xml:space="preserve">
|
||||||
<value>ドックモード</value>
|
<value>ドックモード</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPageAppPictureInPicture.Text" xml:space="preserve">
|
||||||
|
<value>ピクチャーインピクチャーモード</value>
|
||||||
|
</data>
|
||||||
|
<data name="SettingsPageAppStandard.Text" xml:space="preserve">
|
||||||
|
<value>標準モード</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageAutoLock.Header" xml:space="preserve">
|
<data name="SettingsPageAutoLock.Header" xml:space="preserve">
|
||||||
<value>デスクトップモードをアクティブにするときの自動ロック</value>
|
<value>デスクトップモードをアクティブにするときの自動ロック</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -466,6 +475,9 @@
|
|||||||
<data name="SettingsPageAutoStartInAppLyrics.Content" xml:space="preserve">
|
<data name="SettingsPageAutoStartInAppLyrics.Content" xml:space="preserve">
|
||||||
<value>標準モードをアクティブにします</value>
|
<value>標準モードをアクティブにします</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPageAutoStartPIPLyrics.Content" xml:space="preserve">
|
||||||
|
<value>ピクチャーインピクチャーモードを開始します</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageAutoStartWindow.Header" xml:space="preserve">
|
<data name="SettingsPageAutoStartWindow.Header" xml:space="preserve">
|
||||||
<value>アプリを起動するとき</value>
|
<value>アプリを起動するとき</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -502,6 +514,9 @@
|
|||||||
<data name="SettingsPageDiscord.Header" xml:space="preserve">
|
<data name="SettingsPageDiscord.Header" xml:space="preserve">
|
||||||
<value>Discord</value>
|
<value>Discord</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPageDisplayTypeSwitcher.Header" xml:space="preserve">
|
||||||
|
<value>歌詞アルバムレイアウトモード</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageDockMonitor.Header" xml:space="preserve">
|
<data name="SettingsPageDockMonitor.Header" xml:space="preserve">
|
||||||
<value>ターゲットモニター</value>
|
<value>ターゲットモニター</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -559,6 +574,9 @@
|
|||||||
<data name="SettingsPageEN.Content" xml:space="preserve">
|
<data name="SettingsPageEN.Content" xml:space="preserve">
|
||||||
<value>English</value>
|
<value>English</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPageExitOnLyricsWindowClosed.Header" xml:space="preserve">
|
||||||
|
<value>歌詞ウィンドウを閉じてプログラムを終了してください</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageExportSettingsButton.Content" xml:space="preserve">
|
<data name="SettingsPageExportSettingsButton.Content" xml:space="preserve">
|
||||||
<value>エクスポート設定</value>
|
<value>エクスポート設定</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -571,9 +589,15 @@
|
|||||||
<data name="SettingsPageFAQ.Header" xml:space="preserve">
|
<data name="SettingsPageFAQ.Header" xml:space="preserve">
|
||||||
<value>よくある質問</value>
|
<value>よくある質問</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPageFixedTimeStep.Header" xml:space="preserve">
|
||||||
|
<value>固定時間ステップレンダリング</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageFollowSystem.Content" xml:space="preserve">
|
<data name="SettingsPageFollowSystem.Content" xml:space="preserve">
|
||||||
<value>システムをフォローします</value>
|
<value>システムをフォローします</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPageFPS.Header" xml:space="preserve">
|
||||||
|
<value>レンダリングフレームレート</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageGitHub.ActionIconToolTip" xml:space="preserve">
|
<data name="SettingsPageGitHub.ActionIconToolTip" xml:space="preserve">
|
||||||
<value>新しいウィンドウで開きます</value>
|
<value>新しいウィンドウで開きます</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -755,7 +779,7 @@
|
|||||||
<value>グロー効果</value>
|
<value>グロー効果</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SettingsPageLyricsHighlightScope.Header" xml:space="preserve">
|
<data name="SettingsPageLyricsHighlightScope.Header" xml:space="preserve">
|
||||||
<value>ハイライトスコープ</value>
|
<value>オリジナルのハイライト範囲</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SettingsPageLyricsLeft.Content" xml:space="preserve">
|
<data name="SettingsPageLyricsLeft.Content" xml:space="preserve">
|
||||||
<value>左</value>
|
<value>左</value>
|
||||||
@@ -763,6 +787,9 @@
|
|||||||
<data name="SettingsPageLyricsLight.Content" xml:space="preserve">
|
<data name="SettingsPageLyricsLight.Content" xml:space="preserve">
|
||||||
<value>ライト</value>
|
<value>ライト</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPageLyricsLineFade.Header" xml:space="preserve">
|
||||||
|
<value>プレイエリアエッジグラデーション</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageLyricsLineSpacingFactor.Header" xml:space="preserve">
|
<data name="SettingsPageLyricsLineSpacingFactor.Header" xml:space="preserve">
|
||||||
<value>ライン間隔</value>
|
<value>ライン間隔</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -799,6 +826,9 @@
|
|||||||
<data name="SettingsPageLyricsSemiLight.Content" xml:space="preserve">
|
<data name="SettingsPageLyricsSemiLight.Content" xml:space="preserve">
|
||||||
<value>半光</value>
|
<value>半光</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPageLyricsShadow.Header" xml:space="preserve">
|
||||||
|
<value>影だ</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageLyricsStrokeFontColor.Header" xml:space="preserve">
|
<data name="SettingsPageLyricsStrokeFontColor.Header" xml:space="preserve">
|
||||||
<value>歌詞ストロークカラー</value>
|
<value>歌詞ストロークカラー</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -814,6 +844,9 @@
|
|||||||
<data name="SettingsPageLyricsTimelineThreshold.Header" xml:space="preserve">
|
<data name="SettingsPageLyricsTimelineThreshold.Header" xml:space="preserve">
|
||||||
<value>歌詞タイムライン同期しきい値</value>
|
<value>歌詞タイムライン同期しきい値</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPageLyricsTranslationHighlight.Header" xml:space="preserve">
|
||||||
|
<value>翻訳ハイライト</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageLyricsTranslationSeparator.Header" xml:space="preserve">
|
<data name="SettingsPageLyricsTranslationSeparator.Header" xml:space="preserve">
|
||||||
<value>ソースおよび翻訳セパレーター</value>
|
<value>ソースおよび翻訳セパレーター</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -841,6 +874,12 @@
|
|||||||
<data name="SettingsPageMusicLib.Header" xml:space="preserve">
|
<data name="SettingsPageMusicLib.Header" xml:space="preserve">
|
||||||
<value>地元のメディア図書館</value>
|
<value>地元のメディア図書館</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPageMusicLibRealTimeWatch.Header" xml:space="preserve">
|
||||||
|
<value>ファイルの変更をリアルタイムで聞いてください</value>
|
||||||
|
</data>
|
||||||
|
<data name="SettingsPageNextSongHotKey.Header" xml:space="preserve">
|
||||||
|
<value>次のトラックショートカットキー</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageNoBackdrop.Content" xml:space="preserve">
|
<data name="SettingsPageNoBackdrop.Content" xml:space="preserve">
|
||||||
<value>なし</value>
|
<value>なし</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -865,9 +904,18 @@
|
|||||||
<data name="SettingsPagePlaybackNotFound.Text" xml:space="preserve">
|
<data name="SettingsPagePlaybackNotFound.Text" xml:space="preserve">
|
||||||
<value>キャプチャされた再生ソースはありません</value>
|
<value>キャプチャされた再生ソースはありません</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPagePlaybackShortcut.Text" xml:space="preserve">
|
||||||
|
<value>遊ぶ</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPagePlayingMockMusicButton.Content" xml:space="preserve">
|
<data name="SettingsPagePlayingMockMusicButton.Content" xml:space="preserve">
|
||||||
<value>「SoundCloud.com」で「Cut to the Feeling」を再生する</value>
|
<value>「SoundCloud.com」で「Cut to the Feeling」を再生する</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPagePlayOrPauseSongHotKey.Header" xml:space="preserve">
|
||||||
|
<value>ショートカットを再生して一時停止します</value>
|
||||||
|
</data>
|
||||||
|
<data name="SettingsPagePreviousSongHotKey.Header" xml:space="preserve">
|
||||||
|
<value>前のトラックのショートカットキー</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageQQGroup.Header" xml:space="preserve">
|
<data name="SettingsPageQQGroup.Header" xml:space="preserve">
|
||||||
<value>QQフィードバック&チャットグループ</value>
|
<value>QQフィードバック&チャットグループ</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -889,17 +937,23 @@
|
|||||||
<data name="SettingsPageScope.Header" xml:space="preserve">
|
<data name="SettingsPageScope.Header" xml:space="preserve">
|
||||||
<value>範囲</value>
|
<value>範囲</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPageScrollBottomDelay.Header" xml:space="preserve">
|
||||||
|
<value>テールラインの遅延</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageScrollBottomDuration.Header" xml:space="preserve">
|
<data name="SettingsPageScrollBottomDuration.Header" xml:space="preserve">
|
||||||
<value>歌詞スクロールアニメーション期間(最終行)</value>
|
<value>最終ライン期間</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SettingsPageScrollDuration.Header" xml:space="preserve">
|
<data name="SettingsPageScrollDuration.Header" xml:space="preserve">
|
||||||
<value>歌詞スクロールアニメーション期間(現在の行)</value>
|
<value>現在のライン期間</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SettingsPageScrollEasing.Header" xml:space="preserve">
|
<data name="SettingsPageScrollEasing.Header" xml:space="preserve">
|
||||||
<value>歌詞スクロールアニメーションタイプ</value>
|
<value>歌詞スクロールアニメーションタイプ</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPageScrollTopDelay.Header" xml:space="preserve">
|
||||||
|
<value>最初の行の遅延</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageScrollTopDuration.Header" xml:space="preserve">
|
<data name="SettingsPageScrollTopDuration.Header" xml:space="preserve">
|
||||||
<value>歌詞スクロールアニメーション期間(最初の行)</value>
|
<value>最初の行の期間</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SettingsPageServerTestButton.Content" xml:space="preserve">
|
<data name="SettingsPageServerTestButton.Content" xml:space="preserve">
|
||||||
<value>テストサーバー</value>
|
<value>テストサーバー</value>
|
||||||
@@ -913,6 +967,12 @@
|
|||||||
<data name="SettingsPageSettingsManager.Header" xml:space="preserve">
|
<data name="SettingsPageSettingsManager.Header" xml:space="preserve">
|
||||||
<value>設定マネージャー</value>
|
<value>設定マネージャー</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPageShortcutRegFailInfo" xml:space="preserve">
|
||||||
|
<value>このホットキーは正常に登録されていません</value>
|
||||||
|
</data>
|
||||||
|
<data name="SettingsPageShortcutRegSuccessInfo" xml:space="preserve">
|
||||||
|
<value>このホットキーは正常に登録されています</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageSliderPrefix.Text" xml:space="preserve">
|
<data name="SettingsPageSliderPrefix.Text" xml:space="preserve">
|
||||||
<value>現在の値: </value>
|
<value>現在の値: </value>
|
||||||
</data>
|
</data>
|
||||||
@@ -952,6 +1012,9 @@
|
|||||||
<data name="SettingsPageTitleBarType.Header" xml:space="preserve">
|
<data name="SettingsPageTitleBarType.Header" xml:space="preserve">
|
||||||
<value>タイトルバーサイズ</value>
|
<value>タイトルバーサイズ</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPageToggleHotKey.Header" xml:space="preserve">
|
||||||
|
<value>ショートカットキーを切り込んで切り取ります</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageTranslation.Text" xml:space="preserve">
|
<data name="SettingsPageTranslation.Text" xml:space="preserve">
|
||||||
<value>歌詞翻訳</value>
|
<value>歌詞翻訳</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -970,6 +1033,9 @@
|
|||||||
<data name="SystemTrayExit.Text" xml:space="preserve">
|
<data name="SystemTrayExit.Text" xml:space="preserve">
|
||||||
<value>プログラムを終了します</value>
|
<value>プログラムを終了します</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SystemTrayLyrics.Text" xml:space="preserve">
|
||||||
|
<value>歌詞ウィンドウを開きます</value>
|
||||||
|
</data>
|
||||||
<data name="SystemTrayMusicGallery.Text" xml:space="preserve">
|
<data name="SystemTrayMusicGallery.Text" xml:space="preserve">
|
||||||
<value>オープンミュージックギャラリー</value>
|
<value>オープンミュージックギャラリー</value>
|
||||||
</data>
|
</data>
|
||||||
|
|||||||
@@ -129,6 +129,9 @@
|
|||||||
<data name="AllLyricsSettingsControlDock.Content" xml:space="preserve">
|
<data name="AllLyricsSettingsControlDock.Content" xml:space="preserve">
|
||||||
<value>도크 모드</value>
|
<value>도크 모드</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="AllLyricsSettingsControlPictureInPicture.Content" xml:space="preserve">
|
||||||
|
<value>사진 인당 모드</value>
|
||||||
|
</data>
|
||||||
<data name="AllLyricsSettingsControlStandard.Content" xml:space="preserve">
|
<data name="AllLyricsSettingsControlStandard.Content" xml:space="preserve">
|
||||||
<value>표준 모드</value>
|
<value>표준 모드</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -147,9 +150,6 @@
|
|||||||
<data name="BaseWindowMiniFlyoutItem.Text" xml:space="preserve">
|
<data name="BaseWindowMiniFlyoutItem.Text" xml:space="preserve">
|
||||||
<value>사진 인당 모드</value>
|
<value>사진 인당 모드</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="BaseWindowUnMiniFlyoutItem.Text" xml:space="preserve">
|
|
||||||
<value>Picture-in-Picture 모드 종료</value>
|
|
||||||
</data>
|
|
||||||
<data name="Cancel" xml:space="preserve">
|
<data name="Cancel" xml:space="preserve">
|
||||||
<value>취소</value>
|
<value>취소</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -175,7 +175,7 @@
|
|||||||
<value>도크 모드</value>
|
<value>도크 모드</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="HostWindowLockToolTip.Text" xml:space="preserve">
|
<data name="HostWindowLockToolTip.Text" xml:space="preserve">
|
||||||
<value>잠금 잠금을 해제하려면 시스템 트레이로 이동하여 잠금을 해제하거나 누릅니다.</value>
|
<value>잠금</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="HostWindowMoreButtonToolTip.Content" xml:space="preserve">
|
<data name="HostWindowMoreButtonToolTip.Content" xml:space="preserve">
|
||||||
<value>더</value>
|
<value>더</value>
|
||||||
@@ -216,12 +216,12 @@
|
|||||||
<data name="LyricsNotFound" xml:space="preserve">
|
<data name="LyricsNotFound" xml:space="preserve">
|
||||||
<value>가사를 찾을 수 없습니다</value>
|
<value>가사를 찾을 수 없습니다</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LyricsPageDisplayTypeButtonToolTip.Content" xml:space="preserve">
|
|
||||||
<value>디스플레이 유형</value>
|
|
||||||
</data>
|
|
||||||
<data name="LyricsPageLyricsProviderPrefix.Header" xml:space="preserve">
|
<data name="LyricsPageLyricsProviderPrefix.Header" xml:space="preserve">
|
||||||
<value>가사 제공자</value>
|
<value>가사 제공자</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="LyricsPageLyricsSettingsButtonToolTip.Content" xml:space="preserve">
|
||||||
|
<value>가사 스타일과 효과 빠른 설정</value>
|
||||||
|
</data>
|
||||||
<data name="LyricsPagePlaybackSourceButtonToolTip.Content" xml:space="preserve">
|
<data name="LyricsPagePlaybackSourceButtonToolTip.Content" xml:space="preserve">
|
||||||
<value>재생 소스 빠른 설정</value>
|
<value>재생 소스 빠른 설정</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -270,9 +270,6 @@
|
|||||||
<data name="MainPageDesktopLyricsToggler.ToolTipService.ToolTip" xml:space="preserve">
|
<data name="MainPageDesktopLyricsToggler.ToolTipService.ToolTip" xml:space="preserve">
|
||||||
<value>데스크탑 가사 모드로 전환하십시오</value>
|
<value>데스크탑 가사 모드로 전환하십시오</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="MainPageDisplayTypeSwitcher.ToolTipService.ToolTip" xml:space="preserve">
|
|
||||||
<value>디스플레이 유형을 변경하십시오</value>
|
|
||||||
</data>
|
|
||||||
<data name="MainPageEnterImmersiveModeHint" xml:space="preserve">
|
<data name="MainPageEnterImmersiveModeHint" xml:space="preserve">
|
||||||
<value>토글 버튼을 표시하려면 다시 다시 가져옵니다</value>
|
<value>토글 버튼을 표시하려면 다시 다시 가져옵니다</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -433,9 +430,15 @@
|
|||||||
<data name="SettingsPageAlbumRadius.Header" xml:space="preserve">
|
<data name="SettingsPageAlbumRadius.Header" xml:space="preserve">
|
||||||
<value>코너 반경</value>
|
<value>코너 반경</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPageAlbumShadowAmount.Header" xml:space="preserve">
|
||||||
|
<value>그림자가 얼마나 퍼져나가는지</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageAlbumStyle.Content" xml:space="preserve">
|
<data name="SettingsPageAlbumStyle.Content" xml:space="preserve">
|
||||||
<value>앨범 영역 스타일</value>
|
<value>앨범 영역 스타일</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPageAmount.Header" xml:space="preserve">
|
||||||
|
<value>금액</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageApp.Content" xml:space="preserve">
|
<data name="SettingsPageApp.Content" xml:space="preserve">
|
||||||
<value>앱 외관과 행동</value>
|
<value>앱 외관과 행동</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -451,6 +454,12 @@
|
|||||||
<data name="SettingsPageAppDock.Text" xml:space="preserve">
|
<data name="SettingsPageAppDock.Text" xml:space="preserve">
|
||||||
<value>도크 모드</value>
|
<value>도크 모드</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPageAppPictureInPicture.Text" xml:space="preserve">
|
||||||
|
<value>사진 인당 모드</value>
|
||||||
|
</data>
|
||||||
|
<data name="SettingsPageAppStandard.Text" xml:space="preserve">
|
||||||
|
<value>표준 모드</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageAutoLock.Header" xml:space="preserve">
|
<data name="SettingsPageAutoLock.Header" xml:space="preserve">
|
||||||
<value>데스크탑 모드를 활성화 할 때 자동 잠금</value>
|
<value>데스크탑 모드를 활성화 할 때 자동 잠금</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -466,6 +475,9 @@
|
|||||||
<data name="SettingsPageAutoStartInAppLyrics.Content" xml:space="preserve">
|
<data name="SettingsPageAutoStartInAppLyrics.Content" xml:space="preserve">
|
||||||
<value>표준 모드를 활성화합니다</value>
|
<value>표준 모드를 활성화합니다</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPageAutoStartPIPLyrics.Content" xml:space="preserve">
|
||||||
|
<value>Picture-in-Picture 모드를 시작하십시오</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageAutoStartWindow.Header" xml:space="preserve">
|
<data name="SettingsPageAutoStartWindow.Header" xml:space="preserve">
|
||||||
<value>앱을 시작할 때</value>
|
<value>앱을 시작할 때</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -502,6 +514,9 @@
|
|||||||
<data name="SettingsPageDiscord.Header" xml:space="preserve">
|
<data name="SettingsPageDiscord.Header" xml:space="preserve">
|
||||||
<value>Discord</value>
|
<value>Discord</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPageDisplayTypeSwitcher.Header" xml:space="preserve">
|
||||||
|
<value>가사 앨범 레이아웃 모드</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageDockMonitor.Header" xml:space="preserve">
|
<data name="SettingsPageDockMonitor.Header" xml:space="preserve">
|
||||||
<value>대상 모니터</value>
|
<value>대상 모니터</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -559,6 +574,9 @@
|
|||||||
<data name="SettingsPageEN.Content" xml:space="preserve">
|
<data name="SettingsPageEN.Content" xml:space="preserve">
|
||||||
<value>English</value>
|
<value>English</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPageExitOnLyricsWindowClosed.Header" xml:space="preserve">
|
||||||
|
<value>가사 창을 닫으면 프로그램을 종료하세요</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageExportSettingsButton.Content" xml:space="preserve">
|
<data name="SettingsPageExportSettingsButton.Content" xml:space="preserve">
|
||||||
<value>내보내기 설정</value>
|
<value>내보내기 설정</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -571,9 +589,15 @@
|
|||||||
<data name="SettingsPageFAQ.Header" xml:space="preserve">
|
<data name="SettingsPageFAQ.Header" xml:space="preserve">
|
||||||
<value>자주 묻는 질문</value>
|
<value>자주 묻는 질문</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPageFixedTimeStep.Header" xml:space="preserve">
|
||||||
|
<value>고정 시간 단계 렌더링</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageFollowSystem.Content" xml:space="preserve">
|
<data name="SettingsPageFollowSystem.Content" xml:space="preserve">
|
||||||
<value>시스템을 따르십시오</value>
|
<value>시스템을 따르십시오</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPageFPS.Header" xml:space="preserve">
|
||||||
|
<value>렌더링 프레임 속도</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageGitHub.ActionIconToolTip" xml:space="preserve">
|
<data name="SettingsPageGitHub.ActionIconToolTip" xml:space="preserve">
|
||||||
<value>새 창에서 열립니다</value>
|
<value>새 창에서 열립니다</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -755,7 +779,7 @@
|
|||||||
<value>글로우 효과</value>
|
<value>글로우 효과</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SettingsPageLyricsHighlightScope.Header" xml:space="preserve">
|
<data name="SettingsPageLyricsHighlightScope.Header" xml:space="preserve">
|
||||||
<value>하이라이트 범위</value>
|
<value>원래 하이라이트 범위</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SettingsPageLyricsLeft.Content" xml:space="preserve">
|
<data name="SettingsPageLyricsLeft.Content" xml:space="preserve">
|
||||||
<value>왼쪽</value>
|
<value>왼쪽</value>
|
||||||
@@ -763,6 +787,9 @@
|
|||||||
<data name="SettingsPageLyricsLight.Content" xml:space="preserve">
|
<data name="SettingsPageLyricsLight.Content" xml:space="preserve">
|
||||||
<value>빛</value>
|
<value>빛</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPageLyricsLineFade.Header" xml:space="preserve">
|
||||||
|
<value>플레이 영역 에지 그라데이션</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageLyricsLineSpacingFactor.Header" xml:space="preserve">
|
<data name="SettingsPageLyricsLineSpacingFactor.Header" xml:space="preserve">
|
||||||
<value>라인 간격</value>
|
<value>라인 간격</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -799,6 +826,9 @@
|
|||||||
<data name="SettingsPageLyricsSemiLight.Content" xml:space="preserve">
|
<data name="SettingsPageLyricsSemiLight.Content" xml:space="preserve">
|
||||||
<value>반 빛</value>
|
<value>반 빛</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPageLyricsShadow.Header" xml:space="preserve">
|
||||||
|
<value>그림자</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageLyricsStrokeFontColor.Header" xml:space="preserve">
|
<data name="SettingsPageLyricsStrokeFontColor.Header" xml:space="preserve">
|
||||||
<value>가사 스트로크 컬러</value>
|
<value>가사 스트로크 컬러</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -814,6 +844,9 @@
|
|||||||
<data name="SettingsPageLyricsTimelineThreshold.Header" xml:space="preserve">
|
<data name="SettingsPageLyricsTimelineThreshold.Header" xml:space="preserve">
|
||||||
<value>가사 타임 라인 동기화 임계 값</value>
|
<value>가사 타임 라인 동기화 임계 값</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPageLyricsTranslationHighlight.Header" xml:space="preserve">
|
||||||
|
<value>번역 하이라이트</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageLyricsTranslationSeparator.Header" xml:space="preserve">
|
<data name="SettingsPageLyricsTranslationSeparator.Header" xml:space="preserve">
|
||||||
<value>소스 및 번역 분리기</value>
|
<value>소스 및 번역 분리기</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -841,6 +874,12 @@
|
|||||||
<data name="SettingsPageMusicLib.Header" xml:space="preserve">
|
<data name="SettingsPageMusicLib.Header" xml:space="preserve">
|
||||||
<value>로컬 미디어 라이브러리</value>
|
<value>로컬 미디어 라이브러리</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPageMusicLibRealTimeWatch.Header" xml:space="preserve">
|
||||||
|
<value>실시간으로 파일 변경을 듣습니다</value>
|
||||||
|
</data>
|
||||||
|
<data name="SettingsPageNextSongHotKey.Header" xml:space="preserve">
|
||||||
|
<value>다음 트랙 바로 가기 키</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageNoBackdrop.Content" xml:space="preserve">
|
<data name="SettingsPageNoBackdrop.Content" xml:space="preserve">
|
||||||
<value>없음</value>
|
<value>없음</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -865,9 +904,18 @@
|
|||||||
<data name="SettingsPagePlaybackNotFound.Text" xml:space="preserve">
|
<data name="SettingsPagePlaybackNotFound.Text" xml:space="preserve">
|
||||||
<value>재생 소스가 캡처되지 않았습니다</value>
|
<value>재생 소스가 캡처되지 않았습니다</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPagePlaybackShortcut.Text" xml:space="preserve">
|
||||||
|
<value>놀다</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPagePlayingMockMusicButton.Content" xml:space="preserve">
|
<data name="SettingsPagePlayingMockMusicButton.Content" xml:space="preserve">
|
||||||
<value>"soundcloud.com"에서 "Fut to the Feeling"을 재생하십시오.</value>
|
<value>"soundcloud.com"에서 "Fut to the Feeling"을 재생하십시오.</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPagePlayOrPauseSongHotKey.Header" xml:space="preserve">
|
||||||
|
<value>바로 가기를 재생하고 일시 중지합니다</value>
|
||||||
|
</data>
|
||||||
|
<data name="SettingsPagePreviousSongHotKey.Header" xml:space="preserve">
|
||||||
|
<value>이전 트랙의 바로 가기 키</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageQQGroup.Header" xml:space="preserve">
|
<data name="SettingsPageQQGroup.Header" xml:space="preserve">
|
||||||
<value>QQ 피드백 및 채팅 그룹</value>
|
<value>QQ 피드백 및 채팅 그룹</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -889,17 +937,23 @@
|
|||||||
<data name="SettingsPageScope.Header" xml:space="preserve">
|
<data name="SettingsPageScope.Header" xml:space="preserve">
|
||||||
<value>범위</value>
|
<value>범위</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPageScrollBottomDelay.Header" xml:space="preserve">
|
||||||
|
<value>테일 라인 지연</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageScrollBottomDuration.Header" xml:space="preserve">
|
<data name="SettingsPageScrollBottomDuration.Header" xml:space="preserve">
|
||||||
<value>가사 스크롤 애니메이션 지속 시간 (마지막 줄)</value>
|
<value>최종 라인 기간</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SettingsPageScrollDuration.Header" xml:space="preserve">
|
<data name="SettingsPageScrollDuration.Header" xml:space="preserve">
|
||||||
<value>가사 스크롤 애니메이션 지속 시간 (현재 줄)</value>
|
<value>현재 라인 기간</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SettingsPageScrollEasing.Header" xml:space="preserve">
|
<data name="SettingsPageScrollEasing.Header" xml:space="preserve">
|
||||||
<value>가사 스크롤링 애니메이션 유형</value>
|
<value>가사 스크롤링 애니메이션 유형</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPageScrollTopDelay.Header" xml:space="preserve">
|
||||||
|
<value>첫 번째 줄 지연</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageScrollTopDuration.Header" xml:space="preserve">
|
<data name="SettingsPageScrollTopDuration.Header" xml:space="preserve">
|
||||||
<value>가사 스크롤 애니메이션 지속 시간 (첫 번째 줄)</value>
|
<value>첫 번째 줄의 기간</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SettingsPageServerTestButton.Content" xml:space="preserve">
|
<data name="SettingsPageServerTestButton.Content" xml:space="preserve">
|
||||||
<value>테스트 서버</value>
|
<value>테스트 서버</value>
|
||||||
@@ -913,6 +967,12 @@
|
|||||||
<data name="SettingsPageSettingsManager.Header" xml:space="preserve">
|
<data name="SettingsPageSettingsManager.Header" xml:space="preserve">
|
||||||
<value>설정 관리자</value>
|
<value>설정 관리자</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPageShortcutRegFailInfo" xml:space="preserve">
|
||||||
|
<value>이 핫키는 성공적으로 등록되지 않았습니다</value>
|
||||||
|
</data>
|
||||||
|
<data name="SettingsPageShortcutRegSuccessInfo" xml:space="preserve">
|
||||||
|
<value>이 핫키는 성공적으로 등록되었습니다</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageSliderPrefix.Text" xml:space="preserve">
|
<data name="SettingsPageSliderPrefix.Text" xml:space="preserve">
|
||||||
<value>현재 가치 : </value>
|
<value>현재 가치 : </value>
|
||||||
</data>
|
</data>
|
||||||
@@ -952,6 +1012,9 @@
|
|||||||
<data name="SettingsPageTitleBarType.Header" xml:space="preserve">
|
<data name="SettingsPageTitleBarType.Header" xml:space="preserve">
|
||||||
<value>제목 바 크기</value>
|
<value>제목 바 크기</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPageToggleHotKey.Header" xml:space="preserve">
|
||||||
|
<value>바로 가기 키를 자르고 잘라냅니다</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageTranslation.Text" xml:space="preserve">
|
<data name="SettingsPageTranslation.Text" xml:space="preserve">
|
||||||
<value>가사 번역</value>
|
<value>가사 번역</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -970,6 +1033,9 @@
|
|||||||
<data name="SystemTrayExit.Text" xml:space="preserve">
|
<data name="SystemTrayExit.Text" xml:space="preserve">
|
||||||
<value>프로그램을 종료하십시오</value>
|
<value>프로그램을 종료하십시오</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SystemTrayLyrics.Text" xml:space="preserve">
|
||||||
|
<value>가사 창을 여세요</value>
|
||||||
|
</data>
|
||||||
<data name="SystemTrayMusicGallery.Text" xml:space="preserve">
|
<data name="SystemTrayMusicGallery.Text" xml:space="preserve">
|
||||||
<value>오픈 음악 갤러리</value>
|
<value>오픈 음악 갤러리</value>
|
||||||
</data>
|
</data>
|
||||||
|
|||||||
@@ -129,6 +129,9 @@
|
|||||||
<data name="AllLyricsSettingsControlDock.Content" xml:space="preserve">
|
<data name="AllLyricsSettingsControlDock.Content" xml:space="preserve">
|
||||||
<value>停靠模式</value>
|
<value>停靠模式</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="AllLyricsSettingsControlPictureInPicture.Content" xml:space="preserve">
|
||||||
|
<value>画中画模式</value>
|
||||||
|
</data>
|
||||||
<data name="AllLyricsSettingsControlStandard.Content" xml:space="preserve">
|
<data name="AllLyricsSettingsControlStandard.Content" xml:space="preserve">
|
||||||
<value>标准模式</value>
|
<value>标准模式</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -147,9 +150,6 @@
|
|||||||
<data name="BaseWindowMiniFlyoutItem.Text" xml:space="preserve">
|
<data name="BaseWindowMiniFlyoutItem.Text" xml:space="preserve">
|
||||||
<value>画中画模式</value>
|
<value>画中画模式</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="BaseWindowUnMiniFlyoutItem.Text" xml:space="preserve">
|
|
||||||
<value>退出画中画模式</value>
|
|
||||||
</data>
|
|
||||||
<data name="Cancel" xml:space="preserve">
|
<data name="Cancel" xml:space="preserve">
|
||||||
<value>取消</value>
|
<value>取消</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -175,7 +175,7 @@
|
|||||||
<value>停靠模式</value>
|
<value>停靠模式</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="HostWindowLockToolTip.Text" xml:space="preserve">
|
<data name="HostWindowLockToolTip.Text" xml:space="preserve">
|
||||||
<value>锁定后解锁,请转到系统托盘解锁或按下</value>
|
<value>锁定</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="HostWindowMoreButtonToolTip.Content" xml:space="preserve">
|
<data name="HostWindowMoreButtonToolTip.Content" xml:space="preserve">
|
||||||
<value>更多</value>
|
<value>更多</value>
|
||||||
@@ -216,12 +216,12 @@
|
|||||||
<data name="LyricsNotFound" xml:space="preserve">
|
<data name="LyricsNotFound" xml:space="preserve">
|
||||||
<value>未找到歌词</value>
|
<value>未找到歌词</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LyricsPageDisplayTypeButtonToolTip.Content" xml:space="preserve">
|
|
||||||
<value>显示类型</value>
|
|
||||||
</data>
|
|
||||||
<data name="LyricsPageLyricsProviderPrefix.Header" xml:space="preserve">
|
<data name="LyricsPageLyricsProviderPrefix.Header" xml:space="preserve">
|
||||||
<value>歌词来源</value>
|
<value>歌词来源</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="LyricsPageLyricsSettingsButtonToolTip.Content" xml:space="preserve">
|
||||||
|
<value>歌词样式与效果快捷设置</value>
|
||||||
|
</data>
|
||||||
<data name="LyricsPagePlaybackSourceButtonToolTip.Content" xml:space="preserve">
|
<data name="LyricsPagePlaybackSourceButtonToolTip.Content" xml:space="preserve">
|
||||||
<value>播放源快捷设置</value>
|
<value>播放源快捷设置</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -270,9 +270,6 @@
|
|||||||
<data name="MainPageDesktopLyricsToggler.ToolTipService.ToolTip" xml:space="preserve">
|
<data name="MainPageDesktopLyricsToggler.ToolTipService.ToolTip" xml:space="preserve">
|
||||||
<value>切换到桌面歌词模式</value>
|
<value>切换到桌面歌词模式</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="MainPageDisplayTypeSwitcher.ToolTipService.ToolTip" xml:space="preserve">
|
|
||||||
<value>切换显示模式</value>
|
|
||||||
</data>
|
|
||||||
<data name="MainPageEnterImmersiveModeHint" xml:space="preserve">
|
<data name="MainPageEnterImmersiveModeHint" xml:space="preserve">
|
||||||
<value>再次悬停以显示切换按钮</value>
|
<value>再次悬停以显示切换按钮</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -433,9 +430,15 @@
|
|||||||
<data name="SettingsPageAlbumRadius.Header" xml:space="preserve">
|
<data name="SettingsPageAlbumRadius.Header" xml:space="preserve">
|
||||||
<value>圆角半径</value>
|
<value>圆角半径</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPageAlbumShadowAmount.Header" xml:space="preserve">
|
||||||
|
<value>阴影扩散程度</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageAlbumStyle.Content" xml:space="preserve">
|
<data name="SettingsPageAlbumStyle.Content" xml:space="preserve">
|
||||||
<value>专辑区域样式</value>
|
<value>专辑区域样式</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPageAmount.Header" xml:space="preserve">
|
||||||
|
<value>量</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageApp.Content" xml:space="preserve">
|
<data name="SettingsPageApp.Content" xml:space="preserve">
|
||||||
<value>应用外观与行为</value>
|
<value>应用外观与行为</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -451,6 +454,12 @@
|
|||||||
<data name="SettingsPageAppDock.Text" xml:space="preserve">
|
<data name="SettingsPageAppDock.Text" xml:space="preserve">
|
||||||
<value>停靠模式</value>
|
<value>停靠模式</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPageAppPictureInPicture.Text" xml:space="preserve">
|
||||||
|
<value>画中画模式</value>
|
||||||
|
</data>
|
||||||
|
<data name="SettingsPageAppStandard.Text" xml:space="preserve">
|
||||||
|
<value>标准模式</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageAutoLock.Header" xml:space="preserve">
|
<data name="SettingsPageAutoLock.Header" xml:space="preserve">
|
||||||
<value>启动桌面模式时随即锁定窗口</value>
|
<value>启动桌面模式时随即锁定窗口</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -466,6 +475,9 @@
|
|||||||
<data name="SettingsPageAutoStartInAppLyrics.Content" xml:space="preserve">
|
<data name="SettingsPageAutoStartInAppLyrics.Content" xml:space="preserve">
|
||||||
<value>启动标准模式</value>
|
<value>启动标准模式</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPageAutoStartPIPLyrics.Content" xml:space="preserve">
|
||||||
|
<value>启动画中画模式</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageAutoStartWindow.Header" xml:space="preserve">
|
<data name="SettingsPageAutoStartWindow.Header" xml:space="preserve">
|
||||||
<value>启动应用时</value>
|
<value>启动应用时</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -502,6 +514,9 @@
|
|||||||
<data name="SettingsPageDiscord.Header" xml:space="preserve">
|
<data name="SettingsPageDiscord.Header" xml:space="preserve">
|
||||||
<value>Discord</value>
|
<value>Discord</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPageDisplayTypeSwitcher.Header" xml:space="preserve">
|
||||||
|
<value>歌词专辑布局模式</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageDockMonitor.Header" xml:space="preserve">
|
<data name="SettingsPageDockMonitor.Header" xml:space="preserve">
|
||||||
<value>目标显示器</value>
|
<value>目标显示器</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -559,6 +574,9 @@
|
|||||||
<data name="SettingsPageEN.Content" xml:space="preserve">
|
<data name="SettingsPageEN.Content" xml:space="preserve">
|
||||||
<value>English</value>
|
<value>English</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPageExitOnLyricsWindowClosed.Header" xml:space="preserve">
|
||||||
|
<value>关闭歌词窗口时退出程序</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageExportSettingsButton.Content" xml:space="preserve">
|
<data name="SettingsPageExportSettingsButton.Content" xml:space="preserve">
|
||||||
<value>导出设置</value>
|
<value>导出设置</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -571,9 +589,15 @@
|
|||||||
<data name="SettingsPageFAQ.Header" xml:space="preserve">
|
<data name="SettingsPageFAQ.Header" xml:space="preserve">
|
||||||
<value>常见问题与解答</value>
|
<value>常见问题与解答</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPageFixedTimeStep.Header" xml:space="preserve">
|
||||||
|
<value>固定时间步长渲染</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageFollowSystem.Content" xml:space="preserve">
|
<data name="SettingsPageFollowSystem.Content" xml:space="preserve">
|
||||||
<value>跟随系统</value>
|
<value>跟随系统</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPageFPS.Header" xml:space="preserve">
|
||||||
|
<value>渲染帧率</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageGitHub.ActionIconToolTip" xml:space="preserve">
|
<data name="SettingsPageGitHub.ActionIconToolTip" xml:space="preserve">
|
||||||
<value>在新窗口中打开</value>
|
<value>在新窗口中打开</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -755,7 +779,7 @@
|
|||||||
<value>辉光效果</value>
|
<value>辉光效果</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SettingsPageLyricsHighlightScope.Header" xml:space="preserve">
|
<data name="SettingsPageLyricsHighlightScope.Header" xml:space="preserve">
|
||||||
<value>高亮显示范围</value>
|
<value>原文高亮显示范围</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SettingsPageLyricsLeft.Content" xml:space="preserve">
|
<data name="SettingsPageLyricsLeft.Content" xml:space="preserve">
|
||||||
<value>靠左</value>
|
<value>靠左</value>
|
||||||
@@ -763,6 +787,9 @@
|
|||||||
<data name="SettingsPageLyricsLight.Content" xml:space="preserve">
|
<data name="SettingsPageLyricsLight.Content" xml:space="preserve">
|
||||||
<value>细体</value>
|
<value>细体</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPageLyricsLineFade.Header" xml:space="preserve">
|
||||||
|
<value>播放区域边缘渐变</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageLyricsLineSpacingFactor.Header" xml:space="preserve">
|
<data name="SettingsPageLyricsLineSpacingFactor.Header" xml:space="preserve">
|
||||||
<value>行间距</value>
|
<value>行间距</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -799,6 +826,9 @@
|
|||||||
<data name="SettingsPageLyricsSemiLight.Content" xml:space="preserve">
|
<data name="SettingsPageLyricsSemiLight.Content" xml:space="preserve">
|
||||||
<value>次细</value>
|
<value>次细</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPageLyricsShadow.Header" xml:space="preserve">
|
||||||
|
<value>阴影</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageLyricsStrokeFontColor.Header" xml:space="preserve">
|
<data name="SettingsPageLyricsStrokeFontColor.Header" xml:space="preserve">
|
||||||
<value>歌词描边颜色</value>
|
<value>歌词描边颜色</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -814,6 +844,9 @@
|
|||||||
<data name="SettingsPageLyricsTimelineThreshold.Header" xml:space="preserve">
|
<data name="SettingsPageLyricsTimelineThreshold.Header" xml:space="preserve">
|
||||||
<value>歌词时间轴同步阈值</value>
|
<value>歌词时间轴同步阈值</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPageLyricsTranslationHighlight.Header" xml:space="preserve">
|
||||||
|
<value>翻译高亮</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageLyricsTranslationSeparator.Header" xml:space="preserve">
|
<data name="SettingsPageLyricsTranslationSeparator.Header" xml:space="preserve">
|
||||||
<value>原文译文分隔符</value>
|
<value>原文译文分隔符</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -841,6 +874,12 @@
|
|||||||
<data name="SettingsPageMusicLib.Header" xml:space="preserve">
|
<data name="SettingsPageMusicLib.Header" xml:space="preserve">
|
||||||
<value>本地媒体库</value>
|
<value>本地媒体库</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPageMusicLibRealTimeWatch.Header" xml:space="preserve">
|
||||||
|
<value>实时监听文件变化</value>
|
||||||
|
</data>
|
||||||
|
<data name="SettingsPageNextSongHotKey.Header" xml:space="preserve">
|
||||||
|
<value>下一首曲目快捷键</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageNoBackdrop.Content" xml:space="preserve">
|
<data name="SettingsPageNoBackdrop.Content" xml:space="preserve">
|
||||||
<value>无</value>
|
<value>无</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -865,9 +904,18 @@
|
|||||||
<data name="SettingsPagePlaybackNotFound.Text" xml:space="preserve">
|
<data name="SettingsPagePlaybackNotFound.Text" xml:space="preserve">
|
||||||
<value>没有捕获的播放源</value>
|
<value>没有捕获的播放源</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPagePlaybackShortcut.Text" xml:space="preserve">
|
||||||
|
<value>播放</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPagePlayingMockMusicButton.Content" xml:space="preserve">
|
<data name="SettingsPagePlayingMockMusicButton.Content" xml:space="preserve">
|
||||||
<value>在 “soundcloud.com” 上播放 “Cut to the Feeling”</value>
|
<value>在 “soundcloud.com” 上播放 “Cut to the Feeling”</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPagePlayOrPauseSongHotKey.Header" xml:space="preserve">
|
||||||
|
<value>播放与暂停快捷键</value>
|
||||||
|
</data>
|
||||||
|
<data name="SettingsPagePreviousSongHotKey.Header" xml:space="preserve">
|
||||||
|
<value>上一首曲目快捷键</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageQQGroup.Header" xml:space="preserve">
|
<data name="SettingsPageQQGroup.Header" xml:space="preserve">
|
||||||
<value>QQ 反馈交流群</value>
|
<value>QQ 反馈交流群</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -889,17 +937,23 @@
|
|||||||
<data name="SettingsPageScope.Header" xml:space="preserve">
|
<data name="SettingsPageScope.Header" xml:space="preserve">
|
||||||
<value>范围</value>
|
<value>范围</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPageScrollBottomDelay.Header" xml:space="preserve">
|
||||||
|
<value>尾行延时</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageScrollBottomDuration.Header" xml:space="preserve">
|
<data name="SettingsPageScrollBottomDuration.Header" xml:space="preserve">
|
||||||
<value>歌词滚动动画持续时间(最后一行)</value>
|
<value>尾行持续时间</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SettingsPageScrollDuration.Header" xml:space="preserve">
|
<data name="SettingsPageScrollDuration.Header" xml:space="preserve">
|
||||||
<value>歌词滚动动画持续时间(当前行)</value>
|
<value>当前行持续时间</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SettingsPageScrollEasing.Header" xml:space="preserve">
|
<data name="SettingsPageScrollEasing.Header" xml:space="preserve">
|
||||||
<value>歌词滚动动画类型</value>
|
<value>歌词滚动动画类型</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPageScrollTopDelay.Header" xml:space="preserve">
|
||||||
|
<value>首行延时</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageScrollTopDuration.Header" xml:space="preserve">
|
<data name="SettingsPageScrollTopDuration.Header" xml:space="preserve">
|
||||||
<value>歌词滚动动画持续时间(第一行)</value>
|
<value>首行持续时间</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SettingsPageServerTestButton.Content" xml:space="preserve">
|
<data name="SettingsPageServerTestButton.Content" xml:space="preserve">
|
||||||
<value>测试服务器</value>
|
<value>测试服务器</value>
|
||||||
@@ -913,6 +967,12 @@
|
|||||||
<data name="SettingsPageSettingsManager.Header" xml:space="preserve">
|
<data name="SettingsPageSettingsManager.Header" xml:space="preserve">
|
||||||
<value>设置管理器</value>
|
<value>设置管理器</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPageShortcutRegFailInfo" xml:space="preserve">
|
||||||
|
<value>该热键未成功注册</value>
|
||||||
|
</data>
|
||||||
|
<data name="SettingsPageShortcutRegSuccessInfo" xml:space="preserve">
|
||||||
|
<value>该热键已成功注册</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageSliderPrefix.Text" xml:space="preserve">
|
<data name="SettingsPageSliderPrefix.Text" xml:space="preserve">
|
||||||
<value>当前值: </value>
|
<value>当前值: </value>
|
||||||
</data>
|
</data>
|
||||||
@@ -952,6 +1012,9 @@
|
|||||||
<data name="SettingsPageTitleBarType.Header" xml:space="preserve">
|
<data name="SettingsPageTitleBarType.Header" xml:space="preserve">
|
||||||
<value>标题栏大小</value>
|
<value>标题栏大小</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPageToggleHotKey.Header" xml:space="preserve">
|
||||||
|
<value>切入与切出快捷键</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageTranslation.Text" xml:space="preserve">
|
<data name="SettingsPageTranslation.Text" xml:space="preserve">
|
||||||
<value>歌词翻译</value>
|
<value>歌词翻译</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -970,6 +1033,9 @@
|
|||||||
<data name="SystemTrayExit.Text" xml:space="preserve">
|
<data name="SystemTrayExit.Text" xml:space="preserve">
|
||||||
<value>退出程序</value>
|
<value>退出程序</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SystemTrayLyrics.Text" xml:space="preserve">
|
||||||
|
<value>打开歌词窗口</value>
|
||||||
|
</data>
|
||||||
<data name="SystemTrayMusicGallery.Text" xml:space="preserve">
|
<data name="SystemTrayMusicGallery.Text" xml:space="preserve">
|
||||||
<value>打开音乐库</value>
|
<value>打开音乐库</value>
|
||||||
</data>
|
</data>
|
||||||
|
|||||||
@@ -129,6 +129,9 @@
|
|||||||
<data name="AllLyricsSettingsControlDock.Content" xml:space="preserve">
|
<data name="AllLyricsSettingsControlDock.Content" xml:space="preserve">
|
||||||
<value>停靠模式</value>
|
<value>停靠模式</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="AllLyricsSettingsControlPictureInPicture.Content" xml:space="preserve">
|
||||||
|
<value>畫中畫模式</value>
|
||||||
|
</data>
|
||||||
<data name="AllLyricsSettingsControlStandard.Content" xml:space="preserve">
|
<data name="AllLyricsSettingsControlStandard.Content" xml:space="preserve">
|
||||||
<value>標準模式</value>
|
<value>標準模式</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -147,9 +150,6 @@
|
|||||||
<data name="BaseWindowMiniFlyoutItem.Text" xml:space="preserve">
|
<data name="BaseWindowMiniFlyoutItem.Text" xml:space="preserve">
|
||||||
<value>畫中畫模式</value>
|
<value>畫中畫模式</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="BaseWindowUnMiniFlyoutItem.Text" xml:space="preserve">
|
|
||||||
<value>退出畫中畫模式</value>
|
|
||||||
</data>
|
|
||||||
<data name="Cancel" xml:space="preserve">
|
<data name="Cancel" xml:space="preserve">
|
||||||
<value>取消</value>
|
<value>取消</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -175,7 +175,7 @@
|
|||||||
<value>停靠模式</value>
|
<value>停靠模式</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="HostWindowLockToolTip.Text" xml:space="preserve">
|
<data name="HostWindowLockToolTip.Text" xml:space="preserve">
|
||||||
<value>鎖定後解鎖,請轉到系統托盤解鎖或按下</value>
|
<value>鎖定</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="HostWindowMoreButtonToolTip.Content" xml:space="preserve">
|
<data name="HostWindowMoreButtonToolTip.Content" xml:space="preserve">
|
||||||
<value>更多</value>
|
<value>更多</value>
|
||||||
@@ -216,12 +216,12 @@
|
|||||||
<data name="LyricsNotFound" xml:space="preserve">
|
<data name="LyricsNotFound" xml:space="preserve">
|
||||||
<value>找不到歌詞</value>
|
<value>找不到歌詞</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LyricsPageDisplayTypeButtonToolTip.Content" xml:space="preserve">
|
|
||||||
<value>顯示類型</value>
|
|
||||||
</data>
|
|
||||||
<data name="LyricsPageLyricsProviderPrefix.Header" xml:space="preserve">
|
<data name="LyricsPageLyricsProviderPrefix.Header" xml:space="preserve">
|
||||||
<value>歌詞來源</value>
|
<value>歌詞來源</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="LyricsPageLyricsSettingsButtonToolTip.Content" xml:space="preserve">
|
||||||
|
<value>歌詞樣式與效果快捷設置</value>
|
||||||
|
</data>
|
||||||
<data name="LyricsPagePlaybackSourceButtonToolTip.Content" xml:space="preserve">
|
<data name="LyricsPagePlaybackSourceButtonToolTip.Content" xml:space="preserve">
|
||||||
<value>播放源快捷設置</value>
|
<value>播放源快捷設置</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -270,9 +270,6 @@
|
|||||||
<data name="MainPageDesktopLyricsToggler.ToolTipService.ToolTip" xml:space="preserve">
|
<data name="MainPageDesktopLyricsToggler.ToolTipService.ToolTip" xml:space="preserve">
|
||||||
<value>切換到桌面歌詞模式</value>
|
<value>切換到桌面歌詞模式</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="MainPageDisplayTypeSwitcher.ToolTipService.ToolTip" xml:space="preserve">
|
|
||||||
<value>切換顯示模式</value>
|
|
||||||
</data>
|
|
||||||
<data name="MainPageEnterImmersiveModeHint" xml:space="preserve">
|
<data name="MainPageEnterImmersiveModeHint" xml:space="preserve">
|
||||||
<value>再次懸停以顯示切換按鈕</value>
|
<value>再次懸停以顯示切換按鈕</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -433,9 +430,15 @@
|
|||||||
<data name="SettingsPageAlbumRadius.Header" xml:space="preserve">
|
<data name="SettingsPageAlbumRadius.Header" xml:space="preserve">
|
||||||
<value>圓角半徑</value>
|
<value>圓角半徑</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPageAlbumShadowAmount.Header" xml:space="preserve">
|
||||||
|
<value>陰影擴散程度</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageAlbumStyle.Content" xml:space="preserve">
|
<data name="SettingsPageAlbumStyle.Content" xml:space="preserve">
|
||||||
<value>專輯區域樣式</value>
|
<value>專輯區域樣式</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPageAmount.Header" xml:space="preserve">
|
||||||
|
<value>量</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageApp.Content" xml:space="preserve">
|
<data name="SettingsPageApp.Content" xml:space="preserve">
|
||||||
<value>應用外觀與行為</value>
|
<value>應用外觀與行為</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -451,6 +454,12 @@
|
|||||||
<data name="SettingsPageAppDock.Text" xml:space="preserve">
|
<data name="SettingsPageAppDock.Text" xml:space="preserve">
|
||||||
<value>停靠模式</value>
|
<value>停靠模式</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPageAppPictureInPicture.Text" xml:space="preserve">
|
||||||
|
<value>畫中畫模式</value>
|
||||||
|
</data>
|
||||||
|
<data name="SettingsPageAppStandard.Text" xml:space="preserve">
|
||||||
|
<value>標準模式</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageAutoLock.Header" xml:space="preserve">
|
<data name="SettingsPageAutoLock.Header" xml:space="preserve">
|
||||||
<value>啟動桌面模式時隨即鎖定窗口</value>
|
<value>啟動桌面模式時隨即鎖定窗口</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -466,6 +475,9 @@
|
|||||||
<data name="SettingsPageAutoStartInAppLyrics.Content" xml:space="preserve">
|
<data name="SettingsPageAutoStartInAppLyrics.Content" xml:space="preserve">
|
||||||
<value>啟動標準模式</value>
|
<value>啟動標準模式</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPageAutoStartPIPLyrics.Content" xml:space="preserve">
|
||||||
|
<value>啟動畫中畫模式</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageAutoStartWindow.Header" xml:space="preserve">
|
<data name="SettingsPageAutoStartWindow.Header" xml:space="preserve">
|
||||||
<value>啟動應用程式時</value>
|
<value>啟動應用程式時</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -502,6 +514,9 @@
|
|||||||
<data name="SettingsPageDiscord.Header" xml:space="preserve">
|
<data name="SettingsPageDiscord.Header" xml:space="preserve">
|
||||||
<value>Discord</value>
|
<value>Discord</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPageDisplayTypeSwitcher.Header" xml:space="preserve">
|
||||||
|
<value>歌詞專輯佈局模式</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageDockMonitor.Header" xml:space="preserve">
|
<data name="SettingsPageDockMonitor.Header" xml:space="preserve">
|
||||||
<value>目標顯示器</value>
|
<value>目標顯示器</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -559,6 +574,9 @@
|
|||||||
<data name="SettingsPageEN.Content" xml:space="preserve">
|
<data name="SettingsPageEN.Content" xml:space="preserve">
|
||||||
<value>English</value>
|
<value>English</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPageExitOnLyricsWindowClosed.Header" xml:space="preserve">
|
||||||
|
<value>關閉歌詞視窗時退出程式</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageExportSettingsButton.Content" xml:space="preserve">
|
<data name="SettingsPageExportSettingsButton.Content" xml:space="preserve">
|
||||||
<value>導出設置</value>
|
<value>導出設置</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -571,9 +589,15 @@
|
|||||||
<data name="SettingsPageFAQ.Header" xml:space="preserve">
|
<data name="SettingsPageFAQ.Header" xml:space="preserve">
|
||||||
<value>常見問題與解答</value>
|
<value>常見問題與解答</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPageFixedTimeStep.Header" xml:space="preserve">
|
||||||
|
<value>固定時間步長渲染</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageFollowSystem.Content" xml:space="preserve">
|
<data name="SettingsPageFollowSystem.Content" xml:space="preserve">
|
||||||
<value>跟隨系統</value>
|
<value>跟隨系統</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPageFPS.Header" xml:space="preserve">
|
||||||
|
<value>渲染幀率</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageGitHub.ActionIconToolTip" xml:space="preserve">
|
<data name="SettingsPageGitHub.ActionIconToolTip" xml:space="preserve">
|
||||||
<value>在新視窗中開啟</value>
|
<value>在新視窗中開啟</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -755,7 +779,7 @@
|
|||||||
<value>輝光效果</value>
|
<value>輝光效果</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SettingsPageLyricsHighlightScope.Header" xml:space="preserve">
|
<data name="SettingsPageLyricsHighlightScope.Header" xml:space="preserve">
|
||||||
<value>高亮顯示範圍</value>
|
<value>原文高亮顯示範圍</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SettingsPageLyricsLeft.Content" xml:space="preserve">
|
<data name="SettingsPageLyricsLeft.Content" xml:space="preserve">
|
||||||
<value>靠左</value>
|
<value>靠左</value>
|
||||||
@@ -763,6 +787,9 @@
|
|||||||
<data name="SettingsPageLyricsLight.Content" xml:space="preserve">
|
<data name="SettingsPageLyricsLight.Content" xml:space="preserve">
|
||||||
<value>細體</value>
|
<value>細體</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPageLyricsLineFade.Header" xml:space="preserve">
|
||||||
|
<value>播放區域邊緣漸層</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageLyricsLineSpacingFactor.Header" xml:space="preserve">
|
<data name="SettingsPageLyricsLineSpacingFactor.Header" xml:space="preserve">
|
||||||
<value>行間距</value>
|
<value>行間距</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -799,6 +826,9 @@
|
|||||||
<data name="SettingsPageLyricsSemiLight.Content" xml:space="preserve">
|
<data name="SettingsPageLyricsSemiLight.Content" xml:space="preserve">
|
||||||
<value>次細</value>
|
<value>次細</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPageLyricsShadow.Header" xml:space="preserve">
|
||||||
|
<value>陰影</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageLyricsStrokeFontColor.Header" xml:space="preserve">
|
<data name="SettingsPageLyricsStrokeFontColor.Header" xml:space="preserve">
|
||||||
<value>歌詞描邊顏色</value>
|
<value>歌詞描邊顏色</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -814,6 +844,9 @@
|
|||||||
<data name="SettingsPageLyricsTimelineThreshold.Header" xml:space="preserve">
|
<data name="SettingsPageLyricsTimelineThreshold.Header" xml:space="preserve">
|
||||||
<value>歌詞時間軌同步閾值</value>
|
<value>歌詞時間軌同步閾值</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPageLyricsTranslationHighlight.Header" xml:space="preserve">
|
||||||
|
<value>翻譯高亮</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageLyricsTranslationSeparator.Header" xml:space="preserve">
|
<data name="SettingsPageLyricsTranslationSeparator.Header" xml:space="preserve">
|
||||||
<value>原文譯文分隔符</value>
|
<value>原文譯文分隔符</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -841,6 +874,12 @@
|
|||||||
<data name="SettingsPageMusicLib.Header" xml:space="preserve">
|
<data name="SettingsPageMusicLib.Header" xml:space="preserve">
|
||||||
<value>本地音樂資料庫</value>
|
<value>本地音樂資料庫</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPageMusicLibRealTimeWatch.Header" xml:space="preserve">
|
||||||
|
<value>實時監聽文件變化</value>
|
||||||
|
</data>
|
||||||
|
<data name="SettingsPageNextSongHotKey.Header" xml:space="preserve">
|
||||||
|
<value>下一首曲目快捷鍵</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageNoBackdrop.Content" xml:space="preserve">
|
<data name="SettingsPageNoBackdrop.Content" xml:space="preserve">
|
||||||
<value>無</value>
|
<value>無</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -865,9 +904,18 @@
|
|||||||
<data name="SettingsPagePlaybackNotFound.Text" xml:space="preserve">
|
<data name="SettingsPagePlaybackNotFound.Text" xml:space="preserve">
|
||||||
<value>沒有捕獲的播放源</value>
|
<value>沒有捕獲的播放源</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPagePlaybackShortcut.Text" xml:space="preserve">
|
||||||
|
<value>播放</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPagePlayingMockMusicButton.Content" xml:space="preserve">
|
<data name="SettingsPagePlayingMockMusicButton.Content" xml:space="preserve">
|
||||||
<value>在 “soundcloud.com” 上播放 “Cut to the Feeling”</value>
|
<value>在 “soundcloud.com” 上播放 “Cut to the Feeling”</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPagePlayOrPauseSongHotKey.Header" xml:space="preserve">
|
||||||
|
<value>播放與暫停快捷鍵</value>
|
||||||
|
</data>
|
||||||
|
<data name="SettingsPagePreviousSongHotKey.Header" xml:space="preserve">
|
||||||
|
<value>上一首曲目快捷鍵</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageQQGroup.Header" xml:space="preserve">
|
<data name="SettingsPageQQGroup.Header" xml:space="preserve">
|
||||||
<value>QQ 回饋交流群</value>
|
<value>QQ 回饋交流群</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -889,17 +937,23 @@
|
|||||||
<data name="SettingsPageScope.Header" xml:space="preserve">
|
<data name="SettingsPageScope.Header" xml:space="preserve">
|
||||||
<value>範圍</value>
|
<value>範圍</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPageScrollBottomDelay.Header" xml:space="preserve">
|
||||||
|
<value>尾行延時</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageScrollBottomDuration.Header" xml:space="preserve">
|
<data name="SettingsPageScrollBottomDuration.Header" xml:space="preserve">
|
||||||
<value>歌詞滾動動畫持續時間(最後一行)</value>
|
<value>尾行持續時間</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SettingsPageScrollDuration.Header" xml:space="preserve">
|
<data name="SettingsPageScrollDuration.Header" xml:space="preserve">
|
||||||
<value>歌詞滾動動畫持續時間(當前行)</value>
|
<value>當前行持續時間</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SettingsPageScrollEasing.Header" xml:space="preserve">
|
<data name="SettingsPageScrollEasing.Header" xml:space="preserve">
|
||||||
<value>歌詞滾動動畫類型</value>
|
<value>歌詞滾動動畫類型</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPageScrollTopDelay.Header" xml:space="preserve">
|
||||||
|
<value>首行延時</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageScrollTopDuration.Header" xml:space="preserve">
|
<data name="SettingsPageScrollTopDuration.Header" xml:space="preserve">
|
||||||
<value>歌詞滾動動畫持續時間(第一行)</value>
|
<value>首行持續時間</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SettingsPageServerTestButton.Content" xml:space="preserve">
|
<data name="SettingsPageServerTestButton.Content" xml:space="preserve">
|
||||||
<value>測試服務器</value>
|
<value>測試服務器</value>
|
||||||
@@ -913,6 +967,12 @@
|
|||||||
<data name="SettingsPageSettingsManager.Header" xml:space="preserve">
|
<data name="SettingsPageSettingsManager.Header" xml:space="preserve">
|
||||||
<value>設置管理器</value>
|
<value>設置管理器</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPageShortcutRegFailInfo" xml:space="preserve">
|
||||||
|
<value>該熱鍵未成功註冊</value>
|
||||||
|
</data>
|
||||||
|
<data name="SettingsPageShortcutRegSuccessInfo" xml:space="preserve">
|
||||||
|
<value>該熱鍵已成功註冊</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageSliderPrefix.Text" xml:space="preserve">
|
<data name="SettingsPageSliderPrefix.Text" xml:space="preserve">
|
||||||
<value>目前值: </value>
|
<value>目前值: </value>
|
||||||
</data>
|
</data>
|
||||||
@@ -952,6 +1012,9 @@
|
|||||||
<data name="SettingsPageTitleBarType.Header" xml:space="preserve">
|
<data name="SettingsPageTitleBarType.Header" xml:space="preserve">
|
||||||
<value>標題列大小</value>
|
<value>標題列大小</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsPageToggleHotKey.Header" xml:space="preserve">
|
||||||
|
<value>切入與切出快捷鍵</value>
|
||||||
|
</data>
|
||||||
<data name="SettingsPageTranslation.Text" xml:space="preserve">
|
<data name="SettingsPageTranslation.Text" xml:space="preserve">
|
||||||
<value>歌詞翻譯</value>
|
<value>歌詞翻譯</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -970,6 +1033,9 @@
|
|||||||
<data name="SystemTrayExit.Text" xml:space="preserve">
|
<data name="SystemTrayExit.Text" xml:space="preserve">
|
||||||
<value>退出程序</value>
|
<value>退出程序</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SystemTrayLyrics.Text" xml:space="preserve">
|
||||||
|
<value>開啟歌詞視窗</value>
|
||||||
|
</data>
|
||||||
<data name="SystemTrayMusicGallery.Text" xml:space="preserve">
|
<data name="SystemTrayMusicGallery.Text" xml:space="preserve">
|
||||||
<value>開啟音樂庫</value>
|
<value>開啟音樂庫</value>
|
||||||
</data>
|
</data>
|
||||||
|
|||||||
@@ -1,6 +1,11 @@
|
|||||||
using BetterLyrics.WinUI3.Models.Settings;
|
using BetterLyrics.WinUI3.Enums;
|
||||||
|
using BetterLyrics.WinUI3.Models;
|
||||||
|
using BetterLyrics.WinUI3.Models.Settings;
|
||||||
|
using BetterLyrics.WinUI3.Services.LiveStatesService;
|
||||||
using BetterLyrics.WinUI3.Services.SettingsService;
|
using BetterLyrics.WinUI3.Services.SettingsService;
|
||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
|
using CommunityToolkit.Mvvm.Messaging;
|
||||||
|
using CommunityToolkit.Mvvm.Messaging.Messages;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@@ -9,17 +14,33 @@ using System.Threading.Tasks;
|
|||||||
|
|
||||||
namespace BetterLyrics.WinUI3.ViewModels
|
namespace BetterLyrics.WinUI3.ViewModels
|
||||||
{
|
{
|
||||||
public partial class AllLyricsSettingsControlViewModel : BaseViewModel
|
public partial class AllLyricsSettingsControlViewModel : BaseViewModel,
|
||||||
|
IRecipient<PropertyChangedMessage<LyricsWindowMode>>
|
||||||
{
|
{
|
||||||
private readonly ISettingsService _settingsService;
|
private readonly ISettingsService _settingsService;
|
||||||
|
|
||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
public partial AppSettings AppSettings { get; set; }
|
public partial AppSettings AppSettings { get; set; }
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
public partial int SelectedTabIndex { get; set; } = 0;
|
||||||
|
|
||||||
public AllLyricsSettingsControlViewModel(ISettingsService settingsService)
|
public AllLyricsSettingsControlViewModel(ISettingsService settingsService)
|
||||||
{
|
{
|
||||||
_settingsService = settingsService;
|
_settingsService = settingsService;
|
||||||
|
|
||||||
AppSettings = _settingsService.AppSettings;
|
AppSettings = _settingsService.AppSettings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Receive(PropertyChangedMessage<LyricsWindowMode> message)
|
||||||
|
{
|
||||||
|
if (message.Sender is LiveStates)
|
||||||
|
{
|
||||||
|
if (message.PropertyName == nameof(LiveStates.CurrentLyricsWindowMode))
|
||||||
|
{
|
||||||
|
SelectedTabIndex = (int)message.NewValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ using BetterLyrics.WinUI3.Enums;
|
|||||||
using BetterLyrics.WinUI3.Helper;
|
using BetterLyrics.WinUI3.Helper;
|
||||||
using BetterLyrics.WinUI3.Models;
|
using BetterLyrics.WinUI3.Models;
|
||||||
using BetterLyrics.WinUI3.Models.Settings;
|
using BetterLyrics.WinUI3.Models.Settings;
|
||||||
|
using BetterLyrics.WinUI3.Services.LiveStatesService;
|
||||||
using BetterLyrics.WinUI3.Services.MediaSessionsService;
|
using BetterLyrics.WinUI3.Services.MediaSessionsService;
|
||||||
using BetterLyrics.WinUI3.Services.SettingsService;
|
using BetterLyrics.WinUI3.Services.SettingsService;
|
||||||
using BetterLyrics.WinUI3.Views;
|
using BetterLyrics.WinUI3.Views;
|
||||||
@@ -23,29 +24,22 @@ namespace BetterLyrics.WinUI3.ViewModels
|
|||||||
{
|
{
|
||||||
public partial class LyricsPageViewModel : BaseViewModel,
|
public partial class LyricsPageViewModel : BaseViewModel,
|
||||||
IRecipient<PropertyChangedMessage<bool>>,
|
IRecipient<PropertyChangedMessage<bool>>,
|
||||||
IRecipient<PropertyChangedMessage<int>>,
|
|
||||||
IRecipient<PropertyChangedMessage<string>>,
|
|
||||||
IRecipient<PropertyChangedMessage<TimeSpan>>
|
IRecipient<PropertyChangedMessage<TimeSpan>>
|
||||||
{
|
{
|
||||||
private readonly IMediaSessionsService _mediaSessionsService;
|
private readonly IMediaSessionsService _mediaSessionsService;
|
||||||
private readonly ISettingsService _settingsService;
|
private readonly ISettingsService _settingsService;
|
||||||
|
private readonly ILiveStatesService _liveStatesService;
|
||||||
|
|
||||||
private readonly ThrottleHelper _timelineThrottle = new(TimeSpan.FromSeconds(1));
|
private readonly ThrottleHelper _timelineThrottle = new(TimeSpan.FromSeconds(1));
|
||||||
|
|
||||||
private bool _isDockMode = false;
|
public LyricsPageViewModel(ISettingsService settingsService, IMediaSessionsService mediaSessionsService, ILiveStatesService liveStatesService)
|
||||||
private bool _isDesktopMode = false;
|
|
||||||
|
|
||||||
public LyricsPageViewModel(ISettingsService settingsService, IMediaSessionsService mediaSessionsService)
|
|
||||||
{
|
{
|
||||||
_settingsService = settingsService;
|
_settingsService = settingsService;
|
||||||
IsTranslationEnabled = _settingsService.AppSettings.TranslationSettings.IsTranslationEnabled;
|
_liveStatesService = liveStatesService;
|
||||||
DisplayType = _settingsService.AppSettings.GeneralSettings.DisplayType;
|
|
||||||
|
LiveStates = _liveStatesService.LiveStates;
|
||||||
|
|
||||||
IsImmersiveMode = _settingsService.AppSettings.GeneralSettings.IsImmersiveMode;
|
IsImmersiveMode = _settingsService.AppSettings.GeneralSettings.IsImmersiveMode;
|
||||||
ShowTranslationOnly = _settingsService.AppSettings.TranslationSettings.ShowTranslationOnly;
|
|
||||||
|
|
||||||
UpdateHintMessageFontSize();
|
|
||||||
|
|
||||||
LyricsFontFamily = _settingsService.AppSettings.StandardLyricsStyleSettings.LyricsFontFamily;
|
|
||||||
|
|
||||||
OnIsImmersiveModeChanged(IsImmersiveMode);
|
OnIsImmersiveModeChanged(IsImmersiveMode);
|
||||||
|
|
||||||
@@ -81,6 +75,9 @@ namespace BetterLyrics.WinUI3.ViewModels
|
|||||||
SongDurationSeconds = SongInfo?.Duration ?? 0;
|
SongDurationSeconds = SongInfo?.Duration ?? 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
public partial LiveStates LiveStates { get; set; }
|
||||||
|
|
||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
public partial double TimelinePositionSeconds { get; set; }
|
public partial double TimelinePositionSeconds { get; set; }
|
||||||
|
|
||||||
@@ -90,12 +87,6 @@ namespace BetterLyrics.WinUI3.ViewModels
|
|||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
public partial int Volume { get; set; }
|
public partial int Volume { get; set; }
|
||||||
|
|
||||||
[ObservableProperty]
|
|
||||||
public partial string LyricsFontFamily { get; set; }
|
|
||||||
|
|
||||||
[ObservableProperty]
|
|
||||||
public partial int HintMessageFontSize { get; set; }
|
|
||||||
|
|
||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
public partial bool IsImmersiveMode { get; set; }
|
public partial bool IsImmersiveMode { get; set; }
|
||||||
|
|
||||||
@@ -105,71 +96,17 @@ namespace BetterLyrics.WinUI3.ViewModels
|
|||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
public partial double BottomCommandFlyoutTriggerOpacity { get; set; }
|
public partial double BottomCommandFlyoutTriggerOpacity { get; set; }
|
||||||
|
|
||||||
[ObservableProperty]
|
|
||||||
[NotifyPropertyChangedRecipients]
|
|
||||||
public partial LyricsDisplayType DisplayType { get; set; }
|
|
||||||
|
|
||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
public partial SongInfo? SongInfo { get; set; } = null;
|
public partial SongInfo? SongInfo { get; set; } = null;
|
||||||
|
|
||||||
[ObservableProperty]
|
|
||||||
[NotifyPropertyChangedRecipients]
|
|
||||||
public partial bool IsTranslationEnabled { get; set; }
|
|
||||||
|
|
||||||
[ObservableProperty]
|
|
||||||
[NotifyPropertyChangedRecipients]
|
|
||||||
public partial bool ShowTranslationOnly { get; set; }
|
|
||||||
|
|
||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
public partial bool IsSongPlaying { get; set; }
|
public partial bool IsSongPlaying { get; set; }
|
||||||
|
|
||||||
private void UpdateHintMessageFontSize()
|
|
||||||
{
|
|
||||||
if (_isDockMode)
|
|
||||||
{
|
|
||||||
HintMessageFontSize = _settingsService.AppSettings.DockLyricsStyleSettings.LyricsFontSize;
|
|
||||||
}
|
|
||||||
else if (_isDesktopMode)
|
|
||||||
{
|
|
||||||
HintMessageFontSize = _settingsService.AppSettings.DesktopLyricsStyleSettings.LyricsFontSize;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
HintMessageFontSize = _settingsService.AppSettings.StandardLyricsStyleSettings.LyricsFontSize;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Receive(PropertyChangedMessage<bool> message)
|
public void Receive(PropertyChangedMessage<bool> message)
|
||||||
{
|
{
|
||||||
if (message.Sender is LyricsWindowViewModel)
|
if (message.Sender is LyricsWindowViewModel)
|
||||||
{
|
{
|
||||||
if (message.PropertyName == nameof(LyricsWindowViewModel.IsDockMode))
|
if (message.PropertyName == nameof(LyricsWindowViewModel.IsImmersiveMode))
|
||||||
{
|
|
||||||
_isDockMode = message.NewValue;
|
|
||||||
if (message.NewValue)
|
|
||||||
{
|
|
||||||
DisplayType = LyricsDisplayType.LyricsOnly;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DisplayType = _settingsService.AppSettings.GeneralSettings.DisplayType;
|
|
||||||
}
|
|
||||||
UpdateHintMessageFontSize();
|
|
||||||
}
|
|
||||||
else if (message.PropertyName == nameof(LyricsWindowViewModel.IsDesktopMode))
|
|
||||||
{
|
|
||||||
_isDesktopMode = message.NewValue;
|
|
||||||
if (message.NewValue)
|
|
||||||
{
|
|
||||||
DisplayType = LyricsDisplayType.LyricsOnly;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DisplayType = _settingsService.AppSettings.GeneralSettings.DisplayType;
|
|
||||||
}
|
|
||||||
UpdateHintMessageFontSize();
|
|
||||||
}
|
|
||||||
else if (message.PropertyName == nameof(LyricsWindowViewModel.IsImmersiveMode))
|
|
||||||
{
|
{
|
||||||
IsImmersiveMode = message.NewValue;
|
IsImmersiveMode = message.NewValue;
|
||||||
}
|
}
|
||||||
@@ -206,11 +143,6 @@ namespace BetterLyrics.WinUI3.ViewModels
|
|||||||
await _mediaSessionsService.NextAsync();
|
await _mediaSessionsService.NextAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
partial void OnIsTranslationEnabledChanged(bool value)
|
|
||||||
{
|
|
||||||
_settingsService.AppSettings.TranslationSettings.IsTranslationEnabled = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
partial void OnIsImmersiveModeChanged(bool value)
|
partial void OnIsImmersiveModeChanged(bool value)
|
||||||
{
|
{
|
||||||
if (value)
|
if (value)
|
||||||
@@ -225,33 +157,6 @@ namespace BetterLyrics.WinUI3.ViewModels
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
partial void OnShowTranslationOnlyChanged(bool value)
|
|
||||||
{
|
|
||||||
_settingsService.AppSettings.TranslationSettings.ShowTranslationOnly = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Receive(PropertyChangedMessage<int> message)
|
|
||||||
{
|
|
||||||
if (message.Sender is LyricsStyleSettings)
|
|
||||||
{
|
|
||||||
if (message.PropertyName == nameof(LyricsStyleSettings.LyricsFontSize))
|
|
||||||
{
|
|
||||||
UpdateHintMessageFontSize();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Receive(PropertyChangedMessage<string> message)
|
|
||||||
{
|
|
||||||
if (message.Sender is LyricsStyleSettings)
|
|
||||||
{
|
|
||||||
if (message.PropertyName == nameof(LyricsStyleSettings.LyricsFontFamily))
|
|
||||||
{
|
|
||||||
LyricsFontFamily = message.NewValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//partial void OnVolumeChanged(int value)
|
//partial void OnVolumeChanged(int value)
|
||||||
//{
|
//{
|
||||||
// SystemVolumeHelper.SetMasterVolume(value);
|
// SystemVolumeHelper.SetMasterVolume(value);
|
||||||
|
|||||||
@@ -1,99 +0,0 @@
|
|||||||
using BetterLyrics.WinUI3.Enums;
|
|
||||||
using BetterLyrics.WinUI3.Models;
|
|
||||||
using BetterLyrics.WinUI3.Models.Settings;
|
|
||||||
using BetterLyrics.WinUI3.Services.LastFMService;
|
|
||||||
using BetterLyrics.WinUI3.Services.LibWatcherService;
|
|
||||||
using BetterLyrics.WinUI3.Services.LyricsSearchService;
|
|
||||||
using BetterLyrics.WinUI3.Services.MediaSessionsService;
|
|
||||||
using BetterLyrics.WinUI3.Services.SettingsService;
|
|
||||||
using BetterLyrics.WinUI3.Services.TranslateService;
|
|
||||||
using CommunityToolkit.Mvvm.DependencyInjection;
|
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
using System;
|
|
||||||
using System.Diagnostics;
|
|
||||||
|
|
||||||
namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
|
||||||
{
|
|
||||||
public partial class LyricsRendererViewModel
|
|
||||||
{
|
|
||||||
public LyricsRendererViewModel(
|
|
||||||
ISettingsService settingsService,
|
|
||||||
IMediaSessionsService mediaSessionsService,
|
|
||||||
ILyricsSearchService musicSearchService,
|
|
||||||
ILibWatcherService libWatcherService,
|
|
||||||
ITranslateService libreTranslateService,
|
|
||||||
ILastFMService lastFMService
|
|
||||||
)
|
|
||||||
{
|
|
||||||
_settingsService = settingsService;
|
|
||||||
_lyrcsSearchService = musicSearchService;
|
|
||||||
_mediaSessionsService = mediaSessionsService;
|
|
||||||
_libWatcherService = libWatcherService;
|
|
||||||
_translateService = libreTranslateService;
|
|
||||||
|
|
||||||
_lastFMService = lastFMService;
|
|
||||||
|
|
||||||
_logger = Ioc.Default.GetRequiredService<ILogger<LyricsRendererViewModel>>();
|
|
||||||
|
|
||||||
_settingsService.AppSettings.MediaSourceProvidersInfo.ItemPropertyChanged += MediaSourceProvidersInfo_ItemPropertyChanged;
|
|
||||||
_settingsService.AppSettings.LocalMediaFolders.CollectionChanged += LocalMediaFolders_CollectionChanged;
|
|
||||||
_settingsService.AppSettings.LocalMediaFolders.ItemPropertyChanged += LocalMediaFolders_ItemPropertyChanged;
|
|
||||||
|
|
||||||
_lyricsStyleSettings = _settingsService.AppSettings.StandardLyricsStyleSettings;
|
|
||||||
_lyricsEffectSettings = _settingsService.AppSettings.StandardLyricsEffectSettings;
|
|
||||||
|
|
||||||
_titleTextFormat.HorizontalAlignment = _artistTextFormat.HorizontalAlignment = _settingsService.AppSettings.AlbumArtLayoutSettings.SongInfoAlignmentType.ToCanvasHorizontalAlignment();
|
|
||||||
|
|
||||||
_timelineSyncThreshold = 0;
|
|
||||||
|
|
||||||
_displayType = _displayTypeReceived = _settingsService.AppSettings.GeneralSettings.DisplayType;
|
|
||||||
|
|
||||||
_libWatcherService.MusicLibraryFilesChanged += LibWatcherService_MusicLibraryFilesChanged;
|
|
||||||
|
|
||||||
_mediaSessionsService.IsPlayingChanged += PlaybackService_IsPlayingChanged;
|
|
||||||
_mediaSessionsService.SongInfoChanged += PlaybackService_SongInfoChanged;
|
|
||||||
_mediaSessionsService.AlbumArtChangedChanged += PlaybackService_AlbumArtChangedChanged;
|
|
||||||
_mediaSessionsService.TimelineChanged += PlaybackService_TimelineChanged;
|
|
||||||
|
|
||||||
_isPlaying = _mediaSessionsService.IsPlaying;
|
|
||||||
|
|
||||||
UpdateColorConfig();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void LocalMediaFolders_ItemPropertyChanged(object? sender, Extensions.ItemPropertyChangedEventArgs e)
|
|
||||||
{
|
|
||||||
// Music lib changed, re-fetch lyrics
|
|
||||||
_logger.LogInformation("Local lyrics folders changed, refreshing lyrics.");
|
|
||||||
_ = _refreshLyricsRunner.RunAsync(async tokne =>
|
|
||||||
{
|
|
||||||
await RefreshLyricsAsync(tokne);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void LocalMediaFolders_CollectionChanged(object? sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
|
|
||||||
{
|
|
||||||
// Music lib changed, re-fetch lyrics
|
|
||||||
_logger.LogInformation("Local lyrics folders changed, refreshing lyrics.");
|
|
||||||
_ = _refreshLyricsRunner.RunAsync(async tokne =>
|
|
||||||
{
|
|
||||||
await RefreshLyricsAsync(tokne);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void MediaSourceProvidersInfo_ItemPropertyChanged(object? sender, Extensions.ItemPropertyChangedEventArgs e)
|
|
||||||
{
|
|
||||||
switch (e.PropertyName)
|
|
||||||
{
|
|
||||||
case nameof(MediaSourceProviderInfo.LyricsSearchProvidersInfo):
|
|
||||||
_logger.LogInformation("MediaSourceProviderInfo.LyricsSearchProvidersInfo changed, refreshing lyrics.");
|
|
||||||
_ = _refreshLyricsRunner.RunAsync(async token =>
|
|
||||||
{
|
|
||||||
await RefreshLyricsAsync(token);
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -33,18 +33,23 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
|||||||
using var combined = new CanvasCommandList(control);
|
using var combined = new CanvasCommandList(control);
|
||||||
using var combinedDs = combined.CreateDrawingSession();
|
using var combinedDs = combined.CreateDrawingSession();
|
||||||
|
|
||||||
if (_isDockMode)
|
switch (_liveStatesService.LiveStates.CurrentLyricsWindowMode)
|
||||||
{
|
{
|
||||||
FillBackground(control, combinedDs, _immersiveBgColorTransition.Value, 0f, _immersiveBgOpacityTransition.Value * _settingsService.AppSettings.LyricsBackgroundSettings.PureColorOverlayOpacity / 100f);
|
case LyricsWindowMode.DockMode:
|
||||||
}
|
FillBackground(control, combinedDs, _immersiveBgColorTransition.Value, 0f,
|
||||||
else if (_isDesktopMode)
|
_immersiveBgOpacityTransition.Value * _settingsService.AppSettings.LyricsBackgroundSettings.PureColorOverlayOpacity / 100f);
|
||||||
{
|
break;
|
||||||
FillBackground(control, combinedDs, _immersiveBgColorTransition.Value, 0f, _immersiveBgOpacityTransition.Value * _settingsService.AppSettings.LyricsBackgroundSettings.PureColorOverlayOpacity / 100f);
|
case LyricsWindowMode.DesktopMode:
|
||||||
}
|
FillBackground(control, combinedDs, _immersiveBgColorTransition.Value, 0f,
|
||||||
else
|
_immersiveBgOpacityTransition.Value * _settingsService.AppSettings.LyricsBackgroundSettings.PureColorOverlayOpacity / 100f);
|
||||||
{
|
break;
|
||||||
FillBackground(control, combinedDs, _albumArtAccentColorTransition.Value, 0f, _settingsService.AppSettings.LyricsBackgroundSettings.PureColorOverlayOpacity / 100f);
|
case LyricsWindowMode.StandardMode:
|
||||||
DrawAlbumArtBackground(control, combinedDs);
|
case LyricsWindowMode.PictureInPictureMode:
|
||||||
|
FillBackground(control, combinedDs, _albumArtAccentColorTransition.Value, 0f, _settingsService.AppSettings.LyricsBackgroundSettings.PureColorOverlayOpacity / 100.0);
|
||||||
|
DrawAlbumArtBackground(control, combinedDs);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
combinedDs.DrawImage(blurredLyrics);
|
combinedDs.DrawImage(blurredLyrics);
|
||||||
@@ -58,9 +63,7 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
|||||||
{
|
{
|
||||||
_drawFrameCount++;
|
_drawFrameCount++;
|
||||||
|
|
||||||
var currentPlayingLine = _lyricsDataArr
|
var currentPlayingLine = _currentLyricsData?.LyricsLines.ElementAtOrDefault(_playingLineIndex);
|
||||||
.ElementAtOrDefault(_langIndex)
|
|
||||||
?.LyricsLines.ElementAtOrDefault(_playingLineIndex);
|
|
||||||
|
|
||||||
if (currentPlayingLine != null)
|
if (currentPlayingLine != null)
|
||||||
{
|
{
|
||||||
@@ -82,7 +85,6 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
|||||||
$"Visible lines: [{_startVisibleLineIndex}, {_endVisibleLineIndex}]\n" +
|
$"Visible lines: [{_startVisibleLineIndex}, {_endVisibleLineIndex}]\n" +
|
||||||
$"Total line count: {GetMaxLyricsLineIndexBoundaries().Item2 + 1}\n" +
|
$"Total line count: {GetMaxLyricsLineIndexBoundaries().Item2 + 1}\n" +
|
||||||
$"Cur time: {TotalTime + _positionOffset}\n" +
|
$"Cur time: {TotalTime + _positionOffset}\n" +
|
||||||
$"Lang size: {_lyricsDataArr.Count}\n" +
|
|
||||||
$"Song duration: {TimeSpan.FromMilliseconds(SongInfo?.DurationMs ?? 0)}\n" +
|
$"Song duration: {TimeSpan.FromMilliseconds(SongInfo?.DurationMs ?? 0)}\n" +
|
||||||
$"Y offset: {_canvasYScrollTransition.Value}",
|
$"Y offset: {_canvasYScrollTransition.Value}",
|
||||||
new Vector2(10, 40),
|
new Vector2(10, 40),
|
||||||
@@ -114,52 +116,46 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
|||||||
ds.DrawImage(effect, new Vector2((float)x, (float)y));
|
ds.DrawImage(effect, new Vector2((float)x, (float)y));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawForegroundImgae(OpacityEffect effect, CanvasDrawingSession ds)
|
|
||||||
{
|
|
||||||
ds.DrawImage(effect, new Vector2((float)_albumArtXTransition.Value, (float)_albumArtYTransition.Value));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DrawAlbumArtBackground(ICanvasAnimatedControl control, CanvasDrawingSession ds)
|
private void DrawAlbumArtBackground(ICanvasAnimatedControl control, CanvasDrawingSession ds)
|
||||||
{
|
{
|
||||||
if (_albumArtBgEffect == null)
|
ds.Transform = Matrix3x2.CreateRotation((float)_rotateAngle, control.Size.ToVector2() * 0.5f);
|
||||||
|
|
||||||
|
if (_albumArtBgEffect != null)
|
||||||
{
|
{
|
||||||
return;
|
ds.DrawImage(_albumArtBgEffect);
|
||||||
|
}
|
||||||
|
else if (_albumArtBgRenderTarget != null)
|
||||||
|
{
|
||||||
|
double targetSize = Math.Sqrt(Math.Pow(_canvasWidth, 2) + Math.Pow(_canvasHeight, 2));
|
||||||
|
float offsetX = (float)(_canvasWidth - targetSize) / 2;
|
||||||
|
float offsetY = (float)(_canvasHeight - targetSize) / 2;
|
||||||
|
|
||||||
|
ds.DrawImage(_albumArtBgRenderTarget, new Vector2(offsetX, offsetY));
|
||||||
}
|
}
|
||||||
|
|
||||||
ds.Transform = Matrix3x2.CreateRotation((float)_rotateAngle, control.Size.ToVector2() * 0.5f);
|
|
||||||
ds.DrawImage(_albumArtBgEffect);
|
|
||||||
ds.Transform = Matrix3x2.Identity;
|
ds.Transform = Matrix3x2.Identity;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawAlbumArt(ICanvasAnimatedControl control, CanvasDrawingSession ds)
|
private void DrawAlbumArt(ICanvasAnimatedControl control, CanvasDrawingSession ds)
|
||||||
{
|
{
|
||||||
using var albumArt = new CanvasCommandList(control.Device);
|
if (_isAlbumArtEffectChanged && _albumArtEffect != null)
|
||||||
using var albumArtDs = albumArt.CreateDrawingSession();
|
|
||||||
|
|
||||||
if (_lastFgImageEffect != null && !_lastFgImageEffect.IsDisposed() && _lastAlbumArtCanvasBitmap != null)
|
|
||||||
{
|
{
|
||||||
DrawForegroundImgae(_lastFgImageEffect, albumArtDs);
|
ds.DrawImage(new OpacityEffect
|
||||||
|
{
|
||||||
|
Source = _albumArtEffect,
|
||||||
|
Opacity = (float)_albumArtOpacityTransition.Value
|
||||||
|
}, new Vector2((float)_albumArtXTransition.Value, (float)_albumArtYTransition.Value));
|
||||||
}
|
}
|
||||||
if (_fgImageEffect != null && !_fgImageEffect.IsDisposed() && _albumArtCanvasBitmap != null)
|
else if (!_isAlbumArtEffectChanged && _albumArtRenderTarget != null)
|
||||||
{
|
{
|
||||||
DrawForegroundImgae(_fgImageEffect, albumArtDs);
|
// 这里给一个相反的偏移以恢复位置
|
||||||
|
ds.DrawImage(new OpacityEffect
|
||||||
|
{
|
||||||
|
Source = _albumArtRenderTarget,
|
||||||
|
Opacity = (float)_albumArtOpacityTransition.Value
|
||||||
|
}, new Vector2((float)_albumArtXTransition.Value, (float)_albumArtYTransition.Value) -
|
||||||
|
control.Size.ToVector2() / 2 + new Vector2((float)_albumArtSize, (float)_albumArtSize) / 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
using var opacity = new CanvasCommandList(control.Device);
|
|
||||||
using var opacityDs = opacity.CreateDrawingSession();
|
|
||||||
opacityDs.DrawImage(new GaussianBlurEffect
|
|
||||||
{
|
|
||||||
Source = albumArt,
|
|
||||||
BlurAmount = 12f,
|
|
||||||
Optimization = EffectOptimization.Speed,
|
|
||||||
});
|
|
||||||
opacityDs.DrawImage(albumArt);
|
|
||||||
|
|
||||||
ds.DrawImage(new OpacityEffect
|
|
||||||
{
|
|
||||||
Source = opacity,
|
|
||||||
Opacity = (float)_albumArtOpacityTransition.Value
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawTitleAndArtist(ICanvasAnimatedControl control, CanvasDrawingSession ds)
|
private void DrawTitleAndArtist(ICanvasAnimatedControl control, CanvasDrawingSession ds)
|
||||||
@@ -207,9 +203,7 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
|||||||
|
|
||||||
private void DrawBlurredLyrics(ICanvasAnimatedControl control, CanvasDrawingSession ds)
|
private void DrawBlurredLyrics(ICanvasAnimatedControl control, CanvasDrawingSession ds)
|
||||||
{
|
{
|
||||||
var currentPlayingLine = _lyricsDataArr
|
var currentPlayingLine = _currentLyricsData?.LyricsLines.ElementAtOrDefault(_playingLineIndex);
|
||||||
.ElementAtOrDefault(_langIndex)
|
|
||||||
?.LyricsLines.ElementAtOrDefault(_playingLineIndex);
|
|
||||||
|
|
||||||
if (currentPlayingLine == null)
|
if (currentPlayingLine == null)
|
||||||
{
|
{
|
||||||
@@ -218,7 +212,7 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
|||||||
|
|
||||||
for (int i = _startVisibleLineIndex; i <= _endVisibleLineIndex; i++)
|
for (int i = _startVisibleLineIndex; i <= _endVisibleLineIndex; i++)
|
||||||
{
|
{
|
||||||
var line = _lyricsDataArr.ElementAtOrDefault(_langIndex)?.LyricsLines.ElementAtOrDefault(i);
|
var line = _currentLyricsData?.LyricsLines.ElementAtOrDefault(i);
|
||||||
if (line == null) continue;
|
if (line == null) continue;
|
||||||
|
|
||||||
var textLayout = line.CanvasTextLayout;
|
var textLayout = line.CanvasTextLayout;
|
||||||
@@ -237,46 +231,79 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
|||||||
* Matrix3x2.CreateRotation((float)line.AngleTransition.Value, currentPlayingLine.Position)
|
* Matrix3x2.CreateRotation((float)line.AngleTransition.Value, currentPlayingLine.Position)
|
||||||
* Matrix3x2.CreateTranslation((float)_lyricsXTransition.Value, (float)yOffset);
|
* Matrix3x2.CreateTranslation((float)_lyricsXTransition.Value, (float)yOffset);
|
||||||
|
|
||||||
if (line.BackgroundFontEffect == null || line.ForegroundFontEffect == null) continue;
|
using var combined = new CanvasCommandList(control);
|
||||||
|
|
||||||
using var combined = new CanvasCommandList(control.Device);
|
|
||||||
using var combinedDs = combined.CreateDrawingSession();
|
using var combinedDs = combined.CreateDrawingSession();
|
||||||
|
|
||||||
// Mock gradient blurred lyrics layer
|
|
||||||
// 先铺一层带默认透明度的已经加了模糊效果的歌词作为最底层(背景歌词层次)
|
// 先铺一层带默认透明度的已经加了模糊效果的歌词作为最底层(背景歌词层次)
|
||||||
// Current line will not be blurred
|
using var backgroundFontEffect = CanvasHelper.CreateFontEffect(line, control, _strokeFontColor,
|
||||||
combinedDs.DrawImage(line.BackgroundEffect);
|
_liveStatesService.LiveStates.CurrentLyricsStyleSettings.LyricsFontStrokeWidth, _bgFontColor);
|
||||||
|
using var backgroundEffect = CanvasHelper.CreateBackgroundEffect(line, backgroundFontEffect, _lyricsOpacityTransition.Value);
|
||||||
|
combinedDs.DrawImage(backgroundEffect);
|
||||||
|
|
||||||
|
//if (i == _playingLineIndex)
|
||||||
if (line.HighlightOpacityTransition.Value != 0)
|
if (line.HighlightOpacityTransition.Value != 0)
|
||||||
{
|
{
|
||||||
if (line.ForegroundBlurEffect == null || line.ForegroundHighlightEffect == null || line.PlaceholderEffect == null)
|
GetLinePlayingProgress(i, out int charStartIndex, out int charLength, out double charProgress);
|
||||||
|
|
||||||
|
using var charMask = CanvasHelper.CreateCharMask(control, line, charStartIndex, charLength, charProgress);
|
||||||
|
using var lineStartToCharMask = CanvasHelper.CreateLineStartToCharMask(control, line, charStartIndex, charLength, charProgress,
|
||||||
|
_liveStatesService.LiveStates.CurrentLyricsEffectSettings.IsLyricsLineFadeEnabled);
|
||||||
|
using var lineMask = CanvasHelper.CreateLineMask(control, line);
|
||||||
|
|
||||||
|
using var foregroundFontEffect = CanvasHelper.CreateFontEffect(line, control, _strokeFontColor,
|
||||||
|
_liveStatesService.LiveStates.CurrentLyricsStyleSettings.LyricsFontStrokeWidth, _fgFontColor);
|
||||||
|
|
||||||
|
using var effectLayer = new CanvasCommandList(control);
|
||||||
|
using var effectLayerDs = effectLayer.CreateDrawingSession();
|
||||||
|
if (line.OriginalText != line.DisplayedText && _liveStatesService.LiveStates.CurrentLyricsEffectSettings.LyricsTranslationHighlightAmount != 0)
|
||||||
{
|
{
|
||||||
return;
|
using var translationHighlightMask = CanvasHelper.CreateTranslationHighlightMask(control, line);
|
||||||
|
using var foregroundTranslationHighlightEffect = CanvasHelper.CreateForegroundHighlightEffect(foregroundFontEffect, translationHighlightMask,
|
||||||
|
_liveStatesService.LiveStates.CurrentLyricsEffectSettings.LyricsTranslationHighlightAmount / 100.0);
|
||||||
|
effectLayerDs.DrawImage(foregroundTranslationHighlightEffect);
|
||||||
|
}
|
||||||
|
if (_liveStatesService.LiveStates.CurrentLyricsEffectSettings.IsLyricsShadowEnabled)
|
||||||
|
{
|
||||||
|
var shadowEffectMask = CanvasHelper.GetAlphaMask(control, charMask, lineStartToCharMask, lineMask,
|
||||||
|
_liveStatesService.LiveStates.CurrentLyricsEffectSettings.LyricsShadowScope);
|
||||||
|
using var foregroundShadowEffect = CanvasHelper.CreateForegroundShadowEffect(foregroundFontEffect, shadowEffectMask,
|
||||||
|
_albumArtAccentColorTransition.Value, _liveStatesService.LiveStates.CurrentLyricsEffectSettings.LyricsShadowAmount);
|
||||||
|
effectLayerDs.DrawImage(foregroundShadowEffect);
|
||||||
|
}
|
||||||
|
if (_liveStatesService.LiveStates.CurrentLyricsEffectSettings.IsLyricsGlowEffectEnabled)
|
||||||
|
{
|
||||||
|
var blurEffectMask = CanvasHelper.GetAlphaMask(control, charMask, lineStartToCharMask, lineMask,
|
||||||
|
_liveStatesService.LiveStates.CurrentLyricsEffectSettings.LyricsGlowEffectScope);
|
||||||
|
using var foregroundBlurEffect = CanvasHelper.CreateForegroundBlurEffect(foregroundFontEffect, blurEffectMask,
|
||||||
|
_liveStatesService.LiveStates.CurrentLyricsEffectSettings.LyricsGlowEffectAmount);
|
||||||
|
effectLayerDs.DrawImage(foregroundBlurEffect);
|
||||||
|
}
|
||||||
|
if (_liveStatesService.LiveStates.CurrentLyricsEffectSettings.LyricsHighlightAmount != 0)
|
||||||
|
{
|
||||||
|
var highlightEffectMask = CanvasHelper.GetAlphaMask(control, charMask, lineStartToCharMask, lineMask,
|
||||||
|
_liveStatesService.LiveStates.CurrentLyricsEffectSettings.LyricsHighlightScope);
|
||||||
|
using var foregroundHighlightEffect = CanvasHelper.CreateForegroundHighlightEffect(foregroundFontEffect, highlightEffectMask,
|
||||||
|
_liveStatesService.LiveStates.CurrentLyricsEffectSettings.LyricsHighlightAmount / 100.0);
|
||||||
|
effectLayerDs.DrawImage(foregroundHighlightEffect);
|
||||||
}
|
}
|
||||||
|
|
||||||
using var opacityEffect = new OpacityEffect
|
combinedDs.DrawImage(new OpacityEffect
|
||||||
{
|
{
|
||||||
Source = new BlendEffect
|
Source = effectLayer,
|
||||||
{
|
|
||||||
Background = _lyricsEffectSettings.IsLyricsGlowEffectEnabled ? line.ForegroundBlurEffect : line.PlaceholderEffect,
|
|
||||||
Foreground = line.ForegroundHighlightEffect,
|
|
||||||
},
|
|
||||||
Opacity = (float)(line.HighlightOpacityTransition.Value * _lyricsOpacityTransition.Value),
|
Opacity = (float)(line.HighlightOpacityTransition.Value * _lyricsOpacityTransition.Value),
|
||||||
};
|
});
|
||||||
|
|
||||||
combinedDs.DrawImage(opacityEffect);
|
|
||||||
|
|
||||||
if (i == _playingLineIndex)
|
if (i == _playingLineIndex)
|
||||||
{
|
{
|
||||||
if (_lyricsEffectSettings.IsLyricsFloatAnimationEnabled)
|
if (_liveStatesService.LiveStates.CurrentLyricsEffectSettings.IsLyricsFloatAnimationEnabled)
|
||||||
{
|
{
|
||||||
ds.DrawImage(new DisplacementMapEffect
|
ds.DrawImage(new DisplacementMapEffect
|
||||||
{
|
{
|
||||||
Source = combined,
|
Source = combined,
|
||||||
Displacement = line.LineStartToCurrentCharMask,
|
Displacement = lineStartToCharMask,
|
||||||
XChannelSelect = EffectChannelSelect.Red,
|
XChannelSelect = EffectChannelSelect.Red,
|
||||||
YChannelSelect = EffectChannelSelect.Alpha,
|
YChannelSelect = EffectChannelSelect.Alpha,
|
||||||
Amount = 1f,
|
Amount = _liveStatesService.LiveStates.CurrentLyricsEffectSettings.LyricsFloatAmount,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -11,13 +11,8 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
|||||||
{
|
{
|
||||||
public partial class LyricsRendererViewModel
|
public partial class LyricsRendererViewModel
|
||||||
{
|
{
|
||||||
private OpacityEffect? _lastBgImageEffect;
|
private OpacityEffect? _albumArtBgEffect;
|
||||||
private OpacityEffect? _bgImageEffect;
|
private CanvasCommandList? _albumArtEffect;
|
||||||
|
|
||||||
private OpacityEffect? _lastFgImageEffect;
|
|
||||||
private OpacityEffect? _fgImageEffect;
|
|
||||||
|
|
||||||
private CanvasCommandList? _albumArtBgEffect;
|
|
||||||
|
|
||||||
private OpacityEffect CreateBgImageEffect(CanvasBitmap canvasBitmap, double opacity)
|
private OpacityEffect CreateBgImageEffect(CanvasBitmap canvasBitmap, double opacity)
|
||||||
{
|
{
|
||||||
@@ -85,21 +80,42 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateAlbumArtBgEffect(ICanvasAnimatedControl control)
|
private void DisposeAlbumArtBgEffect()
|
||||||
{
|
{
|
||||||
_albumArtBgEffect?.Dispose();
|
_albumArtBgEffect?.Dispose();
|
||||||
_albumArtBgEffect = null;
|
_albumArtBgEffect = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 更新专辑封面背景效果
|
||||||
|
/// <para>应该在以下任意条件满足时调用此函数:</para>
|
||||||
|
/// <para><seealso cref="_isCanvasWidthChanged"/> == true</para>
|
||||||
|
/// <para><seealso cref="_isCanvasHeightChanged"/> == true</para>
|
||||||
|
/// <para><seealso cref="_albumArtChanged"/> == true</para>
|
||||||
|
/// <para><seealso cref="_isAlbumArtBgBlurAmountChanged"/> == true</para>
|
||||||
|
/// <para><seealso cref="_isCoverAcrylicEffectAmountChanged"/> == true</para>
|
||||||
|
/// <para><seealso cref="_isAlbumArtBgOpacityChanged"/> == true</para>
|
||||||
|
/// <para><seealso cref="_albumArtBgTransition"/> 正在变化</para>
|
||||||
|
/// <para><seealso cref="_albumArtAccentColorTransition"/> 正在变化</para>
|
||||||
|
/// 如果上述条件均不满足,需调用 <seealso cref="UpdateAlbumArtBgRenderTarget"/> 来更新渲染缓存
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="control"></param>
|
||||||
|
private void UpdateAlbumArtBgEffect(ICanvasAnimatedControl control)
|
||||||
|
{
|
||||||
|
DisposeAlbumArtBgEffect();
|
||||||
|
|
||||||
using var overlappedCovers = new CanvasCommandList(control);
|
using var overlappedCovers = new CanvasCommandList(control);
|
||||||
using var overlappedCoversDs = overlappedCovers.CreateDrawingSession();
|
using var overlappedCoversDs = overlappedCovers.CreateDrawingSession();
|
||||||
|
|
||||||
if (_lastBgImageEffect != null && !_lastBgImageEffect.IsDisposed() && _lastAlbumArtCanvasBitmap != null)
|
if (_lastAlbumArtCanvasBitmap != null)
|
||||||
{
|
{
|
||||||
DrawBackgroundImgae(_lastBgImageEffect, overlappedCoversDs, _lastAlbumArtCanvasBitmap);
|
using var lastBgImageEffect = CreateBgImageEffect(_lastAlbumArtCanvasBitmap, 1 - _albumArtBgTransition.Value);
|
||||||
|
DrawBackgroundImgae(lastBgImageEffect, overlappedCoversDs, _lastAlbumArtCanvasBitmap);
|
||||||
}
|
}
|
||||||
if (_bgImageEffect != null && !_bgImageEffect.IsDisposed() && _albumArtCanvasBitmap != null)
|
if (_albumArtCanvasBitmap != null)
|
||||||
{
|
{
|
||||||
DrawBackgroundImgae(_bgImageEffect, overlappedCoversDs, _albumArtCanvasBitmap);
|
using var bgImageEffect = CreateBgImageEffect(_albumArtCanvasBitmap, _albumArtBgTransition.Value);
|
||||||
|
DrawBackgroundImgae(bgImageEffect, overlappedCoversDs, _albumArtCanvasBitmap);
|
||||||
}
|
}
|
||||||
|
|
||||||
using var blurredCover = new GaussianBlurEffect
|
using var blurredCover = new GaussianBlurEffect
|
||||||
@@ -110,7 +126,7 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
|||||||
Optimization = EffectOptimization.Speed,
|
Optimization = EffectOptimization.Speed,
|
||||||
};
|
};
|
||||||
|
|
||||||
using var combined = new CanvasCommandList(control);
|
var combined = new CanvasCommandList(control);
|
||||||
using var combinedDs = combined.CreateDrawingSession();
|
using var combinedDs = combined.CreateDrawingSession();
|
||||||
|
|
||||||
if (_settingsService.AppSettings.LyricsBackgroundSettings.CoverAcrylicEffectAmount > 0 && _coverAcrylicNoiseCanvasBitmap != null)
|
if (_settingsService.AppSettings.LyricsBackgroundSettings.CoverAcrylicEffectAmount > 0 && _coverAcrylicNoiseCanvasBitmap != null)
|
||||||
@@ -132,53 +148,103 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
|||||||
combinedDs.DrawImage(blurredCover);
|
combinedDs.DrawImage(blurredCover);
|
||||||
}
|
}
|
||||||
|
|
||||||
_albumArtBgEffect = new CanvasCommandList(control);
|
_albumArtBgEffect = new OpacityEffect
|
||||||
using var albumArtBgDs = _albumArtBgEffect.CreateDrawingSession();
|
|
||||||
albumArtBgDs.DrawImage(new OpacityEffect
|
|
||||||
{
|
{
|
||||||
Opacity = _settingsService.AppSettings.LyricsBackgroundSettings.CoverOverlayOpacity / 100f,
|
Opacity = _settingsService.AppSettings.LyricsBackgroundSettings.CoverOverlayOpacity / 100f,
|
||||||
Source = combined,
|
Source = combined,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DisposeAlbumArtBgRenderTarget()
|
||||||
|
{
|
||||||
|
_albumArtBgRenderTarget?.Dispose();
|
||||||
|
_albumArtBgRenderTarget = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateAlbumArtBgRenderTarget(ICanvasAnimatedControl control)
|
||||||
|
{
|
||||||
|
DisposeAlbumArtBgRenderTarget();
|
||||||
|
|
||||||
|
double targetSize = Math.Sqrt(Math.Pow(_canvasWidth, 2) + Math.Pow(_canvasHeight, 2));
|
||||||
|
|
||||||
|
_albumArtBgRenderTarget = new CanvasRenderTarget(control, (float)targetSize, (float)targetSize);
|
||||||
|
using var ds = _albumArtBgRenderTarget.CreateDrawingSession();
|
||||||
|
|
||||||
|
float offsetX = -(float)(_canvasWidth - targetSize) / 2;
|
||||||
|
float offsetY = -(float)(_canvasHeight - targetSize) / 2;
|
||||||
|
|
||||||
|
ds.DrawImage(_albumArtBgEffect, new Vector2(offsetX, offsetY));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DisposeAlbumArtEffect()
|
||||||
|
{
|
||||||
|
_albumArtEffect?.Dispose();
|
||||||
|
_albumArtEffect = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 更新专辑封面效果
|
||||||
|
/// <para>应该在以下任意条件满足时调用此函数:</para>
|
||||||
|
/// <para><seealso cref="_isCanvasWidthChanged"/> == true</para>
|
||||||
|
/// <para><seealso cref="_isCanvasHeightChanged"/> == true</para>
|
||||||
|
/// <para><seealso cref="_albumArtChanged"/> == true</para>
|
||||||
|
/// <para><seealso cref="_isAlbumArtShadowAmountChanged"/> == true</para>
|
||||||
|
/// <para><seealso cref="_albumArtBgTransition"/> 正在变化</para>
|
||||||
|
/// <para><seealso cref="_albumArtAccentColorTransition"/> 正在变化</para>
|
||||||
|
/// 如果上述条件均不满足,需调用 <seealso cref="UpdateAlbumArtRenderTarget"/> 来更新渲染缓存
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="control"></param>
|
||||||
|
private void UpdateAlbumArtEffect(ICanvasAnimatedControl control)
|
||||||
|
{
|
||||||
|
DisposeAlbumArtEffect();
|
||||||
|
|
||||||
|
using var overlappedCovers = new CanvasCommandList(control);
|
||||||
|
using var overlappedCoversDs = overlappedCovers.CreateDrawingSession();
|
||||||
|
|
||||||
|
if (_lastAlbumArtCanvasBitmap != null)
|
||||||
|
{
|
||||||
|
using var lastFgImageEffect = CreateFgImageEffect(control, _lastAlbumArtCanvasBitmap, 1 - _albumArtBgTransition.Value);
|
||||||
|
if (lastFgImageEffect != null)
|
||||||
|
{
|
||||||
|
overlappedCoversDs.DrawImage(lastFgImageEffect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (_albumArtCanvasBitmap != null)
|
||||||
|
{
|
||||||
|
using var fgImageEffect = CreateFgImageEffect(control, _albumArtCanvasBitmap, _albumArtBgTransition.Value);
|
||||||
|
if (fgImageEffect != null)
|
||||||
|
{
|
||||||
|
overlappedCoversDs.DrawImage(fgImageEffect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_albumArtEffect = new CanvasCommandList(control);
|
||||||
|
using var combinedDs = _albumArtEffect.CreateDrawingSession();
|
||||||
|
combinedDs.DrawImage(new ShadowEffect
|
||||||
|
{
|
||||||
|
Source = overlappedCovers,
|
||||||
|
ShadowColor = _albumArtAccentColorTransition.Value,
|
||||||
|
BlurAmount = _settingsService.AppSettings.AlbumArtLayoutSettings.CoverImageShadowAmount,
|
||||||
|
Optimization = EffectOptimization.Speed,
|
||||||
});
|
});
|
||||||
|
combinedDs.DrawImage(overlappedCovers);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateLastBgImageEffect()
|
private void DisposeAlbumArtRenderTarget()
|
||||||
{
|
{
|
||||||
_lastBgImageEffect?.Dispose();
|
_albumArtRenderTarget?.Dispose();
|
||||||
_lastBgImageEffect = null;
|
_albumArtRenderTarget = null;
|
||||||
if (_lastAlbumArtCanvasBitmap != null)
|
|
||||||
{
|
|
||||||
_lastBgImageEffect = CreateBgImageEffect(_lastAlbumArtCanvasBitmap, 1 - _albumArtBgTransition.Value);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateBgImageEffect()
|
private void UpdateAlbumArtRenderTarget(ICanvasAnimatedControl control)
|
||||||
{
|
{
|
||||||
_bgImageEffect?.Dispose();
|
DisposeAlbumArtRenderTarget();
|
||||||
_bgImageEffect = null;
|
|
||||||
if (_albumArtCanvasBitmap != null)
|
|
||||||
{
|
|
||||||
_bgImageEffect = CreateBgImageEffect(_albumArtCanvasBitmap, _albumArtBgTransition.Value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void UpdateLastFgImageEffect(ICanvasAnimatedControl control)
|
_albumArtRenderTarget = new CanvasRenderTarget(control, (float)_canvasWidth, (float)_canvasHeight);
|
||||||
{
|
using var ds = _albumArtRenderTarget.CreateDrawingSession();
|
||||||
_lastFgImageEffect?.Dispose();
|
|
||||||
_lastFgImageEffect = null;
|
|
||||||
if (_lastAlbumArtCanvasBitmap != null)
|
|
||||||
{
|
|
||||||
_lastFgImageEffect = CreateFgImageEffect(control, _lastAlbumArtCanvasBitmap, 1 - _albumArtBgTransition.Value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void UpdateFgImageEffect(ICanvasAnimatedControl control)
|
// 给一个偏移,是为了避免绘制时从原点开始,这样会造成阴影被裁切
|
||||||
{
|
ds.DrawImage(_albumArtEffect, control.Size.ToVector2() / 2 - new Vector2((float)_albumArtSize, (float)_albumArtSize) / 2);
|
||||||
_fgImageEffect?.Dispose();
|
|
||||||
_fgImageEffect = null;
|
|
||||||
if (_albumArtCanvasBitmap != null)
|
|
||||||
{
|
|
||||||
_fgImageEffect = CreateFgImageEffect(control, _albumArtCanvasBitmap, _albumArtBgTransition.Value);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
|||||||
IRecipient<PropertyChangedMessage<double>>,
|
IRecipient<PropertyChangedMessage<double>>,
|
||||||
IRecipient<PropertyChangedMessage<bool>>,
|
IRecipient<PropertyChangedMessage<bool>>,
|
||||||
IRecipient<PropertyChangedMessage<Color>>,
|
IRecipient<PropertyChangedMessage<Color>>,
|
||||||
|
IRecipient<PropertyChangedMessage<LyricsWindowMode>>,
|
||||||
IRecipient<PropertyChangedMessage<LyricsDisplayType>>,
|
IRecipient<PropertyChangedMessage<LyricsDisplayType>>,
|
||||||
IRecipient<PropertyChangedMessage<LyricsFontColorType>>,
|
IRecipient<PropertyChangedMessage<LyricsFontColorType>>,
|
||||||
IRecipient<PropertyChangedMessage<TextAlignmentType>>,
|
IRecipient<PropertyChangedMessage<TextAlignmentType>>,
|
||||||
@@ -52,39 +53,9 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (message.Sender is TranslationSettings)
|
|
||||||
{
|
|
||||||
if (message.PropertyName == nameof(TranslationSettings.IsLibreTranslateEnabled))
|
|
||||||
{
|
|
||||||
UpdateTranslations();
|
|
||||||
}
|
|
||||||
else if (message.PropertyName == nameof(TranslationSettings.IsTranslationEnabled))
|
|
||||||
{
|
|
||||||
_logger.LogInformation("Translation enabled state changed: {IsEnabled}", _settingsService.AppSettings.TranslationSettings.IsTranslationEnabled);
|
|
||||||
UpdateTranslations();
|
|
||||||
}
|
|
||||||
else if (message.PropertyName == nameof(TranslationSettings.ShowTranslationOnly))
|
|
||||||
{
|
|
||||||
UpdateTranslations();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (message.Sender is LyricsWindowViewModel)
|
else if (message.Sender is LyricsWindowViewModel)
|
||||||
{
|
{
|
||||||
if (message.PropertyName == nameof(LyricsWindowViewModel.IsDockMode))
|
if (message.PropertyName == nameof(LyricsWindowViewModel.IsLyricsWindowLocked))
|
||||||
{
|
|
||||||
_isDockMode = message.NewValue;
|
|
||||||
UpdateColorConfig();
|
|
||||||
UpdateImmersiveBackgroundOpacity();
|
|
||||||
_isLayoutChanged = true;
|
|
||||||
}
|
|
||||||
else if (message.PropertyName == nameof(LyricsWindowViewModel.IsDesktopMode))
|
|
||||||
{
|
|
||||||
_isDesktopMode = message.NewValue;
|
|
||||||
UpdateColorConfig();
|
|
||||||
UpdateImmersiveBackgroundOpacity();
|
|
||||||
_isLayoutChanged = true;
|
|
||||||
}
|
|
||||||
else if (message.PropertyName == nameof(LyricsWindowViewModel.IsLyricsWindowLocked))
|
|
||||||
{
|
{
|
||||||
_isLyricsWindowLocked = message.NewValue;
|
_isLyricsWindowLocked = message.NewValue;
|
||||||
UpdateImmersiveBackgroundOpacity();
|
UpdateImmersiveBackgroundOpacity();
|
||||||
@@ -102,18 +73,6 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
|||||||
UpdateIsLastFMTrackEnabled();
|
UpdateIsLastFMTrackEnabled();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (message.Sender is LyricsSearchProviderInfo)
|
|
||||||
{
|
|
||||||
if (message.PropertyName == nameof(LyricsSearchProviderInfo.IsEnabled))
|
|
||||||
{
|
|
||||||
_logger.LogInformation("LyricsSearchProviderInfo.IsEnabled changed, refreshing lyrics.");
|
|
||||||
_ = _refreshLyricsRunner.RunAsync(async token =>
|
|
||||||
{
|
|
||||||
await RefreshLyricsAsync(token);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Receive(PropertyChangedMessage<Color> message)
|
public void Receive(PropertyChangedMessage<Color> message)
|
||||||
@@ -163,6 +122,10 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
|||||||
{
|
{
|
||||||
_isAlbumArtCornerRadiusChanged = true;
|
_isAlbumArtCornerRadiusChanged = true;
|
||||||
}
|
}
|
||||||
|
else if (message.PropertyName == nameof(AlbumArtLayoutSettings.CoverImageShadowAmount))
|
||||||
|
{
|
||||||
|
_isAlbumArtShadowAmountChanged = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (message.Sender is LyricsBackgroundSettings)
|
else if (message.Sender is LyricsBackgroundSettings)
|
||||||
{
|
{
|
||||||
@@ -204,6 +167,14 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
|||||||
{
|
{
|
||||||
_isLayoutChanged = true;
|
_isLayoutChanged = true;
|
||||||
}
|
}
|
||||||
|
else if (message.PropertyName == nameof(LyricsEffectSettings.LyricsScrollTopDelay))
|
||||||
|
{
|
||||||
|
_isLayoutChanged = true;
|
||||||
|
}
|
||||||
|
else if (message.PropertyName == nameof(LyricsEffectSettings.LyricsScrollBottomDelay))
|
||||||
|
{
|
||||||
|
_isLayoutChanged = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (message.Sender is LyricsStyleSettings)
|
else if (message.Sender is LyricsStyleSettings)
|
||||||
{
|
{
|
||||||
@@ -220,14 +191,6 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
|||||||
_isLayoutChanged = true;
|
_isLayoutChanged = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (message.Sender is TranslationSettings)
|
|
||||||
{
|
|
||||||
if (message.PropertyName == nameof(TranslationSettings.SelectedTargetLanguageIndex))
|
|
||||||
{
|
|
||||||
_logger.LogInformation("Target language index changed: {Index}", _settingsService.AppSettings.TranslationSettings.SelectedTargetLanguageIndex);
|
|
||||||
UpdateTranslations();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (message.Sender is MediaSourceProviderInfo)
|
else if (message.Sender is MediaSourceProviderInfo)
|
||||||
{
|
{
|
||||||
if (message.PropertyName == nameof(MediaSourceProviderInfo.TimelineSyncThreshold))
|
if (message.PropertyName == nameof(MediaSourceProviderInfo.TimelineSyncThreshold))
|
||||||
@@ -277,7 +240,13 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
|||||||
|
|
||||||
public void Receive(PropertyChangedMessage<LyricsDisplayType> message)
|
public void Receive(PropertyChangedMessage<LyricsDisplayType> message)
|
||||||
{
|
{
|
||||||
_displayTypeReceived = message.NewValue;
|
if (message.Sender is LiveStates)
|
||||||
|
{
|
||||||
|
if (message.PropertyName == nameof(LiveStates.CurrentLyricsDisplayType))
|
||||||
|
{
|
||||||
|
_isDisplayTypeChanged = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Receive(PropertyChangedMessage<LyricsFontColorType> message)
|
public void Receive(PropertyChangedMessage<LyricsFontColorType> message)
|
||||||
@@ -340,9 +309,18 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
|||||||
{
|
{
|
||||||
_isLayoutChanged = true;
|
_isLayoutChanged = true;
|
||||||
}
|
}
|
||||||
else if (message.PropertyName == nameof(LyricsStyleSettings.LyricsTranslationSeparator))
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Receive(PropertyChangedMessage<LyricsWindowMode> message)
|
||||||
|
{
|
||||||
|
if (message.Sender is LiveStates)
|
||||||
|
{
|
||||||
|
if (message.PropertyName == nameof(LiveStates.CurrentLyricsWindowMode))
|
||||||
{
|
{
|
||||||
UpdateTranslations();
|
UpdateColorConfig();
|
||||||
|
UpdateImmersiveBackgroundOpacity();
|
||||||
|
_isLayoutChanged = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
|||||||
private readonly ValueTransition<double> _canvasYScrollTransition = new(
|
private readonly ValueTransition<double> _canvasYScrollTransition = new(
|
||||||
initialValue: 0f,
|
initialValue: 0f,
|
||||||
durationSeconds: 0.3f,
|
durationSeconds: 0.3f,
|
||||||
easingType: EasingType.EaseInOutSine
|
easingType: EasingType.EaseInOutQuad
|
||||||
);
|
);
|
||||||
|
|
||||||
private readonly ValueTransition<Color> _immersiveBgColorTransition = new(
|
private readonly ValueTransition<Color> _immersiveBgColorTransition = new(
|
||||||
@@ -38,25 +38,25 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
|||||||
private readonly ValueTransition<double> _titleXTransition = new(
|
private readonly ValueTransition<double> _titleXTransition = new(
|
||||||
initialValue: 0f,
|
initialValue: 0f,
|
||||||
durationSeconds: 0.3f,
|
durationSeconds: 0.3f,
|
||||||
easingType: EasingType.EaseInOutBack
|
easingType: EasingType.EaseInOutQuad
|
||||||
);
|
);
|
||||||
|
|
||||||
private readonly ValueTransition<double> _titleYTransition = new(
|
private readonly ValueTransition<double> _titleYTransition = new(
|
||||||
initialValue: 0f,
|
initialValue: 0f,
|
||||||
durationSeconds: 0.3f,
|
durationSeconds: 0.3f,
|
||||||
easingType: EasingType.EaseInOutBack
|
easingType: EasingType.EaseInOutQuad
|
||||||
);
|
);
|
||||||
|
|
||||||
private readonly ValueTransition<double> _lyricsXTransition = new(
|
private readonly ValueTransition<double> _lyricsXTransition = new(
|
||||||
initialValue: 0f,
|
initialValue: 0f,
|
||||||
durationSeconds: 0.3f,
|
durationSeconds: 0.3f,
|
||||||
easingType: EasingType.EaseInOutBack
|
easingType: EasingType.EaseInOutQuad
|
||||||
);
|
);
|
||||||
|
|
||||||
private readonly ValueTransition<double> _lyricsYTransition = new(
|
private readonly ValueTransition<double> _lyricsYTransition = new(
|
||||||
initialValue: 0f,
|
initialValue: 0f,
|
||||||
durationSeconds: 0.3f,
|
durationSeconds: 0.3f,
|
||||||
easingType: EasingType.EaseInOutBack
|
easingType: EasingType.EaseInOutQuad
|
||||||
);
|
);
|
||||||
|
|
||||||
private readonly ValueTransition<double> _lyricsOpacityTransition = new(
|
private readonly ValueTransition<double> _lyricsOpacityTransition = new(
|
||||||
@@ -77,13 +77,13 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
|||||||
private readonly ValueTransition<double> _albumArtXTransition = new(
|
private readonly ValueTransition<double> _albumArtXTransition = new(
|
||||||
initialValue: 0f,
|
initialValue: 0f,
|
||||||
durationSeconds: 0.3f,
|
durationSeconds: 0.3f,
|
||||||
easingType: EasingType.EaseInOutBack
|
easingType: EasingType.EaseInOutQuad
|
||||||
);
|
);
|
||||||
|
|
||||||
private readonly ValueTransition<double> _albumArtYTransition = new(
|
private readonly ValueTransition<double> _albumArtYTransition = new(
|
||||||
initialValue: 0f,
|
initialValue: 0f,
|
||||||
durationSeconds: 0.3f,
|
durationSeconds: 0.3f,
|
||||||
easingType: EasingType.EaseInOutBack
|
easingType: EasingType.EaseInOutQuad
|
||||||
);
|
);
|
||||||
|
|
||||||
private readonly ValueTransition<double> _songInfoOpacityTransition = new(
|
private readonly ValueTransition<double> _songInfoOpacityTransition = new(
|
||||||
|
|||||||
@@ -2,12 +2,14 @@
|
|||||||
using BetterLyrics.WinUI3.Helper;
|
using BetterLyrics.WinUI3.Helper;
|
||||||
using BetterLyrics.WinUI3.Models;
|
using BetterLyrics.WinUI3.Models;
|
||||||
using Microsoft.Graphics.Canvas;
|
using Microsoft.Graphics.Canvas;
|
||||||
|
using Microsoft.Graphics.Canvas.Effects;
|
||||||
using Microsoft.Graphics.Canvas.Text;
|
using Microsoft.Graphics.Canvas.Text;
|
||||||
using Microsoft.Graphics.Canvas.UI.Xaml;
|
using Microsoft.Graphics.Canvas.UI.Xaml;
|
||||||
using Microsoft.UI;
|
using Microsoft.UI;
|
||||||
using Microsoft.UI.Xaml;
|
using Microsoft.UI.Xaml;
|
||||||
using Microsoft.UI.Xaml.Controls;
|
using Microsoft.UI.Xaml.Controls;
|
||||||
using Microsoft.UI.Xaml.Media.Imaging;
|
using Microsoft.UI.Xaml.Media.Imaging;
|
||||||
|
using Microsoft.UI.Xaml.Shapes;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
@@ -30,21 +32,25 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
|||||||
private bool _isPlayingLineChanged = false;
|
private bool _isPlayingLineChanged = false;
|
||||||
private bool _isVisibleLinesBoundaryChanged = false;
|
private bool _isVisibleLinesBoundaryChanged = false;
|
||||||
|
|
||||||
private bool _isDebugOverlayEnabledChanged = false;
|
private bool _isDebugOverlayEnabledChanged = true;
|
||||||
|
|
||||||
private bool _albumArtChanged = false;
|
private bool _albumArtChanged = false;
|
||||||
private bool _isCoverAcrylicEffectAmountChanged = false;
|
private bool _isCoverAcrylicEffectAmountChanged = false;
|
||||||
|
|
||||||
private bool _isAlbumArtCornerRadiusChanged = true;
|
private bool _isAlbumArtCornerRadiusChanged = true;
|
||||||
|
private bool _isAlbumArtShadowAmountChanged = false;
|
||||||
|
|
||||||
private bool _isAlbumArtBgOpacityChanged = false;
|
private bool _isAlbumArtBgOpacityChanged = false;
|
||||||
private bool _isAlbumArtBgBlurAmountChanged = false;
|
private bool _isAlbumArtBgBlurAmountChanged = false;
|
||||||
|
|
||||||
|
private bool _isAlbumArtBgEffectChanged = false;
|
||||||
|
private bool _isAlbumArtEffectChanged = false;
|
||||||
|
|
||||||
public void Update(ICanvasAnimatedControl control, CanvasAnimatedUpdateEventArgs args)
|
public void Update(ICanvasAnimatedControl control, CanvasAnimatedUpdateEventArgs args)
|
||||||
{
|
{
|
||||||
_elapsedTime = args.Timing.ElapsedTime;
|
_elapsedTime = args.Timing.ElapsedTime;
|
||||||
|
|
||||||
if (_isPlaying)
|
if (IsPlaying)
|
||||||
{
|
{
|
||||||
TotalTime += _elapsedTime;
|
TotalTime += _elapsedTime;
|
||||||
_totalPlayingTime += _elapsedTime;
|
_totalPlayingTime += _elapsedTime;
|
||||||
@@ -55,18 +61,19 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 检测播放行变更
|
||||||
var playingLineIndex = GetCurrentPlayingLineIndex();
|
var playingLineIndex = GetCurrentPlayingLineIndex();
|
||||||
|
|
||||||
_isCanvasWidthChanged = _canvasWidth != control.Size.Width;
|
|
||||||
_isCanvasHeightChanged = _canvasHeight != control.Size.Height;
|
|
||||||
_isDisplayTypeChanged = _displayType != _displayTypeReceived;
|
|
||||||
_isPlayingLineChanged = _playingLineIndex != playingLineIndex;
|
_isPlayingLineChanged = _playingLineIndex != playingLineIndex;
|
||||||
|
|
||||||
_canvasWidth = control.Size.Width;
|
|
||||||
_canvasHeight = control.Size.Height;
|
|
||||||
_displayType = _displayTypeReceived;
|
|
||||||
_playingLineIndex = playingLineIndex;
|
_playingLineIndex = playingLineIndex;
|
||||||
|
|
||||||
|
// 检测画布宽度变更
|
||||||
|
_isCanvasWidthChanged = _canvasWidth != control.Size.Width;
|
||||||
|
_canvasWidth = control.Size.Width;
|
||||||
|
|
||||||
|
// 检测画布高度变更
|
||||||
|
_isCanvasHeightChanged = _canvasHeight != control.Size.Height;
|
||||||
|
_canvasHeight = control.Size.Height;
|
||||||
|
|
||||||
if (_isDebugOverlayEnabledChanged)
|
if (_isDebugOverlayEnabledChanged)
|
||||||
{
|
{
|
||||||
if (_isDebugOverlayEnabled)
|
if (_isDebugOverlayEnabled)
|
||||||
@@ -81,7 +88,6 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
|||||||
_isDebugOverlayEnabledChanged = false;
|
_isDebugOverlayEnabledChanged = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
_rotateAngle += _coverRotateBaseSpeed * _settingsService.AppSettings.LyricsBackgroundSettings.CoverOverlaySpeed / 100.0;
|
_rotateAngle += _coverRotateBaseSpeed * _settingsService.AppSettings.LyricsBackgroundSettings.CoverOverlaySpeed / 100.0;
|
||||||
_rotateAngle %= Math.PI * 2;
|
_rotateAngle %= Math.PI * 2;
|
||||||
|
|
||||||
@@ -113,7 +119,7 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
|||||||
_albumArtYTransition.StartTransition((_canvasHeight - _albumArtSize * 1.05 - _titleTextFormat.FontSize - _artistTextFormat.FontSize) / 2.0, jumpTo);
|
_albumArtYTransition.StartTransition((_canvasHeight - _albumArtSize * 1.05 - _titleTextFormat.FontSize - _artistTextFormat.FontSize) / 2.0, jumpTo);
|
||||||
_titleYTransition.StartTransition(_albumArtYTransition.TargetValue + _albumArtSize * 1.05, jumpTo);
|
_titleYTransition.StartTransition(_albumArtYTransition.TargetValue + _albumArtSize * 1.05, jumpTo);
|
||||||
_lyricsYTransition.StartTransition(0, jumpTo);
|
_lyricsYTransition.StartTransition(0, jumpTo);
|
||||||
switch (_displayType)
|
switch (_liveStatesService.LiveStates.CurrentLyricsDisplayType)
|
||||||
{
|
{
|
||||||
case LyricsDisplayType.AlbumArtOnly:
|
case LyricsDisplayType.AlbumArtOnly:
|
||||||
_lyricsOpacityTransition.StartTransition(0f, jumpTo);
|
_lyricsOpacityTransition.StartTransition(0f, jumpTo);
|
||||||
@@ -142,7 +148,7 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
|||||||
_lyricsXTransition.StartTransition(_leftMargin, jumpTo);
|
_lyricsXTransition.StartTransition(_leftMargin, jumpTo);
|
||||||
_albumArtXTransition.StartTransition(_leftMargin, jumpTo);
|
_albumArtXTransition.StartTransition(_leftMargin, jumpTo);
|
||||||
_titleXTransition.StartTransition(_leftMargin + _albumArtSize * 1.2, jumpTo);
|
_titleXTransition.StartTransition(_leftMargin + _albumArtSize * 1.2, jumpTo);
|
||||||
switch (_displayType)
|
switch (_liveStatesService.LiveStates.CurrentLyricsDisplayType)
|
||||||
{
|
{
|
||||||
case LyricsDisplayType.AlbumArtOnly:
|
case LyricsDisplayType.AlbumArtOnly:
|
||||||
_lyricsOpacityTransition.StartTransition(0f, jumpTo);
|
_lyricsOpacityTransition.StartTransition(0f, jumpTo);
|
||||||
@@ -169,13 +175,26 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
_isDisplayTypeChanged = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_isAlbumArtCornerRadiusChanged)
|
// 先重置这两个的变化状态
|
||||||
|
_isAlbumArtEffectChanged = false;
|
||||||
|
_isAlbumArtBgEffectChanged = false;
|
||||||
|
|
||||||
|
if (_isAlbumArtCornerRadiusChanged || _isAlbumArtShadowAmountChanged)
|
||||||
{
|
{
|
||||||
UpdateLastFgImageEffect(control);
|
DisposeAlbumArtRenderTarget();
|
||||||
UpdateFgImageEffect(control);
|
UpdateAlbumArtEffect(control);
|
||||||
_isAlbumArtCornerRadiusChanged = false;
|
_isAlbumArtEffectChanged = true;
|
||||||
|
if (_isAlbumArtCornerRadiusChanged)
|
||||||
|
{
|
||||||
|
_isAlbumArtCornerRadiusChanged = false;
|
||||||
|
}
|
||||||
|
if (_isAlbumArtShadowAmountChanged)
|
||||||
|
{
|
||||||
|
_isAlbumArtShadowAmountChanged = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 背景图切换计算
|
// 背景图切换计算
|
||||||
@@ -192,7 +211,7 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
|||||||
_albumArtBgTransition.Reset(0f);
|
_albumArtBgTransition.Reset(0f);
|
||||||
_albumArtBgTransition.StartTransition(1f);
|
_albumArtBgTransition.StartTransition(1f);
|
||||||
}
|
}
|
||||||
// 更新 last
|
// 更新 last 和 current
|
||||||
if (_albumArtChanged)
|
if (_albumArtChanged)
|
||||||
{
|
{
|
||||||
if (_lastAlbumArtSwBitmap != null)
|
if (_lastAlbumArtSwBitmap != null)
|
||||||
@@ -201,12 +220,6 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
|||||||
_lastAlbumArtCanvasBitmap = null;
|
_lastAlbumArtCanvasBitmap = null;
|
||||||
_lastAlbumArtCanvasBitmap = CanvasBitmap.CreateFromSoftwareBitmap(control, _lastAlbumArtSwBitmap);
|
_lastAlbumArtCanvasBitmap = CanvasBitmap.CreateFromSoftwareBitmap(control, _lastAlbumArtSwBitmap);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
UpdateLastFgImageEffect(control);
|
|
||||||
UpdateLastBgImageEffect();
|
|
||||||
// 更新 current
|
|
||||||
if (_albumArtChanged)
|
|
||||||
{
|
|
||||||
if (_albumArtSwBitmap != null)
|
if (_albumArtSwBitmap != null)
|
||||||
{
|
{
|
||||||
_albumArtCanvasBitmap?.Dispose();
|
_albumArtCanvasBitmap?.Dispose();
|
||||||
@@ -214,33 +227,59 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
|||||||
_albumArtCanvasBitmap = CanvasBitmap.CreateFromSoftwareBitmap(control, _albumArtSwBitmap);
|
_albumArtCanvasBitmap = CanvasBitmap.CreateFromSoftwareBitmap(control, _albumArtSwBitmap);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
UpdateFgImageEffect(control);
|
|
||||||
UpdateBgImageEffect();
|
|
||||||
// 更新叠加的背景效果
|
// 更新叠加的背景效果
|
||||||
|
DisposeAlbumArtRenderTarget();
|
||||||
|
UpdateAlbumArtEffect(control);
|
||||||
|
_isAlbumArtEffectChanged = true;
|
||||||
|
|
||||||
|
DisposeAlbumArtBgRenderTarget();
|
||||||
UpdateAlbumArtBgEffect(control);
|
UpdateAlbumArtBgEffect(control);
|
||||||
|
_isAlbumArtBgEffectChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_isCoverAcrylicEffectAmountChanged)
|
if (_isCoverAcrylicEffectAmountChanged)
|
||||||
{
|
{
|
||||||
UpdateCoverAcrylicOverlay(control);
|
UpdateCoverAcrylicOverlay(control);
|
||||||
|
|
||||||
|
DisposeAlbumArtBgRenderTarget();
|
||||||
UpdateAlbumArtBgEffect(control);
|
UpdateAlbumArtBgEffect(control);
|
||||||
|
_isAlbumArtBgEffectChanged = true;
|
||||||
|
|
||||||
_isCoverAcrylicEffectAmountChanged = false;
|
_isCoverAcrylicEffectAmountChanged = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_isAlbumArtBgOpacityChanged)
|
if (_isAlbumArtBgOpacityChanged)
|
||||||
{
|
{
|
||||||
|
DisposeAlbumArtBgRenderTarget();
|
||||||
UpdateAlbumArtBgEffect(control);
|
UpdateAlbumArtBgEffect(control);
|
||||||
|
_isAlbumArtBgEffectChanged = true;
|
||||||
|
|
||||||
_isAlbumArtBgOpacityChanged = false;
|
_isAlbumArtBgOpacityChanged = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_isAlbumArtBgBlurAmountChanged)
|
if (_isAlbumArtBgBlurAmountChanged)
|
||||||
{
|
{
|
||||||
|
DisposeAlbumArtBgRenderTarget();
|
||||||
UpdateAlbumArtBgEffect(control);
|
UpdateAlbumArtBgEffect(control);
|
||||||
|
_isAlbumArtBgEffectChanged = true;
|
||||||
|
|
||||||
_isAlbumArtBgBlurAmountChanged = false;
|
_isAlbumArtBgBlurAmountChanged = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
_albumArtChanged = false;
|
_albumArtChanged = false;
|
||||||
|
|
||||||
|
if (!_isAlbumArtEffectChanged && _albumArtEffect != null)
|
||||||
|
{
|
||||||
|
UpdateAlbumArtRenderTarget(control);
|
||||||
|
DisposeAlbumArtEffect();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_isAlbumArtBgEffectChanged && _albumArtBgEffect != null)
|
||||||
|
{
|
||||||
|
UpdateAlbumArtBgRenderTarget(control);
|
||||||
|
DisposeAlbumArtBgEffect();
|
||||||
|
}
|
||||||
|
|
||||||
if (_isCanvasHeightChanged || _isCanvasWidthChanged || _lyricsXTransition.IsTransitioning)
|
if (_isCanvasHeightChanged || _isCanvasWidthChanged || _lyricsXTransition.IsTransitioning)
|
||||||
{
|
{
|
||||||
_maxLyricsWidth = _canvasWidth - _lyricsXTransition.Value - _rightMargin;
|
_maxLyricsWidth = _canvasWidth - _lyricsXTransition.Value - _rightMargin;
|
||||||
@@ -261,7 +300,7 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
|||||||
|
|
||||||
UpdateVisibleLinesBoundary();
|
UpdateVisibleLinesBoundary();
|
||||||
|
|
||||||
UpdateLinesProps(control);
|
UpdateVisibleLinesProps(control);
|
||||||
|
|
||||||
_isLayoutChanged = false;
|
_isLayoutChanged = false;
|
||||||
|
|
||||||
@@ -287,58 +326,35 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
|||||||
if (control == null)
|
if (control == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (_isDockMode)
|
_lyricsTextFormat.FontSize = _liveStatesService.LiveStates.CurrentLyricsStyleSettings.LyricsFontSize;
|
||||||
{
|
_lyricsTextFormat.FontWeight = _liveStatesService.LiveStates.CurrentLyricsStyleSettings.LyricsFontWeight.ToFontWeight();
|
||||||
_lyricsStyleSettings = _settingsService.AppSettings.DockLyricsStyleSettings;
|
_lyricsTextFormat.FontFamily = _artistTextFormat.FontFamily = _titleTextFormat.FontFamily = _liveStatesService.LiveStates.CurrentLyricsStyleSettings.LyricsFontFamily;
|
||||||
_lyricsEffectSettings = _settingsService.AppSettings.DockLyricsEffectSettings;
|
|
||||||
}
|
|
||||||
else if (_isDesktopMode)
|
|
||||||
{
|
|
||||||
_lyricsStyleSettings = _settingsService.AppSettings.DesktopLyricsStyleSettings;
|
|
||||||
_lyricsEffectSettings = _settingsService.AppSettings.DesktopLyricsEffectSettings;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_lyricsStyleSettings = _settingsService.AppSettings.StandardLyricsStyleSettings;
|
|
||||||
_lyricsEffectSettings = _settingsService.AppSettings.StandardLyricsEffectSettings;
|
|
||||||
}
|
|
||||||
|
|
||||||
_lyricsTextFormat.FontSize = _lyricsStyleSettings.LyricsFontSize;
|
_canvasYScrollTransition.SetDuration(_liveStatesService.LiveStates.CurrentLyricsEffectSettings.LyricsScrollDuration / 1000.0);
|
||||||
_lyricsTextFormat.FontWeight = _lyricsStyleSettings.LyricsFontWeight.ToFontWeight();
|
_canvasYScrollTransition.SetEasingType(_liveStatesService.LiveStates.CurrentLyricsEffectSettings.LyricsScrollEasingType);
|
||||||
_lyricsTextFormat.FontFamily = _artistTextFormat.FontFamily = _titleTextFormat.FontFamily = _lyricsStyleSettings.LyricsFontFamily;
|
|
||||||
|
|
||||||
_canvasYScrollTransition.SetDuration(_lyricsEffectSettings.LyricsScrollDuration / 1000.0);
|
|
||||||
_canvasYScrollTransition.SetEasingType(_lyricsEffectSettings.LyricsScrollEasingType);
|
|
||||||
|
|
||||||
double y = 0;
|
double y = 0;
|
||||||
|
|
||||||
// Init Positions
|
// Init Positions
|
||||||
for (int i = 0; i < _lyricsDataArr.ElementAtOrDefault(_langIndex)?.LyricsLines.Count; i++)
|
for (int i = 0; i < _currentLyricsData?.LyricsLines.Count; i++)
|
||||||
{
|
{
|
||||||
var line = _lyricsDataArr[_langIndex].LyricsLines.ElementAtOrDefault(i);
|
var line = _currentLyricsData?.LyricsLines.ElementAtOrDefault(i);
|
||||||
|
|
||||||
if (line == null)
|
if (line == null)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
line.RecreatePlaceholder(control);
|
|
||||||
|
|
||||||
line.Position = new Vector2(0, (float)y);
|
line.Position = new Vector2(0, (float)y);
|
||||||
line.RecreateTextLayout(control, _lyricsTextFormat, _maxLyricsWidth, _canvasHeight, _lyricsStyleSettings.LyricsAlignmentType);
|
line.RecreateTextLayout(control, _lyricsTextFormat, _maxLyricsWidth, _canvasHeight, _liveStatesService.LiveStates.CurrentLyricsStyleSettings.LyricsAlignmentType);
|
||||||
line.UpdateCenterPosition(_maxLyricsWidth, _lyricsStyleSettings.LyricsAlignmentType);
|
line.UpdateCenterPosition(_maxLyricsWidth, _liveStatesService.LiveStates.CurrentLyricsStyleSettings.LyricsAlignmentType);
|
||||||
|
|
||||||
line.RecreateTextGeometry();
|
line.RecreateTextGeometry();
|
||||||
line.RecreateFontEffect(control, _strokeFontColor, _lyricsStyleSettings.LyricsFontStrokeWidth, _bgFontColor, _fgFontColor);
|
|
||||||
line.RecreateBackgroundEffect(_lyricsOpacityTransition.Value);
|
|
||||||
line.RecreateCurrentLineMask(control);
|
|
||||||
line.RecreateForegroundBlurEffect(control, _lyricsEffectSettings.LyricsGlowEffectScope, _lyricsGlowEffectAmount);
|
|
||||||
line.RecreateForegroundHighlightEffect(control, _lyricsEffectSettings.LyricsHighlightScope);
|
|
||||||
|
|
||||||
y +=
|
y +=
|
||||||
(double)line.CanvasTextLayout!.LayoutBounds.Height
|
(double)line.CanvasTextLayout!.LayoutBounds.Height
|
||||||
/ line.CanvasTextLayout.LineCount
|
/ line.CanvasTextLayout.LineCount
|
||||||
* (line.CanvasTextLayout.LineCount + _lyricsStyleSettings.LyricsLineSpacingFactor);
|
* (line.CanvasTextLayout.LineCount + _liveStatesService.LiveStates.CurrentLyricsStyleSettings.LyricsLineSpacingFactor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -350,7 +366,7 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
|||||||
|
|
||||||
// Set _scrollOffsetY
|
// Set _scrollOffsetY
|
||||||
|
|
||||||
LyricsLine? currentPlayingLine = _lyricsDataArr.ElementAtOrDefault(_langIndex)?.LyricsLines.ElementAtOrDefault(_playingLineIndex);
|
LyricsLine? currentPlayingLine = _currentLyricsData?.LyricsLines.ElementAtOrDefault(_playingLineIndex);
|
||||||
|
|
||||||
if (currentPlayingLine == null) return;
|
if (currentPlayingLine == null) return;
|
||||||
|
|
||||||
@@ -358,7 +374,7 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
|||||||
|
|
||||||
if (playingTextLayout == null) return;
|
if (playingTextLayout == null) return;
|
||||||
|
|
||||||
double? targetYScrollOffset = -currentPlayingLine!.Position.Y + _lyricsDataArr.ElementAtOrDefault(_langIndex)?.LyricsLines[0].Position.Y - playingTextLayout.LayoutBounds.Height / 2.0;
|
double? targetYScrollOffset = -currentPlayingLine!.Position.Y + _currentLyricsData?.LyricsLines[0].Position.Y - playingTextLayout.LayoutBounds.Height / 2.0;
|
||||||
|
|
||||||
if (!targetYScrollOffset.HasValue) return;
|
if (!targetYScrollOffset.HasValue) return;
|
||||||
|
|
||||||
@@ -369,7 +385,7 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
|||||||
{
|
{
|
||||||
var (startLineIndex, endLineIndex) = GetMaxLyricsLineIndexBoundaries();
|
var (startLineIndex, endLineIndex) = GetMaxLyricsLineIndexBoundaries();
|
||||||
|
|
||||||
var lines = _lyricsDataArr.ElementAtOrDefault(_langIndex)?.LyricsLines;
|
var lines = _currentLyricsData?.LyricsLines;
|
||||||
if (lines == null || lines.Count == 0) return;
|
if (lines == null || lines.Count == 0) return;
|
||||||
|
|
||||||
double offset = _canvasYScrollTransition.Value + _canvasHeight / 2;
|
double offset = _canvasYScrollTransition.Value + _canvasHeight / 2;
|
||||||
@@ -435,7 +451,8 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
|||||||
|
|
||||||
private void UpdateColorConfig()
|
private void UpdateColorConfig()
|
||||||
{
|
{
|
||||||
if (_isDesktopMode || _isDockMode)
|
if (_liveStatesService.LiveStates.CurrentLyricsWindowMode == LyricsWindowMode.DesktopMode ||
|
||||||
|
_liveStatesService.LiveStates.CurrentLyricsWindowMode == LyricsWindowMode.DockMode)
|
||||||
{
|
{
|
||||||
ThemeTypeSent = Helper.ColorHelper.GetElementThemeFromBackgroundColor(_environmentalColor);
|
ThemeTypeSent = Helper.ColorHelper.GetElementThemeFromBackgroundColor(_environmentalColor);
|
||||||
}
|
}
|
||||||
@@ -445,7 +462,6 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
|||||||
}
|
}
|
||||||
|
|
||||||
double brightness;
|
double brightness;
|
||||||
Color grayedEnvironmentalColor = Colors.Transparent;
|
|
||||||
|
|
||||||
bool isLight = ThemeTypeSent switch
|
bool isLight = ThemeTypeSent switch
|
||||||
{
|
{
|
||||||
@@ -459,20 +475,21 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
|||||||
{
|
{
|
||||||
_adaptiveGrayedFontColor = _darkColor;
|
_adaptiveGrayedFontColor = _darkColor;
|
||||||
brightness = 0.7f;
|
brightness = 0.7f;
|
||||||
grayedEnvironmentalColor = _lightColor;
|
_grayedEnvironmentalColor = _lightColor;
|
||||||
_albumArtAccentColorTransition.StartTransition(_albumArtLightAccentColor);
|
_albumArtAccentColorTransition.StartTransition(_albumArtLightAccentColor);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_adaptiveGrayedFontColor = _lightColor;
|
_adaptiveGrayedFontColor = _lightColor;
|
||||||
brightness = 0.3f;
|
brightness = 0.3f;
|
||||||
grayedEnvironmentalColor = _darkColor;
|
_grayedEnvironmentalColor = _darkColor;
|
||||||
_albumArtAccentColorTransition.StartTransition(_albumArtDarkAccentColor);
|
_albumArtAccentColorTransition.StartTransition(_albumArtDarkAccentColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
_lyricsBgBrightnessTransition.StartTransition(brightness);
|
_lyricsBgBrightnessTransition.StartTransition(brightness);
|
||||||
|
|
||||||
if (_isDesktopMode || _isDockMode)
|
if (_liveStatesService.LiveStates.CurrentLyricsWindowMode == LyricsWindowMode.DockMode ||
|
||||||
|
_liveStatesService.LiveStates.CurrentLyricsWindowMode == LyricsWindowMode.DesktopMode)
|
||||||
{
|
{
|
||||||
_adaptiveColoredFontColor = Helper.ColorHelper.GetForegroundColor(_environmentalColor);
|
_adaptiveColoredFontColor = Helper.ColorHelper.GetForegroundColor(_environmentalColor);
|
||||||
}
|
}
|
||||||
@@ -488,7 +505,7 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (_lyricsStyleSettings.LyricsBgFontColorType)
|
switch (_liveStatesService.LiveStates.CurrentLyricsStyleSettings.LyricsBgFontColorType)
|
||||||
{
|
{
|
||||||
case LyricsFontColorType.AdaptiveGrayed:
|
case LyricsFontColorType.AdaptiveGrayed:
|
||||||
_bgFontColor = _adaptiveGrayedFontColor;
|
_bgFontColor = _adaptiveGrayedFontColor;
|
||||||
@@ -497,13 +514,13 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
|||||||
_bgFontColor = _adaptiveColoredFontColor ?? _adaptiveGrayedFontColor;
|
_bgFontColor = _adaptiveColoredFontColor ?? _adaptiveGrayedFontColor;
|
||||||
break;
|
break;
|
||||||
case LyricsFontColorType.Custom:
|
case LyricsFontColorType.Custom:
|
||||||
_bgFontColor = _lyricsStyleSettings.LyricsCustomBgFontColor;
|
_bgFontColor = _liveStatesService.LiveStates.CurrentLyricsStyleSettings.LyricsCustomBgFontColor;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (_lyricsStyleSettings.LyricsFgFontColorType)
|
switch (_liveStatesService.LiveStates.CurrentLyricsStyleSettings.LyricsFgFontColorType)
|
||||||
{
|
{
|
||||||
case LyricsFontColorType.AdaptiveGrayed:
|
case LyricsFontColorType.AdaptiveGrayed:
|
||||||
_fgFontColor = _adaptiveGrayedFontColor;
|
_fgFontColor = _adaptiveGrayedFontColor;
|
||||||
@@ -512,22 +529,22 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
|||||||
_fgFontColor = _adaptiveColoredFontColor ?? _adaptiveGrayedFontColor;
|
_fgFontColor = _adaptiveColoredFontColor ?? _adaptiveGrayedFontColor;
|
||||||
break;
|
break;
|
||||||
case LyricsFontColorType.Custom:
|
case LyricsFontColorType.Custom:
|
||||||
_fgFontColor = _lyricsStyleSettings.LyricsCustomFgFontColor;
|
_fgFontColor = _liveStatesService.LiveStates.CurrentLyricsStyleSettings.LyricsCustomFgFontColor;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (_lyricsStyleSettings.LyricsStrokeFontColorType)
|
switch (_liveStatesService.LiveStates.CurrentLyricsStyleSettings.LyricsStrokeFontColorType)
|
||||||
{
|
{
|
||||||
case LyricsFontColorType.AdaptiveGrayed:
|
case LyricsFontColorType.AdaptiveGrayed:
|
||||||
_strokeFontColor = grayedEnvironmentalColor.WithBrightness(0.7);
|
_strokeFontColor = _grayedEnvironmentalColor.WithBrightness(0.7);
|
||||||
break;
|
break;
|
||||||
case LyricsFontColorType.AdaptiveColored:
|
case LyricsFontColorType.AdaptiveColored:
|
||||||
_strokeFontColor = _environmentalColor.WithBrightness(0.7);
|
_strokeFontColor = _environmentalColor.WithBrightness(0.7);
|
||||||
break;
|
break;
|
||||||
case LyricsFontColorType.Custom:
|
case LyricsFontColorType.Custom:
|
||||||
_strokeFontColor = _lyricsStyleSettings.LyricsCustomStrokeFontColor;
|
_strokeFontColor = _liveStatesService.LiveStates.CurrentLyricsStyleSettings.LyricsCustomStrokeFontColor;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@@ -536,38 +553,18 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
|||||||
_isLayoutChanged = true;
|
_isLayoutChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateLinesProps(ICanvasAnimatedControl control)
|
private void UpdateVisibleLinesProps(ICanvasAnimatedControl control)
|
||||||
{
|
{
|
||||||
var currentPlayingLine = _lyricsDataArr
|
var currentPlayingLine = _currentLyricsData?.LyricsLines.ElementAtOrDefault(_playingLineIndex);
|
||||||
.ElementAtOrDefault(_langIndex)
|
|
||||||
?.LyricsLines.ElementAtOrDefault(_playingLineIndex);
|
|
||||||
|
|
||||||
if (currentPlayingLine == null) return;
|
if (currentPlayingLine == null) return;
|
||||||
|
|
||||||
for (int i = _startVisibleLineIndex; i <= _endVisibleLineIndex + 1; i++)
|
for (int i = _startVisibleLineIndex; i <= _endVisibleLineIndex + 1; i++)
|
||||||
{
|
{
|
||||||
var line = _lyricsDataArr.ElementAtOrDefault(_langIndex)?.LyricsLines.ElementAtOrDefault(i);
|
var line = _currentLyricsData?.LyricsLines.ElementAtOrDefault(i);
|
||||||
|
|
||||||
if (line == null) continue;
|
if (line == null) continue;
|
||||||
|
|
||||||
line.UpdateBackgroundEffect(_lyricsOpacityTransition.Value);
|
|
||||||
|
|
||||||
if (i == _playingLineIndex)
|
|
||||||
{
|
|
||||||
GetLinePlayingProgress(
|
|
||||||
_playingLineIndex,
|
|
||||||
out int charStartIndex,
|
|
||||||
out int charLength,
|
|
||||||
out double charProgress
|
|
||||||
);
|
|
||||||
|
|
||||||
line.RecreateCurrentCharMask(control, charStartIndex, charLength, charProgress);
|
|
||||||
line.RecreateLineStartToCurrentCharMask(control, charStartIndex, charLength, charProgress);
|
|
||||||
|
|
||||||
line.UpdateForegroundBlurEffect(control, _lyricsEffectSettings.LyricsGlowEffectScope, _lyricsGlowEffectAmount);
|
|
||||||
line.UpdateForegroundHighlightEffect(control, _lyricsEffectSettings.LyricsHighlightScope);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_isLayoutChanged || _isPlayingLineChanged)
|
if (_isLayoutChanged || _isPlayingLineChanged)
|
||||||
{
|
{
|
||||||
int lineCountDelta = i - _playingLineIndex;
|
int lineCountDelta = i - _playingLineIndex;
|
||||||
@@ -575,7 +572,7 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
|||||||
double distanceFromPlayingLine = Math.Abs(line.Position.Y - currentPlayingLine.Position.Y);
|
double distanceFromPlayingLine = Math.Abs(line.Position.Y - currentPlayingLine.Position.Y);
|
||||||
double distanceFactor = Math.Clamp(distanceFromPlayingLine / (_canvasHeight / 2), 0, 1);
|
double distanceFactor = Math.Clamp(distanceFromPlayingLine / (_canvasHeight / 2), 0, 1);
|
||||||
|
|
||||||
line.AngleTransition.StartTransition(_lyricsEffectSettings.IsFanLyricsEnabled
|
line.AngleTransition.StartTransition(_liveStatesService.LiveStates.CurrentLyricsEffectSettings.IsFanLyricsEnabled
|
||||||
? Math.PI
|
? Math.PI
|
||||||
* (30.0 / 180.0)
|
* (30.0 / 180.0)
|
||||||
* distanceFactor
|
* distanceFactor
|
||||||
@@ -583,27 +580,40 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
|||||||
: 0
|
: 0
|
||||||
);
|
);
|
||||||
|
|
||||||
line.BlurAmountTransition.StartTransition(_lyricsEffectSettings.LyricsBlurAmount * distanceFactor);
|
line.BlurAmountTransition.StartTransition(_liveStatesService.LiveStates.CurrentLyricsEffectSettings.LyricsBlurAmount * distanceFactor);
|
||||||
line.ScaleTransition.StartTransition(_highlightedScale - distanceFactor * (_highlightedScale - _defaultScale));
|
line.ScaleTransition.StartTransition(_highlightedScale - distanceFactor * (_highlightedScale - _defaultScale));
|
||||||
line.OpacityTransition.StartTransition(_lyricsStyleSettings.LyricsBgFontOpacity / 100.0 - distanceFactor * _lyricsStyleSettings.LyricsBgFontOpacity / 100.0 * (1 - _lyricsEffectSettings.LyricsVerticalEdgeOpacity / 100.0));
|
line.OpacityTransition.StartTransition(
|
||||||
|
_liveStatesService.LiveStates.CurrentLyricsStyleSettings.LyricsBgFontOpacity / 100.0 -
|
||||||
|
distanceFactor * _liveStatesService.LiveStates.CurrentLyricsStyleSettings.LyricsBgFontOpacity / 100.0 *
|
||||||
|
(1 - _liveStatesService.LiveStates.CurrentLyricsEffectSettings.LyricsVerticalEdgeOpacity / 100.0));
|
||||||
line.HighlightOpacityTransition.StartTransition(i == _playingLineIndex ? 1f : 0f);
|
line.HighlightOpacityTransition.StartTransition(i == _playingLineIndex ? 1f : 0f);
|
||||||
|
|
||||||
double yScrollDuration;
|
double yScrollDuration;
|
||||||
|
double yScrollDelay;
|
||||||
|
|
||||||
if (lineCountDelta < 0)
|
if (lineCountDelta < 0)
|
||||||
{
|
{
|
||||||
yScrollDuration = _canvasYScrollTransition.DurationSeconds + distanceFactor * (_lyricsEffectSettings.LyricsScrollTopDuration / 1000.0 - _canvasYScrollTransition.DurationSeconds);
|
yScrollDuration =
|
||||||
|
_canvasYScrollTransition.DurationSeconds +
|
||||||
|
distanceFactor * (_liveStatesService.LiveStates.CurrentLyricsEffectSettings.LyricsScrollTopDuration / 1000.0 - _canvasYScrollTransition.DurationSeconds);
|
||||||
|
yScrollDelay = distanceFactor * _liveStatesService.LiveStates.CurrentLyricsEffectSettings.LyricsScrollTopDelay / 1000.0;
|
||||||
}
|
}
|
||||||
else if (lineCountDelta == 0)
|
else if (lineCountDelta == 0)
|
||||||
{
|
{
|
||||||
yScrollDuration = _canvasYScrollTransition.DurationSeconds;
|
yScrollDuration = _canvasYScrollTransition.DurationSeconds;
|
||||||
|
yScrollDelay = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
yScrollDuration = _canvasYScrollTransition.DurationSeconds + distanceFactor * (_lyricsEffectSettings.LyricsScrollBottomDuration / 1000.0 - _canvasYScrollTransition.DurationSeconds);
|
yScrollDuration =
|
||||||
|
_canvasYScrollTransition.DurationSeconds +
|
||||||
|
distanceFactor * (_liveStatesService.LiveStates.CurrentLyricsEffectSettings.LyricsScrollBottomDuration / 1000.0 - _canvasYScrollTransition.DurationSeconds);
|
||||||
|
yScrollDelay = distanceFactor * _liveStatesService.LiveStates.CurrentLyricsEffectSettings.LyricsScrollBottomDelay / 1000.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
line.YOffsetTransition.SetEasingType(_canvasYScrollTransition.EasingType ?? EasingType.Linear);
|
line.YOffsetTransition.SetEasingType(_canvasYScrollTransition.EasingType ?? EasingType.Linear);
|
||||||
line.YOffsetTransition.SetDuration(yScrollDuration);
|
line.YOffsetTransition.SetDuration(yScrollDuration);
|
||||||
|
line.YOffsetTransition.SetDelay(yScrollDelay);
|
||||||
line.YOffsetTransition.StartTransition(_canvasTargetYScrollOffset, _isLayoutChanged);
|
line.YOffsetTransition.StartTransition(_canvasTargetYScrollOffset, _isLayoutChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -619,7 +629,7 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
|||||||
private void UpdateImmersiveBackgroundOpacity()
|
private void UpdateImmersiveBackgroundOpacity()
|
||||||
{
|
{
|
||||||
double targetOpacity;
|
double targetOpacity;
|
||||||
if (_isDesktopMode)
|
if (_liveStatesService.LiveStates.CurrentLyricsWindowMode == LyricsWindowMode.DesktopMode)
|
||||||
{
|
{
|
||||||
if (_isLyricsWindowLocked)
|
if (_isLyricsWindowLocked)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -8,11 +8,13 @@ using BetterLyrics.WinUI3.Models.Settings;
|
|||||||
using BetterLyrics.WinUI3.Services;
|
using BetterLyrics.WinUI3.Services;
|
||||||
using BetterLyrics.WinUI3.Services.LastFMService;
|
using BetterLyrics.WinUI3.Services.LastFMService;
|
||||||
using BetterLyrics.WinUI3.Services.LibWatcherService;
|
using BetterLyrics.WinUI3.Services.LibWatcherService;
|
||||||
|
using BetterLyrics.WinUI3.Services.LiveStatesService;
|
||||||
using BetterLyrics.WinUI3.Services.LyricsSearchService;
|
using BetterLyrics.WinUI3.Services.LyricsSearchService;
|
||||||
using BetterLyrics.WinUI3.Services.MediaSessionsService;
|
using BetterLyrics.WinUI3.Services.MediaSessionsService;
|
||||||
using BetterLyrics.WinUI3.Services.SettingsService;
|
using BetterLyrics.WinUI3.Services.SettingsService;
|
||||||
using BetterLyrics.WinUI3.Services.TranslateService;
|
using BetterLyrics.WinUI3.Services.TranslateService;
|
||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
|
using CommunityToolkit.Mvvm.DependencyInjection;
|
||||||
using CommunityToolkit.WinUI;
|
using CommunityToolkit.WinUI;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Microsoft.Graphics.Canvas;
|
using Microsoft.Graphics.Canvas;
|
||||||
@@ -33,8 +35,8 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
|||||||
{
|
{
|
||||||
public partial class LyricsRendererViewModel : BaseViewModel
|
public partial class LyricsRendererViewModel : BaseViewModel
|
||||||
{
|
{
|
||||||
private LyricsStyleSettings _lyricsStyleSettings;
|
[ObservableProperty]
|
||||||
private LyricsEffectSettings _lyricsEffectSettings;
|
public partial AppSettings AppSettings { get; set; }
|
||||||
|
|
||||||
private bool _isLastFMTrackEnabled = false;
|
private bool _isLastFMTrackEnabled = false;
|
||||||
private bool _isLastFMTracked = false;
|
private bool _isLastFMTracked = false;
|
||||||
@@ -54,14 +56,15 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
|||||||
private int _drawFrameCount = 0;
|
private int _drawFrameCount = 0;
|
||||||
private int _displayedDrawFrameCount = 0;
|
private int _displayedDrawFrameCount = 0;
|
||||||
|
|
||||||
private Queue<SoftwareBitmap?> _cachedAlbumArtSwBitmaps = [];
|
|
||||||
|
|
||||||
private SoftwareBitmap? _lastAlbumArtSwBitmap = null;
|
private SoftwareBitmap? _lastAlbumArtSwBitmap = null;
|
||||||
private SoftwareBitmap? _albumArtSwBitmap = null;
|
private SoftwareBitmap? _albumArtSwBitmap = null;
|
||||||
|
|
||||||
private CanvasBitmap? _lastAlbumArtCanvasBitmap = null;
|
private CanvasBitmap? _lastAlbumArtCanvasBitmap = null;
|
||||||
private CanvasBitmap? _albumArtCanvasBitmap = null;
|
private CanvasBitmap? _albumArtCanvasBitmap = null;
|
||||||
|
|
||||||
|
private CanvasRenderTarget? _albumArtBgRenderTarget;
|
||||||
|
private CanvasRenderTarget? _albumArtRenderTarget;
|
||||||
|
|
||||||
private CanvasBitmap? _coverAcrylicNoiseCanvasBitmap = null;
|
private CanvasBitmap? _coverAcrylicNoiseCanvasBitmap = null;
|
||||||
|
|
||||||
private double _albumArtSize = 0f;
|
private double _albumArtSize = 0f;
|
||||||
@@ -83,24 +86,12 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
|||||||
|
|
||||||
private double _canvasTargetYScrollOffset = 0;
|
private double _canvasTargetYScrollOffset = 0;
|
||||||
|
|
||||||
[ObservableProperty]
|
|
||||||
[NotifyPropertyChangedRecipients]
|
|
||||||
public partial LyricsSearchProvider? LyricsSearchProvider { get; set; } = null;
|
|
||||||
|
|
||||||
[ObservableProperty]
|
|
||||||
[NotifyPropertyChangedRecipients]
|
|
||||||
public partial TranslationSearchProvider? TranslationSearchProvider { get; set; } = null;
|
|
||||||
|
|
||||||
private readonly double _lyricsGlowEffectAmount = 8f;
|
|
||||||
|
|
||||||
private double _maxLyricsWidth = 0f;
|
private double _maxLyricsWidth = 0f;
|
||||||
|
|
||||||
private readonly ISettingsService _settingsService;
|
private readonly ISettingsService _settingsService;
|
||||||
private readonly ILyricsSearchService _lyrcsSearchService;
|
|
||||||
private readonly ILibWatcherService _libWatcherService;
|
|
||||||
private readonly IMediaSessionsService _mediaSessionsService;
|
private readonly IMediaSessionsService _mediaSessionsService;
|
||||||
private readonly ITranslateService _translateService;
|
|
||||||
private readonly ILastFMService _lastFMService;
|
private readonly ILastFMService _lastFMService;
|
||||||
|
private readonly ILiveStatesService _liveStatesService;
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
|
|
||||||
private readonly double _leftMargin = 36f;
|
private readonly double _leftMargin = 36f;
|
||||||
@@ -115,6 +106,7 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
|||||||
private Color _albumArtLightAccentColor = Colors.Transparent;
|
private Color _albumArtLightAccentColor = Colors.Transparent;
|
||||||
private Color _albumArtDarkAccentColor = Colors.Transparent;
|
private Color _albumArtDarkAccentColor = Colors.Transparent;
|
||||||
private Color _environmentalColor = Colors.Transparent;
|
private Color _environmentalColor = Colors.Transparent;
|
||||||
|
private Color _grayedEnvironmentalColor = Colors.Transparent;
|
||||||
|
|
||||||
private Color _lightColor = Colors.White;
|
private Color _lightColor = Colors.White;
|
||||||
private Color _darkColor = Colors.Black;
|
private Color _darkColor = Colors.Black;
|
||||||
@@ -128,21 +120,18 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
|||||||
private int _startVisibleLineIndex = -1;
|
private int _startVisibleLineIndex = -1;
|
||||||
private int _endVisibleLineIndex = -1;
|
private int _endVisibleLineIndex = -1;
|
||||||
|
|
||||||
private bool _isDebugOverlayEnabled = false;
|
private LyricsData? _currentLyricsData;
|
||||||
private bool _isDesktopMode = false;
|
|
||||||
private bool _isDockMode = false;
|
|
||||||
|
|
||||||
private bool _isPlaying = true;
|
private bool _isDebugOverlayEnabled = false;
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
public partial bool IsPlaying { get; set; } = false;
|
||||||
|
|
||||||
private bool _isLyricsWindowLocked = false;
|
private bool _isLyricsWindowLocked = false;
|
||||||
private bool _isMouseWithinWindow = false;
|
private bool _isMouseWithinWindow = false;
|
||||||
|
|
||||||
private bool _isLayoutChanged = true;
|
private bool _isLayoutChanged = true;
|
||||||
|
|
||||||
private int _langIndex = 0;
|
|
||||||
|
|
||||||
private List<LyricsData> _lyricsDataArr = [];
|
|
||||||
|
|
||||||
private int _timelineSyncThreshold = 0;
|
private int _timelineSyncThreshold = 0;
|
||||||
|
|
||||||
private CanvasTextFormat _lyricsTextFormat = new()
|
private CanvasTextFormat _lyricsTextFormat = new()
|
||||||
@@ -175,17 +164,8 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
|||||||
FontWeight = FontWeights.ExtraBlack,
|
FontWeight = FontWeights.ExtraBlack,
|
||||||
};
|
};
|
||||||
|
|
||||||
private LatestOnlyTaskRunner _refreshLyricsRunner = new();
|
|
||||||
private LatestOnlyTaskRunner _showTranslationsRunner = new();
|
|
||||||
|
|
||||||
private LyricsDisplayType _displayTypeReceived;
|
|
||||||
private LyricsDisplayType _displayType;
|
|
||||||
|
|
||||||
private LyricsLayoutOrientation _lyricsLayoutOrientation;
|
private LyricsLayoutOrientation _lyricsLayoutOrientation;
|
||||||
|
|
||||||
[ObservableProperty]
|
|
||||||
public partial bool IsTranslating { get; set; } = false;
|
|
||||||
|
|
||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
public partial SongInfo? SongInfo { get; set; }
|
public partial SongInfo? SongInfo { get; set; }
|
||||||
|
|
||||||
@@ -193,16 +173,53 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
|||||||
[NotifyPropertyChangedRecipients]
|
[NotifyPropertyChangedRecipients]
|
||||||
public partial ElementTheme ThemeTypeSent { get; set; }
|
public partial ElementTheme ThemeTypeSent { get; set; }
|
||||||
|
|
||||||
|
public LyricsRendererViewModel(
|
||||||
|
ISettingsService settingsService,
|
||||||
|
IMediaSessionsService mediaSessionsService,
|
||||||
|
ILastFMService lastFMService,
|
||||||
|
ILiveStatesService liveStatesService)
|
||||||
|
{
|
||||||
|
_settingsService = settingsService;
|
||||||
|
_mediaSessionsService = mediaSessionsService;
|
||||||
|
_liveStatesService = liveStatesService;
|
||||||
|
|
||||||
|
_lastFMService = lastFMService;
|
||||||
|
|
||||||
|
_logger = Ioc.Default.GetRequiredService<ILogger<LyricsRendererViewModel>>();
|
||||||
|
|
||||||
|
AppSettings = _settingsService.AppSettings;
|
||||||
|
|
||||||
|
_titleTextFormat.HorizontalAlignment = _artistTextFormat.HorizontalAlignment = _settingsService.AppSettings.AlbumArtLayoutSettings.SongInfoAlignmentType.ToCanvasHorizontalAlignment();
|
||||||
|
|
||||||
|
_timelineSyncThreshold = 0;
|
||||||
|
|
||||||
|
_mediaSessionsService.IsPlayingChanged += MediaSessionsService_IsPlayingChanged;
|
||||||
|
_mediaSessionsService.SongInfoChanged += MediaSessionsService_SongInfoChanged;
|
||||||
|
_mediaSessionsService.AlbumArtChanged += MediaSessionsService_AlbumArtChangedChanged;
|
||||||
|
_mediaSessionsService.LyricsChanged += MediaSessionsService_LyricsChanged;
|
||||||
|
_mediaSessionsService.TimelineChanged += MediaSessionsService_TimelineChanged;
|
||||||
|
|
||||||
|
IsPlaying = _mediaSessionsService.IsPlaying;
|
||||||
|
|
||||||
|
UpdateColorConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void MediaSessionsService_LyricsChanged(object? sender, LyricsChangedEventArgs e)
|
||||||
|
{
|
||||||
|
_currentLyricsData = e.LyricsData;
|
||||||
|
_isLayoutChanged = true;
|
||||||
|
}
|
||||||
|
|
||||||
private int GetCurrentPlayingLineIndex()
|
private int GetCurrentPlayingLineIndex()
|
||||||
{
|
{
|
||||||
var totalMs = TotalTime.TotalMilliseconds + _positionOffset.TotalMilliseconds;
|
var totalMs = TotalTime.TotalMilliseconds + _positionOffset.TotalMilliseconds;
|
||||||
if (totalMs < _lyricsDataArr.ElementAtOrDefault(_langIndex)?.LyricsLines.FirstOrDefault()?.StartMs) return 0;
|
if (totalMs < _currentLyricsData?.LyricsLines.FirstOrDefault()?.StartMs) return 0;
|
||||||
|
|
||||||
for (int i = 0; i < _lyricsDataArr.ElementAtOrDefault(_langIndex)?.LyricsLines.Count; i++)
|
for (int i = 0; i < _currentLyricsData?.LyricsLines.Count; i++)
|
||||||
{
|
{
|
||||||
var line = _lyricsDataArr.ElementAtOrDefault(_langIndex)?.LyricsLines.ElementAtOrDefault(i);
|
var line = _currentLyricsData?.LyricsLines.ElementAtOrDefault(i);
|
||||||
if (line == null) continue;
|
if (line == null) continue;
|
||||||
var nextLine = _lyricsDataArr.ElementAtOrDefault(_langIndex)?.LyricsLines.ElementAtOrDefault(i + 1);
|
var nextLine = _currentLyricsData?.LyricsLines.ElementAtOrDefault(i + 1);
|
||||||
if (nextLine != null && line.StartMs <= totalMs && totalMs < nextLine.StartMs)
|
if (nextLine != null && line.StartMs <= totalMs && totalMs < nextLine.StartMs)
|
||||||
{
|
{
|
||||||
return i;
|
return i;
|
||||||
@@ -222,9 +239,9 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
|||||||
charLength = 0;
|
charLength = 0;
|
||||||
charProgress = 0f;
|
charProgress = 0f;
|
||||||
|
|
||||||
var line = _lyricsDataArr.ElementAtOrDefault(_langIndex)?.LyricsLines.ElementAtOrDefault(lineIndex);
|
var line = _currentLyricsData?.LyricsLines.ElementAtOrDefault(lineIndex);
|
||||||
if (line == null) return;
|
if (line == null) return;
|
||||||
var nextLine = _lyricsDataArr.ElementAtOrDefault(_langIndex)?.LyricsLines.ElementAtOrDefault(lineIndex + 1);
|
var nextLine = _currentLyricsData?.LyricsLines.ElementAtOrDefault(lineIndex + 1);
|
||||||
|
|
||||||
int lineEndMs;
|
int lineEndMs;
|
||||||
if (line.EndMs != null) lineEndMs = line.EndMs.Value;
|
if (line.EndMs != null) lineEndMs = line.EndMs.Value;
|
||||||
@@ -309,31 +326,22 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
|||||||
{
|
{
|
||||||
if (
|
if (
|
||||||
SongInfo == null
|
SongInfo == null
|
||||||
|| _lyricsDataArr.ElementAtOrDefault(_langIndex) == null
|
|| _currentLyricsData == null
|
||||||
|| _lyricsDataArr[_langIndex].LyricsLines.Count == 0
|
|| _currentLyricsData.LyricsLines.Count == 0
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
return new Tuple<int, int>(-1, -1);
|
return new Tuple<int, int>(-1, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Tuple<int, int>(0, _lyricsDataArr[_langIndex].LyricsLines.Count - 1);
|
return new Tuple<int, int>(0, _currentLyricsData.LyricsLines.Count - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void LibWatcherService_MusicLibraryFilesChanged(object? sender, LibChangedEventArgs e)
|
private void MediaSessionsService_IsPlayingChanged(object? sender, IsPlayingChangedEventArgs e)
|
||||||
{
|
{
|
||||||
_logger.LogInformation("Music library files changed: {ChangeType} {FilePath}, refreshing lyrics...", e.ChangeType, e.FilePath);
|
IsPlaying = e.IsPlaying;
|
||||||
_ = _refreshLyricsRunner.RunAsync(async token =>
|
|
||||||
{
|
|
||||||
await RefreshLyricsAsync(token);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void PlaybackService_IsPlayingChanged(object? sender, IsPlayingChangedEventArgs e)
|
private void MediaSessionsService_TimelineChanged(object? sender, TimelineChangedEventArgs e)
|
||||||
{
|
|
||||||
_isPlaying = e.IsPlaying;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void PlaybackService_TimelineChanged(object? sender, TimelineChangedEventArgs e)
|
|
||||||
{
|
{
|
||||||
var diff = Math.Abs(TotalTime.TotalMilliseconds - e.Position.TotalMilliseconds);
|
var diff = Math.Abs(TotalTime.TotalMilliseconds - e.Position.TotalMilliseconds);
|
||||||
if (diff >= _timelineSyncThreshold)
|
if (diff >= _timelineSyncThreshold)
|
||||||
@@ -352,7 +360,7 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void PlaybackService_SongInfoChanged(object? sender, SongInfoChangedEventArgs e)
|
private void MediaSessionsService_SongInfoChanged(object? sender, SongInfoChangedEventArgs e)
|
||||||
{
|
{
|
||||||
SongInfo = e.SongInfo;
|
SongInfo = e.SongInfo;
|
||||||
|
|
||||||
@@ -373,11 +381,6 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
|||||||
_songInfoOpacityTransition.Reset(0f);
|
_songInfoOpacityTransition.Reset(0f);
|
||||||
_songInfoOpacityTransition.StartTransition(1f);
|
_songInfoOpacityTransition.StartTransition(1f);
|
||||||
|
|
||||||
_logger.LogInformation("Song info changed: Title={Title}, Artist={Artist}, refreshing lyrics...", _songTitle, _songArtist);
|
|
||||||
_ = _refreshLyricsRunner.RunAsync(async token =>
|
|
||||||
{
|
|
||||||
await RefreshLyricsAsync(token);
|
|
||||||
});
|
|
||||||
TotalTime = TimeSpan.Zero;
|
TotalTime = TimeSpan.Zero;
|
||||||
|
|
||||||
// 处理 Last.fm 追踪
|
// 处理 Last.fm 追踪
|
||||||
@@ -386,216 +389,17 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void PlaybackService_AlbumArtChangedChanged(object? sender, AlbumArtChangedEventArgs e)
|
private void MediaSessionsService_AlbumArtChangedChanged(object? sender, AlbumArtChangedEventArgs e)
|
||||||
{
|
{
|
||||||
if (e.AlbumArtSwBitmap != _albumArtSwBitmap)
|
_lastAlbumArtSwBitmap = _albumArtSwBitmap;
|
||||||
{
|
_albumArtSwBitmap = e.AlbumArtSwBitmap;
|
||||||
_cachedAlbumArtSwBitmaps.Append(_albumArtSwBitmap);
|
|
||||||
|
|
||||||
_lastAlbumArtSwBitmap = _albumArtSwBitmap;
|
_albumArtChanged = true;
|
||||||
|
|
||||||
if (_cachedAlbumArtSwBitmaps.Count > 2)
|
_albumArtLightAccentColor = e.AlbumArtLightAccentColor ?? Colors.Transparent;
|
||||||
{
|
_albumArtDarkAccentColor = e.AlbumArtDarkAccentColor ?? Colors.Transparent;
|
||||||
_cachedAlbumArtSwBitmaps.Dequeue()?.Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
_cachedAlbumArtSwBitmaps.Append(e.AlbumArtSwBitmap);
|
UpdateColorConfig();
|
||||||
|
|
||||||
_albumArtSwBitmap = e.AlbumArtSwBitmap;
|
|
||||||
|
|
||||||
if (_cachedAlbumArtSwBitmaps.Count > 2)
|
|
||||||
{
|
|
||||||
_cachedAlbumArtSwBitmaps.Dequeue()?.Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
_albumArtChanged = true;
|
|
||||||
|
|
||||||
_albumArtLightAccentColor = e.AlbumArtLightAccentColor ?? Colors.Transparent;
|
|
||||||
_albumArtDarkAccentColor = e.AlbumArtDarkAccentColor ?? Colors.Transparent;
|
|
||||||
|
|
||||||
UpdateColorConfig();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
e.AlbumArtSwBitmap?.Dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void UpdateTranslations()
|
|
||||||
{
|
|
||||||
TranslationSearchProvider = null;
|
|
||||||
_lyricsDataArr.ElementAtOrDefault(0)?.SetDisplayedTextInOriginalText();
|
|
||||||
_isLayoutChanged = true;
|
|
||||||
|
|
||||||
IsTranslating = true;
|
|
||||||
if (_settingsService.AppSettings.TranslationSettings.IsTranslationEnabled)
|
|
||||||
{
|
|
||||||
_ = _refreshLyricsRunner.RunAsync(async token =>
|
|
||||||
{
|
|
||||||
await SetDisplayedAlongWithTranslationsAsync(token);
|
|
||||||
IsTranslating = false;
|
|
||||||
_isLayoutChanged = true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_lyricsDataArr.ElementAtOrDefault(0)?.SetDisplayedTextInOriginalText();
|
|
||||||
_langIndex = 0;
|
|
||||||
IsTranslating = false;
|
|
||||||
_isLayoutChanged = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task SetDisplayedAlongWithTranslationsAsync(CancellationToken token)
|
|
||||||
{
|
|
||||||
_logger.LogInformation("Showing translation for lyrics...");
|
|
||||||
string targetLangCode = LanguageHelper.GetUserTargetLanguageCode();
|
|
||||||
string? originalText = _lyricsDataArr.FirstOrDefault()?.WrappedOriginalText;
|
|
||||||
if (originalText == null) return;
|
|
||||||
|
|
||||||
string? originalLangCode = LanguageHelper.DetectLanguageCode(originalText);
|
|
||||||
|
|
||||||
if (originalLangCode == targetLangCode)
|
|
||||||
{
|
|
||||||
_logger.LogInformation("Original lyrics already in target language: {TargetLangCode}", targetLangCode);
|
|
||||||
_lyricsDataArr[0].SetDisplayedTextInOriginalText();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Try get translation from itself first
|
|
||||||
int found = _translateService.SearchTranslatedLyricsItself(_lyricsDataArr);
|
|
||||||
if (found >= 0)
|
|
||||||
{
|
|
||||||
if (_settingsService.AppSettings.TranslationSettings.ShowTranslationOnly)
|
|
||||||
{
|
|
||||||
_lyricsDataArr[found].SetDisplayedTextInOriginalText();
|
|
||||||
_langIndex = found;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_lyricsDataArr[0].SetDisplayedTextAlongWith(_lyricsDataArr[found], _lyricsStyleSettings.LyricsTranslationSeparator, 50);
|
|
||||||
_langIndex = 0;
|
|
||||||
}
|
|
||||||
TranslationSearchProvider = LyricsSearchProvider.ToTranslationSearchProvider();
|
|
||||||
}
|
|
||||||
else if (_settingsService.AppSettings.TranslationSettings.IsLibreTranslateEnabled)
|
|
||||||
{
|
|
||||||
string translated = string.Empty;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
translated = await _translateService.TranslateTextAsync(originalText, targetLangCode, token);
|
|
||||||
if (translated == string.Empty) return;
|
|
||||||
|
|
||||||
if (_settingsService.AppSettings.TranslationSettings.ShowTranslationOnly)
|
|
||||||
{
|
|
||||||
_lyricsDataArr[^1] = _lyricsDataArr[0].CreateLyricsDataFrom(translated);
|
|
||||||
_lyricsDataArr[^1].SetDisplayedTextInOriginalText();
|
|
||||||
_langIndex = _lyricsDataArr.Count - 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_lyricsDataArr[0].SetDisplayedTextAlongWith(translated, _lyricsStyleSettings.LyricsTranslationSeparator);
|
|
||||||
_langIndex = 0;
|
|
||||||
}
|
|
||||||
TranslationSearchProvider = Enums.TranslationSearchProvider.LibreTranslate;
|
|
||||||
token.ThrowIfCancellationRequested();
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
App.Current.LyricsWindowNotificationPanel?.Notify(App.ResourceLoader?.GetString("LibreTranslateFailed")!, Microsoft.UI.Xaml.Controls.InfoBarSeverity.Error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task RefreshLyricsAsync(CancellationToken token)
|
|
||||||
{
|
|
||||||
LyricsSearchProvider = null;
|
|
||||||
_logger.LogInformation("Refreshing lyrics...");
|
|
||||||
|
|
||||||
_lyricsDataArr = [LyricsData.GetLoadingPlaceholder()];
|
|
||||||
_isLayoutChanged = true;
|
|
||||||
|
|
||||||
string? lyricsRaw = null;
|
|
||||||
LyricsSearchProvider? lyricsSearchProvider = null;
|
|
||||||
|
|
||||||
if (SongInfo != null)
|
|
||||||
{
|
|
||||||
(lyricsRaw, lyricsSearchProvider) = await _lyrcsSearchService.SearchAsync(
|
|
||||||
SongInfo.SourceAppUserModelId ?? "",
|
|
||||||
SongInfo.Title,
|
|
||||||
SongInfo.Artist,
|
|
||||||
SongInfo.Album ?? "",
|
|
||||||
SongInfo.DurationMs ?? 0,
|
|
||||||
token
|
|
||||||
);
|
|
||||||
LyricsSearchProvider = lyricsSearchProvider;
|
|
||||||
_logger.LogInformation("Lyrics search result: {LyricsRaw}", lyricsRaw ?? "null");
|
|
||||||
token.ThrowIfCancellationRequested();
|
|
||||||
_lyricsDataArr = new LyricsParser().Parse(lyricsRaw, (int?)SongInfo?.DurationMs);
|
|
||||||
FillTranslationFromCache(LyricsSearchProvider);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_logger.LogWarning("SongInfo is null, cannot search lyrics.");
|
|
||||||
}
|
|
||||||
|
|
||||||
_logger.LogInformation("Parsed lyrics: {MultiLangLyricsCount} languages", _lyricsDataArr.Count);
|
|
||||||
|
|
||||||
// This ensures that original lyrics are always shown while waiting for translations
|
|
||||||
_lyricsDataArr[0].SetDisplayedTextInOriginalText();
|
|
||||||
_isLayoutChanged = true;
|
|
||||||
|
|
||||||
UpdateTranslations();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void FillTranslationFromCache(LyricsSearchProvider? provider)
|
|
||||||
{
|
|
||||||
string? translationRaw = null;
|
|
||||||
switch (provider)
|
|
||||||
{
|
|
||||||
case Enums.LyricsSearchProvider.QQ:
|
|
||||||
translationRaw = Helper.FileHelper.ReadLyricsCache(SongInfo!.Title, SongInfo.Artist, LyricsFormat.Lrc, Helper.PathHelper.QQTranslationCacheDirectory);
|
|
||||||
break;
|
|
||||||
case Enums.LyricsSearchProvider.Kugou:
|
|
||||||
break;
|
|
||||||
case Enums.LyricsSearchProvider.Netease:
|
|
||||||
translationRaw = Helper.FileHelper.ReadLyricsCache(SongInfo!.Title, SongInfo.Artist, LyricsFormat.Lrc, Helper.PathHelper.NeteaseTranslationCacheDirectory);
|
|
||||||
break;
|
|
||||||
case Enums.LyricsSearchProvider.LrcLib:
|
|
||||||
break;
|
|
||||||
case Enums.LyricsSearchProvider.AmllTtmlDb:
|
|
||||||
break;
|
|
||||||
case Enums.LyricsSearchProvider.LocalMusicFile:
|
|
||||||
break;
|
|
||||||
case Enums.LyricsSearchProvider.LocalLrcFile:
|
|
||||||
break;
|
|
||||||
case Enums.LyricsSearchProvider.LocalEslrcFile:
|
|
||||||
break;
|
|
||||||
case Enums.LyricsSearchProvider.LocalTtmlFile:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (translationRaw != null)
|
|
||||||
{
|
|
||||||
var translationData = new LyricsParser().Parse(translationRaw, (int?)SongInfo?.DurationMs);
|
|
||||||
if (provider == Enums.LyricsSearchProvider.QQ)
|
|
||||||
{
|
|
||||||
foreach (var data in translationData)
|
|
||||||
{
|
|
||||||
foreach (var item in data.LyricsLines)
|
|
||||||
{
|
|
||||||
if (item.OriginalText == "//")
|
|
||||||
{
|
|
||||||
item.OriginalText = "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_lyricsDataArr = _lyricsDataArr.Concat(translationData).ToList();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ using BetterLyrics.WinUI3.Enums;
|
|||||||
using BetterLyrics.WinUI3.Helper;
|
using BetterLyrics.WinUI3.Helper;
|
||||||
using BetterLyrics.WinUI3.Models;
|
using BetterLyrics.WinUI3.Models;
|
||||||
using BetterLyrics.WinUI3.Models.Settings;
|
using BetterLyrics.WinUI3.Models.Settings;
|
||||||
|
using BetterLyrics.WinUI3.Services.LiveStatesService;
|
||||||
using BetterLyrics.WinUI3.Services.MediaSessionsService;
|
using BetterLyrics.WinUI3.Services.MediaSessionsService;
|
||||||
using BetterLyrics.WinUI3.Services.SettingsService;
|
using BetterLyrics.WinUI3.Services.SettingsService;
|
||||||
using BetterLyrics.WinUI3.ViewModels;
|
using BetterLyrics.WinUI3.ViewModels;
|
||||||
@@ -17,6 +18,8 @@ using CommunityToolkit.Mvvm.Messaging.Messages;
|
|||||||
using CommunityToolkit.WinUI;
|
using CommunityToolkit.WinUI;
|
||||||
using Microsoft.UI.Windowing;
|
using Microsoft.UI.Windowing;
|
||||||
using Microsoft.UI.Xaml;
|
using Microsoft.UI.Xaml;
|
||||||
|
using Microsoft.UI.Xaml.Controls;
|
||||||
|
using System.Collections.Generic;
|
||||||
using Vanara.PInvoke;
|
using Vanara.PInvoke;
|
||||||
using Windows.System;
|
using Windows.System;
|
||||||
using Windows.UI;
|
using Windows.UI;
|
||||||
@@ -28,6 +31,7 @@ namespace BetterLyrics.WinUI3
|
|||||||
public partial class LyricsWindowViewModel
|
public partial class LyricsWindowViewModel
|
||||||
: BaseWindowViewModel,
|
: BaseWindowViewModel,
|
||||||
IRecipient<PropertyChangedMessage<int>>,
|
IRecipient<PropertyChangedMessage<int>>,
|
||||||
|
IRecipient<PropertyChangedMessage<List<string>>>,
|
||||||
IRecipient<PropertyChangedMessage<bool>>,
|
IRecipient<PropertyChangedMessage<bool>>,
|
||||||
IRecipient<PropertyChangedMessage<string>>,
|
IRecipient<PropertyChangedMessage<string>>,
|
||||||
IRecipient<PropertyChangedMessage<ElementTheme>>,
|
IRecipient<PropertyChangedMessage<ElementTheme>>,
|
||||||
@@ -35,6 +39,7 @@ namespace BetterLyrics.WinUI3
|
|||||||
{
|
{
|
||||||
private readonly IMediaSessionsService _mediaSessionsService;
|
private readonly IMediaSessionsService _mediaSessionsService;
|
||||||
private readonly ISettingsService _settingsService;
|
private readonly ISettingsService _settingsService;
|
||||||
|
private readonly ILiveStatesService _liveStatesService;
|
||||||
|
|
||||||
private ForegroundWindowWatcher? _windowWatcher = null;
|
private ForegroundWindowWatcher? _windowWatcher = null;
|
||||||
private bool _ignoreFullscreenWindow;
|
private bool _ignoreFullscreenWindow;
|
||||||
@@ -44,10 +49,14 @@ namespace BetterLyrics.WinUI3
|
|||||||
private int _dockWindowHeight;
|
private int _dockWindowHeight;
|
||||||
private string _dockMonitorDeviceName;
|
private string _dockMonitorDeviceName;
|
||||||
|
|
||||||
public LyricsWindowViewModel(ISettingsService settingsService, IMediaSessionsService mediaSessionsService)
|
public LyricsWindowViewModel(ISettingsService settingsService, IMediaSessionsService mediaSessionsService, ILiveStatesService liveStatesService)
|
||||||
{
|
{
|
||||||
_settingsService = settingsService;
|
_settingsService = settingsService;
|
||||||
_mediaSessionsService = mediaSessionsService;
|
_mediaSessionsService = mediaSessionsService;
|
||||||
|
_liveStatesService = liveStatesService;
|
||||||
|
|
||||||
|
AppSettings = _settingsService.AppSettings;
|
||||||
|
LiveStates = _liveStatesService.LiveStates;
|
||||||
|
|
||||||
_dockMonitorDeviceName = _settingsService.AppSettings.DockModeSettings.DockMonitorDeviceName;
|
_dockMonitorDeviceName = _settingsService.AppSettings.DockModeSettings.DockMonitorDeviceName;
|
||||||
_ignoreFullscreenWindow = _settingsService.AppSettings.GeneralSettings.IgnoreFullscreenWindow;
|
_ignoreFullscreenWindow = _settingsService.AppSettings.GeneralSettings.IgnoreFullscreenWindow;
|
||||||
@@ -62,21 +71,19 @@ namespace BetterLyrics.WinUI3
|
|||||||
|
|
||||||
private void PlaybackService_IsPlayingChanged(object? sender, Events.IsPlayingChangedEventArgs e)
|
private void PlaybackService_IsPlayingChanged(object? sender, Events.IsPlayingChangedEventArgs e)
|
||||||
{
|
{
|
||||||
UpdateDockWindow();
|
UpdateDockOrDesktopWindow();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
public partial AppSettings AppSettings { get; set; }
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
public partial LiveStates LiveStates { get; set; }
|
||||||
|
|
||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
[NotifyPropertyChangedRecipients]
|
[NotifyPropertyChangedRecipients]
|
||||||
public partial Color ActivatedWindowAccentColor { get; set; }
|
public partial Color ActivatedWindowAccentColor { get; set; }
|
||||||
|
|
||||||
[ObservableProperty]
|
|
||||||
[NotifyPropertyChangedRecipients]
|
|
||||||
public partial bool IsDesktopMode { get; set; } = false;
|
|
||||||
|
|
||||||
[ObservableProperty]
|
|
||||||
[NotifyPropertyChangedRecipients]
|
|
||||||
public partial bool IsDockMode { get; set; } = false;
|
|
||||||
|
|
||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
[NotifyPropertyChangedRecipients]
|
[NotifyPropertyChangedRecipients]
|
||||||
public partial bool IsLyricsWindowLocked { get; set; } = false;
|
public partial bool IsLyricsWindowLocked { get; set; } = false;
|
||||||
@@ -98,21 +105,32 @@ namespace BetterLyrics.WinUI3
|
|||||||
[NotifyPropertyChangedRecipients]
|
[NotifyPropertyChangedRecipients]
|
||||||
public partial bool IsMouseWithinWindow { get; set; } = false;
|
public partial bool IsMouseWithinWindow { get; set; } = false;
|
||||||
|
|
||||||
[ObservableProperty]
|
[ObservableProperty] public partial Visibility AOTFlyoutItemVisibility { get; set; } = Visibility.Visible;
|
||||||
public partial string LockHotKey { get; set; } = "";
|
[ObservableProperty] public partial Visibility FullScreenFlyoutItemVisibility { get; set; } = Visibility.Visible;
|
||||||
|
[ObservableProperty] public partial Visibility LockButtonVisibility { get; set; } = Visibility.Visible;
|
||||||
|
[ObservableProperty] public partial Visibility DesktopFlyoutItemVisibility { get; set; } = Visibility.Visible;
|
||||||
|
[ObservableProperty] public partial Visibility PIPFlyoutItemVisibility { get; set; } = Visibility.Visible;
|
||||||
|
[ObservableProperty] public partial Visibility DockFlyoutItemVisibility { get; set; } = Visibility.Visible;
|
||||||
|
|
||||||
private void UpdateDockWindow()
|
[ObservableProperty] public partial bool IsAOTFlyoutItemChecked { get; set; } = false;
|
||||||
|
[ObservableProperty] public partial bool IsFullScreenFlyoutItemChecked { get; set; } = false;
|
||||||
|
[ObservableProperty] public partial bool IsDesktopFlyoutItemChecked { get; set; } = false;
|
||||||
|
[ObservableProperty] public partial bool IsPIPFlyoutItemChecked { get; set; } = false;
|
||||||
|
[ObservableProperty] public partial bool IsDockFlyoutItemChecked { get; set; } = false;
|
||||||
|
|
||||||
|
private void UpdateDockOrDesktopWindow()
|
||||||
{
|
{
|
||||||
|
|
||||||
var window = WindowHelper.GetWindowByWindowType<LyricsWindow>();
|
var window = WindowHelper.GetWindowByWindowType<LyricsWindow>();
|
||||||
if (window == null) return;
|
if (window == null) return;
|
||||||
|
|
||||||
var hwnd = WindowNative.GetWindowHandle(window);
|
var hwnd = WindowNative.GetWindowHandle(window);
|
||||||
|
|
||||||
if (IsDockMode || IsDesktopMode)
|
if (LiveStates.CurrentLyricsWindowMode == LyricsWindowMode.DockMode || LiveStates.CurrentLyricsWindowMode == LyricsWindowMode.DesktopMode)
|
||||||
{
|
{
|
||||||
if (_hideWindowWhenNotPlaying && !_mediaSessionsService.IsPlaying)
|
if (_hideWindowWhenNotPlaying && !_mediaSessionsService.IsPlaying)
|
||||||
{
|
{
|
||||||
if (IsDockMode)
|
if (LiveStates.CurrentLyricsWindowMode == LyricsWindowMode.DockMode)
|
||||||
{
|
{
|
||||||
DockModeHelper.UpdateAppBarHeight(hwnd, _dockMonitorDeviceName, 0, _dockPlacement);
|
DockModeHelper.UpdateAppBarHeight(hwnd, _dockMonitorDeviceName, 0, _dockPlacement);
|
||||||
}
|
}
|
||||||
@@ -120,7 +138,7 @@ namespace BetterLyrics.WinUI3
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (IsDockMode)
|
if (LiveStates.CurrentLyricsWindowMode == LyricsWindowMode.DockMode)
|
||||||
{
|
{
|
||||||
DockModeHelper.UpdateAppBarHeight(hwnd, _dockMonitorDeviceName, _dockWindowHeight, _dockPlacement);
|
DockModeHelper.UpdateAppBarHeight(hwnd, _dockMonitorDeviceName, _dockWindowHeight, _dockPlacement);
|
||||||
}
|
}
|
||||||
@@ -162,7 +180,7 @@ namespace BetterLyrics.WinUI3
|
|||||||
else if (message.PropertyName == nameof(GeneralSettings.HideWindowWhenNotPlaying))
|
else if (message.PropertyName == nameof(GeneralSettings.HideWindowWhenNotPlaying))
|
||||||
{
|
{
|
||||||
_hideWindowWhenNotPlaying = message.NewValue;
|
_hideWindowWhenNotPlaying = message.NewValue;
|
||||||
UpdateDockWindow();
|
UpdateDockOrDesktopWindow();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -185,37 +203,128 @@ namespace BetterLyrics.WinUI3
|
|||||||
if (message.PropertyName == nameof(DockModeSettings.DockWindowHeight))
|
if (message.PropertyName == nameof(DockModeSettings.DockWindowHeight))
|
||||||
{
|
{
|
||||||
_dockWindowHeight = message.NewValue;
|
_dockWindowHeight = message.NewValue;
|
||||||
UpdateDockWindow();
|
UpdateDockOrDesktopWindow();
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (message.Sender is DesktopModeSettings)
|
|
||||||
{
|
|
||||||
if (message.PropertyName == nameof(DesktopModeSettings.LockHotKeyIndex))
|
|
||||||
{
|
|
||||||
UpdateLockHotKey(message.NewValue);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateLockHotKey(int hotKeyIndex)
|
public void InitShortcuts()
|
||||||
{
|
{
|
||||||
var window = WindowHelper.GetWindowByWindowType<LyricsWindow>();
|
UpdateDesktopLockShortcut();
|
||||||
if (window == null) return;
|
UpdateDesktopToggleShortcut();
|
||||||
|
UpdateDockToggleShortcut();
|
||||||
|
UpdatePictureInPictureToggleShortcut();
|
||||||
|
}
|
||||||
|
|
||||||
GlobalHotKeyHelper.UnregisterAllHotKeys(window);
|
private void UpdateDesktopLockShortcut()
|
||||||
GlobalHotKeyHelper.RegisterHotKey(
|
{
|
||||||
window,
|
GlobalHotKeyHelper.UpdateHotKey<LyricsWindow>(ShortcutID.DesktopLock,
|
||||||
User32.HotKeyModifiers.MOD_CONTROL | User32.HotKeyModifiers.MOD_ALT,
|
_settingsService.AppSettings.DesktopModeSettings.LockShortcut,
|
||||||
(uint)(hotKeyIndex + (int)VirtualKey.A),
|
|
||||||
() =>
|
() =>
|
||||||
{
|
{
|
||||||
if (IsDesktopMode)
|
if (LiveStates.CurrentLyricsWindowMode == LyricsWindowMode.DesktopMode)
|
||||||
{
|
{
|
||||||
ToggleLockWindowCommand.Execute(null);
|
ToggleLockWindow();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
LockHotKey = ((VirtualKey)(hotKeyIndex + (int)VirtualKey.A)).ToString();
|
}
|
||||||
|
|
||||||
|
private void UpdateDesktopToggleShortcut()
|
||||||
|
{
|
||||||
|
GlobalHotKeyHelper.UpdateHotKey<LyricsWindow>(ShortcutID.DesktopToggle,
|
||||||
|
_settingsService.AppSettings.DesktopModeSettings.ToggleShortcut,
|
||||||
|
() =>
|
||||||
|
{
|
||||||
|
if (LiveStates.CurrentLyricsWindowMode == LyricsWindowMode.DesktopMode ||
|
||||||
|
LiveStates.CurrentLyricsWindowMode == LyricsWindowMode.StandardMode)
|
||||||
|
{
|
||||||
|
ToggleDesktopMode();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateDockToggleShortcut()
|
||||||
|
{
|
||||||
|
GlobalHotKeyHelper.UpdateHotKey<LyricsWindow>(ShortcutID.DockToggle,
|
||||||
|
_settingsService.AppSettings.DockModeSettings.ToggleShortcut,
|
||||||
|
() =>
|
||||||
|
{
|
||||||
|
if (LiveStates.CurrentLyricsWindowMode == LyricsWindowMode.DockMode ||
|
||||||
|
LiveStates.CurrentLyricsWindowMode == LyricsWindowMode.StandardMode)
|
||||||
|
{
|
||||||
|
ToggleDockMode();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdatePictureInPictureToggleShortcut()
|
||||||
|
{
|
||||||
|
GlobalHotKeyHelper.UpdateHotKey<LyricsWindow>(ShortcutID.PictureInPictureToggle,
|
||||||
|
_settingsService.AppSettings.PictureInPictureModeSettings.ToggleShortcut,
|
||||||
|
() =>
|
||||||
|
{
|
||||||
|
if (LiveStates.CurrentLyricsWindowMode == LyricsWindowMode.PictureInPictureMode ||
|
||||||
|
LiveStates.CurrentLyricsWindowMode == LyricsWindowMode.StandardMode)
|
||||||
|
{
|
||||||
|
TogglePictureInPictureMode();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetFullscreenTitleBarControlsStatus()
|
||||||
|
{
|
||||||
|
AOTFlyoutItemVisibility = LockButtonVisibility = DesktopFlyoutItemVisibility = PIPFlyoutItemVisibility = DockFlyoutItemVisibility = Visibility.Collapsed;
|
||||||
|
IsFullScreenFlyoutItemChecked = true;
|
||||||
|
IsImmersiveMode = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetPIPModeTitleBarControlsStatus()
|
||||||
|
{
|
||||||
|
AOTFlyoutItemVisibility = DesktopFlyoutItemVisibility = FullScreenFlyoutItemVisibility = DockFlyoutItemVisibility = LockButtonVisibility = Visibility.Collapsed;
|
||||||
|
IsImmersiveMode = true;
|
||||||
|
IsPIPFlyoutItemChecked = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetDockModeTitleBarControlsStatus()
|
||||||
|
{
|
||||||
|
var window = WindowHelper.GetWindowByWindowType<LyricsWindow>();
|
||||||
|
if (window == null) return;
|
||||||
|
var overlappedPresenter = (OverlappedPresenter)window.AppWindow.Presenter;
|
||||||
|
|
||||||
|
overlappedPresenter.IsMinimizable = overlappedPresenter.IsMaximizable = false;
|
||||||
|
AOTFlyoutItemVisibility = DesktopFlyoutItemVisibility = LockButtonVisibility = FullScreenFlyoutItemVisibility = PIPFlyoutItemVisibility = Visibility.Collapsed;
|
||||||
|
IsImmersiveMode = true;
|
||||||
|
IsDockFlyoutItemChecked = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetDesktopModeTitleBarControlsStatus()
|
||||||
|
{
|
||||||
|
var window = WindowHelper.GetWindowByWindowType<LyricsWindow>();
|
||||||
|
if (window == null) return;
|
||||||
|
var overlappedPresenter = (OverlappedPresenter)window.AppWindow.Presenter;
|
||||||
|
|
||||||
|
overlappedPresenter.IsMinimizable = overlappedPresenter.IsMaximizable = false;
|
||||||
|
DockFlyoutItemVisibility = AOTFlyoutItemVisibility = FullScreenFlyoutItemVisibility = PIPFlyoutItemVisibility = Visibility.Collapsed;
|
||||||
|
LockButtonVisibility = Visibility.Visible;
|
||||||
|
IsDesktopFlyoutItemChecked = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetStandardModeTitleBarControlsStatus()
|
||||||
|
{
|
||||||
|
var window = WindowHelper.GetWindowByWindowType<LyricsWindow>();
|
||||||
|
if (window == null) return;
|
||||||
|
var overlappedPresenter = (OverlappedPresenter)window.AppWindow.Presenter;
|
||||||
|
|
||||||
|
overlappedPresenter.IsMinimizable = overlappedPresenter.IsMaximizable = true;
|
||||||
|
AOTFlyoutItemVisibility = DesktopFlyoutItemVisibility = DockFlyoutItemVisibility = PIPFlyoutItemVisibility = FullScreenFlyoutItemVisibility = Visibility.Visible;
|
||||||
|
LockButtonVisibility = Visibility.Collapsed;
|
||||||
|
IsFullScreenFlyoutItemChecked = IsDesktopFlyoutItemChecked = IsDockFlyoutItemChecked = IsPIPFlyoutItemChecked = false;
|
||||||
|
IsAOTFlyoutItemChecked = overlappedPresenter.IsAlwaysOnTop;
|
||||||
|
IsImmersiveMode = _settingsService.AppSettings.GeneralSettings.IsImmersiveMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void StartWatchWindowColorChange()
|
public void StartWatchWindowColorChange()
|
||||||
@@ -230,7 +339,7 @@ namespace BetterLyrics.WinUI3
|
|||||||
{
|
{
|
||||||
_dispatcherQueueTimer.Debounce(() =>
|
_dispatcherQueueTimer.Debounce(() =>
|
||||||
{
|
{
|
||||||
if ((IsDockMode || IsDesktopMode) && _ignoreFullscreenWindow && window.AppWindow.Presenter is OverlappedPresenter presenter)
|
if ((LiveStates.CurrentLyricsWindowMode == LyricsWindowMode.DockMode || LiveStates.CurrentLyricsWindowMode == LyricsWindowMode.DesktopMode) && _ignoreFullscreenWindow && window.AppWindow.Presenter is OverlappedPresenter presenter)
|
||||||
{
|
{
|
||||||
presenter.IsAlwaysOnTop = true;
|
presenter.IsAlwaysOnTop = true;
|
||||||
}
|
}
|
||||||
@@ -250,17 +359,24 @@ namespace BetterLyrics.WinUI3
|
|||||||
|
|
||||||
public void UpdateAccentColor(nint hwnd)
|
public void UpdateAccentColor(nint hwnd)
|
||||||
{
|
{
|
||||||
WindowPixelSampleMode mode = IsDesktopMode ? WindowPixelSampleMode.WindowEdge : _dockPlacement.ToWindowPixelSampleMode();
|
WindowPixelSampleMode mode = LiveStates.CurrentLyricsWindowMode == LyricsWindowMode.DesktopMode ? WindowPixelSampleMode.WindowEdge : _dockPlacement.ToWindowPixelSampleMode();
|
||||||
ActivatedWindowAccentColor = ColorHelper.GetAccentColor(hwnd, _settingsService.AppSettings.DockModeSettings.DockMonitorDeviceName, mode).ToColor();
|
ActivatedWindowAccentColor = ColorHelper.GetAccentColor(hwnd, _settingsService.AppSettings.DockModeSettings.DockMonitorDeviceName, mode).ToColor();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void InitLockHotKey()
|
public void ExitOrClose()
|
||||||
{
|
{
|
||||||
UpdateLockHotKey(_settingsService.AppSettings.DesktopModeSettings.LockHotKeyIndex);
|
if (_settingsService.AppSettings.GeneralSettings.ExitOnLyricsWindowClosed)
|
||||||
|
{
|
||||||
|
WindowHelper.ExitApp();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var window = WindowHelper.GetWindowByWindowType<LyricsWindow>();
|
||||||
|
window?.Hide();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[RelayCommand]
|
public void ToggleLockWindow()
|
||||||
private void ToggleLockWindow()
|
|
||||||
{
|
{
|
||||||
var window = WindowHelper.GetWindowByWindowType<LyricsWindow>();
|
var window = WindowHelper.GetWindowByWindowType<LyricsWindow>();
|
||||||
if (window == null) return;
|
if (window == null) return;
|
||||||
@@ -278,50 +394,111 @@ namespace BetterLyrics.WinUI3
|
|||||||
IsImmersiveMode = true;
|
IsImmersiveMode = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateDockWindow();
|
UpdateDockOrDesktopWindow();
|
||||||
}
|
}
|
||||||
|
|
||||||
[RelayCommand]
|
public void ToggleDesktopMode()
|
||||||
private void ToggleDesktopMode()
|
|
||||||
{
|
{
|
||||||
var window = WindowHelper.GetWindowByWindowType<LyricsWindow>();
|
var window = WindowHelper.GetWindowByWindowType<LyricsWindow>();
|
||||||
if (window == null) return;
|
if (window == null) return;
|
||||||
|
|
||||||
StopWatchWindowColorChange();
|
StopWatchWindowColorChange();
|
||||||
|
|
||||||
IsDesktopMode = !IsDesktopMode;
|
LiveStates.ToggleLyricsWindowMode(LyricsWindowMode.DesktopMode);
|
||||||
if (IsDesktopMode)
|
if (LiveStates.CurrentLyricsWindowMode == LyricsWindowMode.DesktopMode)
|
||||||
{
|
{
|
||||||
DesktopModeHelper.Enable(window);
|
DesktopModeHelper.Enable(window);
|
||||||
StartWatchWindowColorChange();
|
StartWatchWindowColorChange();
|
||||||
|
if (_settingsService.AppSettings.DesktopModeSettings.AutoLockOnDesktopMode)
|
||||||
|
{
|
||||||
|
ToggleLockWindow();
|
||||||
|
}
|
||||||
|
SetDesktopModeTitleBarControlsStatus();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if (IsLyricsWindowLocked)
|
||||||
|
{
|
||||||
|
ToggleLockWindow();
|
||||||
|
}
|
||||||
DesktopModeHelper.Disable(window);
|
DesktopModeHelper.Disable(window);
|
||||||
|
SetStandardModeTitleBarControlsStatus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[RelayCommand]
|
public void ToggleDockMode()
|
||||||
private void ToggleDockMode()
|
|
||||||
{
|
{
|
||||||
var window = WindowHelper.GetWindowByWindowType<LyricsWindow>();
|
var window = WindowHelper.GetWindowByWindowType<LyricsWindow>();
|
||||||
if (window == null) return;
|
if (window == null) return;
|
||||||
|
|
||||||
StopWatchWindowColorChange();
|
StopWatchWindowColorChange();
|
||||||
|
|
||||||
IsDockMode = !IsDockMode;
|
LiveStates.ToggleLyricsWindowMode(LyricsWindowMode.DockMode);
|
||||||
if (IsDockMode)
|
if (LiveStates.CurrentLyricsWindowMode == LyricsWindowMode.DockMode)
|
||||||
{
|
{
|
||||||
window.Restore();
|
window.Restore();
|
||||||
DockModeHelper.Enable(window, _dockMonitorDeviceName, _dockWindowHeight, _dockPlacement);
|
DockModeHelper.Enable(window, _dockMonitorDeviceName, _dockWindowHeight, _dockPlacement);
|
||||||
StartWatchWindowColorChange();
|
StartWatchWindowColorChange();
|
||||||
|
SetDockModeTitleBarControlsStatus();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DockModeHelper.Disable(window);
|
DockModeHelper.Disable(window);
|
||||||
|
SetStandardModeTitleBarControlsStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateDockWindow();
|
UpdateDockOrDesktopWindow();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void TogglePictureInPictureMode()
|
||||||
|
{
|
||||||
|
var window = WindowHelper.GetWindowByWindowType<LyricsWindow>();
|
||||||
|
if (window == null) return;
|
||||||
|
|
||||||
|
LiveStates.ToggleLyricsWindowMode(LyricsWindowMode.PictureInPictureMode);
|
||||||
|
if (LiveStates.CurrentLyricsWindowMode == LyricsWindowMode.PictureInPictureMode)
|
||||||
|
{
|
||||||
|
window.AppWindow.SetPresenter(AppWindowPresenterKind.CompactOverlay);
|
||||||
|
window.AppWindow.Move(AppSettings.PictureInPictureModeSettings.WindowPosition.ToPointInt32());
|
||||||
|
SetPIPModeTitleBarControlsStatus();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
window.AppWindow.SetPresenter(AppWindowPresenterKind.Overlapped);
|
||||||
|
SetStandardModeTitleBarControlsStatus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ToggleAlwaysOnTop()
|
||||||
|
{
|
||||||
|
var window = WindowHelper.GetWindowByWindowType<LyricsWindow>();
|
||||||
|
if (window == null) return;
|
||||||
|
|
||||||
|
if (window.AppWindow.Presenter is OverlappedPresenter presenter)
|
||||||
|
{
|
||||||
|
presenter.IsAlwaysOnTop = !presenter.IsAlwaysOnTop;
|
||||||
|
IsAOTFlyoutItemChecked = presenter.IsAlwaysOnTop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ToggleFullscreen()
|
||||||
|
{
|
||||||
|
var window = WindowHelper.GetWindowByWindowType<LyricsWindow>();
|
||||||
|
if (window == null) return;
|
||||||
|
|
||||||
|
switch (window.AppWindow.Presenter.Kind)
|
||||||
|
{
|
||||||
|
case AppWindowPresenterKind.FullScreen:
|
||||||
|
window.AppWindow.SetPresenter(AppWindowPresenterKind.Overlapped);
|
||||||
|
SetStandardModeTitleBarControlsStatus();
|
||||||
|
break;
|
||||||
|
case AppWindowPresenterKind.Overlapped:
|
||||||
|
window.AppWindow.SetPresenter(AppWindowPresenterKind.FullScreen);
|
||||||
|
SetFullscreenTitleBarControlsStatus();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[RelayCommand]
|
[RelayCommand]
|
||||||
@@ -337,7 +514,7 @@ namespace BetterLyrics.WinUI3
|
|||||||
if (message.PropertyName == nameof(DockModeSettings.DockPlacement))
|
if (message.PropertyName == nameof(DockModeSettings.DockPlacement))
|
||||||
{
|
{
|
||||||
_dockPlacement = message.NewValue;
|
_dockPlacement = message.NewValue;
|
||||||
UpdateDockWindow();
|
UpdateDockOrDesktopWindow();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -349,7 +526,39 @@ namespace BetterLyrics.WinUI3
|
|||||||
if (message.PropertyName == nameof(DockModeSettings.DockMonitorDeviceName))
|
if (message.PropertyName == nameof(DockModeSettings.DockMonitorDeviceName))
|
||||||
{
|
{
|
||||||
_dockMonitorDeviceName = message.NewValue;
|
_dockMonitorDeviceName = message.NewValue;
|
||||||
UpdateDockWindow();
|
UpdateDockOrDesktopWindow();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Receive(PropertyChangedMessage<List<string>> message)
|
||||||
|
{
|
||||||
|
if (message.Sender is DesktopModeSettings)
|
||||||
|
{
|
||||||
|
if (message.PropertyName == nameof(DesktopModeSettings.LockShortcut))
|
||||||
|
{
|
||||||
|
UpdateDesktopLockShortcut();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (message.Sender is DockModeSettings)
|
||||||
|
{
|
||||||
|
if (message.PropertyName == nameof(DockModeSettings.ToggleShortcut))
|
||||||
|
{
|
||||||
|
UpdateDockToggleShortcut();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (message.Sender is PictureInPictureModeSettings)
|
||||||
|
{
|
||||||
|
if (message.PropertyName == nameof(PictureInPictureModeSettings.ToggleShortcut))
|
||||||
|
{
|
||||||
|
UpdatePictureInPictureToggleShortcut();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (message.Sender is DesktopModeSettings)
|
||||||
|
{
|
||||||
|
if (message.PropertyName == nameof(DesktopModeSettings.ToggleShortcut))
|
||||||
|
{
|
||||||
|
UpdateDesktopToggleShortcut();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ namespace BetterLyrics.WinUI3.ViewModels
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
AppSettings.LocalMediaFolders.Add(new LocalMediaFolder(path, true));
|
AppSettings.LocalMediaFolders.Add(new LocalMediaFolder(path));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
using BetterLyrics.WinUI3.Enums;
|
using BetterLyrics.WinUI3.Enums;
|
||||||
using BetterLyrics.WinUI3.Extensions;
|
using BetterLyrics.WinUI3.Extensions;
|
||||||
using BetterLyrics.WinUI3.Helper;
|
using BetterLyrics.WinUI3.Helper;
|
||||||
|
using BetterLyrics.WinUI3.Helper.BetterLyrics.WinUI3.Helper;
|
||||||
using BetterLyrics.WinUI3.Models;
|
using BetterLyrics.WinUI3.Models;
|
||||||
using BetterLyrics.WinUI3.Models.Settings;
|
using BetterLyrics.WinUI3.Models.Settings;
|
||||||
using BetterLyrics.WinUI3.Services;
|
using BetterLyrics.WinUI3.Services;
|
||||||
@@ -35,6 +36,7 @@ namespace BetterLyrics.WinUI3.ViewModels
|
|||||||
private readonly MediaPlayer _mediaPlayer = new();
|
private readonly MediaPlayer _mediaPlayer = new();
|
||||||
private readonly MediaTimelineController _timelineController = new();
|
private readonly MediaTimelineController _timelineController = new();
|
||||||
private readonly SystemMediaTransportControls _smtc;
|
private readonly SystemMediaTransportControls _smtc;
|
||||||
|
|
||||||
// All songs
|
// All songs
|
||||||
private List<Track> _tracks = [];
|
private List<Track> _tracks = [];
|
||||||
// Songs in current playlist
|
// Songs in current playlist
|
||||||
@@ -251,6 +253,10 @@ namespace BetterLyrics.WinUI3.ViewModels
|
|||||||
RefreshSongs();
|
RefreshSongs();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void CancelRefreshSongs()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
public void RefreshSongs()
|
public void RefreshSongs()
|
||||||
{
|
{
|
||||||
_dispatcherQueueTimer.Debounce(() =>
|
_dispatcherQueueTimer.Debounce(() =>
|
||||||
@@ -260,18 +266,27 @@ namespace BetterLyrics.WinUI3.ViewModels
|
|||||||
|
|
||||||
Task.Run(() =>
|
Task.Run(() =>
|
||||||
{
|
{
|
||||||
foreach (var folder in _settingsService.AppSettings.LocalMediaFolders)
|
try
|
||||||
{
|
{
|
||||||
if (Directory.Exists(folder.Path) && folder.IsEnabled)
|
foreach (var folder in _settingsService.AppSettings.LocalMediaFolders)
|
||||||
{
|
{
|
||||||
foreach (var file in Directory.GetFiles(folder.Path, $"*.*", SearchOption.AllDirectories))
|
if (Directory.Exists(folder.Path) && folder.IsEnabled)
|
||||||
{
|
{
|
||||||
Track track = new(file);
|
foreach (var file in DirectoryHelper.GetAllFiles(folder.Path))
|
||||||
if (track.Duration <= 0) continue;
|
{
|
||||||
_tracks.Add(track);
|
if (FileHelper.MusicExtensions.Contains(Path.GetExtension(file)))
|
||||||
|
{
|
||||||
|
Track track = new(file);
|
||||||
|
if (track.Duration <= 0) continue;
|
||||||
|
_tracks.Add(track);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
_dispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, () =>
|
_dispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, () =>
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -80,6 +80,9 @@ namespace BetterLyrics.WinUI3.ViewModels
|
|||||||
IsLastFMAuthenticated = _lastFMService.IsAuthenticated;
|
IsLastFMAuthenticated = _lastFMService.IsAuthenticated;
|
||||||
LastFMUser = _lastFMService.User;
|
LastFMUser = _lastFMService.User;
|
||||||
|
|
||||||
|
LyricsSearchProvider = _mediaSessionsService.LyricsSearchProvider;
|
||||||
|
TranslationSearchProvider = _mediaSessionsService.TranslationSearchProvider;
|
||||||
|
|
||||||
SelectedMediaSourceProvider = AppSettings.MediaSourceProvidersInfo.FirstOrDefault();
|
SelectedMediaSourceProvider = AppSettings.MediaSourceProvidersInfo.FirstOrDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,7 +124,7 @@ namespace BetterLyrics.WinUI3.ViewModels
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
string targetLangCode = LanguageHelper.SupportedTargetLanguages[AppSettings.TranslationSettings.SelectedTargetLanguageIndex].Code;
|
string targetLangCode = LanguageHelper.SupportedTargetLanguages[AppSettings.TranslationSettings.SelectedTargetLanguageIndex].Code;
|
||||||
string result = await _libreTranslateService.TranslateTextAsync("Hello, world!", targetLangCode, null);
|
string result = await _libreTranslateService.TranslateTextAsync("Hello, world!", targetLangCode, new System.Threading.CancellationToken());
|
||||||
_dispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, () =>
|
_dispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, () =>
|
||||||
{
|
{
|
||||||
App.Current.SettingsWindowNotificationPanel?.Notify(App.ResourceLoader!.GetString("SettingsPageServerTestSuccessInfo"), InfoBarSeverity.Success);
|
App.Current.SettingsWindowNotificationPanel?.Notify(App.ResourceLoader!.GetString("SettingsPageServerTestSuccessInfo"), InfoBarSeverity.Success);
|
||||||
@@ -183,9 +186,9 @@ namespace BetterLyrics.WinUI3.ViewModels
|
|||||||
|
|
||||||
public void Receive(PropertyChangedMessage<LyricsSearchProvider?> message)
|
public void Receive(PropertyChangedMessage<LyricsSearchProvider?> message)
|
||||||
{
|
{
|
||||||
if (message.Sender is LyricsRendererViewModel.LyricsRendererViewModel)
|
if (message.Sender is MediaSessionsService)
|
||||||
{
|
{
|
||||||
if (message.PropertyName == nameof(LyricsRendererViewModel.LyricsRendererViewModel.LyricsSearchProvider))
|
if (message.PropertyName == nameof(MediaSessionsService.LyricsSearchProvider))
|
||||||
{
|
{
|
||||||
LyricsSearchProvider = message.NewValue;
|
LyricsSearchProvider = message.NewValue;
|
||||||
}
|
}
|
||||||
@@ -194,9 +197,9 @@ namespace BetterLyrics.WinUI3.ViewModels
|
|||||||
|
|
||||||
public void Receive(PropertyChangedMessage<TranslationSearchProvider?> message)
|
public void Receive(PropertyChangedMessage<TranslationSearchProvider?> message)
|
||||||
{
|
{
|
||||||
if (message.Sender is LyricsRendererViewModel.LyricsRendererViewModel)
|
if (message.Sender is MediaSessionsService)
|
||||||
{
|
{
|
||||||
if (message.PropertyName == nameof(LyricsRendererViewModel.LyricsRendererViewModel.TranslationSearchProvider))
|
if (message.PropertyName == nameof(MediaSessionsService.TranslationSearchProvider))
|
||||||
{
|
{
|
||||||
TranslationSearchProvider = message.NewValue;
|
TranslationSearchProvider = message.NewValue;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ namespace BetterLyrics.WinUI3.ViewModels
|
|||||||
}
|
}
|
||||||
|
|
||||||
[RelayCommand]
|
[RelayCommand]
|
||||||
private static void OpenLyricsWindow()
|
private static void OpenLyrics()
|
||||||
{
|
{
|
||||||
WindowHelper.OpenWindow<LyricsWindow>();
|
WindowHelper.OpenWindow<LyricsWindow>();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
<Grid x:Name="RootGrid" SizeChanged="RootGrid_SizeChanged">
|
<Grid x:Name="RootGrid" SizeChanged="RootGrid_SizeChanged">
|
||||||
<!-- Lyrics area -->
|
<!-- Lyrics area -->
|
||||||
<renderer:LyricsRenderer />
|
<renderer:LyricsRenderer />
|
||||||
|
<!--<Image Source="/Assets/Cover.jpg" />-->
|
||||||
|
|
||||||
<!-- No music playing placeholder -->
|
<!-- No music playing placeholder -->
|
||||||
<Grid x:Name="NoMusicPlayingGrid" Background="{ThemeResource AcrylicBackgroundFillColorBaseBrush}">
|
<Grid x:Name="NoMusicPlayingGrid" Background="{ThemeResource AcrylicBackgroundFillColorBaseBrush}">
|
||||||
@@ -28,8 +29,8 @@
|
|||||||
x:Uid="MainPageNoMusicPlaying"
|
x:Uid="MainPageNoMusicPlaying"
|
||||||
HorizontalAlignment="Center"
|
HorizontalAlignment="Center"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
FontFamily="{x:Bind ViewModel.LyricsFontFamily, Mode=OneWay}"
|
FontFamily="{x:Bind ViewModel.LiveStates.CurrentLyricsStyleSettings.LyricsFontFamily, Mode=OneWay}"
|
||||||
FontSize="{x:Bind ViewModel.HintMessageFontSize, Mode=OneWay}" />
|
FontSize="{x:Bind ViewModel.LiveStates.CurrentLyricsStyleSettings.LyricsFontSize, Mode=OneWay}" />
|
||||||
<Grid.OpacityTransition>
|
<Grid.OpacityTransition>
|
||||||
<ScalarTransition />
|
<ScalarTransition />
|
||||||
</Grid.OpacityTransition>
|
</Grid.OpacityTransition>
|
||||||
@@ -218,6 +219,24 @@
|
|||||||
</Button.DataContext>
|
</Button.DataContext>
|
||||||
</Button>-->
|
</Button>-->
|
||||||
|
|
||||||
|
<Button
|
||||||
|
Click="LyricsSettingsShortcutButton_Click"
|
||||||
|
Content="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
|
||||||
|
Glyph=}"
|
||||||
|
Style="{StaticResource GhostButtonStyle}">
|
||||||
|
<ToolTipService.ToolTip>
|
||||||
|
<ToolTip x:Uid="LyricsPageLyricsSettingsButtonToolTip" />
|
||||||
|
</ToolTipService.ToolTip>
|
||||||
|
<Button.ContextFlyout>
|
||||||
|
<Flyout
|
||||||
|
x:Name="LyricsSettingsFlyout"
|
||||||
|
Closed="LyricsSettingsFlyout_Closed"
|
||||||
|
FlyoutPresenterStyle="{StaticResource FlyoutPageStyle}"
|
||||||
|
Placement="Right"
|
||||||
|
ShouldConstrainToRootBounds="False" />
|
||||||
|
</Button.ContextFlyout>
|
||||||
|
</Button>
|
||||||
|
|
||||||
<!-- Lyrics & Translation -->
|
<!-- Lyrics & Translation -->
|
||||||
<Button
|
<Button
|
||||||
Click="PlaybackSettingsShortcutButton_Click"
|
Click="PlaybackSettingsShortcutButton_Click"
|
||||||
@@ -230,48 +249,10 @@
|
|||||||
<Button.ContextFlyout>
|
<Button.ContextFlyout>
|
||||||
<Flyout
|
<Flyout
|
||||||
x:Name="PlaybackSettingsFlyout"
|
x:Name="PlaybackSettingsFlyout"
|
||||||
|
Closed="PlaybackSettingsFlyout_Closed"
|
||||||
|
FlyoutPresenterStyle="{StaticResource FlyoutPageStyle}"
|
||||||
Placement="Right"
|
Placement="Right"
|
||||||
ShouldConstrainToRootBounds="False">
|
ShouldConstrainToRootBounds="False" />
|
||||||
<Flyout.FlyoutPresenterStyle>
|
|
||||||
<Style TargetType="FlyoutPresenter">
|
|
||||||
<Setter Property="MinWidth" Value="800" />
|
|
||||||
<Setter Property="Padding" Value="0" />
|
|
||||||
<Setter Property="CornerRadius" Value="12" />
|
|
||||||
<Setter Property="ScrollViewer.VerticalScrollMode" Value="Disabled" />
|
|
||||||
<Setter Property="ScrollViewer.HorizontalScrollMode" Value="Disabled" />
|
|
||||||
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Hidden" />
|
|
||||||
</Style>
|
|
||||||
</Flyout.FlyoutPresenterStyle>
|
|
||||||
<uc:PlaybackSettingsControl MaxWidth="800" MaxHeight="500" />
|
|
||||||
</Flyout>
|
|
||||||
</Button.ContextFlyout>
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
<!-- Display type -->
|
|
||||||
<Button
|
|
||||||
x:Name="DisplayTypeSwitchButton"
|
|
||||||
x:Uid="MainPageDisplayTypeSwitcher"
|
|
||||||
Click="DisplayTypeSwitchButton_Click"
|
|
||||||
Content="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
|
|
||||||
Glyph=}"
|
|
||||||
Style="{StaticResource GhostButtonStyle}">
|
|
||||||
<ToolTipService.ToolTip>
|
|
||||||
<ToolTip x:Name="PresentationTypeToolTip" x:Uid="LyricsPageDisplayTypeButtonToolTip" />
|
|
||||||
</ToolTipService.ToolTip>
|
|
||||||
<Button.ContextFlyout>
|
|
||||||
<Flyout x:Name="DisplayTypeSwitchFlyout" ShouldConstrainToRootBounds="false">
|
|
||||||
<Flyout.FlyoutPresenterStyle>
|
|
||||||
<Style TargetType="FlyoutPresenter">
|
|
||||||
<Setter Property="Padding" Value="12,2,12,8" />
|
|
||||||
<Setter Property="CornerRadius" Value="8" />
|
|
||||||
</Style>
|
|
||||||
</Flyout.FlyoutPresenterStyle>
|
|
||||||
<RadioButtons MaxColumns="1" SelectedIndex="{x:Bind ViewModel.DisplayType, Mode=OneWay, Converter={StaticResource EnumToIntConverter}}">
|
|
||||||
<RadioButton x:Uid="MainPageAlbumArtOnly" Click="AlbumArtOnlyRadioButton_Click" />
|
|
||||||
<RadioButton x:Uid="MainPageLyriscOnly" Click="LyricsOnlyRadioButton_Click" />
|
|
||||||
<RadioButton x:Uid="MainPageSplitView" Click="SplitViewRadioButton_Click" />
|
|
||||||
</RadioButtons>
|
|
||||||
</Flyout>
|
|
||||||
</Button.ContextFlyout>
|
</Button.ContextFlyout>
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
// 2025/6/23 by Zhe Fang
|
// 2025/6/23 by Zhe Fang
|
||||||
|
|
||||||
|
using BetterLyrics.WinUI3.Controls;
|
||||||
using BetterLyrics.WinUI3.Enums;
|
using BetterLyrics.WinUI3.Enums;
|
||||||
using BetterLyrics.WinUI3.Models.Settings;
|
using BetterLyrics.WinUI3.Models.Settings;
|
||||||
using BetterLyrics.WinUI3.Services.MediaSessionsService;
|
using BetterLyrics.WinUI3.Services.MediaSessionsService;
|
||||||
@@ -29,24 +30,6 @@ namespace BetterLyrics.WinUI3.Views
|
|||||||
DataContext = Ioc.Default.GetRequiredService<LyricsPageViewModel>();
|
DataContext = Ioc.Default.GetRequiredService<LyricsPageViewModel>();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void LyricsOnlyRadioButton_Click(object sender, RoutedEventArgs e)
|
|
||||||
{
|
|
||||||
ViewModel.DisplayType = LyricsDisplayType.LyricsOnly;
|
|
||||||
_settingsService.AppSettings.GeneralSettings.DisplayType = ViewModel.DisplayType;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void AlbumArtOnlyRadioButton_Click(object sender, RoutedEventArgs e)
|
|
||||||
{
|
|
||||||
ViewModel.DisplayType = LyricsDisplayType.AlbumArtOnly;
|
|
||||||
_settingsService.AppSettings.GeneralSettings.DisplayType = ViewModel.DisplayType;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SplitViewRadioButton_Click(object sender, RoutedEventArgs e)
|
|
||||||
{
|
|
||||||
ViewModel.DisplayType = LyricsDisplayType.SplitView;
|
|
||||||
_settingsService.AppSettings.GeneralSettings.DisplayType = ViewModel.DisplayType;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void BottomCommandGrid_PointerEntered(object sender, Microsoft.UI.Xaml.Input.PointerRoutedEventArgs e)
|
private void BottomCommandGrid_PointerEntered(object sender, Microsoft.UI.Xaml.Input.PointerRoutedEventArgs e)
|
||||||
{
|
{
|
||||||
if (ViewModel.IsImmersiveMode && BottomCommandGrid.Children.Count != 0)
|
if (ViewModel.IsImmersiveMode && BottomCommandGrid.Children.Count != 0)
|
||||||
@@ -65,13 +48,13 @@ namespace BetterLyrics.WinUI3.Views
|
|||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DisplayTypeSwitchButton_Click(object sender, RoutedEventArgs e)
|
|
||||||
{
|
|
||||||
DisplayTypeSwitchFlyout.ShowAt(BottomRightCommandStackPanel);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void PlaybackSettingsShortcutButton_Click(object sender, RoutedEventArgs e)
|
private void PlaybackSettingsShortcutButton_Click(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
|
PlaybackSettingsFlyout.Content = new PlaybackSettingsControl
|
||||||
|
{
|
||||||
|
MaxHeight = 500,
|
||||||
|
MaxWidth = 850,
|
||||||
|
};
|
||||||
PlaybackSettingsFlyout.ShowAt(BottomRightCommandStackPanel);
|
PlaybackSettingsFlyout.ShowAt(BottomRightCommandStackPanel);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,5 +114,25 @@ namespace BetterLyrics.WinUI3.Views
|
|||||||
{
|
{
|
||||||
_mediaSessionsService.ChangePosition(TimelineSlider.Value);
|
_mediaSessionsService.ChangePosition(TimelineSlider.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void PlaybackSettingsFlyout_Closed(object sender, object e)
|
||||||
|
{
|
||||||
|
PlaybackSettingsFlyout.Content = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LyricsSettingsFlyout_Closed(object sender, object e)
|
||||||
|
{
|
||||||
|
LyricsSettingsFlyout.Content = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LyricsSettingsShortcutButton_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
LyricsSettingsFlyout.Content = new AllLyricsSettingsControl
|
||||||
|
{
|
||||||
|
MaxHeight = 500,
|
||||||
|
MaxWidth = 850,
|
||||||
|
};
|
||||||
|
LyricsSettingsFlyout.ShowAt(BottomRightCommandStackPanel);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,7 +48,8 @@
|
|||||||
<Button
|
<Button
|
||||||
x:Name="ClickThroughButton"
|
x:Name="ClickThroughButton"
|
||||||
Click="ClickThroughButton_Click"
|
Click="ClickThroughButton_Click"
|
||||||
Style="{StaticResource TitleBarButtonStyle}">
|
Style="{StaticResource TitleBarButtonStyle}"
|
||||||
|
Visibility="{x:Bind ViewModel.LockButtonVisibility, Mode=OneWay}">
|
||||||
<FontIcon
|
<FontIcon
|
||||||
FontFamily="{StaticResource IconFontFamily}"
|
FontFamily="{StaticResource IconFontFamily}"
|
||||||
FontSize="{x:Bind ViewModel.TitleBarFontSize, Mode=OneWay}"
|
FontSize="{x:Bind ViewModel.TitleBarFontSize, Mode=OneWay}"
|
||||||
@@ -58,15 +59,6 @@
|
|||||||
<ToolTip.Content>
|
<ToolTip.Content>
|
||||||
<StackPanel Orientation="Horizontal">
|
<StackPanel Orientation="Horizontal">
|
||||||
<TextBlock x:Uid="HostWindowLockToolTip" />
|
<TextBlock x:Uid="HostWindowLockToolTip" />
|
||||||
<TextBlock
|
|
||||||
Margin="6,0"
|
|
||||||
VerticalAlignment="Center"
|
|
||||||
Opacity="0.7"
|
|
||||||
Text="Ctrl + Alt + " />
|
|
||||||
<TextBlock
|
|
||||||
VerticalAlignment="Center"
|
|
||||||
Opacity="0.7"
|
|
||||||
Text="{x:Bind ViewModel.LockHotKey, Mode=OneWay}" />
|
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</ToolTip.Content>
|
</ToolTip.Content>
|
||||||
</ToolTip>
|
</ToolTip>
|
||||||
@@ -86,34 +78,63 @@
|
|||||||
<ToggleMenuFlyoutItem
|
<ToggleMenuFlyoutItem
|
||||||
x:Name="AOTFlyoutItem"
|
x:Name="AOTFlyoutItem"
|
||||||
x:Uid="BaseWindowAOTFlyoutItem"
|
x:Uid="BaseWindowAOTFlyoutItem"
|
||||||
Click="AOTFlyoutItem_Click" />
|
Click="AOTFlyoutItem_Click"
|
||||||
|
Icon="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
|
||||||
|
Glyph=}"
|
||||||
|
IsChecked="{x:Bind ViewModel.IsAOTFlyoutItemChecked, Mode=OneWay}"
|
||||||
|
Visibility="{x:Bind ViewModel.AOTFlyoutItemVisibility, Mode=OneWay}" />
|
||||||
<ToggleMenuFlyoutItem
|
<ToggleMenuFlyoutItem
|
||||||
x:Name="FullScreenFlyoutItem"
|
x:Name="FullScreenFlyoutItem"
|
||||||
x:Uid="BaseWindowFullScreenFlyoutItem"
|
x:Uid="BaseWindowFullScreenFlyoutItem"
|
||||||
Click="FullScreenFlyoutItem_Click" />
|
Click="FullScreenFlyoutItem_Click"
|
||||||
|
Icon="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
|
||||||
|
Glyph=}"
|
||||||
|
IsChecked="{x:Bind ViewModel.IsFullScreenFlyoutItemChecked, Mode=OneWay}"
|
||||||
|
Visibility="{x:Bind ViewModel.FullScreenFlyoutItemVisibility, Mode=OneWay}" />
|
||||||
|
<MenuFlyoutSeparator />
|
||||||
<ToggleMenuFlyoutItem
|
<ToggleMenuFlyoutItem
|
||||||
x:Name="DockFlyoutItem"
|
x:Name="DockFlyoutItem"
|
||||||
x:Uid="HostWindowDockFlyoutItem"
|
x:Uid="HostWindowDockFlyoutItem"
|
||||||
Click="DockFlyoutItem_Click"
|
Click="DockFlyoutItem_Click"
|
||||||
IsChecked="{x:Bind ViewModel.IsDockMode, Mode=OneWay}" />
|
Icon="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
|
||||||
|
Glyph=}"
|
||||||
|
IsChecked="{x:Bind ViewModel.IsDockFlyoutItemChecked, Mode=OneWay}"
|
||||||
|
Visibility="{x:Bind ViewModel.DockFlyoutItemVisibility, Mode=OneWay}" />
|
||||||
<ToggleMenuFlyoutItem
|
<ToggleMenuFlyoutItem
|
||||||
x:Name="DesktopFlyoutItem"
|
x:Name="DesktopFlyoutItem"
|
||||||
x:Uid="HostWindowDesktopFlyoutItem"
|
x:Uid="HostWindowDesktopFlyoutItem"
|
||||||
Click="DesktopFlyoutItem_Click"
|
Click="DesktopFlyoutItem_Click"
|
||||||
IsChecked="{x:Bind ViewModel.IsDesktopMode, Mode=OneWay}" />
|
Icon="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
|
||||||
|
Glyph=}"
|
||||||
|
IsChecked="{x:Bind ViewModel.IsDesktopFlyoutItemChecked, Mode=OneWay}"
|
||||||
|
Visibility="{x:Bind ViewModel.DesktopFlyoutItemVisibility, Mode=OneWay}" />
|
||||||
<ToggleMenuFlyoutItem
|
<ToggleMenuFlyoutItem
|
||||||
x:Name="MiniFlyoutItem"
|
x:Name="PIPFlyoutItem"
|
||||||
x:Uid="BaseWindowMiniFlyoutItem"
|
x:Uid="BaseWindowMiniFlyoutItem"
|
||||||
Click="MiniFlyoutItem_Click" />
|
Click="PIPFlyoutItem_Click"
|
||||||
|
Icon="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
|
||||||
|
Glyph=}"
|
||||||
|
IsChecked="{x:Bind ViewModel.IsPIPFlyoutItemChecked, Mode=OneWay}"
|
||||||
|
Visibility="{x:Bind ViewModel.PIPFlyoutItemVisibility, Mode=OneWay}" />
|
||||||
|
<MenuFlyoutSeparator />
|
||||||
<MenuFlyoutItem
|
<MenuFlyoutItem
|
||||||
x:Name="MusicGalleryFlyoutItem"
|
x:Name="MusicGalleryFlyoutItem"
|
||||||
x:Uid="SystemTrayMusicGallery"
|
x:Uid="SystemTrayMusicGallery"
|
||||||
Click="MusicGalleryMenuFlyoutItem_Click" />
|
Click="MusicGalleryMenuFlyoutItem_Click"
|
||||||
|
Icon="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
|
||||||
|
Glyph=}" />
|
||||||
<MenuFlyoutItem
|
<MenuFlyoutItem
|
||||||
x:Name="SettingsFlyoutItem"
|
x:Name="SettingsFlyoutItem"
|
||||||
x:Uid="SystemTraySettings"
|
x:Uid="SystemTraySettings"
|
||||||
Click="SettingsMenuFlyoutItem_Click" />
|
Click="SettingsMenuFlyoutItem_Click"
|
||||||
<MenuFlyoutItem x:Uid="SystemTrayExit" Click="ExitAppMenuFlyoutItem_Click" />
|
Icon="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
|
||||||
|
Glyph=}" />
|
||||||
|
<MenuFlyoutSeparator />
|
||||||
|
<MenuFlyoutItem
|
||||||
|
x:Uid="SystemTrayExit"
|
||||||
|
Click="ExitAppMenuFlyoutItem_Click"
|
||||||
|
Icon="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
|
||||||
|
Glyph=}" />
|
||||||
</MenuFlyout>
|
</MenuFlyout>
|
||||||
</Button.Flyout>
|
</Button.Flyout>
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ namespace BetterLyrics.WinUI3.Views
|
|||||||
{
|
{
|
||||||
private readonly ISettingsService _settingsService = Ioc.Default.GetRequiredService<ISettingsService>();
|
private readonly ISettingsService _settingsService = Ioc.Default.GetRequiredService<ISettingsService>();
|
||||||
private readonly WindowMessageMonitor _wmm;
|
private readonly WindowMessageMonitor _wmm;
|
||||||
|
private bool _autoSelectLyricsModeOnRunning = true;
|
||||||
|
|
||||||
public LyricsWindow()
|
public LyricsWindow()
|
||||||
{
|
{
|
||||||
@@ -42,7 +43,8 @@ namespace BetterLyrics.WinUI3.Views
|
|||||||
|
|
||||||
private void AppWindow_Closing(AppWindow sender, AppWindowClosingEventArgs args)
|
private void AppWindow_Closing(AppWindow sender, AppWindowClosingEventArgs args)
|
||||||
{
|
{
|
||||||
WindowHelper.ExitApp();
|
ViewModel.ExitOrClose();
|
||||||
|
args.Cancel = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateTitleBarArea()
|
public void UpdateTitleBarArea()
|
||||||
@@ -68,41 +70,47 @@ namespace BetterLyrics.WinUI3.Views
|
|||||||
|
|
||||||
public LyricsWindowViewModel ViewModel { get; private set; } = Ioc.Default.GetRequiredService<LyricsWindowViewModel>();
|
public LyricsWindowViewModel ViewModel { get; private set; } = Ioc.Default.GetRequiredService<LyricsWindowViewModel>();
|
||||||
|
|
||||||
public void AutoSelectLyricsMode(AutoStartWindowType? type = null, bool? autoLook = null)
|
public void AutoSelectLyricsMode(LyricsWindowMode? type = null)
|
||||||
{
|
{
|
||||||
type ??= _settingsService.AppSettings.GeneralSettings.AutoStartWindowType;
|
type ??= _settingsService.AppSettings.GeneralSettings.AutoStartWindowType;
|
||||||
switch (type!)
|
switch (type!)
|
||||||
{
|
{
|
||||||
case AutoStartWindowType.StandardMode:
|
case LyricsWindowMode.StandardMode:
|
||||||
AppWindow.MoveAndResize(_settingsService.AppSettings.StandardModeSettings.WindowBounds.ToRectInt32());
|
ViewModel.SetStandardModeTitleBarControlsStatus();
|
||||||
break;
|
if (_settingsService.AppSettings.StandardModeSettings.IsMaximized)
|
||||||
case AutoStartWindowType.DockMode:
|
|
||||||
DockFlyoutItem.IsChecked = true;
|
|
||||||
ViewModel.ToggleDockModeCommand.Execute(null);
|
|
||||||
break;
|
|
||||||
case AutoStartWindowType.DesktopMode:
|
|
||||||
DesktopFlyoutItem.IsChecked = true;
|
|
||||||
ViewModel.ToggleDesktopModeCommand.Execute(null);
|
|
||||||
if (autoLook == null && _settingsService.AppSettings.DesktopModeSettings.AutoLockOnDesktopMode)
|
|
||||||
{
|
{
|
||||||
ViewModel.ToggleLockWindowCommand.Execute(null);
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ô<EFBFBD><C3B4>ڴ<EFBFBD>С<EFBFBD>Ա<EFBFBD><D4B1>˳<EFBFBD><CBB3><EFBFBD><EFBFBD><EFBFBD>
|
||||||
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܶ<EFBFBD><DCB6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ļ<EFBFBD><C4BB>ԵӰ<D4B5><D3B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||||
|
this.Maximize();
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AppWindow.MoveAndResize(_settingsService.AppSettings.StandardModeSettings.WindowBounds.ToRectInt32());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case LyricsWindowMode.DockMode:
|
||||||
|
ViewModel.ToggleDockMode();
|
||||||
|
break;
|
||||||
|
case LyricsWindowMode.DesktopMode:
|
||||||
|
ViewModel.ToggleDesktopMode();
|
||||||
|
break;
|
||||||
|
case LyricsWindowMode.PictureInPictureMode:
|
||||||
|
ViewModel.TogglePictureInPictureMode();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
_autoSelectLyricsModeOnRunning = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AOTFlyoutItem_Click(object sender, RoutedEventArgs e)
|
private void AOTFlyoutItem_Click(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
var overlappedPresenter = (OverlappedPresenter)AppWindow.Presenter;
|
ViewModel.ToggleAlwaysOnTop();
|
||||||
overlappedPresenter.IsAlwaysOnTop = !overlappedPresenter.IsAlwaysOnTop;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AppWindow_Changed(AppWindow sender, AppWindowChangedEventArgs args)
|
private void AppWindow_Changed(AppWindow sender, AppWindowChangedEventArgs args)
|
||||||
{
|
{
|
||||||
if (args.DidPresenterChange)
|
if (_autoSelectLyricsModeOnRunning) return;
|
||||||
UpdateTitleBarWindowButtonsVisibility();
|
|
||||||
|
|
||||||
if (args.DidPositionChange || args.DidSizeChange)
|
if (args.DidPositionChange || args.DidSizeChange)
|
||||||
{
|
{
|
||||||
@@ -115,54 +123,42 @@ namespace BetterLyrics.WinUI3.Views
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
App.DispatcherQueueTimer?.Debounce(() =>
|
switch (ViewModel.LiveStates.CurrentLyricsWindowMode)
|
||||||
{
|
{
|
||||||
if (ViewModel.IsDesktopMode)
|
case LyricsWindowMode.StandardMode:
|
||||||
{
|
if (AppWindow.Presenter is OverlappedPresenter overlappedPresenter)
|
||||||
|
{
|
||||||
|
_settingsService.AppSettings.StandardModeSettings.WindowBounds = new Windows.Foundation.Rect(rect.X, rect.Y, size.Width, size.Height);
|
||||||
|
_settingsService.AppSettings.StandardModeSettings.IsMaximized = overlappedPresenter.State == OverlappedPresenterState.Maximized;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case LyricsWindowMode.DockMode:
|
||||||
|
break;
|
||||||
|
case LyricsWindowMode.DesktopMode:
|
||||||
_settingsService.AppSettings.DesktopModeSettings.WindowBounds = new Windows.Foundation.Rect(rect.X, rect.Y, size.Width, size.Height);
|
_settingsService.AppSettings.DesktopModeSettings.WindowBounds = new Windows.Foundation.Rect(rect.X, rect.Y, size.Width, size.Height);
|
||||||
}
|
break;
|
||||||
else if (ViewModel.IsDockMode)
|
case LyricsWindowMode.PictureInPictureMode:
|
||||||
{
|
if (AppWindow.Presenter is CompactOverlayPresenter compactOverlayPresenter)
|
||||||
|
{
|
||||||
}
|
_settingsService.AppSettings.PictureInPictureModeSettings.WindowPosition = new Windows.Foundation.Point(rect.X, rect.Y);
|
||||||
else
|
}
|
||||||
{
|
break;
|
||||||
_settingsService.AppSettings.StandardModeSettings.WindowBounds = new Windows.Foundation.Rect(rect.X, rect.Y, size.Width, size.Height);
|
default:
|
||||||
}
|
break;
|
||||||
}, Constants.Time.DebounceTimeout);
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void FullScreenFlyoutItem_Click(object sender, RoutedEventArgs e)
|
private void FullScreenFlyoutItem_Click(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
switch (AppWindow.Presenter.Kind)
|
|
||||||
{
|
ViewModel.ToggleFullscreen();
|
||||||
case AppWindowPresenterKind.Default:
|
|
||||||
break;
|
|
||||||
case AppWindowPresenterKind.CompactOverlay:
|
|
||||||
break;
|
|
||||||
case AppWindowPresenterKind.FullScreen:
|
|
||||||
AppWindow.SetPresenter(AppWindowPresenterKind.Overlapped);
|
|
||||||
break;
|
|
||||||
case AppWindowPresenterKind.Overlapped:
|
|
||||||
AppWindow.SetPresenter(AppWindowPresenterKind.FullScreen);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void MiniFlyoutItem_Click(object sender, RoutedEventArgs e)
|
private void PIPFlyoutItem_Click(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
if (MiniFlyoutItem.IsChecked)
|
ViewModel.TogglePictureInPictureMode();
|
||||||
{
|
|
||||||
AppWindow.SetPresenter(AppWindowPresenterKind.CompactOverlay);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
AppWindow.SetPresenter(AppWindowPresenterKind.Overlapped);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SettingsMenuFlyoutItem_Click(object sender, RoutedEventArgs e)
|
private void SettingsMenuFlyoutItem_Click(object sender, RoutedEventArgs e)
|
||||||
@@ -170,82 +166,6 @@ namespace BetterLyrics.WinUI3.Views
|
|||||||
WindowHelper.OpenWindow<SettingsWindow>();
|
WindowHelper.OpenWindow<SettingsWindow>();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateTitleBarWindowButtonsVisibility()
|
|
||||||
{
|
|
||||||
switch (AppWindow.Presenter.Kind)
|
|
||||||
{
|
|
||||||
case AppWindowPresenterKind.Default:
|
|
||||||
break;
|
|
||||||
case AppWindowPresenterKind.CompactOverlay:
|
|
||||||
AOTFlyoutItem.Visibility = DesktopFlyoutItem.Visibility = FullScreenFlyoutItem.Visibility = DockFlyoutItem.Visibility =
|
|
||||||
ClickThroughButton.Visibility = Visibility.Collapsed;
|
|
||||||
|
|
||||||
ViewModel.IsImmersiveMode = true;
|
|
||||||
break;
|
|
||||||
case AppWindowPresenterKind.FullScreen:
|
|
||||||
|
|
||||||
AOTFlyoutItem.Visibility =
|
|
||||||
ClickThroughButton.Visibility =
|
|
||||||
DesktopFlyoutItem.Visibility =
|
|
||||||
MiniFlyoutItem.Visibility =
|
|
||||||
DockFlyoutItem.Visibility =
|
|
||||||
Visibility.Collapsed;
|
|
||||||
FullScreenFlyoutItem.IsChecked = true;
|
|
||||||
ViewModel.IsImmersiveMode = true;
|
|
||||||
break;
|
|
||||||
case AppWindowPresenterKind.Overlapped:
|
|
||||||
DockFlyoutItem.Visibility = Visibility.Visible;
|
|
||||||
var overlappedPresenter = (OverlappedPresenter)AppWindow.Presenter;
|
|
||||||
if (DockFlyoutItem.IsChecked)
|
|
||||||
{
|
|
||||||
overlappedPresenter.IsMinimizable =
|
|
||||||
overlappedPresenter.IsMaximizable = false;
|
|
||||||
|
|
||||||
AOTFlyoutItem.Visibility =
|
|
||||||
DesktopFlyoutItem.Visibility =
|
|
||||||
ClickThroughButton.Visibility =
|
|
||||||
FullScreenFlyoutItem.Visibility =
|
|
||||||
MiniFlyoutItem.Visibility =
|
|
||||||
Visibility.Collapsed;
|
|
||||||
|
|
||||||
ViewModel.IsImmersiveMode = true;
|
|
||||||
}
|
|
||||||
else if (DesktopFlyoutItem.IsChecked)
|
|
||||||
{
|
|
||||||
overlappedPresenter.IsMinimizable =
|
|
||||||
overlappedPresenter.IsMaximizable = false;
|
|
||||||
|
|
||||||
DockFlyoutItem.Visibility =
|
|
||||||
AOTFlyoutItem.Visibility =
|
|
||||||
FullScreenFlyoutItem.Visibility =
|
|
||||||
MiniFlyoutItem.Visibility =
|
|
||||||
Visibility.Collapsed;
|
|
||||||
|
|
||||||
ClickThroughButton.Visibility = Visibility.Visible;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
overlappedPresenter.IsMinimizable =
|
|
||||||
overlappedPresenter.IsMaximizable = true;
|
|
||||||
|
|
||||||
AOTFlyoutItem.Visibility =
|
|
||||||
DesktopFlyoutItem.Visibility =
|
|
||||||
DockFlyoutItem.Visibility =
|
|
||||||
MiniFlyoutItem.Visibility =
|
|
||||||
FullScreenFlyoutItem.Visibility =
|
|
||||||
Visibility.Visible;
|
|
||||||
FullScreenFlyoutItem.IsChecked = false;
|
|
||||||
ClickThroughButton.Visibility = Visibility.Collapsed;
|
|
||||||
AOTFlyoutItem.IsChecked = overlappedPresenter.IsAlwaysOnTop;
|
|
||||||
|
|
||||||
ViewModel.IsImmersiveMode = _settingsService.AppSettings.GeneralSettings.IsImmersiveMode;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void TopCommandGrid_PointerEntered(object sender, PointerRoutedEventArgs e)
|
private void TopCommandGrid_PointerEntered(object sender, PointerRoutedEventArgs e)
|
||||||
{
|
{
|
||||||
if (ViewModel.IsImmersiveMode)
|
if (ViewModel.IsImmersiveMode)
|
||||||
@@ -280,18 +200,17 @@ namespace BetterLyrics.WinUI3.Views
|
|||||||
|
|
||||||
private void ClickThroughButton_Click(object sender, RoutedEventArgs e)
|
private void ClickThroughButton_Click(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
ViewModel.ToggleLockWindowCommand.Execute(null);
|
ViewModel.ToggleLockWindow();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DockFlyoutItem_Click(object sender, RoutedEventArgs e)
|
private void DockFlyoutItem_Click(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
ViewModel.ToggleDockModeCommand.Execute(null);
|
ViewModel.ToggleDockMode();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DesktopFlyoutItem_Click(object sender, RoutedEventArgs e)
|
private void DesktopFlyoutItem_Click(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
ViewModel.ToggleDesktopModeCommand.Execute(null);
|
ViewModel.ToggleDesktopMode();
|
||||||
UpdateTitleBarWindowButtonsVisibility();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void MusicGalleryMenuFlyoutItem_Click(object sender, RoutedEventArgs e)
|
private void MusicGalleryMenuFlyoutItem_Click(object sender, RoutedEventArgs e)
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
xmlns:models="using:BetterLyrics.WinUI3.Models"
|
xmlns:models="using:BetterLyrics.WinUI3.Models"
|
||||||
xmlns:templateselector="using:BetterLyrics.WinUI3.TemplateSelector"
|
xmlns:templateselector="using:BetterLyrics.WinUI3.TemplateSelector"
|
||||||
xmlns:ui="using:CommunityToolkit.WinUI"
|
xmlns:ui="using:CommunityToolkit.WinUI"
|
||||||
|
Unloaded="Page_Unloaded"
|
||||||
mc:Ignorable="d">
|
mc:Ignorable="d">
|
||||||
<Page.Resources>
|
<Page.Resources>
|
||||||
<CollectionViewSource
|
<CollectionViewSource
|
||||||
|
|||||||
@@ -177,5 +177,10 @@ namespace BetterLyrics.WinUI3.Views
|
|||||||
ViewModel.PlayingSongIndex = ViewModel.PlayingSongIndex + 1;
|
ViewModel.PlayingSongIndex = ViewModel.PlayingSongIndex + 1;
|
||||||
ViewModel.PlayTrackAt(ViewModel.PlayingSongIndex);
|
ViewModel.PlayTrackAt(ViewModel.PlayingSongIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void Page_Unloaded(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
ViewModel.CancelRefreshSongs();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,6 +34,12 @@ namespace BetterLyrics.WinUI3.Views
|
|||||||
AppWindow.TitleBar.PreferredTheme = TitleBarTheme.UseDefaultAppMode;
|
AppWindow.TitleBar.PreferredTheme = TitleBarTheme.UseDefaultAppMode;
|
||||||
AppWindow.SetIcons();
|
AppWindow.SetIcons();
|
||||||
|
|
||||||
|
AppWindow.Closing += AppWindow_Closing;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AppWindow_Closing(AppWindow sender, AppWindowClosingEventArgs args)
|
||||||
|
{
|
||||||
|
WindowHelper.CloseWindow<MusicGalleryWindow>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -89,7 +89,7 @@
|
|||||||
|
|
||||||
<!-- Lyrics background -->
|
<!-- Lyrics background -->
|
||||||
<controls:Case Value="Background">
|
<controls:Case Value="Background">
|
||||||
<uc:LyricsBavkgroundSettingsControl />
|
<uc:LyricsBackgroundSettingsControl />
|
||||||
</controls:Case>
|
</controls:Case>
|
||||||
|
|
||||||
<!-- Album art area style -->
|
<!-- Album art area style -->
|
||||||
@@ -197,6 +197,19 @@
|
|||||||
<ToggleSwitch IsOn="{x:Bind ViewModel.IsDebugOverlayEnabled, Mode=TwoWay}" />
|
<ToggleSwitch IsOn="{x:Bind ViewModel.IsDebugOverlayEnabled, Mode=TwoWay}" />
|
||||||
</controls:SettingsCard>
|
</controls:SettingsCard>
|
||||||
|
|
||||||
|
<controls:SettingsCard x:Uid="SettingsPageFixedTimeStep" Visibility="Collapsed">
|
||||||
|
<ToggleSwitch IsOn="{x:Bind ViewModel.AppSettings.AdvancedSettings.IsFixedTimeStep, Mode=TwoWay}" />
|
||||||
|
</controls:SettingsCard>
|
||||||
|
|
||||||
|
<controls:SettingsCard x:Uid="SettingsPageFPS" Visibility="Collapsed">
|
||||||
|
<uc:ExtendedSlider
|
||||||
|
Default="60"
|
||||||
|
Frequency="10"
|
||||||
|
Maximum="240"
|
||||||
|
Minimum="30"
|
||||||
|
Value="{x:Bind ViewModel.AppSettings.AdvancedSettings.FPS, Mode=TwoWay}" />
|
||||||
|
</controls:SettingsCard>
|
||||||
|
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Grid>
|
</Grid>
|
||||||
</ScrollViewer>
|
</ScrollViewer>
|
||||||
|
|||||||
@@ -18,9 +18,16 @@ namespace BetterLyrics.WinUI3.Views
|
|||||||
AppWindow.TitleBar.PreferredTheme = TitleBarTheme.UseDefaultAppMode;
|
AppWindow.TitleBar.PreferredTheme = TitleBarTheme.UseDefaultAppMode;
|
||||||
AppWindow.SetIcons();
|
AppWindow.SetIcons();
|
||||||
|
|
||||||
|
AppWindow.Closing += AppWindow_Closing;
|
||||||
|
|
||||||
RootFrame.Navigate(typeof(SettingsPage));
|
RootFrame.Navigate(typeof(SettingsPage));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void AppWindow_Closing(AppWindow sender, AppWindowClosingEventArgs args)
|
||||||
|
{
|
||||||
|
WindowHelper.CloseWindow<SettingsWindow>();
|
||||||
|
}
|
||||||
|
|
||||||
private void TipContainerCenter_Loaded(object sender, RoutedEventArgs e)
|
private void TipContainerCenter_Loaded(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
App.Current.SettingsWindowNotificationPanel = TipContainerCenter;
|
App.Current.SettingsWindowNotificationPanel = TipContainerCenter;
|
||||||
|
|||||||
Reference in New Issue
Block a user