Compare commits
47 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
94b22552e5 | ||
|
|
6deb16f6cb | ||
|
|
e467ab9c73 | ||
|
|
ea038c9c56 | ||
|
|
560250ad30 | ||
|
|
536acc69a5 | ||
|
|
0bbb379912 | ||
|
|
1f4d29e6f2 | ||
|
|
5d1d7476c9 | ||
|
|
e016baefe1 | ||
|
|
70b6194788 | ||
|
|
9f103b0ea3 | ||
|
|
2924140f95 | ||
|
|
3d3f168926 | ||
|
|
63b2285a36 | ||
|
|
780689fa05 | ||
|
|
01384717c4 | ||
|
|
e18d78170a | ||
|
|
023bf77afc | ||
|
|
2877ac2101 | ||
|
|
16d82109bb | ||
|
|
c703f04119 | ||
|
|
998853f9d2 | ||
|
|
f560735da0 | ||
|
|
ab9da73b49 | ||
|
|
dc364edf75 | ||
|
|
7fbc8fbfe7 | ||
|
|
4a00bb2ddf | ||
|
|
7472aa048f | ||
|
|
49b0f7a692 | ||
|
|
4d0602ebef | ||
|
|
626395d93a | ||
|
|
0ab5602569 | ||
|
|
37a7528762 | ||
|
|
3ca391a509 | ||
|
|
f5e542d2f3 | ||
|
|
107bdf8bee | ||
|
|
3e9e56f5cc | ||
|
|
b0fd43ead5 | ||
|
|
81c59495c0 | ||
|
|
7c5f1a804e | ||
|
|
13ee4227f7 | ||
|
|
c1360ac972 | ||
|
|
c72aa8a58f | ||
|
|
9545ed610b | ||
|
|
1c4515acb9 | ||
|
|
92a6fe46de |
@@ -12,13 +12,13 @@
|
||||
<Identity
|
||||
Name="37412.BetterLyrics"
|
||||
Publisher="CN=E1428B0E-DC1D-4EA4-ACB1-4556569D5BA9"
|
||||
Version="1.0.61.0" />
|
||||
Version="1.0.75.0" />
|
||||
|
||||
<mp:PhoneIdentity PhoneProductId="ca4a4830-fc19-40d9-b823-53e2bff3d816" PhonePublisherId="00000000-0000-0000-0000-000000000000"/>
|
||||
|
||||
<Properties>
|
||||
<DisplayName>BetterLyrics</DisplayName>
|
||||
<PublisherDisplayName>founchoo</PublisherDisplayName>
|
||||
<PublisherDisplayName>Zhe Fang</PublisherDisplayName>
|
||||
<Logo>Images\StoreLogo.png</Logo>
|
||||
</Properties>
|
||||
|
||||
|
||||
@@ -58,6 +58,7 @@
|
||||
<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" />
|
||||
|
||||
BIN
BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/Alipay.jpg
Normal file
|
After Width: | Height: | Size: 140 KiB |
|
Before Width: | Height: | Size: 14 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 |
@@ -32,6 +32,7 @@
|
||||
<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" />
|
||||
@@ -59,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" />
|
||||
@@ -71,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" />
|
||||
@@ -78,7 +81,6 @@
|
||||
<PackageReference Include="System.Drawing.Common" Version="9.0.8" />
|
||||
<PackageReference Include="System.Text.Encoding.CodePages" Version="9.0.8" />
|
||||
<PackageReference Include="TagLibSharp" Version="2.3.0" />
|
||||
<PackageReference Include="TinyPinyin.Net" Version="1.0.2" />
|
||||
<PackageReference Include="Ude.NetStandard" Version="1.2.0" />
|
||||
<PackageReference Include="Vanara.PInvoke.CoreAudio" Version="4.1.6" />
|
||||
<PackageReference Include="Vanara.PInvoke.DwmApi" Version="4.1.6" />
|
||||
@@ -112,9 +114,6 @@
|
||||
<Content Update="Assets\Chrome.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\Discord.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\Edge.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
@@ -166,9 +165,6 @@
|
||||
<Content Update="Assets\PotPlayer.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\QQ.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\QQMusic.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
@@ -181,13 +177,15 @@
|
||||
<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>
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Constants
|
||||
{
|
||||
public static class AppleMusic
|
||||
{
|
||||
public const string MediaUserTokenKey = "AppleMusicMediaUserToken";
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,6 @@ namespace BetterLyrics.WinUI3.Constants
|
||||
{
|
||||
public static class LXMusic
|
||||
{
|
||||
public const string QuerySuffix = "/subscribe-player-status?filter=progress,duration";
|
||||
public const string QuerySuffix = "/subscribe-player-status?filter=progress,duration,picUrl";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,61 +13,61 @@
|
||||
|
||||
<Grid Padding="16" RowSpacing="6">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid Grid.Row="0" Margin="0,0,0,6">
|
||||
<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.Row="1">
|
||||
<Grid Grid.Row="0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="2*" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid Grid.Column="0" RowSpacing="12">
|
||||
<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>
|
||||
@@ -144,7 +144,7 @@
|
||||
ShowPaused="False"
|
||||
Visibility="{x:Bind ViewModel.IsSearching, Converter={StaticResource BoolToVisibilityConverter}, Mode=OneWay}" />
|
||||
</Grid>
|
||||
<Grid Grid.Column="1">
|
||||
<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
|
||||
@@ -197,7 +197,7 @@
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid Grid.Row="2">
|
||||
<Grid Grid.Row="1">
|
||||
<RelativePanel>
|
||||
<TextBlock
|
||||
x:Uid="LyricsSearchControlHelp"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -231,42 +231,60 @@
|
||||
IsExpanded="True">
|
||||
<ToggleSwitch IsOn="{x:Bind ViewModel.AppSettings.TranslationSettings.IsTranslationEnabled, Mode=TwoWay}" />
|
||||
<controls:SettingsExpander.Items>
|
||||
<controls:SettingsCard x:Uid="SettingsPageTargetLanguage">
|
||||
<ComboBox SelectedIndex="{x:Bind ViewModel.AppSettings.TranslationSettings.SelectedTargetLanguageIndex, Mode=TwoWay}">
|
||||
<controls:SettingsCard x:Uid="SettingsPageTargetLanguage" IsEnabled="{x:Bind ViewModel.AppSettings.TranslationSettings.IsTranslationEnabled, Mode=OneWay}">
|
||||
<ComboBox SelectedIndex="{x:Bind ViewModel.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="bg" />
|
||||
<ComboBoxItem Content="বাংলা" Tag="bn" />
|
||||
<ComboBoxItem Content="Català" Tag="ca" />
|
||||
<ComboBoxItem Content="Čeština" Tag="cs" />
|
||||
<ComboBoxItem Content="Dansk" Tag="da" />
|
||||
<ComboBoxItem Content="Nederlands" Tag="nl" />
|
||||
<ComboBoxItem Content="English" Tag="en" />
|
||||
<ComboBoxItem Content="Esperanto" Tag="eo" />
|
||||
<ComboBoxItem Content="Suomi" Tag="fi" />
|
||||
<ComboBoxItem Content="Français" Tag="fr" />
|
||||
<ComboBoxItem Content="Deutsch" Tag="de" />
|
||||
<ComboBoxItem Content="Ελληνικά" Tag="el" />
|
||||
<ComboBoxItem Content="English" Tag="en" />
|
||||
<ComboBoxItem Content="Esperanto" Tag="eo" />
|
||||
<ComboBoxItem Content="Español" Tag="es" />
|
||||
<ComboBoxItem Content="Eesti" Tag="et" />
|
||||
<ComboBoxItem Content="Euskara" Tag="eu" />
|
||||
<ComboBoxItem Content="فارسی" Tag="fa" />
|
||||
<ComboBoxItem Content="Suomi" Tag="fi" />
|
||||
<ComboBoxItem Content="Français" Tag="fr" />
|
||||
<ComboBoxItem Content="Gaeilge" Tag="ga" />
|
||||
<ComboBoxItem Content="Galego" Tag="gl" />
|
||||
<ComboBoxItem Content="עברית" Tag="he" />
|
||||
<ComboBoxItem Content="हिन्दी" Tag="hi" />
|
||||
<ComboBoxItem Content="Magyar" Tag="hu" />
|
||||
<ComboBoxItem Content="Bahasa Indonesia" Tag="id" />
|
||||
<ComboBoxItem Content="Gaeilge" Tag="ga" />
|
||||
<ComboBoxItem Content="Italiano" Tag="it" />
|
||||
<ComboBoxItem Content="日本語" Tag="ja" />
|
||||
<ComboBoxItem Content="한국어" Tag="ko" />
|
||||
<ComboBoxItem Content="فارسی" Tag="fa" />
|
||||
<ComboBoxItem Content="Кыргызча" Tag="ky" />
|
||||
<ComboBoxItem Content="Lietuvių" Tag="lt" />
|
||||
<ComboBoxItem Content="Latviešu" Tag="lv" />
|
||||
<ComboBoxItem Content="Bahasa Melayu" Tag="ms" />
|
||||
<ComboBoxItem Content="Norsk bokmål" Tag="nb" />
|
||||
<ComboBoxItem Content="Nederlands" Tag="nl" />
|
||||
<ComboBoxItem Content="Português (Brasil)" Tag="pt-BR" />
|
||||
<ComboBoxItem Content="Polski" Tag="pl" />
|
||||
<ComboBoxItem Content="Português" Tag="pt" />
|
||||
<ComboBoxItem Content="Română" Tag="ro" />
|
||||
<ComboBoxItem Content="Русский" Tag="ru" />
|
||||
<ComboBoxItem Content="Slovenčina" Tag="sk" />
|
||||
<ComboBoxItem Content="Español" Tag="es" />
|
||||
<ComboBoxItem Content="Slovenščina" Tag="sl" />
|
||||
<ComboBoxItem Content="Shqip" Tag="sq" />
|
||||
<ComboBoxItem Content="Српски" Tag="sr" />
|
||||
<ComboBoxItem Content="Svenska" Tag="sv" />
|
||||
<ComboBoxItem Content="ไทย" Tag="th" />
|
||||
<ComboBoxItem Content="Filipino" Tag="tl" />
|
||||
<ComboBoxItem Content="Türkçe" Tag="tr" />
|
||||
<ComboBoxItem Content="Українська" Tag="uk" />
|
||||
<ComboBoxItem Content="اردو" Tag="ur" />
|
||||
<ComboBoxItem Content="Tiếng Việt" Tag="vi" />
|
||||
<ComboBoxItem Content="中文" Tag="zh" />
|
||||
</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
|
||||
@@ -295,6 +313,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>
|
||||
@@ -315,6 +356,26 @@
|
||||
IsEnabled="{x:Bind ViewModel.IsLXMusicServerTesting, Converter={StaticResource BoolNegationConverter}, Mode=OneWay}" />
|
||||
</StackPanel>
|
||||
</controls:SettingsCard>
|
||||
<!-- Apple Music token -->
|
||||
<TextBlock Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" Text="media-user-token (for Apple Muisc)" />
|
||||
<controls:SettingsCard
|
||||
Background="{ThemeResource SystemFillColorCautionBackgroundBrush}"
|
||||
Foreground="{ThemeResource SystemFillColorCautionBrush}"
|
||||
Header="Use at your own risk">
|
||||
<StackPanel Orientation="Horizontal" Spacing="6">
|
||||
<TextBox
|
||||
MaxWidth="250"
|
||||
PlaceholderText="media-user-token"
|
||||
Text="{x:Bind ViewModel.AppleMusicMediaUserToken, Mode=TwoWay}"
|
||||
TextWrapping="Wrap" />
|
||||
<Button
|
||||
Command="{x:Bind ViewModel.SaveAppleMusicMediaUserTokenCommand}"
|
||||
Content="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
|
||||
FontSize=12,
|
||||
Glyph=}"
|
||||
Style="{StaticResource GhostButtonStyle}" />
|
||||
</StackPanel>
|
||||
</controls:SettingsCard>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</ScrollViewer>
|
||||
|
||||
@@ -19,6 +19,7 @@ namespace BetterLyrics.WinUI3.Converter
|
||||
LyricsSearchProvider.Netease => "网易云音乐",
|
||||
LyricsSearchProvider.Kugou => "酷狗音乐",
|
||||
LyricsSearchProvider.AmllTtmlDb => "amll-ttml-db",
|
||||
LyricsSearchProvider.AppleMusic => "Apple Music",
|
||||
LyricsSearchProvider.LocalLrcFile => App.ResourceLoader!.GetString("LyricsSearchProviderLocalLrcFile"),
|
||||
LyricsSearchProvider.LocalMusicFile => App.ResourceLoader!.GetString("LyricsSearchProviderLocalMusicFile"),
|
||||
LyricsSearchProvider.LocalEslrcFile => App.ResourceLoader!.GetString("LyricsSearchProviderEslrcFile"),
|
||||
|
||||
@@ -2,10 +2,6 @@
|
||||
using BetterLyrics.WinUI3.Helper;
|
||||
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
|
||||
{
|
||||
@@ -19,6 +15,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,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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,7 @@ namespace BetterLyrics.WinUI3.Converter
|
||||
TranslationSearchProvider.Netease => "网易云音乐",
|
||||
TranslationSearchProvider.Kugou => "酷狗音乐",
|
||||
TranslationSearchProvider.AmllTtmlDb => "amll-ttml-db",
|
||||
TranslationSearchProvider.AppleMusic => "Apple Music",
|
||||
TranslationSearchProvider.LocalLrcFile => App.ResourceLoader!.GetString("LyricsSearchProviderLocalLrcFile"),
|
||||
TranslationSearchProvider.LocalMusicFile => App.ResourceLoader!.GetString("LyricsSearchProviderLocalMusicFile"),
|
||||
TranslationSearchProvider.LocalEslrcFile => App.ResourceLoader!.GetString("LyricsSearchProviderEslrcFile"),
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,7 @@ namespace BetterLyrics.WinUI3.Enums
|
||||
LocalLrcFile,
|
||||
LocalEslrcFile,
|
||||
LocalTtmlFile,
|
||||
AppleMusic,
|
||||
}
|
||||
|
||||
public static class LyricsSearchProviderExtensions
|
||||
@@ -28,6 +29,7 @@ namespace BetterLyrics.WinUI3.Enums
|
||||
LyricsSearchProvider.Netease => PathHelper.NeteaseLyricsCacheDirectory,
|
||||
LyricsSearchProvider.Kugou => PathHelper.KugouLyricsCacheDirectory,
|
||||
LyricsSearchProvider.AmllTtmlDb => PathHelper.AmllTtmlDbLyricsCacheDirectory,
|
||||
LyricsSearchProvider.AppleMusic => PathHelper.AppleMusicCacheDirectory,
|
||||
_ => throw new System.ArgumentOutOfRangeException(nameof(provider)),
|
||||
};
|
||||
}
|
||||
@@ -41,6 +43,7 @@ namespace BetterLyrics.WinUI3.Enums
|
||||
LyricsSearchProvider.Kugou => LyricsFormat.Krc,
|
||||
LyricsSearchProvider.Netease => LyricsFormat.Lrc,
|
||||
LyricsSearchProvider.AmllTtmlDb => LyricsFormat.Ttml,
|
||||
LyricsSearchProvider.AppleMusic => LyricsFormat.Ttml,
|
||||
LyricsSearchProvider.LocalLrcFile => LyricsFormat.Lrc,
|
||||
LyricsSearchProvider.LocalEslrcFile => LyricsFormat.Eslrc,
|
||||
LyricsSearchProvider.LocalTtmlFile => LyricsFormat.Ttml,
|
||||
@@ -71,6 +74,7 @@ namespace BetterLyrics.WinUI3.Enums
|
||||
LyricsSearchProvider.Kugou => TranslationSearchProvider.Kugou,
|
||||
LyricsSearchProvider.Netease => TranslationSearchProvider.Netease,
|
||||
LyricsSearchProvider.AmllTtmlDb => TranslationSearchProvider.AmllTtmlDb,
|
||||
LyricsSearchProvider.AppleMusic => TranslationSearchProvider.AppleMusic,
|
||||
LyricsSearchProvider.LocalMusicFile => TranslationSearchProvider.LocalMusicFile,
|
||||
LyricsSearchProvider.LocalLrcFile => TranslationSearchProvider.LocalLrcFile,
|
||||
LyricsSearchProvider.LocalEslrcFile => TranslationSearchProvider.LocalEslrcFile,
|
||||
|
||||
@@ -8,7 +8,8 @@ namespace BetterLyrics.WinUI3.Enums
|
||||
{
|
||||
public enum ShortcutID
|
||||
{
|
||||
DesktopLock,
|
||||
LyricsWindowShowOrHide,
|
||||
DesktopLockOrUnlock,
|
||||
DesktopToggle,
|
||||
DockToggle,
|
||||
PictureInPictureToggle,
|
||||
|
||||
@@ -13,6 +13,7 @@ namespace BetterLyrics.WinUI3.Enums
|
||||
Netease,
|
||||
LrcLib,
|
||||
AmllTtmlDb,
|
||||
AppleMusic,
|
||||
LocalMusicFile,
|
||||
LocalLrcFile,
|
||||
LocalEslrcFile,
|
||||
|
||||
126
BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/AppleMusic.cs
Normal file
@@ -0,0 +1,126 @@
|
||||
using BetterLyrics.WinUI3.Constants;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Helper
|
||||
{
|
||||
public class AppleMusic
|
||||
{
|
||||
private readonly HttpClient _client;
|
||||
private string _accessToken = "";
|
||||
private string _storefront = "";
|
||||
private string _language = "";
|
||||
|
||||
public AppleMusic()
|
||||
{
|
||||
_client = new HttpClient();
|
||||
_client.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36");
|
||||
_client.DefaultRequestHeaders.Add("Accept", "application/json");
|
||||
_client.DefaultRequestHeaders.Add("Origin", "https://music.apple.com");
|
||||
_client.DefaultRequestHeaders.Add("Referer", "https://music.apple.com/");
|
||||
}
|
||||
|
||||
public async Task<bool> InitAsync()
|
||||
{
|
||||
await GetAccessTokenAsync();
|
||||
await SetMediaUserTokenAsync();
|
||||
return
|
||||
!string.IsNullOrEmpty(_accessToken) &&
|
||||
!string.IsNullOrEmpty(PasswordVaultHelper.Get(Constants.App.AppName, Constants.AppleMusic.MediaUserTokenKey));
|
||||
}
|
||||
|
||||
private async Task GetAccessTokenAsync()
|
||||
{
|
||||
var resp = await _client.GetStringAsync("https://music.apple.com/us/browse");
|
||||
var jsMatch = Regex.Match(resp, "(?<=index)(.*?)(?=\\.js\")");
|
||||
if (!jsMatch.Success) throw new Exception("Failed to find index.js");
|
||||
var jsUrl = $"https://music.apple.com/assets/index{jsMatch.Value}.js";
|
||||
var jsResp = await _client.GetStringAsync(jsUrl);
|
||||
var tokenMatch = Regex.Match(jsResp, "(?=eyJh)(.*?)(?=\")");
|
||||
if (!tokenMatch.Success) throw new Exception("Failed to find access token");
|
||||
_accessToken = tokenMatch.Value;
|
||||
_client.DefaultRequestHeaders.Remove("Authorization");
|
||||
_client.DefaultRequestHeaders.Add("Authorization", $"Bearer {_accessToken}");
|
||||
}
|
||||
|
||||
private async Task SetMediaUserTokenAsync()
|
||||
{
|
||||
_client.DefaultRequestHeaders.Remove("media-user-token");
|
||||
_client.DefaultRequestHeaders.Add("media-user-token",
|
||||
PasswordVaultHelper.Get(Constants.App.AppName, Constants.AppleMusic.MediaUserTokenKey));
|
||||
var resp = await _client.GetStringAsync("https://amp-api.music.apple.com/v1/me/storefront");
|
||||
var json = JsonSerializer.Deserialize(resp, Serialization.SourceGenerationContext.Default.JsonElement);
|
||||
_storefront = json.GetProperty("data")[0].GetProperty("id").ToString();
|
||||
_language = json.GetProperty("data")[0].GetProperty("attributes").GetProperty("defaultLanguageTag").ToString();
|
||||
_client.DefaultRequestHeaders.Remove("Accept-Language");
|
||||
_client.DefaultRequestHeaders.Add("Accept-Language", $"{_language},en;q=0.9");
|
||||
}
|
||||
|
||||
public async Task<string?> GetLyricsAsync(string title, string artist)
|
||||
{
|
||||
string id = await SearchSongInfoAsync(artist, title);
|
||||
|
||||
var apiUrl = $"https://amp-api.music.apple.com/v1/catalog/{_storefront}/songs/{id}";
|
||||
var url = apiUrl + $"?include[songs]=lyrics,syllable-lyrics&l={_language}";
|
||||
var resp = await _client.GetStringAsync(url);
|
||||
var json = JsonSerializer.Deserialize(resp, Serialization.SourceGenerationContext.Default.JsonElement);
|
||||
var data = json.GetProperty("data");
|
||||
if (data.GetArrayLength() == 0) return string.Empty;
|
||||
var song = data[0];
|
||||
|
||||
if (!song.TryGetProperty("relationships", out var relationships))
|
||||
return string.Empty;
|
||||
|
||||
if (relationships.TryGetProperty("syllable-lyrics", out var syllableLyrics) &&
|
||||
syllableLyrics.GetProperty("data").GetArrayLength() > 0)
|
||||
{
|
||||
var syllableLyric = syllableLyrics.GetProperty("data")[0];
|
||||
if (syllableLyric.TryGetProperty("attributes", out var attributes) &&
|
||||
attributes.TryGetProperty("ttml", out var ttml))
|
||||
{
|
||||
string? raw = ttml.GetString();
|
||||
if (raw != null && raw.Contains("begin=") && raw.Contains("end="))
|
||||
{
|
||||
return raw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//if (relationships.TryGetProperty("lyrics", out var lyrics) &&
|
||||
// lyrics.GetProperty("data").GetArrayLength() > 0)
|
||||
//{
|
||||
// var lyric = lyrics.GetProperty("data")[0];
|
||||
// if (lyric.TryGetProperty("attributes", out var attributes) &&
|
||||
// attributes.TryGetProperty("ttml", out var ttml))
|
||||
// {
|
||||
// return ttml.GetString();
|
||||
// }
|
||||
//}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private async Task<string> SearchSongInfoAsync(string artist, string title)
|
||||
{
|
||||
var query = $"{artist} {title}";
|
||||
var apiUrl = $"https://amp-api.music.apple.com/v1/catalog/{_storefront}/search";
|
||||
var url = apiUrl + $"?term={WebUtility.UrlEncode(query)}&types=songs&limit=1&l={_language}";
|
||||
var resp = await _client.GetStringAsync(url);
|
||||
var json = JsonSerializer.Deserialize(resp, Serialization.SourceGenerationContext.Default.JsonElement);
|
||||
var results = json.GetProperty("results");
|
||||
if (results.TryGetProperty("songs", out var songs) && songs.GetProperty("data").GetArrayLength() > 0)
|
||||
{
|
||||
var song = songs.GetProperty("data")[0];
|
||||
return song.GetProperty("id").ToString();
|
||||
}
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
{
|
||||
// 确保亮度因子在合理范围内
|
||||
|
||||
@@ -14,6 +14,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Numerics;
|
||||
using System.Runtime.InteropServices.WindowsRuntime;
|
||||
using System.Threading.Tasks;
|
||||
@@ -219,5 +220,68 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
}
|
||||
return pixelData;
|
||||
}
|
||||
|
||||
public static async Task<byte[]> DownloadImageAsByteArrayAsync(string url)
|
||||
{
|
||||
using var httpClient = new HttpClient();
|
||||
return await httpClient.GetByteArrayAsync(url);
|
||||
}
|
||||
|
||||
public static byte[]? DataUrlToByteArray(string dataUrl)
|
||||
{
|
||||
const string base64Marker = ";base64,";
|
||||
int base64Index = dataUrl.IndexOf(base64Marker, StringComparison.OrdinalIgnoreCase);
|
||||
if (base64Index >= 0)
|
||||
{
|
||||
string base64Data = dataUrl.Substring(base64Index + base64Marker.Length);
|
||||
return Convert.FromBase64String(base64Data);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 非 base64,直接取逗号后内容并解码
|
||||
int commaIndex = dataUrl.IndexOf(',');
|
||||
if (commaIndex >= 0)
|
||||
{
|
||||
string rawData = dataUrl.Substring(commaIndex + 1);
|
||||
return System.Text.Encoding.UTF8.GetBytes(Uri.UnescapeDataString(rawData));
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task<byte[]?> GetImageBytesFromUrlAsync(string url)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(url))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (url.StartsWith("data:", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
// data URL,直接解析
|
||||
return DataUrlToByteArray(url);
|
||||
}
|
||||
else if (Uri.TryCreate(url, UriKind.Absolute, out var uri) &&
|
||||
(uri.Scheme == Uri.UriSchemeHttp || uri.Scheme == Uri.UriSchemeHttps))
|
||||
{
|
||||
// 普通网络图片,下载
|
||||
return await DownloadImageAsByteArrayAsync(url);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 其他类型暂不支持
|
||||
return null;
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,7 @@
|
||||
using BetterLyrics.WinUI3.Helper;
|
||||
using BetterLyrics.WinUI3.Services.SettingsService;
|
||||
using CommunityToolkit.Mvvm.DependencyInjection;
|
||||
using Lyricify.Lyrics.Helpers.General;
|
||||
using NTextCat;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using TinyPinyin;
|
||||
using Windows.Globalization;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Services
|
||||
@@ -18,49 +11,83 @@ namespace BetterLyrics.WinUI3.Services
|
||||
private static readonly RankedLanguageIdentifierFactory _factory = new();
|
||||
private static readonly RankedLanguageIdentifier _identifier;
|
||||
|
||||
public static List<Models.LanguageInfo> SupportedTargetLanguages =>
|
||||
public static List<Models.LanguageInfo> SupportedTargetLanguages { get; set; } =
|
||||
[
|
||||
new Models.LanguageInfo("ar", "العربية"),
|
||||
new Models.LanguageInfo("az", "Azərbaycan dili"),
|
||||
new Models.LanguageInfo("zh-Hans", "简体中文"),
|
||||
new Models.LanguageInfo("zh-Hant", "繁體中文"),
|
||||
|
||||
new Models.LanguageInfo("bg", "Български"),
|
||||
new Models.LanguageInfo("bn", "বাংলা"),
|
||||
|
||||
new Models.LanguageInfo("ca", "Català"),
|
||||
new Models.LanguageInfo("cs", "Čeština"),
|
||||
|
||||
new Models.LanguageInfo("da", "Dansk"),
|
||||
new Models.LanguageInfo("nl", "Nederlands"),
|
||||
new Models.LanguageInfo("de", "Deutsch"),
|
||||
|
||||
new Models.LanguageInfo("el", "Ελληνικά"),
|
||||
new Models.LanguageInfo("en", "English"),
|
||||
new Models.LanguageInfo("eo", "Esperanto"),
|
||||
new Models.LanguageInfo("es", "Español"),
|
||||
new Models.LanguageInfo("et", "Eesti"),
|
||||
new Models.LanguageInfo("eu", "Euskara"),
|
||||
|
||||
new Models.LanguageInfo("fa", "فارسی"),
|
||||
new Models.LanguageInfo("fi", "Suomi"),
|
||||
new Models.LanguageInfo("fr", "Français"),
|
||||
new Models.LanguageInfo("de", "Deutsch"),
|
||||
new Models.LanguageInfo("el", "Ελληνικά"),
|
||||
|
||||
new Models.LanguageInfo("ga", "Gaeilge"),
|
||||
new Models.LanguageInfo("gl", "Galego"),
|
||||
|
||||
new Models.LanguageInfo("he", "עברית"),
|
||||
new Models.LanguageInfo("hi", "हिन्दी"),
|
||||
new Models.LanguageInfo("hu", "Magyar"),
|
||||
|
||||
new Models.LanguageInfo("id", "Bahasa Indonesia"),
|
||||
new Models.LanguageInfo("ga", "Gaeilge"),
|
||||
new Models.LanguageInfo("it", "Italiano"),
|
||||
|
||||
new Models.LanguageInfo("ja", "日本語"),
|
||||
|
||||
new Models.LanguageInfo("ko", "한국어"),
|
||||
new Models.LanguageInfo("fa", "فارسی"),
|
||||
new Models.LanguageInfo("ky", "Кыргызча"),
|
||||
|
||||
new Models.LanguageInfo("lt", "Lietuvių"),
|
||||
new Models.LanguageInfo("lv", "Latviešu"),
|
||||
|
||||
new Models.LanguageInfo("ms", "Bahasa Melayu"),
|
||||
|
||||
new Models.LanguageInfo("nb", "Norsk bokmål"),
|
||||
new Models.LanguageInfo("nl", "Nederlands"),
|
||||
|
||||
new Models.LanguageInfo("pt-BR", "Português (Brasil)"),
|
||||
new Models.LanguageInfo("pl", "Polski"),
|
||||
new Models.LanguageInfo("pt", "Português"),
|
||||
|
||||
new Models.LanguageInfo("ro", "Română"),
|
||||
new Models.LanguageInfo("ru", "Русский"),
|
||||
|
||||
new Models.LanguageInfo("sk", "Slovenčina"),
|
||||
new Models.LanguageInfo("es", "Español"),
|
||||
new Models.LanguageInfo("sl", "Slovenščina"),
|
||||
new Models.LanguageInfo("sq", "Shqip"),
|
||||
new Models.LanguageInfo("sr", "Српски"),
|
||||
new Models.LanguageInfo("sv", "Svenska"),
|
||||
|
||||
new Models.LanguageInfo("th", "ไทย"),
|
||||
new Models.LanguageInfo("tl", "Filipino"),
|
||||
new Models.LanguageInfo("tr", "Türkçe"),
|
||||
|
||||
new Models.LanguageInfo("uk", "Українська"),
|
||||
new Models.LanguageInfo("ur", "اردو"),
|
||||
|
||||
new Models.LanguageInfo("vi", "Tiếng Việt"),
|
||||
|
||||
new Models.LanguageInfo("zh", "中文"),
|
||||
];
|
||||
|
||||
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 +99,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,26 +115,17 @@ namespace BetterLyrics.WinUI3.Services
|
||||
};
|
||||
}
|
||||
|
||||
public static string ConvertToCountryCode(string? languageCode)
|
||||
public static string GetDefaultTargetLanguageCode()
|
||||
{
|
||||
if (languageCode == null) return "us";
|
||||
|
||||
return languageCode switch
|
||||
var found = SupportedTargetLanguages.Find(x => ApplicationLanguages.Languages.FirstOrDefault()?.Contains(x.Code) == true);
|
||||
if (found == null)
|
||||
{
|
||||
"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);
|
||||
if (found == -1) found = 7; // 默认使用英语
|
||||
return found;
|
||||
return "en";
|
||||
}
|
||||
else
|
||||
{
|
||||
return found.Code;
|
||||
}
|
||||
}
|
||||
|
||||
public static string GetOrderChar(string text)
|
||||
@@ -118,12 +135,17 @@ namespace BetterLyrics.WinUI3.Services
|
||||
if (char.IsLetter(c) && c < 128)
|
||||
return char.ToUpper(c).ToString();
|
||||
|
||||
if (PinyinHelper.IsChinese(c))
|
||||
if (Pinyin.Pinyin.Instance.IsHanzi(c.ToString()))
|
||||
{
|
||||
return PinyinHelper.GetPinyinInitials($"{c}");
|
||||
return Pinyin.Pinyin.Instance.HanziToPinyin(c.ToString(), Pinyin.ManTone.Style.NORMAL).ToStr().ToUpper().FirstOrDefault().ToString();
|
||||
}
|
||||
|
||||
return "#";
|
||||
}
|
||||
|
||||
public static string ToRomaji(string text)
|
||||
{
|
||||
return string.Join(" ", RomajiConverter.Core.Helpers.RomajiHelper.SentenceToRomaji(text).Select(x => x.Romaji));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,14 +3,12 @@
|
||||
using BetterLyrics.WinUI3.Enums;
|
||||
using BetterLyrics.WinUI3.Models;
|
||||
using BetterLyrics.WinUI3.Services;
|
||||
using Lyricify.Lyrics.Helpers.General;
|
||||
using Lyricify.Lyrics.Models;
|
||||
using System;
|
||||
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 +46,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()
|
||||
@@ -230,10 +245,11 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
int pStartMs = ParseTtmlTime(pBegin);
|
||||
int pEndMs = ParseTtmlTime(pEnd);
|
||||
|
||||
// 只获取一级span,且排除ttm:role="x-bg"的span
|
||||
// 只获取一级span,且排除 ttm:role="x-bg" 的 span 和 ttm:role="x-roman"
|
||||
var spans = p.Elements()
|
||||
.Where(s => s.Name.LocalName == "span" &&
|
||||
s.Attribute(XName.Get("role", "http://www.w3.org/ns/ttml#metadata"))?.Value != "x-bg")
|
||||
s.Attribute(XName.Get("role", "http://www.w3.org/ns/ttml#metadata"))?.Value != "x-bg" &&
|
||||
s.Attribute(XName.Get("role", "http://www.w3.org/ns/ttml#metadata"))?.Value != "x-roman")
|
||||
.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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,6 +46,7 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
public static string QQLyricsCacheDirectory => Path.Combine(LyricsCacheDirectory, "qq");
|
||||
public static string KugouLyricsCacheDirectory => Path.Combine(LyricsCacheDirectory, "kugou");
|
||||
public static string AmllTtmlDbLyricsCacheDirectory => Path.Combine(LyricsCacheDirectory, "amll-ttml-db");
|
||||
public static string AppleMusicCacheDirectory => Path.Combine(LyricsCacheDirectory, "apple-music");
|
||||
public static string AmllTtmlDbIndexPath => Path.Combine(LyricsCacheDirectory, "amll-ttml-db-index.json");
|
||||
public static string AmllTtmlDbLastUpdatedPath => Path.Combine(LyricsCacheDirectory, "amll-ttml-db-last-updated.txt");
|
||||
|
||||
@@ -53,6 +54,7 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
|
||||
public static string QQTranslationCacheDirectory => Path.Combine(TranslationCacheDirectory, "qq");
|
||||
public static string NeteaseTranslationCacheDirectory => Path.Combine(TranslationCacheDirectory, "netease");
|
||||
public static string KugouTranslationCacheDirectory => Path.Combine(TranslationCacheDirectory, "kugou");
|
||||
|
||||
public static string AlbumArtCacheDirectory => Path.Combine(CacheFolder, "album-art");
|
||||
|
||||
@@ -69,9 +71,11 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
Directory.CreateDirectory(KugouLyricsCacheDirectory);
|
||||
Directory.CreateDirectory(NeteaseLyricsCacheDirectory);
|
||||
Directory.CreateDirectory(AmllTtmlDbLyricsCacheDirectory);
|
||||
Directory.CreateDirectory(AppleMusicCacheDirectory);
|
||||
|
||||
Directory.CreateDirectory(QQTranslationCacheDirectory);
|
||||
Directory.CreateDirectory(NeteaseTranslationCacheDirectory);
|
||||
Directory.CreateDirectory(KugouTranslationCacheDirectory);
|
||||
|
||||
Directory.CreateDirectory(iTunesAlbumArtCacheDirectory);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
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
|
||||
);
|
||||
DemoLyricsWindowBounds = new Rect(
|
||||
(value.X - mointor.rcMonitor.Left) * factor,
|
||||
(value.Y - mointor.rcMonitor.Top) * factor,
|
||||
value.Width * factor,
|
||||
value.Height * factor
|
||||
);
|
||||
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()
|
||||
|
||||
@@ -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,8 +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;
|
||||
@@ -14,7 +15,12 @@ namespace BetterLyrics.WinUI3.Models.Settings
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial string LibreTranslateServer { get; set; } = string.Empty;
|
||||
[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 string SelectedTargetLanguageCode { get; set; } = LanguageHelper.GetDefaultTargetLanguageCode();
|
||||
[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() { }
|
||||
}
|
||||
|
||||
@@ -21,11 +21,14 @@ namespace BetterLyrics.WinUI3.Models
|
||||
public partial double? DurationMs { get; set; }
|
||||
|
||||
[ObservableProperty]
|
||||
public partial string? SourceAppUserModelId { get; set; } = null;
|
||||
public partial string? PlayerId { get; set; } = null;
|
||||
|
||||
[ObservableProperty]
|
||||
public partial string Title { get; set; }
|
||||
|
||||
[ObservableProperty]
|
||||
public partial string? SongId { get; set; } = null;
|
||||
|
||||
public SongInfo() { }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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; }
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
|
||||
{
|
||||
public interface ILyricsSearchService
|
||||
{
|
||||
Task<LyricsSearchResult> SearchSmartlyAsync(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, string? songId, CancellationToken token);
|
||||
|
||||
Task<List<LyricsSearchResult>> SearchAllAsync(string title, string artist, string album, double durationMs, CancellationToken token);
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
|
||||
{
|
||||
private readonly HttpClient _amllTtmlDbHttpClient;
|
||||
private readonly HttpClient _lrcLibHttpClient;
|
||||
private readonly AppleMusic _appleMusic;
|
||||
|
||||
private readonly ISettingsService _settingsService;
|
||||
private readonly ILogger _logger;
|
||||
@@ -40,9 +41,10 @@ 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();
|
||||
_appleMusic = new AppleMusic();
|
||||
}
|
||||
|
||||
private static bool IsAmllTtmlDbIndexInvalid()
|
||||
@@ -89,7 +91,7 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<LyricsSearchResult> SearchSmartlyAsync(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, string? songId, CancellationToken token)
|
||||
{
|
||||
var lyricsSearchResult = new LyricsSearchResult();
|
||||
|
||||
@@ -121,7 +123,7 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
|
||||
var targetProvider = found.LyricsSearchProvider;
|
||||
if (targetProvider != null)
|
||||
{
|
||||
return await SearchSingleAsync(targetProvider.Value, overridenTitle, overridenArtist, album, durationMs, token);
|
||||
return await SearchSingleAsync(targetProvider.Value, overridenTitle, overridenArtist, album, durationMs, songId, token);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,7 +134,7 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
|
||||
continue;
|
||||
}
|
||||
|
||||
lyricsSearchResult = await SearchSingleAsync(provider.Provider, overridenTitle, overridenArtist, album, durationMs, token);
|
||||
lyricsSearchResult = await SearchSingleAsync(provider.Provider, overridenTitle, overridenArtist, album, durationMs, null, token);
|
||||
|
||||
if (lyricsSearchResult.IsFound)
|
||||
{
|
||||
@@ -149,13 +151,13 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
|
||||
var results = new List<LyricsSearchResult>();
|
||||
foreach (var provider in Enum.GetValues<LyricsSearchProvider>())
|
||||
{
|
||||
var searchResult = await SearchSingleAsync(provider, title, artist, album, durationMs, token);
|
||||
var searchResult = await SearchSingleAsync(provider, title, artist, album, durationMs, null, token);
|
||||
results.Add(searchResult);
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
private async Task<LyricsSearchResult> SearchSingleAsync(LyricsSearchProvider provider, string title, string artist, string album, double durationMs, CancellationToken token)
|
||||
private async Task<LyricsSearchResult> SearchSingleAsync(LyricsSearchProvider provider, string title, string artist, string album, double durationMs, string? songId, CancellationToken token)
|
||||
{
|
||||
var lyricsSearchResult = new LyricsSearchResult
|
||||
{
|
||||
@@ -198,17 +200,20 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
|
||||
lyricsSearchResult = await SearchLrcLibAsync(title, artist, album, (int)(durationMs / 1000));
|
||||
break;
|
||||
case LyricsSearchProvider.QQ:
|
||||
lyricsSearchResult = await SearchQQNeteaseKugouAsync(title, artist, album, (int)durationMs, Searchers.QQMusic);
|
||||
lyricsSearchResult = await SearchQQNeteaseKugouAsync(title, artist, album, (int)durationMs, songId, Searchers.QQMusic);
|
||||
break;
|
||||
case LyricsSearchProvider.Kugou:
|
||||
lyricsSearchResult = await SearchQQNeteaseKugouAsync(title, artist, album, (int)durationMs, Searchers.Kugou);
|
||||
lyricsSearchResult = await SearchQQNeteaseKugouAsync(title, artist, album, (int)durationMs, songId, Searchers.Kugou);
|
||||
break;
|
||||
case LyricsSearchProvider.Netease:
|
||||
lyricsSearchResult = await SearchQQNeteaseKugouAsync(title, artist, album, (int)durationMs, Searchers.Netease);
|
||||
lyricsSearchResult = await SearchQQNeteaseKugouAsync(title, artist, album, (int)durationMs, songId, Searchers.Netease);
|
||||
break;
|
||||
case LyricsSearchProvider.AmllTtmlDb:
|
||||
lyricsSearchResult = await SearchAmllTtmlDbAsync(title, artist);
|
||||
break;
|
||||
case LyricsSearchProvider.AppleMusic:
|
||||
lyricsSearchResult = await SearchAppleMusicAsync(title, artist, album, (int)durationMs);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -431,7 +436,7 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
|
||||
return lyricsSearchResult;
|
||||
}
|
||||
|
||||
private static async Task<LyricsSearchResult> 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, string? songId, Searchers searchers)
|
||||
{
|
||||
var lyricsSearchResult = new LyricsSearchResult();
|
||||
|
||||
@@ -452,15 +457,23 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
|
||||
break;
|
||||
}
|
||||
|
||||
var result = await SearchersHelper.GetSearcher(searchers).SearchForResult(
|
||||
new Lyricify.Lyrics.Models.TrackMultiArtistMetadata()
|
||||
{
|
||||
DurationMs = durationMs,
|
||||
Album = album,
|
||||
Artists = [artist],
|
||||
Title = title,
|
||||
}
|
||||
);
|
||||
ISearchResult? result;
|
||||
if (searchers == Searchers.Netease && songId != null)
|
||||
{
|
||||
result = new NeteaseSearchResult(title, [artist], album, null, durationMs, songId);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = await SearchersHelper.GetSearcher(searchers).SearchForResult(
|
||||
new Lyricify.Lyrics.Models.TrackMultiArtistMetadata()
|
||||
{
|
||||
DurationMs = durationMs,
|
||||
Album = album,
|
||||
Artists = [artist],
|
||||
Title = title,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
if (result is QQMusicSearchResult qqResult)
|
||||
{
|
||||
@@ -508,7 +521,21 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
|
||||
string? original = null;
|
||||
if (response?.Candidates.FirstOrDefault() is SearchLyricsResponse.Candidate candidate)
|
||||
{
|
||||
original = Lyricify.Lyrics.Decrypter.Krc.Helper.GetLyrics(candidate.Id, candidate.AccessKey);
|
||||
original = await Lyricify.Lyrics.Decrypter.Krc.Helper.GetLyricsAsync(candidate.Id, candidate.AccessKey);
|
||||
if (candidate.TransId != null)
|
||||
{
|
||||
string? translated = await Lyricify.Lyrics.Decrypter.Krc.Helper.GetLyricsAsync(candidate.TransId, candidate.AccessKey);
|
||||
if (!string.IsNullOrEmpty(translated))
|
||||
{
|
||||
FileHelper.WriteLyricsCache(
|
||||
title,
|
||||
artist,
|
||||
translated,
|
||||
LyricsFormat.Lrc,
|
||||
PathHelper.KugouTranslationCacheDirectory
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lyricsSearchResult.Raw = original;
|
||||
@@ -518,5 +545,24 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
|
||||
|
||||
return lyricsSearchResult;
|
||||
}
|
||||
|
||||
private async Task<LyricsSearchResult> SearchAppleMusicAsync(string title, string artist, string album, int durationMs)
|
||||
{
|
||||
var lyricsSearchResult = new LyricsSearchResult
|
||||
{
|
||||
Provider = LyricsSearchProvider.AppleMusic,
|
||||
};
|
||||
|
||||
if (await _appleMusic.InitAsync())
|
||||
{
|
||||
var raw = await _appleMusic.GetLyricsAsync(title, artist);
|
||||
_logger.LogInformation("Apple Music lyrics search result for {Title} - {Artist}: {Raw}", title, artist, raw ?? "null");
|
||||
lyricsSearchResult.Raw = raw;
|
||||
lyricsSearchResult.Title = title;
|
||||
lyricsSearchResult.Artist = artist;
|
||||
}
|
||||
|
||||
return lyricsSearchResult;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,9 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
|
||||
MediaSourceProviderInfo? GetCurrentMediaSourceProviderInfo();
|
||||
|
||||
void UpdateLyrics();
|
||||
void UpdateTranslations();
|
||||
|
||||
bool IsPlaying { get; }
|
||||
SongInfo? SongInfo { get; }
|
||||
TimeSpan Position { get; }
|
||||
|
||||
@@ -34,7 +34,7 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
}
|
||||
|
||||
byte[]? bytes = await Task.Run(async () => await _albumArtSearchService.SearchAsync(
|
||||
SongInfo?.SourceAppUserModelId ?? "",
|
||||
SongInfo?.PlayerId ?? "",
|
||||
_cachedSongInfo.Title,
|
||||
_cachedSongInfo.Artist,
|
||||
_cachedSongInfo?.Album ?? string.Empty,
|
||||
|
||||
@@ -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;
|
||||
@@ -57,7 +58,7 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
private async Task SetDisplayedAlongWithTranslationsAsync(CancellationToken token)
|
||||
{
|
||||
_logger.LogInformation("Showing translation for lyrics...");
|
||||
string targetLangCode = LanguageHelper.SupportedTargetLanguages[_settingsService.AppSettings.TranslationSettings.SelectedTargetLanguageIndex].Code;
|
||||
string targetLangCode = _settingsService.AppSettings.TranslationSettings.SelectedTargetLanguageCode;
|
||||
_logger.LogInformation("Target language code: {TargetLangCode}", targetLangCode);
|
||||
string? originalText = _lyricsDataArr.FirstOrDefault()?.WrappedOriginalText;
|
||||
if (originalText == null) return;
|
||||
@@ -65,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);
|
||||
@@ -74,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);
|
||||
@@ -85,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();
|
||||
}
|
||||
@@ -108,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;
|
||||
@@ -136,19 +156,21 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
SongInfo.Title, SongInfo.Artist, SongInfo.Album, SongInfo.DurationMs);
|
||||
|
||||
var lyricsSearchResult = await Task.Run(async () => await _lyrcsSearchService.SearchSmartlyAsync(
|
||||
SongInfo.SourceAppUserModelId ?? "",
|
||||
SongInfo.PlayerId ?? "",
|
||||
SongInfo.Title,
|
||||
SongInfo.Artist,
|
||||
SongInfo.Album ?? "",
|
||||
SongInfo.DurationMs ?? 0,
|
||||
SongInfo.SongId,
|
||||
token
|
||||
), token);
|
||||
if (token.IsCancellationRequested) return;
|
||||
LyricsSearchProvider = lyricsSearchResult?.Provider;
|
||||
|
||||
|
||||
_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
|
||||
@@ -161,10 +183,23 @@ 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;
|
||||
@@ -174,6 +209,7 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
translationRaw = FileHelper.ReadLyricsCache(SongInfo!.Title, SongInfo.Artist, LyricsFormat.Lrc, PathHelper.QQTranslationCacheDirectory);
|
||||
break;
|
||||
case Enums.LyricsSearchProvider.Kugou:
|
||||
translationRaw = FileHelper.ReadLyricsCache(SongInfo!.Title, SongInfo.Artist, LyricsFormat.Lrc, PathHelper.KugouTranslationCacheDirectory);
|
||||
break;
|
||||
case Enums.LyricsSearchProvider.Netease:
|
||||
translationRaw = FileHelper.ReadLyricsCache(SongInfo!.Title, SongInfo.Artist, LyricsFormat.Lrc, PathHelper.NeteaseTranslationCacheDirectory);
|
||||
@@ -214,12 +250,12 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateLyrics()
|
||||
public void UpdateLyrics()
|
||||
{
|
||||
_refreshLyricsRunner.RunAsync(RefreshLyricsAsync);
|
||||
}
|
||||
|
||||
private void UpdateTranslations()
|
||||
public void UpdateTranslations()
|
||||
{
|
||||
_refreshTranslationRunner.RunAsync(RefreshTranslationAsync);
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ using BetterLyrics.WinUI3.Helper;
|
||||
using BetterLyrics.WinUI3.Models;
|
||||
using BetterLyrics.WinUI3.Models.Settings;
|
||||
using BetterLyrics.WinUI3.Services.AlbumArtSearchService;
|
||||
using BetterLyrics.WinUI3.Services.LastFMService;
|
||||
using BetterLyrics.WinUI3.Services.LibWatcherService;
|
||||
using BetterLyrics.WinUI3.Services.LiveStatesService;
|
||||
using BetterLyrics.WinUI3.Services.LyricsSearchService;
|
||||
@@ -20,19 +19,12 @@ using CommunityToolkit.Mvvm.Messaging;
|
||||
using CommunityToolkit.Mvvm.Messaging.Messages;
|
||||
using EvtSource;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Graphics.Canvas;
|
||||
using Microsoft.UI.Dispatching;
|
||||
using SixLabors.ImageSharp.PixelFormats;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices.WindowsRuntime;
|
||||
using System.Text.Json;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.Graphics.Imaging;
|
||||
using Windows.Media.Control;
|
||||
using Windows.Storage.Streams;
|
||||
using WindowsMediaController;
|
||||
@@ -40,10 +32,10 @@ using WindowsMediaController;
|
||||
namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
{
|
||||
public partial class MediaSessionsService : BaseViewModel, IMediaSessionsService,
|
||||
IRecipient<PropertyChangedMessage<int>>,
|
||||
IRecipient<PropertyChangedMessage<bool>>,
|
||||
IRecipient<PropertyChangedMessage<string>>,
|
||||
IRecipient<PropertyChangedMessage<LyricsWindowMode>>,
|
||||
IRecipient<PropertyChangedMessage<ChineseRomanization>>,
|
||||
IRecipient<PropertyChangedMessage<List<string>>>
|
||||
{
|
||||
private readonly IAlbumArtSearchService _albumArtSearchService;
|
||||
@@ -56,6 +48,7 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
|
||||
private double _lxMusicPositionSeconds = 0;
|
||||
private double _lxMusicDurationSeconds = 0;
|
||||
private byte[]? _lxMusicAlbumArtBytes = null;
|
||||
|
||||
private bool _cachedIsPlaying = false;
|
||||
private TimeSpan _cachedPosition = TimeSpan.Zero;
|
||||
@@ -291,21 +284,21 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
if (!_mediaManager.IsStarted) return;
|
||||
if (mediaSession == null) return;
|
||||
|
||||
string id = mediaSession.Id;
|
||||
string sessionId = mediaSession.Id;
|
||||
|
||||
var desiredSession = GetCurrentSession();
|
||||
|
||||
//RecordMediaSourceProviderInfo(mediaSession);
|
||||
if (mediaSession != desiredSession) return;
|
||||
|
||||
if (!IsMediaSourceEnabled(id))
|
||||
if (!IsMediaSourceEnabled(sessionId))
|
||||
{
|
||||
_cachedSongInfo = null;
|
||||
|
||||
_logger.LogInformation("Media properties changed: Title: {Title}, Artist: {Artist}, Album: {Album}",
|
||||
mediaProperties.Title, mediaProperties.Artist, mediaProperties.AlbumTitle);
|
||||
|
||||
if (id == Constants.PlayerID.LXMusic)
|
||||
if (sessionId == Constants.PlayerID.LXMusic)
|
||||
{
|
||||
StopSSE();
|
||||
}
|
||||
@@ -320,21 +313,39 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
currentMediaSourceProviderInfo?.PositionOffset = 0;
|
||||
}
|
||||
|
||||
string fixedArtist = mediaProperties.Artist;
|
||||
string fixedAlbum = mediaProperties.AlbumTitle;
|
||||
string? songId = null;
|
||||
|
||||
if (sessionId == Constants.PlayerID.AppleMusic || sessionId == Constants.PlayerID.AppleMusicAlternative)
|
||||
{
|
||||
fixedArtist = mediaProperties.Artist.Split(" — ").FirstOrDefault() ?? mediaProperties.Artist;
|
||||
fixedAlbum = mediaProperties.Artist.Split(" — ").LastOrDefault() ?? mediaProperties.AlbumTitle;
|
||||
}
|
||||
else if (sessionId == Constants.PlayerID.NetEaseCloudMusic)
|
||||
{
|
||||
songId = mediaProperties.Genres.FirstOrDefault()?.Replace("NCM-", "");
|
||||
if (songId != null && songId.Length != 10)
|
||||
{
|
||||
songId = null;
|
||||
}
|
||||
}
|
||||
|
||||
_cachedSongInfo = new SongInfo
|
||||
{
|
||||
Title = mediaProperties.Title,
|
||||
Artist = mediaProperties.Artist,
|
||||
Album = mediaProperties.AlbumTitle,
|
||||
Artist = fixedArtist,
|
||||
Album = fixedAlbum,
|
||||
DurationMs = mediaSession.ControlSession.GetTimelineProperties().EndTime.TotalMilliseconds,
|
||||
SourceAppUserModelId = id,
|
||||
PlayerId = sessionId,
|
||||
SongId = songId
|
||||
};
|
||||
|
||||
_cachedSongInfo.Duration = (int)(_cachedSongInfo.DurationMs / 1000f);
|
||||
|
||||
_logger.LogInformation("Media properties changed: Title: {Title}, Artist: {Artist}, Album: {Album}",
|
||||
mediaProperties.Title, mediaProperties.Artist, mediaProperties.AlbumTitle);
|
||||
|
||||
if (id == Constants.PlayerID.LXMusic)
|
||||
if (sessionId == Constants.PlayerID.LXMusic)
|
||||
{
|
||||
StartSSE();
|
||||
}
|
||||
@@ -343,7 +354,11 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
StopSSE();
|
||||
}
|
||||
|
||||
if (mediaProperties.Thumbnail is IRandomAccessStreamReference streamReference)
|
||||
if (sessionId == Constants.PlayerID.LXMusic && _lxMusicAlbumArtBytes != null)
|
||||
{
|
||||
_SMTCAlbumArtBytes = _lxMusicAlbumArtBytes;
|
||||
}
|
||||
else if (mediaProperties.Thumbnail is IRandomAccessStreamReference streamReference)
|
||||
{
|
||||
_SMTCAlbumArtBytes = await ImageHelper.ToByteArrayAsync(streamReference);
|
||||
}
|
||||
@@ -447,6 +462,11 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
|
||||
private void StartSSE()
|
||||
{
|
||||
if (_sse != null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
_sse = new EventSourceReader(new Uri($"{_settingsService.AppSettings.GeneralSettings.LXMusicServer}{Constants.LXMusic.QuerySuffix}")).Start();
|
||||
@@ -486,9 +506,9 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
|
||||
private void Sse_MessageReceived(object sender, EventSourceMessageEventArgs e)
|
||||
{
|
||||
_dispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, () =>
|
||||
_dispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, async () =>
|
||||
{
|
||||
if (_cachedSongInfo?.SourceAppUserModelId == Constants.PlayerID.LXMusic)
|
||||
if (_cachedSongInfo?.PlayerId == Constants.PlayerID.LXMusic)
|
||||
{
|
||||
var data = JsonSerializer.Deserialize(e.Message, Serialization.SourceGenerationContext.Default.JsonElement);
|
||||
if (data.ValueKind == JsonValueKind.Number)
|
||||
@@ -507,6 +527,20 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
TimelineChanged?.Invoke(this, new TimelineChangedEventArgs(TimeSpan.FromSeconds(_lxMusicPositionSeconds), TimeSpan.FromSeconds(_lxMusicDurationSeconds)));
|
||||
}
|
||||
}
|
||||
else if (data.ValueKind == JsonValueKind.String)
|
||||
{
|
||||
if (e.Event == "picUrl")
|
||||
{
|
||||
string? picUrl = data.GetString();
|
||||
if (picUrl != null)
|
||||
{
|
||||
_logger.LogInformation("LX Music Album Art URL: {url}", picUrl);
|
||||
_lxMusicAlbumArtBytes = await ImageHelper.GetImageBytesFromUrlAsync(picUrl);
|
||||
_SMTCAlbumArtBytes = _lxMusicAlbumArtBytes;
|
||||
UpdateAlbumArt();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -579,6 +613,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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -601,18 +647,6 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
}
|
||||
}
|
||||
|
||||
public void Receive(PropertyChangedMessage<int> message)
|
||||
{
|
||||
if (message.Sender is TranslationSettings)
|
||||
{
|
||||
if (message.PropertyName == nameof(TranslationSettings.SelectedTargetLanguageIndex))
|
||||
{
|
||||
_logger.LogInformation("Target language index changed: {Index}", _settingsService.AppSettings.TranslationSettings.SelectedTargetLanguageIndex);
|
||||
UpdateTranslations();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Receive(PropertyChangedMessage<string> message)
|
||||
{
|
||||
if (message.Sender is LyricsStyleSettings)
|
||||
@@ -622,13 +656,33 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
UpdateTranslations();
|
||||
}
|
||||
}
|
||||
else if (message.Sender is TranslationSettings)
|
||||
{
|
||||
if (message.PropertyName == nameof(TranslationSettings.SelectedTargetLanguageCode))
|
||||
{
|
||||
_logger.LogInformation("Target language code changed: {code}", _settingsService.AppSettings.TranslationSettings.SelectedTargetLanguageCode);
|
||||
UpdateTranslations();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void Receive(PropertyChangedMessage<LyricsWindowMode> message)
|
||||
{
|
||||
if (message.Sender is LiveStates)
|
||||
{
|
||||
if (message.PropertyName == nameof(LiveStates.CurrentLyricsWindowMode))
|
||||
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();
|
||||
}
|
||||
|
||||
@@ -60,6 +60,9 @@ namespace BetterLyrics.WinUI3.Services.SettingsService
|
||||
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>
|
||||
@@ -285,6 +285,9 @@
|
||||
<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>
|
||||
@@ -439,6 +442,15 @@ 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="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>
|
||||
@@ -475,6 +487,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>
|
||||
@@ -484,17 +499,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>
|
||||
@@ -532,22 +538,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">
|
||||
@@ -568,6 +589,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>
|
||||
@@ -622,7 +646,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">
|
||||
@@ -634,15 +658,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>
|
||||
@@ -650,10 +665,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>
|
||||
@@ -670,9 +685,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>
|
||||
@@ -892,6 +913,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>
|
||||
@@ -937,6 +961,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>
|
||||
@@ -955,9 +982,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>
|
||||
@@ -970,6 +1003,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>
|
||||
@@ -1012,6 +1048,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>
|
||||
@@ -1039,7 +1078,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>
|
||||
@@ -285,6 +285,9 @@
|
||||
<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>
|
||||
@@ -439,6 +442,15 @@
|
||||
<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="SetingsPageThanks.Text" xml:space="preserve">
|
||||
<value>このプロジェクトが気に入っている場合は、寄付してサポートすることを検討してください。あなたのサポートは、プロジェクトを生かし続け、さらなる開発を促進するのに役立ちます。</value>
|
||||
</data>
|
||||
<data name="SettingsPageAbout.Content" xml:space="preserve">
|
||||
<value>について</value>
|
||||
</data>
|
||||
@@ -475,6 +487,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>
|
||||
@@ -484,17 +499,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>
|
||||
@@ -532,22 +538,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">
|
||||
@@ -568,6 +589,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>
|
||||
@@ -622,7 +646,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">
|
||||
@@ -634,15 +658,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>
|
||||
@@ -650,10 +665,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>
|
||||
@@ -670,9 +685,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>
|
||||
@@ -892,6 +913,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>
|
||||
@@ -937,6 +961,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>
|
||||
@@ -955,9 +982,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>
|
||||
@@ -970,6 +1003,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>
|
||||
@@ -1012,6 +1048,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>
|
||||
@@ -1039,7 +1078,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>
|
||||
@@ -285,6 +285,9 @@
|
||||
<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>
|
||||
@@ -439,6 +442,15 @@
|
||||
<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="SetingsPageThanks.Text" xml:space="preserve">
|
||||
<value>이 프로젝트가 마음에 들면 기부하여 지원을 고려하십시오. 귀하의 지원은 프로젝트를 계속 유지하고 추가 개발을 장려하는 데 도움이 될 것입니다.</value>
|
||||
</data>
|
||||
<data name="SettingsPageAbout.Content" xml:space="preserve">
|
||||
<value>에 대한</value>
|
||||
</data>
|
||||
@@ -475,6 +487,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>
|
||||
@@ -484,17 +499,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>
|
||||
@@ -532,22 +538,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">
|
||||
@@ -568,6 +589,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>
|
||||
@@ -622,7 +646,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">
|
||||
@@ -634,15 +658,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>
|
||||
@@ -650,10 +665,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>
|
||||
@@ -670,9 +685,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>
|
||||
@@ -892,6 +913,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>
|
||||
@@ -937,6 +961,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>
|
||||
@@ -955,9 +982,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>
|
||||
@@ -970,6 +1003,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>
|
||||
@@ -1012,6 +1048,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>
|
||||
@@ -1039,7 +1078,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>
|
||||
@@ -285,6 +285,9 @@
|
||||
<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>
|
||||
@@ -439,6 +442,15 @@
|
||||
<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="SetingsPageThanks.Text" xml:space="preserve">
|
||||
<value>如果您喜欢这个项目,请考虑通过捐赠来支持它。您的支持将有助于保持项目的生命并鼓励进一步的发展。</value>
|
||||
</data>
|
||||
<data name="SettingsPageAbout.Content" xml:space="preserve">
|
||||
<value>关于</value>
|
||||
</data>
|
||||
@@ -475,6 +487,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>
|
||||
@@ -484,17 +499,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>
|
||||
@@ -532,22 +538,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">
|
||||
@@ -568,6 +589,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>
|
||||
@@ -622,7 +646,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">
|
||||
@@ -634,15 +658,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>
|
||||
@@ -650,10 +665,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>
|
||||
@@ -670,9 +685,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>
|
||||
@@ -892,6 +913,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>
|
||||
@@ -937,6 +961,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>
|
||||
@@ -955,9 +982,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>
|
||||
@@ -970,6 +1003,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>
|
||||
@@ -1012,6 +1048,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>
|
||||
@@ -1039,7 +1078,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>
|
||||
@@ -285,6 +285,9 @@
|
||||
<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>
|
||||
@@ -439,6 +442,15 @@
|
||||
<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="SetingsPageThanks.Text" xml:space="preserve">
|
||||
<value>如果您喜歡這個項目,請考慮通過捐贈來支持它。您的支持將有助於保持項目的生命並鼓勵進一步的發展。</value>
|
||||
</data>
|
||||
<data name="SettingsPageAbout.Content" xml:space="preserve">
|
||||
<value>關於</value>
|
||||
</data>
|
||||
@@ -475,6 +487,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>
|
||||
@@ -484,17 +499,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>
|
||||
@@ -532,22 +538,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">
|
||||
@@ -568,6 +589,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>
|
||||
@@ -622,7 +646,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">
|
||||
@@ -634,15 +658,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>
|
||||
@@ -650,10 +665,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>
|
||||
@@ -670,9 +685,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>
|
||||
@@ -892,6 +913,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>
|
||||
@@ -937,6 +961,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>
|
||||
@@ -955,9 +982,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>
|
||||
@@ -970,6 +1003,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>
|
||||
@@ -1012,6 +1048,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>
|
||||
@@ -1039,7 +1078,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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
@@ -688,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;
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,7 +56,11 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
[ObservableProperty]
|
||||
public partial TranslationSearchProvider? TranslationSearchProvider { get; set; } = null;
|
||||
|
||||
[ObservableProperty]
|
||||
public partial int SelectedTargetLanguageIndex { get; set; }
|
||||
|
||||
[ObservableProperty]
|
||||
public partial string AppleMusicMediaUserToken { get; set; }
|
||||
|
||||
public PlaybackSettingsControlViewModel(
|
||||
ISettingsService settingsService,
|
||||
@@ -77,6 +81,10 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
AppSettings = _settingsService.AppSettings;
|
||||
AppSettings.MediaSourceProvidersInfo.CollectionChanged += MediaSourceProvidersInfo_CollectionChanged;
|
||||
|
||||
AppleMusicMediaUserToken = PasswordVaultHelper.Get(Constants.App.AppName, Constants.AppleMusic.MediaUserTokenKey) ?? "";
|
||||
|
||||
SelectedTargetLanguageIndex = LanguageHelper.SupportedTargetLanguages.ToList().FindIndex(x => x.Code == AppSettings.TranslationSettings.SelectedTargetLanguageCode);
|
||||
|
||||
IsLastFMAuthenticated = _lastFMService.IsAuthenticated;
|
||||
LastFMUser = _lastFMService.User;
|
||||
|
||||
@@ -103,7 +111,7 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
|
||||
private void MediaSessionsService_SongInfoChanged(object? sender, Events.SongInfoChangedEventArgs e)
|
||||
{
|
||||
var current = AppSettings.MediaSourceProvidersInfo.Where(x => x.Provider == e.SongInfo?.SourceAppUserModelId)?.FirstOrDefault();
|
||||
var current = AppSettings.MediaSourceProvidersInfo.Where(x => x.Provider == e.SongInfo?.PlayerId)?.FirstOrDefault();
|
||||
if (_mediaSessionsService.Position.TotalSeconds <= 1 && current?.ResetPositionOffsetOnSongChanged == true)
|
||||
{
|
||||
current.PositionOffset = 0;
|
||||
@@ -123,8 +131,8 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
{
|
||||
try
|
||||
{
|
||||
string targetLangCode = LanguageHelper.SupportedTargetLanguages[AppSettings.TranslationSettings.SelectedTargetLanguageIndex].Code;
|
||||
string result = await _libreTranslateService.TranslateTextAsync("Hello, world!", targetLangCode, new System.Threading.CancellationToken());
|
||||
string result = await _libreTranslateService.TranslateTextAsync(
|
||||
"Hello, world!", AppSettings.TranslationSettings.SelectedTargetLanguageCode, new System.Threading.CancellationToken());
|
||||
_dispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, () =>
|
||||
{
|
||||
App.Current.SettingsWindowNotificationPanel?.Notify(App.ResourceLoader!.GetString("SettingsPageServerTestSuccessInfo"), InfoBarSeverity.Success);
|
||||
@@ -184,6 +192,13 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
});
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void SaveAppleMusicMediaUserToken()
|
||||
{
|
||||
PasswordVaultHelper.Save(Constants.App.AppName, Constants.AppleMusic.MediaUserTokenKey, AppleMusicMediaUserToken);
|
||||
_mediaSessionsService.UpdateLyrics();
|
||||
}
|
||||
|
||||
public void Receive(PropertyChangedMessage<LyricsSearchProvider?> message)
|
||||
{
|
||||
if (message.Sender is MediaSessionsService)
|
||||
@@ -205,5 +220,10 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
partial void OnSelectedTargetLanguageIndexChanged(int value)
|
||||
{
|
||||
AppSettings.TranslationSettings.SelectedTargetLanguageCode = LanguageHelper.SupportedTargetLanguages[value].Code;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
@@ -29,6 +30,7 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
public partial class SettingsPageViewModel : BaseViewModel
|
||||
{
|
||||
private readonly ISettingsService _settingsService;
|
||||
private readonly IMediaSessionsService _mediaSessionsService;
|
||||
|
||||
public string Version { get; set; } = MetadataHelper.AppVersion;
|
||||
|
||||
@@ -42,16 +44,17 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
[ObservableProperty]
|
||||
public partial object NavViewSelectedItemTag { get; set; } = "App";
|
||||
|
||||
public SettingsPageViewModel(ISettingsService settingsService)
|
||||
public SettingsPageViewModel(ISettingsService settingsService, IMediaSessionsService mediaSessionsService)
|
||||
{
|
||||
_settingsService = settingsService;
|
||||
_mediaSessionsService = mediaSessionsService;
|
||||
AppSettings = _settingsService.AppSettings;
|
||||
}
|
||||
|
||||
[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]
|
||||
|
||||
@@ -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>
|
||||
@@ -245,14 +245,6 @@
|
||||
<ToolTipService.ToolTip>
|
||||
<ToolTip x:Uid="LyricsPageLyricsSearchButtonToolTip" />
|
||||
</ToolTipService.ToolTip>
|
||||
<Button.ContextFlyout>
|
||||
<Flyout
|
||||
x:Name="LyricsSearchFlyout"
|
||||
Closed="LyricsSearchFlyout_Closed"
|
||||
FlyoutPresenterStyle="{StaticResource FlyoutPageStyle}"
|
||||
Placement="Right"
|
||||
ShouldConstrainToRootBounds="False" />
|
||||
</Button.ContextFlyout>
|
||||
</Button>
|
||||
|
||||
<!-- Playback shortcut settings -->
|
||||
|
||||
@@ -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;
|
||||
@@ -133,17 +134,7 @@ namespace BetterLyrics.WinUI3.Views
|
||||
|
||||
private void LyricsSearchShortcutButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
LyricsSearchFlyout.Content = new LyricsSearchControl
|
||||
{
|
||||
MaxHeight = 500,
|
||||
MaxWidth = 850,
|
||||
};
|
||||
LyricsSearchFlyout.ShowAt(BottomRightCommandStackPanel);
|
||||
}
|
||||
|
||||
private void LyricsSearchFlyout_Closed(object sender, object e)
|
||||
{
|
||||
LyricsSearchFlyout.Content = null;
|
||||
WindowHelper.OpenWindow<LyricsSearchWindow>();
|
||||
}
|
||||
|
||||
private void TimelineSliderOverlay_PointerPressed(object sender, Microsoft.UI.Xaml.Input.PointerRoutedEventArgs e)
|
||||
|
||||
@@ -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>();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -76,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)
|
||||
|
||||
@@ -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,104 @@
|
||||
|
||||
<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:SettingsCard x:Uid="SettingsPageTelegram" HeaderIcon="{ui:BitmapIcon Source=ms-appx:///Assets/Telegram.png}">
|
||||
<Button x:Uid="SettingsPageJoinNowButton" Click="TelegramGroupButton_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>
|
||||
|
||||
</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? (for test package only)
|
||||
[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 |
BIN
FAQ/image-12.png
|
Before Width: | Height: | Size: 367 KiB |
BIN
FAQ/image-2.png
|
Before Width: | Height: | Size: 66 KiB |
BIN
FAQ/image-3.png
|
Before Width: | Height: | Size: 631 KiB |
BIN
FAQ/image-4.png
|
Before Width: | Height: | Size: 599 KiB |
BIN
FAQ/image-5.png
|
Before Width: | Height: | Size: 859 KiB |
BIN
FAQ/image-6.png
|
Before Width: | Height: | Size: 854 KiB |
BIN
FAQ/image-7.png
|
Before Width: | Height: | Size: 139 KiB |
BIN
FAQ/image-8.png
|
Before Width: | Height: | Size: 1.1 MiB |
BIN
FAQ/image-9.png
|
Before Width: | Height: | Size: 250 KiB |