Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b0fd43ead5 | ||
|
|
81c59495c0 | ||
|
|
7c5f1a804e | ||
|
|
13ee4227f7 | ||
|
|
c1360ac972 | ||
|
|
c72aa8a58f | ||
|
|
9545ed610b | ||
|
|
1c4515acb9 | ||
|
|
92a6fe46de | ||
|
|
2f9fa02214 | ||
|
|
c174363c07 | ||
|
|
8506062c9a | ||
|
|
52711cba1f | ||
|
|
7eda076920 | ||
|
|
282c2f5ac0 |
2
.github/FUNDING.yml
vendored
@@ -12,4 +12,4 @@ lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cl
|
||||
polar: # Replace with a single Polar username
|
||||
buy_me_a_coffee: founchoo
|
||||
thanks_dev: # Replace with a single thanks.dev username
|
||||
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
|
||||
custom: ['https://paypal.me/zhefangpay']
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<Identity
|
||||
Name="37412.BetterLyrics"
|
||||
Publisher="CN=E1428B0E-DC1D-4EA4-ACB1-4556569D5BA9"
|
||||
Version="1.0.56.0" />
|
||||
Version="1.0.65.0" />
|
||||
|
||||
<mp:PhoneIdentity PhoneProductId="ca4a4830-fc19-40d9-b823-53e2bff3d816" PhonePublisherId="00000000-0000-0000-0000-000000000000"/>
|
||||
|
||||
|
||||
@@ -51,10 +51,14 @@
|
||||
<converter:TranslationSearchProviderToDisplayNameConverter x:Key="TranslationSearchProviderToDisplayNameConverter" />
|
||||
<converter:AlbumArtSearchProviderToDisplayNameConverter x:Key="AlbumArtSearchProviderToDisplayNameConverter" />
|
||||
<converter:SecondsToFormattedTimeConverter x:Key="SecondsToFormattedTimeConverter" />
|
||||
<converter:MillisecondsToFormattedTimeConverter x:Key="MillisecondsToFormattedTimeConverter" />
|
||||
<converter:MediaSourceProviderToLogoUriConverter x:Key="MediaSourceProviderToLogoUriConverter" />
|
||||
<converter:MediaSourceProviderToDisplayedNameConverter x:Key="MediaSourceProviderToDisplayedNameConverter" />
|
||||
<converter:FPSToTimeSpanConverter x:Key="FPSToTimeSpanConverter" />
|
||||
<converter:ShortcutToStringConverter x:Key="ShortcutToStringConverter" />
|
||||
<converter:BoolNegationToVisibilityConverter x:Key="BoolNegationToVisibilityConverter" />
|
||||
<converter:BoolToOpacityConverter x:Key="BoolToOpacityConverter" />
|
||||
<converter:RectToMarginConverter x:Key="RectToMarginConverter" />
|
||||
|
||||
<converters:BoolToVisibilityConverter x:Key="BoolToVisibilityConverter" />
|
||||
<converters:BoolNegationConverter x:Key="BoolNegationConverter" />
|
||||
|
||||
@@ -118,6 +118,7 @@ namespace BetterLyrics.WinUI3
|
||||
.AddSingleton<PlaybackSettingsControlViewModel>()
|
||||
.AddSingleton<MediaSettingsControlViewModel>()
|
||||
.AddSingleton<AllLyricsSettingsControlViewModel>()
|
||||
.AddSingleton<LyricsSearchControlViewModel>()
|
||||
.AddSingleton<LyricsWindowViewModel>()
|
||||
.AddSingleton<SettingsWindowViewModel>()
|
||||
.AddSingleton<SystemTrayViewModel>()
|
||||
|
||||
BIN
BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/Alipay.jpg
Normal file
|
After Width: | Height: | Size: 140 KiB |
|
Before Width: | Height: | Size: 14 KiB |
BIN
BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/Empty.png
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/Page.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 166 KiB |
|
Before Width: | Height: | Size: 192 KiB |
BIN
BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/WeChatReward.png
Normal file
|
After Width: | Height: | Size: 209 KiB |
@@ -26,11 +26,13 @@
|
||||
<None Remove="Controls\AllLyricsSettingsControl.xaml" />
|
||||
<None Remove="Controls\AppSettingsControl.xaml" />
|
||||
<None Remove="Controls\ExtendedSlider.xaml" />
|
||||
<None Remove="Controls\LyricsSearchControl.xaml" />
|
||||
<None Remove="Controls\LyricsSettingsControl.xaml" />
|
||||
<None Remove="Controls\MediaSettingsControl.xaml" />
|
||||
<None Remove="Controls\PlaybackSettingsControl.xaml" />
|
||||
<None Remove="Controls\ShortcutTextBox.xaml" />
|
||||
<None Remove="Controls\SystemTray.xaml" />
|
||||
<None Remove="Views\LyricsSearchWindow.xaml" />
|
||||
<None Remove="Views\MusicGalleryPage.xaml" />
|
||||
<None Remove="Views\MusicGalleryWindow.xaml" />
|
||||
<None Remove="Views\SettingsWindow.xaml" />
|
||||
@@ -58,6 +60,7 @@
|
||||
<PackageReference Include="CommunityToolkit.WinUI.Extensions" Version="8.2.250402" />
|
||||
<PackageReference Include="CommunityToolkit.WinUI.Helpers" Version="8.2.250402" />
|
||||
<PackageReference Include="CommunityToolkit.WinUI.Media" Version="8.2.250402" />
|
||||
<PackageReference Include="csharp-pinyin" Version="1.0.1" />
|
||||
<PackageReference Include="Dubya.WindowsMediaController" Version="2.5.5" />
|
||||
<PackageReference Include="H.NotifyIcon.WinUI" Version="2.3.0" />
|
||||
<PackageReference Include="Hqub.Last.fm" Version="2.5.1" />
|
||||
@@ -70,6 +73,7 @@
|
||||
<PackageReference Include="Nito.AsyncEx" Version="5.1.2" />
|
||||
<PackageReference Include="Nito.AsyncEx.Tasks" Version="5.1.2" />
|
||||
<PackageReference Include="NTextCat" Version="0.3.65" />
|
||||
<PackageReference Include="RomajiConverter.Core" Version="1.0.9" />
|
||||
<PackageReference Include="Serilog.Extensions.Logging" Version="9.0.3-dev-02320" />
|
||||
<PackageReference Include="Serilog.Sinks.File" Version="7.0.0" />
|
||||
<PackageReference Include="ShadowViewer.Controls.Notification" Version="1.2.1" />
|
||||
@@ -111,10 +115,10 @@
|
||||
<Content Update="Assets\Chrome.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\Discord.png">
|
||||
<Content Update="Assets\Edge.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\Edge.png">
|
||||
<Content Update="Assets\Empty.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\EmptyBox.png">
|
||||
@@ -156,10 +160,10 @@
|
||||
<Content Update="Assets\NetEaseCloudMusic.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\PotPlayer.png">
|
||||
<Content Update="Assets\Page.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\QQ.png">
|
||||
<Content Update="Assets\PotPlayer.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\QQMusic.png">
|
||||
@@ -174,13 +178,20 @@
|
||||
<Content Update="Assets\Spotify.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\Telegram.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\Wiki82.profile.xml">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Update="Views\LyricsSearchWindow.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Update="Controls\LyricsSearchControl.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Update="Controls\ShortcutTextBox.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
|
||||
@@ -8,7 +8,8 @@ namespace BetterLyrics.WinUI3.Constants
|
||||
{
|
||||
public static class Link
|
||||
{
|
||||
public const string GithubUrl = "https://github.com/jayfunc/BetterLyrics";
|
||||
public const string GitHubUrl = "https://github.com/jayfunc/BetterLyrics";
|
||||
public const string FAQUrl = $"{GitHubUrl}/blob/dev/FAQ/FAQ.md";
|
||||
public const string QQGroupUrl = "https://qun.qq.com/universal-share/share?ac=1&authKey=4Q%2BYTq3wZldYpF5SbS5c19ECFsiYoLZFAIcBNNzYpBUtiEjaZ8sZ%2F%2BnFN0qw3lad&busi_data=eyJncm91cENvZGUiOiIxMDU0NzAwMzg4IiwidG9rZW4iOiJiVnhqemVYN0N5QVc3b1ZkR24wWmZOTUtvUkJoWm1JRWlaWW5iZnlBcXJtZUtGc2FFTHNlUlFZMi9iRm03cWF5IiwidWluIjoiMTM5NTczOTY2MCJ9&data=39UmAihyH_o6CZaOs7nk2mO_lz2ruODoDou6pxxh7utcxP4WF5sbDBDOPvZ_Wqfzeey4441anegsLYQJxkrBAA&svctype=4&tempid=h5_group_info";
|
||||
public const string DiscordUrl = "https://discord.gg/5yAQPnyCKv";
|
||||
public const string TelegramUrl = "https://t.me/+svhSLZ7awPsxNGY1";
|
||||
|
||||
@@ -17,6 +17,7 @@ namespace BetterLyrics.WinUI3.Constants
|
||||
public const string PotPlayer = "PotPlayerMini64.exe";
|
||||
public const string Spotify = "Spotify.exe";
|
||||
public const string AppleMusic = "AppleInc.AppleMusicWin_nzyj5cx40ttqa!App";
|
||||
public const string AppleMusicAlternative = "AppleMusic.exe";
|
||||
public const string NetEaseCloudMusic = "cloudmusic.exe";
|
||||
public const string KugouMusic = "kugou";
|
||||
public const string QQMusic = "QQMusic.exe";
|
||||
|
||||
@@ -16,6 +16,7 @@ namespace BetterLyrics.WinUI3.Constants
|
||||
public const string PotPlayer = "PotPlayer";
|
||||
public const string Spotify = "Spotify";
|
||||
public const string AppleMusic = "Apple Music";
|
||||
public const string AppleMusicAlternative = "Apple Music";
|
||||
public const string NetEaseCloudMusic = "网易云音乐";
|
||||
public const string KugouMusic = "酷狗音乐";
|
||||
public const string QQMusic = "QQ 音乐";
|
||||
|
||||
@@ -46,6 +46,15 @@
|
||||
</ComboBox>
|
||||
</controls:SettingsCard>
|
||||
|
||||
<controls:SettingsCard x:Uid="SettingsPageLyricsFontSize" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||
<local:ExtendedSlider
|
||||
Default="18"
|
||||
Frequency="2"
|
||||
Maximum="48"
|
||||
Minimum="12"
|
||||
Value="{x:Bind ViewModel.AppSettings.AlbumArtLayoutSettings.SongInfoFontSize, Mode=TwoWay}" />
|
||||
</controls:SettingsCard>
|
||||
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</ScrollViewer>
|
||||
|
||||
@@ -11,185 +11,375 @@
|
||||
mc:Ignorable="d">
|
||||
|
||||
<Grid>
|
||||
<ScrollViewer Style="{StaticResource SettingsScrollViewerStyle}">
|
||||
<Grid Style="{StaticResource SettingsGridStyle}">
|
||||
<StackPanel Spacing="{StaticResource SettingsCardSpacing}">
|
||||
<controls:SwitchPresenter Margin="0,72,0,0" Value="{Binding SelectedItem.Tag, ElementName=SegmentedControl}">
|
||||
|
||||
<!-- App appearance -->
|
||||
<controls:Case Value="General">
|
||||
<ScrollViewer Style="{StaticResource SettingsScrollViewerStyle}">
|
||||
<Grid Style="{StaticResource SettingsGridStyle}">
|
||||
<StackPanel Spacing="{StaticResource SettingsCardSpacing}">
|
||||
|
||||
<TextBlock x:Uid="SettingsPageAppAppearance" Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" />
|
||||
<!-- App appearance -->
|
||||
|
||||
<controls:SettingsExpander
|
||||
x:Uid="SettingsPageLanguage"
|
||||
HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
|
||||
Glyph=}"
|
||||
IsExpanded="True">
|
||||
<ComboBox SelectedIndex="{x:Bind ViewModel.AppSettings.GeneralSettings.Language, Mode=TwoWay, Converter={StaticResource EnumToIntConverter}}">
|
||||
<ComboBoxItem x:Uid="SettingsPageSystemLanguage" />
|
||||
<ComboBoxItem x:Uid="SettingsPageEN" />
|
||||
<ComboBoxItem x:Uid="SettingsPageSC" />
|
||||
<ComboBoxItem x:Uid="SettingsPageTC" />
|
||||
<ComboBoxItem x:Uid="SettingsPageJA" />
|
||||
<ComboBoxItem x:Uid="SettingsPageKO" />
|
||||
</ComboBox>
|
||||
<controls:SettingsExpander.Items>
|
||||
<controls:SettingsCard>
|
||||
<Button x:Uid="SettingsPageRestart" Command="{x:Bind ViewModel.RestartAppCommand}" />
|
||||
<TextBlock x:Uid="SettingsPageAppAppearance" Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" />
|
||||
|
||||
<controls:SettingsExpander
|
||||
x:Uid="SettingsPageLanguage"
|
||||
HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
|
||||
Glyph=}"
|
||||
IsExpanded="True">
|
||||
<ComboBox SelectedIndex="{x:Bind ViewModel.AppSettings.GeneralSettings.Language, Mode=TwoWay, Converter={StaticResource EnumToIntConverter}}">
|
||||
<ComboBoxItem x:Uid="SettingsPageSystemLanguage" />
|
||||
<ComboBoxItem x:Uid="SettingsPageEN" />
|
||||
<ComboBoxItem x:Uid="SettingsPageSC" />
|
||||
<ComboBoxItem x:Uid="SettingsPageTC" />
|
||||
<ComboBoxItem x:Uid="SettingsPageJA" />
|
||||
<ComboBoxItem x:Uid="SettingsPageKO" />
|
||||
</ComboBox>
|
||||
<controls:SettingsExpander.Items>
|
||||
<controls:SettingsCard>
|
||||
<Button x:Uid="SettingsPageRestart" Command="{x:Bind ViewModel.RestartAppCommand}" />
|
||||
</controls:SettingsCard>
|
||||
</controls:SettingsExpander.Items>
|
||||
</controls:SettingsExpander>
|
||||
|
||||
<!-- App behavior -->
|
||||
|
||||
<TextBlock x:Uid="SettingsPageAppBehavior" Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" />
|
||||
|
||||
<controls:SettingsCard x:Uid="SettingsPageAutoStart" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||
<ToggleSwitch
|
||||
x:Name="AutoStartupToggleSwitch"
|
||||
Loaded="AutoStartupToggleSwitch_Loaded"
|
||||
Unloaded="AutoStartupToggleSwitch_Unloaded" />
|
||||
</controls:SettingsCard>
|
||||
</controls:SettingsExpander.Items>
|
||||
</controls:SettingsExpander>
|
||||
|
||||
<!-- App behavior -->
|
||||
<controls:SettingsCard x:Uid="SettingsPageAutoStartWindow" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||
<ComboBox SelectedIndex="{x:Bind ViewModel.AppSettings.GeneralSettings.AutoStartWindowType, Mode=TwoWay, Converter={StaticResource EnumToIntConverter}}">
|
||||
<ComboBoxItem x:Uid="SettingsPageAutoStartInAppLyrics" />
|
||||
<ComboBoxItem x:Uid="SettingsPageAutoStartDockLyrics" />
|
||||
<ComboBoxItem x:Uid="SettingsPageAutoStartDesktopLyrics" />
|
||||
<ComboBoxItem x:Uid="SettingsPageAutoStartPIPLyrics" />
|
||||
</ComboBox>
|
||||
</controls:SettingsCard>
|
||||
|
||||
<TextBlock x:Uid="SettingsPageAppBehavior" Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" />
|
||||
<controls:SettingsExpander
|
||||
x:Name="LyricsWindowManagerExpander"
|
||||
x:Uid="SettingsPageLyricsWindowManager"
|
||||
HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
|
||||
Glyph=}"
|
||||
IsExpanded="True" />
|
||||
|
||||
<controls:SettingsCard x:Uid="SettingsPageAutoStart" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||
<ToggleSwitch
|
||||
x:Name="AutoStartupToggleSwitch"
|
||||
Loaded="AutoStartupToggleSwitch_Loaded"
|
||||
Unloaded="AutoStartupToggleSwitch_Unloaded" />
|
||||
</controls:SettingsCard>
|
||||
<Grid
|
||||
Margin="0,-20,0,0"
|
||||
Padding="60,16"
|
||||
Background="{ThemeResource CardBackgroundFillColorDefaultBrush}"
|
||||
CornerRadius="4"
|
||||
Visibility="{Binding ElementName=LyricsWindowManagerExpander, Path=IsExpanded, Mode=OneWay, Converter={StaticResource BoolToVisibilityConverter}}">
|
||||
<StackPanel Spacing="16">
|
||||
<TextBlock x:Uid="SettingsPageCurrentLyricsWindowStatus" />
|
||||
<StackPanel HorizontalAlignment="Left" Spacing="4">
|
||||
<Grid
|
||||
Width="{x:Bind ViewModel.LiveStates.DemoLyricsWindowMonitorBounds.Width, Mode=OneWay}"
|
||||
Height="{x:Bind ViewModel.LiveStates.DemoLyricsWindowMonitorBounds.Height, Mode=OneWay}"
|
||||
Background="{ThemeResource CardBackgroundFillColorSecondaryBrush}">
|
||||
<Grid
|
||||
Width="{x:Bind ViewModel.LiveStates.DemoLyricsWindowBounds.Width, Mode=OneWay}"
|
||||
Height="{x:Bind ViewModel.LiveStates.DemoLyricsWindowBounds.Height, Mode=OneWay}"
|
||||
Margin="{x:Bind ViewModel.LiveStates.DemoLyricsWindowBounds, Converter={StaticResource RectToMarginConverter}, Mode=OneWay}"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Top"
|
||||
Background="{ThemeResource AccentFillColorDefaultBrush}"
|
||||
CornerRadius="4" />
|
||||
<TextBlock
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
FontWeight="ExtraBlack"
|
||||
Opacity="0.7"
|
||||
Text="{x:Bind ViewModel.LiveStates.LyricsWindowMonitorName, Mode=OneWay}"
|
||||
TextWrapping="Wrap" />
|
||||
</Grid>
|
||||
<Grid>
|
||||
<Button
|
||||
x:Uid="SettingsPageRecord"
|
||||
HorizontalAlignment="Stretch"
|
||||
Command="{x:Bind ViewModel.RecordCurrentWindowBoundsCommand}"
|
||||
Style="{StaticResource AccentButtonStyle}" />
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
<controls:SettingsCard x:Uid="SettingsPageAutoStartWindow" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||
<ComboBox SelectedIndex="{x:Bind ViewModel.AppSettings.GeneralSettings.AutoStartWindowType, Mode=TwoWay, Converter={StaticResource EnumToIntConverter}}">
|
||||
<ComboBoxItem x:Uid="SettingsPageAutoStartInAppLyrics" />
|
||||
<ComboBoxItem x:Uid="SettingsPageAutoStartDockLyrics" />
|
||||
<ComboBoxItem x:Uid="SettingsPageAutoStartDesktopLyrics" />
|
||||
<ComboBoxItem x:Uid="SettingsPageAutoStartPIPLyrics" />
|
||||
</ComboBox>
|
||||
</controls:SettingsCard>
|
||||
<StackPanel
|
||||
Margin="0,-3,0,0"
|
||||
Padding="60,16"
|
||||
Background="{ThemeResource CardBackgroundFillColorDefaultBrush}"
|
||||
CornerRadius="4"
|
||||
Spacing="16"
|
||||
Visibility="{Binding ElementName=LyricsWindowManagerExpander, Path=IsExpanded, Mode=OneWay, Converter={StaticResource BoolToVisibilityConverter}}">
|
||||
<TextBlock x:Uid="SettingsPageRecordedWindowStatus" />
|
||||
<GridView
|
||||
Margin="-2"
|
||||
CornerRadius="4"
|
||||
ItemsSource="{x:Bind ViewModel.AppSettings.WindowBoundsRecords, Mode=OneWay}"
|
||||
SelectionMode="None">
|
||||
<GridView.ItemContainerStyle>
|
||||
<Style BasedOn="{StaticResource DefaultGridViewItemStyle}" TargetType="GridViewItem">
|
||||
<Setter Property="Margin" Value="5,5,5,5" />
|
||||
</Style>
|
||||
</GridView.ItemContainerStyle>
|
||||
<GridView.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<ItemsWrapGrid Orientation="Horizontal" />
|
||||
</ItemsPanelTemplate>
|
||||
</GridView.ItemsPanel>
|
||||
<GridView.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Grid>
|
||||
<StackPanel Spacing="4">
|
||||
<Grid
|
||||
Width="{Binding DemoMonitorBounds.Width}"
|
||||
Height="{Binding DemoMonitorBounds.Height}"
|
||||
Background="{ThemeResource CardBackgroundFillColorSecondaryBrush}">
|
||||
<Grid
|
||||
Width="{Binding DemoWindowBounds.Width}"
|
||||
Height="{Binding DemoWindowBounds.Height}"
|
||||
Margin="{Binding DemoWindowBounds, Converter={StaticResource RectToMarginConverter}}"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Top"
|
||||
Background="{ThemeResource AccentFillColorDefaultBrush}"
|
||||
CornerRadius="4" />
|
||||
<TextBlock
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
FontWeight="ExtraBlack"
|
||||
Opacity="0.7"
|
||||
Text="{Binding MonitorDeviceName}"
|
||||
TextWrapping="Wrap" />
|
||||
</Grid>
|
||||
<Grid ColumnSpacing="4">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Button
|
||||
x:Uid="SettingsPageDelete"
|
||||
Grid.Column="0"
|
||||
HorizontalAlignment="Stretch"
|
||||
Click="DeleteWindowBoundsRecordButton_Click" />
|
||||
<Button
|
||||
x:Uid="SettingsPageApply"
|
||||
Grid.Column="1"
|
||||
HorizontalAlignment="Stretch"
|
||||
Click="ApplyWindowBoundsRecordButton_Click"
|
||||
Style="{StaticResource AccentButtonStyle}" />
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</GridView.ItemTemplate>
|
||||
</GridView>
|
||||
</StackPanel>
|
||||
|
||||
<controls:SettingsCard x:Uid="SettingsPageIgnoreFullscreenWindow" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||
<ToggleSwitch IsOn="{x:Bind ViewModel.AppSettings.GeneralSettings.IgnoreFullscreenWindow, Mode=TwoWay}" />
|
||||
</controls:SettingsCard>
|
||||
<controls:SettingsCard x:Uid="SettingsPageIgnoreFullscreenWindow" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||
<ToggleSwitch IsOn="{x:Bind ViewModel.AppSettings.GeneralSettings.IgnoreFullscreenWindow, Mode=TwoWay}" />
|
||||
</controls:SettingsCard>
|
||||
|
||||
<controls:SettingsCard x:Uid="SettingsPageHideWindow" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||
<ToggleSwitch IsOn="{x:Bind ViewModel.AppSettings.GeneralSettings.HideWindowWhenNotPlaying, Mode=TwoWay}" />
|
||||
</controls:SettingsCard>
|
||||
<controls:SettingsCard x:Uid="SettingsPageHideWindow" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||
<ToggleSwitch IsOn="{x:Bind ViewModel.AppSettings.GeneralSettings.HideWindowWhenNotPlaying, Mode=TwoWay}" />
|
||||
</controls:SettingsCard>
|
||||
|
||||
<controls:SettingsCard x:Uid="SettingsPageGlobalDrag" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||
<ToggleSwitch IsOn="{x:Bind ViewModel.AppSettings.GeneralSettings.IsDragEverywhereEnabled, Mode=TwoWay}" />
|
||||
</controls:SettingsCard>
|
||||
<controls:SettingsCard x:Uid="SettingsPageShowHideHotKey" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||
<local:ShortcutTextBox Shortcut="{x:Bind ViewModel.AppSettings.GeneralSettings.ShowOrHideLyricsWindowShortcut, Mode=TwoWay}" />
|
||||
</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>
|
||||
<controls:SettingsCard x:Uid="SettingsPageGlobalDrag" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||
<ToggleSwitch IsOn="{x:Bind ViewModel.AppSettings.GeneralSettings.IsDragEverywhereEnabled, Mode=TwoWay}" />
|
||||
</controls:SettingsCard>
|
||||
|
||||
<!-- Standard mode -->
|
||||
<controls:SettingsCard x:Uid="SettingsPageExitOnLyricsWindowClosed" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||
<ToggleSwitch IsOn="{x:Bind ViewModel.AppSettings.GeneralSettings.ExitOnLyricsWindowClosed, Mode=TwoWay}" />
|
||||
</controls:SettingsCard>
|
||||
|
||||
<TextBlock x:Uid="SettingsPageAppStandard" Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" />
|
||||
<!-- Playback shortcut -->
|
||||
|
||||
<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>
|
||||
<TextBlock x:Uid="SettingsPagePlaybackShortcut" Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" />
|
||||
|
||||
<!-- Desktop mode -->
|
||||
<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>
|
||||
|
||||
<TextBlock x:Uid="SettingsPageAppDesktop" Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" />
|
||||
<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="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="SettingsPagePreviousSongHotKey" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||
<local:ShortcutTextBox Shortcut="{x:Bind ViewModel.AppSettings.GeneralSettings.PreviousSongShortcut, 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=}">
|
||||
<ToggleSwitch IsOn="{x:Bind ViewModel.AppSettings.DesktopModeSettings.AutoLockOnDesktopMode, Mode=TwoWay}" />
|
||||
</controls:SettingsCard>
|
||||
|
||||
<controls:SettingsCard x:Uid="SettingsPageLockHotKey" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||
<local:ShortcutTextBox Shortcut="{x:Bind ViewModel.AppSettings.DesktopModeSettings.LockShortcut, Mode=TwoWay}" />
|
||||
</controls:SettingsCard>
|
||||
|
||||
<!-- Dock mode -->
|
||||
|
||||
<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=}">
|
||||
<StackPanel Orientation="Horizontal" Spacing="6">
|
||||
<ComboBox ItemsSource="{x:Bind ViewModel.MonitorDeviceNames, Mode=OneWay}" SelectedItem="{x:Bind ViewModel.AppSettings.DockModeSettings.DockMonitorDeviceName, Mode=TwoWay}" />
|
||||
<Button
|
||||
Command="{x:Bind ViewModel.RefreshMonitorDeviceNamesCommand}"
|
||||
Content="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
|
||||
FontSize=12,
|
||||
Glyph=}"
|
||||
Style="{StaticResource GhostButtonStyle}" />
|
||||
</StackPanel>
|
||||
</controls:SettingsCard>
|
||||
</Grid>
|
||||
</ScrollViewer>
|
||||
|
||||
<controls:SettingsCard x:Uid="SettingsPageDockWindowHeight" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||
<local:ExtendedSlider
|
||||
Default="64"
|
||||
Frequency="1"
|
||||
Maximum="200"
|
||||
Minimum="64"
|
||||
Unit="px"
|
||||
Value="{x:Bind ViewModel.AppSettings.DockModeSettings.DockWindowHeight, Mode=TwoWay}" />
|
||||
</controls:SettingsCard>
|
||||
</controls:Case>
|
||||
|
||||
<controls:SettingsCard x:Uid="SettingsPageDockPlacement" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||
<ComboBox SelectedIndex="{x:Bind ViewModel.AppSettings.DockModeSettings.DockPlacement, Mode=TwoWay, Converter={StaticResource EnumToIntConverter}}">
|
||||
<ComboBoxItem x:Uid="SettingsPageDockPlacementTop" />
|
||||
<ComboBoxItem x:Uid="SettingsPageDockPlacementBottom" />
|
||||
</ComboBox>
|
||||
</controls:SettingsCard>
|
||||
<controls:Case Value="Standard">
|
||||
<ScrollViewer Style="{StaticResource SettingsScrollViewerStyle}">
|
||||
<Grid Style="{StaticResource SettingsGridStyle}">
|
||||
<StackPanel Spacing="{StaticResource SettingsCardSpacing}">
|
||||
|
||||
<!-- Picture in picture mode -->
|
||||
<!-- Standard mode -->
|
||||
|
||||
<TextBlock x:Uid="SettingsPageAppPictureInPicture" Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" />
|
||||
<TextBlock 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.StandardModeSettings.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="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>
|
||||
<controls:SettingsCard x:Uid="SettingsPageAOT" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||
<ToggleSwitch IsOn="{x:Bind ViewModel.AppSettings.StandardModeSettings.IsAlwaysOnTop, Mode=TwoWay}" />
|
||||
</controls:SettingsCard>
|
||||
|
||||
<!-- Playback shortcut -->
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</ScrollViewer>
|
||||
</controls:Case>
|
||||
|
||||
<TextBlock x:Uid="SettingsPagePlaybackShortcut" Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" />
|
||||
<controls:Case Value="Desktop">
|
||||
<ScrollViewer Style="{StaticResource SettingsScrollViewerStyle}">
|
||||
<Grid Style="{StaticResource SettingsGridStyle}">
|
||||
<StackPanel Spacing="{StaticResource SettingsCardSpacing}">
|
||||
|
||||
<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>
|
||||
<!-- Desktop mode -->
|
||||
|
||||
<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>
|
||||
<TextBlock Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" />
|
||||
|
||||
<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>
|
||||
<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="SettingsPageAOT" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||
<ToggleSwitch IsOn="{x:Bind ViewModel.AppSettings.DesktopModeSettings.IsAlwaysOnTop, Mode=TwoWay}" />
|
||||
</controls:SettingsCard>
|
||||
|
||||
<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="SettingsPageAutoLock" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||
<ToggleSwitch IsOn="{x:Bind ViewModel.AppSettings.DesktopModeSettings.AutoLockOnDesktopMode, Mode=TwoWay}" />
|
||||
</controls:SettingsCard>
|
||||
|
||||
<controls:SettingsCard x:Uid="SettingsPageLockHotKey" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||
<local:ShortcutTextBox Shortcut="{x:Bind ViewModel.AppSettings.DesktopModeSettings.LockShortcut, Mode=TwoWay}" />
|
||||
</controls:SettingsCard>
|
||||
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</ScrollViewer>
|
||||
</controls:Case>
|
||||
|
||||
<controls:Case Value="Dock">
|
||||
<ScrollViewer Style="{StaticResource SettingsScrollViewerStyle}">
|
||||
<Grid Style="{StaticResource SettingsGridStyle}">
|
||||
<StackPanel Spacing="{StaticResource SettingsCardSpacing}">
|
||||
|
||||
<!-- Dock mode -->
|
||||
|
||||
<TextBlock Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" />
|
||||
|
||||
<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="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="SettingsPageDockMonitor" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||
<StackPanel Orientation="Horizontal" Spacing="6">
|
||||
<ComboBox ItemsSource="{x:Bind ViewModel.MonitorDeviceNames, Mode=OneWay}" SelectedItem="{x:Bind ViewModel.AppSettings.DockModeSettings.DockMonitorDeviceName, Mode=TwoWay}" />
|
||||
<Button
|
||||
Command="{x:Bind ViewModel.RefreshMonitorDeviceNamesCommand}"
|
||||
Content="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
|
||||
FontSize=12,
|
||||
Glyph=}"
|
||||
Style="{StaticResource GhostButtonStyle}" />
|
||||
</StackPanel>
|
||||
</controls:SettingsCard>
|
||||
|
||||
<controls:SettingsCard x:Uid="SettingsPageDockWindowHeight" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||
<local:ExtendedSlider
|
||||
Default="64"
|
||||
Frequency="1"
|
||||
Maximum="200"
|
||||
Minimum="64"
|
||||
Unit="px"
|
||||
Value="{x:Bind ViewModel.AppSettings.DockModeSettings.DockWindowHeight, Mode=TwoWay}" />
|
||||
</controls:SettingsCard>
|
||||
|
||||
<controls:SettingsCard x:Uid="SettingsPageDockPlacement" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||
<ComboBox SelectedIndex="{x:Bind ViewModel.AppSettings.DockModeSettings.DockPlacement, Mode=TwoWay, Converter={StaticResource EnumToIntConverter}}">
|
||||
<ComboBoxItem x:Uid="SettingsPageDockPlacementTop" />
|
||||
<ComboBoxItem x:Uid="SettingsPageDockPlacementBottom" />
|
||||
</ComboBox>
|
||||
</controls:SettingsCard>
|
||||
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</ScrollViewer>
|
||||
</controls:Case>
|
||||
|
||||
<controls:Case Value="PictureInPicture">
|
||||
<ScrollViewer Style="{StaticResource SettingsScrollViewerStyle}">
|
||||
<Grid Style="{StaticResource SettingsGridStyle}">
|
||||
<StackPanel Spacing="{StaticResource SettingsCardSpacing}">
|
||||
|
||||
<!-- Picture in picture mode -->
|
||||
|
||||
<TextBlock Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" />
|
||||
|
||||
<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>
|
||||
|
||||
<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>
|
||||
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</ScrollViewer>
|
||||
</controls:Case>
|
||||
|
||||
</controls:SwitchPresenter>
|
||||
<controls:Segmented
|
||||
x:Name="SegmentedControl"
|
||||
Margin="36,36,36,0"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Top"
|
||||
SelectedIndex="0">
|
||||
<controls:SegmentedItem x:Uid="AppSettingsControlGeneral" Tag="General" />
|
||||
<controls:SegmentedItem x:Uid="AllLyricsSettingsControlStandard" Tag="Standard" />
|
||||
<controls:SegmentedItem x:Uid="AllLyricsSettingsControlDock" Tag="Dock" />
|
||||
<controls:SegmentedItem x:Uid="AllLyricsSettingsControlDesktop" Tag="Desktop" />
|
||||
<controls:SegmentedItem x:Uid="AllLyricsSettingsControlPictureInPicture" Tag="PictureInPicture" />
|
||||
</controls:Segmented>
|
||||
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</ScrollViewer>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
using BetterLyrics.WinUI3.Helper;
|
||||
using BetterLyrics.WinUI3.Models;
|
||||
using BetterLyrics.WinUI3.Models.Settings;
|
||||
using BetterLyrics.WinUI3.ViewModels;
|
||||
using BetterLyrics.WinUI3.Views;
|
||||
using CommunityToolkit.Mvvm.DependencyInjection;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
@@ -46,5 +49,33 @@ namespace BetterLyrics.WinUI3.Controls
|
||||
{
|
||||
AutoStartupToggleSwitch.Toggled -= AutoStartupToggleSwitch_Toggled;
|
||||
}
|
||||
|
||||
private void DeleteWindowBoundsRecordButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (sender is Button button)
|
||||
{
|
||||
var data = button.DataContext as WindowBoundsRecord;
|
||||
if (data != null)
|
||||
{
|
||||
ViewModel.AppSettings.WindowBoundsRecords.Remove(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyWindowBoundsRecordButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (sender is Button button)
|
||||
{
|
||||
var data = button.DataContext as WindowBoundsRecord;
|
||||
if (data != null)
|
||||
{
|
||||
var lyricsWindow = WindowHelper.GetWindowByWindowType<LyricsWindow>();
|
||||
if (lyricsWindow != null)
|
||||
{
|
||||
lyricsWindow.AppWindow.MoveAndResize(data.WindowBounds.ToRectInt32());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,227 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<UserControl
|
||||
x:Class="BetterLyrics.WinUI3.Controls.LyricsSearchControl"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:controls="using:CommunityToolkit.WinUI.Controls"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:interactivity="using:Microsoft.Xaml.Interactivity"
|
||||
xmlns:local="using:BetterLyrics.WinUI3.Controls"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:ui="using:CommunityToolkit.WinUI"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<Grid Padding="16" RowSpacing="6">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid Grid.Row="0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid Grid.Column="0">
|
||||
<StackPanel Spacing="{StaticResource SettingsCardSpacing}">
|
||||
<controls:SettingsExpander x:Uid="LyricsSearchControlSongInfoMapping" IsExpanded="True">
|
||||
<controls:SettingsExpander.Items>
|
||||
<controls:SettingsCard x:Uid="LyricsSearchControlTitle" Description="{x:Bind ViewModel.MappedSongSearchQuery.OriginalTitle, Mode=OneWay}">
|
||||
<StackPanel Orientation="Horizontal" Spacing="6">
|
||||
<TextBlock x:Uid="LyricsSearchControlMappedAs" VerticalAlignment="Center" />
|
||||
<TextBox Text="{x:Bind ViewModel.MappedSongSearchQuery.MappedTitle, Mode=TwoWay}" TextWrapping="Wrap" />
|
||||
<Button
|
||||
VerticalAlignment="Center"
|
||||
Command="{x:Bind ViewModel.ResetMappedTitleCommand}"
|
||||
Content="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
|
||||
FontSize=12,
|
||||
Glyph=}"
|
||||
Style="{StaticResource GhostButtonStyle}" />
|
||||
</StackPanel>
|
||||
</controls:SettingsCard>
|
||||
<controls:SettingsCard x:Uid="LyricsSearchControlArtist" Description="{x:Bind ViewModel.MappedSongSearchQuery.OriginalArtist, Mode=OneWay}">
|
||||
<StackPanel Orientation="Horizontal" Spacing="6">
|
||||
<TextBlock x:Uid="LyricsSearchControlMappedAs" VerticalAlignment="Center" />
|
||||
<TextBox Text="{x:Bind ViewModel.MappedSongSearchQuery.MappedArtist, Mode=TwoWay}" TextWrapping="Wrap" />
|
||||
<Button
|
||||
VerticalAlignment="Center"
|
||||
Command="{x:Bind ViewModel.ResetMappedArtistCommand}"
|
||||
Content="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
|
||||
FontSize=12,
|
||||
Glyph=}"
|
||||
Style="{StaticResource GhostButtonStyle}" />
|
||||
</StackPanel>
|
||||
</controls:SettingsCard>
|
||||
<controls:SettingsCard>
|
||||
<CheckBox x:Uid="LyricsSearchControlMarkAsPureMusic" IsChecked="{x:Bind ViewModel.MappedSongSearchQuery.IsMarkedAsPureMusic, Mode=TwoWay}" />
|
||||
</controls:SettingsCard>
|
||||
</controls:SettingsExpander.Items>
|
||||
</controls:SettingsExpander>
|
||||
|
||||
<controls:SettingsCard x:Uid="LyricsSearchControlTargetSearchProvider">
|
||||
<Button
|
||||
x:Uid="LyricsSearchControlSearch"
|
||||
Command="{x:Bind ViewModel.SearchCommand}"
|
||||
Style="{StaticResource AccentButtonStyle}" />
|
||||
</controls:SettingsCard>
|
||||
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
<Grid Grid.Column="1">
|
||||
<ListView ItemsSource="{x:Bind ViewModel.LyricsSearchResults, Mode=OneWay}" SelectedItem="{x:Bind ViewModel.SelectedLyricsSearchResult, Mode=TwoWay}">
|
||||
<ListView.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<ListViewItem IsEnabled="{Binding IsFound}">
|
||||
<Grid Opacity="{Binding IsFound, Converter={StaticResource BoolToOpacityConverter}}">
|
||||
<RelativePanel Padding="0,6">
|
||||
<TextBlock
|
||||
x:Name="SearchedTitle"
|
||||
RelativePanel.AlignLeftWithPanel="True"
|
||||
Text="{Binding Title}"
|
||||
Visibility="{Binding IsFound, Converter={StaticResource BoolToVisibilityConverter}}" />
|
||||
<TextBlock
|
||||
x:Name="SearchedArtists"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
RelativePanel.AlignLeftWithPanel="True"
|
||||
RelativePanel.Below="SearchedTitle"
|
||||
Text="{Binding Artist}"
|
||||
Visibility="{Binding IsFound, Converter={StaticResource BoolToVisibilityConverter}}" />
|
||||
<TextBlock
|
||||
x:Name="SearchedProvider"
|
||||
RelativePanel.AlignRightWithPanel="True"
|
||||
RelativePanel.AlignVerticalCenterWithPanel="True"
|
||||
Text="{Binding Provider, Converter={StaticResource LyricsSearchProviderToDisplayNameConverter}}" />
|
||||
</RelativePanel>
|
||||
<TextBlock
|
||||
x:Uid="LyricsSearchControlNotFound"
|
||||
VerticalAlignment="Center"
|
||||
Text="Not found"
|
||||
Visibility="{Binding IsFound, Converter={StaticResource BoolNegationToVisibilityConverter}}" />
|
||||
</Grid>
|
||||
</ListViewItem>
|
||||
</DataTemplate>
|
||||
</ListView.ItemTemplate>
|
||||
<interactivity:Interaction.Behaviors>
|
||||
<interactivity:DataTriggerBehavior
|
||||
Binding="{x:Bind ViewModel.LyricsSearchResults.Count, Mode=OneWay}"
|
||||
ComparisonCondition="Equal"
|
||||
Value="0">
|
||||
<interactivity:ChangePropertyAction PropertyName="Visibility" Value="Collapsed" />
|
||||
</interactivity:DataTriggerBehavior>
|
||||
<interactivity:DataTriggerBehavior
|
||||
Binding="{x:Bind ViewModel.LyricsSearchResults.Count, Mode=OneWay}"
|
||||
ComparisonCondition="NotEqual"
|
||||
Value="0">
|
||||
<interactivity:ChangePropertyAction PropertyName="Visibility" Value="Visible" />
|
||||
</interactivity:DataTriggerBehavior>
|
||||
</interactivity:Interaction.Behaviors>
|
||||
</ListView>
|
||||
<StackPanel
|
||||
Padding="0,36"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Spacing="12">
|
||||
<Image MaxWidth="100" Source="/Assets/Empty.png" />
|
||||
<interactivity:Interaction.Behaviors>
|
||||
<interactivity:DataTriggerBehavior
|
||||
Binding="{x:Bind ViewModel.LyricsSearchResults.Count, Mode=OneWay}"
|
||||
ComparisonCondition="NotEqual"
|
||||
Value="0">
|
||||
<interactivity:ChangePropertyAction PropertyName="Visibility" Value="Collapsed" />
|
||||
</interactivity:DataTriggerBehavior>
|
||||
<interactivity:DataTriggerBehavior
|
||||
Binding="{x:Bind ViewModel.LyricsSearchResults.Count, Mode=OneWay}"
|
||||
ComparisonCondition="Equal"
|
||||
Value="0">
|
||||
<interactivity:ChangePropertyAction PropertyName="Visibility" Value="Visible" />
|
||||
</interactivity:DataTriggerBehavior>
|
||||
</interactivity:Interaction.Behaviors>
|
||||
</StackPanel>
|
||||
<ProgressBar
|
||||
VerticalAlignment="Top"
|
||||
IsIndeterminate="True"
|
||||
ShowError="False"
|
||||
ShowPaused="False"
|
||||
Visibility="{x:Bind ViewModel.IsSearching, Converter={StaticResource BoolToVisibilityConverter}, Mode=OneWay}" />
|
||||
</Grid>
|
||||
<Grid Grid.Column="2">
|
||||
<ListView ItemsSource="{x:Bind ViewModel.LyricsData.LyricsLines, Mode=OneWay}" SelectedItem="{x:Bind ViewModel.SelectedLyricsLine, Mode=TwoWay}">
|
||||
<interactivity:Interaction.Behaviors>
|
||||
<interactivity:DataTriggerBehavior
|
||||
Binding="{x:Bind ViewModel.LyricsData, Mode=OneWay}"
|
||||
ComparisonCondition="Equal"
|
||||
Value="{x:Null}">
|
||||
<interactivity:ChangePropertyAction PropertyName="Visibility" Value="Collapsed" />
|
||||
</interactivity:DataTriggerBehavior>
|
||||
<interactivity:DataTriggerBehavior
|
||||
Binding="{x:Bind ViewModel.LyricsData, Mode=OneWay}"
|
||||
ComparisonCondition="NotEqual"
|
||||
Value="{x:Null}">
|
||||
<interactivity:ChangePropertyAction PropertyName="Visibility" Value="Visible" />
|
||||
</interactivity:DataTriggerBehavior>
|
||||
</interactivity:Interaction.Behaviors>
|
||||
<ListView.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock Foreground="{ThemeResource SystemFillColorNeutralBrush}" Text="{Binding StartMs, Converter={StaticResource MillisecondsToFormattedTimeConverter}}" />
|
||||
<TextBlock
|
||||
Margin="1,0"
|
||||
Foreground="{ThemeResource SystemFillColorNeutralBrush}"
|
||||
Text="-" />
|
||||
<TextBlock Foreground="{ThemeResource SystemFillColorNeutralBrush}" Text="{Binding EndMs, Converter={StaticResource MillisecondsToFormattedTimeConverter}}" />
|
||||
<TextBlock Margin="6,0" Text="{Binding OriginalText}" />
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
</ListView.ItemTemplate>
|
||||
</ListView>
|
||||
<StackPanel
|
||||
Padding="0,36"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Spacing="12">
|
||||
<Image MaxWidth="100" Source="/Assets/Page.png" />
|
||||
<interactivity:Interaction.Behaviors>
|
||||
<interactivity:DataTriggerBehavior
|
||||
Binding="{x:Bind ViewModel.LyricsData, Mode=OneWay}"
|
||||
ComparisonCondition="NotEqual"
|
||||
Value="{x:Null}">
|
||||
<interactivity:ChangePropertyAction PropertyName="Visibility" Value="Collapsed" />
|
||||
</interactivity:DataTriggerBehavior>
|
||||
<interactivity:DataTriggerBehavior
|
||||
Binding="{x:Bind ViewModel.LyricsData, Mode=OneWay}"
|
||||
ComparisonCondition="Equal"
|
||||
Value="{x:Null}">
|
||||
<interactivity:ChangePropertyAction PropertyName="Visibility" Value="Visible" />
|
||||
</interactivity:DataTriggerBehavior>
|
||||
</interactivity:Interaction.Behaviors>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid Grid.Row="1">
|
||||
<RelativePanel>
|
||||
<TextBlock
|
||||
x:Uid="LyricsSearchControlHelp"
|
||||
Margin="0,0,24,0"
|
||||
FontSize="12"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
RelativePanel.AlignVerticalCenterWithPanel="True"
|
||||
RelativePanel.LeftOf="Reset"
|
||||
TextWrapping="Wrap" />
|
||||
<Button
|
||||
x:Name="Reset"
|
||||
x:Uid="LyricsSearchControlReset"
|
||||
Margin="0,0,6,0"
|
||||
Command="{x:Bind ViewModel.ResetCommand}"
|
||||
RelativePanel.AlignVerticalCenterWithPanel="True"
|
||||
RelativePanel.LeftOf="SaveChanges" />
|
||||
<Button
|
||||
x:Name="SaveChanges"
|
||||
x:Uid="LyricsSearchControlSaveChanges"
|
||||
Command="{x:Bind ViewModel.SaveCommand}"
|
||||
RelativePanel.AlignRightWithPanel="True"
|
||||
RelativePanel.AlignVerticalCenterWithPanel="True"
|
||||
Style="{StaticResource AccentButtonStyle}" />
|
||||
</RelativePanel>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,35 @@
|
||||
using BetterLyrics.WinUI3.Models;
|
||||
using BetterLyrics.WinUI3.ViewModels;
|
||||
using CommunityToolkit.Mvvm.DependencyInjection;
|
||||
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 Ude.Core;
|
||||
using Windows.Foundation;
|
||||
using Windows.Foundation.Collections;
|
||||
|
||||
// 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 LyricsSearchControl : UserControl
|
||||
{
|
||||
public LyricsSearchControlViewModel ViewModel => (LyricsSearchControlViewModel)DataContext;
|
||||
|
||||
public LyricsSearchControl()
|
||||
{
|
||||
InitializeComponent();
|
||||
DataContext = Ioc.Default.GetRequiredService<LyricsSearchControlViewModel>();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -175,14 +175,25 @@
|
||||
</interactivity:Interaction.Behaviors>
|
||||
</ColorPicker>
|
||||
|
||||
<controls:SettingsCard x:Uid="SettingsPageLyricsFontSize" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||
<local:ExtendedSlider
|
||||
Frequency="2"
|
||||
Maximum="96"
|
||||
Minimum="12"
|
||||
ResetButtonVisibility="Collapsed"
|
||||
Value="{x:Bind LyricsStyleSettings.LyricsFontSize, Mode=TwoWay}" />
|
||||
</controls:SettingsCard>
|
||||
<controls:SettingsExpander
|
||||
x:Uid="SettingsPageLyricsFontSize"
|
||||
HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
|
||||
Glyph=}"
|
||||
IsExpanded="True">
|
||||
<controls:SettingsExpander.Items>
|
||||
<controls:SettingsCard x:Uid="SettingsPageDynamicLyricsFontSize">
|
||||
<ToggleSwitch IsOn="{x:Bind LyricsStyleSettings.IsDynamicLyricsFontSize, Mode=TwoWay}" />
|
||||
</controls:SettingsCard>
|
||||
<controls:SettingsCard IsEnabled="{x:Bind LyricsStyleSettings.IsDynamicLyricsFontSize, Converter={StaticResource BoolNegationConverter}, Mode=OneWay}">
|
||||
<local:ExtendedSlider
|
||||
Frequency="2"
|
||||
Maximum="96"
|
||||
Minimum="12"
|
||||
ResetButtonVisibility="Collapsed"
|
||||
Value="{x:Bind LyricsStyleSettings.LyricsFontSize, Mode=TwoWay}" />
|
||||
</controls:SettingsCard>
|
||||
</controls:SettingsExpander.Items>
|
||||
</controls:SettingsExpander>
|
||||
|
||||
<controls:SettingsCard x:Uid="SettingsPageLyricsLineSpacingFactor" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||
<local:ExtendedSlider
|
||||
|
||||
@@ -31,16 +31,20 @@
|
||||
</controls:SettingsCard>
|
||||
|
||||
<!-- 时间轴相关配置 -->
|
||||
<controls:SettingsCard x:Uid="SettingsPageLyricsTimelineThreshold">
|
||||
<local:ExtendedSlider
|
||||
x:Uid="SettingsPageLyricsTimelineThresholdReset"
|
||||
Frequency="100"
|
||||
Maximum="1000"
|
||||
Minimum="0"
|
||||
ResetButtonVisibility="Collapsed"
|
||||
Unit="ms"
|
||||
Value="{x:Bind ViewModel.SelectedMediaSourceProvider.TimelineSyncThreshold, Mode=TwoWay}" />
|
||||
</controls:SettingsCard>
|
||||
<controls:SettingsExpander x:Uid="SettingsPageLyricsTimeline" IsExpanded="True">
|
||||
<ToggleSwitch IsOn="{x:Bind ViewModel.SelectedMediaSourceProvider.IsTimelineSyncEnabled, Mode=TwoWay}" />
|
||||
<controls:SettingsExpander.Items>
|
||||
<controls:SettingsCard x:Uid="SettingsPageLyricsTimelineThreshold" IsEnabled="{x:Bind ViewModel.SelectedMediaSourceProvider.IsTimelineSyncEnabled, Mode=OneWay}">
|
||||
<local:ExtendedSlider
|
||||
Frequency="100"
|
||||
Maximum="1000"
|
||||
Minimum="0"
|
||||
ResetButtonVisibility="Collapsed"
|
||||
Unit="ms"
|
||||
Value="{x:Bind ViewModel.SelectedMediaSourceProvider.TimelineSyncThreshold, Mode=TwoWay}" />
|
||||
</controls:SettingsCard>
|
||||
</controls:SettingsExpander.Items>
|
||||
</controls:SettingsExpander>
|
||||
<controls:SettingsExpander x:Uid="MainPagePositionOffsetSlider" IsExpanded="True">
|
||||
<local:ExtendedSlider
|
||||
x:Uid="SettingsPagePositionOffsetReset"
|
||||
@@ -227,12 +231,11 @@
|
||||
IsExpanded="True">
|
||||
<ToggleSwitch IsOn="{x:Bind ViewModel.AppSettings.TranslationSettings.IsTranslationEnabled, Mode=TwoWay}" />
|
||||
<controls:SettingsExpander.Items>
|
||||
<controls:SettingsCard x:Uid="SettingsPageTargetLanguage">
|
||||
<controls:SettingsCard x:Uid="SettingsPageTargetLanguage" IsEnabled="{x:Bind ViewModel.AppSettings.TranslationSettings.IsTranslationEnabled, Mode=OneWay}">
|
||||
<ComboBox SelectedIndex="{x:Bind ViewModel.AppSettings.TranslationSettings.SelectedTargetLanguageIndex, Mode=TwoWay}">
|
||||
<ComboBoxItem Content="العربية" Tag="ar" />
|
||||
<ComboBoxItem Content="Azərbaycan dili" Tag="az" />
|
||||
<ComboBoxItem Content="简体中文" Tag="zh-Hans" />
|
||||
<ComboBoxItem Content="繁體中文" Tag="zh-Hant" />
|
||||
<ComboBoxItem Content="中文" Tag="zh" />
|
||||
<ComboBoxItem Content="Čeština" Tag="cs" />
|
||||
<ComboBoxItem Content="Dansk" Tag="da" />
|
||||
<ComboBoxItem Content="Nederlands" Tag="nl" />
|
||||
@@ -262,7 +265,7 @@
|
||||
<ComboBoxItem Content="Tiếng Việt" Tag="vi" />
|
||||
</ComboBox>
|
||||
</controls:SettingsCard>
|
||||
<controls:SettingsCard x:Uid="SettingsPageTranslationConfig">
|
||||
<controls:SettingsCard x:Uid="SettingsPageTranslationConfig" IsEnabled="{x:Bind ViewModel.AppSettings.TranslationSettings.IsTranslationEnabled, Mode=OneWay}">
|
||||
<controls:SettingsCard.Description>
|
||||
<HyperlinkButton Margin="0,6,0,0" NavigateUri="https://github.com/LibreTranslate/LibreTranslate">
|
||||
<TextBlock
|
||||
@@ -291,6 +294,29 @@
|
||||
</controls:SettingsCard>
|
||||
</controls:SettingsExpander.Items>
|
||||
</controls:SettingsExpander>
|
||||
<!-- Lyrics phonetic -->
|
||||
<controls:SettingsExpander
|
||||
x:Uid="SettingsPageChinese"
|
||||
IsEnabled="{x:Bind ViewModel.AppSettings.TranslationSettings.IsTranslationEnabled, Mode=OneWay}"
|
||||
IsExpanded="True">
|
||||
<ToggleSwitch IsOn="{x:Bind ViewModel.AppSettings.TranslationSettings.IsChineseRomanizationEnabled, Mode=TwoWay}" />
|
||||
<controls:SettingsExpander.Items>
|
||||
<controls:SettingsCard>
|
||||
<ComboBox SelectedIndex="{x:Bind ViewModel.AppSettings.TranslationSettings.ChineseRomanization, Converter={StaticResource EnumToIntConverter}, Mode=TwoWay}">
|
||||
<ComboBoxItem x:Uid="SettingsPagePinyin" />
|
||||
<ComboBoxItem x:Uid="SettingsPageJyutping" />
|
||||
</ComboBox>
|
||||
</controls:SettingsCard>
|
||||
</controls:SettingsExpander.Items>
|
||||
</controls:SettingsExpander>
|
||||
<controls:SettingsCard x:Uid="SettingsPageJapanese" IsEnabled="{x:Bind ViewModel.AppSettings.TranslationSettings.IsTranslationEnabled, Mode=OneWay}">
|
||||
<ToggleSwitch IsOn="{x:Bind ViewModel.AppSettings.TranslationSettings.IsJapaneseRomanizationEnabled, Mode=TwoWay}" />
|
||||
</controls:SettingsCard>
|
||||
<!-- 中文简体繁体偏好 -->
|
||||
<controls:SettingsCard x:Uid="SettingsPageChinesePreference">
|
||||
<ToggleSwitch IsOn="{x:Bind ViewModel.AppSettings.TranslationSettings.IsTraditionalChineseEnabled, Mode=TwoWay}" />
|
||||
</controls:SettingsCard>
|
||||
<!-- Provider info -->
|
||||
<controls:SettingsCard x:Uid="LyricsPageLyricsProviderPrefix">
|
||||
<TextBlock Foreground="{ThemeResource TextFillColorSecondaryBrush}" Text="{x:Bind ViewModel.LyricsSearchProvider, Mode=OneWay, Converter={StaticResource LyricsSearchProviderToDisplayNameConverter}}" />
|
||||
</controls:SettingsCard>
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Data;
|
||||
using System;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Converter
|
||||
{
|
||||
public partial class BoolNegationToVisibilityConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
if (value is bool boolValue)
|
||||
{
|
||||
return boolValue ? Visibility.Collapsed : Visibility.Visible;
|
||||
}
|
||||
return Visibility.Visible;
|
||||
}
|
||||
|
||||
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 BoolToOpacityConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
if (value is bool boolValue)
|
||||
{
|
||||
return boolValue ? 1.0 : 0.3;
|
||||
}
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,7 @@ namespace BetterLyrics.WinUI3.Converter
|
||||
{
|
||||
PlayerID.Spotify => PathHelper.SpotifyLogoPath,
|
||||
PlayerID.AppleMusic => PathHelper.AppleMusicLogoPath,
|
||||
PlayerID.AppleMusicAlternative => PathHelper.AppleMusicLogoPath,
|
||||
PlayerID.iTunes => PathHelper.iTunesLogoPath,
|
||||
PlayerID.KugouMusic => PathHelper.KugouMusicLogoPath,
|
||||
PlayerID.NetEaseCloudMusic => PathHelper.NetEaseCloudMusicLogoPath,
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
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 MillisecondsToFormattedTimeConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
if (value is int milliseconds)
|
||||
{
|
||||
return TimeSpan.FromMilliseconds(milliseconds).ToString(@"mm\:ss\.fff");
|
||||
}
|
||||
else if (value is double doubleMilliseconds)
|
||||
{
|
||||
return TimeSpan.FromMilliseconds(doubleMilliseconds).ToString(@"mm\:ss\.fff");
|
||||
}
|
||||
return value?.ToString() ?? "";
|
||||
}
|
||||
|
||||
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 RectToMarginConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
if (value is Windows.Foundation.Rect rect)
|
||||
{
|
||||
return new Microsoft.UI.Xaml.Thickness(rect.X, rect.Y, 0, 0);
|
||||
}
|
||||
return new Microsoft.UI.Xaml.Thickness(0);
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Enums
|
||||
{
|
||||
public enum ChineseRomanization
|
||||
{
|
||||
Pinyin,
|
||||
Jyutping,
|
||||
}
|
||||
}
|
||||
@@ -67,5 +67,16 @@ namespace BetterLyrics.WinUI3.Enums
|
||||
_ => ".*",
|
||||
};
|
||||
}
|
||||
|
||||
public static LyricsSearchProvider? ToLyricsSearchProvider(this LyricsFormat format)
|
||||
{
|
||||
return format switch
|
||||
{
|
||||
LyricsFormat.Lrc => LyricsSearchProvider.LocalLrcFile,
|
||||
LyricsFormat.Eslrc => LyricsSearchProvider.LocalEslrcFile,
|
||||
LyricsFormat.Ttml => LyricsSearchProvider.LocalTtmlFile,
|
||||
_ => null,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,8 @@ namespace BetterLyrics.WinUI3.Enums
|
||||
{
|
||||
public enum ShortcutID
|
||||
{
|
||||
DesktopLock,
|
||||
LyricsWindowShowOrHide,
|
||||
DesktopLockOrUnlock,
|
||||
DesktopToggle,
|
||||
DockToggle,
|
||||
PictureInPictureToggle,
|
||||
|
||||
@@ -74,9 +74,17 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
using var ds = list.CreateDrawingSession();
|
||||
if (strokeWidth > 0)
|
||||
{
|
||||
if (lyricsLine.TextGeometry == null)
|
||||
{
|
||||
return list;
|
||||
}
|
||||
ds.DrawGeometry(lyricsLine.TextGeometry, lyricsLine.Position, strokeColor, strokeWidth); // 描边
|
||||
}
|
||||
ds.FillGeometry(lyricsLine.TextGeometry, lyricsLine.Position, fontColor); // 填充
|
||||
if (lyricsLine.CanvasTextLayout == null)
|
||||
{
|
||||
return list;
|
||||
}
|
||||
ds.DrawTextLayout(lyricsLine.CanvasTextLayout, lyricsLine.Position, fontColor); // 绘制文本(填充)
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
@@ -94,6 +94,11 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
return Color.FromArgb(alpha, color.R, color.G, color.B);
|
||||
}
|
||||
|
||||
public static Color WithOpacity(this Color color, float opacity)
|
||||
{
|
||||
return Color.FromArgb((byte)(opacity * 255), color.R, color.G, color.B);
|
||||
}
|
||||
|
||||
public static Color WithBrightness(this Color color, double brightness)
|
||||
{
|
||||
// 确保亮度因子在合理范围内
|
||||
@@ -116,15 +121,11 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
{
|
||||
case WindowPixelSampleMode.BelowWindow:
|
||||
{
|
||||
int sampleHeight = 1;
|
||||
int sampleY = myRect.Bottom + 1;
|
||||
return GetAverageColorFromScreenRegion(myRect.Left, sampleY, screenWidth, sampleHeight);
|
||||
return GetAverageColorFromScreenRegion(myRect.Left, myRect.Bottom + 2, screenWidth, 1);
|
||||
}
|
||||
case WindowPixelSampleMode.AboveWindow:
|
||||
{
|
||||
int sampleHeight = 1;
|
||||
int sampleY = myRect.Top - 1;
|
||||
return GetAverageColorFromScreenRegion(myRect.Left, sampleY, screenWidth, sampleHeight);
|
||||
return GetAverageColorFromScreenRegion(myRect.Left, myRect.Top - 3, screenWidth, 1);
|
||||
}
|
||||
case WindowPixelSampleMode.WindowArea:
|
||||
{
|
||||
|
||||
@@ -11,6 +11,6 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
{
|
||||
public static class FontHelper
|
||||
{
|
||||
public static string[] SystemFontFamilies => CanvasTextFormat.GetSystemFontFamilies();
|
||||
public static string[] SystemFontFamilies => CanvasTextFormat.GetSystemFontFamilies().Order().ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,8 +22,7 @@ namespace BetterLyrics.WinUI3.Services
|
||||
[
|
||||
new Models.LanguageInfo("ar", "العربية"),
|
||||
new Models.LanguageInfo("az", "Azərbaycan dili"),
|
||||
new Models.LanguageInfo("zh-Hans", "简体中文"),
|
||||
new Models.LanguageInfo("zh-Hant", "繁體中文"),
|
||||
new Models.LanguageInfo("zh", "中文"),
|
||||
new Models.LanguageInfo("cs", "Čeština"),
|
||||
new Models.LanguageInfo("da", "Dansk"),
|
||||
new Models.LanguageInfo("nl", "Nederlands"),
|
||||
@@ -56,11 +55,7 @@ namespace BetterLyrics.WinUI3.Services
|
||||
static LanguageHelper()
|
||||
{
|
||||
_identifier = _factory.Load(PathHelper.LanguageProfilePath);
|
||||
}
|
||||
|
||||
private static string SimplifiedChineseOrTraditionalChinese(string text)
|
||||
{
|
||||
return text == ChineseConverter.ConvertToSimplifiedChinese(text) ? "zh-Hans" : "zh-Hant";
|
||||
RomajiConverter.Core.Helpers.RomajiHelper.Init();
|
||||
}
|
||||
|
||||
public static string? DetectLanguageCode(string? text)
|
||||
@@ -72,9 +67,8 @@ namespace BetterLyrics.WinUI3.Services
|
||||
code = code switch
|
||||
{
|
||||
"simple" => "en",
|
||||
"zh_classical" => SimplifiedChineseOrTraditionalChinese(text),
|
||||
"zh_yue" => SimplifiedChineseOrTraditionalChinese(text),
|
||||
"zh" => SimplifiedChineseOrTraditionalChinese(text),
|
||||
"zh_classical" => "zh",
|
||||
"zh_yue" => "zh",
|
||||
_ => code
|
||||
};
|
||||
return code;
|
||||
@@ -89,21 +83,6 @@ namespace BetterLyrics.WinUI3.Services
|
||||
};
|
||||
}
|
||||
|
||||
public static string ConvertToCountryCode(string? languageCode)
|
||||
{
|
||||
if (languageCode == null) return "us";
|
||||
|
||||
return languageCode switch
|
||||
{
|
||||
"zh" => "cn",
|
||||
"zh-Hans" => "cn",
|
||||
"zh-Hant" => "tw",
|
||||
"ja" => "jp",
|
||||
"ko" => "kr",
|
||||
_ => "us"
|
||||
};
|
||||
}
|
||||
|
||||
public static int GetDefaultTargetLanguageIndex()
|
||||
{
|
||||
int found = SupportedTargetLanguages.FindIndex(x => ApplicationLanguages.Languages.FirstOrDefault()?.Contains(x.Code) == true);
|
||||
@@ -125,5 +104,10 @@ namespace BetterLyrics.WinUI3.Services
|
||||
|
||||
return "#";
|
||||
}
|
||||
|
||||
public static string ToRomaji(string text)
|
||||
{
|
||||
return string.Join(" ", RomajiConverter.Core.Helpers.RomajiHelper.SentenceToRomaji(text).Select(x=>x.Romaji));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Xml.Linq;
|
||||
using Windows.Globalization.Fonts;
|
||||
using LyricsData = BetterLyrics.WinUI3.Models.LyricsData;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Helper
|
||||
@@ -48,50 +47,67 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
break;
|
||||
}
|
||||
}
|
||||
FillChineseLyricsData();
|
||||
FillRomanizationLyricsData();
|
||||
_lyricsDataArr.Add(new LyricsData()); // 为机翻预留
|
||||
return _lyricsDataArr;
|
||||
}
|
||||
|
||||
private void FillChineseLyricsData()
|
||||
private void FillRomanizationLyricsData()
|
||||
{
|
||||
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)
|
||||
var chinese = _lyricsDataArr.Where(x => x.LanguageCode == "zh").FirstOrDefault();
|
||||
if (chinese != null)
|
||||
{
|
||||
// 如果没有繁体中文歌词,则将简体中文歌词转换为繁体中文
|
||||
_lyricsDataArr.Add(new LyricsData
|
||||
{
|
||||
LyricsLines = simplifiedChinese.LyricsLines.Select(line => new LyricsLine
|
||||
LanguageCode = "pinyin",
|
||||
LyricsLines = chinese.LyricsLines.Select(line => new LyricsLine
|
||||
{
|
||||
StartMs = line.StartMs,
|
||||
EndMs = line.EndMs,
|
||||
OriginalText = ChineseConverter.ConvertToTraditionalChinese(line.OriginalText),
|
||||
OriginalText = Pinyin.Pinyin.Instance.HanziToPinyin(line.OriginalText).ToStr(),
|
||||
LyricsChars = line.LyricsChars.Select(c => new LyricsChar
|
||||
{
|
||||
StartMs = c.StartMs,
|
||||
EndMs = c.EndMs,
|
||||
Text = ChineseConverter.ConvertToTraditionalChinese(c.Text),
|
||||
Text = Pinyin.Pinyin.Instance.HanziToPinyin(c.Text).ToStr(),
|
||||
StartIndex = c.StartIndex
|
||||
}).ToList()
|
||||
}).ToList()
|
||||
});
|
||||
_lyricsDataArr.Add(new LyricsData
|
||||
{
|
||||
LanguageCode = "jyutping",
|
||||
LyricsLines = chinese.LyricsLines.Select(line => new LyricsLine
|
||||
{
|
||||
StartMs = line.StartMs,
|
||||
EndMs = line.EndMs,
|
||||
OriginalText = Pinyin.Jyutping.Instance.HanziToPinyin(line.OriginalText).ToStr(),
|
||||
LyricsChars = line.LyricsChars.Select(c => new LyricsChar
|
||||
{
|
||||
StartMs = c.StartMs,
|
||||
EndMs = c.EndMs,
|
||||
Text = Pinyin.Jyutping.Instance.HanziToPinyin(c.Text).ToStr(),
|
||||
StartIndex = c.StartIndex
|
||||
}).ToList()
|
||||
}).ToList()
|
||||
});
|
||||
}
|
||||
else if (traditionalChinese != null && simplifiedChinese == null)
|
||||
var japanese = _lyricsDataArr.Where(x => x.LanguageCode == "ja").FirstOrDefault();
|
||||
if (japanese != null)
|
||||
{
|
||||
// 如果没有简体中文歌词,则将繁体中文歌词转换为简体中文
|
||||
_lyricsDataArr.Add(new LyricsData
|
||||
{
|
||||
LyricsLines = traditionalChinese.LyricsLines.Select(line => new LyricsLine
|
||||
LanguageCode = "romaji",
|
||||
LyricsLines = japanese.LyricsLines.Select(line => new LyricsLine
|
||||
{
|
||||
StartMs = line.StartMs,
|
||||
EndMs = line.EndMs,
|
||||
OriginalText = ChineseConverter.ConvertToSimplifiedChinese(line.OriginalText),
|
||||
OriginalText = LanguageHelper.ToRomaji(line.OriginalText),
|
||||
LyricsChars = line.LyricsChars.Select(c => new LyricsChar
|
||||
{
|
||||
StartMs = c.StartMs,
|
||||
EndMs = c.EndMs,
|
||||
Text = ChineseConverter.ConvertToSimplifiedChinese(c.Text),
|
||||
Text = LanguageHelper.ToRomaji(c.Text),
|
||||
StartIndex = c.StartIndex
|
||||
}).ToList()
|
||||
}).ToList()
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using Microsoft.UI.Xaml;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
@@ -6,6 +7,7 @@ using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Vanara.PInvoke;
|
||||
using WinRT.Interop;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Helper
|
||||
{
|
||||
@@ -60,5 +62,14 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
var primaryMonitorInfo = GetPrimaryMonitorInfoEx();
|
||||
return primaryMonitorInfo.szDevice;
|
||||
}
|
||||
|
||||
public static User32.MONITORINFOEX GetMonitorInfoExFromWindow(Window window)
|
||||
{
|
||||
var hwnd = WindowNative.GetWindowHandle(window);
|
||||
var hMonitor = User32.MonitorFromWindow(hwnd, User32.MonitorFlags.MONITOR_DEFAULTTONEAREST);
|
||||
User32.MONITORINFOEX monitorInfoEx = new() { cbSize = (uint)Marshal.SizeOf<User32.MONITORINFOEX>() };
|
||||
User32.GetMonitorInfo(hMonitor, ref monitorInfoEx);
|
||||
return monitorInfoEx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,6 +59,10 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
{
|
||||
window = new MusicGalleryWindow();
|
||||
}
|
||||
else if (typeof(T) == typeof(LyricsSearchWindow))
|
||||
{
|
||||
window = new LyricsSearchWindow();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException("Unsupported window type", nameof(T));
|
||||
@@ -73,6 +77,7 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
var lyricsWindow = (LyricsWindow)window;
|
||||
lyricsWindow.ViewModel.InitShortcuts();
|
||||
lyricsWindow.AutoSelectLyricsMode();
|
||||
lyricsWindow.ViewModel.SetIsAlwaysOnTop();
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
14
BetterLyrics.WinUI3/BetterLyrics.WinUI3/Models/LibInfo.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Models
|
||||
{
|
||||
public class LibInfo
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string Url => $"https://www.nuget.org/packages/{Name}/";
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using BetterLyrics.WinUI3.Enums;
|
||||
using BetterLyrics.WinUI3.Helper;
|
||||
using BetterLyrics.WinUI3.Models.Settings;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using System;
|
||||
@@ -6,34 +7,70 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Vanara.PInvoke;
|
||||
using Windows.Foundation;
|
||||
|
||||
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; }
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial LyricsWindowMode LyricsWindowMode { get; set; }
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial LyricsDisplayType LyricsDisplayType { get; set; }
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsAlwaysOnTop { get; set; }
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial LyricsStyleSettings LyricsStyleSettings { get; set; }
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial LyricsEffectSettings LyricsEffectSettings { get; set; }
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial Rect LyricsWindowBounds { get; set; }
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial Rect LyricsWindowMonitorBounds { get; set; }
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial Rect DemoLyricsWindowBounds { get; set; }
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial Rect DemoLyricsWindowMonitorBounds { get; set; }
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial string LyricsWindowMonitorName { get; set; }
|
||||
|
||||
public LiveStates(AppSettings appSettings)
|
||||
{
|
||||
CurrentLyricsWindowMode = LyricsWindowMode.StandardMode;
|
||||
CurrentLyricsDisplayType = appSettings.StandardModeSettings.LyricsDisplayType;
|
||||
CurrentLyricsStyleSettings = appSettings.StandardLyricsStyleSettings;
|
||||
CurrentLyricsEffectSettings = appSettings.StandardLyricsEffectSettings;
|
||||
LyricsWindowMode = LyricsWindowMode.StandardMode;
|
||||
LyricsDisplayType = appSettings.StandardModeSettings.LyricsDisplayType;
|
||||
LyricsStyleSettings = appSettings.StandardLyricsStyleSettings;
|
||||
LyricsEffectSettings = appSettings.StandardLyricsEffectSettings;
|
||||
IsAlwaysOnTop = false;
|
||||
}
|
||||
|
||||
public void ToggleLyricsWindowMode(LyricsWindowMode mode)
|
||||
{
|
||||
if (CurrentLyricsWindowMode == mode)
|
||||
if (LyricsWindowMode == mode)
|
||||
{
|
||||
CurrentLyricsWindowMode = LyricsWindowMode.StandardMode;
|
||||
LyricsWindowMode = LyricsWindowMode.StandardMode;
|
||||
}
|
||||
else
|
||||
{
|
||||
CurrentLyricsWindowMode = mode;
|
||||
LyricsWindowMode = mode;
|
||||
}
|
||||
}
|
||||
|
||||
partial void OnLyricsWindowBoundsChanged(Rect value)
|
||||
{
|
||||
double factor = 0.1;
|
||||
DemoLyricsWindowBounds = new Rect(
|
||||
value.X * factor,
|
||||
value.Y * factor,
|
||||
value.Width * factor,
|
||||
value.Height * factor
|
||||
);
|
||||
var lyricsWindow = WindowHelper.GetWindowByWindowType<Views.LyricsWindow>();
|
||||
if (lyricsWindow == null) return;
|
||||
var mointor = MonitorHelper.GetMonitorInfoExFromWindow(lyricsWindow);
|
||||
LyricsWindowMonitorName = mointor.szDevice;
|
||||
LyricsWindowMonitorBounds = new Rect(
|
||||
mointor.rcMonitor.Left,
|
||||
mointor.rcMonitor.Top,
|
||||
mointor.rcMonitor.Width,
|
||||
mointor.rcMonitor.Height
|
||||
);
|
||||
DemoLyricsWindowMonitorBounds = new Rect(
|
||||
mointor.rcMonitor.Left * factor,
|
||||
mointor.rcMonitor.Top * factor,
|
||||
mointor.rcMonitor.Width * factor,
|
||||
mointor.rcMonitor.Height * factor
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using BetterLyrics.WinUI3.Helper;
|
||||
using BetterLyrics.WinUI3.Enums;
|
||||
using BetterLyrics.WinUI3.Helper;
|
||||
using BetterLyrics.WinUI3.Services;
|
||||
using Lyricify.Lyrics.Helpers.General;
|
||||
using System;
|
||||
@@ -13,7 +14,12 @@ namespace BetterLyrics.WinUI3.Models
|
||||
public class LyricsData
|
||||
{
|
||||
public List<LyricsLine> LyricsLines { get; set; }
|
||||
public string? LanguageCode => LanguageHelper.DetectLanguageCode(WrappedOriginalText);
|
||||
private string? _languageCode;
|
||||
public string? LanguageCode
|
||||
{
|
||||
get => _languageCode ?? LanguageHelper.DetectLanguageCode(WrappedOriginalText);
|
||||
set => _languageCode = value;
|
||||
}
|
||||
public string WrappedOriginalText => string.Join(StringHelper.NewLine, LyricsLines.Select(line => line.OriginalText));
|
||||
|
||||
public LyricsData()
|
||||
@@ -120,5 +126,18 @@ namespace BetterLyrics.WinUI3.Models
|
||||
},
|
||||
]);
|
||||
}
|
||||
|
||||
public LyricsLine? GetLyricsLine(double sec)
|
||||
{
|
||||
for (int i = 0; i < LyricsLines.Count; i++)
|
||||
{
|
||||
var line = LyricsLines[i];
|
||||
if (line.StartMs > sec * 1000)
|
||||
{
|
||||
return LyricsLines.ElementAtOrDefault(i - 1);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
using BetterLyrics.WinUI3.Enums;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Models
|
||||
{
|
||||
public class LyricsSearchResult
|
||||
{
|
||||
public bool IsFound => !string.IsNullOrEmpty(Raw);
|
||||
public LyricsSearchProvider? Provider { get; set; }
|
||||
|
||||
public string? Raw { get; set; }
|
||||
|
||||
public string? Title { get; set; }
|
||||
public string? Artist { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
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
|
||||
{
|
||||
public partial class MappedSongSearchQuery : ObservableRecipient
|
||||
{
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial string OriginalTitle { get; set; } = string.Empty;
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial string OriginalArtist { get; set; } = string.Empty;
|
||||
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial string MappedTitle { get; set; } = string.Empty;
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial string MappedArtist { get; set; } = string.Empty;
|
||||
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsMarkedAsPureMusic { get; set; } = false;
|
||||
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial LyricsSearchProvider? LyricsSearchProvider { get; set; }
|
||||
|
||||
public MappedSongSearchQuery Clone()
|
||||
{
|
||||
return new MappedSongSearchQuery
|
||||
{
|
||||
OriginalTitle = this.OriginalTitle,
|
||||
OriginalArtist = this.OriginalArtist,
|
||||
MappedTitle = this.MappedTitle,
|
||||
MappedArtist = this.MappedArtist,
|
||||
IsMarkedAsPureMusic = this.IsMarkedAsPureMusic,
|
||||
LyricsSearchProvider = this.LyricsSearchProvider
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,23 +12,29 @@ namespace BetterLyrics.WinUI3.Models
|
||||
{
|
||||
public partial class MediaSourceProviderInfo : ObservableRecipient
|
||||
{
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsEnabled { get; set; }
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsEnabled { get; set; } = true;
|
||||
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial string Provider { get; set; }
|
||||
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsLastFMTrackEnabled { get; set; }
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsLastFMTrackEnabled { get; set; } = false;
|
||||
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsTimelineSyncEnabled { get; set; } = true;
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial int TimelineSyncThreshold { get; set; }
|
||||
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial int PositionOffset { get; set; }
|
||||
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool ResetPositionOffsetOnSongChanged { get; set; }
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool ResetPositionOffsetOnSongChanged { get; set; } = false;
|
||||
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial FullyObservableCollection<LyricsSearchProviderInfo> LyricsSearchProvidersInfo { get; set; }
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial FullyObservableCollection<LyricsSearchProviderInfo> LyricsSearchProvidersInfo { get; set; } = [.. Enum.GetValues<LyricsSearchProvider>().Select(p => new LyricsSearchProviderInfo(p, true))];
|
||||
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial FullyObservableCollection<AlbumArtSearchProviderInfo> AlbumArtSearchProvidersInfo { get; set; }
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial FullyObservableCollection<AlbumArtSearchProviderInfo> AlbumArtSearchProvidersInfo { get; set; } = [.. Enum.GetValues<AlbumArtSearchProvider>().Select(p => new AlbumArtSearchProviderInfo(p, true))];
|
||||
|
||||
public MediaSourceProviderInfo() { }
|
||||
public MediaSourceProviderInfo()
|
||||
{
|
||||
Provider = string.Empty;
|
||||
TimelineSyncThreshold = 0;
|
||||
PositionOffset = 0;
|
||||
}
|
||||
|
||||
public MediaSourceProviderInfo(string provider) : base()
|
||||
{
|
||||
@@ -47,11 +53,6 @@ namespace BetterLyrics.WinUI3.Models
|
||||
}
|
||||
|
||||
Provider = provider;
|
||||
IsEnabled = true;
|
||||
IsLastFMTrackEnabled = false;
|
||||
ResetPositionOffsetOnSongChanged = false;
|
||||
LyricsSearchProvidersInfo = [.. Enum.GetValues<LyricsSearchProvider>().Select(p => new LyricsSearchProviderInfo(p, true))];
|
||||
AlbumArtSearchProvidersInfo = [.. Enum.GetValues<AlbumArtSearchProvider>().Select(p => new AlbumArtSearchProviderInfo(p, true))];
|
||||
}
|
||||
|
||||
partial void OnAlbumArtSearchProvidersInfoChanged(FullyObservableCollection<AlbumArtSearchProviderInfo> oldValue, FullyObservableCollection<AlbumArtSearchProviderInfo> newValue)
|
||||
|
||||
@@ -13,6 +13,7 @@ namespace BetterLyrics.WinUI3.Models.Settings
|
||||
[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 CoverImageShadowAmount { get; set; } = 12;
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial int SongInfoFontSize { get; set; } = 18;
|
||||
|
||||
public AlbumArtLayoutSettings() { }
|
||||
}
|
||||
|
||||
@@ -34,6 +34,8 @@ namespace BetterLyrics.WinUI3.Models.Settings
|
||||
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial FullyObservableCollection<LocalMediaFolder> LocalMediaFolders { get; set; } = [];
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial FullyObservableCollection<MediaSourceProviderInfo> MediaSourceProvidersInfo { get; set; } = [];
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial FullyObservableCollection<MappedSongSearchQuery> MappedSongSearchQueries { get; set; } = [];
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial FullyObservableCollection<WindowBoundsRecord> WindowBoundsRecords { get; set; } = [];
|
||||
|
||||
public AppSettings() { }
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ namespace BetterLyrics.WinUI3.Models.Settings
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool AutoLockOnDesktopMode { get; set; } = false;
|
||||
[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" };
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsAlwaysOnTop { get; set; } = true;
|
||||
|
||||
public DesktopModeSettings()
|
||||
{
|
||||
|
||||
@@ -15,6 +15,7 @@ namespace BetterLyrics.WinUI3.Models.Settings
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IgnoreFullscreenWindow { get; set; } = false;
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial string LXMusicServer { get; set; } = string.Empty;
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool HideWindowWhenNotPlaying { get; set; } = true;
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial List<string> ShowOrHideLyricsWindowShortcut { get; set; } = new List<string> { "Ctrl", "Alt", "H" };
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsDragEverywhereEnabled { get; set; } = false;
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsImmersiveMode { get; set; } = false;
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool ExitOnLyricsWindowClosed { get; set; } = true;
|
||||
|
||||
@@ -13,6 +13,7 @@ namespace BetterLyrics.WinUI3.Models.Settings
|
||||
{
|
||||
public partial class LyricsStyleSettings : ObservableRecipient
|
||||
{
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsDynamicLyricsFontSize { get; set; } = false;
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial int LyricsFontSize { get; set; }
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial TextAlignmentType LyricsAlignmentType { get; set; }
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial int LyricsBgFontOpacity { get; set; } = 30; // 30% opacity
|
||||
|
||||
@@ -14,6 +14,7 @@ namespace BetterLyrics.WinUI3.Models.Settings
|
||||
{
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial Rect WindowBounds { get; set; } = new Rect(100, 100, 1000, 600);
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsMaximized { get; set; } = false;
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsAlwaysOnTop { get; set; } = false;
|
||||
|
||||
public StandardModeSettings()
|
||||
{
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using BetterLyrics.WinUI3.Services;
|
||||
using BetterLyrics.WinUI3.Enums;
|
||||
using BetterLyrics.WinUI3.Services;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@@ -15,6 +16,11 @@ namespace BetterLyrics.WinUI3.Models.Settings
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsTranslationEnabled { get; set; } = true;
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool ShowTranslationOnly { get; set; } = false;
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial int SelectedTargetLanguageIndex { get; set; } = LanguageHelper.GetDefaultTargetLanguageIndex();
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsJyutpingEnabled { get; set; } = false;
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial ChineseRomanization ChineseRomanization { get; set; }
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsChineseRomanizationEnabled { get; set; } = false;
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsJapaneseRomanizationEnabled { get; set; } = false;
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsTraditionalChineseEnabled { get; set; } = false;
|
||||
|
||||
public TranslationSettings() { }
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
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
|
||||
{
|
||||
public partial class WindowBoundsRecord : ObservableObject
|
||||
{
|
||||
[ObservableProperty] public partial string MonitorDeviceName { get; set; } = string.Empty;
|
||||
[ObservableProperty] public partial Rect WindowBounds { get; set; }
|
||||
[ObservableProperty] public partial Rect DemoWindowBounds { get; set; }
|
||||
[ObservableProperty] public partial Rect MonitorBounds { get; set; }
|
||||
[ObservableProperty] public partial Rect DemoMonitorBounds { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -12,6 +12,7 @@ using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Text.Json;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Services.AlbumArtSearchService
|
||||
@@ -30,12 +31,7 @@ namespace BetterLyrics.WinUI3.Services.AlbumArtSearchService
|
||||
_iTunesHttpClinet = new();
|
||||
}
|
||||
|
||||
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)
|
||||
public async Task<byte[]?> SearchAsync(string mediaSessionId, string title, string artist, string album, byte[]? bytesFromSMTC, CancellationToken token)
|
||||
{
|
||||
byte[]? result = null;
|
||||
|
||||
@@ -60,6 +56,7 @@ namespace BetterLyrics.WinUI3.Services.AlbumArtSearchService
|
||||
foreach (string countryCode in new List<string>() { "us", "cn", "jp", "kr" })
|
||||
{
|
||||
result = await SearchiTunesAsync(artist, album, title, countryCode);
|
||||
if (token.IsCancellationRequested) return result;
|
||||
if (result != null) break;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -2,12 +2,13 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Services.AlbumArtSearchService
|
||||
{
|
||||
public interface IAlbumArtSearchService
|
||||
{
|
||||
Task<byte[]?> SearchAsync(string mediaSessionId, string title, string artist, string album, byte[]? bytesFromSMTC = null);
|
||||
Task<byte[]?> SearchAsync(string mediaSessionId, string title, string artist, string album, byte[]? bytesFromSMTC, CancellationToken token);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,8 @@ namespace BetterLyrics.WinUI3.Services.LiveStatesService
|
||||
{
|
||||
public class LiveStatesService : BaseViewModel, ILiveStatesService,
|
||||
IRecipient<PropertyChangedMessage<LyricsWindowMode>>,
|
||||
IRecipient<PropertyChangedMessage<LyricsDisplayType>>
|
||||
IRecipient<PropertyChangedMessage<LyricsDisplayType>>,
|
||||
IRecipient<PropertyChangedMessage<bool>>
|
||||
{
|
||||
private readonly ISettingsService _settingsService;
|
||||
|
||||
@@ -32,29 +33,33 @@ namespace BetterLyrics.WinUI3.Services.LiveStatesService
|
||||
{
|
||||
if (message.Sender is LiveStates)
|
||||
{
|
||||
if (message.PropertyName == nameof(LiveStates.CurrentLyricsWindowMode))
|
||||
if (message.PropertyName == nameof(LiveStates.LyricsWindowMode))
|
||||
{
|
||||
switch (message.NewValue)
|
||||
{
|
||||
case LyricsWindowMode.StandardMode:
|
||||
LiveStates.CurrentLyricsStyleSettings = _settingsService.AppSettings.StandardLyricsStyleSettings;
|
||||
LiveStates.CurrentLyricsEffectSettings = _settingsService.AppSettings.StandardLyricsEffectSettings;
|
||||
LiveStates.CurrentLyricsDisplayType = _settingsService.AppSettings.StandardModeSettings.LyricsDisplayType;
|
||||
LiveStates.LyricsStyleSettings = _settingsService.AppSettings.StandardLyricsStyleSettings;
|
||||
LiveStates.LyricsEffectSettings = _settingsService.AppSettings.StandardLyricsEffectSettings;
|
||||
LiveStates.LyricsDisplayType = _settingsService.AppSettings.StandardModeSettings.LyricsDisplayType;
|
||||
LiveStates.IsAlwaysOnTop = _settingsService.AppSettings.StandardModeSettings.IsAlwaysOnTop;
|
||||
break;
|
||||
case LyricsWindowMode.DockMode:
|
||||
LiveStates.CurrentLyricsStyleSettings = _settingsService.AppSettings.DockLyricsStyleSettings;
|
||||
LiveStates.CurrentLyricsEffectSettings = _settingsService.AppSettings.DockLyricsEffectSettings;
|
||||
LiveStates.CurrentLyricsDisplayType = _settingsService.AppSettings.DockModeSettings.LyricsDisplayType;
|
||||
LiveStates.LyricsStyleSettings = _settingsService.AppSettings.DockLyricsStyleSettings;
|
||||
LiveStates.LyricsEffectSettings = _settingsService.AppSettings.DockLyricsEffectSettings;
|
||||
LiveStates.LyricsDisplayType = _settingsService.AppSettings.DockModeSettings.LyricsDisplayType;
|
||||
LiveStates.IsAlwaysOnTop = true;
|
||||
break;
|
||||
case LyricsWindowMode.DesktopMode:
|
||||
LiveStates.CurrentLyricsStyleSettings = _settingsService.AppSettings.DesktopLyricsStyleSettings;
|
||||
LiveStates.CurrentLyricsEffectSettings = _settingsService.AppSettings.DesktopLyricsEffectSettings;
|
||||
LiveStates.CurrentLyricsDisplayType = _settingsService.AppSettings.DesktopModeSettings.LyricsDisplayType;
|
||||
LiveStates.LyricsStyleSettings = _settingsService.AppSettings.DesktopLyricsStyleSettings;
|
||||
LiveStates.LyricsEffectSettings = _settingsService.AppSettings.DesktopLyricsEffectSettings;
|
||||
LiveStates.LyricsDisplayType = _settingsService.AppSettings.DesktopModeSettings.LyricsDisplayType;
|
||||
LiveStates.IsAlwaysOnTop = _settingsService.AppSettings.DesktopModeSettings.IsAlwaysOnTop;
|
||||
break;
|
||||
case LyricsWindowMode.PictureInPictureMode:
|
||||
LiveStates.CurrentLyricsStyleSettings = _settingsService.AppSettings.PictureInPictureLyricsStyleSettings;
|
||||
LiveStates.CurrentLyricsEffectSettings = _settingsService.AppSettings.PictureInPictureLyricsEffectSettings;
|
||||
LiveStates.CurrentLyricsDisplayType = _settingsService.AppSettings.PictureInPictureModeSettings.LyricsDisplayType;
|
||||
LiveStates.LyricsStyleSettings = _settingsService.AppSettings.PictureInPictureLyricsStyleSettings;
|
||||
LiveStates.LyricsEffectSettings = _settingsService.AppSettings.PictureInPictureLyricsEffectSettings;
|
||||
LiveStates.LyricsDisplayType = _settingsService.AppSettings.PictureInPictureModeSettings.LyricsDisplayType;
|
||||
// IsAlwaysOnTop 由系统托管
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -69,9 +74,9 @@ namespace BetterLyrics.WinUI3.Services.LiveStatesService
|
||||
{
|
||||
if (message.PropertyName == nameof(StandardModeSettings.LyricsDisplayType))
|
||||
{
|
||||
if (LiveStates.CurrentLyricsWindowMode == LyricsWindowMode.StandardMode)
|
||||
if (LiveStates.LyricsWindowMode == LyricsWindowMode.StandardMode)
|
||||
{
|
||||
LiveStates.CurrentLyricsDisplayType = message.NewValue;
|
||||
LiveStates.LyricsDisplayType = message.NewValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -79,9 +84,9 @@ namespace BetterLyrics.WinUI3.Services.LiveStatesService
|
||||
{
|
||||
if (message.PropertyName == nameof(DockModeSettings.LyricsDisplayType))
|
||||
{
|
||||
if (LiveStates.CurrentLyricsWindowMode == LyricsWindowMode.DockMode)
|
||||
if (LiveStates.LyricsWindowMode == LyricsWindowMode.DockMode)
|
||||
{
|
||||
LiveStates.CurrentLyricsDisplayType = message.NewValue;
|
||||
LiveStates.LyricsDisplayType = message.NewValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -89,9 +94,9 @@ namespace BetterLyrics.WinUI3.Services.LiveStatesService
|
||||
{
|
||||
if (message.PropertyName == nameof(DesktopModeSettings.LyricsDisplayType))
|
||||
{
|
||||
if (LiveStates.CurrentLyricsWindowMode == LyricsWindowMode.DesktopMode)
|
||||
if (LiveStates.LyricsWindowMode == LyricsWindowMode.DesktopMode)
|
||||
{
|
||||
LiveStates.CurrentLyricsDisplayType = message.NewValue;
|
||||
LiveStates.LyricsDisplayType = message.NewValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -99,9 +104,33 @@ namespace BetterLyrics.WinUI3.Services.LiveStatesService
|
||||
{
|
||||
if (message.PropertyName == nameof(PictureInPictureModeSettings.LyricsDisplayType))
|
||||
{
|
||||
if (LiveStates.CurrentLyricsWindowMode == LyricsWindowMode.PictureInPictureMode)
|
||||
if (LiveStates.LyricsWindowMode == LyricsWindowMode.PictureInPictureMode)
|
||||
{
|
||||
LiveStates.CurrentLyricsDisplayType = message.NewValue;
|
||||
LiveStates.LyricsDisplayType = message.NewValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Receive(PropertyChangedMessage<bool> message)
|
||||
{
|
||||
if (message.Sender is StandardModeSettings)
|
||||
{
|
||||
if (message.PropertyName == nameof(StandardModeSettings.IsAlwaysOnTop))
|
||||
{
|
||||
if (LiveStates.LyricsWindowMode == LyricsWindowMode.StandardMode)
|
||||
{
|
||||
LiveStates.IsAlwaysOnTop = message.NewValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (message.Sender is DesktopModeSettings)
|
||||
{
|
||||
if (message.PropertyName == nameof(DesktopModeSettings.IsAlwaysOnTop))
|
||||
{
|
||||
if (LiveStates.LyricsWindowMode == LyricsWindowMode.DesktopMode)
|
||||
{
|
||||
LiveStates.IsAlwaysOnTop = message.NewValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,18 @@
|
||||
// 2025/6/23 by Zhe Fang
|
||||
|
||||
using BetterLyrics.WinUI3.Enums;
|
||||
using BetterLyrics.WinUI3.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using BetterLyrics.WinUI3.Enums;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Services.LyricsSearchService
|
||||
{
|
||||
public interface ILyricsSearchService
|
||||
{
|
||||
Task<(string?, LyricsSearchProvider?)> SearchAsync(string mediaSessionId, string title, string artist, string album, double durationMs, CancellationToken token);
|
||||
Task<LyricsSearchResult> SearchSmartlyAsync(string mediaSessionId, string title, string artist, string album, double durationMs, CancellationToken token);
|
||||
|
||||
Task<List<LyricsSearchResult>> SearchAllAsync(string title, string artist, string album, double durationMs, CancellationToken token);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ using ATL;
|
||||
using BetterLyrics.WinUI3.Enums;
|
||||
using BetterLyrics.WinUI3.Helper;
|
||||
using BetterLyrics.WinUI3.Helper.BetterLyrics.WinUI3.Helper;
|
||||
using BetterLyrics.WinUI3.Models;
|
||||
using BetterLyrics.WinUI3.Services.SettingsService;
|
||||
using CommunityToolkit.Mvvm.DependencyInjection;
|
||||
using Lyricify.Lyrics.Providers.Web.Kugou;
|
||||
@@ -11,6 +12,7 @@ using Lyricify.Lyrics.Searchers;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using NTextCat.Commons;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
@@ -38,7 +40,7 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
|
||||
_lrcLibHttpClient = new();
|
||||
_lrcLibHttpClient.DefaultRequestHeaders.Add(
|
||||
"User-Agent",
|
||||
$"{Constants.App.AppName} {MetadataHelper.AppVersion} ({Constants.Link.GithubUrl})"
|
||||
$"{Constants.App.AppName} {MetadataHelper.AppVersion} ({Constants.Link.GitHubUrl})"
|
||||
);
|
||||
_amllTtmlDbHttpClient = new();
|
||||
}
|
||||
@@ -87,94 +89,158 @@ 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<LyricsSearchResult> SearchSmartlyAsync(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);
|
||||
var lyricsSearchResult = new LyricsSearchResult();
|
||||
|
||||
string overridenTitle = title;
|
||||
string overridenArtist = artist;
|
||||
|
||||
_logger.LogInformation("Searching img for: {Title} - {Artist} (Album: {Album}, Duration: {DurationMs}ms)", title, artist, album, durationMs);
|
||||
|
||||
var found = _settingsService.AppSettings.MappedSongSearchQueries
|
||||
.Where(x => x.OriginalTitle == title && x.OriginalArtist == artist)
|
||||
.FirstOrDefault();
|
||||
|
||||
if (found != null)
|
||||
{
|
||||
overridenTitle = found.MappedTitle;
|
||||
overridenArtist = found.MappedArtist;
|
||||
|
||||
_logger.LogInformation("Found mapped song search query: {MappedSongSearchQuery}", found);
|
||||
|
||||
var pureMusic = found.IsMarkedAsPureMusic;
|
||||
if (pureMusic)
|
||||
{
|
||||
lyricsSearchResult.Title = overridenTitle;
|
||||
lyricsSearchResult.Artist = overridenArtist;
|
||||
lyricsSearchResult.Raw = "[99:00.000]🎶🎶🎶";
|
||||
return lyricsSearchResult;
|
||||
}
|
||||
|
||||
var targetProvider = found.LyricsSearchProvider;
|
||||
if (targetProvider != null)
|
||||
{
|
||||
return await SearchSingleAsync(targetProvider.Value, overridenTitle, overridenArtist, album, durationMs, token);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var provider in _settingsService.AppSettings.MediaSourceProvidersInfo.Where(x => x.Provider == mediaSessionId).FirstOrDefault()?.LyricsSearchProvidersInfo ?? [])
|
||||
{
|
||||
if (!provider.IsEnabled)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
lyricsSearchResult = await SearchSingleAsync(provider.Provider, overridenTitle, overridenArtist, album, durationMs, token);
|
||||
|
||||
if (lyricsSearchResult.IsFound)
|
||||
{
|
||||
return lyricsSearchResult;
|
||||
}
|
||||
}
|
||||
|
||||
return lyricsSearchResult;
|
||||
}
|
||||
|
||||
private async Task<(string?, LyricsSearchProvider?)> SearchAsyncCore(string mediaSessionId, string title, string artist, string album, double durationMs, CancellationToken token)
|
||||
public async Task<List<LyricsSearchResult>> SearchAllAsync(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 all lyrics for: {Title} - {Artist} (Album: {Album}, Duration: {DurationMs}ms)", title, artist, album, durationMs);
|
||||
var results = new List<LyricsSearchResult>();
|
||||
foreach (var provider in Enum.GetValues<LyricsSearchProvider>())
|
||||
{
|
||||
var searchResult = await SearchSingleAsync(provider, title, artist, album, durationMs, token);
|
||||
results.Add(searchResult);
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
private async Task<LyricsSearchResult> SearchSingleAsync(LyricsSearchProvider provider, string title, string artist, string album, double durationMs, CancellationToken token)
|
||||
{
|
||||
var lyricsSearchResult = new LyricsSearchResult
|
||||
{
|
||||
Provider = provider,
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
foreach (var provider in _settingsService.AppSettings.MediaSourceProvidersInfo.Where(x => x.Provider == mediaSessionId).FirstOrDefault()?.LyricsSearchProvidersInfo ?? [])
|
||||
LyricsFormat lyricsFormat = provider.GetLyricsFormat();
|
||||
|
||||
// Check cache first
|
||||
if (provider.IsRemote())
|
||||
{
|
||||
if (!provider.IsEnabled)
|
||||
var cachedLyrics = FileHelper.ReadLyricsCache(title, artist, lyricsFormat, provider.GetCacheDirectory());
|
||||
if (!string.IsNullOrWhiteSpace(cachedLyrics))
|
||||
{
|
||||
continue;
|
||||
lyricsSearchResult.Raw = cachedLyrics;
|
||||
lyricsSearchResult.Title = title;
|
||||
lyricsSearchResult.Artist = artist;
|
||||
return lyricsSearchResult;
|
||||
}
|
||||
}
|
||||
|
||||
string? cachedLyrics;
|
||||
LyricsFormat lyricsFormat = provider.Provider.GetLyricsFormat();
|
||||
|
||||
// Check cache first
|
||||
if (provider.Provider.IsRemote())
|
||||
if (provider.IsLocal())
|
||||
{
|
||||
if (provider == LyricsSearchProvider.LocalMusicFile)
|
||||
{
|
||||
cachedLyrics = FileHelper.ReadLyricsCache(title, artist, lyricsFormat, provider.Provider.GetCacheDirectory());
|
||||
if (!string.IsNullOrWhiteSpace(cachedLyrics))
|
||||
{
|
||||
return (cachedLyrics, provider.Provider);
|
||||
}
|
||||
}
|
||||
|
||||
string? searchedLyrics = null;
|
||||
|
||||
if (provider.Provider.IsLocal())
|
||||
{
|
||||
if (provider.Provider == LyricsSearchProvider.LocalMusicFile)
|
||||
{
|
||||
searchedLyrics = SearchEmbedded(title, artist);
|
||||
}
|
||||
else
|
||||
{
|
||||
searchedLyrics = await SearchFile(title, artist, lyricsFormat);
|
||||
}
|
||||
lyricsSearchResult = SearchEmbedded(title, artist);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (provider.Provider)
|
||||
{
|
||||
case LyricsSearchProvider.LrcLib:
|
||||
searchedLyrics = await SearchLrcLibAsync(title, artist, album, (int)(durationMs / 1000));
|
||||
break;
|
||||
case LyricsSearchProvider.QQ:
|
||||
searchedLyrics = await SearchQQNeteaseKugouAsync(title, artist, album, (int)durationMs, Searchers.QQMusic);
|
||||
break;
|
||||
case LyricsSearchProvider.Kugou:
|
||||
searchedLyrics = await SearchQQNeteaseKugouAsync(title, artist, album, (int)durationMs, Searchers.Kugou);
|
||||
break;
|
||||
case LyricsSearchProvider.Netease:
|
||||
searchedLyrics = await SearchQQNeteaseKugouAsync(title, artist, album, (int)durationMs, Searchers.Netease);
|
||||
break;
|
||||
case LyricsSearchProvider.AmllTtmlDb:
|
||||
searchedLyrics = await SearchAmllTtmlDbAsync(title, artist);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
lyricsSearchResult = await SearchFile(title, artist, lyricsFormat);
|
||||
}
|
||||
|
||||
token.ThrowIfCancellationRequested();
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(searchedLyrics))
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (provider)
|
||||
{
|
||||
if (provider.Provider.IsRemote())
|
||||
{
|
||||
FileHelper.WriteLyricsCache(title, artist, searchedLyrics, lyricsFormat, provider.Provider.GetCacheDirectory());
|
||||
}
|
||||
case LyricsSearchProvider.LrcLib:
|
||||
lyricsSearchResult = await SearchLrcLibAsync(title, artist, album, (int)(durationMs / 1000));
|
||||
break;
|
||||
case LyricsSearchProvider.QQ:
|
||||
lyricsSearchResult = await SearchQQNeteaseKugouAsync(title, artist, album, (int)durationMs, Searchers.QQMusic);
|
||||
break;
|
||||
case LyricsSearchProvider.Kugou:
|
||||
lyricsSearchResult = await SearchQQNeteaseKugouAsync(title, artist, album, (int)durationMs, Searchers.Kugou);
|
||||
break;
|
||||
case LyricsSearchProvider.Netease:
|
||||
lyricsSearchResult = await SearchQQNeteaseKugouAsync(title, artist, album, (int)durationMs, Searchers.Netease);
|
||||
break;
|
||||
case LyricsSearchProvider.AmllTtmlDb:
|
||||
lyricsSearchResult = await SearchAmllTtmlDbAsync(title, artist);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return (searchedLyrics, provider.Provider);
|
||||
if (token.IsCancellationRequested)
|
||||
{
|
||||
return lyricsSearchResult;
|
||||
}
|
||||
|
||||
if (lyricsSearchResult.IsFound)
|
||||
{
|
||||
if (provider.IsRemote())
|
||||
{
|
||||
FileHelper.WriteLyricsCache(title, artist, lyricsSearchResult.Raw!, lyricsFormat, provider.GetCacheDirectory());
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception) { }
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
|
||||
return (null, null);
|
||||
return lyricsSearchResult;
|
||||
}
|
||||
|
||||
private async Task<string?> SearchFile(string title, string artist, LyricsFormat format)
|
||||
private async Task<LyricsSearchResult> SearchFile(string title, string artist, LyricsFormat format)
|
||||
{
|
||||
var lyricsSearchResult = new LyricsSearchResult
|
||||
{
|
||||
Provider = format.ToLyricsSearchProvider(),
|
||||
};
|
||||
|
||||
foreach (var folder in _settingsService.AppSettings.LocalMediaFolders)
|
||||
{
|
||||
if (Directory.Exists(folder.Path) && folder.IsEnabled)
|
||||
@@ -188,7 +254,9 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
|
||||
string? raw = await File.ReadAllTextAsync(file, FileHelper.GetEncoding(file));
|
||||
if (raw != null)
|
||||
{
|
||||
return raw;
|
||||
lyricsSearchResult.Raw = raw;
|
||||
lyricsSearchResult.Title = title;
|
||||
lyricsSearchResult.Artist = artist;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -198,11 +266,16 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
return lyricsSearchResult;
|
||||
}
|
||||
|
||||
private string? SearchEmbedded(string title, string artist)
|
||||
private LyricsSearchResult SearchEmbedded(string title, string artist)
|
||||
{
|
||||
var lyricsSearchResult = new LyricsSearchResult
|
||||
{
|
||||
Provider = LyricsSearchProvider.LocalMusicFile,
|
||||
};
|
||||
|
||||
foreach (var folder in _settingsService.AppSettings.LocalMediaFolders)
|
||||
{
|
||||
if (Directory.Exists(folder.Path) && folder.IsEnabled)
|
||||
@@ -217,23 +290,32 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
|
||||
var plain = TagLib.File.Create(file).Tag.Lyrics;
|
||||
if (!plain.IsNullOrEmpty())
|
||||
{
|
||||
return plain;
|
||||
lyricsSearchResult.Raw = plain;
|
||||
lyricsSearchResult.Title = track.Title;
|
||||
lyricsSearchResult.Artist = artist;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
return lyricsSearchResult;
|
||||
}
|
||||
|
||||
private async Task<string?> SearchAmllTtmlDbAsync(string title, string artist)
|
||||
private async Task<LyricsSearchResult> SearchAmllTtmlDbAsync(string title, string artist)
|
||||
{
|
||||
var lyricsSearchResult = new LyricsSearchResult
|
||||
{
|
||||
Provider = LyricsSearchProvider.AmllTtmlDb,
|
||||
};
|
||||
|
||||
if (IsAmllTtmlDbIndexInvalid())
|
||||
{
|
||||
var downloadOk = await DownloadAmllTtmlDbIndexAsync();
|
||||
if (!downloadOk)
|
||||
return null;
|
||||
{
|
||||
return lyricsSearchResult;
|
||||
}
|
||||
}
|
||||
|
||||
string? rawLyricFile = null;
|
||||
@@ -276,7 +358,9 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(rawLyricFile))
|
||||
return null;
|
||||
{
|
||||
return lyricsSearchResult;
|
||||
}
|
||||
|
||||
// 下载歌词内容
|
||||
var url = $"{Constants.AmllTTmlDB.QueryPrefix}{rawLyricFile}";
|
||||
@@ -284,17 +368,29 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
|
||||
{
|
||||
using var response = await _amllTtmlDbHttpClient.GetAsync(url);
|
||||
if (!response.IsSuccessStatusCode)
|
||||
return null;
|
||||
return await response.Content.ReadAsStringAsync();
|
||||
{
|
||||
return lyricsSearchResult;
|
||||
}
|
||||
string lyrics = await response.Content.ReadAsStringAsync();
|
||||
|
||||
lyricsSearchResult.Raw = lyrics;
|
||||
lyricsSearchResult.Title = title;
|
||||
lyricsSearchResult.Artist = artist;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return lyricsSearchResult;
|
||||
}
|
||||
|
||||
private async Task<string?> SearchLrcLibAsync(string title, string artist, string album, int duration)
|
||||
private async Task<LyricsSearchResult> SearchLrcLibAsync(string title, string artist, string album, int duration)
|
||||
{
|
||||
var lyricsSearchResult = new LyricsSearchResult
|
||||
{
|
||||
Provider = LyricsSearchProvider.LrcLib,
|
||||
};
|
||||
|
||||
// Build API query URL
|
||||
var url =
|
||||
$"https://lrclib.net/api/search?" +
|
||||
@@ -305,7 +401,9 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
|
||||
|
||||
using var response = await _lrcLibHttpClient.GetAsync(url);
|
||||
if (!response.IsSuccessStatusCode)
|
||||
return null;
|
||||
{
|
||||
return lyricsSearchResult;
|
||||
}
|
||||
|
||||
var json = await response.Content.ReadAsStringAsync();
|
||||
|
||||
@@ -313,22 +411,47 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
|
||||
json,
|
||||
Serialization.SourceGenerationContext.Default.JsonElement
|
||||
);
|
||||
|
||||
string? original = null;
|
||||
string? searchedTitle = null;
|
||||
string? searchedArtist = null;
|
||||
|
||||
if (jArr.ValueKind == JsonValueKind.Array && jArr.GetArrayLength() > 0)
|
||||
{
|
||||
var first = jArr[0];
|
||||
var syncedLyrics = first.GetProperty("syncedLyrics").GetString();
|
||||
var result = string.IsNullOrWhiteSpace(syncedLyrics) ? null : syncedLyrics;
|
||||
if (!string.IsNullOrWhiteSpace(result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
original = first.GetProperty("syncedLyrics").GetString();
|
||||
searchedTitle = first.GetProperty("trackName").GetString();
|
||||
searchedArtist = first.GetProperty("artistName").GetString();
|
||||
}
|
||||
|
||||
return null;
|
||||
lyricsSearchResult.Raw = original;
|
||||
lyricsSearchResult.Title = searchedTitle;
|
||||
lyricsSearchResult.Artist = searchedArtist;
|
||||
|
||||
return lyricsSearchResult;
|
||||
}
|
||||
|
||||
private static async Task<string?> SearchQQNeteaseKugouAsync(string title, string artist, string album, int durationMs, Searchers searchers)
|
||||
private static async Task<LyricsSearchResult> SearchQQNeteaseKugouAsync(string title, string artist, string album, int durationMs, Searchers searchers)
|
||||
{
|
||||
var lyricsSearchResult = new LyricsSearchResult();
|
||||
|
||||
switch (searchers)
|
||||
{
|
||||
case Searchers.QQMusic:
|
||||
lyricsSearchResult.Provider = LyricsSearchProvider.QQ;
|
||||
break;
|
||||
case Searchers.Netease:
|
||||
lyricsSearchResult.Provider = LyricsSearchProvider.Netease;
|
||||
break;
|
||||
case Searchers.Kugou:
|
||||
lyricsSearchResult.Provider = LyricsSearchProvider.Kugou;
|
||||
break;
|
||||
case Searchers.Musixmatch:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
var result = await SearchersHelper.GetSearcher(searchers).SearchForResult(
|
||||
new Lyricify.Lyrics.Models.TrackMultiArtistMetadata()
|
||||
{
|
||||
@@ -354,11 +477,15 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
|
||||
PathHelper.QQTranslationCacheDirectory
|
||||
);
|
||||
}
|
||||
return original;
|
||||
|
||||
lyricsSearchResult.Raw = original;
|
||||
lyricsSearchResult.Title = qqResult.Title;
|
||||
lyricsSearchResult.Artist = qqResult.Artists.Join(" | ");
|
||||
}
|
||||
else if (result is NeteaseSearchResult neteaseResult)
|
||||
{
|
||||
var response = await Lyricify.Lyrics.Helpers.ProviderHelper.NeteaseApi.GetLyric(neteaseResult.Id);
|
||||
var original = response?.Lrc?.Lyric;
|
||||
var translated = response?.Tlyric?.Lyric;
|
||||
if (!string.IsNullOrEmpty(translated))
|
||||
{
|
||||
@@ -370,21 +497,26 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
|
||||
PathHelper.NeteaseTranslationCacheDirectory
|
||||
);
|
||||
}
|
||||
return response?.Lrc.Lyric;
|
||||
|
||||
lyricsSearchResult.Raw = original;
|
||||
lyricsSearchResult.Title = neteaseResult.Title;
|
||||
lyricsSearchResult.Artist = neteaseResult.Artists.Join(" | ");
|
||||
}
|
||||
else if (result is KugouSearchResult kugouResult)
|
||||
{
|
||||
var response = await Lyricify.Lyrics.Helpers.ProviderHelper.KugouApi.GetSearchLyrics(hash: kugouResult.Hash);
|
||||
string? original = null;
|
||||
if (response?.Candidates.FirstOrDefault() is SearchLyricsResponse.Candidate candidate)
|
||||
{
|
||||
return Lyricify.Lyrics.Decrypter.Krc.Helper.GetLyrics(
|
||||
candidate.Id,
|
||||
candidate.AccessKey
|
||||
);
|
||||
original = Lyricify.Lyrics.Decrypter.Krc.Helper.GetLyrics(candidate.Id, candidate.AccessKey);
|
||||
}
|
||||
|
||||
lyricsSearchResult.Raw = original;
|
||||
lyricsSearchResult.Title = kugouResult.Title;
|
||||
lyricsSearchResult.Artist = kugouResult.Artists.Join(" | ");
|
||||
}
|
||||
|
||||
return null;
|
||||
return lyricsSearchResult;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
bool IsPlaying { get; }
|
||||
SongInfo? SongInfo { get; }
|
||||
TimeSpan Position { get; }
|
||||
LyricsData? CurrentLyricsData { get; }
|
||||
|
||||
LyricsSearchProvider? LyricsSearchProvider { get; }
|
||||
TranslationSearchProvider? TranslationSearchProvider { get; }
|
||||
|
||||
@@ -33,14 +33,15 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
return;
|
||||
}
|
||||
|
||||
byte[]? bytes = await _albumArtSearchService.SearchAsync(
|
||||
byte[]? bytes = await Task.Run(async () => await _albumArtSearchService.SearchAsync(
|
||||
SongInfo?.SourceAppUserModelId ?? "",
|
||||
_cachedSongInfo.Title,
|
||||
_cachedSongInfo.Artist,
|
||||
_cachedSongInfo?.Album ?? string.Empty,
|
||||
_SMTCAlbumArtBytes
|
||||
);
|
||||
token.ThrowIfCancellationRequested();
|
||||
_SMTCAlbumArtBytes,
|
||||
token
|
||||
), token);
|
||||
if (token.IsCancellationRequested) return;
|
||||
|
||||
if (bytes == null)
|
||||
{
|
||||
@@ -57,7 +58,8 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
var decoder = await BitmapDecoder.CreateAsync(stream);
|
||||
token.ThrowIfCancellationRequested();
|
||||
|
||||
var albumArtSwBitmap = await decoder.GetSoftwareBitmapAsync(BitmapPixelFormat.Rgba16, BitmapAlphaMode.Premultiplied);
|
||||
var albumArtSwBitmap = await decoder.GetSoftwareBitmapAsync(BitmapPixelFormat.Rgba8, BitmapAlphaMode.Premultiplied);
|
||||
albumArtSwBitmap = SoftwareBitmap.Copy(albumArtSwBitmap);
|
||||
token.ThrowIfCancellationRequested();
|
||||
|
||||
var albumArtLightAccentColor = ImageHelper.GetAccentColorsFromByte(bytes, 1, false).FirstOrDefault();
|
||||
|
||||
@@ -3,6 +3,7 @@ using BetterLyrics.WinUI3.Events;
|
||||
using BetterLyrics.WinUI3.Helper;
|
||||
using BetterLyrics.WinUI3.Models;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Lyricify.Lyrics.Helpers.General;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@@ -17,12 +18,12 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
public partial class MediaSessionsService : IMediaSessionsService
|
||||
{
|
||||
private LatestOnlyTaskRunner _refreshLyricsRunner = new();
|
||||
private LatestOnlyTaskRunner _showTranslationsRunner = new();
|
||||
private LatestOnlyTaskRunner _refreshTranslationRunner = new();
|
||||
|
||||
private int _langIndex = 0;
|
||||
private List<LyricsData> _lyricsDataArr = [];
|
||||
|
||||
private LyricsData? CurrentLyricsData => _lyricsDataArr.ElementAtOrDefault(_langIndex);
|
||||
public LyricsData? CurrentLyricsData => _lyricsDataArr.ElementAtOrDefault(_langIndex);
|
||||
|
||||
public event EventHandler<LyricsChangedEventArgs>? LyricsChanged;
|
||||
|
||||
@@ -32,7 +33,7 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
|
||||
[ObservableProperty] public partial bool IsTranslating { get; set; } = false;
|
||||
|
||||
private void UpdateTranslations()
|
||||
private async Task RefreshTranslationAsync(CancellationToken token)
|
||||
{
|
||||
TranslationSearchProvider = null;
|
||||
_lyricsDataArr.ElementAtOrDefault(0)?.SetDisplayedTextInOriginalText();
|
||||
@@ -41,20 +42,17 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
|
||||
if (_settingsService.AppSettings.TranslationSettings.IsTranslationEnabled)
|
||||
{
|
||||
_showTranslationsRunner.RunAsync(async token =>
|
||||
{
|
||||
await SetDisplayedAlongWithTranslationsAsync(token);
|
||||
IsTranslating = false;
|
||||
LyricsChanged?.Invoke(this, new LyricsChangedEventArgs(CurrentLyricsData));
|
||||
});
|
||||
await SetDisplayedAlongWithTranslationsAsync(token);
|
||||
if (token.IsCancellationRequested) return;
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogInformation("Translation is disabled, showing original lyrics only.");
|
||||
_lyricsDataArr.ElementAtOrDefault(0)?.SetDisplayedTextInOriginalText();
|
||||
_langIndex = 0;
|
||||
IsTranslating = false;
|
||||
LyricsChanged?.Invoke(this, new LyricsChangedEventArgs(CurrentLyricsData));
|
||||
}
|
||||
IsTranslating = false;
|
||||
LyricsChanged?.Invoke(this, new LyricsChangedEventArgs(CurrentLyricsData));
|
||||
}
|
||||
|
||||
private async Task SetDisplayedAlongWithTranslationsAsync(CancellationToken token)
|
||||
@@ -68,6 +66,25 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
string? originalLangCode = LanguageHelper.DetectLanguageCode(originalText);
|
||||
_logger.LogInformation("Original language code: {OriginalLangCode}", originalLangCode ?? "null");
|
||||
|
||||
if (originalLangCode == "zh" && _settingsService.AppSettings.TranslationSettings.IsChineseRomanizationEnabled)
|
||||
{
|
||||
switch (_settingsService.AppSettings.TranslationSettings.ChineseRomanization)
|
||||
{
|
||||
case ChineseRomanization.Pinyin:
|
||||
targetLangCode = "pinyin";
|
||||
break;
|
||||
case ChineseRomanization.Jyutping:
|
||||
targetLangCode = "jyutping";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (originalLangCode == "ja" && _settingsService.AppSettings.TranslationSettings.IsJapaneseRomanizationEnabled)
|
||||
{
|
||||
targetLangCode = "romaji";
|
||||
}
|
||||
|
||||
if (originalLangCode == targetLangCode)
|
||||
{
|
||||
_logger.LogInformation("Original lyrics already in target language: {TargetLangCode}", targetLangCode);
|
||||
@@ -77,7 +94,7 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
else
|
||||
{
|
||||
// Try get translation from itself first
|
||||
int found = _translateService.SearchTranslatedLyricsItself(_lyricsDataArr);
|
||||
int found = _translateService.SearchTranslatedLyricsItself(_lyricsDataArr, targetLangCode);
|
||||
if (found >= 0)
|
||||
{
|
||||
_logger.LogInformation("Found translation in lyrics data at index {FoundIndex}", found);
|
||||
@@ -88,7 +105,7 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
}
|
||||
else
|
||||
{
|
||||
_lyricsDataArr[0].SetDisplayedTextAlongWith(_lyricsDataArr[found], _liveStatesService.LiveStates.CurrentLyricsStyleSettings.LyricsTranslationSeparator, 50);
|
||||
_lyricsDataArr[0].SetDisplayedTextAlongWith(_lyricsDataArr[found], _liveStatesService.LiveStates.LyricsStyleSettings.LyricsTranslationSeparator, 50);
|
||||
_langIndex = 0;
|
||||
TranslationSearchProvider = LyricsSearchProvider.ToTranslationSearchProvider();
|
||||
}
|
||||
@@ -111,7 +128,7 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
}
|
||||
else
|
||||
{
|
||||
_lyricsDataArr[0].SetDisplayedTextAlongWith(translated, _liveStatesService.LiveStates.CurrentLyricsStyleSettings.LyricsTranslationSeparator);
|
||||
_lyricsDataArr[0].SetDisplayedTextAlongWith(translated, _liveStatesService.LiveStates.LyricsStyleSettings.LyricsTranslationSeparator);
|
||||
_langIndex = 0;
|
||||
}
|
||||
TranslationSearchProvider = Enums.TranslationSearchProvider.LibreTranslate;
|
||||
@@ -133,27 +150,26 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
|
||||
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(
|
||||
|
||||
var lyricsSearchResult = await Task.Run(async () => await _lyrcsSearchService.SearchSmartlyAsync(
|
||||
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();
|
||||
), token);
|
||||
if (token.IsCancellationRequested) return;
|
||||
LyricsSearchProvider = lyricsSearchResult?.Provider;
|
||||
|
||||
_lyricsDataArr = new LyricsParser().Parse(lyricsRaw, (int?)SongInfo?.DurationMs);
|
||||
_logger.LogInformation("Lyrics was found? {Found}, Provider: {LyricsSearchProvider}", lyricsSearchResult?.IsFound, LyricsSearchProvider?.ToString() ?? "null");
|
||||
|
||||
_lyricsDataArr = new LyricsParser().Parse(lyricsSearchResult?.Raw, (int?)SongInfo?.DurationMs);
|
||||
ApplyChinesePreference();
|
||||
FillTranslationFromCache(LyricsSearchProvider);
|
||||
}
|
||||
else
|
||||
@@ -166,22 +182,35 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
// This ensures that original lyrics are always shown while waiting for translations
|
||||
_lyricsDataArr[0].SetDisplayedTextInOriginalText();
|
||||
LyricsChanged?.Invoke(this, new LyricsChangedEventArgs(CurrentLyricsData));
|
||||
|
||||
ApplyChinesePreference();
|
||||
UpdateTranslations();
|
||||
}
|
||||
|
||||
private void ApplyChinesePreference()
|
||||
{
|
||||
var traditionalChinesePreferred = _settingsService.AppSettings.TranslationSettings.IsTraditionalChineseEnabled;
|
||||
var found = _lyricsDataArr.FindIndex(x => x.LanguageCode == "zh");
|
||||
if (found >= 0)
|
||||
{
|
||||
foreach (var item in _lyricsDataArr[found].LyricsLines)
|
||||
{
|
||||
item.OriginalText = traditionalChinesePreferred ? ChineseHelper.S2T(item.OriginalText) : ChineseHelper.T2S(item.OriginalText);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
translationRaw = FileHelper.ReadLyricsCache(SongInfo!.Title, SongInfo.Artist, LyricsFormat.Lrc, 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);
|
||||
translationRaw = FileHelper.ReadLyricsCache(SongInfo!.Title, SongInfo.Artist, LyricsFormat.Lrc, PathHelper.NeteaseTranslationCacheDirectory);
|
||||
break;
|
||||
case Enums.LyricsSearchProvider.LrcLib:
|
||||
break;
|
||||
@@ -223,5 +252,10 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
{
|
||||
_refreshLyricsRunner.RunAsync(RefreshLyricsAsync);
|
||||
}
|
||||
|
||||
private void UpdateTranslations()
|
||||
{
|
||||
_refreshTranslationRunner.RunAsync(RefreshTranslationAsync);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,6 +43,8 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
IRecipient<PropertyChangedMessage<int>>,
|
||||
IRecipient<PropertyChangedMessage<bool>>,
|
||||
IRecipient<PropertyChangedMessage<string>>,
|
||||
IRecipient<PropertyChangedMessage<LyricsWindowMode>>,
|
||||
IRecipient<PropertyChangedMessage<ChineseRomanization>>,
|
||||
IRecipient<PropertyChangedMessage<List<string>>>
|
||||
{
|
||||
private readonly IAlbumArtSearchService _albumArtSearchService;
|
||||
@@ -92,15 +94,29 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
_logger = Ioc.Default.GetRequiredService<ILogger<MediaSessionsService>>();
|
||||
|
||||
_settingsService.AppSettings.MediaSourceProvidersInfo.ItemPropertyChanged += MediaSourceProvidersInfo_ItemPropertyChanged;
|
||||
|
||||
_settingsService.AppSettings.LocalMediaFolders.CollectionChanged += LocalMediaFolders_CollectionChanged;
|
||||
_settingsService.AppSettings.LocalMediaFolders.ItemPropertyChanged += LocalMediaFolders_ItemPropertyChanged;
|
||||
|
||||
_settingsService.AppSettings.MappedSongSearchQueries.CollectionChanged += MappedSongSearchQueries_CollectionChanged;
|
||||
_settingsService.AppSettings.MappedSongSearchQueries.ItemPropertyChanged += MappedSongSearchQueries_ItemPropertyChanged;
|
||||
|
||||
_libWatcherService.MusicLibraryFilesChanged += LibWatcherService_MusicLibraryFilesChanged;
|
||||
|
||||
InitMediaManager();
|
||||
InitPlaybackShortcuts();
|
||||
}
|
||||
|
||||
private void MappedSongSearchQueries_ItemPropertyChanged(object? sender, ItemPropertyChangedEventArgs e)
|
||||
{
|
||||
UpdateLyrics();
|
||||
}
|
||||
|
||||
private void MappedSongSearchQueries_CollectionChanged(object? sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
UpdateLyrics();
|
||||
}
|
||||
|
||||
private void InitPlaybackShortcuts()
|
||||
{
|
||||
UpdatePlayOrPauseSongShortcut();
|
||||
@@ -172,11 +188,22 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
UpdateLyrics();
|
||||
}
|
||||
|
||||
public MediaSourceProviderInfo? GetCurrentMediaSourceProviderInfo()
|
||||
{
|
||||
var desiredSession = GetCurrentSession();
|
||||
return _settingsService.AppSettings.MediaSourceProvidersInfo.FirstOrDefault(x => x.Provider == desiredSession?.Id);
|
||||
}
|
||||
|
||||
private bool IsMediaSourceEnabled(string id)
|
||||
{
|
||||
return _settingsService.AppSettings.MediaSourceProvidersInfo.FirstOrDefault(s => s.Provider == id)?.IsEnabled ?? true;
|
||||
}
|
||||
|
||||
private bool IsMediaSourceTimelineSyncEnabled(string id)
|
||||
{
|
||||
return _settingsService.AppSettings.MediaSourceProvidersInfo.FirstOrDefault(s => s.Provider == id)?.IsTimelineSyncEnabled ?? true;
|
||||
}
|
||||
|
||||
private void InitMediaManager()
|
||||
{
|
||||
_mediaManager.OnAnySessionOpened += MediaManager_OnAnySessionOpened;
|
||||
@@ -204,9 +231,9 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
if (!_mediaManager.IsStarted) return;
|
||||
if (mediaSession == null) return;
|
||||
|
||||
var focusedSession = _mediaManager.GetFocusedSession();
|
||||
var desiredSession = GetCurrentSession();
|
||||
|
||||
if (mediaSession != focusedSession) return;
|
||||
if (mediaSession != desiredSession) return;
|
||||
|
||||
if (!IsMediaSourceEnabled(mediaSession.Id))
|
||||
{
|
||||
@@ -218,11 +245,14 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
}
|
||||
else
|
||||
{
|
||||
_cachedPosition = timelineProperties.Position;
|
||||
_dispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, () =>
|
||||
if (IsMediaSourceTimelineSyncEnabled(mediaSession.Id))
|
||||
{
|
||||
TimelineChanged?.Invoke(this, new TimelineChangedEventArgs(_cachedPosition, timelineProperties.EndTime));
|
||||
});
|
||||
_cachedPosition = timelineProperties.Position;
|
||||
_dispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, () =>
|
||||
{
|
||||
TimelineChanged?.Invoke(this, new TimelineChangedEventArgs(_cachedPosition, timelineProperties.EndTime));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -233,10 +263,10 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
if (!_mediaManager.IsStarted) return;
|
||||
if (mediaSession == null) return;
|
||||
|
||||
var focusedSession = _mediaManager.GetFocusedSession();
|
||||
var desiredSession = GetCurrentSession();
|
||||
|
||||
//RecordMediaSourceProviderInfo(mediaSession);
|
||||
if (mediaSession != focusedSession) return;
|
||||
if (mediaSession != desiredSession) return;
|
||||
|
||||
if (!IsMediaSourceEnabled(mediaSession.Id))
|
||||
{
|
||||
@@ -264,10 +294,10 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
|
||||
string id = mediaSession.Id;
|
||||
|
||||
var focusedSession = _mediaManager.GetFocusedSession();
|
||||
var desiredSession = GetCurrentSession();
|
||||
|
||||
//RecordMediaSourceProviderInfo(mediaSession);
|
||||
if (mediaSession != focusedSession) return;
|
||||
if (mediaSession != desiredSession) return;
|
||||
|
||||
if (!IsMediaSourceEnabled(id))
|
||||
{
|
||||
@@ -291,14 +321,31 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
currentMediaSourceProviderInfo?.PositionOffset = 0;
|
||||
}
|
||||
|
||||
_cachedSongInfo = new SongInfo
|
||||
if (id == Constants.PlayerID.AppleMusic || id == Constants.PlayerID.AppleMusicAlternative)
|
||||
{
|
||||
Title = mediaProperties.Title,
|
||||
Artist = mediaProperties.Artist,
|
||||
Album = mediaProperties.AlbumTitle,
|
||||
DurationMs = mediaSession.ControlSession.GetTimelineProperties().EndTime.TotalMilliseconds,
|
||||
SourceAppUserModelId = id,
|
||||
};
|
||||
string fixedArtist = mediaProperties.Artist.Split(" — ").FirstOrDefault() ?? mediaProperties.Artist;
|
||||
string fixedAlbum = mediaProperties.Artist.Split(" — ").LastOrDefault() ?? mediaProperties.AlbumTitle;
|
||||
|
||||
_cachedSongInfo = new SongInfo
|
||||
{
|
||||
Title = mediaProperties.Title,
|
||||
Artist = fixedArtist,
|
||||
Album = fixedAlbum,
|
||||
DurationMs = mediaSession.ControlSession.GetTimelineProperties().EndTime.TotalMilliseconds,
|
||||
SourceAppUserModelId = id,
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
_cachedSongInfo = new SongInfo
|
||||
{
|
||||
Title = mediaProperties.Title,
|
||||
Artist = mediaProperties.Artist,
|
||||
Album = mediaProperties.AlbumTitle,
|
||||
DurationMs = mediaSession.ControlSession.GetTimelineProperties().EndTime.TotalMilliseconds,
|
||||
SourceAppUserModelId = id,
|
||||
};
|
||||
}
|
||||
|
||||
_cachedSongInfo.Duration = (int)(_cachedSongInfo.DurationMs / 1000f);
|
||||
|
||||
@@ -350,6 +397,30 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
SendFocusedMessagesAsync().ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private MediaManager.MediaSession? GetCurrentSession()
|
||||
{
|
||||
var focusedSession = _mediaManager.GetFocusedSession();
|
||||
if (focusedSession == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (IsMediaSourceEnabled(focusedSession.Id))
|
||||
{
|
||||
return focusedSession;
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var session in _mediaManager.CurrentMediaSessions.Values)
|
||||
{
|
||||
if (IsMediaSourceEnabled(session.Id))
|
||||
{
|
||||
return session;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void RecordMediaSourceProviderInfo(MediaManager.MediaSession mediaSession)
|
||||
{
|
||||
if (!_mediaManager.IsStarted) return;
|
||||
@@ -382,13 +453,14 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
|
||||
private async Task SendFocusedMessagesAsync()
|
||||
{
|
||||
var focusedSession = _mediaManager.GetFocusedSession();
|
||||
if (focusedSession == null || focusedSession.ControlSession == null) return;
|
||||
var desiredSession = GetCurrentSession();
|
||||
if (desiredSession == null || desiredSession.ControlSession == null) return;
|
||||
|
||||
var mediaProps = await focusedSession.ControlSession.TryGetMediaPropertiesAsync();
|
||||
MediaManager_OnAnyTimelinePropertyChanged(focusedSession, focusedSession.ControlSession.GetTimelineProperties());
|
||||
MediaManager_OnAnyMediaPropertyChanged(focusedSession, mediaProps);
|
||||
MediaManager_OnAnyPlaybackStateChanged(focusedSession, focusedSession.ControlSession.GetPlaybackInfo());
|
||||
var mediaProps = await desiredSession.ControlSession.TryGetMediaPropertiesAsync();
|
||||
if (desiredSession == null || desiredSession.ControlSession == null) return;
|
||||
MediaManager_OnAnyTimelinePropertyChanged(desiredSession, desiredSession.ControlSession.GetTimelineProperties());
|
||||
MediaManager_OnAnyMediaPropertyChanged(desiredSession, mediaProps);
|
||||
MediaManager_OnAnyPlaybackStateChanged(desiredSession, desiredSession.ControlSession.GetPlaybackInfo());
|
||||
}
|
||||
|
||||
private void StartSSE()
|
||||
@@ -448,7 +520,10 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
_lxMusicDurationSeconds = data.GetDouble();
|
||||
}
|
||||
|
||||
TimelineChanged?.Invoke(this, new TimelineChangedEventArgs(TimeSpan.FromSeconds(_lxMusicPositionSeconds), TimeSpan.FromSeconds(_lxMusicDurationSeconds)));
|
||||
if (IsMediaSourceTimelineSyncEnabled(Constants.PlayerID.LXMusic))
|
||||
{
|
||||
TimelineChanged?.Invoke(this, new TimelineChangedEventArgs(TimeSpan.FromSeconds(_lxMusicPositionSeconds), TimeSpan.FromSeconds(_lxMusicDurationSeconds)));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -456,54 +531,49 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
|
||||
public async Task PlayAsync()
|
||||
{
|
||||
var focusedSession = _mediaManager.GetFocusedSession();
|
||||
if (focusedSession != null)
|
||||
var desiredSession = GetCurrentSession();
|
||||
if (desiredSession != null)
|
||||
{
|
||||
await focusedSession.ControlSession?.TryPlayAsync();
|
||||
await desiredSession.ControlSession?.TryPlayAsync();
|
||||
}
|
||||
}
|
||||
|
||||
public async Task PauseAsync()
|
||||
{
|
||||
var focusedSession = _mediaManager.GetFocusedSession();
|
||||
if (focusedSession != null)
|
||||
var desiredSession = GetCurrentSession();
|
||||
if (desiredSession != null)
|
||||
{
|
||||
await focusedSession.ControlSession?.TryPauseAsync();
|
||||
await desiredSession.ControlSession?.TryPauseAsync();
|
||||
}
|
||||
}
|
||||
|
||||
public async Task PreviousAsync()
|
||||
{
|
||||
var focusedSession = _mediaManager.GetFocusedSession();
|
||||
if (focusedSession != null)
|
||||
var desiredSession = GetCurrentSession();
|
||||
if (desiredSession != null)
|
||||
{
|
||||
await focusedSession.ControlSession?.TrySkipPreviousAsync();
|
||||
await desiredSession.ControlSession?.TrySkipPreviousAsync();
|
||||
}
|
||||
}
|
||||
|
||||
public async Task NextAsync()
|
||||
{
|
||||
var focusedSession = _mediaManager.GetFocusedSession();
|
||||
if (focusedSession != null)
|
||||
var desiredSession = GetCurrentSession();
|
||||
if (desiredSession != null)
|
||||
{
|
||||
await focusedSession.ControlSession?.TrySkipNextAsync();
|
||||
await desiredSession.ControlSession?.TrySkipNextAsync();
|
||||
}
|
||||
}
|
||||
|
||||
public async Task ChangePosition(double seconds)
|
||||
{
|
||||
var focusedSession = _mediaManager.GetFocusedSession();
|
||||
if (focusedSession != null)
|
||||
var desiredSession = GetCurrentSession();
|
||||
if (desiredSession != null)
|
||||
{
|
||||
await focusedSession.ControlSession?.TryChangePlaybackPositionAsync(TimeSpan.FromSeconds(seconds).Ticks);
|
||||
await desiredSession.ControlSession?.TryChangePlaybackPositionAsync(TimeSpan.FromSeconds(seconds).Ticks);
|
||||
}
|
||||
}
|
||||
|
||||
public MediaSourceProviderInfo? GetCurrentMediaSourceProviderInfo()
|
||||
{
|
||||
return _settingsService.AppSettings.MediaSourceProvidersInfo.Where(x => x.Provider == _cachedSongInfo?.SourceAppUserModelId)?.FirstOrDefault();
|
||||
}
|
||||
|
||||
public void Receive(PropertyChangedMessage<bool> message)
|
||||
{
|
||||
if (message.Sender is MediaSourceProviderInfo)
|
||||
@@ -527,6 +597,18 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
{
|
||||
UpdateTranslations();
|
||||
}
|
||||
else if (message.PropertyName == nameof(TranslationSettings.IsChineseRomanizationEnabled))
|
||||
{
|
||||
UpdateTranslations();
|
||||
}
|
||||
else if (message.PropertyName == nameof(TranslationSettings.IsJapaneseRomanizationEnabled))
|
||||
{
|
||||
UpdateTranslations();
|
||||
}
|
||||
else if (message.PropertyName == nameof(TranslationSettings.IsTraditionalChineseEnabled))
|
||||
{
|
||||
UpdateLyrics();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -571,5 +653,27 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Receive(PropertyChangedMessage<LyricsWindowMode> message)
|
||||
{
|
||||
if (message.Sender is LiveStates)
|
||||
{
|
||||
if (message.PropertyName == nameof(LiveStates.LyricsWindowMode))
|
||||
{
|
||||
UpdateTranslations();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Receive(PropertyChangedMessage<ChineseRomanization> message)
|
||||
{
|
||||
if (message.Sender is TranslationSettings)
|
||||
{
|
||||
if (message.PropertyName == nameof(TranslationSettings.ChineseRomanization))
|
||||
{
|
||||
UpdateTranslations();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,6 +57,12 @@ namespace BetterLyrics.WinUI3.Services.SettingsService
|
||||
AppSettings.LocalMediaFolders.CollectionChanged += AppSettings_CollectionChanged;
|
||||
AppSettings.LocalMediaFolders.ItemPropertyChanged += AppSettings_ItemPropertyChanged;
|
||||
|
||||
AppSettings.MappedSongSearchQueries.CollectionChanged += AppSettings_CollectionChanged;
|
||||
AppSettings.MappedSongSearchQueries.ItemPropertyChanged += AppSettings_ItemPropertyChanged;
|
||||
|
||||
AppSettings.WindowBoundsRecords.CollectionChanged += AppSettings_CollectionChanged;
|
||||
AppSettings.WindowBoundsRecords.ItemPropertyChanged += AppSettings_ItemPropertyChanged;
|
||||
|
||||
AppSettings.Version = MetadataHelper.AppVersion;
|
||||
|
||||
EnsureMediaSourceProvidersInfo();
|
||||
|
||||
@@ -12,6 +12,6 @@ namespace BetterLyrics.WinUI3.Services.TranslateService
|
||||
{
|
||||
Task<string> TranslateTextAsync(string text, string targetLangCode, CancellationToken token);
|
||||
|
||||
int SearchTranslatedLyricsItself(List<LyricsData> lyricsDataArr);
|
||||
int SearchTranslatedLyricsItself(List<LyricsData> lyricsDataArr, string targetLangCode);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,9 +58,8 @@ namespace BetterLyrics.WinUI3.Services.TranslateService
|
||||
return result?.TranslatedText ?? string.Empty;
|
||||
}
|
||||
|
||||
public int SearchTranslatedLyricsItself(List<LyricsData> lyricsDataArr)
|
||||
public int SearchTranslatedLyricsItself(List<LyricsData> lyricsDataArr, string targetLangCode)
|
||||
{
|
||||
string targetLangCode = LanguageHelper.SupportedTargetLanguages[_settingsService.AppSettings.TranslationSettings.SelectedTargetLanguageIndex].Code;
|
||||
if (lyricsDataArr.Count > 1)
|
||||
{
|
||||
for (int i = 1; i < lyricsDataArr.Count; i++)
|
||||
|
||||
@@ -135,8 +135,8 @@
|
||||
<data name="AllLyricsSettingsControlStandard.Content" xml:space="preserve">
|
||||
<value>Standard</value>
|
||||
</data>
|
||||
<data name="BaseWindowAOTFlyoutItem.Text" xml:space="preserve">
|
||||
<value>Always on top</value>
|
||||
<data name="AppSettingsControlGeneral.Content" xml:space="preserve">
|
||||
<value>General</value>
|
||||
</data>
|
||||
<data name="BaseWindowEnterFullScreenHint" xml:space="preserve">
|
||||
<value>Press Esc to exit full screen mode</value>
|
||||
@@ -219,6 +219,9 @@
|
||||
<data name="LyricsPageLyricsProviderPrefix.Header" xml:space="preserve">
|
||||
<value>Lyrics provider</value>
|
||||
</data>
|
||||
<data name="LyricsPageLyricsSearchButtonToolTip.Content" xml:space="preserve">
|
||||
<value>Manually search lyrics</value>
|
||||
</data>
|
||||
<data name="LyricsPageLyricsSettingsButtonToolTip.Content" xml:space="preserve">
|
||||
<value>Lyrics style and effect quick settings</value>
|
||||
</data>
|
||||
@@ -249,6 +252,42 @@
|
||||
<data name="LyricsPageTranslationProviderPrefix.Header" xml:space="preserve">
|
||||
<value>Translation provider</value>
|
||||
</data>
|
||||
<data name="LyricsSearchControlArtist.Header" xml:space="preserve">
|
||||
<value>Artist</value>
|
||||
</data>
|
||||
<data name="LyricsSearchControlHelp.Text" xml:space="preserve">
|
||||
<value>* Save changes take effect immediately, after which the track lyrics will be retrieved with mapping information and target lyrics; marking as pure music will directly return to pure music placeholder lyrics. Reset to retrieve by original data.</value>
|
||||
</data>
|
||||
<data name="LyricsSearchControlMappedAs.Text" xml:space="preserve">
|
||||
<value>mapped as</value>
|
||||
</data>
|
||||
<data name="LyricsSearchControlMarkAsPureMusic.Content" xml:space="preserve">
|
||||
<value>Mark as pure music</value>
|
||||
</data>
|
||||
<data name="LyricsSearchControlNotFound.Text" xml:space="preserve">
|
||||
<value>Not found</value>
|
||||
</data>
|
||||
<data name="LyricsSearchControlReset.Content" xml:space="preserve">
|
||||
<value>Reset</value>
|
||||
</data>
|
||||
<data name="LyricsSearchControlSaveChanges.Content" xml:space="preserve">
|
||||
<value>Save changes</value>
|
||||
</data>
|
||||
<data name="LyricsSearchControlSearch.Content" xml:space="preserve">
|
||||
<value>Search</value>
|
||||
</data>
|
||||
<data name="LyricsSearchControlSongInfoMapping.Header" xml:space="preserve">
|
||||
<value>Song info mapping</value>
|
||||
</data>
|
||||
<data name="LyricsSearchControlTargetSearchProvider.Header" xml:space="preserve">
|
||||
<value>Target lyrics search provider</value>
|
||||
</data>
|
||||
<data name="LyricsSearchControlTitle.Header" xml:space="preserve">
|
||||
<value>Title</value>
|
||||
</data>
|
||||
<data name="LyricsSearchPageTitle" xml:space="preserve">
|
||||
<value>Lyrics search - BetterLyrics</value>
|
||||
</data>
|
||||
<data name="LyricsSearchProviderEslrcFile" xml:space="preserve">
|
||||
<value>Local .ESLRC files</value>
|
||||
</data>
|
||||
@@ -403,6 +442,18 @@ If you encounter any problems, please go to the Settings page, About tab, and vi
|
||||
<data name="MusicGalleryPageTitle" xml:space="preserve">
|
||||
<value>Music gallery - BetterLyrics</value>
|
||||
</data>
|
||||
<data name="SetingsPageDonation.Text" xml:space="preserve">
|
||||
<value>Donation</value>
|
||||
</data>
|
||||
<data name="SetingsPageFeedback.Text" xml:space="preserve">
|
||||
<value>Feedback</value>
|
||||
</data>
|
||||
<data name="SetingsPageRef.Text" xml:space="preserve">
|
||||
<value>Library used</value>
|
||||
</data>
|
||||
<data name="SetingsPageThanks.Text" xml:space="preserve">
|
||||
<value>If you like this project, please consider supporting it by donating. Your support will help keep the project alive and encourage further development.</value>
|
||||
</data>
|
||||
<data name="SettingsPageAbout.Content" xml:space="preserve">
|
||||
<value>About</value>
|
||||
</data>
|
||||
@@ -439,6 +490,9 @@ If you encounter any problems, please go to the Settings page, About tab, and vi
|
||||
<data name="SettingsPageAmount.Header" xml:space="preserve">
|
||||
<value>Amount</value>
|
||||
</data>
|
||||
<data name="SettingsPageAOT.Header" xml:space="preserve">
|
||||
<value>Always on top</value>
|
||||
</data>
|
||||
<data name="SettingsPageApp.Content" xml:space="preserve">
|
||||
<value>App appearance and behavior</value>
|
||||
</data>
|
||||
@@ -448,17 +502,8 @@ If you encounter any problems, please go to the Settings page, About tab, and vi
|
||||
<data name="SettingsPageAppBehavior.Text" xml:space="preserve">
|
||||
<value>App behavior</value>
|
||||
</data>
|
||||
<data name="SettingsPageAppDesktop.Text" xml:space="preserve">
|
||||
<value>Desktop mode</value>
|
||||
</data>
|
||||
<data name="SettingsPageAppDock.Text" xml:space="preserve">
|
||||
<value>Dock mode</value>
|
||||
</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 name="SettingsPageApply.Content" xml:space="preserve">
|
||||
<value>Apply</value>
|
||||
</data>
|
||||
<data name="SettingsPageAutoLock.Header" xml:space="preserve">
|
||||
<value>Auto-lock when activating desktop mode</value>
|
||||
@@ -485,7 +530,7 @@ If you encounter any problems, please go to the Settings page, About tab, and vi
|
||||
<value>Lyrics backdrop</value>
|
||||
</data>
|
||||
<data name="SettingsPageBackgroundAcrylicEffectAmount.Header" xml:space="preserve">
|
||||
<value>Album Background Acrylic Effect Strength!</value>
|
||||
<value>Album Background Acrylic Effect Strength</value>
|
||||
</data>
|
||||
<data name="SettingsPageBackgroundOverlay.Content" xml:space="preserve">
|
||||
<value>Lyrics background</value>
|
||||
@@ -496,22 +541,37 @@ If you encounter any problems, please go to the Settings page, About tab, and vi
|
||||
<data name="SettingsPageCache.Header" xml:space="preserve">
|
||||
<value>Cache</value>
|
||||
</data>
|
||||
<data name="SettingsPageChinese.Header" xml:space="preserve">
|
||||
<value>Chinese pronunciation</value>
|
||||
</data>
|
||||
<data name="SettingsPageChinesePreference.Header" xml:space="preserve">
|
||||
<value>Convert Chinese to Traditional Chinese</value>
|
||||
</data>
|
||||
<data name="SettingsPageCompactTitleBar.Content" xml:space="preserve">
|
||||
<value>Compact</value>
|
||||
</data>
|
||||
<data name="SettingsPageCurrentLyricsWindowStatus.Text" xml:space="preserve">
|
||||
<value>Current lyrics window status</value>
|
||||
</data>
|
||||
<data name="SettingsPageDark.Content" xml:space="preserve">
|
||||
<value>Dark</value>
|
||||
</data>
|
||||
<data name="SettingsPageDebugOverlay.Header" xml:space="preserve">
|
||||
<value>Show debug overlay</value>
|
||||
</data>
|
||||
<data name="SettingsPageDelete.Content" xml:space="preserve">
|
||||
<value>Delete</value>
|
||||
</data>
|
||||
<data name="SettingsPageDesktopAcrylic.Content" xml:space="preserve">
|
||||
<value>Desktop Acrylic</value>
|
||||
</data>
|
||||
<data name="SettingsPageDev.Content" xml:space="preserve">
|
||||
<value>Advanced options</value>
|
||||
</data>
|
||||
<data name="SettingsPageDiscord.Header" xml:space="preserve">
|
||||
<data name="SettingsPageDisclaimer.Text" xml:space="preserve">
|
||||
<value>This project is provided as is without warranty of any kind. All lyrics, fonts, icons, and other third-party resources are the property of their respective copyright holders. The author of this project does not claim ownership of such resources. This project is non-commercial and should not be used to infringe any rights. Users are responsible for ensuring their own use complies with applicable laws and licenses.</value>
|
||||
</data>
|
||||
<data name="SettingsPageDiscord.Content" xml:space="preserve">
|
||||
<value>Discord</value>
|
||||
</data>
|
||||
<data name="SettingsPageDisplayTypeSwitcher.Header" xml:space="preserve">
|
||||
@@ -532,6 +592,9 @@ If you encounter any problems, please go to the Settings page, About tab, and vi
|
||||
<data name="SettingsPageDockWindowHeight.Header" xml:space="preserve">
|
||||
<value>Window height</value>
|
||||
</data>
|
||||
<data name="SettingsPageDynamicLyricsFontSize.Header" xml:space="preserve">
|
||||
<value>Automatic adjustment</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingFuncType.Header" xml:space="preserve">
|
||||
<value>Easing animation type</value>
|
||||
</data>
|
||||
@@ -586,7 +649,7 @@ If you encounter any problems, please go to the Settings page, About tab, and vi
|
||||
<data name="SettingsPageFan.Header" xml:space="preserve">
|
||||
<value>Fan lyrics</value>
|
||||
</data>
|
||||
<data name="SettingsPageFAQ.Header" xml:space="preserve">
|
||||
<data name="SettingsPageFAQ.Content" xml:space="preserve">
|
||||
<value>Frequently asked questions</value>
|
||||
</data>
|
||||
<data name="SettingsPageFixedTimeStep.Header" xml:space="preserve">
|
||||
@@ -598,15 +661,6 @@ If you encounter any problems, please go to the Settings page, About tab, and vi
|
||||
<data name="SettingsPageFPS.Header" xml:space="preserve">
|
||||
<value>Rendering frame rate</value>
|
||||
</data>
|
||||
<data name="SettingsPageGitHub.ActionIconToolTip" xml:space="preserve">
|
||||
<value>Open in new window</value>
|
||||
</data>
|
||||
<data name="SettingsPageGitHub.Description" xml:space="preserve">
|
||||
<value>See source code on GitHub</value>
|
||||
</data>
|
||||
<data name="SettingsPageGitHub.Header" xml:space="preserve">
|
||||
<value>This is an open source app</value>
|
||||
</data>
|
||||
<data name="SettingsPageGlobalDrag.Description" xml:space="preserve">
|
||||
<value>Extend the title bar to the entire page so that the window can be dragged in any non-interactive area</value>
|
||||
</data>
|
||||
@@ -614,10 +668,10 @@ If you encounter any problems, please go to the Settings page, About tab, and vi
|
||||
<value>Global drag</value>
|
||||
</data>
|
||||
<data name="SettingsPageHideWindow.Description" xml:space="preserve">
|
||||
<value>Automatically hide the window when no songs are playing in dock mode or desktop mode</value>
|
||||
<value>In docking mode or desktop mode, when no song is playing, the window will be automatically hidden; otherwise, the window will be automatically displayed.</value>
|
||||
</data>
|
||||
<data name="SettingsPageHideWindow.Header" xml:space="preserve">
|
||||
<value>Auto-hide window</value>
|
||||
<value>Automatically hide/show windows</value>
|
||||
</data>
|
||||
<data name="SettingsPageIgnoreFullscreenWindow.Description" xml:space="preserve">
|
||||
<value>Force this app to appear on top of full-screen apps when docked or desktop mode is enabled</value>
|
||||
@@ -634,9 +688,15 @@ If you encounter any problems, please go to the Settings page, About tab, and vi
|
||||
<data name="SettingsPageJA.Content" xml:space="preserve">
|
||||
<value>日本語</value>
|
||||
</data>
|
||||
<data name="SettingsPageJapanese.Header" xml:space="preserve">
|
||||
<value>Japanese annotation</value>
|
||||
</data>
|
||||
<data name="SettingsPageJoinNowButton.Content" xml:space="preserve">
|
||||
<value>Join now</value>
|
||||
</data>
|
||||
<data name="SettingsPageJyutping.Content" xml:space="preserve">
|
||||
<value>Cantonese pinyin</value>
|
||||
</data>
|
||||
<data name="SettingsPageKO.Content" xml:space="preserve">
|
||||
<value>한국어</value>
|
||||
</data>
|
||||
@@ -695,13 +755,13 @@ If you encounter any problems, please go to the Settings page, About tab, and vi
|
||||
<value>Lyrics background</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsBackgroundBlurAmount.Header" xml:space="preserve">
|
||||
<value>Album background layer ambiguity!</value>
|
||||
<value>Album background layer ambiguity</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsBackgroundOpacity.Header" xml:space="preserve">
|
||||
<value>Album background layer opacity!</value>
|
||||
<value>Album background layer opacity</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsBackgroundSpeed.Header" xml:space="preserve">
|
||||
<value>Album Background Layer Motion Rate!</value>
|
||||
<value>Album Background Layer Motion Rate</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsBgFontColor.Header" xml:space="preserve">
|
||||
<value>Font color (Non-current playback area)</value>
|
||||
@@ -838,6 +898,9 @@ If you encounter any problems, please go to the Settings page, About tab, and vi
|
||||
<data name="SettingsPageLyricsThin.Content" xml:space="preserve">
|
||||
<value>Thin</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsTimeline.Header" xml:space="preserve">
|
||||
<value>Lyrics timeline sync</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsTimelineThreshold.Description" xml:space="preserve">
|
||||
<value>If the lyrics progress is jittery, try increasing this threshold; changing this value can cause lyrics synchronization to deviate</value>
|
||||
</data>
|
||||
@@ -853,6 +916,9 @@ If you encounter any problems, please go to the Settings page, About tab, and vi
|
||||
<data name="SettingsPageLyricsVerticalEdgeOpacity.Header" xml:space="preserve">
|
||||
<value>Top and bottom edge opacity</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsWindowManager.Header" xml:space="preserve">
|
||||
<value>Lyrics window manager</value>
|
||||
</data>
|
||||
<data name="SettingsPageMediaLib.Content" xml:space="preserve">
|
||||
<value>Media library</value>
|
||||
</data>
|
||||
@@ -898,6 +964,9 @@ If you encounter any problems, please go to the Settings page, About tab, and vi
|
||||
<data name="SettingsPagePathNotFound.Text" xml:space="preserve">
|
||||
<value>The path cannot be found on your computer</value>
|
||||
</data>
|
||||
<data name="SettingsPagePinyin.Content" xml:space="preserve">
|
||||
<value>Pinyin of Mandarin</value>
|
||||
</data>
|
||||
<data name="SettingsPagePlaybackLib.Content" xml:space="preserve">
|
||||
<value>Playback sources</value>
|
||||
</data>
|
||||
@@ -916,9 +985,15 @@ If you encounter any problems, please go to the Settings page, About tab, and vi
|
||||
<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.Content" xml:space="preserve">
|
||||
<value>QQ feedback & chat group</value>
|
||||
</data>
|
||||
<data name="SettingsPageRecord.Content" xml:space="preserve">
|
||||
<value>Record</value>
|
||||
</data>
|
||||
<data name="SettingsPageRecordedWindowStatus.Text" xml:space="preserve">
|
||||
<value>Recorded window status</value>
|
||||
</data>
|
||||
<data name="SettingsPageRemoveInfo.Message" xml:space="preserve">
|
||||
<value>Original files and folders in this path will not be deleted when removing it from this app</value>
|
||||
</data>
|
||||
@@ -931,6 +1006,9 @@ If you encounter any problems, please go to the Settings page, About tab, and vi
|
||||
<data name="SettingsPageRestart.Content" xml:space="preserve">
|
||||
<value>Restart app to apply change</value>
|
||||
</data>
|
||||
<data name="SettingsPageRomaji.Header" xml:space="preserve">
|
||||
<value>Japanese annotation</value>
|
||||
</data>
|
||||
<data name="SettingsPageSC.Content" xml:space="preserve">
|
||||
<value>简体中文</value>
|
||||
</data>
|
||||
@@ -973,6 +1051,9 @@ If you encounter any problems, please go to the Settings page, About tab, and vi
|
||||
<data name="SettingsPageShortcutRegSuccessInfo" xml:space="preserve">
|
||||
<value>This hotkey has been successfully registered</value>
|
||||
</data>
|
||||
<data name="SettingsPageShowHideHotKey.Header" xml:space="preserve">
|
||||
<value>Lyrics window display and hide shortcut keys</value>
|
||||
</data>
|
||||
<data name="SettingsPageSliderPrefix.Text" xml:space="preserve">
|
||||
<value>Current value: </value>
|
||||
</data>
|
||||
@@ -1000,7 +1081,7 @@ If you encounter any problems, please go to the Settings page, About tab, and vi
|
||||
<data name="SettingsPageTC.Content" xml:space="preserve">
|
||||
<value>繁體中文</value>
|
||||
</data>
|
||||
<data name="SettingsPageTelegram.Header" xml:space="preserve">
|
||||
<data name="SettingsPageTelegram.Content" xml:space="preserve">
|
||||
<value>Telegram</value>
|
||||
</data>
|
||||
<data name="SettingsPageTheme.Header" xml:space="preserve">
|
||||
|
||||
@@ -135,8 +135,8 @@
|
||||
<data name="AllLyricsSettingsControlStandard.Content" xml:space="preserve">
|
||||
<value>標準モード</value>
|
||||
</data>
|
||||
<data name="BaseWindowAOTFlyoutItem.Text" xml:space="preserve">
|
||||
<value>常にトップ</value>
|
||||
<data name="AppSettingsControlGeneral.Content" xml:space="preserve">
|
||||
<value>一般的な</value>
|
||||
</data>
|
||||
<data name="BaseWindowEnterFullScreenHint" xml:space="preserve">
|
||||
<value>ESCを押して、フルスクリーンモードを終了します</value>
|
||||
@@ -196,7 +196,7 @@
|
||||
<value>ブラウザの承認を完了してください</value>
|
||||
</data>
|
||||
<data name="LastFMRequestAuthTitle" xml:space="preserve">
|
||||
<value>BetterLyricsにLast.fmアカウントへのアクセスを許可してください!</value>
|
||||
<value>BetterLyricsにLast.fmアカウントへのアクセスを許可してください</value>
|
||||
</data>
|
||||
<data name="LastFMRequestUnAuthConfirm" xml:space="preserve">
|
||||
<value>認可をキャンセルしました</value>
|
||||
@@ -205,7 +205,7 @@
|
||||
<value>ブラウザでキャンセル操作を完了してください</value>
|
||||
</data>
|
||||
<data name="LastFMRequestUnAuthTitle" xml:space="preserve">
|
||||
<value>Last.fmアカウントへのBetterLyricsアクセスを取り消します!</value>
|
||||
<value>Last.fmアカウントへのBetterLyricsアクセスを取り消します</value>
|
||||
</data>
|
||||
<data name="LibreTranslateFailed" xml:space="preserve">
|
||||
<value>リブレットランスレートからの翻訳のリクエストが失敗しました。設定またはネイティブリブレットランレート構成を確認してください</value>
|
||||
@@ -219,6 +219,9 @@
|
||||
<data name="LyricsPageLyricsProviderPrefix.Header" xml:space="preserve">
|
||||
<value>歌詞プロバイダー</value>
|
||||
</data>
|
||||
<data name="LyricsPageLyricsSearchButtonToolTip.Content" xml:space="preserve">
|
||||
<value>手動で歌詞を検索します</value>
|
||||
</data>
|
||||
<data name="LyricsPageLyricsSettingsButtonToolTip.Content" xml:space="preserve">
|
||||
<value>歌詞スタイルと効果クイック設定</value>
|
||||
</data>
|
||||
@@ -249,6 +252,42 @@
|
||||
<data name="LyricsPageTranslationProviderPrefix.Header" xml:space="preserve">
|
||||
<value>翻訳プロバイダー</value>
|
||||
</data>
|
||||
<data name="LyricsSearchControlArtist.Header" xml:space="preserve">
|
||||
<value>アーティスト</value>
|
||||
</data>
|
||||
<data name="LyricsSearchControlHelp.Text" xml:space="preserve">
|
||||
<value>*保存変更はすぐに有効になります。その後、トラックの歌詞がマッピング情報とターゲット歌詞で取得されます。純粋な音楽としてのマーキングは、純粋な音楽プレースホルダーの歌詞に直接戻ります。元のデータで取得するためにリセット。</value>
|
||||
</data>
|
||||
<data name="LyricsSearchControlMappedAs.Text" xml:space="preserve">
|
||||
<value>としてマッピングされました</value>
|
||||
</data>
|
||||
<data name="LyricsSearchControlMarkAsPureMusic.Content" xml:space="preserve">
|
||||
<value>純粋な音楽としてマークしてください</value>
|
||||
</data>
|
||||
<data name="LyricsSearchControlNotFound.Text" xml:space="preserve">
|
||||
<value>見つかりませんでした</value>
|
||||
</data>
|
||||
<data name="LyricsSearchControlReset.Content" xml:space="preserve">
|
||||
<value>リセット</value>
|
||||
</data>
|
||||
<data name="LyricsSearchControlSaveChanges.Content" xml:space="preserve">
|
||||
<value>変更を保存</value>
|
||||
</data>
|
||||
<data name="LyricsSearchControlSearch.Content" xml:space="preserve">
|
||||
<value>検索する</value>
|
||||
</data>
|
||||
<data name="LyricsSearchControlSongInfoMapping.Header" xml:space="preserve">
|
||||
<value>曲情報マッピング</value>
|
||||
</data>
|
||||
<data name="LyricsSearchControlTargetSearchProvider.Header" xml:space="preserve">
|
||||
<value>ターゲット歌詞検索プロバイダー</value>
|
||||
</data>
|
||||
<data name="LyricsSearchControlTitle.Header" xml:space="preserve">
|
||||
<value>タイトル</value>
|
||||
</data>
|
||||
<data name="LyricsSearchPageTitle" xml:space="preserve">
|
||||
<value>歌詞検索 - BetterLyrics</value>
|
||||
</data>
|
||||
<data name="LyricsSearchProviderEslrcFile" xml:space="preserve">
|
||||
<value>ローカル.ESLRCファイル</value>
|
||||
</data>
|
||||
@@ -403,6 +442,18 @@
|
||||
<data name="MusicGalleryPageTitle" xml:space="preserve">
|
||||
<value>音楽ギャラリー - BetterLyrics</value>
|
||||
</data>
|
||||
<data name="SetingsPageDonation.Text" xml:space="preserve">
|
||||
<value>寄付</value>
|
||||
</data>
|
||||
<data name="SetingsPageFeedback.Text" xml:space="preserve">
|
||||
<value>フィードバック</value>
|
||||
</data>
|
||||
<data name="SetingsPageRef.Text" xml:space="preserve">
|
||||
<value>使用されているライブラリ</value>
|
||||
</data>
|
||||
<data name="SetingsPageThanks.Text" xml:space="preserve">
|
||||
<value>このプロジェクトが気に入っている場合は、寄付してサポートすることを検討してください。あなたのサポートは、プロジェクトを生かし続け、さらなる開発を促進するのに役立ちます。</value>
|
||||
</data>
|
||||
<data name="SettingsPageAbout.Content" xml:space="preserve">
|
||||
<value>について</value>
|
||||
</data>
|
||||
@@ -439,6 +490,9 @@
|
||||
<data name="SettingsPageAmount.Header" xml:space="preserve">
|
||||
<value>量</value>
|
||||
</data>
|
||||
<data name="SettingsPageAOT.Header" xml:space="preserve">
|
||||
<value>常にトップ</value>
|
||||
</data>
|
||||
<data name="SettingsPageApp.Content" xml:space="preserve">
|
||||
<value>アプリの外観と動作</value>
|
||||
</data>
|
||||
@@ -448,17 +502,8 @@
|
||||
<data name="SettingsPageAppBehavior.Text" xml:space="preserve">
|
||||
<value>アプリの動作</value>
|
||||
</data>
|
||||
<data name="SettingsPageAppDesktop.Text" xml:space="preserve">
|
||||
<value>デスクトップモード</value>
|
||||
</data>
|
||||
<data name="SettingsPageAppDock.Text" xml:space="preserve">
|
||||
<value>ドックモード</value>
|
||||
</data>
|
||||
<data name="SettingsPageAppPictureInPicture.Text" xml:space="preserve">
|
||||
<value>ピクチャーインピクチャーモード</value>
|
||||
</data>
|
||||
<data name="SettingsPageAppStandard.Text" xml:space="preserve">
|
||||
<value>標準モード</value>
|
||||
<data name="SettingsPageApply.Content" xml:space="preserve">
|
||||
<value>適用する</value>
|
||||
</data>
|
||||
<data name="SettingsPageAutoLock.Header" xml:space="preserve">
|
||||
<value>デスクトップモードをアクティブにするときの自動ロック</value>
|
||||
@@ -485,7 +530,7 @@
|
||||
<value>歌詞の背景素材</value>
|
||||
</data>
|
||||
<data name="SettingsPageBackgroundAcrylicEffectAmount.Header" xml:space="preserve">
|
||||
<value>アルバムの背景アクリル効果の強さ!</value>
|
||||
<value>アルバムの背景アクリル効果の強さ</value>
|
||||
</data>
|
||||
<data name="SettingsPageBackgroundOverlay.Content" xml:space="preserve">
|
||||
<value>歌詞の背景</value>
|
||||
@@ -496,22 +541,37 @@
|
||||
<data name="SettingsPageCache.Header" xml:space="preserve">
|
||||
<value>キャッシュ</value>
|
||||
</data>
|
||||
<data name="SettingsPageChinese.Header" xml:space="preserve">
|
||||
<value>中国の発音</value>
|
||||
</data>
|
||||
<data name="SettingsPageChinesePreference.Header" xml:space="preserve">
|
||||
<value>中国人を伝統的な中国人に変換します</value>
|
||||
</data>
|
||||
<data name="SettingsPageCompactTitleBar.Content" xml:space="preserve">
|
||||
<value>コンパクト</value>
|
||||
</data>
|
||||
<data name="SettingsPageCurrentLyricsWindowStatus.Text" xml:space="preserve">
|
||||
<value>現在の歌詞ウィンドウステータス</value>
|
||||
</data>
|
||||
<data name="SettingsPageDark.Content" xml:space="preserve">
|
||||
<value>暗い</value>
|
||||
</data>
|
||||
<data name="SettingsPageDebugOverlay.Header" xml:space="preserve">
|
||||
<value>デバッグオーバーレイを表示します</value>
|
||||
</data>
|
||||
<data name="SettingsPageDelete.Content" xml:space="preserve">
|
||||
<value>消去</value>
|
||||
</data>
|
||||
<data name="SettingsPageDesktopAcrylic.Content" xml:space="preserve">
|
||||
<value>デスクトップアクリル</value>
|
||||
</data>
|
||||
<data name="SettingsPageDev.Content" xml:space="preserve">
|
||||
<value>高度なオプション</value>
|
||||
</data>
|
||||
<data name="SettingsPageDiscord.Header" xml:space="preserve">
|
||||
<data name="SettingsPageDisclaimer.Text" xml:space="preserve">
|
||||
<value>このプロジェクトは、いかなる種類の保証もなく現状のまま提供されています。すべての歌詞、フォント、アイコン、およびその他のサードパーティのリソースは、それぞれの著作権所有者の財産です。このプロジェクトの作成者は、そのようなリソースの所有権を主張していません。このプロジェクトは非営利的であり、いかなる権利も侵害するために使用すべきではありません。ユーザーは、自らの使用が適用される法律およびライセンスに準拠していることを確認する責任があります。</value>
|
||||
</data>
|
||||
<data name="SettingsPageDiscord.Content" xml:space="preserve">
|
||||
<value>Discord</value>
|
||||
</data>
|
||||
<data name="SettingsPageDisplayTypeSwitcher.Header" xml:space="preserve">
|
||||
@@ -532,6 +592,9 @@
|
||||
<data name="SettingsPageDockWindowHeight.Header" xml:space="preserve">
|
||||
<value>窓の高さ</value>
|
||||
</data>
|
||||
<data name="SettingsPageDynamicLyricsFontSize.Header" xml:space="preserve">
|
||||
<value>自動調整</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingFuncType.Header" xml:space="preserve">
|
||||
<value>アニメーションタイプを緩和します</value>
|
||||
</data>
|
||||
@@ -586,7 +649,7 @@
|
||||
<data name="SettingsPageFan.Header" xml:space="preserve">
|
||||
<value>ファンの歌詞</value>
|
||||
</data>
|
||||
<data name="SettingsPageFAQ.Header" xml:space="preserve">
|
||||
<data name="SettingsPageFAQ.Content" xml:space="preserve">
|
||||
<value>よくある質問</value>
|
||||
</data>
|
||||
<data name="SettingsPageFixedTimeStep.Header" xml:space="preserve">
|
||||
@@ -598,15 +661,6 @@
|
||||
<data name="SettingsPageFPS.Header" xml:space="preserve">
|
||||
<value>レンダリングフレームレート</value>
|
||||
</data>
|
||||
<data name="SettingsPageGitHub.ActionIconToolTip" xml:space="preserve">
|
||||
<value>新しいウィンドウで開きます</value>
|
||||
</data>
|
||||
<data name="SettingsPageGitHub.Description" xml:space="preserve">
|
||||
<value>GitHubのソースコードを参照してください</value>
|
||||
</data>
|
||||
<data name="SettingsPageGitHub.Header" xml:space="preserve">
|
||||
<value>これはオープンソースアプリです</value>
|
||||
</data>
|
||||
<data name="SettingsPageGlobalDrag.Description" xml:space="preserve">
|
||||
<value>タイトルバーをページ全体に拡張して、ウィンドウを非対話領域でドラッグできるようにします</value>
|
||||
</data>
|
||||
@@ -614,10 +668,10 @@
|
||||
<value>グローバルドラッグ</value>
|
||||
</data>
|
||||
<data name="SettingsPageHideWindow.Description" xml:space="preserve">
|
||||
<value>ドックモードやデスクトップモードで再生されている曲がないときにウィンドウを自動的に非表示にする</value>
|
||||
<value>ドッキングモードまたはデスクトップモードでは、曲が再生されていない場合、ウィンドウは自動的に非表示になります。それ以外の場合、ウィンドウが自動的に表示されます。</value>
|
||||
</data>
|
||||
<data name="SettingsPageHideWindow.Header" xml:space="preserve">
|
||||
<value>自動ハイドウィンドウ</value>
|
||||
<value>Windowsを自動的に非表示/表示します</value>
|
||||
</data>
|
||||
<data name="SettingsPageIgnoreFullscreenWindow.Description" xml:space="preserve">
|
||||
<value>このアプリは、ドッキングまたはデスクトップモードが有効になっているときにフルスクリーンアプリの上に表示されます</value>
|
||||
@@ -634,9 +688,15 @@
|
||||
<data name="SettingsPageJA.Content" xml:space="preserve">
|
||||
<value>日本語</value>
|
||||
</data>
|
||||
<data name="SettingsPageJapanese.Header" xml:space="preserve">
|
||||
<value>日本の注釈</value>
|
||||
</data>
|
||||
<data name="SettingsPageJoinNowButton.Content" xml:space="preserve">
|
||||
<value>今すぐ参加してください</value>
|
||||
</data>
|
||||
<data name="SettingsPageJyutping.Content" xml:space="preserve">
|
||||
<value>広東語のピンイン</value>
|
||||
</data>
|
||||
<data name="SettingsPageKO.Content" xml:space="preserve">
|
||||
<value>한국어</value>
|
||||
</data>
|
||||
@@ -695,13 +755,13 @@
|
||||
<value>歌詞の背景</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsBackgroundBlurAmount.Header" xml:space="preserve">
|
||||
<value>アルバムの背景レイヤーの曖昧さ!</value>
|
||||
<value>アルバムの背景レイヤーの曖昧さ</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsBackgroundOpacity.Header" xml:space="preserve">
|
||||
<value>アルバムの背景レイヤーの不透明度!</value>
|
||||
<value>アルバムの背景レイヤーの不透明度</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsBackgroundSpeed.Header" xml:space="preserve">
|
||||
<value>アルバムの背景レイヤーのモーションレート!</value>
|
||||
<value>アルバムの背景レイヤーのモーションレート</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsBgFontColor.Header" xml:space="preserve">
|
||||
<value>フォントカラー(非電流再生エリア)</value>
|
||||
@@ -838,6 +898,9 @@
|
||||
<data name="SettingsPageLyricsThin.Content" xml:space="preserve">
|
||||
<value>薄い</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsTimeline.Header" xml:space="preserve">
|
||||
<value>歌詞のタイムラインを同期</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsTimelineThreshold.Description" xml:space="preserve">
|
||||
<value>歌詞の進行が不安定な場合は、このしきい値を増やしてみてください。この値を変更すると、歌詞の同期が逸脱する可能性があります</value>
|
||||
</data>
|
||||
@@ -853,6 +916,9 @@
|
||||
<data name="SettingsPageLyricsVerticalEdgeOpacity.Header" xml:space="preserve">
|
||||
<value>上端と下端の不透明度</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsWindowManager.Header" xml:space="preserve">
|
||||
<value>歌詞ウィンドウマネージャー</value>
|
||||
</data>
|
||||
<data name="SettingsPageMediaLib.Content" xml:space="preserve">
|
||||
<value>メディアライブラリ</value>
|
||||
</data>
|
||||
@@ -898,6 +964,9 @@
|
||||
<data name="SettingsPagePathNotFound.Text" xml:space="preserve">
|
||||
<value>パスはコンピューターでは見つかりません</value>
|
||||
</data>
|
||||
<data name="SettingsPagePinyin.Content" xml:space="preserve">
|
||||
<value>マンダリンのピンイン</value>
|
||||
</data>
|
||||
<data name="SettingsPagePlaybackLib.Content" xml:space="preserve">
|
||||
<value>再生ソース</value>
|
||||
</data>
|
||||
@@ -916,9 +985,15 @@
|
||||
<data name="SettingsPagePreviousSongHotKey.Header" xml:space="preserve">
|
||||
<value>前のトラックのショートカットキー</value>
|
||||
</data>
|
||||
<data name="SettingsPageQQGroup.Header" xml:space="preserve">
|
||||
<data name="SettingsPageQQGroup.Content" xml:space="preserve">
|
||||
<value>QQフィードバック&チャットグループ</value>
|
||||
</data>
|
||||
<data name="SettingsPageRecord.Content" xml:space="preserve">
|
||||
<value>記録</value>
|
||||
</data>
|
||||
<data name="SettingsPageRecordedWindowStatus.Text" xml:space="preserve">
|
||||
<value>記録されたウィンドウステータス</value>
|
||||
</data>
|
||||
<data name="SettingsPageRemoveInfo.Message" xml:space="preserve">
|
||||
<value>このパスの元のファイルとフォルダーは、このアプリから削除するときに削除されません</value>
|
||||
</data>
|
||||
@@ -931,6 +1006,9 @@
|
||||
<data name="SettingsPageRestart.Content" xml:space="preserve">
|
||||
<value>変更を適用するためのアプリを再起動します</value>
|
||||
</data>
|
||||
<data name="SettingsPageRomaji.Header" xml:space="preserve">
|
||||
<value>日本の注釈</value>
|
||||
</data>
|
||||
<data name="SettingsPageSC.Content" xml:space="preserve">
|
||||
<value>简体中文</value>
|
||||
</data>
|
||||
@@ -973,6 +1051,9 @@
|
||||
<data name="SettingsPageShortcutRegSuccessInfo" xml:space="preserve">
|
||||
<value>このホットキーは正常に登録されています</value>
|
||||
</data>
|
||||
<data name="SettingsPageShowHideHotKey.Header" xml:space="preserve">
|
||||
<value>歌詞ウィンドウディスプレイとショートカットキーを非表示にします</value>
|
||||
</data>
|
||||
<data name="SettingsPageSliderPrefix.Text" xml:space="preserve">
|
||||
<value>現在の値: </value>
|
||||
</data>
|
||||
@@ -1000,7 +1081,7 @@
|
||||
<data name="SettingsPageTC.Content" xml:space="preserve">
|
||||
<value>繁體中文</value>
|
||||
</data>
|
||||
<data name="SettingsPageTelegram.Header" xml:space="preserve">
|
||||
<data name="SettingsPageTelegram.Content" xml:space="preserve">
|
||||
<value>Telegram</value>
|
||||
</data>
|
||||
<data name="SettingsPageTheme.Header" xml:space="preserve">
|
||||
@@ -1058,6 +1139,6 @@
|
||||
<value>翻訳サーバーは設定されていません。最初に設定で構成してください</value>
|
||||
</data>
|
||||
<data name="TryRunMultipleInstance" xml:space="preserve">
|
||||
<value>BetterLyrics はすでに実行されています!</value>
|
||||
<value>BetterLyrics はすでに実行されています</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -135,8 +135,8 @@
|
||||
<data name="AllLyricsSettingsControlStandard.Content" xml:space="preserve">
|
||||
<value>표준 모드</value>
|
||||
</data>
|
||||
<data name="BaseWindowAOTFlyoutItem.Text" xml:space="preserve">
|
||||
<value>항상 위에</value>
|
||||
<data name="AppSettingsControlGeneral.Content" xml:space="preserve">
|
||||
<value>일반적인</value>
|
||||
</data>
|
||||
<data name="BaseWindowEnterFullScreenHint" xml:space="preserve">
|
||||
<value>ESC를 눌러 전체 화면 모드를 종료하십시오</value>
|
||||
@@ -196,7 +196,7 @@
|
||||
<value>브라우저에서 승인을 완료하십시오</value>
|
||||
</data>
|
||||
<data name="LastFMRequestAuthTitle" xml:space="preserve">
|
||||
<value>Last.fm 계정에 BetterLyrics 액세스 권한을 부여하세요!</value>
|
||||
<value>Last.fm 계정에 BetterLyrics 액세스 권한을 부여하세요</value>
|
||||
</data>
|
||||
<data name="LastFMRequestUnAuthConfirm" xml:space="preserve">
|
||||
<value>내 승인을 취소했습니다</value>
|
||||
@@ -205,7 +205,7 @@
|
||||
<value>브라우저에서 취소 작업을 완료하십시오</value>
|
||||
</data>
|
||||
<data name="LastFMRequestUnAuthTitle" xml:space="preserve">
|
||||
<value>Last.fm 계정에 대한 BetterLyrics 액세스를 취소하십시오!</value>
|
||||
<value>Last.fm 계정에 대한 BetterLyrics 액세스를 취소하십시오</value>
|
||||
</data>
|
||||
<data name="LibreTranslateFailed" xml:space="preserve">
|
||||
<value>LibreTranslate에서 번역 요청 실패, 설정 또는 기본 LibreTranslate 구성을 확인하십시오.</value>
|
||||
@@ -219,6 +219,9 @@
|
||||
<data name="LyricsPageLyricsProviderPrefix.Header" xml:space="preserve">
|
||||
<value>가사 제공자</value>
|
||||
</data>
|
||||
<data name="LyricsPageLyricsSearchButtonToolTip.Content" xml:space="preserve">
|
||||
<value>가사를 수동으로 검색합니다</value>
|
||||
</data>
|
||||
<data name="LyricsPageLyricsSettingsButtonToolTip.Content" xml:space="preserve">
|
||||
<value>가사 스타일과 효과 빠른 설정</value>
|
||||
</data>
|
||||
@@ -249,6 +252,42 @@
|
||||
<data name="LyricsPageTranslationProviderPrefix.Header" xml:space="preserve">
|
||||
<value>번역 제공자</value>
|
||||
</data>
|
||||
<data name="LyricsSearchControlArtist.Header" xml:space="preserve">
|
||||
<value>아티스트</value>
|
||||
</data>
|
||||
<data name="LyricsSearchControlHelp.Text" xml:space="preserve">
|
||||
<value>* 변경 사항 저장 변경은 즉시 적용되며, 그 후 트랙 가사는 맵핑 정보와 대상 가사로 검색됩니다. 순수한 음악으로 표시하면 순수한 음악 자리 표시 자 가사로 직접 돌아갑니다. 원래 데이터로 검색하도록 재설정하십시오.</value>
|
||||
</data>
|
||||
<data name="LyricsSearchControlMappedAs.Text" xml:space="preserve">
|
||||
<value>로 매핑됨</value>
|
||||
</data>
|
||||
<data name="LyricsSearchControlMarkAsPureMusic.Content" xml:space="preserve">
|
||||
<value>순수한 음악으로 표시하세요</value>
|
||||
</data>
|
||||
<data name="LyricsSearchControlNotFound.Text" xml:space="preserve">
|
||||
<value>찾을 수 없음</value>
|
||||
</data>
|
||||
<data name="LyricsSearchControlReset.Content" xml:space="preserve">
|
||||
<value>재설정</value>
|
||||
</data>
|
||||
<data name="LyricsSearchControlSaveChanges.Content" xml:space="preserve">
|
||||
<value>변경 사항 저장</value>
|
||||
</data>
|
||||
<data name="LyricsSearchControlSearch.Content" xml:space="preserve">
|
||||
<value>검색</value>
|
||||
</data>
|
||||
<data name="LyricsSearchControlSongInfoMapping.Header" xml:space="preserve">
|
||||
<value>노래 정보 매핑</value>
|
||||
</data>
|
||||
<data name="LyricsSearchControlTargetSearchProvider.Header" xml:space="preserve">
|
||||
<value>가사 검색 공급자를 타겟팅하십시오</value>
|
||||
</data>
|
||||
<data name="LyricsSearchControlTitle.Header" xml:space="preserve">
|
||||
<value>제목</value>
|
||||
</data>
|
||||
<data name="LyricsSearchPageTitle" xml:space="preserve">
|
||||
<value>가사 검색 - BetterLyrics</value>
|
||||
</data>
|
||||
<data name="LyricsSearchProviderEslrcFile" xml:space="preserve">
|
||||
<value>로컬 .ESLRC 파일</value>
|
||||
</data>
|
||||
@@ -403,6 +442,18 @@
|
||||
<data name="MusicGalleryPageTitle" xml:space="preserve">
|
||||
<value>음악 갤러리 - BetterLyrics</value>
|
||||
</data>
|
||||
<data name="SetingsPageDonation.Text" xml:space="preserve">
|
||||
<value>기부</value>
|
||||
</data>
|
||||
<data name="SetingsPageFeedback.Text" xml:space="preserve">
|
||||
<value>피드백</value>
|
||||
</data>
|
||||
<data name="SetingsPageRef.Text" xml:space="preserve">
|
||||
<value>사용 된 라이브러리</value>
|
||||
</data>
|
||||
<data name="SetingsPageThanks.Text" xml:space="preserve">
|
||||
<value>이 프로젝트가 마음에 들면 기부하여 지원을 고려하십시오. 귀하의 지원은 프로젝트를 계속 유지하고 추가 개발을 장려하는 데 도움이 될 것입니다.</value>
|
||||
</data>
|
||||
<data name="SettingsPageAbout.Content" xml:space="preserve">
|
||||
<value>에 대한</value>
|
||||
</data>
|
||||
@@ -439,6 +490,9 @@
|
||||
<data name="SettingsPageAmount.Header" xml:space="preserve">
|
||||
<value>금액</value>
|
||||
</data>
|
||||
<data name="SettingsPageAOT.Header" xml:space="preserve">
|
||||
<value>항상 위에</value>
|
||||
</data>
|
||||
<data name="SettingsPageApp.Content" xml:space="preserve">
|
||||
<value>앱 외관과 행동</value>
|
||||
</data>
|
||||
@@ -448,17 +502,8 @@
|
||||
<data name="SettingsPageAppBehavior.Text" xml:space="preserve">
|
||||
<value>앱 동작</value>
|
||||
</data>
|
||||
<data name="SettingsPageAppDesktop.Text" xml:space="preserve">
|
||||
<value>데스크탑 모드</value>
|
||||
</data>
|
||||
<data name="SettingsPageAppDock.Text" xml:space="preserve">
|
||||
<value>도크 모드</value>
|
||||
</data>
|
||||
<data name="SettingsPageAppPictureInPicture.Text" xml:space="preserve">
|
||||
<value>사진 인당 모드</value>
|
||||
</data>
|
||||
<data name="SettingsPageAppStandard.Text" xml:space="preserve">
|
||||
<value>표준 모드</value>
|
||||
<data name="SettingsPageApply.Content" xml:space="preserve">
|
||||
<value>적용하다</value>
|
||||
</data>
|
||||
<data name="SettingsPageAutoLock.Header" xml:space="preserve">
|
||||
<value>데스크탑 모드를 활성화 할 때 자동 잠금</value>
|
||||
@@ -485,7 +530,7 @@
|
||||
<value>가사 배경 자료</value>
|
||||
</data>
|
||||
<data name="SettingsPageBackgroundAcrylicEffectAmount.Header" xml:space="preserve">
|
||||
<value>앨범 배경 아크릴 효과 강도!</value>
|
||||
<value>앨범 배경 아크릴 효과 강도</value>
|
||||
</data>
|
||||
<data name="SettingsPageBackgroundOverlay.Content" xml:space="preserve">
|
||||
<value>가사 배경</value>
|
||||
@@ -496,22 +541,37 @@
|
||||
<data name="SettingsPageCache.Header" xml:space="preserve">
|
||||
<value>은닉처</value>
|
||||
</data>
|
||||
<data name="SettingsPageChinese.Header" xml:space="preserve">
|
||||
<value>화음</value>
|
||||
</data>
|
||||
<data name="SettingsPageChinesePreference.Header" xml:space="preserve">
|
||||
<value>중국어를 전통적인 중국어로 전환합니다</value>
|
||||
</data>
|
||||
<data name="SettingsPageCompactTitleBar.Content" xml:space="preserve">
|
||||
<value>콤팩트</value>
|
||||
</data>
|
||||
<data name="SettingsPageCurrentLyricsWindowStatus.Text" xml:space="preserve">
|
||||
<value>현재 가사 창 상태</value>
|
||||
</data>
|
||||
<data name="SettingsPageDark.Content" xml:space="preserve">
|
||||
<value>어두운</value>
|
||||
</data>
|
||||
<data name="SettingsPageDebugOverlay.Header" xml:space="preserve">
|
||||
<value>디버그 오버레이를 표시하십시오</value>
|
||||
</data>
|
||||
<data name="SettingsPageDelete.Content" xml:space="preserve">
|
||||
<value>삭제</value>
|
||||
</data>
|
||||
<data name="SettingsPageDesktopAcrylic.Content" xml:space="preserve">
|
||||
<value>데스크탑 아크릴</value>
|
||||
</data>
|
||||
<data name="SettingsPageDev.Content" xml:space="preserve">
|
||||
<value>고급 옵션</value>
|
||||
</data>
|
||||
<data name="SettingsPageDiscord.Header" xml:space="preserve">
|
||||
<data name="SettingsPageDisclaimer.Text" xml:space="preserve">
|
||||
<value>이 프로젝트는 어떠한 종류의 보증도 없이 그대로 제공됩니다. 모든 가사, 글꼴, 아이콘 및 기타 제3자 리소스는 해당 저작권 소유자의 재산입니다. 이 프로젝트의 저자는 그러한 자원의 소유권을 주장하지 않습니다. 이 프로젝트는 비상업적이기 때문에 어떠한 권리도 침해해서는 안 됩니다. 사용자는 자신의 사용이 관련 법률 및 라이센스를 준수하는지 확인할 책임이 있습니다.</value>
|
||||
</data>
|
||||
<data name="SettingsPageDiscord.Content" xml:space="preserve">
|
||||
<value>Discord</value>
|
||||
</data>
|
||||
<data name="SettingsPageDisplayTypeSwitcher.Header" xml:space="preserve">
|
||||
@@ -532,6 +592,9 @@
|
||||
<data name="SettingsPageDockWindowHeight.Header" xml:space="preserve">
|
||||
<value>창 높이</value>
|
||||
</data>
|
||||
<data name="SettingsPageDynamicLyricsFontSize.Header" xml:space="preserve">
|
||||
<value>자동 조정</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingFuncType.Header" xml:space="preserve">
|
||||
<value>애니메이션 유형 완화</value>
|
||||
</data>
|
||||
@@ -586,7 +649,7 @@
|
||||
<data name="SettingsPageFan.Header" xml:space="preserve">
|
||||
<value>팬 가사</value>
|
||||
</data>
|
||||
<data name="SettingsPageFAQ.Header" xml:space="preserve">
|
||||
<data name="SettingsPageFAQ.Content" xml:space="preserve">
|
||||
<value>자주 묻는 질문</value>
|
||||
</data>
|
||||
<data name="SettingsPageFixedTimeStep.Header" xml:space="preserve">
|
||||
@@ -598,15 +661,6 @@
|
||||
<data name="SettingsPageFPS.Header" xml:space="preserve">
|
||||
<value>렌더링 프레임 속도</value>
|
||||
</data>
|
||||
<data name="SettingsPageGitHub.ActionIconToolTip" xml:space="preserve">
|
||||
<value>새 창에서 열립니다</value>
|
||||
</data>
|
||||
<data name="SettingsPageGitHub.Description" xml:space="preserve">
|
||||
<value>GitHub의 소스 코드를 참조하십시오</value>
|
||||
</data>
|
||||
<data name="SettingsPageGitHub.Header" xml:space="preserve">
|
||||
<value>이것은 오픈 소스 앱입니다</value>
|
||||
</data>
|
||||
<data name="SettingsPageGlobalDrag.Description" xml:space="preserve">
|
||||
<value>비 중과 영역에서 창을 드래그 할 수 있도록 제목 표시 줄을 전체 페이지로 확장하십시오.</value>
|
||||
</data>
|
||||
@@ -614,10 +668,10 @@
|
||||
<value>글로벌 드래그</value>
|
||||
</data>
|
||||
<data name="SettingsPageHideWindow.Description" xml:space="preserve">
|
||||
<value>도크 모드 또는 데스크탑 모드에서 재생되지 않을 때는 창을 자동으로 숨기고 있습니다</value>
|
||||
<value>도킹 모드 또는 데스크탑 모드에서는 노래가 재생되지 않으면 창이 자동으로 숨겨집니다. 그렇지 않으면 창이 자동으로 표시됩니다.</value>
|
||||
</data>
|
||||
<data name="SettingsPageHideWindow.Header" xml:space="preserve">
|
||||
<value>자동 가죽 창</value>
|
||||
<value>Windows를 자동으로 숨기고 표시합니다</value>
|
||||
</data>
|
||||
<data name="SettingsPageIgnoreFullscreenWindow.Description" xml:space="preserve">
|
||||
<value>도킹 또는 데스크탑 모드가 활성화 될 때이 앱이 전체 화면 앱 위에 나타나도록 강요</value>
|
||||
@@ -634,9 +688,15 @@
|
||||
<data name="SettingsPageJA.Content" xml:space="preserve">
|
||||
<value>日本語</value>
|
||||
</data>
|
||||
<data name="SettingsPageJapanese.Header" xml:space="preserve">
|
||||
<value>일본 주석</value>
|
||||
</data>
|
||||
<data name="SettingsPageJoinNowButton.Content" xml:space="preserve">
|
||||
<value>지금 가입하십시오</value>
|
||||
</data>
|
||||
<data name="SettingsPageJyutping.Content" xml:space="preserve">
|
||||
<value>광동어 Pinyin</value>
|
||||
</data>
|
||||
<data name="SettingsPageKO.Content" xml:space="preserve">
|
||||
<value>한국어</value>
|
||||
</data>
|
||||
@@ -695,13 +755,13 @@
|
||||
<value>가사 배경</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsBackgroundBlurAmount.Header" xml:space="preserve">
|
||||
<value>앨범 배경 레이어 모호성!</value>
|
||||
<value>앨범 배경 레이어 모호성</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsBackgroundOpacity.Header" xml:space="preserve">
|
||||
<value>앨범 배경 레이어 불투명도!</value>
|
||||
<value>앨범 배경 레이어 불투명도</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsBackgroundSpeed.Header" xml:space="preserve">
|
||||
<value>앨범 배경 레이어 모션 속도!</value>
|
||||
<value>앨범 배경 레이어 모션 속도</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsBgFontColor.Header" xml:space="preserve">
|
||||
<value>글꼴 색상 (비 전류 재생 영역)</value>
|
||||
@@ -838,6 +898,9 @@
|
||||
<data name="SettingsPageLyricsThin.Content" xml:space="preserve">
|
||||
<value>얇은</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsTimeline.Header" xml:space="preserve">
|
||||
<value>가사 타임라인 동기화</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsTimelineThreshold.Description" xml:space="preserve">
|
||||
<value>가사 진행 상황이 불안하다면이 임계 값을 높이십시오. 이 값을 변경하면 가사가 동기화 될 수 있습니다</value>
|
||||
</data>
|
||||
@@ -853,6 +916,9 @@
|
||||
<data name="SettingsPageLyricsVerticalEdgeOpacity.Header" xml:space="preserve">
|
||||
<value>상단 및 하단 가장자리 불투명도</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsWindowManager.Header" xml:space="preserve">
|
||||
<value>가사 창 관리자</value>
|
||||
</data>
|
||||
<data name="SettingsPageMediaLib.Content" xml:space="preserve">
|
||||
<value>미디어 라이브러리</value>
|
||||
</data>
|
||||
@@ -898,6 +964,9 @@
|
||||
<data name="SettingsPagePathNotFound.Text" xml:space="preserve">
|
||||
<value>경로는 컴퓨터에서 찾을 수 없습니다</value>
|
||||
</data>
|
||||
<data name="SettingsPagePinyin.Content" xml:space="preserve">
|
||||
<value>만다린의 피니 인</value>
|
||||
</data>
|
||||
<data name="SettingsPagePlaybackLib.Content" xml:space="preserve">
|
||||
<value>재생 소스</value>
|
||||
</data>
|
||||
@@ -916,9 +985,15 @@
|
||||
<data name="SettingsPagePreviousSongHotKey.Header" xml:space="preserve">
|
||||
<value>이전 트랙의 바로 가기 키</value>
|
||||
</data>
|
||||
<data name="SettingsPageQQGroup.Header" xml:space="preserve">
|
||||
<data name="SettingsPageQQGroup.Content" xml:space="preserve">
|
||||
<value>QQ 피드백 및 채팅 그룹</value>
|
||||
</data>
|
||||
<data name="SettingsPageRecord.Content" xml:space="preserve">
|
||||
<value>기록</value>
|
||||
</data>
|
||||
<data name="SettingsPageRecordedWindowStatus.Text" xml:space="preserve">
|
||||
<value>기록 된 창 상태</value>
|
||||
</data>
|
||||
<data name="SettingsPageRemoveInfo.Message" xml:space="preserve">
|
||||
<value>이 경로의 원본 파일과 폴더는이 앱에서 제거 할 때 삭제되지 않습니다.</value>
|
||||
</data>
|
||||
@@ -931,6 +1006,9 @@
|
||||
<data name="SettingsPageRestart.Content" xml:space="preserve">
|
||||
<value>변경 사항을 적용하려면 앱을 다시 시작하십시오</value>
|
||||
</data>
|
||||
<data name="SettingsPageRomaji.Header" xml:space="preserve">
|
||||
<value>일본 주석</value>
|
||||
</data>
|
||||
<data name="SettingsPageSC.Content" xml:space="preserve">
|
||||
<value>简体中文</value>
|
||||
</data>
|
||||
@@ -973,6 +1051,9 @@
|
||||
<data name="SettingsPageShortcutRegSuccessInfo" xml:space="preserve">
|
||||
<value>이 핫키는 성공적으로 등록되었습니다</value>
|
||||
</data>
|
||||
<data name="SettingsPageShowHideHotKey.Header" xml:space="preserve">
|
||||
<value>가사 창 디스플레이 및 바로 가기 키 숨기기</value>
|
||||
</data>
|
||||
<data name="SettingsPageSliderPrefix.Text" xml:space="preserve">
|
||||
<value>현재 가치 : </value>
|
||||
</data>
|
||||
@@ -1000,7 +1081,7 @@
|
||||
<data name="SettingsPageTC.Content" xml:space="preserve">
|
||||
<value>繁體中文</value>
|
||||
</data>
|
||||
<data name="SettingsPageTelegram.Header" xml:space="preserve">
|
||||
<data name="SettingsPageTelegram.Content" xml:space="preserve">
|
||||
<value>Telegram</value>
|
||||
</data>
|
||||
<data name="SettingsPageTheme.Header" xml:space="preserve">
|
||||
|
||||
@@ -135,8 +135,8 @@
|
||||
<data name="AllLyricsSettingsControlStandard.Content" xml:space="preserve">
|
||||
<value>标准模式</value>
|
||||
</data>
|
||||
<data name="BaseWindowAOTFlyoutItem.Text" xml:space="preserve">
|
||||
<value>将应用置于顶层</value>
|
||||
<data name="AppSettingsControlGeneral.Content" xml:space="preserve">
|
||||
<value>通用</value>
|
||||
</data>
|
||||
<data name="BaseWindowEnterFullScreenHint" xml:space="preserve">
|
||||
<value>按 Esc 退出全屏模式</value>
|
||||
@@ -219,6 +219,9 @@
|
||||
<data name="LyricsPageLyricsProviderPrefix.Header" xml:space="preserve">
|
||||
<value>歌词来源</value>
|
||||
</data>
|
||||
<data name="LyricsPageLyricsSearchButtonToolTip.Content" xml:space="preserve">
|
||||
<value>手动检索歌词</value>
|
||||
</data>
|
||||
<data name="LyricsPageLyricsSettingsButtonToolTip.Content" xml:space="preserve">
|
||||
<value>歌词样式与效果快捷设置</value>
|
||||
</data>
|
||||
@@ -249,6 +252,42 @@
|
||||
<data name="LyricsPageTranslationProviderPrefix.Header" xml:space="preserve">
|
||||
<value>翻译来源</value>
|
||||
</data>
|
||||
<data name="LyricsSearchControlArtist.Header" xml:space="preserve">
|
||||
<value>艺术家</value>
|
||||
</data>
|
||||
<data name="LyricsSearchControlHelp.Text" xml:space="preserve">
|
||||
<value>* 保存更改立即生效,此后将以映射信息和目标歌词源检索该曲目歌词;标记为纯音乐将直接返回纯音乐占位歌词。重置以按原始数据检索。</value>
|
||||
</data>
|
||||
<data name="LyricsSearchControlMappedAs.Text" xml:space="preserve">
|
||||
<value>映射为</value>
|
||||
</data>
|
||||
<data name="LyricsSearchControlMarkAsPureMusic.Content" xml:space="preserve">
|
||||
<value>标记为纯音乐</value>
|
||||
</data>
|
||||
<data name="LyricsSearchControlNotFound.Text" xml:space="preserve">
|
||||
<value>未找到</value>
|
||||
</data>
|
||||
<data name="LyricsSearchControlReset.Content" xml:space="preserve">
|
||||
<value>重置</value>
|
||||
</data>
|
||||
<data name="LyricsSearchControlSaveChanges.Content" xml:space="preserve">
|
||||
<value>保存更改</value>
|
||||
</data>
|
||||
<data name="LyricsSearchControlSearch.Content" xml:space="preserve">
|
||||
<value>搜索</value>
|
||||
</data>
|
||||
<data name="LyricsSearchControlSongInfoMapping.Header" xml:space="preserve">
|
||||
<value>歌曲信息映射</value>
|
||||
</data>
|
||||
<data name="LyricsSearchControlTargetSearchProvider.Header" xml:space="preserve">
|
||||
<value>目标歌词搜索提供商</value>
|
||||
</data>
|
||||
<data name="LyricsSearchControlTitle.Header" xml:space="preserve">
|
||||
<value>标题</value>
|
||||
</data>
|
||||
<data name="LyricsSearchPageTitle" xml:space="preserve">
|
||||
<value>歌词搜索 - BetterLyrics</value>
|
||||
</data>
|
||||
<data name="LyricsSearchProviderEslrcFile" xml:space="preserve">
|
||||
<value>本地 .ESLRC 文件</value>
|
||||
</data>
|
||||
@@ -403,6 +442,18 @@
|
||||
<data name="MusicGalleryPageTitle" xml:space="preserve">
|
||||
<value>音乐库 - BetterLyrics</value>
|
||||
</data>
|
||||
<data name="SetingsPageDonation.Text" xml:space="preserve">
|
||||
<value>捐贈</value>
|
||||
</data>
|
||||
<data name="SetingsPageFeedback.Text" xml:space="preserve">
|
||||
<value>反馈</value>
|
||||
</data>
|
||||
<data name="SetingsPageRef.Text" xml:space="preserve">
|
||||
<value>使用的库</value>
|
||||
</data>
|
||||
<data name="SetingsPageThanks.Text" xml:space="preserve">
|
||||
<value>如果您喜欢这个项目,请考虑通过捐赠来支持它。您的支持将有助于保持项目的生命并鼓励进一步的发展。</value>
|
||||
</data>
|
||||
<data name="SettingsPageAbout.Content" xml:space="preserve">
|
||||
<value>关于</value>
|
||||
</data>
|
||||
@@ -439,6 +490,9 @@
|
||||
<data name="SettingsPageAmount.Header" xml:space="preserve">
|
||||
<value>量</value>
|
||||
</data>
|
||||
<data name="SettingsPageAOT.Header" xml:space="preserve">
|
||||
<value>将应用置于顶层</value>
|
||||
</data>
|
||||
<data name="SettingsPageApp.Content" xml:space="preserve">
|
||||
<value>应用外观与行为</value>
|
||||
</data>
|
||||
@@ -448,17 +502,8 @@
|
||||
<data name="SettingsPageAppBehavior.Text" xml:space="preserve">
|
||||
<value>应用行为</value>
|
||||
</data>
|
||||
<data name="SettingsPageAppDesktop.Text" xml:space="preserve">
|
||||
<value>桌面模式</value>
|
||||
</data>
|
||||
<data name="SettingsPageAppDock.Text" xml:space="preserve">
|
||||
<value>停靠模式</value>
|
||||
</data>
|
||||
<data name="SettingsPageAppPictureInPicture.Text" xml:space="preserve">
|
||||
<value>画中画模式</value>
|
||||
</data>
|
||||
<data name="SettingsPageAppStandard.Text" xml:space="preserve">
|
||||
<value>标准模式</value>
|
||||
<data name="SettingsPageApply.Content" xml:space="preserve">
|
||||
<value>应用</value>
|
||||
</data>
|
||||
<data name="SettingsPageAutoLock.Header" xml:space="preserve">
|
||||
<value>启动桌面模式时随即锁定窗口</value>
|
||||
@@ -496,22 +541,37 @@
|
||||
<data name="SettingsPageCache.Header" xml:space="preserve">
|
||||
<value>缓存</value>
|
||||
</data>
|
||||
<data name="SettingsPageChinese.Header" xml:space="preserve">
|
||||
<value>中文注音</value>
|
||||
</data>
|
||||
<data name="SettingsPageChinesePreference.Header" xml:space="preserve">
|
||||
<value>中文转换为繁体</value>
|
||||
</data>
|
||||
<data name="SettingsPageCompactTitleBar.Content" xml:space="preserve">
|
||||
<value>紧凑</value>
|
||||
</data>
|
||||
<data name="SettingsPageCurrentLyricsWindowStatus.Text" xml:space="preserve">
|
||||
<value>当前歌词窗口状态</value>
|
||||
</data>
|
||||
<data name="SettingsPageDark.Content" xml:space="preserve">
|
||||
<value>深色</value>
|
||||
</data>
|
||||
<data name="SettingsPageDebugOverlay.Header" xml:space="preserve">
|
||||
<value>显示调试覆盖层</value>
|
||||
</data>
|
||||
<data name="SettingsPageDelete.Content" xml:space="preserve">
|
||||
<value>删除</value>
|
||||
</data>
|
||||
<data name="SettingsPageDesktopAcrylic.Content" xml:space="preserve">
|
||||
<value>亚克力(桌面)</value>
|
||||
</data>
|
||||
<data name="SettingsPageDev.Content" xml:space="preserve">
|
||||
<value>高级选项</value>
|
||||
</data>
|
||||
<data name="SettingsPageDiscord.Header" xml:space="preserve">
|
||||
<data name="SettingsPageDisclaimer.Text" xml:space="preserve">
|
||||
<value>本项目按原样提供,不提供任何形式的保证。所有歌词、字体、图标和其他第三方资源均为其各自版权所有者的财产。本项目的作者不主张此类资源的所有权。本项目为非商业性项目,不得用于侵犯任何权利。用户有责任确保自己的使用符合适用的法律和许可。</value>
|
||||
</data>
|
||||
<data name="SettingsPageDiscord.Content" xml:space="preserve">
|
||||
<value>Discord</value>
|
||||
</data>
|
||||
<data name="SettingsPageDisplayTypeSwitcher.Header" xml:space="preserve">
|
||||
@@ -532,6 +592,9 @@
|
||||
<data name="SettingsPageDockWindowHeight.Header" xml:space="preserve">
|
||||
<value>窗口高度</value>
|
||||
</data>
|
||||
<data name="SettingsPageDynamicLyricsFontSize.Header" xml:space="preserve">
|
||||
<value>自动调整</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingFuncType.Header" xml:space="preserve">
|
||||
<value>缓动动画类型</value>
|
||||
</data>
|
||||
@@ -586,7 +649,7 @@
|
||||
<data name="SettingsPageFan.Header" xml:space="preserve">
|
||||
<value>扇形歌词</value>
|
||||
</data>
|
||||
<data name="SettingsPageFAQ.Header" xml:space="preserve">
|
||||
<data name="SettingsPageFAQ.Content" xml:space="preserve">
|
||||
<value>常见问题与解答</value>
|
||||
</data>
|
||||
<data name="SettingsPageFixedTimeStep.Header" xml:space="preserve">
|
||||
@@ -598,15 +661,6 @@
|
||||
<data name="SettingsPageFPS.Header" xml:space="preserve">
|
||||
<value>渲染帧率</value>
|
||||
</data>
|
||||
<data name="SettingsPageGitHub.ActionIconToolTip" xml:space="preserve">
|
||||
<value>在新窗口中打开</value>
|
||||
</data>
|
||||
<data name="SettingsPageGitHub.Description" xml:space="preserve">
|
||||
<value>在 GitHub 上查看源代码</value>
|
||||
</data>
|
||||
<data name="SettingsPageGitHub.Header" xml:space="preserve">
|
||||
<value>此应用已开源</value>
|
||||
</data>
|
||||
<data name="SettingsPageGlobalDrag.Description" xml:space="preserve">
|
||||
<value>将标题栏扩展至整个页面使得在任意非交互区域均可拖拽窗口</value>
|
||||
</data>
|
||||
@@ -614,10 +668,10 @@
|
||||
<value>全局拖拽</value>
|
||||
</data>
|
||||
<data name="SettingsPageHideWindow.Description" xml:space="preserve">
|
||||
<value>停靠模式或桌面模式下,无歌曲正在播放时,自动隐藏窗口</value>
|
||||
<value>停靠模式或桌面模式下,无歌曲正在播放时,自动隐藏窗口;反之自动显示窗口</value>
|
||||
</data>
|
||||
<data name="SettingsPageHideWindow.Header" xml:space="preserve">
|
||||
<value>自动隐藏窗口</value>
|
||||
<value>自动隐藏/显示窗口</value>
|
||||
</data>
|
||||
<data name="SettingsPageIgnoreFullscreenWindow.Description" xml:space="preserve">
|
||||
<value>当启用停靠模式或桌面模式时强制将本应用显示在全屏应用的上方</value>
|
||||
@@ -634,9 +688,15 @@
|
||||
<data name="SettingsPageJA.Content" xml:space="preserve">
|
||||
<value>日本語</value>
|
||||
</data>
|
||||
<data name="SettingsPageJapanese.Header" xml:space="preserve">
|
||||
<value>日语注音</value>
|
||||
</data>
|
||||
<data name="SettingsPageJoinNowButton.Content" xml:space="preserve">
|
||||
<value>立即加入</value>
|
||||
</data>
|
||||
<data name="SettingsPageJyutping.Content" xml:space="preserve">
|
||||
<value>广东话拼音</value>
|
||||
</data>
|
||||
<data name="SettingsPageKO.Content" xml:space="preserve">
|
||||
<value>한국어</value>
|
||||
</data>
|
||||
@@ -838,6 +898,9 @@
|
||||
<data name="SettingsPageLyricsThin.Content" xml:space="preserve">
|
||||
<value>极细</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsTimeline.Header" xml:space="preserve">
|
||||
<value>歌词时间轴同步</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsTimelineThreshold.Description" xml:space="preserve">
|
||||
<value>当歌词进度抖动时,请尝试增加该阈值;更改此值会导致歌词同步有偏差</value>
|
||||
</data>
|
||||
@@ -853,6 +916,9 @@
|
||||
<data name="SettingsPageLyricsVerticalEdgeOpacity.Header" xml:space="preserve">
|
||||
<value>上下边缘不透明度</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsWindowManager.Header" xml:space="preserve">
|
||||
<value>歌词窗口管理</value>
|
||||
</data>
|
||||
<data name="SettingsPageMediaLib.Content" xml:space="preserve">
|
||||
<value>媒体库</value>
|
||||
</data>
|
||||
@@ -898,6 +964,9 @@
|
||||
<data name="SettingsPagePathNotFound.Text" xml:space="preserve">
|
||||
<value>无法在您的计算机中找到该路径</value>
|
||||
</data>
|
||||
<data name="SettingsPagePinyin.Content" xml:space="preserve">
|
||||
<value>普通话拼音</value>
|
||||
</data>
|
||||
<data name="SettingsPagePlaybackLib.Content" xml:space="preserve">
|
||||
<value>播放源</value>
|
||||
</data>
|
||||
@@ -916,9 +985,15 @@
|
||||
<data name="SettingsPagePreviousSongHotKey.Header" xml:space="preserve">
|
||||
<value>上一首曲目快捷键</value>
|
||||
</data>
|
||||
<data name="SettingsPageQQGroup.Header" xml:space="preserve">
|
||||
<data name="SettingsPageQQGroup.Content" xml:space="preserve">
|
||||
<value>QQ 反馈交流群</value>
|
||||
</data>
|
||||
<data name="SettingsPageRecord.Content" xml:space="preserve">
|
||||
<value>记录</value>
|
||||
</data>
|
||||
<data name="SettingsPageRecordedWindowStatus.Text" xml:space="preserve">
|
||||
<value>记录的窗口状态</value>
|
||||
</data>
|
||||
<data name="SettingsPageRemoveInfo.Message" xml:space="preserve">
|
||||
<value>路径中的原始文件和文件夹不会被删除</value>
|
||||
</data>
|
||||
@@ -931,6 +1006,9 @@
|
||||
<data name="SettingsPageRestart.Content" xml:space="preserve">
|
||||
<value>重启应用以应用更改</value>
|
||||
</data>
|
||||
<data name="SettingsPageRomaji.Header" xml:space="preserve">
|
||||
<value>日语注音</value>
|
||||
</data>
|
||||
<data name="SettingsPageSC.Content" xml:space="preserve">
|
||||
<value>简体中文</value>
|
||||
</data>
|
||||
@@ -973,6 +1051,9 @@
|
||||
<data name="SettingsPageShortcutRegSuccessInfo" xml:space="preserve">
|
||||
<value>该热键已成功注册</value>
|
||||
</data>
|
||||
<data name="SettingsPageShowHideHotKey.Header" xml:space="preserve">
|
||||
<value>歌词窗口显示和隐藏快捷键</value>
|
||||
</data>
|
||||
<data name="SettingsPageSliderPrefix.Text" xml:space="preserve">
|
||||
<value>当前值: </value>
|
||||
</data>
|
||||
@@ -1000,7 +1081,7 @@
|
||||
<data name="SettingsPageTC.Content" xml:space="preserve">
|
||||
<value>繁體中文</value>
|
||||
</data>
|
||||
<data name="SettingsPageTelegram.Header" xml:space="preserve">
|
||||
<data name="SettingsPageTelegram.Content" xml:space="preserve">
|
||||
<value>Telegram</value>
|
||||
</data>
|
||||
<data name="SettingsPageTheme.Header" xml:space="preserve">
|
||||
|
||||
@@ -135,8 +135,8 @@
|
||||
<data name="AllLyricsSettingsControlStandard.Content" xml:space="preserve">
|
||||
<value>標準模式</value>
|
||||
</data>
|
||||
<data name="BaseWindowAOTFlyoutItem.Text" xml:space="preserve">
|
||||
<value>將應用置於頂層</value>
|
||||
<data name="AppSettingsControlGeneral.Content" xml:space="preserve">
|
||||
<value>一般</value>
|
||||
</data>
|
||||
<data name="BaseWindowEnterFullScreenHint" xml:space="preserve">
|
||||
<value>按 Esc 退出全螢幕模式</value>
|
||||
@@ -219,6 +219,9 @@
|
||||
<data name="LyricsPageLyricsProviderPrefix.Header" xml:space="preserve">
|
||||
<value>歌詞來源</value>
|
||||
</data>
|
||||
<data name="LyricsPageLyricsSearchButtonToolTip.Content" xml:space="preserve">
|
||||
<value>手動檢索歌詞</value>
|
||||
</data>
|
||||
<data name="LyricsPageLyricsSettingsButtonToolTip.Content" xml:space="preserve">
|
||||
<value>歌詞樣式與效果快捷設置</value>
|
||||
</data>
|
||||
@@ -249,6 +252,42 @@
|
||||
<data name="LyricsPageTranslationProviderPrefix.Header" xml:space="preserve">
|
||||
<value>翻譯來源</value>
|
||||
</data>
|
||||
<data name="LyricsSearchControlArtist.Header" xml:space="preserve">
|
||||
<value>藝術家</value>
|
||||
</data>
|
||||
<data name="LyricsSearchControlHelp.Text" xml:space="preserve">
|
||||
<value>* 保存更改立即生效,此後將以映射信息和目標歌詞源檢索該曲目歌詞;標記為純音樂將直接返回純音樂佔位歌詞。重置以按原始數據檢索。</value>
|
||||
</data>
|
||||
<data name="LyricsSearchControlMappedAs.Text" xml:space="preserve">
|
||||
<value>映射爲</value>
|
||||
</data>
|
||||
<data name="LyricsSearchControlMarkAsPureMusic.Content" xml:space="preserve">
|
||||
<value>標記為純音樂</value>
|
||||
</data>
|
||||
<data name="LyricsSearchControlNotFound.Text" xml:space="preserve">
|
||||
<value>找不到</value>
|
||||
</data>
|
||||
<data name="LyricsSearchControlReset.Content" xml:space="preserve">
|
||||
<value>重設</value>
|
||||
</data>
|
||||
<data name="LyricsSearchControlSaveChanges.Content" xml:space="preserve">
|
||||
<value>保存更改</value>
|
||||
</data>
|
||||
<data name="LyricsSearchControlSearch.Content" xml:space="preserve">
|
||||
<value>搜索</value>
|
||||
</data>
|
||||
<data name="LyricsSearchControlSongInfoMapping.Header" xml:space="preserve">
|
||||
<value>歌曲信息映射</value>
|
||||
</data>
|
||||
<data name="LyricsSearchControlTargetSearchProvider.Header" xml:space="preserve">
|
||||
<value>目標歌詞搜尋提供者</value>
|
||||
</data>
|
||||
<data name="LyricsSearchControlTitle.Header" xml:space="preserve">
|
||||
<value>標題</value>
|
||||
</data>
|
||||
<data name="LyricsSearchPageTitle" xml:space="preserve">
|
||||
<value>歌詞搜尋 - BetterLyrics</value>
|
||||
</data>
|
||||
<data name="LyricsSearchProviderEslrcFile" xml:space="preserve">
|
||||
<value>本地 .ESLRC 文件</value>
|
||||
</data>
|
||||
@@ -403,6 +442,18 @@
|
||||
<data name="MusicGalleryPageTitle" xml:space="preserve">
|
||||
<value>音樂庫 - BetterLyrics</value>
|
||||
</data>
|
||||
<data name="SetingsPageDonation.Text" xml:space="preserve">
|
||||
<value>捐贈</value>
|
||||
</data>
|
||||
<data name="SetingsPageFeedback.Text" xml:space="preserve">
|
||||
<value>回饋</value>
|
||||
</data>
|
||||
<data name="SetingsPageRef.Text" xml:space="preserve">
|
||||
<value>使用的庫</value>
|
||||
</data>
|
||||
<data name="SetingsPageThanks.Text" xml:space="preserve">
|
||||
<value>如果您喜歡這個項目,請考慮通過捐贈來支持它。您的支持將有助於保持項目的生命並鼓勵進一步的發展。</value>
|
||||
</data>
|
||||
<data name="SettingsPageAbout.Content" xml:space="preserve">
|
||||
<value>關於</value>
|
||||
</data>
|
||||
@@ -439,6 +490,9 @@
|
||||
<data name="SettingsPageAmount.Header" xml:space="preserve">
|
||||
<value>量</value>
|
||||
</data>
|
||||
<data name="SettingsPageAOT.Header" xml:space="preserve">
|
||||
<value>將應用置於頂層</value>
|
||||
</data>
|
||||
<data name="SettingsPageApp.Content" xml:space="preserve">
|
||||
<value>應用外觀與行為</value>
|
||||
</data>
|
||||
@@ -448,17 +502,8 @@
|
||||
<data name="SettingsPageAppBehavior.Text" xml:space="preserve">
|
||||
<value>應用行為</value>
|
||||
</data>
|
||||
<data name="SettingsPageAppDesktop.Text" xml:space="preserve">
|
||||
<value>桌面模式</value>
|
||||
</data>
|
||||
<data name="SettingsPageAppDock.Text" xml:space="preserve">
|
||||
<value>停靠模式</value>
|
||||
</data>
|
||||
<data name="SettingsPageAppPictureInPicture.Text" xml:space="preserve">
|
||||
<value>畫中畫模式</value>
|
||||
</data>
|
||||
<data name="SettingsPageAppStandard.Text" xml:space="preserve">
|
||||
<value>標準模式</value>
|
||||
<data name="SettingsPageApply.Content" xml:space="preserve">
|
||||
<value>應用</value>
|
||||
</data>
|
||||
<data name="SettingsPageAutoLock.Header" xml:space="preserve">
|
||||
<value>啟動桌面模式時隨即鎖定窗口</value>
|
||||
@@ -485,7 +530,7 @@
|
||||
<value>歌詞背景材質</value>
|
||||
</data>
|
||||
<data name="SettingsPageBackgroundAcrylicEffectAmount.Header" xml:space="preserve">
|
||||
<value>專輯背景壓克力效果強度!</value>
|
||||
<value>專輯背景壓克力效果強度</value>
|
||||
</data>
|
||||
<data name="SettingsPageBackgroundOverlay.Content" xml:space="preserve">
|
||||
<value>歌詞背景</value>
|
||||
@@ -496,22 +541,37 @@
|
||||
<data name="SettingsPageCache.Header" xml:space="preserve">
|
||||
<value>快取</value>
|
||||
</data>
|
||||
<data name="SettingsPageChinese.Header" xml:space="preserve">
|
||||
<value>中文注音</value>
|
||||
</data>
|
||||
<data name="SettingsPageChinesePreference.Header" xml:space="preserve">
|
||||
<value>中文轉換為繁體</value>
|
||||
</data>
|
||||
<data name="SettingsPageCompactTitleBar.Content" xml:space="preserve">
|
||||
<value>緊湊</value>
|
||||
</data>
|
||||
<data name="SettingsPageCurrentLyricsWindowStatus.Text" xml:space="preserve">
|
||||
<value>當前歌詞窗口狀態</value>
|
||||
</data>
|
||||
<data name="SettingsPageDark.Content" xml:space="preserve">
|
||||
<value>深色</value>
|
||||
</data>
|
||||
<data name="SettingsPageDebugOverlay.Header" xml:space="preserve">
|
||||
<value>顯示調試覆蓋層</value>
|
||||
</data>
|
||||
<data name="SettingsPageDelete.Content" xml:space="preserve">
|
||||
<value>刪除</value>
|
||||
</data>
|
||||
<data name="SettingsPageDesktopAcrylic.Content" xml:space="preserve">
|
||||
<value>亞克力(桌面)</value>
|
||||
</data>
|
||||
<data name="SettingsPageDev.Content" xml:space="preserve">
|
||||
<value>高級選項</value>
|
||||
</data>
|
||||
<data name="SettingsPageDiscord.Header" xml:space="preserve">
|
||||
<data name="SettingsPageDisclaimer.Text" xml:space="preserve">
|
||||
<value>本項目按原樣提供,不提供任何形式的保證。所有歌詞、字型、圖示和其他第三方資源均屬其各自的版權擁有者所有。此專案的作者並未聲明此類資源的所有權。此專案為非商業專案,不應用於侵犯任何權利。用戶有責任確保自己的使用符合適用的法律和許可證。</value>
|
||||
</data>
|
||||
<data name="SettingsPageDiscord.Content" xml:space="preserve">
|
||||
<value>Discord</value>
|
||||
</data>
|
||||
<data name="SettingsPageDisplayTypeSwitcher.Header" xml:space="preserve">
|
||||
@@ -532,6 +592,9 @@
|
||||
<data name="SettingsPageDockWindowHeight.Header" xml:space="preserve">
|
||||
<value>窗口高度</value>
|
||||
</data>
|
||||
<data name="SettingsPageDynamicLyricsFontSize.Header" xml:space="preserve">
|
||||
<value>自動調整</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingFuncType.Header" xml:space="preserve">
|
||||
<value>緩動動畫類型</value>
|
||||
</data>
|
||||
@@ -586,7 +649,7 @@
|
||||
<data name="SettingsPageFan.Header" xml:space="preserve">
|
||||
<value>扇形歌詞</value>
|
||||
</data>
|
||||
<data name="SettingsPageFAQ.Header" xml:space="preserve">
|
||||
<data name="SettingsPageFAQ.Content" xml:space="preserve">
|
||||
<value>常見問題與解答</value>
|
||||
</data>
|
||||
<data name="SettingsPageFixedTimeStep.Header" xml:space="preserve">
|
||||
@@ -598,15 +661,6 @@
|
||||
<data name="SettingsPageFPS.Header" xml:space="preserve">
|
||||
<value>渲染幀率</value>
|
||||
</data>
|
||||
<data name="SettingsPageGitHub.ActionIconToolTip" xml:space="preserve">
|
||||
<value>在新視窗中開啟</value>
|
||||
</data>
|
||||
<data name="SettingsPageGitHub.Description" xml:space="preserve">
|
||||
<value>在 GitHub 上查看原始碼</value>
|
||||
</data>
|
||||
<data name="SettingsPageGitHub.Header" xml:space="preserve">
|
||||
<value>此應用程式已開源</value>
|
||||
</data>
|
||||
<data name="SettingsPageGlobalDrag.Description" xml:space="preserve">
|
||||
<value>將標題列擴展至整個頁面使得在任意非互動區域均可拖曳窗口</value>
|
||||
</data>
|
||||
@@ -614,10 +668,10 @@
|
||||
<value>全域拖曳</value>
|
||||
</data>
|
||||
<data name="SettingsPageHideWindow.Description" xml:space="preserve">
|
||||
<value>停靠模式或桌面模式下,無歌曲正在播放時,自動隱藏窗口</value>
|
||||
<value>停靠模式或桌面模式下,無歌曲正在播放時,自動隱藏窗口;反之自動顯示窗口</value>
|
||||
</data>
|
||||
<data name="SettingsPageHideWindow.Header" xml:space="preserve">
|
||||
<value>自動隱藏窗口</value>
|
||||
<value>自動隱藏/顯示窗口</value>
|
||||
</data>
|
||||
<data name="SettingsPageIgnoreFullscreenWindow.Description" xml:space="preserve">
|
||||
<value>啟用停靠模式或桌面模式時強制將本應用程式顯示在全螢幕應用程式的上方</value>
|
||||
@@ -634,9 +688,15 @@
|
||||
<data name="SettingsPageJA.Content" xml:space="preserve">
|
||||
<value>日本語</value>
|
||||
</data>
|
||||
<data name="SettingsPageJapanese.Header" xml:space="preserve">
|
||||
<value>日語注音</value>
|
||||
</data>
|
||||
<data name="SettingsPageJoinNowButton.Content" xml:space="preserve">
|
||||
<value>立即加入</value>
|
||||
</data>
|
||||
<data name="SettingsPageJyutping.Content" xml:space="preserve">
|
||||
<value>廣東話拼音</value>
|
||||
</data>
|
||||
<data name="SettingsPageKO.Content" xml:space="preserve">
|
||||
<value>한국어</value>
|
||||
</data>
|
||||
@@ -695,13 +755,13 @@
|
||||
<value>歌詞背景</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsBackgroundBlurAmount.Header" xml:space="preserve">
|
||||
<value>專輯背景層模糊度!</value>
|
||||
<value>專輯背景層模糊度</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsBackgroundOpacity.Header" xml:space="preserve">
|
||||
<value>專輯背景層不透明度!</value>
|
||||
<value>專輯背景層不透明度</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsBackgroundSpeed.Header" xml:space="preserve">
|
||||
<value>專輯背景層運動速率!</value>
|
||||
<value>專輯背景層運動速率</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsBgFontColor.Header" xml:space="preserve">
|
||||
<value>字體顏色(非當前播放區域)</value>
|
||||
@@ -838,6 +898,9 @@
|
||||
<data name="SettingsPageLyricsThin.Content" xml:space="preserve">
|
||||
<value>極細</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsTimeline.Header" xml:space="preserve">
|
||||
<value>歌詞時間軌同步閾值</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsTimelineThreshold.Description" xml:space="preserve">
|
||||
<value>當歌詞進度抖動時,請嘗試增加該閾值;更改此值會導致歌詞同步偏差</value>
|
||||
</data>
|
||||
@@ -853,6 +916,9 @@
|
||||
<data name="SettingsPageLyricsVerticalEdgeOpacity.Header" xml:space="preserve">
|
||||
<value>上下邊緣不透明度</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsWindowManager.Header" xml:space="preserve">
|
||||
<value>歌詞視窗管理</value>
|
||||
</data>
|
||||
<data name="SettingsPageMediaLib.Content" xml:space="preserve">
|
||||
<value>媒體庫</value>
|
||||
</data>
|
||||
@@ -898,6 +964,9 @@
|
||||
<data name="SettingsPagePathNotFound.Text" xml:space="preserve">
|
||||
<value>無法在您的電腦中找到該路徑</value>
|
||||
</data>
|
||||
<data name="SettingsPagePinyin.Content" xml:space="preserve">
|
||||
<value>普通話拼音</value>
|
||||
</data>
|
||||
<data name="SettingsPagePlaybackLib.Content" xml:space="preserve">
|
||||
<value>播放源</value>
|
||||
</data>
|
||||
@@ -916,9 +985,15 @@
|
||||
<data name="SettingsPagePreviousSongHotKey.Header" xml:space="preserve">
|
||||
<value>上一首曲目快捷鍵</value>
|
||||
</data>
|
||||
<data name="SettingsPageQQGroup.Header" xml:space="preserve">
|
||||
<data name="SettingsPageQQGroup.Content" xml:space="preserve">
|
||||
<value>QQ 回饋交流群</value>
|
||||
</data>
|
||||
<data name="SettingsPageRecord.Content" xml:space="preserve">
|
||||
<value>記錄</value>
|
||||
</data>
|
||||
<data name="SettingsPageRecordedWindowStatus.Text" xml:space="preserve">
|
||||
<value>記錄的窗口狀態</value>
|
||||
</data>
|
||||
<data name="SettingsPageRemoveInfo.Message" xml:space="preserve">
|
||||
<value>路徑中的原始檔案和資料夾不會被刪除</value>
|
||||
</data>
|
||||
@@ -931,6 +1006,9 @@
|
||||
<data name="SettingsPageRestart.Content" xml:space="preserve">
|
||||
<value>重啟應用程式以應用更改</value>
|
||||
</data>
|
||||
<data name="SettingsPageRomaji.Header" xml:space="preserve">
|
||||
<value>日語注音</value>
|
||||
</data>
|
||||
<data name="SettingsPageSC.Content" xml:space="preserve">
|
||||
<value>简体中文</value>
|
||||
</data>
|
||||
@@ -973,6 +1051,9 @@
|
||||
<data name="SettingsPageShortcutRegSuccessInfo" xml:space="preserve">
|
||||
<value>該熱鍵已成功註冊</value>
|
||||
</data>
|
||||
<data name="SettingsPageShowHideHotKey.Header" xml:space="preserve">
|
||||
<value>歌詞窗口顯示和隱藏快捷鍵</value>
|
||||
</data>
|
||||
<data name="SettingsPageSliderPrefix.Text" xml:space="preserve">
|
||||
<value>目前值: </value>
|
||||
</data>
|
||||
@@ -1000,7 +1081,7 @@
|
||||
<data name="SettingsPageTC.Content" xml:space="preserve">
|
||||
<value>繁體中文</value>
|
||||
</data>
|
||||
<data name="SettingsPageTelegram.Header" xml:space="preserve">
|
||||
<data name="SettingsPageTelegram.Content" xml:space="preserve">
|
||||
<value>Telegram</value>
|
||||
</data>
|
||||
<data name="SettingsPageTheme.Header" xml:space="preserve">
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
{
|
||||
if (message.Sender is LiveStates)
|
||||
{
|
||||
if (message.PropertyName == nameof(LiveStates.CurrentLyricsWindowMode))
|
||||
if (message.PropertyName == nameof(LiveStates.LyricsWindowMode))
|
||||
{
|
||||
SelectedTabIndex = (int)message.NewValue;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
using BetterLyrics.WinUI3.Helper;
|
||||
using BetterLyrics.WinUI3.Models;
|
||||
using BetterLyrics.WinUI3.Models.Settings;
|
||||
using BetterLyrics.WinUI3.Services.LiveStatesService;
|
||||
using BetterLyrics.WinUI3.Services.SettingsService;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
@@ -13,19 +15,25 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
public partial class AppSettingsControlViewModel : BaseViewModel
|
||||
{
|
||||
private readonly ISettingsService _settingsService;
|
||||
private readonly ILiveStatesService _liveStatesService;
|
||||
|
||||
[ObservableProperty]
|
||||
public partial AppSettings AppSettings { get; set; }
|
||||
|
||||
[ObservableProperty]
|
||||
public partial LiveStates LiveStates { get; set; }
|
||||
|
||||
[ObservableProperty]
|
||||
public partial ObservableCollection<string> MonitorDeviceNames { get; set; }
|
||||
|
||||
|
||||
public AppSettingsControlViewModel(ISettingsService settingsService)
|
||||
public AppSettingsControlViewModel(ISettingsService settingsService, ILiveStatesService liveStatesService)
|
||||
{
|
||||
_settingsService = settingsService;
|
||||
_liveStatesService = liveStatesService;
|
||||
MonitorDeviceNames = [.. MonitorHelper.GetAllMonitorDeviceNames()];
|
||||
AppSettings = _settingsService.AppSettings;
|
||||
LiveStates = _liveStatesService.LiveStates;
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
@@ -41,6 +49,19 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
AppSettings.DockModeSettings.DockMonitorDeviceName = MonitorHelper.GetPrimaryMonitorDeviceName();
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void RecordCurrentWindowBounds()
|
||||
{
|
||||
AppSettings.WindowBoundsRecords.Add(new WindowBoundsRecord
|
||||
{
|
||||
WindowBounds = LiveStates.LyricsWindowBounds,
|
||||
MonitorDeviceName = LiveStates.LyricsWindowMonitorName,
|
||||
MonitorBounds = LiveStates.LyricsWindowMonitorBounds,
|
||||
DemoWindowBounds = LiveStates.DemoLyricsWindowBounds,
|
||||
DemoMonitorBounds = LiveStates.DemoLyricsWindowMonitorBounds
|
||||
});
|
||||
}
|
||||
|
||||
public async Task<bool> ToggleAutoStartupAsync(bool target)
|
||||
{
|
||||
StartupTask startupTask = await StartupTask.GetAsync(Constants.App.AutoStartupTaskId);
|
||||
|
||||
@@ -102,6 +102,15 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
[ObservableProperty]
|
||||
public partial bool IsSongPlaying { get; set; }
|
||||
|
||||
[ObservableProperty]
|
||||
public partial float TimelineSliderThumbOpacity { get; set; } = 0f;
|
||||
|
||||
[ObservableProperty]
|
||||
public partial LyricsLine? TimelineSliderThumbLyricsLine { get; set; }
|
||||
|
||||
[ObservableProperty]
|
||||
public partial double TimelineSliderThumbSeconds { get; set; } = 0;
|
||||
|
||||
public void Receive(PropertyChangedMessage<bool> message)
|
||||
{
|
||||
if (message.Sender is LyricsWindowViewModel)
|
||||
@@ -157,6 +166,11 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
partial void OnTimelineSliderThumbSecondsChanged(double value)
|
||||
{
|
||||
TimelineSliderThumbLyricsLine = _mediaSessionsService.CurrentLyricsData?.GetLyricsLine(value);
|
||||
}
|
||||
|
||||
//partial void OnVolumeChanged(int value)
|
||||
//{
|
||||
// SystemVolumeHelper.SetMasterVolume(value);
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
||||
using var combined = new CanvasCommandList(control);
|
||||
using var combinedDs = combined.CreateDrawingSession();
|
||||
|
||||
switch (_liveStatesService.LiveStates.CurrentLyricsWindowMode)
|
||||
switch (_liveStatesService.LiveStates.LyricsWindowMode)
|
||||
{
|
||||
case LyricsWindowMode.DockMode:
|
||||
FillBackground(control, combinedDs, _immersiveBgColorTransition.Value, 0f,
|
||||
@@ -236,7 +236,7 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
||||
|
||||
// 先铺一层带默认透明度的已经加了模糊效果的歌词作为最底层(背景歌词层次)
|
||||
using var backgroundFontEffect = CanvasHelper.CreateFontEffect(line, control, _strokeFontColor,
|
||||
_liveStatesService.LiveStates.CurrentLyricsStyleSettings.LyricsFontStrokeWidth, _bgFontColor);
|
||||
_liveStatesService.LiveStates.LyricsStyleSettings.LyricsFontStrokeWidth, _bgFontColor);
|
||||
using var backgroundEffect = CanvasHelper.CreateBackgroundEffect(line, backgroundFontEffect, _lyricsOpacityTransition.Value);
|
||||
combinedDs.DrawImage(backgroundEffect);
|
||||
|
||||
@@ -247,43 +247,43 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
||||
|
||||
using var charMask = CanvasHelper.CreateCharMask(control, line, charStartIndex, charLength, charProgress);
|
||||
using var lineStartToCharMask = CanvasHelper.CreateLineStartToCharMask(control, line, charStartIndex, charLength, charProgress,
|
||||
_liveStatesService.LiveStates.CurrentLyricsEffectSettings.IsLyricsLineFadeEnabled);
|
||||
_liveStatesService.LiveStates.LyricsEffectSettings.IsLyricsLineFadeEnabled);
|
||||
using var lineMask = CanvasHelper.CreateLineMask(control, line);
|
||||
|
||||
using var foregroundFontEffect = CanvasHelper.CreateFontEffect(line, control, _strokeFontColor,
|
||||
_liveStatesService.LiveStates.CurrentLyricsStyleSettings.LyricsFontStrokeWidth, _fgFontColor);
|
||||
_liveStatesService.LiveStates.LyricsStyleSettings.LyricsFontStrokeWidth, _fgFontColor);
|
||||
|
||||
using var effectLayer = new CanvasCommandList(control);
|
||||
using var effectLayerDs = effectLayer.CreateDrawingSession();
|
||||
if (line.OriginalText != line.DisplayedText && _liveStatesService.LiveStates.CurrentLyricsEffectSettings.LyricsTranslationHighlightAmount != 0)
|
||||
if (line.OriginalText != line.DisplayedText && _liveStatesService.LiveStates.LyricsEffectSettings.LyricsTranslationHighlightAmount != 0)
|
||||
{
|
||||
using var translationHighlightMask = CanvasHelper.CreateTranslationHighlightMask(control, line);
|
||||
using var foregroundTranslationHighlightEffect = CanvasHelper.CreateForegroundHighlightEffect(foregroundFontEffect, translationHighlightMask,
|
||||
_liveStatesService.LiveStates.CurrentLyricsEffectSettings.LyricsTranslationHighlightAmount / 100.0);
|
||||
_liveStatesService.LiveStates.LyricsEffectSettings.LyricsTranslationHighlightAmount / 100.0);
|
||||
effectLayerDs.DrawImage(foregroundTranslationHighlightEffect);
|
||||
}
|
||||
if (_liveStatesService.LiveStates.CurrentLyricsEffectSettings.IsLyricsShadowEnabled)
|
||||
if (_liveStatesService.LiveStates.LyricsEffectSettings.IsLyricsShadowEnabled)
|
||||
{
|
||||
var shadowEffectMask = CanvasHelper.GetAlphaMask(control, charMask, lineStartToCharMask, lineMask,
|
||||
_liveStatesService.LiveStates.CurrentLyricsEffectSettings.LyricsShadowScope);
|
||||
_liveStatesService.LiveStates.LyricsEffectSettings.LyricsShadowScope);
|
||||
using var foregroundShadowEffect = CanvasHelper.CreateForegroundShadowEffect(foregroundFontEffect, shadowEffectMask,
|
||||
_albumArtAccentColorTransition.Value, _liveStatesService.LiveStates.CurrentLyricsEffectSettings.LyricsShadowAmount);
|
||||
_albumArtAccentColorTransition.Value, _liveStatesService.LiveStates.LyricsEffectSettings.LyricsShadowAmount);
|
||||
effectLayerDs.DrawImage(foregroundShadowEffect);
|
||||
}
|
||||
if (_liveStatesService.LiveStates.CurrentLyricsEffectSettings.IsLyricsGlowEffectEnabled)
|
||||
if (_liveStatesService.LiveStates.LyricsEffectSettings.IsLyricsGlowEffectEnabled)
|
||||
{
|
||||
var blurEffectMask = CanvasHelper.GetAlphaMask(control, charMask, lineStartToCharMask, lineMask,
|
||||
_liveStatesService.LiveStates.CurrentLyricsEffectSettings.LyricsGlowEffectScope);
|
||||
_liveStatesService.LiveStates.LyricsEffectSettings.LyricsGlowEffectScope);
|
||||
using var foregroundBlurEffect = CanvasHelper.CreateForegroundBlurEffect(foregroundFontEffect, blurEffectMask,
|
||||
_liveStatesService.LiveStates.CurrentLyricsEffectSettings.LyricsGlowEffectAmount);
|
||||
_liveStatesService.LiveStates.LyricsEffectSettings.LyricsGlowEffectAmount);
|
||||
effectLayerDs.DrawImage(foregroundBlurEffect);
|
||||
}
|
||||
if (_liveStatesService.LiveStates.CurrentLyricsEffectSettings.LyricsHighlightAmount != 0)
|
||||
if (_liveStatesService.LiveStates.LyricsEffectSettings.LyricsHighlightAmount != 0)
|
||||
{
|
||||
var highlightEffectMask = CanvasHelper.GetAlphaMask(control, charMask, lineStartToCharMask, lineMask,
|
||||
_liveStatesService.LiveStates.CurrentLyricsEffectSettings.LyricsHighlightScope);
|
||||
_liveStatesService.LiveStates.LyricsEffectSettings.LyricsHighlightScope);
|
||||
using var foregroundHighlightEffect = CanvasHelper.CreateForegroundHighlightEffect(foregroundFontEffect, highlightEffectMask,
|
||||
_liveStatesService.LiveStates.CurrentLyricsEffectSettings.LyricsHighlightAmount / 100.0);
|
||||
_liveStatesService.LiveStates.LyricsEffectSettings.LyricsHighlightAmount / 100.0);
|
||||
effectLayerDs.DrawImage(foregroundHighlightEffect);
|
||||
}
|
||||
|
||||
@@ -295,7 +295,7 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
||||
|
||||
if (i == _playingLineIndex)
|
||||
{
|
||||
if (_liveStatesService.LiveStates.CurrentLyricsEffectSettings.IsLyricsFloatAnimationEnabled)
|
||||
if (_liveStatesService.LiveStates.LyricsEffectSettings.IsLyricsFloatAnimationEnabled)
|
||||
{
|
||||
ds.DrawImage(new DisplacementMapEffect
|
||||
{
|
||||
@@ -303,7 +303,7 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
||||
Displacement = lineStartToCharMask,
|
||||
XChannelSelect = EffectChannelSelect.Red,
|
||||
YChannelSelect = EffectChannelSelect.Alpha,
|
||||
Amount = _liveStatesService.LiveStates.CurrentLyricsEffectSettings.LyricsFloatAmount,
|
||||
Amount = _liveStatesService.LiveStates.LyricsEffectSettings.LyricsFloatAmount,
|
||||
});
|
||||
}
|
||||
else
|
||||
|
||||
@@ -73,6 +73,13 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
||||
UpdateIsLastFMTrackEnabled();
|
||||
}
|
||||
}
|
||||
else if (message.Sender is LyricsStyleSettings)
|
||||
{
|
||||
if (message.PropertyName == nameof(LyricsStyleSettings.IsDynamicLyricsFontSize))
|
||||
{
|
||||
_isLayoutChanged = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Receive(PropertyChangedMessage<Color> message)
|
||||
@@ -126,6 +133,10 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
||||
{
|
||||
_isAlbumArtShadowAmountChanged = true;
|
||||
}
|
||||
else if (message.PropertyName == nameof(AlbumArtLayoutSettings.SongInfoFontSize))
|
||||
{
|
||||
UpdateSongInfoFontSize();
|
||||
}
|
||||
}
|
||||
else if (message.Sender is LyricsBackgroundSettings)
|
||||
{
|
||||
@@ -242,7 +253,7 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
||||
{
|
||||
if (message.Sender is LiveStates)
|
||||
{
|
||||
if (message.PropertyName == nameof(LiveStates.CurrentLyricsDisplayType))
|
||||
if (message.PropertyName == nameof(LiveStates.LyricsDisplayType))
|
||||
{
|
||||
_isDisplayTypeChanged = true;
|
||||
}
|
||||
@@ -316,7 +327,7 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
||||
{
|
||||
if (message.Sender is LiveStates)
|
||||
{
|
||||
if (message.PropertyName == nameof(LiveStates.CurrentLyricsWindowMode))
|
||||
if (message.PropertyName == nameof(LiveStates.LyricsWindowMode))
|
||||
{
|
||||
UpdateColorConfig();
|
||||
UpdateImmersiveBackgroundOpacity();
|
||||
|
||||
@@ -93,7 +93,7 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
||||
|
||||
if (_isCanvasWidthChanged)
|
||||
{
|
||||
if (_canvasWidth < 450)
|
||||
if (_canvasWidth < 500)
|
||||
{
|
||||
_lyricsLayoutOrientation = LyricsLayoutOrientation.Vertical;
|
||||
}
|
||||
@@ -119,7 +119,7 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
||||
_albumArtYTransition.StartTransition((_canvasHeight - _albumArtSize * 1.05 - _titleTextFormat.FontSize - _artistTextFormat.FontSize) / 2.0, jumpTo);
|
||||
_titleYTransition.StartTransition(_albumArtYTransition.TargetValue + _albumArtSize * 1.05, jumpTo);
|
||||
_lyricsYTransition.StartTransition(0, jumpTo);
|
||||
switch (_liveStatesService.LiveStates.CurrentLyricsDisplayType)
|
||||
switch (_liveStatesService.LiveStates.LyricsDisplayType)
|
||||
{
|
||||
case LyricsDisplayType.AlbumArtOnly:
|
||||
_lyricsOpacityTransition.StartTransition(0f, jumpTo);
|
||||
@@ -148,7 +148,7 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
||||
_lyricsXTransition.StartTransition(_leftMargin, jumpTo);
|
||||
_albumArtXTransition.StartTransition(_leftMargin, jumpTo);
|
||||
_titleXTransition.StartTransition(_leftMargin + _albumArtSize * 1.2, jumpTo);
|
||||
switch (_liveStatesService.LiveStates.CurrentLyricsDisplayType)
|
||||
switch (_liveStatesService.LiveStates.LyricsDisplayType)
|
||||
{
|
||||
case LyricsDisplayType.AlbumArtOnly:
|
||||
_lyricsOpacityTransition.StartTransition(0f, jumpTo);
|
||||
@@ -326,12 +326,19 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
||||
if (control == null)
|
||||
return;
|
||||
|
||||
_lyricsTextFormat.FontSize = _liveStatesService.LiveStates.CurrentLyricsStyleSettings.LyricsFontSize;
|
||||
_lyricsTextFormat.FontWeight = _liveStatesService.LiveStates.CurrentLyricsStyleSettings.LyricsFontWeight.ToFontWeight();
|
||||
_lyricsTextFormat.FontFamily = _artistTextFormat.FontFamily = _titleTextFormat.FontFamily = _liveStatesService.LiveStates.CurrentLyricsStyleSettings.LyricsFontFamily;
|
||||
if (_liveStatesService.LiveStates.LyricsStyleSettings.IsDynamicLyricsFontSize)
|
||||
{
|
||||
_lyricsTextFormat.FontSize = (float)Math.Clamp(Math.Min(_canvasHeight, _canvasWidth) / 10, 12, 72);
|
||||
}
|
||||
else
|
||||
{
|
||||
_lyricsTextFormat.FontSize = _liveStatesService.LiveStates.LyricsStyleSettings.LyricsFontSize;
|
||||
}
|
||||
_lyricsTextFormat.FontWeight = _liveStatesService.LiveStates.LyricsStyleSettings.LyricsFontWeight.ToFontWeight();
|
||||
_lyricsTextFormat.FontFamily = _artistTextFormat.FontFamily = _titleTextFormat.FontFamily = _liveStatesService.LiveStates.LyricsStyleSettings.LyricsFontFamily;
|
||||
|
||||
_canvasYScrollTransition.SetDuration(_liveStatesService.LiveStates.CurrentLyricsEffectSettings.LyricsScrollDuration / 1000.0);
|
||||
_canvasYScrollTransition.SetEasingType(_liveStatesService.LiveStates.CurrentLyricsEffectSettings.LyricsScrollEasingType);
|
||||
_canvasYScrollTransition.SetDuration(_liveStatesService.LiveStates.LyricsEffectSettings.LyricsScrollDuration / 1000.0);
|
||||
_canvasYScrollTransition.SetEasingType(_liveStatesService.LiveStates.LyricsEffectSettings.LyricsScrollEasingType);
|
||||
|
||||
double y = 0;
|
||||
|
||||
@@ -346,15 +353,15 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
||||
}
|
||||
|
||||
line.Position = new Vector2(0, (float)y);
|
||||
line.RecreateTextLayout(control, _lyricsTextFormat, _maxLyricsWidth, _canvasHeight, _liveStatesService.LiveStates.CurrentLyricsStyleSettings.LyricsAlignmentType);
|
||||
line.UpdateCenterPosition(_maxLyricsWidth, _liveStatesService.LiveStates.CurrentLyricsStyleSettings.LyricsAlignmentType);
|
||||
line.RecreateTextLayout(control, _lyricsTextFormat, _maxLyricsWidth, _canvasHeight, _liveStatesService.LiveStates.LyricsStyleSettings.LyricsAlignmentType);
|
||||
line.UpdateCenterPosition(_maxLyricsWidth, _liveStatesService.LiveStates.LyricsStyleSettings.LyricsAlignmentType);
|
||||
|
||||
line.RecreateTextGeometry();
|
||||
|
||||
y +=
|
||||
(double)line.CanvasTextLayout!.LayoutBounds.Height
|
||||
/ line.CanvasTextLayout.LineCount
|
||||
* (line.CanvasTextLayout.LineCount + _liveStatesService.LiveStates.CurrentLyricsStyleSettings.LyricsLineSpacingFactor);
|
||||
* (line.CanvasTextLayout.LineCount + _liveStatesService.LiveStates.LyricsStyleSettings.LyricsLineSpacingFactor);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -451,8 +458,8 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
||||
|
||||
private void UpdateColorConfig()
|
||||
{
|
||||
if (_liveStatesService.LiveStates.CurrentLyricsWindowMode == LyricsWindowMode.DesktopMode ||
|
||||
_liveStatesService.LiveStates.CurrentLyricsWindowMode == LyricsWindowMode.DockMode)
|
||||
if (_liveStatesService.LiveStates.LyricsWindowMode == LyricsWindowMode.DesktopMode ||
|
||||
_liveStatesService.LiveStates.LyricsWindowMode == LyricsWindowMode.DockMode)
|
||||
{
|
||||
ThemeTypeSent = Helper.ColorHelper.GetElementThemeFromBackgroundColor(_environmentalColor);
|
||||
}
|
||||
@@ -488,8 +495,8 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
||||
|
||||
_lyricsBgBrightnessTransition.StartTransition(brightness);
|
||||
|
||||
if (_liveStatesService.LiveStates.CurrentLyricsWindowMode == LyricsWindowMode.DockMode ||
|
||||
_liveStatesService.LiveStates.CurrentLyricsWindowMode == LyricsWindowMode.DesktopMode)
|
||||
if (_liveStatesService.LiveStates.LyricsWindowMode == LyricsWindowMode.DockMode ||
|
||||
_liveStatesService.LiveStates.LyricsWindowMode == LyricsWindowMode.DesktopMode)
|
||||
{
|
||||
_adaptiveColoredFontColor = Helper.ColorHelper.GetForegroundColor(_environmentalColor);
|
||||
}
|
||||
@@ -505,7 +512,7 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
||||
}
|
||||
}
|
||||
|
||||
switch (_liveStatesService.LiveStates.CurrentLyricsStyleSettings.LyricsBgFontColorType)
|
||||
switch (_liveStatesService.LiveStates.LyricsStyleSettings.LyricsBgFontColorType)
|
||||
{
|
||||
case LyricsFontColorType.AdaptiveGrayed:
|
||||
_bgFontColor = _adaptiveGrayedFontColor;
|
||||
@@ -514,13 +521,13 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
||||
_bgFontColor = _adaptiveColoredFontColor ?? _adaptiveGrayedFontColor;
|
||||
break;
|
||||
case LyricsFontColorType.Custom:
|
||||
_bgFontColor = _liveStatesService.LiveStates.CurrentLyricsStyleSettings.LyricsCustomBgFontColor;
|
||||
_bgFontColor = _liveStatesService.LiveStates.LyricsStyleSettings.LyricsCustomBgFontColor;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (_liveStatesService.LiveStates.CurrentLyricsStyleSettings.LyricsFgFontColorType)
|
||||
switch (_liveStatesService.LiveStates.LyricsStyleSettings.LyricsFgFontColorType)
|
||||
{
|
||||
case LyricsFontColorType.AdaptiveGrayed:
|
||||
_fgFontColor = _adaptiveGrayedFontColor;
|
||||
@@ -529,13 +536,13 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
||||
_fgFontColor = _adaptiveColoredFontColor ?? _adaptiveGrayedFontColor;
|
||||
break;
|
||||
case LyricsFontColorType.Custom:
|
||||
_fgFontColor = _liveStatesService.LiveStates.CurrentLyricsStyleSettings.LyricsCustomFgFontColor;
|
||||
_fgFontColor = _liveStatesService.LiveStates.LyricsStyleSettings.LyricsCustomFgFontColor;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (_liveStatesService.LiveStates.CurrentLyricsStyleSettings.LyricsStrokeFontColorType)
|
||||
switch (_liveStatesService.LiveStates.LyricsStyleSettings.LyricsStrokeFontColorType)
|
||||
{
|
||||
case LyricsFontColorType.AdaptiveGrayed:
|
||||
_strokeFontColor = _grayedEnvironmentalColor.WithBrightness(0.7);
|
||||
@@ -544,7 +551,7 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
||||
_strokeFontColor = _environmentalColor.WithBrightness(0.7);
|
||||
break;
|
||||
case LyricsFontColorType.Custom:
|
||||
_strokeFontColor = _liveStatesService.LiveStates.CurrentLyricsStyleSettings.LyricsCustomStrokeFontColor;
|
||||
_strokeFontColor = _liveStatesService.LiveStates.LyricsStyleSettings.LyricsCustomStrokeFontColor;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -572,7 +579,7 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
||||
double distanceFromPlayingLine = Math.Abs(line.Position.Y - currentPlayingLine.Position.Y);
|
||||
double distanceFactor = Math.Clamp(distanceFromPlayingLine / (_canvasHeight / 2), 0, 1);
|
||||
|
||||
line.AngleTransition.StartTransition(_liveStatesService.LiveStates.CurrentLyricsEffectSettings.IsFanLyricsEnabled
|
||||
line.AngleTransition.StartTransition(_liveStatesService.LiveStates.LyricsEffectSettings.IsFanLyricsEnabled
|
||||
? Math.PI
|
||||
* (30.0 / 180.0)
|
||||
* distanceFactor
|
||||
@@ -580,12 +587,12 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
||||
: 0
|
||||
);
|
||||
|
||||
line.BlurAmountTransition.StartTransition(_liveStatesService.LiveStates.CurrentLyricsEffectSettings.LyricsBlurAmount * distanceFactor);
|
||||
line.BlurAmountTransition.StartTransition(_liveStatesService.LiveStates.LyricsEffectSettings.LyricsBlurAmount * distanceFactor);
|
||||
line.ScaleTransition.StartTransition(_highlightedScale - distanceFactor * (_highlightedScale - _defaultScale));
|
||||
line.OpacityTransition.StartTransition(
|
||||
_liveStatesService.LiveStates.CurrentLyricsStyleSettings.LyricsBgFontOpacity / 100.0 -
|
||||
distanceFactor * _liveStatesService.LiveStates.CurrentLyricsStyleSettings.LyricsBgFontOpacity / 100.0 *
|
||||
(1 - _liveStatesService.LiveStates.CurrentLyricsEffectSettings.LyricsVerticalEdgeOpacity / 100.0));
|
||||
_liveStatesService.LiveStates.LyricsStyleSettings.LyricsBgFontOpacity / 100.0 -
|
||||
distanceFactor * _liveStatesService.LiveStates.LyricsStyleSettings.LyricsBgFontOpacity / 100.0 *
|
||||
(1 - _liveStatesService.LiveStates.LyricsEffectSettings.LyricsVerticalEdgeOpacity / 100.0));
|
||||
line.HighlightOpacityTransition.StartTransition(i == _playingLineIndex ? 1f : 0f);
|
||||
|
||||
double yScrollDuration;
|
||||
@@ -595,8 +602,8 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
||||
{
|
||||
yScrollDuration =
|
||||
_canvasYScrollTransition.DurationSeconds +
|
||||
distanceFactor * (_liveStatesService.LiveStates.CurrentLyricsEffectSettings.LyricsScrollTopDuration / 1000.0 - _canvasYScrollTransition.DurationSeconds);
|
||||
yScrollDelay = distanceFactor * _liveStatesService.LiveStates.CurrentLyricsEffectSettings.LyricsScrollTopDelay / 1000.0;
|
||||
distanceFactor * (_liveStatesService.LiveStates.LyricsEffectSettings.LyricsScrollTopDuration / 1000.0 - _canvasYScrollTransition.DurationSeconds);
|
||||
yScrollDelay = distanceFactor * _liveStatesService.LiveStates.LyricsEffectSettings.LyricsScrollTopDelay / 1000.0;
|
||||
}
|
||||
else if (lineCountDelta == 0)
|
||||
{
|
||||
@@ -607,8 +614,8 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
||||
{
|
||||
yScrollDuration =
|
||||
_canvasYScrollTransition.DurationSeconds +
|
||||
distanceFactor * (_liveStatesService.LiveStates.CurrentLyricsEffectSettings.LyricsScrollBottomDuration / 1000.0 - _canvasYScrollTransition.DurationSeconds);
|
||||
yScrollDelay = distanceFactor * _liveStatesService.LiveStates.CurrentLyricsEffectSettings.LyricsScrollBottomDelay / 1000.0;
|
||||
distanceFactor * (_liveStatesService.LiveStates.LyricsEffectSettings.LyricsScrollBottomDuration / 1000.0 - _canvasYScrollTransition.DurationSeconds);
|
||||
yScrollDelay = distanceFactor * _liveStatesService.LiveStates.LyricsEffectSettings.LyricsScrollBottomDelay / 1000.0;
|
||||
}
|
||||
|
||||
line.YOffsetTransition.SetEasingType(_canvasYScrollTransition.EasingType ?? EasingType.Linear);
|
||||
@@ -629,7 +636,7 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
||||
private void UpdateImmersiveBackgroundOpacity()
|
||||
{
|
||||
double targetOpacity;
|
||||
if (_liveStatesService.LiveStates.CurrentLyricsWindowMode == LyricsWindowMode.DesktopMode)
|
||||
if (_liveStatesService.LiveStates.LyricsWindowMode == LyricsWindowMode.DesktopMode)
|
||||
{
|
||||
if (_isLyricsWindowLocked)
|
||||
{
|
||||
@@ -673,7 +680,8 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
||||
|
||||
private void UpdateTimelineSyncThreshold()
|
||||
{
|
||||
_timelineSyncThreshold = _mediaSessionsService.GetCurrentMediaSourceProviderInfo()?.TimelineSyncThreshold ?? 0;
|
||||
var current = _mediaSessionsService.GetCurrentMediaSourceProviderInfo();
|
||||
_timelineSyncThreshold = current?.TimelineSyncThreshold ?? 0;
|
||||
}
|
||||
|
||||
private void UpdatePositionOffset()
|
||||
@@ -687,5 +695,11 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
||||
var current = _mediaSessionsService.GetCurrentMediaSourceProviderInfo();
|
||||
_isLastFMTrackEnabled = current?.IsLastFMTrackEnabled ?? false;
|
||||
}
|
||||
|
||||
private void UpdateSongInfoFontSize()
|
||||
{
|
||||
_titleTextFormat.FontSize = _settingsService.AppSettings.AlbumArtLayoutSettings.SongInfoFontSize;
|
||||
_artistTextFormat.FontSize = _settingsService.AppSettings.AlbumArtLayoutSettings.SongInfoFontSize - 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -190,6 +190,8 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
||||
AppSettings = _settingsService.AppSettings;
|
||||
|
||||
_titleTextFormat.HorizontalAlignment = _artistTextFormat.HorizontalAlignment = _settingsService.AppSettings.AlbumArtLayoutSettings.SongInfoAlignmentType.ToCanvasHorizontalAlignment();
|
||||
UpdateSongInfoFontSize();
|
||||
|
||||
|
||||
_timelineSyncThreshold = 0;
|
||||
|
||||
|
||||
@@ -0,0 +1,193 @@
|
||||
using BetterLyrics.WinUI3.Helper;
|
||||
using BetterLyrics.WinUI3.Models;
|
||||
using BetterLyrics.WinUI3.Models.Settings;
|
||||
using BetterLyrics.WinUI3.Services.LyricsSearchService;
|
||||
using BetterLyrics.WinUI3.Services.MediaSessionsService;
|
||||
using BetterLyrics.WinUI3.Services.SettingsService;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.DependencyInjection;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using CommunityToolkit.Mvvm.Messaging;
|
||||
using CommunityToolkit.Mvvm.Messaging.Messages;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BetterLyrics.WinUI3.ViewModels
|
||||
{
|
||||
public partial class LyricsSearchControlViewModel : BaseViewModel
|
||||
{
|
||||
private readonly ILyricsSearchService _lyricsSearchService;
|
||||
private readonly IMediaSessionsService _mediaSessionsService;
|
||||
private readonly ISettingsService _settingsService;
|
||||
|
||||
private LatestOnlyTaskRunner _lyricsSearchRunner = new();
|
||||
|
||||
[ObservableProperty]
|
||||
public partial AppSettings AppSettings { get; set; }
|
||||
|
||||
[ObservableProperty]
|
||||
public partial ObservableCollection<LyricsSearchResult> LyricsSearchResults { get; set; } = [];
|
||||
|
||||
[ObservableProperty]
|
||||
public partial LyricsSearchResult? SelectedLyricsSearchResult { get; set; }
|
||||
|
||||
[ObservableProperty]
|
||||
public partial LyricsData? LyricsData { get; set; }
|
||||
|
||||
[ObservableProperty]
|
||||
public partial LyricsLine? SelectedLyricsLine { get; set; }
|
||||
|
||||
[ObservableProperty]
|
||||
public partial MappedSongSearchQuery? MappedSongSearchQuery { get; set; }
|
||||
|
||||
[ObservableProperty]
|
||||
public partial bool IsSearching { get; set; } = false;
|
||||
|
||||
public LyricsSearchControlViewModel(ILyricsSearchService lyricsSearchService, IMediaSessionsService mediaSessionsService, ISettingsService settingsService)
|
||||
{
|
||||
_lyricsSearchService = lyricsSearchService;
|
||||
_mediaSessionsService = mediaSessionsService;
|
||||
_settingsService = settingsService;
|
||||
|
||||
AppSettings = _settingsService.AppSettings;
|
||||
|
||||
_mediaSessionsService.SongInfoChanged += MediaSessionsService_SongInfoChanged;
|
||||
|
||||
InitMappedSongSearchQuery();
|
||||
}
|
||||
|
||||
private void MediaSessionsService_SongInfoChanged(object? sender, Events.SongInfoChangedEventArgs e)
|
||||
{
|
||||
InitMappedSongSearchQuery();
|
||||
}
|
||||
|
||||
private void InitMappedSongSearchQuery()
|
||||
{
|
||||
LyricsSearchResults.Clear();
|
||||
LyricsData = null;
|
||||
if (_mediaSessionsService.SongInfo != null)
|
||||
{
|
||||
var found = GetMappedSongSearchQueryFromSettings();
|
||||
if (found == null)
|
||||
{
|
||||
MappedSongSearchQuery = new MappedSongSearchQuery
|
||||
{
|
||||
OriginalTitle = _mediaSessionsService.SongInfo.Title,
|
||||
OriginalArtist = _mediaSessionsService.SongInfo.Artist,
|
||||
MappedTitle = _mediaSessionsService.SongInfo.Title,
|
||||
MappedArtist = _mediaSessionsService.SongInfo.Artist,
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
MappedSongSearchQuery = found.Clone();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private MappedSongSearchQuery? GetMappedSongSearchQueryFromSettings()
|
||||
{
|
||||
if (_mediaSessionsService.SongInfo == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
var found = AppSettings.MappedSongSearchQueries
|
||||
.Where(x => x.OriginalTitle == _mediaSessionsService.SongInfo.Title && x.OriginalArtist == _mediaSessionsService.SongInfo.Artist).FirstOrDefault();
|
||||
return found;
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void Search()
|
||||
{
|
||||
if (MappedSongSearchQuery == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
IsSearching = true;
|
||||
LyricsSearchResults.Clear();
|
||||
MappedSongSearchQuery.LyricsSearchProvider = null;
|
||||
_ = _lyricsSearchRunner.RunAsync(async (token) =>
|
||||
{
|
||||
LyricsSearchResults = [..await Task.Run(async () =>
|
||||
{
|
||||
return await _lyricsSearchService.SearchAllAsync(
|
||||
MappedSongSearchQuery.MappedTitle,
|
||||
MappedSongSearchQuery.MappedArtist,
|
||||
_mediaSessionsService.SongInfo?.Album ?? "",
|
||||
_mediaSessionsService.SongInfo?.DurationMs ?? 0, token);
|
||||
}, token)];
|
||||
IsSearching = false;
|
||||
});
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void Save()
|
||||
{
|
||||
if (MappedSongSearchQuery == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var existing = GetMappedSongSearchQueryFromSettings();
|
||||
if (existing != null)
|
||||
{
|
||||
AppSettings.MappedSongSearchQueries.Remove(existing);
|
||||
}
|
||||
AppSettings.MappedSongSearchQueries.Add(MappedSongSearchQuery);
|
||||
MappedSongSearchQuery = MappedSongSearchQuery.Clone();
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void Reset()
|
||||
{
|
||||
var existing = GetMappedSongSearchQueryFromSettings();
|
||||
if (existing != null)
|
||||
{
|
||||
AppSettings.MappedSongSearchQueries.Remove(existing);
|
||||
}
|
||||
InitMappedSongSearchQuery();
|
||||
SelectedLyricsSearchResult = null;
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void ResetMappedTitle()
|
||||
{
|
||||
MappedSongSearchQuery?.MappedTitle = MappedSongSearchQuery?.OriginalTitle ?? string.Empty;
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void ResetMappedArtist()
|
||||
{
|
||||
MappedSongSearchQuery?.MappedArtist = MappedSongSearchQuery?.OriginalArtist ?? string.Empty;
|
||||
}
|
||||
|
||||
partial void OnSelectedLyricsSearchResultChanged(LyricsSearchResult? value)
|
||||
{
|
||||
MappedSongSearchQuery?.LyricsSearchProvider = value?.Provider;
|
||||
if (value?.Raw != null)
|
||||
{
|
||||
var lyricsParser = new LyricsParser();
|
||||
var lyricsDataArr = lyricsParser.Parse(value?.Raw, (int?)_mediaSessionsService.SongInfo?.DurationMs);
|
||||
LyricsData = lyricsDataArr.FirstOrDefault();
|
||||
}
|
||||
else
|
||||
{
|
||||
LyricsData = null;
|
||||
}
|
||||
}
|
||||
|
||||
partial void OnSelectedLyricsLineChanged(LyricsLine? value)
|
||||
{
|
||||
if (value?.StartMs == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
_mediaSessionsService.ChangePosition(value.StartMs / 1000.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -105,14 +105,12 @@ namespace BetterLyrics.WinUI3
|
||||
[NotifyPropertyChangedRecipients]
|
||||
public partial bool IsMouseWithinWindow { get; set; } = false;
|
||||
|
||||
[ObservableProperty] public partial Visibility AOTFlyoutItemVisibility { get; set; } = Visibility.Visible;
|
||||
[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;
|
||||
|
||||
[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;
|
||||
@@ -126,11 +124,11 @@ namespace BetterLyrics.WinUI3
|
||||
|
||||
var hwnd = WindowNative.GetWindowHandle(window);
|
||||
|
||||
if (LiveStates.CurrentLyricsWindowMode == LyricsWindowMode.DockMode || LiveStates.CurrentLyricsWindowMode == LyricsWindowMode.DesktopMode)
|
||||
if (LiveStates.LyricsWindowMode == LyricsWindowMode.DockMode || LiveStates.LyricsWindowMode == LyricsWindowMode.DesktopMode)
|
||||
{
|
||||
if (_hideWindowWhenNotPlaying && !_mediaSessionsService.IsPlaying)
|
||||
{
|
||||
if (LiveStates.CurrentLyricsWindowMode == LyricsWindowMode.DockMode)
|
||||
if (LiveStates.LyricsWindowMode == LyricsWindowMode.DockMode)
|
||||
{
|
||||
DockModeHelper.UpdateAppBarHeight(hwnd, _dockMonitorDeviceName, 0, _dockPlacement);
|
||||
}
|
||||
@@ -138,7 +136,7 @@ namespace BetterLyrics.WinUI3
|
||||
}
|
||||
else
|
||||
{
|
||||
if (LiveStates.CurrentLyricsWindowMode == LyricsWindowMode.DockMode)
|
||||
if (LiveStates.LyricsWindowMode == LyricsWindowMode.DockMode)
|
||||
{
|
||||
DockModeHelper.UpdateAppBarHeight(hwnd, _dockMonitorDeviceName, _dockWindowHeight, _dockPlacement);
|
||||
}
|
||||
@@ -176,6 +174,7 @@ namespace BetterLyrics.WinUI3
|
||||
if (message.PropertyName == nameof(GeneralSettings.IgnoreFullscreenWindow))
|
||||
{
|
||||
_ignoreFullscreenWindow = message.NewValue;
|
||||
SetIsAlwaysOnTop();
|
||||
}
|
||||
else if (message.PropertyName == nameof(GeneralSettings.HideWindowWhenNotPlaying))
|
||||
{
|
||||
@@ -183,6 +182,13 @@ namespace BetterLyrics.WinUI3
|
||||
UpdateDockOrDesktopWindow();
|
||||
}
|
||||
}
|
||||
else if (message.Sender is LiveStates)
|
||||
{
|
||||
if (message.PropertyName == nameof(LiveStates.IsAlwaysOnTop))
|
||||
{
|
||||
SetIsAlwaysOnTop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Receive(PropertyChangedMessage<ElementTheme> message)
|
||||
@@ -210,19 +216,40 @@ namespace BetterLyrics.WinUI3
|
||||
|
||||
public void InitShortcuts()
|
||||
{
|
||||
UpdateDesktopLockShortcut();
|
||||
UpdateDesktopLockUnlockShortcut();
|
||||
UpdateDesktopToggleShortcut();
|
||||
UpdateDockToggleShortcut();
|
||||
UpdatePictureInPictureToggleShortcut();
|
||||
UpdateLyricsWindowShowHideShortcut();
|
||||
}
|
||||
|
||||
private void UpdateDesktopLockShortcut()
|
||||
private void UpdateLyricsWindowShowHideShortcut()
|
||||
{
|
||||
GlobalHotKeyHelper.UpdateHotKey<LyricsWindow>(ShortcutID.DesktopLock,
|
||||
GlobalHotKeyHelper.UpdateHotKey<LyricsWindow>(ShortcutID.LyricsWindowShowOrHide,
|
||||
_settingsService.AppSettings.GeneralSettings.ShowOrHideLyricsWindowShortcut,
|
||||
() =>
|
||||
{
|
||||
var window = WindowHelper.GetWindowByWindowType<LyricsWindow>();
|
||||
if (window == null) return;
|
||||
if (window.Visible)
|
||||
{
|
||||
window.Hide();
|
||||
}
|
||||
else
|
||||
{
|
||||
WindowHelper.OpenWindow<LyricsWindow>();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
private void UpdateDesktopLockUnlockShortcut()
|
||||
{
|
||||
GlobalHotKeyHelper.UpdateHotKey<LyricsWindow>(ShortcutID.DesktopLockOrUnlock,
|
||||
_settingsService.AppSettings.DesktopModeSettings.LockShortcut,
|
||||
() =>
|
||||
{
|
||||
if (LiveStates.CurrentLyricsWindowMode == LyricsWindowMode.DesktopMode)
|
||||
if (LiveStates.LyricsWindowMode == LyricsWindowMode.DesktopMode)
|
||||
{
|
||||
ToggleLockWindow();
|
||||
}
|
||||
@@ -236,8 +263,8 @@ namespace BetterLyrics.WinUI3
|
||||
_settingsService.AppSettings.DesktopModeSettings.ToggleShortcut,
|
||||
() =>
|
||||
{
|
||||
if (LiveStates.CurrentLyricsWindowMode == LyricsWindowMode.DesktopMode ||
|
||||
LiveStates.CurrentLyricsWindowMode == LyricsWindowMode.StandardMode)
|
||||
if (LiveStates.LyricsWindowMode == LyricsWindowMode.DesktopMode ||
|
||||
LiveStates.LyricsWindowMode == LyricsWindowMode.StandardMode)
|
||||
{
|
||||
ToggleDesktopMode();
|
||||
}
|
||||
@@ -251,8 +278,8 @@ namespace BetterLyrics.WinUI3
|
||||
_settingsService.AppSettings.DockModeSettings.ToggleShortcut,
|
||||
() =>
|
||||
{
|
||||
if (LiveStates.CurrentLyricsWindowMode == LyricsWindowMode.DockMode ||
|
||||
LiveStates.CurrentLyricsWindowMode == LyricsWindowMode.StandardMode)
|
||||
if (LiveStates.LyricsWindowMode == LyricsWindowMode.DockMode ||
|
||||
LiveStates.LyricsWindowMode == LyricsWindowMode.StandardMode)
|
||||
{
|
||||
ToggleDockMode();
|
||||
}
|
||||
@@ -266,8 +293,8 @@ namespace BetterLyrics.WinUI3
|
||||
_settingsService.AppSettings.PictureInPictureModeSettings.ToggleShortcut,
|
||||
() =>
|
||||
{
|
||||
if (LiveStates.CurrentLyricsWindowMode == LyricsWindowMode.PictureInPictureMode ||
|
||||
LiveStates.CurrentLyricsWindowMode == LyricsWindowMode.StandardMode)
|
||||
if (LiveStates.LyricsWindowMode == LyricsWindowMode.PictureInPictureMode ||
|
||||
LiveStates.LyricsWindowMode == LyricsWindowMode.StandardMode)
|
||||
{
|
||||
TogglePictureInPictureMode();
|
||||
}
|
||||
@@ -277,14 +304,14 @@ namespace BetterLyrics.WinUI3
|
||||
|
||||
private void SetFullscreenTitleBarControlsStatus()
|
||||
{
|
||||
AOTFlyoutItemVisibility = LockButtonVisibility = DesktopFlyoutItemVisibility = PIPFlyoutItemVisibility = DockFlyoutItemVisibility = Visibility.Collapsed;
|
||||
LockButtonVisibility = DesktopFlyoutItemVisibility = PIPFlyoutItemVisibility = DockFlyoutItemVisibility = Visibility.Collapsed;
|
||||
IsFullScreenFlyoutItemChecked = true;
|
||||
IsImmersiveMode = true;
|
||||
}
|
||||
|
||||
private void SetPIPModeTitleBarControlsStatus()
|
||||
{
|
||||
AOTFlyoutItemVisibility = DesktopFlyoutItemVisibility = FullScreenFlyoutItemVisibility = DockFlyoutItemVisibility = LockButtonVisibility = Visibility.Collapsed;
|
||||
DesktopFlyoutItemVisibility = FullScreenFlyoutItemVisibility = DockFlyoutItemVisibility = LockButtonVisibility = Visibility.Collapsed;
|
||||
IsImmersiveMode = true;
|
||||
IsPIPFlyoutItemChecked = true;
|
||||
}
|
||||
@@ -296,7 +323,7 @@ namespace BetterLyrics.WinUI3
|
||||
var overlappedPresenter = (OverlappedPresenter)window.AppWindow.Presenter;
|
||||
|
||||
overlappedPresenter.IsMinimizable = overlappedPresenter.IsMaximizable = false;
|
||||
AOTFlyoutItemVisibility = DesktopFlyoutItemVisibility = LockButtonVisibility = FullScreenFlyoutItemVisibility = PIPFlyoutItemVisibility = Visibility.Collapsed;
|
||||
DesktopFlyoutItemVisibility = LockButtonVisibility = FullScreenFlyoutItemVisibility = PIPFlyoutItemVisibility = Visibility.Collapsed;
|
||||
IsImmersiveMode = true;
|
||||
IsDockFlyoutItemChecked = true;
|
||||
}
|
||||
@@ -308,7 +335,7 @@ namespace BetterLyrics.WinUI3
|
||||
var overlappedPresenter = (OverlappedPresenter)window.AppWindow.Presenter;
|
||||
|
||||
overlappedPresenter.IsMinimizable = overlappedPresenter.IsMaximizable = false;
|
||||
DockFlyoutItemVisibility = AOTFlyoutItemVisibility = FullScreenFlyoutItemVisibility = PIPFlyoutItemVisibility = Visibility.Collapsed;
|
||||
DockFlyoutItemVisibility = FullScreenFlyoutItemVisibility = PIPFlyoutItemVisibility = Visibility.Collapsed;
|
||||
LockButtonVisibility = Visibility.Visible;
|
||||
IsDesktopFlyoutItemChecked = true;
|
||||
}
|
||||
@@ -320,10 +347,9 @@ namespace BetterLyrics.WinUI3
|
||||
var overlappedPresenter = (OverlappedPresenter)window.AppWindow.Presenter;
|
||||
|
||||
overlappedPresenter.IsMinimizable = overlappedPresenter.IsMaximizable = true;
|
||||
AOTFlyoutItemVisibility = DesktopFlyoutItemVisibility = DockFlyoutItemVisibility = PIPFlyoutItemVisibility = FullScreenFlyoutItemVisibility = Visibility.Visible;
|
||||
DesktopFlyoutItemVisibility = DockFlyoutItemVisibility = PIPFlyoutItemVisibility = FullScreenFlyoutItemVisibility = Visibility.Visible;
|
||||
LockButtonVisibility = Visibility.Collapsed;
|
||||
IsFullScreenFlyoutItemChecked = IsDesktopFlyoutItemChecked = IsDockFlyoutItemChecked = IsPIPFlyoutItemChecked = false;
|
||||
IsAOTFlyoutItemChecked = overlappedPresenter.IsAlwaysOnTop;
|
||||
IsImmersiveMode = _settingsService.AppSettings.GeneralSettings.IsImmersiveMode;
|
||||
}
|
||||
|
||||
@@ -339,7 +365,7 @@ namespace BetterLyrics.WinUI3
|
||||
{
|
||||
_dispatcherQueueTimer.Debounce(() =>
|
||||
{
|
||||
if ((LiveStates.CurrentLyricsWindowMode == LyricsWindowMode.DockMode || LiveStates.CurrentLyricsWindowMode == LyricsWindowMode.DesktopMode) && _ignoreFullscreenWindow && window.AppWindow.Presenter is OverlappedPresenter presenter)
|
||||
if ((LiveStates.LyricsWindowMode == LyricsWindowMode.DockMode || LiveStates.LyricsWindowMode == LyricsWindowMode.DesktopMode) && _ignoreFullscreenWindow && window.AppWindow.Presenter is OverlappedPresenter presenter)
|
||||
{
|
||||
presenter.IsAlwaysOnTop = true;
|
||||
}
|
||||
@@ -359,7 +385,7 @@ namespace BetterLyrics.WinUI3
|
||||
|
||||
public void UpdateAccentColor(nint hwnd)
|
||||
{
|
||||
WindowPixelSampleMode mode = LiveStates.CurrentLyricsWindowMode == LyricsWindowMode.DesktopMode ? WindowPixelSampleMode.WindowEdge : _dockPlacement.ToWindowPixelSampleMode();
|
||||
WindowPixelSampleMode mode = LiveStates.LyricsWindowMode == LyricsWindowMode.DesktopMode ? WindowPixelSampleMode.WindowEdge : _dockPlacement.ToWindowPixelSampleMode();
|
||||
ActivatedWindowAccentColor = ColorHelper.GetAccentColor(hwnd, _settingsService.AppSettings.DockModeSettings.DockMonitorDeviceName, mode).ToColor();
|
||||
}
|
||||
|
||||
@@ -405,7 +431,7 @@ namespace BetterLyrics.WinUI3
|
||||
StopWatchWindowColorChange();
|
||||
|
||||
LiveStates.ToggleLyricsWindowMode(LyricsWindowMode.DesktopMode);
|
||||
if (LiveStates.CurrentLyricsWindowMode == LyricsWindowMode.DesktopMode)
|
||||
if (LiveStates.LyricsWindowMode == LyricsWindowMode.DesktopMode)
|
||||
{
|
||||
DesktopModeHelper.Enable(window);
|
||||
StartWatchWindowColorChange();
|
||||
@@ -424,6 +450,7 @@ namespace BetterLyrics.WinUI3
|
||||
DesktopModeHelper.Disable(window);
|
||||
SetStandardModeTitleBarControlsStatus();
|
||||
}
|
||||
SetIsAlwaysOnTop();
|
||||
}
|
||||
|
||||
public void ToggleDockMode()
|
||||
@@ -434,7 +461,7 @@ namespace BetterLyrics.WinUI3
|
||||
StopWatchWindowColorChange();
|
||||
|
||||
LiveStates.ToggleLyricsWindowMode(LyricsWindowMode.DockMode);
|
||||
if (LiveStates.CurrentLyricsWindowMode == LyricsWindowMode.DockMode)
|
||||
if (LiveStates.LyricsWindowMode == LyricsWindowMode.DockMode)
|
||||
{
|
||||
window.Restore();
|
||||
DockModeHelper.Enable(window, _dockMonitorDeviceName, _dockWindowHeight, _dockPlacement);
|
||||
@@ -448,6 +475,7 @@ namespace BetterLyrics.WinUI3
|
||||
}
|
||||
|
||||
UpdateDockOrDesktopWindow();
|
||||
SetIsAlwaysOnTop();
|
||||
}
|
||||
|
||||
public void TogglePictureInPictureMode()
|
||||
@@ -456,7 +484,7 @@ namespace BetterLyrics.WinUI3
|
||||
if (window == null) return;
|
||||
|
||||
LiveStates.ToggleLyricsWindowMode(LyricsWindowMode.PictureInPictureMode);
|
||||
if (LiveStates.CurrentLyricsWindowMode == LyricsWindowMode.PictureInPictureMode)
|
||||
if (LiveStates.LyricsWindowMode == LyricsWindowMode.PictureInPictureMode)
|
||||
{
|
||||
window.AppWindow.SetPresenter(AppWindowPresenterKind.CompactOverlay);
|
||||
window.AppWindow.Move(AppSettings.PictureInPictureModeSettings.WindowPosition.ToPointInt32());
|
||||
@@ -467,17 +495,17 @@ namespace BetterLyrics.WinUI3
|
||||
window.AppWindow.SetPresenter(AppWindowPresenterKind.Overlapped);
|
||||
SetStandardModeTitleBarControlsStatus();
|
||||
}
|
||||
SetIsAlwaysOnTop();
|
||||
}
|
||||
|
||||
public void ToggleAlwaysOnTop()
|
||||
public void SetIsAlwaysOnTop()
|
||||
{
|
||||
var window = WindowHelper.GetWindowByWindowType<LyricsWindow>();
|
||||
if (window == null) return;
|
||||
|
||||
if (window.AppWindow.Presenter is OverlappedPresenter presenter)
|
||||
{
|
||||
presenter.IsAlwaysOnTop = !presenter.IsAlwaysOnTop;
|
||||
IsAOTFlyoutItemChecked = presenter.IsAlwaysOnTop;
|
||||
presenter.IsAlwaysOnTop = _liveStatesService.LiveStates.IsAlwaysOnTop;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -537,7 +565,7 @@ namespace BetterLyrics.WinUI3
|
||||
{
|
||||
if (message.PropertyName == nameof(DesktopModeSettings.LockShortcut))
|
||||
{
|
||||
UpdateDesktopLockShortcut();
|
||||
UpdateDesktopLockUnlockShortcut();
|
||||
}
|
||||
}
|
||||
else if (message.Sender is DockModeSettings)
|
||||
@@ -561,6 +589,13 @@ namespace BetterLyrics.WinUI3
|
||||
UpdateDesktopToggleShortcut();
|
||||
}
|
||||
}
|
||||
else if (message.Sender is GeneralSettings)
|
||||
{
|
||||
if (message.PropertyName == nameof(GeneralSettings.ShowOrHideLyricsWindowShortcut))
|
||||
{
|
||||
UpdateLyricsWindowShowHideShortcut();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ using Microsoft.UI.Dispatching;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
@@ -42,16 +43,69 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
[ObservableProperty]
|
||||
public partial object NavViewSelectedItemTag { get; set; } = "App";
|
||||
|
||||
[ObservableProperty]
|
||||
public partial ObservableCollection<LibInfo> Libs { get; set; }
|
||||
|
||||
public SettingsPageViewModel(ISettingsService settingsService)
|
||||
{
|
||||
_settingsService = settingsService;
|
||||
AppSettings = _settingsService.AppSettings;
|
||||
|
||||
Libs =
|
||||
[
|
||||
new LibInfo { Name = "3v.EvtSource" },
|
||||
new LibInfo { Name = "ColorThief.ImageSharp" },
|
||||
new LibInfo { Name = "CommunityToolkit.Labs.WinUI.MarqueeText" },
|
||||
new LibInfo { Name = "CommunityToolkit.Labs.WinUI.OpacityMaskView" },
|
||||
new LibInfo { Name = "CommunityToolkit.Labs.WinUI.Shimmer" },
|
||||
new LibInfo { Name = "CommunityToolkit.Mvvm" },
|
||||
new LibInfo { Name = "CommunityToolkit.WinUI.Behaviors" },
|
||||
new LibInfo { Name = "CommunityToolkit.WinUI.Controls.MetadataControl" },
|
||||
new LibInfo { Name = "CommunityToolkit.WinUI.Controls.Primitives" },
|
||||
new LibInfo { Name = "CommunityToolkit.WinUI.Controls.Segmented" },
|
||||
new LibInfo { Name = "CommunityToolkit.WinUI.Controls.SettingsControls" },
|
||||
new LibInfo { Name = "CommunityToolkit.WinUI.Controls.Sizers" },
|
||||
new LibInfo { Name = "CommunityToolkit.WinUI.Converters" },
|
||||
new LibInfo { Name = "CommunityToolkit.WinUI.Extensions" },
|
||||
new LibInfo { Name = "CommunityToolkit.WinUI.Helpers" },
|
||||
new LibInfo { Name = "CommunityToolkit.WinUI.Media" },
|
||||
new LibInfo { Name = "csharp-pinyin" },
|
||||
new LibInfo { Name = "Dubya.WindowsMediaController" },
|
||||
new LibInfo { Name = "H.NotifyIcon.WinUI"},
|
||||
new LibInfo { Name = "Hqub.Last.fm"},
|
||||
new LibInfo { Name = "Lyricify.Lyrics.Helper-NativeAot"},
|
||||
new LibInfo { Name = "Microsoft.Extensions.DependencyInjection"},
|
||||
new LibInfo { Name = "Microsoft.Extensions.Logging"},
|
||||
new LibInfo { Name = "Microsoft.Graphics.Win2D"},
|
||||
new LibInfo { Name = "Microsoft.Windows.SDK.BuildTools"},
|
||||
new LibInfo { Name = "Microsoft.WindowsAppSDK"},
|
||||
new LibInfo { Name = "Nito.AsyncEx"},
|
||||
new LibInfo { Name = "Nito.AsyncEx.Tasks"},
|
||||
new LibInfo { Name = "NTextCat"},
|
||||
new LibInfo { Name = "RomajiConverter.Core"},
|
||||
new LibInfo { Name = "Serilog.Extensions.Logging"},
|
||||
new LibInfo { Name = "Serilog.Sinks.File"},
|
||||
new LibInfo { Name = "ShadowViewer.Controls.Notification"},
|
||||
new LibInfo { Name = "SixLabors.ImageSharp" },
|
||||
new LibInfo { Name = "System.Drawing.Common"},
|
||||
new LibInfo { Name = "System.Text.Encoding.CodePages"},
|
||||
new LibInfo { Name = "TagLibSharp" },
|
||||
new LibInfo { Name = "TinyPinyin.Net"},
|
||||
new LibInfo { Name = "Ude.NetStandard"},
|
||||
new LibInfo { Name = "Vanara.PInvoke.CoreAudio"},
|
||||
new LibInfo { Name = "Vanara.PInvoke.DwmApi"},
|
||||
new LibInfo { Name = "Vanara.PInvoke.Gdi32"},
|
||||
new LibInfo { Name = "Vanara.PInvoke.Shell32"},
|
||||
new LibInfo { Name = "Vanara.PInvoke.User32"},
|
||||
new LibInfo { Name = "WinUIEx" },
|
||||
new LibInfo { Name = "z440.atl.core" },
|
||||
];
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private async Task LaunchProjectGitHubPageAsync()
|
||||
{
|
||||
await Windows.System.Launcher.LaunchUriAsync(new Uri(Constants.Link.GithubUrl));
|
||||
await Windows.System.Launcher.LaunchUriAsync(new Uri(Constants.Link.GitHubUrl));
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
@@ -80,14 +134,17 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
|
||||
var file = await picker.PickSingleFileAsync();
|
||||
|
||||
var succeed = _settingsService.ImportSettings(file.Path);
|
||||
if (succeed)
|
||||
if (file != null)
|
||||
{
|
||||
WindowHelper.RestartApp();
|
||||
}
|
||||
else
|
||||
{
|
||||
App.Current.SettingsWindowNotificationPanel?.Notify(App.ResourceLoader?.GetString("ImportSettingsFailed") ?? "");
|
||||
var succeed = _settingsService.ImportSettings(file.Path);
|
||||
if (succeed)
|
||||
{
|
||||
WindowHelper.RestartApp();
|
||||
}
|
||||
else
|
||||
{
|
||||
App.Current.SettingsWindowNotificationPanel?.Notify(App.ResourceLoader?.GetString("ImportSettingsFailed") ?? "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -29,8 +29,8 @@
|
||||
x:Uid="MainPageNoMusicPlaying"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
FontFamily="{x:Bind ViewModel.LiveStates.CurrentLyricsStyleSettings.LyricsFontFamily, Mode=OneWay}"
|
||||
FontSize="{x:Bind ViewModel.LiveStates.CurrentLyricsStyleSettings.LyricsFontSize, Mode=OneWay}" />
|
||||
FontFamily="{x:Bind ViewModel.LiveStates.LyricsStyleSettings.LyricsFontFamily, Mode=OneWay}"
|
||||
FontSize="{x:Bind ViewModel.LiveStates.LyricsStyleSettings.LyricsFontSize, Mode=OneWay}" />
|
||||
<Grid.OpacityTransition>
|
||||
<ScalarTransition />
|
||||
</Grid.OpacityTransition>
|
||||
@@ -237,7 +237,17 @@
|
||||
</Button.ContextFlyout>
|
||||
</Button>
|
||||
|
||||
<!-- Lyrics & Translation -->
|
||||
<Button
|
||||
Click="LyricsSearchShortcutButton_Click"
|
||||
Content="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
|
||||
Glyph=}"
|
||||
Style="{StaticResource GhostButtonStyle}">
|
||||
<ToolTipService.ToolTip>
|
||||
<ToolTip x:Uid="LyricsPageLyricsSearchButtonToolTip" />
|
||||
</ToolTipService.ToolTip>
|
||||
</Button>
|
||||
|
||||
<!-- Playback shortcut settings -->
|
||||
<Button
|
||||
Click="PlaybackSettingsShortcutButton_Click"
|
||||
Content="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
|
||||
@@ -279,9 +289,40 @@
|
||||
Maximum="{x:Bind ViewModel.SongDurationSeconds, Mode=OneWay}"
|
||||
Minimum="0"
|
||||
Style="{StaticResource GhostSliderStyle}"
|
||||
Tapped="TimelineSliderOverlay_Tapped"
|
||||
ThumbToolTipValueConverter="{StaticResource SecondsToFormattedTimeConverter}"
|
||||
Value="{x:Bind ViewModel.TimelinePositionSeconds, Mode=OneWay}" />
|
||||
<Grid
|
||||
x:Name="TimelineSliderLyricsLineInfo"
|
||||
Margin="0,-48,0,0"
|
||||
Padding="8,4"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Top"
|
||||
Background="{ThemeResource SolidBackgroundFillColorQuarternaryBrush}"
|
||||
CornerRadius="6"
|
||||
Opacity="{x:Bind ViewModel.TimelineSliderThumbOpacity, Mode=OneWay}">
|
||||
<Grid.OpacityTransition>
|
||||
<ScalarTransition />
|
||||
</Grid.OpacityTransition>
|
||||
<Grid.TranslationTransition>
|
||||
<Vector3Transition />
|
||||
</Grid.TranslationTransition>
|
||||
<StackPanel Orientation="Horizontal" Spacing="6">
|
||||
<TextBlock
|
||||
Margin="0,0,0,2"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
Text="{x:Bind ViewModel.TimelineSliderThumbLyricsLine.StartMs, Converter={StaticResource MillisecondsToFormattedTimeConverter}, Mode=OneWay}" />
|
||||
<TextBlock Margin="0,0,0,2" Text="{x:Bind ViewModel.TimelineSliderThumbLyricsLine.DisplayedText, Mode=OneWay}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
<Grid
|
||||
Height="32"
|
||||
Margin="0,-32,0,0"
|
||||
VerticalAlignment="Top"
|
||||
Background="Transparent"
|
||||
PointerEntered="TimelineSliderOverlay_PointerEntered"
|
||||
PointerExited="TimelineSliderOverlay_PointerExited"
|
||||
PointerMoved="TimelineSliderOverlay_PointerMoved"
|
||||
PointerPressed="TimelineSliderOverlay_PointerPressed" />
|
||||
</Grid>
|
||||
|
||||
</Grid>
|
||||
@@ -315,7 +356,7 @@
|
||||
<Flyout x:Name="BottomCommandFlyout" ShouldConstrainToRootBounds="False">
|
||||
<Flyout.FlyoutPresenterStyle>
|
||||
<Style TargetType="FlyoutPresenter">
|
||||
<Setter Property="MinWidth" Value="450" />
|
||||
<Setter Property="MinWidth" Value="500" />
|
||||
<Setter Property="MinHeight" Value="100" />
|
||||
<Setter Property="CornerRadius" Value="12" />
|
||||
</Style>
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
using BetterLyrics.WinUI3.Controls;
|
||||
using BetterLyrics.WinUI3.Enums;
|
||||
using BetterLyrics.WinUI3.Helper;
|
||||
using BetterLyrics.WinUI3.Models.Settings;
|
||||
using BetterLyrics.WinUI3.Services.MediaSessionsService;
|
||||
using BetterLyrics.WinUI3.Services.SettingsService;
|
||||
@@ -10,6 +11,7 @@ using CommunityToolkit.Mvvm.DependencyInjection;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading.Tasks;
|
||||
@@ -60,7 +62,7 @@ namespace BetterLyrics.WinUI3.Views
|
||||
|
||||
private void RootGrid_SizeChanged(object sender, SizeChangedEventArgs e)
|
||||
{
|
||||
if (e.NewSize.Width < 450 || e.NewSize.Height < 100)
|
||||
if (e.NewSize.Width < 500 || e.NewSize.Height < 100)
|
||||
{
|
||||
if (BottomCommandGrid.Children.Count != 0)
|
||||
{
|
||||
@@ -110,11 +112,6 @@ namespace BetterLyrics.WinUI3.Views
|
||||
}
|
||||
}
|
||||
|
||||
private void TimelineSliderOverlay_Tapped(object sender, Microsoft.UI.Xaml.Input.TappedRoutedEventArgs e)
|
||||
{
|
||||
_mediaSessionsService.ChangePosition(TimelineSlider.Value);
|
||||
}
|
||||
|
||||
private void PlaybackSettingsFlyout_Closed(object sender, object e)
|
||||
{
|
||||
PlaybackSettingsFlyout.Content = null;
|
||||
@@ -134,5 +131,46 @@ namespace BetterLyrics.WinUI3.Views
|
||||
};
|
||||
LyricsSettingsFlyout.ShowAt(BottomRightCommandStackPanel);
|
||||
}
|
||||
|
||||
private void LyricsSearchShortcutButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
WindowHelper.OpenWindow<LyricsSearchWindow>();
|
||||
}
|
||||
|
||||
private void TimelineSliderOverlay_PointerPressed(object sender, Microsoft.UI.Xaml.Input.PointerRoutedEventArgs e)
|
||||
{
|
||||
var grid = (Grid)sender;
|
||||
var pos = e.GetCurrentPoint(grid).Position;
|
||||
var ratio = pos.X / grid.ActualWidth;
|
||||
_mediaSessionsService.ChangePosition(TimelineSlider.Maximum * ratio);
|
||||
}
|
||||
|
||||
private void TimelineSliderOverlay_PointerMoved(object sender, Microsoft.UI.Xaml.Input.PointerRoutedEventArgs e)
|
||||
{
|
||||
float targetX;
|
||||
var grid = (Grid)sender;
|
||||
var pos = e.GetCurrentPoint(grid).Position;
|
||||
var ratio = pos.X / grid.ActualWidth;
|
||||
ViewModel.TimelineSliderThumbSeconds = TimelineSlider.Maximum * ratio;
|
||||
if (pos.X + TimelineSliderLyricsLineInfo.ActualWidth > grid.ActualWidth)
|
||||
{
|
||||
targetX = (float)(grid.ActualWidth - TimelineSliderLyricsLineInfo.ActualWidth);
|
||||
}
|
||||
else
|
||||
{
|
||||
targetX = (float)pos.X;
|
||||
}
|
||||
TimelineSliderLyricsLineInfo.Translation = new Vector3(targetX, 0, 0);
|
||||
}
|
||||
|
||||
private void TimelineSliderOverlay_PointerEntered(object sender, Microsoft.UI.Xaml.Input.PointerRoutedEventArgs e)
|
||||
{
|
||||
ViewModel.TimelineSliderThumbOpacity = 0.7f;
|
||||
}
|
||||
|
||||
private void TimelineSliderOverlay_PointerExited(object sender, Microsoft.UI.Xaml.Input.PointerRoutedEventArgs e)
|
||||
{
|
||||
ViewModel.TimelineSliderThumbOpacity = 0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<Window
|
||||
x:Class="BetterLyrics.WinUI3.Views.LyricsSearchWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:controls="using:BetterLyrics.WinUI3.Controls"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="using:BetterLyrics.WinUI3.Views"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:media="using:CommunityToolkit.WinUI.Media"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<Grid Background="{ThemeResource SystemControlAcrylicWindowBrush}" Opacity="0.85">
|
||||
<controls:LyricsSearchControl />
|
||||
</Grid>
|
||||
</Window>
|
||||
@@ -0,0 +1,47 @@
|
||||
using BetterLyrics.WinUI3.Helper;
|
||||
using Microsoft.UI.Windowing;
|
||||
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;
|
||||
|
||||
// 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.Views
|
||||
{
|
||||
/// <summary>
|
||||
/// An empty window that can be used on its own or navigated to within a Frame.
|
||||
/// </summary>
|
||||
public sealed partial class LyricsSearchWindow : Window
|
||||
{
|
||||
public LyricsSearchWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
Title = App.ResourceLoader?.GetString("LyricsSearchPageTitle");
|
||||
AppWindow.TitleBar.PreferredTheme = TitleBarTheme.UseDefaultAppMode;
|
||||
AppWindow.SetIcons();
|
||||
|
||||
AppWindow.Closing += AppWindow_Closing;
|
||||
|
||||
SystemBackdrop = SystemBackdropHelper.CreateSystemBackdrop(Enums.BackdropType.Transparent);
|
||||
}
|
||||
|
||||
private void AppWindow_Closing(AppWindow sender, AppWindowClosingEventArgs args)
|
||||
{
|
||||
WindowHelper.CloseWindow<LyricsSearchWindow>();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -25,6 +25,7 @@
|
||||
<!-- Top command -->
|
||||
<Grid
|
||||
x:Name="TopCommandGrid"
|
||||
Margin="6"
|
||||
VerticalAlignment="Top"
|
||||
Background="Transparent"
|
||||
Opacity="{x:Bind ViewModel.TopCommandGridOpacity, Mode=OneWay}"
|
||||
@@ -75,14 +76,6 @@
|
||||
</ToolTipService.ToolTip>
|
||||
<Button.Flyout>
|
||||
<MenuFlyout>
|
||||
<ToggleMenuFlyoutItem
|
||||
x:Name="AOTFlyoutItem"
|
||||
x:Uid="BaseWindowAOTFlyoutItem"
|
||||
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
|
||||
x:Name="FullScreenFlyoutItem"
|
||||
x:Uid="BaseWindowFullScreenFlyoutItem"
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
using BetterLyrics.WinUI3.Enums;
|
||||
using BetterLyrics.WinUI3.Helper;
|
||||
using BetterLyrics.WinUI3.Services.LiveStatesService;
|
||||
using BetterLyrics.WinUI3.Services.SettingsService;
|
||||
using CommunityToolkit.Mvvm.DependencyInjection;
|
||||
using CommunityToolkit.WinUI;
|
||||
@@ -19,6 +20,7 @@ namespace BetterLyrics.WinUI3.Views
|
||||
public sealed partial class LyricsWindow : Window
|
||||
{
|
||||
private readonly ISettingsService _settingsService = Ioc.Default.GetRequiredService<ISettingsService>();
|
||||
private readonly ILiveStatesService _liveStatesService = Ioc.Default.GetRequiredService<ILiveStatesService>();
|
||||
private readonly WindowMessageMonitor _wmm;
|
||||
private bool _autoSelectLyricsModeOnRunning = true;
|
||||
|
||||
@@ -101,11 +103,11 @@ namespace BetterLyrics.WinUI3.Views
|
||||
break;
|
||||
}
|
||||
_autoSelectLyricsModeOnRunning = false;
|
||||
}
|
||||
|
||||
private void AOTFlyoutItem_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
ViewModel.ToggleAlwaysOnTop();
|
||||
var size = AppWindow.Size;
|
||||
var rect = AppWindow.Position;
|
||||
|
||||
_liveStatesService.LiveStates.LyricsWindowBounds = new Windows.Foundation.Rect(rect.X, rect.Y, size.Width, size.Height);
|
||||
}
|
||||
|
||||
private void AppWindow_Changed(AppWindow sender, AppWindowChangedEventArgs args)
|
||||
@@ -117,13 +119,15 @@ namespace BetterLyrics.WinUI3.Views
|
||||
var size = AppWindow.Size;
|
||||
var rect = AppWindow.Position;
|
||||
|
||||
_liveStatesService.LiveStates.LyricsWindowBounds = new Windows.Foundation.Rect(rect.X, rect.Y, size.Width, size.Height);
|
||||
|
||||
if (rect.X < 0 && rect.Y < 0 && rect.X + size.Width < 0 && rect.Y + size.Height < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (ViewModel.LiveStates.CurrentLyricsWindowMode)
|
||||
switch (ViewModel.LiveStates.LyricsWindowMode)
|
||||
{
|
||||
case LyricsWindowMode.StandardMode:
|
||||
if (AppWindow.Presenter is OverlappedPresenter overlappedPresenter)
|
||||
|
||||
@@ -354,7 +354,7 @@
|
||||
<StackPanel>
|
||||
<TextBlock Text="{Binding Track.Title}" TextWrapping="Wrap" />
|
||||
<TextBlock
|
||||
Foreground="{StaticResource TextFillColorSecondaryBrush}"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
Text="{Binding Track.Artist}"
|
||||
TextWrapping="Wrap" />
|
||||
</StackPanel>
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
x:Class="BetterLyrics.WinUI3.Views.SettingsPage"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:const="using:BetterLyrics.WinUI3.Constants"
|
||||
xmlns:controls="using:CommunityToolkit.WinUI.Controls"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:interactivity="using:Microsoft.Xaml.Interactivity"
|
||||
@@ -120,41 +121,130 @@
|
||||
|
||||
<TextBlock Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" />
|
||||
|
||||
<controls:SettingsCard Header="BetterLyrics" HeaderIcon="{ui:BitmapIcon Source=ms-appx:///Assets/Logo.png}">
|
||||
<controls:SettingsCard.Description>
|
||||
<RichTextBlock>
|
||||
<Paragraph>
|
||||
<Run x:Uid="SettingsPageVersion" />
|
||||
<Run Text="{x:Bind ViewModel.Version, Mode=OneWay}" />
|
||||
</Paragraph>
|
||||
</RichTextBlock>
|
||||
</controls:SettingsCard.Description>
|
||||
</controls:SettingsCard>
|
||||
<controls:SettingsExpander
|
||||
Header="BetterLyrics"
|
||||
HeaderIcon="{ui:BitmapIcon Source=ms-appx:///Assets/Logo.png}"
|
||||
IsExpanded="True">
|
||||
<controls:SettingsExpander.Description>
|
||||
<HyperlinkButton Content="by Zhe Fang" NavigateUri="https://github.com/jayfunc" />
|
||||
</controls:SettingsExpander.Description>
|
||||
<RichTextBlock Foreground="{ThemeResource TextFillColorSecondaryBrush}">
|
||||
<Paragraph>
|
||||
<Run x:Uid="SettingsPageVersion" />
|
||||
<Run Text="{x:Bind ViewModel.Version, Mode=OneWay}" />
|
||||
</Paragraph>
|
||||
</RichTextBlock>
|
||||
<controls:SettingsExpander.Items>
|
||||
|
||||
<controls:SettingsCard
|
||||
x:Uid="SettingsPageGitHub"
|
||||
ActionIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
|
||||
Glyph=}"
|
||||
Command="{x:Bind ViewModel.LaunchProjectGitHubPageCommand}"
|
||||
HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
|
||||
Glyph=}"
|
||||
IsClickEnabled="True" />
|
||||
<controls:SettingsCard HorizontalContentAlignment="Left" ContentAlignment="Left">
|
||||
<StackPanel Margin="-12,0,0,0" Orientation="Horizontal">
|
||||
<HyperlinkButton Content="GitHub" NavigateUri="{x:Bind const:Link.GitHubUrl}" />
|
||||
<HyperlinkButton x:Uid="SettingsPageFAQ" NavigateUri="{x:Bind const:Link.FAQUrl}" />
|
||||
</StackPanel>
|
||||
</controls:SettingsCard>
|
||||
|
||||
<controls:SettingsCard x:Uid="SettingsPageFAQ" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||
<HyperlinkButton Content="https://github.com/jayfunc/BetterLyrics/blob/dev/FAQ/FAQ.md" NavigateUri="https://github.com/jayfunc/BetterLyrics/blob/dev/FAQ/FAQ.md" />
|
||||
</controls:SettingsCard>
|
||||
<controls:SettingsCard HorizontalContentAlignment="Left" ContentAlignment="Left">
|
||||
<StackPanel Spacing="6">
|
||||
<TextBlock x:Uid="SetingsPageFeedback" />
|
||||
<StackPanel Margin="-12,0,0,0" Orientation="Horizontal">
|
||||
<HyperlinkButton x:Uid="SettingsPageQQGroup" NavigateUri="{x:Bind const:Link.QQGroupUrl}" />
|
||||
<HyperlinkButton x:Uid="SettingsPageDiscord" NavigateUri="{x:Bind const:Link.DiscordUrl}" />
|
||||
<HyperlinkButton x:Uid="SettingsPageTelegram" NavigateUri="{x:Bind const:Link.TelegramUrl}" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</controls:SettingsCard>
|
||||
|
||||
<controls:SettingsCard x:Uid="SettingsPageQQGroup" HeaderIcon="{ui:BitmapIcon Source=ms-appx:///Assets/QQ.png}">
|
||||
<Button x:Uid="SettingsPageJoinNowButton" Click="QQGroupButton_Click" />
|
||||
</controls:SettingsCard>
|
||||
<controls:SettingsCard HorizontalContentAlignment="Left" ContentAlignment="Left">
|
||||
<StackPanel Spacing="6">
|
||||
<TextBlock x:Uid="SetingsPageDonation" />
|
||||
<StackPanel Margin="-12,0,0,0" Orientation="Horizontal">
|
||||
<HyperlinkButton Content="Buy Me a Coffee" NavigateUri="https://buymeacoffee.com/founchoo" />
|
||||
<HyperlinkButton Content="PayPal" NavigateUri="https://paypal.me/zhefangpay" />
|
||||
<Button
|
||||
Content="支付宝"
|
||||
Foreground="{ThemeResource AccentTextFillColorPrimaryBrush}"
|
||||
Style="{StaticResource GhostButtonStyle}">
|
||||
<Button.Flyout>
|
||||
<Flyout>
|
||||
<Flyout.FlyoutPresenterStyle>
|
||||
<Style TargetType="FlyoutPresenter">
|
||||
<Setter Property="CornerRadius" Value="12" />
|
||||
<Setter Property="Padding" Value="0" />
|
||||
</Style>
|
||||
</Flyout.FlyoutPresenterStyle>
|
||||
<Image Height="300" Source="/Assets/Alipay.jpg" />
|
||||
</Flyout>
|
||||
</Button.Flyout>
|
||||
</Button>
|
||||
<Button
|
||||
Content="微信"
|
||||
Foreground="{ThemeResource AccentTextFillColorPrimaryBrush}"
|
||||
Style="{StaticResource GhostButtonStyle}">
|
||||
<Button.Flyout>
|
||||
<Flyout>
|
||||
<Flyout.FlyoutPresenterStyle>
|
||||
<Style TargetType="FlyoutPresenter">
|
||||
<Setter Property="CornerRadius" Value="12" />
|
||||
<Setter Property="Padding" Value="0" />
|
||||
</Style>
|
||||
</Flyout.FlyoutPresenterStyle>
|
||||
<Image Height="300" Source="/Assets/WeChatReward.png" />
|
||||
</Flyout>
|
||||
</Button.Flyout>
|
||||
</Button>
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal" Spacing="6">
|
||||
<TextBlock Foreground="{ThemeResource TextFillColorSecondaryBrush}" Text="*" />
|
||||
<TextBlock
|
||||
x:Uid="SetingsPageThanks"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
TextWrapping="Wrap" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</controls:SettingsCard>
|
||||
|
||||
<controls:SettingsCard x:Uid="SettingsPageDiscord" HeaderIcon="{ui:BitmapIcon Source=ms-appx:///Assets/Discord.png}">
|
||||
<Button x:Uid="SettingsPageJoinNowButton" Click="DiscodGroupButton_Click" />
|
||||
</controls:SettingsCard>
|
||||
</controls:SettingsExpander.Items>
|
||||
<controls:SettingsExpander.ItemsHeader>
|
||||
<InfoBar
|
||||
BorderThickness="0"
|
||||
CornerRadius="0"
|
||||
IsClosable="False"
|
||||
IsOpen="True"
|
||||
Severity="Warning">
|
||||
<TextBlock
|
||||
x:Uid="SettingsPageDisclaimer"
|
||||
Margin="12"
|
||||
Foreground="{ThemeResource SystemFillColorCautionBrush}"
|
||||
TextWrapping="Wrap" />
|
||||
</InfoBar>
|
||||
</controls:SettingsExpander.ItemsHeader>
|
||||
</controls:SettingsExpander>
|
||||
|
||||
<controls:SettingsCard x:Uid="SettingsPageTelegram" HeaderIcon="{ui:BitmapIcon Source=ms-appx:///Assets/Telegram.png}">
|
||||
<Button x:Uid="SettingsPageJoinNowButton" Click="TelegramGroupButton_Click" />
|
||||
</controls:SettingsCard>
|
||||
<TextBlock x:Uid="SetingsPageRef" Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" />
|
||||
|
||||
<ListView
|
||||
Padding="0,6"
|
||||
Background="{ThemeResource CardBackgroundFillColorDefault}"
|
||||
CornerRadius="4"
|
||||
ItemsSource="{x:Bind ViewModel.Libs, Mode=OneWay}"
|
||||
SelectionMode="None">
|
||||
<ListView.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<RelativePanel Padding="42,0">
|
||||
<HyperlinkButton
|
||||
Margin="-12,0,0,0"
|
||||
Content="{Binding Name}"
|
||||
NavigateUri="{Binding Url}"
|
||||
RelativePanel.AlignLeftWithPanel="True"
|
||||
RelativePanel.AlignVerticalCenterWithPanel="True" />
|
||||
<TextBlock
|
||||
RelativePanel.AlignRightWithPanel="True"
|
||||
RelativePanel.AlignVerticalCenterWithPanel="True"
|
||||
Text="{Binding Version}" />
|
||||
</RelativePanel>
|
||||
</DataTemplate>
|
||||
</ListView.ItemTemplate>
|
||||
</ListView>
|
||||
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
@@ -29,20 +29,5 @@ namespace BetterLyrics.WinUI3.Views
|
||||
{
|
||||
ViewModel.NavViewSelectedItemTag = (args.SelectedItem as NavigationViewItem)!.Tag;
|
||||
}
|
||||
|
||||
private void QQGroupButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
Launcher.LaunchUriAsync(new Uri(Constants.Link.QQGroupUrl));
|
||||
}
|
||||
|
||||
private void DiscodGroupButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
Launcher.LaunchUriAsync(new Uri(Constants.Link.DiscordUrl));
|
||||
}
|
||||
|
||||
private void TelegramGroupButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
Launcher.LaunchUriAsync(new Uri(Constants.Link.TelegramUrl));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BIN
Donate/Alipay.jpg
Normal file
|
After Width: | Height: | Size: 140 KiB |
BIN
Donate/WeChatReward.png
Normal file
|
After Width: | Height: | Size: 209 KiB |
40
FAQ/FAQ.md
@@ -1,14 +1,34 @@
|
||||
## FAQ has been moved
|
||||
[Click here to visit](https://github.com/jayfunc/BetterLyrics?tab=readme-ov-file#faq)
|
||||
### Where I can find the logs?
|
||||
`C:\Users\%USERNAME%\AppData\Local\Packages\37412.BetterLyrics_rd1g0rsrrtxw8\LocalCache\logs`
|
||||
|
||||
## FAQ 现已迁移
|
||||
[点此访问](https://github.com/jayfunc/BetterLyrics/blob/dev/README.zh-CN.md#faq)
|
||||
### How to install ".msixbundle" package?
|
||||
[See this doc](https://github.com/jayfunc/BetterLyrics/blob/dev/How2Install/How2Install.md)
|
||||
|
||||
## FAQ 已移至新位置
|
||||
[點此前往](https://github.com/jayfunc/BetterLyrics/blob/dev/README.zh-TW.md#faq)
|
||||
### Lyrics are moving back and forth constantly, how to fix it?
|
||||

|
||||
|
||||
## FAQ は移動しました
|
||||
[こちらをクリック](https://github.com/jayfunc/BetterLyrics/blob/dev/README.ja.md#faq)
|
||||
Go to Settings > Playback sources > Disable "Lyrics timeline sync" or increase "Lyrics timeline sync threshold"
|
||||
|
||||
## FAQ가 이동되었습니다
|
||||
[여기를 클릭하세요](https://github.com/jayfunc/BetterLyrics/blob/dev/README.ko.md#faq)
|
||||
### Wrong lyrics are shown, how to fix it?
|
||||

|
||||
|
||||
Open search panel to manually search for the correct lyrics.
|
||||
|
||||
### Playback control panel is not showing in dock mode, how to fix it?
|
||||

|
||||
|
||||
Hover over the bottom of the lyrics window and click on the white line to show the playback control panel.
|
||||
|
||||
### How to lock/unlock the lyrics window in desktop mode?
|
||||

|
||||
|
||||

|
||||
|
||||
Alternatively, you can also use the shortcut `Ctrl+Alt+U` (default) to toggle lock/unlock.
|
||||
|
||||

|
||||
|
||||
You can change the shortcut in Settings > App appearance and behavior > Unlock and lock shortcut keys
|
||||
|
||||
### How to enable/disable immersive mode?
|
||||

|
||||
BIN
FAQ/Snipaste_2025-08-22_14-47-21.png
Normal file
|
After Width: | Height: | Size: 151 KiB |
BIN
FAQ/Snipaste_2025-08-22_14-50-16.png
Normal file
|
After Width: | Height: | Size: 33 KiB |
BIN
FAQ/Snipaste_2025-08-22_14-52-53.png
Normal file
|
After Width: | Height: | Size: 34 KiB |
BIN
FAQ/Snipaste_2025-08-22_14-53-21.png
Normal file
|
After Width: | Height: | Size: 36 KiB |
BIN
FAQ/Snipaste_2025-08-22_14-53-58.png
Normal file
|
After Width: | Height: | Size: 148 KiB |
BIN
FAQ/Snipaste_2025-08-22_14-58-44.png
Normal file
|
After Width: | Height: | Size: 157 KiB |
BIN
FAQ/Snipaste_2025-08-22_14-59-53.png
Normal file
|
After Width: | Height: | Size: 79 KiB |
BIN
FAQ/image-1.png
|
Before Width: | Height: | Size: 510 KiB |
BIN
FAQ/image-10.png
|
Before Width: | Height: | Size: 224 KiB |
BIN
FAQ/image-11.png
|
Before Width: | Height: | Size: 221 KiB |