mirror of
https://github.com/jayfunc/BetterLyrics.git
synced 2026-01-12 19:24:55 +08:00
Compare commits
22 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f681b43e96 | ||
|
|
133acf5592 | ||
|
|
cbaa81b9bb | ||
|
|
b834be49ce | ||
|
|
8abe6d7f01 | ||
|
|
8a73ba9e6a | ||
|
|
49a090b0c7 | ||
|
|
a47dd67056 | ||
|
|
900ecc9776 | ||
|
|
464742d7c5 | ||
|
|
5f3aad4e99 | ||
|
|
7b6eca6ff6 | ||
|
|
9fcb1ac869 | ||
|
|
74ebda2b6d | ||
|
|
e194dfaa70 | ||
|
|
bfc877f924 | ||
|
|
af55446004 | ||
|
|
faf8acf669 | ||
|
|
5b79a54117 | ||
|
|
4ef55f6ece | ||
|
|
0593f9aa3f | ||
|
|
b09a6494ff |
@@ -12,7 +12,7 @@
|
||||
<Identity
|
||||
Name="37412.BetterLyrics"
|
||||
Publisher="CN=E1428B0E-DC1D-4EA4-ACB1-4556569D5BA9"
|
||||
Version="1.0.45.0" />
|
||||
Version="1.0.53.0" />
|
||||
|
||||
<mp:PhoneIdentity PhoneProductId="ca4a4830-fc19-40d9-b823-53e2bff3d816" PhonePublisherId="00000000-0000-0000-0000-000000000000"/>
|
||||
|
||||
|
||||
@@ -10,10 +10,10 @@
|
||||
<Application.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<!-- Merged dictionaries here -->
|
||||
<XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls" />
|
||||
<ResourceDictionary Source="ms-appx:///CommunityToolkit.WinUI.Controls.SettingsControls/SettingsExpander/SettingsExpander.xaml" />
|
||||
<ResourceDictionary Source="ms-appx:///CommunityToolkit.WinUI.Controls.Segmented/Segmented/Segmented.xaml" />
|
||||
<!-- Other merged dictionaries here -->
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
|
||||
<!-- Theme -->
|
||||
@@ -53,6 +53,9 @@
|
||||
<converter:SecondsToFormattedTimeConverter x:Key="SecondsToFormattedTimeConverter" />
|
||||
<converter:MediaSourceProviderToLogoUriConverter x:Key="MediaSourceProviderToLogoUriConverter" />
|
||||
<converter:MediaSourceProviderToDisplayedNameConverter x:Key="MediaSourceProviderToDisplayedNameConverter" />
|
||||
<converter:FPSToTimeSpanConverter x:Key="FPSToTimeSpanConverter" />
|
||||
<converter:ShortcutToStringConverter x:Key="ShortcutToStringConverter" />
|
||||
|
||||
<converters:BoolToVisibilityConverter x:Key="BoolToVisibilityConverter" />
|
||||
<converters:BoolNegationConverter x:Key="BoolNegationConverter" />
|
||||
<converters:ColorToDisplayNameConverter x:Key="ColorToDisplayNameConverter" />
|
||||
@@ -297,6 +300,29 @@
|
||||
<Setter Property="Padding" Value="0" />
|
||||
</Style>
|
||||
|
||||
<Style
|
||||
x:Key="SettingsScrollViewerStyle"
|
||||
BasedOn="{StaticResource DefaultScrollViewerStyle}"
|
||||
TargetType="ScrollViewer">
|
||||
<Setter Property="Padding" Value="36,0" />
|
||||
</Style>
|
||||
|
||||
<Style x:Key="SettingsGridStyle" TargetType="Grid">
|
||||
<Setter Property="Padding" Value="0,0,0,36" />
|
||||
</Style>
|
||||
|
||||
<Style
|
||||
x:Key="FlyoutPageStyle"
|
||||
BasedOn="{StaticResource DefaultFlyoutPresenterStyle}"
|
||||
TargetType="FlyoutPresenter">
|
||||
<Setter Property="Opacity" Value="0.9" />
|
||||
<Setter Property="MinWidth" Value="850" />
|
||||
<Setter Property="Padding" Value="0" />
|
||||
<Setter Property="ScrollViewer.VerticalScrollMode" Value="Disabled" />
|
||||
<Setter Property="ScrollViewer.HorizontalScrollMode" Value="Disabled" />
|
||||
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Hidden" />
|
||||
</Style>
|
||||
|
||||
<StaticResource x:Key="ToggleButtonBackgroundChecked" ResourceKey="TextFillColorPrimaryBrush" />
|
||||
<StaticResource x:Key="ToggleButtonBackgroundCheckedPointerOver" ResourceKey="TextFillColorPrimaryBrush" />
|
||||
<StaticResource x:Key="ToggleButtonBackgroundCheckedPressed" ResourceKey="TextFillColorPrimaryBrush" />
|
||||
|
||||
@@ -6,13 +6,13 @@ using BetterLyrics.WinUI3.Services;
|
||||
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;
|
||||
using BetterLyrics.WinUI3.Services.MediaSessionsService;
|
||||
using BetterLyrics.WinUI3.Services.SettingsService;
|
||||
using BetterLyrics.WinUI3.Services.TranslateService;
|
||||
using BetterLyrics.WinUI3.ViewModels;
|
||||
using BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel;
|
||||
using BetterLyrics.WinUI3.ViewModels.SettingsPageViewModel;
|
||||
using BetterLyrics.WinUI3.Views;
|
||||
using CommunityToolkit.Mvvm.DependencyInjection;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
@@ -85,13 +85,6 @@ namespace BetterLyrics.WinUI3
|
||||
protected override void OnLaunched(LaunchActivatedEventArgs args)
|
||||
{
|
||||
WindowHelper.OpenWindow<LyricsWindow>();
|
||||
|
||||
var lyricsWindow = WindowHelper.GetWindowByWindowType<LyricsWindow>();
|
||||
if (lyricsWindow != null)
|
||||
{
|
||||
lyricsWindow.ViewModel.InitLockHotKey();
|
||||
lyricsWindow.AutoSelectLyricsMode();
|
||||
}
|
||||
}
|
||||
|
||||
private static void ConfigureServices()
|
||||
@@ -110,6 +103,7 @@ namespace BetterLyrics.WinUI3
|
||||
loggingBuilder.AddSerilog();
|
||||
})
|
||||
// Services
|
||||
.AddSingleton<ILiveStatesService, LiveStatesService>()
|
||||
.AddSingleton<ISettingsService, SettingsService>()
|
||||
.AddSingleton<IMediaSessionsService, MediaSessionsService>()
|
||||
.AddSingleton<IAlbumArtSearchService, AlbumArtSearchService>()
|
||||
@@ -118,6 +112,12 @@ namespace BetterLyrics.WinUI3
|
||||
.AddSingleton<ITranslateService, TranslateService>()
|
||||
.AddSingleton<ILastFMService, LastFMService>()
|
||||
// ViewModels
|
||||
.AddSingleton<AppSettingsControlViewModel>()
|
||||
.AddSingleton<LyricsBackgroundSettingsControlViewModel>()
|
||||
.AddSingleton<AlbumArtLayoutSettingsControlViewModel>()
|
||||
.AddSingleton<PlaybackSettingsControlViewModel>()
|
||||
.AddSingleton<MediaSettingsControlViewModel>()
|
||||
.AddSingleton<AllLyricsSettingsControlViewModel>()
|
||||
.AddSingleton<LyricsWindowViewModel>()
|
||||
.AddSingleton<SettingsWindowViewModel>()
|
||||
.AddSingleton<SystemTrayViewModel>()
|
||||
|
||||
BIN
BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/Cover.jpg
Normal file
BIN
BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/Cover.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 84 KiB |
@@ -22,6 +22,15 @@
|
||||
<ItemGroup>
|
||||
<None Remove="Assets\Segoe Fluent Icons.ttf" />
|
||||
<None Remove="Assets\Wiki82.profile.xml" />
|
||||
<None Remove="Controls\AlbumArtLayoutSettingsControl.xaml" />
|
||||
<None Remove="Controls\AllLyricsSettingsControl.xaml" />
|
||||
<None Remove="Controls\AppSettingsControl.xaml" />
|
||||
<None Remove="Controls\ExtendedSlider.xaml" />
|
||||
<None Remove="Controls\LyricsBavkgroundSettingsControl.xaml" />
|
||||
<None Remove="Controls\LyricsSettingsControl.xaml" />
|
||||
<None Remove="Controls\MediaSettingsControl.xaml" />
|
||||
<None Remove="Controls\PlaybackSettingsControl.xaml" />
|
||||
<None Remove="Controls\ShortcutTextBox.xaml" />
|
||||
<None Remove="Controls\SystemTray.xaml" />
|
||||
<None Remove="Views\MusicGalleryPage.xaml" />
|
||||
<None Remove="Views\MusicGalleryWindow.xaml" />
|
||||
@@ -177,6 +186,51 @@
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Update="Controls\ShortcutTextBox.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Update="Controls\ExtendedSlider.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Update="Controls\AllLyricsSettingsControl.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Update="Controls\LyricsSettingsControl.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Update="Controls\MediaSettingsControl.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Update="Controls\PlaybackSettingsControl.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Update="Controls\AlbumArtLayoutSettingsControl.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Update="Controls\LyricsBavkgroundSettingsControl.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Update="Controls\AppSettingsControl.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Update="Views\MusicGalleryWindow.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
|
||||
@@ -5,5 +5,6 @@ namespace BetterLyrics.WinUI3.Constants
|
||||
public const string ApiKey = "Your api key here";
|
||||
public const string SharedSecret = "Your shared secret here";
|
||||
public const string UnAuthUrl = "https://www.last.fm/settings/applications";
|
||||
public const string SessionKeyCredentialKey = "LastFMSessionKey";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<UserControl
|
||||
x:Class="BetterLyrics.WinUI3.Controls.AlbumArtLayoutSettingsControl"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:controls="using:CommunityToolkit.WinUI.Controls"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="using:BetterLyrics.WinUI3.Controls"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:ui="using:CommunityToolkit.WinUI"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<Grid>
|
||||
<ScrollViewer Style="{StaticResource SettingsScrollViewerStyle}">
|
||||
<Grid Style="{StaticResource SettingsGridStyle}">
|
||||
<StackPanel Spacing="{StaticResource SettingsCardSpacing}">
|
||||
|
||||
<TextBlock x:Uid="SettingsPageAlbumArt" Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" />
|
||||
|
||||
<controls:SettingsCard x:Uid="SettingsPageAlbumRadius" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||
<local:ExtendedSlider
|
||||
Default="12"
|
||||
Frequency="1"
|
||||
Maximum="100"
|
||||
Minimum="0"
|
||||
Unit="%"
|
||||
Value="{x:Bind ViewModel.AppSettings.AlbumArtLayoutSettings.CoverImageRadius, Mode=TwoWay}" />
|
||||
</controls:SettingsCard>
|
||||
|
||||
<controls:SettingsCard x:Uid="SettingsPageAlbumShadowAmount" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||
<local:ExtendedSlider
|
||||
Default="12"
|
||||
Frequency="1"
|
||||
Maximum="64"
|
||||
Minimum="0"
|
||||
Value="{x:Bind ViewModel.AppSettings.AlbumArtLayoutSettings.CoverImageShadowAmount, Mode=TwoWay}" />
|
||||
</controls:SettingsCard>
|
||||
|
||||
<TextBlock x:Uid="SettingsPageSongInfo" Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" />
|
||||
|
||||
<controls:SettingsCard x:Uid="SettingsPageSongInfoAlignment" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||
<ComboBox SelectedIndex="{x:Bind ViewModel.AppSettings.AlbumArtLayoutSettings.SongInfoAlignmentType, Mode=TwoWay, Converter={StaticResource EnumToIntConverter}}">
|
||||
<ComboBoxItem x:Uid="SettingsPageSongInfoLeft" />
|
||||
<ComboBoxItem x:Uid="SettingsPageSongInfoCenter" />
|
||||
<ComboBoxItem x:Uid="SettingsPageSongInfoRight" />
|
||||
</ComboBox>
|
||||
</controls:SettingsCard>
|
||||
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</ScrollViewer>
|
||||
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,32 @@
|
||||
using BetterLyrics.WinUI3.ViewModels;
|
||||
using CommunityToolkit.Mvvm.DependencyInjection;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Controls.Primitives;
|
||||
using Microsoft.UI.Xaml.Data;
|
||||
using Microsoft.UI.Xaml.Input;
|
||||
using Microsoft.UI.Xaml.Media;
|
||||
using Microsoft.UI.Xaml.Navigation;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices.WindowsRuntime;
|
||||
using Windows.Foundation;
|
||||
using Windows.Foundation.Collections;
|
||||
|
||||
// To learn more about WinUI, the WinUI project structure,
|
||||
// and more about our project templates, see: http://aka.ms/winui-project-info.
|
||||
|
||||
namespace BetterLyrics.WinUI3.Controls
|
||||
{
|
||||
public sealed partial class AlbumArtLayoutSettingsControl : UserControl
|
||||
{
|
||||
public AlbumArtLayoutSettingsControlViewModel ViewModel => (AlbumArtLayoutSettingsControlViewModel)DataContext;
|
||||
public AlbumArtLayoutSettingsControl()
|
||||
{
|
||||
InitializeComponent();
|
||||
DataContext = Ioc.Default.GetRequiredService<AlbumArtLayoutSettingsControlViewModel>();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<UserControl
|
||||
x:Class="BetterLyrics.WinUI3.Controls.AllLyricsSettingsControl"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:controls="using:CommunityToolkit.WinUI.Controls"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="using:BetterLyrics.WinUI3.Controls"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:uc="using:BetterLyrics.WinUI3.Controls"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<Grid>
|
||||
<controls:SwitchPresenter Margin="0,72,0,0" Value="{Binding SelectedItem.Tag, ElementName=LyricsSettingsSegmentedControl}">
|
||||
<controls:Case Value="Standard">
|
||||
<uc:LyricsSettingsControl LyricsEffectSettings="{x:Bind ViewModel.AppSettings.StandardLyricsEffectSettings, Mode=OneWay}" LyricsStyleSettings="{x:Bind ViewModel.AppSettings.StandardLyricsStyleSettings, Mode=OneWay}" />
|
||||
</controls:Case>
|
||||
<controls:Case Value="Desktop">
|
||||
<uc:LyricsSettingsControl LyricsEffectSettings="{x:Bind ViewModel.AppSettings.DesktopLyricsEffectSettings, Mode=OneWay}" LyricsStyleSettings="{x:Bind ViewModel.AppSettings.DesktopLyricsStyleSettings, Mode=OneWay}" />
|
||||
</controls:Case>
|
||||
<controls:Case Value="Dock">
|
||||
<uc:LyricsSettingsControl LyricsEffectSettings="{x:Bind ViewModel.AppSettings.DockLyricsEffectSettings, Mode=OneWay}" LyricsStyleSettings="{x:Bind ViewModel.AppSettings.DockLyricsStyleSettings, Mode=OneWay}" />
|
||||
</controls:Case>
|
||||
<controls:Case Value="PictureInPicture">
|
||||
<uc:LyricsSettingsControl LyricsEffectSettings="{x:Bind ViewModel.AppSettings.PictureInPictureLyricsEffectSettings, Mode=OneWay}" LyricsStyleSettings="{x:Bind ViewModel.AppSettings.PictureInPictureLyricsStyleSettings, Mode=OneWay}" />
|
||||
</controls:Case>
|
||||
</controls:SwitchPresenter>
|
||||
<controls:Segmented
|
||||
x:Name="LyricsSettingsSegmentedControl"
|
||||
Margin="36,36,36,0"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Top"
|
||||
SelectedIndex="{x:Bind ViewModel.SelectedTabIndex, Mode=OneWay}">
|
||||
<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>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,32 @@
|
||||
using BetterLyrics.WinUI3.ViewModels;
|
||||
using CommunityToolkit.Mvvm.DependencyInjection;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Controls.Primitives;
|
||||
using Microsoft.UI.Xaml.Data;
|
||||
using Microsoft.UI.Xaml.Input;
|
||||
using Microsoft.UI.Xaml.Media;
|
||||
using Microsoft.UI.Xaml.Navigation;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices.WindowsRuntime;
|
||||
using Windows.Foundation;
|
||||
using Windows.Foundation.Collections;
|
||||
|
||||
// To learn more about WinUI, the WinUI project structure,
|
||||
// and more about our project templates, see: http://aka.ms/winui-project-info.
|
||||
|
||||
namespace BetterLyrics.WinUI3.Controls
|
||||
{
|
||||
public sealed partial class AllLyricsSettingsControl : UserControl
|
||||
{
|
||||
public AllLyricsSettingsControlViewModel ViewModel => (AllLyricsSettingsControlViewModel)DataContext;
|
||||
public AllLyricsSettingsControl()
|
||||
{
|
||||
InitializeComponent();
|
||||
DataContext = Ioc.Default.GetRequiredService<AllLyricsSettingsControlViewModel>();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,194 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<UserControl
|
||||
x:Class="BetterLyrics.WinUI3.Controls.AppSettingsControl"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:controls="using:CommunityToolkit.WinUI.Controls"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="using:BetterLyrics.WinUI3.Controls"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:ui="using:CommunityToolkit.WinUI"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<Grid>
|
||||
<ScrollViewer Style="{StaticResource SettingsScrollViewerStyle}">
|
||||
<Grid Style="{StaticResource SettingsGridStyle}">
|
||||
<StackPanel Spacing="{StaticResource SettingsCardSpacing}">
|
||||
|
||||
<!-- App appearance -->
|
||||
|
||||
<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: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" />
|
||||
</ComboBox>
|
||||
</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="SettingsPageGlobalDrag" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||
<ToggleSwitch IsOn="{x:Bind ViewModel.AppSettings.GeneralSettings.IsDragEverywhereEnabled, 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>
|
||||
|
||||
<!-- Standard mode -->
|
||||
|
||||
<TextBlock x:Uid="SettingsPageAppStandard" Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" />
|
||||
|
||||
<controls:SettingsCard x:Uid="SettingsPageDisplayTypeSwitcher" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||
<ComboBox SelectedIndex="{x:Bind ViewModel.AppSettings.StandardModeSettings.LyricsDisplayType, Mode=TwoWay, Converter={StaticResource EnumToIntConverter}}">
|
||||
<ComboBoxItem x:Uid="MainPageAlbumArtOnly" />
|
||||
<ComboBoxItem x:Uid="MainPageLyriscOnly" />
|
||||
<ComboBoxItem x:Uid="MainPageSplitView" />
|
||||
</ComboBox>
|
||||
</controls:SettingsCard>
|
||||
|
||||
<!-- Desktop mode -->
|
||||
|
||||
<TextBlock x:Uid="SettingsPageAppDesktop" Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" />
|
||||
|
||||
<controls:SettingsCard x:Uid="SettingsPageToggleHotKey" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||
<local:ShortcutTextBox Shortcut="{x:Bind ViewModel.AppSettings.DesktopModeSettings.ToggleShortcut, Mode=TwoWay}" />
|
||||
</controls:SettingsCard>
|
||||
|
||||
<controls:SettingsCard x:Uid="SettingsPageDisplayTypeSwitcher" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||
<ComboBox SelectedIndex="{x:Bind ViewModel.AppSettings.DesktopModeSettings.LyricsDisplayType, Mode=TwoWay, Converter={StaticResource EnumToIntConverter}}">
|
||||
<ComboBoxItem x:Uid="MainPageAlbumArtOnly" />
|
||||
<ComboBoxItem x:Uid="MainPageLyriscOnly" />
|
||||
<ComboBoxItem x:Uid="MainPageSplitView" />
|
||||
</ComboBox>
|
||||
</controls:SettingsCard>
|
||||
|
||||
<controls:SettingsCard x:Uid="SettingsPageAutoLock" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||
<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>
|
||||
|
||||
<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>
|
||||
|
||||
<!-- Picture in picture mode -->
|
||||
|
||||
<TextBlock x:Uid="SettingsPageAppPictureInPicture" Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" />
|
||||
|
||||
<controls:SettingsCard x:Uid="SettingsPageToggleHotKey" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||
<local:ShortcutTextBox Shortcut="{x:Bind ViewModel.AppSettings.PictureInPictureModeSettings.ToggleShortcut, Mode=TwoWay}" />
|
||||
</controls:SettingsCard>
|
||||
|
||||
<controls:SettingsCard x:Uid="SettingsPageDisplayTypeSwitcher" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||
<ComboBox SelectedIndex="{x:Bind ViewModel.AppSettings.PictureInPictureModeSettings.LyricsDisplayType, Mode=TwoWay, Converter={StaticResource EnumToIntConverter}}">
|
||||
<ComboBoxItem x:Uid="MainPageAlbumArtOnly" />
|
||||
<ComboBoxItem x:Uid="MainPageLyriscOnly" />
|
||||
<ComboBoxItem x:Uid="MainPageSplitView" />
|
||||
</ComboBox>
|
||||
</controls:SettingsCard>
|
||||
|
||||
<!-- Playback shortcut -->
|
||||
|
||||
<TextBlock x:Uid="SettingsPagePlaybackShortcut" Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" />
|
||||
|
||||
<controls:SettingsCard x:Uid="SettingsPagePlayOrPauseSongHotKey" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||
<local:ShortcutTextBox Shortcut="{x:Bind ViewModel.AppSettings.GeneralSettings.PlayOrPauseShortcut, Mode=TwoWay}" />
|
||||
</controls:SettingsCard>
|
||||
|
||||
<controls:SettingsCard x:Uid="SettingsPageNextSongHotKey" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||
<local:ShortcutTextBox Shortcut="{x:Bind ViewModel.AppSettings.GeneralSettings.NextSongShortcut, Mode=TwoWay}" />
|
||||
</controls:SettingsCard>
|
||||
|
||||
<controls:SettingsCard x:Uid="SettingsPagePreviousSongHotKey" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||
<local:ShortcutTextBox Shortcut="{x:Bind ViewModel.AppSettings.GeneralSettings.PreviousSongShortcut, Mode=TwoWay}" />
|
||||
</controls:SettingsCard>
|
||||
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</ScrollViewer>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,50 @@
|
||||
using BetterLyrics.WinUI3.Models.Settings;
|
||||
using BetterLyrics.WinUI3.ViewModels;
|
||||
using CommunityToolkit.Mvvm.DependencyInjection;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Controls.Primitives;
|
||||
using Microsoft.UI.Xaml.Data;
|
||||
using Microsoft.UI.Xaml.Input;
|
||||
using Microsoft.UI.Xaml.Media;
|
||||
using Microsoft.UI.Xaml.Navigation;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices.WindowsRuntime;
|
||||
using Windows.Foundation;
|
||||
using Windows.Foundation.Collections;
|
||||
|
||||
// To learn more about WinUI, the WinUI project structure,
|
||||
// and more about our project templates, see: http://aka.ms/winui-project-info.
|
||||
|
||||
namespace BetterLyrics.WinUI3.Controls
|
||||
{
|
||||
public sealed partial class AppSettingsControl : UserControl
|
||||
{
|
||||
public AppSettingsControlViewModel ViewModel => (AppSettingsControlViewModel)DataContext;
|
||||
|
||||
public AppSettingsControl()
|
||||
{
|
||||
InitializeComponent();
|
||||
DataContext = Ioc.Default.GetRequiredService<AppSettingsControlViewModel>();
|
||||
}
|
||||
|
||||
private async void AutoStartupToggleSwitch_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
AutoStartupToggleSwitch.IsOn = await ViewModel.DetectIsAutoStartupEnabledAsync();
|
||||
AutoStartupToggleSwitch.Toggled += AutoStartupToggleSwitch_Toggled;
|
||||
}
|
||||
|
||||
private void AutoStartupToggleSwitch_Toggled(object sender, RoutedEventArgs e)
|
||||
{
|
||||
ViewModel.ToggleAutoStartupAsync(AutoStartupToggleSwitch.IsOn);
|
||||
}
|
||||
|
||||
private void AutoStartupToggleSwitch_Unloaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
AutoStartupToggleSwitch.Toggled -= AutoStartupToggleSwitch_Toggled;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<UserControl
|
||||
x:Class="BetterLyrics.WinUI3.Controls.ExtendedSlider"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="using:BetterLyrics.WinUI3.Controls"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:ui="using:CommunityToolkit.WinUI"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Margin="6,0,2,0"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Bind Value, Mode=OneWay}" />
|
||||
<TextBlock
|
||||
Margin="0,0,14,0"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Bind Unit, Mode=OneWay}" />
|
||||
<Slider
|
||||
Maximum="{x:Bind Maximum, Mode=OneWay}"
|
||||
Minimum="{x:Bind Minimum, Mode=OneWay}"
|
||||
SnapsTo="Ticks"
|
||||
StepFrequency="{x:Bind Frequency, Mode=OneWay}"
|
||||
TickFrequency="{x:Bind Frequency, Mode=OneWay}"
|
||||
TickPlacement="Outside"
|
||||
Value="{x:Bind Value, Mode=TwoWay}" />
|
||||
<Button
|
||||
Margin="3,0,0,0"
|
||||
VerticalAlignment="Center"
|
||||
Click="ResetButton_Click"
|
||||
Content="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
|
||||
FontSize=12,
|
||||
Glyph=}"
|
||||
Style="{StaticResource GhostButtonStyle}"
|
||||
Visibility="{x:Bind ResetButtonVisibility, Mode=OneWay}" />
|
||||
<Button
|
||||
x:Name="SubtractButton"
|
||||
Margin="3,0,0,0"
|
||||
VerticalAlignment="Center"
|
||||
Click="SubtractButton_Click"
|
||||
Content="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
|
||||
FontSize=12,
|
||||
Glyph=}"
|
||||
Style="{StaticResource GhostButtonStyle}" />
|
||||
<Button
|
||||
x:Name="AddButton"
|
||||
Margin="3,0,0,0"
|
||||
VerticalAlignment="Center"
|
||||
Click="AddButton_Click"
|
||||
Content="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
|
||||
FontSize=12,
|
||||
Glyph=}"
|
||||
Style="{StaticResource GhostButtonStyle}" />
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,129 @@
|
||||
using Microsoft.UI.Input;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Controls.Primitives;
|
||||
using Microsoft.UI.Xaml.Data;
|
||||
using Microsoft.UI.Xaml.Input;
|
||||
using Microsoft.UI.Xaml.Media;
|
||||
using Microsoft.UI.Xaml.Navigation;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices.WindowsRuntime;
|
||||
using Windows.Foundation;
|
||||
using Windows.Foundation.Collections;
|
||||
|
||||
// To learn more about WinUI, the WinUI project structure,
|
||||
// and more about our project templates, see: http://aka.ms/winui-project-info.
|
||||
|
||||
namespace BetterLyrics.WinUI3.Controls
|
||||
{
|
||||
public sealed partial class ExtendedSlider : UserControl
|
||||
{
|
||||
public ExtendedSlider()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void Subtract()
|
||||
{
|
||||
if (Value - Frequency < Minimum)
|
||||
{
|
||||
Value = Minimum;
|
||||
}
|
||||
else
|
||||
{
|
||||
Value -= Frequency;
|
||||
}
|
||||
}
|
||||
|
||||
private void Add()
|
||||
{
|
||||
if (Value + Frequency > Maximum)
|
||||
{
|
||||
Value = Maximum;
|
||||
}
|
||||
else
|
||||
{
|
||||
Value += Frequency;
|
||||
}
|
||||
}
|
||||
|
||||
private void SubtractTimer_Tick(object? sender, object e)
|
||||
{
|
||||
Subtract();
|
||||
}
|
||||
|
||||
private void AddTimer_Tick(object? sender, object e)
|
||||
{
|
||||
Add();
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty FrequencyProperty =
|
||||
DependencyProperty.Register(nameof(Frequency), typeof(double), typeof(ExtendedSlider), new PropertyMetadata(default));
|
||||
public static readonly DependencyProperty MinimumProperty =
|
||||
DependencyProperty.Register(nameof(Minimum), typeof(double), typeof(ExtendedSlider), new PropertyMetadata(default));
|
||||
public static readonly DependencyProperty MaximumProperty =
|
||||
DependencyProperty.Register(nameof(Maximum), typeof(double), typeof(ExtendedSlider), new PropertyMetadata(default));
|
||||
public static readonly DependencyProperty ValueProperty =
|
||||
DependencyProperty.Register(nameof(Value), typeof(double), typeof(ExtendedSlider), new PropertyMetadata(default));
|
||||
public static readonly DependencyProperty DefaultProperty =
|
||||
DependencyProperty.Register(nameof(Default), typeof(double), typeof(ExtendedSlider), new PropertyMetadata(default));
|
||||
public static readonly DependencyProperty ResetButtonVisibilityProperty =
|
||||
DependencyProperty.Register(nameof(ResetButtonVisibility), typeof(Visibility), typeof(ExtendedSlider), new PropertyMetadata(Visibility.Visible));
|
||||
public static readonly DependencyProperty UnitProperty =
|
||||
DependencyProperty.Register(nameof(Unit), typeof(string), typeof(ExtendedSlider), new PropertyMetadata(""));
|
||||
|
||||
public double Frequency
|
||||
{
|
||||
get => (double)GetValue(FrequencyProperty);
|
||||
set => SetValue(FrequencyProperty, value);
|
||||
}
|
||||
public double Minimum
|
||||
{
|
||||
get => (double)GetValue(MinimumProperty);
|
||||
set => SetValue(MinimumProperty, value);
|
||||
}
|
||||
public double Maximum
|
||||
{
|
||||
get => (double)GetValue(MaximumProperty);
|
||||
set => SetValue(MaximumProperty, value);
|
||||
}
|
||||
public double Value
|
||||
{
|
||||
get => (double)GetValue(ValueProperty);
|
||||
set => SetValue(ValueProperty, value);
|
||||
}
|
||||
public double Default
|
||||
{
|
||||
get => (double)GetValue(DefaultProperty);
|
||||
set => SetValue(DefaultProperty, value);
|
||||
}
|
||||
public Visibility ResetButtonVisibility
|
||||
{
|
||||
get => (Visibility)GetValue(ResetButtonVisibilityProperty);
|
||||
set => SetValue(ResetButtonVisibilityProperty, value);
|
||||
}
|
||||
public string Unit
|
||||
{
|
||||
get => (string)GetValue(UnitProperty);
|
||||
set => SetValue(UnitProperty, value);
|
||||
}
|
||||
|
||||
private void ResetButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
Value = Default;
|
||||
}
|
||||
|
||||
private void SubtractButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
Subtract();
|
||||
}
|
||||
|
||||
private void AddButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
Add();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<UserControl
|
||||
x:Class="BetterLyrics.WinUI3.Controls.LyricsBavkgroundSettingsControl"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:controls="using:CommunityToolkit.WinUI.Controls"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:uc="using:BetterLyrics.WinUI3.Controls"
|
||||
xmlns:ui="using:CommunityToolkit.WinUI"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<Grid>
|
||||
<ScrollViewer Style="{StaticResource SettingsScrollViewerStyle}">
|
||||
<Grid Style="{StaticResource SettingsGridStyle}">
|
||||
<StackPanel Spacing="{StaticResource SettingsCardSpacing}">
|
||||
|
||||
<TextBlock Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" />
|
||||
|
||||
<controls:SettingsCard x:Uid="SettingsPageTheme" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||
<ComboBox x:Name="ThemeComboBox" SelectedIndex="{x:Bind ViewModel.AppSettings.LyricsBackgroundSettings.LyricsBackgroundTheme, Mode=TwoWay, Converter={StaticResource EnumToIntConverter}}">
|
||||
<ComboBoxItem x:Uid="SettingsPageFollowSystem" />
|
||||
<ComboBoxItem x:Uid="SettingsPageLight" />
|
||||
<ComboBoxItem x:Uid="SettingsPageDark" />
|
||||
</ComboBox>
|
||||
</controls:SettingsCard>
|
||||
|
||||
<controls:SettingsCard x:Uid="SettingsPageLyricsPureColorBgOpacity" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||
<uc:ExtendedSlider
|
||||
Default="100"
|
||||
Frequency="1"
|
||||
Maximum="100"
|
||||
Minimum="0"
|
||||
Unit="%"
|
||||
Value="{x:Bind ViewModel.AppSettings.LyricsBackgroundSettings.PureColorOverlayOpacity, Mode=TwoWay}" />
|
||||
</controls:SettingsCard>
|
||||
|
||||
<controls:SettingsCard x:Uid="SettingsPageLyricsBackgroundOpacity" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||
<uc:ExtendedSlider
|
||||
Default="100"
|
||||
Frequency="1"
|
||||
Maximum="100"
|
||||
Minimum="0"
|
||||
Unit="%"
|
||||
Value="{x:Bind ViewModel.AppSettings.LyricsBackgroundSettings.CoverOverlayOpacity, Mode=TwoWay}" />
|
||||
</controls:SettingsCard>
|
||||
|
||||
<controls:SettingsCard x:Uid="SettingsPageLyricsBackgroundSpeed" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||
<uc:ExtendedSlider
|
||||
Default="50"
|
||||
Frequency="1"
|
||||
Maximum="100"
|
||||
Minimum="0"
|
||||
Unit="%"
|
||||
Value="{x:Bind ViewModel.AppSettings.LyricsBackgroundSettings.CoverOverlaySpeed, Mode=TwoWay}" />
|
||||
</controls:SettingsCard>
|
||||
|
||||
<controls:SettingsCard x:Uid="SettingsPageLyricsBackgroundBlurAmount" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||
<uc:ExtendedSlider
|
||||
Default="100"
|
||||
Frequency="1"
|
||||
Maximum="100"
|
||||
Minimum="0"
|
||||
Value="{x:Bind ViewModel.AppSettings.LyricsBackgroundSettings.CoverOverlayBlurAmount, Mode=TwoWay}" />
|
||||
</controls:SettingsCard>
|
||||
|
||||
<controls:SettingsCard x:Uid="SettingsPageBackgroundAcrylicEffectAmount" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||
<uc:ExtendedSlider
|
||||
Default="0"
|
||||
Frequency="1"
|
||||
Maximum="10"
|
||||
Minimum="0"
|
||||
Value="{x:Bind ViewModel.AppSettings.LyricsBackgroundSettings.CoverAcrylicEffectAmount, Mode=TwoWay}" />
|
||||
</controls:SettingsCard>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</ScrollViewer>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,33 @@
|
||||
using BetterLyrics.WinUI3.ViewModels;
|
||||
using CommunityToolkit.Mvvm.DependencyInjection;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Controls.Primitives;
|
||||
using Microsoft.UI.Xaml.Data;
|
||||
using Microsoft.UI.Xaml.Input;
|
||||
using Microsoft.UI.Xaml.Media;
|
||||
using Microsoft.UI.Xaml.Navigation;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices.WindowsRuntime;
|
||||
using Windows.Foundation;
|
||||
using Windows.Foundation.Collections;
|
||||
|
||||
// To learn more about WinUI, the WinUI project structure,
|
||||
// and more about our project templates, see: http://aka.ms/winui-project-info.
|
||||
|
||||
namespace BetterLyrics.WinUI3.Controls
|
||||
{
|
||||
public sealed partial class LyricsBavkgroundSettingsControl : UserControl
|
||||
{
|
||||
public LyricsBackgroundSettingsControlViewModel ViewModel => (LyricsBackgroundSettingsControlViewModel)DataContext;
|
||||
|
||||
public LyricsBavkgroundSettingsControl()
|
||||
{
|
||||
InitializeComponent();
|
||||
DataContext = Ioc.Default.GetRequiredService<LyricsBackgroundSettingsControlViewModel>();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,379 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<UserControl
|
||||
x:Class="BetterLyrics.WinUI3.Controls.LyricsSettingsControl"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:controls="using:CommunityToolkit.WinUI.Controls"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:interactivity="using:Microsoft.Xaml.Interactivity"
|
||||
xmlns:local="using:BetterLyrics.WinUI3.Controls"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:ui="using:CommunityToolkit.WinUI"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<Grid>
|
||||
<ScrollViewer Style="{StaticResource SettingsScrollViewerStyle}">
|
||||
<Grid Style="{StaticResource SettingsGridStyle}">
|
||||
<StackPanel Spacing="{StaticResource SettingsCardSpacing}">
|
||||
|
||||
<!-- Lyrics style -->
|
||||
|
||||
<TextBlock x:Uid="SettingsPageLyricsStyle" Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" />
|
||||
|
||||
<controls:SettingsCard x:Uid="SettingsPageLyricsAlignment" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||
<ComboBox SelectedIndex="{x:Bind LyricsStyleSettings.LyricsAlignmentType, Mode=TwoWay, Converter={StaticResource EnumToIntConverter}}">
|
||||
<ComboBoxItem x:Uid="SettingsPageLyricsLeft" />
|
||||
<ComboBoxItem x:Uid="SettingsPageLyricsCenter" />
|
||||
<ComboBoxItem x:Uid="SettingsPageLyricsRight" />
|
||||
</ComboBox>
|
||||
</controls:SettingsCard>
|
||||
|
||||
<controls:SettingsCard x:Uid="SettingsPageLyricsFontFamily" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||
<ComboBox ItemsSource="{x:Bind SystemFontNames, Mode=OneWay}" SelectedItem="{x:Bind LyricsStyleSettings.LyricsFontFamily, Mode=TwoWay}">
|
||||
<ComboBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding}" />
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
</controls:SettingsCard>
|
||||
|
||||
<controls:SettingsCard x:Uid="SettingsPageLyricsFontWeight" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||
<ComboBox SelectedIndex="{x:Bind LyricsStyleSettings.LyricsFontWeight, Mode=TwoWay, Converter={StaticResource EnumToIntConverter}}">
|
||||
<ComboBoxItem x:Uid="SettingsPageLyricsThin" />
|
||||
<ComboBoxItem x:Uid="SettingsPageLyricsExtraLight" />
|
||||
<ComboBoxItem x:Uid="SettingsPageLyricsLight" />
|
||||
<ComboBoxItem x:Uid="SettingsPageLyricsSemiLight" />
|
||||
<ComboBoxItem x:Uid="SettingsPageLyricsNormal" />
|
||||
<ComboBoxItem x:Uid="SettingsPageLyricsMedium" />
|
||||
<ComboBoxItem x:Uid="SettingsPageLyricsSemiBold" />
|
||||
<ComboBoxItem x:Uid="SettingsPageLyricsBold" />
|
||||
<ComboBoxItem x:Uid="SettingsPageLyricsExtraBold" />
|
||||
<ComboBoxItem x:Uid="SettingsPageLyricsBlack" />
|
||||
<ComboBoxItem x:Uid="SettingsPageLyricsExtraBlack" />
|
||||
</ComboBox>
|
||||
</controls:SettingsCard>
|
||||
|
||||
<controls:SettingsCard x:Uid="SettingsPageLyricsBgFontOpacity" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||
<local:ExtendedSlider
|
||||
Default="30"
|
||||
Frequency="1"
|
||||
Maximum="100"
|
||||
Minimum="0"
|
||||
Unit="%"
|
||||
Value="{x:Bind LyricsStyleSettings.LyricsBgFontOpacity, Mode=TwoWay}" />
|
||||
</controls:SettingsCard>
|
||||
|
||||
<controls:SettingsCard x:Uid="SettingsPageLyricsFontStrokeWidth" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||
<local:ExtendedSlider
|
||||
Default="0"
|
||||
Frequency="1"
|
||||
Maximum="5"
|
||||
Minimum="0"
|
||||
Value="{x:Bind LyricsStyleSettings.LyricsFontStrokeWidth, Mode=TwoWay}" />
|
||||
</controls:SettingsCard>
|
||||
|
||||
<controls:SettingsCard x:Uid="SettingsPageLyricsStrokeFontColor" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||
<ComboBox SelectedIndex="{x:Bind LyricsStyleSettings.LyricsStrokeFontColorType, Mode=TwoWay, Converter={StaticResource EnumToIntConverter}}">
|
||||
<ComboBoxItem x:Uid="SettingsPageLyricsFontColorAdaptiveColored" />
|
||||
<ComboBoxItem x:Uid="SettingsPageLyricsFontColorAdaptiveGrayed" />
|
||||
<ComboBoxItem x:Uid="SettingsPageLyricsFontColorCustom" />
|
||||
</ComboBox>
|
||||
</controls:SettingsCard>
|
||||
|
||||
<ColorPicker
|
||||
ColorSpectrumShape="Box"
|
||||
IsAlphaEnabled="True"
|
||||
IsAlphaSliderVisible="True"
|
||||
IsAlphaTextInputVisible="True"
|
||||
IsColorChannelTextInputVisible="True"
|
||||
IsColorSliderVisible="True"
|
||||
IsHexInputVisible="True"
|
||||
IsMoreButtonVisible="True"
|
||||
Color="{x:Bind LyricsStyleSettings.LyricsCustomStrokeFontColor, Mode=TwoWay}">
|
||||
<interactivity:Interaction.Behaviors>
|
||||
<interactivity:DataTriggerBehavior
|
||||
Binding="{x:Bind LyricsStyleSettings.LyricsStrokeFontColorType, Mode=OneWay, Converter={StaticResource EnumToIntConverter}}"
|
||||
ComparisonCondition="Equal"
|
||||
Value="2">
|
||||
<interactivity:ChangePropertyAction PropertyName="Visibility" Value="Visible" />
|
||||
</interactivity:DataTriggerBehavior>
|
||||
<interactivity:DataTriggerBehavior
|
||||
Binding="{x:Bind LyricsStyleSettings.LyricsStrokeFontColorType, Mode=OneWay, Converter={StaticResource EnumToIntConverter}}"
|
||||
ComparisonCondition="NotEqual"
|
||||
Value="2">
|
||||
<interactivity:ChangePropertyAction PropertyName="Visibility" Value="Collapsed" />
|
||||
</interactivity:DataTriggerBehavior>
|
||||
</interactivity:Interaction.Behaviors>
|
||||
</ColorPicker>
|
||||
|
||||
<controls:SettingsCard x:Uid="SettingsPageLyricsBgFontColor" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||
<ComboBox SelectedIndex="{x:Bind LyricsStyleSettings.LyricsBgFontColorType, Mode=TwoWay, Converter={StaticResource EnumToIntConverter}}">
|
||||
<ComboBoxItem x:Uid="SettingsPageLyricsFontColorAdaptiveColored" />
|
||||
<ComboBoxItem x:Uid="SettingsPageLyricsFontColorAdaptiveGrayed" />
|
||||
<ComboBoxItem x:Uid="SettingsPageLyricsFontColorCustom" />
|
||||
</ComboBox>
|
||||
</controls:SettingsCard>
|
||||
|
||||
<ColorPicker
|
||||
ColorSpectrumShape="Box"
|
||||
IsAlphaEnabled="True"
|
||||
IsAlphaSliderVisible="True"
|
||||
IsAlphaTextInputVisible="True"
|
||||
IsColorChannelTextInputVisible="True"
|
||||
IsColorSliderVisible="True"
|
||||
IsHexInputVisible="True"
|
||||
IsMoreButtonVisible="True"
|
||||
Color="{x:Bind LyricsStyleSettings.LyricsCustomBgFontColor, Mode=TwoWay}">
|
||||
<interactivity:Interaction.Behaviors>
|
||||
<interactivity:DataTriggerBehavior
|
||||
Binding="{x:Bind LyricsStyleSettings.LyricsBgFontColorType, Mode=OneWay, Converter={StaticResource EnumToIntConverter}}"
|
||||
ComparisonCondition="Equal"
|
||||
Value="2">
|
||||
<interactivity:ChangePropertyAction PropertyName="Visibility" Value="Visible" />
|
||||
</interactivity:DataTriggerBehavior>
|
||||
<interactivity:DataTriggerBehavior
|
||||
Binding="{x:Bind LyricsStyleSettings.LyricsBgFontColorType, Mode=OneWay, Converter={StaticResource EnumToIntConverter}}"
|
||||
ComparisonCondition="NotEqual"
|
||||
Value="2">
|
||||
<interactivity:ChangePropertyAction PropertyName="Visibility" Value="Collapsed" />
|
||||
</interactivity:DataTriggerBehavior>
|
||||
</interactivity:Interaction.Behaviors>
|
||||
</ColorPicker>
|
||||
|
||||
<controls:SettingsCard x:Uid="SettingsPageLyricsFgFontColor" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||
<ComboBox SelectedIndex="{x:Bind LyricsStyleSettings.LyricsFgFontColorType, Mode=TwoWay, Converter={StaticResource EnumToIntConverter}}">
|
||||
<ComboBoxItem x:Uid="SettingsPageLyricsFontColorAdaptiveColored" />
|
||||
<ComboBoxItem x:Uid="SettingsPageLyricsFontColorAdaptiveGrayed" />
|
||||
<ComboBoxItem x:Uid="SettingsPageLyricsFontColorCustom" />
|
||||
</ComboBox>
|
||||
</controls:SettingsCard>
|
||||
|
||||
<ColorPicker
|
||||
ColorSpectrumShape="Box"
|
||||
IsAlphaEnabled="True"
|
||||
IsAlphaSliderVisible="True"
|
||||
IsAlphaTextInputVisible="True"
|
||||
IsColorChannelTextInputVisible="True"
|
||||
IsColorSliderVisible="True"
|
||||
IsHexInputVisible="True"
|
||||
IsMoreButtonVisible="True"
|
||||
Color="{x:Bind LyricsStyleSettings.LyricsCustomFgFontColor, Mode=TwoWay}">
|
||||
<interactivity:Interaction.Behaviors>
|
||||
<interactivity:DataTriggerBehavior
|
||||
Binding="{x:Bind LyricsStyleSettings.LyricsFgFontColorType, Mode=OneWay, Converter={StaticResource EnumToIntConverter}}"
|
||||
ComparisonCondition="Equal"
|
||||
Value="2">
|
||||
<interactivity:ChangePropertyAction PropertyName="Visibility" Value="Visible" />
|
||||
</interactivity:DataTriggerBehavior>
|
||||
<interactivity:DataTriggerBehavior
|
||||
Binding="{x:Bind LyricsStyleSettings.LyricsFgFontColorType, Mode=OneWay, Converter={StaticResource EnumToIntConverter}}"
|
||||
ComparisonCondition="NotEqual"
|
||||
Value="2">
|
||||
<interactivity:ChangePropertyAction PropertyName="Visibility" Value="Collapsed" />
|
||||
</interactivity:DataTriggerBehavior>
|
||||
</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:SettingsCard x:Uid="SettingsPageLyricsLineSpacingFactor" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||
<local:ExtendedSlider
|
||||
x:Uid="SettingsPageLyricsLineSpacingFactorSlider"
|
||||
Default="0.5"
|
||||
Frequency="0.1"
|
||||
Maximum="2"
|
||||
Minimum="0"
|
||||
Unit="x"
|
||||
Value="{x:Bind LyricsStyleSettings.LyricsLineSpacingFactor, Mode=TwoWay}" />
|
||||
</controls:SettingsCard>
|
||||
|
||||
<controls:SettingsCard x:Uid="SettingsPageLyricsTranslationSeparator" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||
<StackPanel Orientation="Horizontal" Spacing="6">
|
||||
<TextBox AcceptsReturn="True" Text="{x:Bind LyricsStyleSettings.LyricsTranslationSeparator, Mode=TwoWay}" />
|
||||
<Button Content="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, FontSize=12, Glyph=}" Style="{StaticResource GhostButtonStyle}" />
|
||||
</StackPanel>
|
||||
</controls:SettingsCard>
|
||||
|
||||
<!-- Effect -->
|
||||
|
||||
<TextBlock
|
||||
x:Uid="SettingsPageLyricsEffect"
|
||||
Style="{StaticResource SettingsSectionHeaderTextBlockStyle}"
|
||||
Text="Effect" />
|
||||
|
||||
<controls:SettingsCard x:Uid="SettingsPageLyricsVerticalEdgeOpacity" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||
<local:ExtendedSlider
|
||||
x:Uid="SettingsPageLyricsVerticalEdgeOpacitySlider"
|
||||
Default="0"
|
||||
Frequency="1"
|
||||
Maximum="100"
|
||||
Minimum="0"
|
||||
Unit="%"
|
||||
Value="{x:Bind LyricsEffectSettings.LyricsVerticalEdgeOpacity, Mode=TwoWay}" />
|
||||
</controls:SettingsCard>
|
||||
|
||||
<controls:SettingsCard x:Uid="SettingsPageLyricsBlurAmount" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||
<local:ExtendedSlider
|
||||
x:Uid="SettingsPageLyricsBlurAmountExtendedSlider"
|
||||
Default="5"
|
||||
Frequency="1"
|
||||
Maximum="10"
|
||||
Minimum="0"
|
||||
Value="{x:Bind LyricsEffectSettings.LyricsBlurAmount, Mode=TwoWay}" />
|
||||
</controls:SettingsCard>
|
||||
|
||||
<controls:SettingsCard x:Uid="SettingsPageLyricsLineFade" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||
<ToggleSwitch IsOn="{x:Bind LyricsEffectSettings.IsLyricsLineFadeEnabled, Mode=TwoWay}" />
|
||||
</controls:SettingsCard>
|
||||
|
||||
<!-- 高亮 -->
|
||||
<controls:SettingsCard x:Uid="SettingsPageLyricsHighlightScope" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||
<ComboBox SelectedIndex="{x:Bind LyricsEffectSettings.LyricsHighlightScope, Mode=TwoWay, Converter={StaticResource EnumToIntConverter}}">
|
||||
<ComboBoxItem x:Uid="SettingsPageLyricsRendingScopeCurrentChar" />
|
||||
<ComboBoxItem x:Uid="SettingsPageLyricsRendingScopeLineStartToCurrentChar" />
|
||||
<ComboBoxItem x:Uid="SettingsPageLyricsRendingScopeCurrentLine" />
|
||||
</ComboBox>
|
||||
</controls:SettingsCard>
|
||||
|
||||
<!-- 阴影 -->
|
||||
<controls:SettingsExpander
|
||||
x:Uid="SettingsPageLyricsShadow"
|
||||
HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
|
||||
Glyph=}"
|
||||
IsExpanded="{x:Bind LyricsEffectSettings.IsLyricsShadowEnabled, Mode=OneWay}">
|
||||
<ToggleSwitch IsOn="{x:Bind LyricsEffectSettings.IsLyricsShadowEnabled, Mode=TwoWay}" />
|
||||
<controls:SettingsExpander.Items>
|
||||
<controls:SettingsCard x:Uid="SettingsPageScope" IsEnabled="{x:Bind LyricsEffectSettings.IsLyricsShadowEnabled, Mode=OneWay}">
|
||||
<ComboBox SelectedIndex="{x:Bind LyricsEffectSettings.LyricsShadowScope, Mode=TwoWay, Converter={StaticResource EnumToIntConverter}}">
|
||||
<ComboBoxItem x:Uid="SettingsPageLyricsRendingScopeCurrentChar" />
|
||||
<ComboBoxItem x:Uid="SettingsPageLyricsRendingScopeLineStartToCurrentChar" />
|
||||
<ComboBoxItem x:Uid="SettingsPageLyricsRendingScopeCurrentLine" />
|
||||
</ComboBox>
|
||||
</controls:SettingsCard>
|
||||
<controls:SettingsCard x:Uid="SettingsPageAmount" IsEnabled="{x:Bind LyricsEffectSettings.IsLyricsShadowEnabled, Mode=OneWay}">
|
||||
<local:ExtendedSlider
|
||||
Default="8"
|
||||
Frequency="1"
|
||||
Maximum="20"
|
||||
Minimum="1"
|
||||
Value="{x:Bind LyricsEffectSettings.LyricsShadowAmount, Mode=TwoWay}" />
|
||||
</controls:SettingsCard>
|
||||
</controls:SettingsExpander.Items>
|
||||
</controls:SettingsExpander>
|
||||
|
||||
<!-- 辉光效果 -->
|
||||
<controls:SettingsExpander
|
||||
x:Uid="SettingsPageLyricsGlowEffect"
|
||||
HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
|
||||
Glyph=}"
|
||||
IsExpanded="{x:Bind LyricsEffectSettings.IsLyricsGlowEffectEnabled, Mode=OneWay}">
|
||||
<ToggleSwitch IsOn="{x:Bind LyricsEffectSettings.IsLyricsGlowEffectEnabled, Mode=TwoWay}" />
|
||||
<controls:SettingsExpander.Items>
|
||||
<controls:SettingsCard x:Uid="SettingsPageScope" IsEnabled="{x:Bind LyricsEffectSettings.IsLyricsGlowEffectEnabled, Mode=OneWay}">
|
||||
<ComboBox SelectedIndex="{x:Bind LyricsEffectSettings.LyricsGlowEffectScope, Mode=TwoWay, Converter={StaticResource EnumToIntConverter}}">
|
||||
<ComboBoxItem x:Uid="SettingsPageLyricsRendingScopeCurrentChar" />
|
||||
<ComboBoxItem x:Uid="SettingsPageLyricsRendingScopeLineStartToCurrentChar" />
|
||||
<ComboBoxItem x:Uid="SettingsPageLyricsRendingScopeCurrentLine" />
|
||||
</ComboBox>
|
||||
</controls:SettingsCard>
|
||||
<controls:SettingsCard x:Uid="SettingsPageAmount" IsEnabled="{x:Bind LyricsEffectSettings.IsLyricsGlowEffectEnabled, Mode=OneWay}">
|
||||
<local:ExtendedSlider
|
||||
Default="8"
|
||||
Frequency="1"
|
||||
Maximum="20"
|
||||
Minimum="1"
|
||||
Value="{x:Bind LyricsEffectSettings.LyricsGlowEffectAmount, Mode=TwoWay}" />
|
||||
</controls:SettingsCard>
|
||||
</controls:SettingsExpander.Items>
|
||||
</controls:SettingsExpander>
|
||||
|
||||
<!-- 浮动动画 -->
|
||||
<controls:SettingsExpander
|
||||
x:Uid="SettingsPageLyricsFloatAnimation"
|
||||
HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
|
||||
Glyph=}"
|
||||
IsExpanded="True">
|
||||
<ToggleSwitch IsOn="{x:Bind LyricsEffectSettings.IsLyricsFloatAnimationEnabled, Mode=TwoWay}" />
|
||||
<controls:SettingsExpander.Items>
|
||||
<controls:SettingsCard x:Uid="SettingsPageAmount" IsEnabled="{x:Bind LyricsEffectSettings.IsLyricsGlowEffectEnabled, Mode=OneWay}">
|
||||
<local:ExtendedSlider
|
||||
Default="1"
|
||||
Frequency="1"
|
||||
Maximum="4"
|
||||
Minimum="1"
|
||||
Value="{x:Bind LyricsEffectSettings.LyricsFloatAmount, Mode=TwoWay}" />
|
||||
</controls:SettingsCard>
|
||||
</controls:SettingsExpander.Items>
|
||||
</controls:SettingsExpander>
|
||||
|
||||
<!-- 扇形歌词 -->
|
||||
<controls:SettingsCard x:Uid="SettingsPageFan" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||
<ToggleSwitch IsOn="{x:Bind LyricsEffectSettings.IsFanLyricsEnabled, Mode=TwoWay}" />
|
||||
</controls:SettingsCard>
|
||||
|
||||
<controls:SettingsExpander
|
||||
x:Uid="SettingsPageScrollEasing"
|
||||
HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
|
||||
Glyph=}"
|
||||
IsExpanded="True">
|
||||
<ComboBox SelectedIndex="{x:Bind LyricsEffectSettings.LyricsScrollEasingType, Mode=TwoWay, Converter={StaticResource EnumToIntConverter}}">
|
||||
<ComboBoxItem x:Uid="SettingsPageEasingTypeLinear" />
|
||||
<ComboBoxItem x:Uid="SettingsPageEasingTypeSmoothStep" />
|
||||
<ComboBoxItem x:Uid="SettingsPageEasingTypeEaseInOutSine" />
|
||||
<ComboBoxItem x:Uid="SettingsPageEasingTypeEaseInOutQuad" />
|
||||
<ComboBoxItem x:Uid="SettingsPageEasingTypeEaseInOutCubic" />
|
||||
<ComboBoxItem x:Uid="SettingsPageEasingTypeEaseInOutQuart" />
|
||||
<ComboBoxItem x:Uid="SettingsPageEasingTypeEaseInOutQuint" />
|
||||
<ComboBoxItem x:Uid="SettingsPageEasingTypeEaseInOutExpo" />
|
||||
<ComboBoxItem x:Uid="SettingsPageEasingTypeEaseInOutCirc" />
|
||||
<ComboBoxItem x:Uid="SettingsPageEasingTypeEaseInOutBack" />
|
||||
<ComboBoxItem x:Uid="SettingsPageEasingTypeEaseInOutElastic" />
|
||||
<ComboBoxItem x:Uid="SettingsPageEasingTypeEaseInOutBounce" />
|
||||
</ComboBox>
|
||||
<controls:SettingsExpander.Items>
|
||||
<controls:SettingsCard x:Uid="SettingsPageScrollTopDuration">
|
||||
<local:ExtendedSlider
|
||||
x:Uid="SettingsPageLyricsScrollTopDurationExtendedSlider"
|
||||
Default="500"
|
||||
Frequency="50"
|
||||
Maximum="1000"
|
||||
Minimum="50"
|
||||
Unit="ms"
|
||||
Value="{x:Bind LyricsEffectSettings.LyricsScrollTopDuration, Mode=TwoWay}" />
|
||||
</controls:SettingsCard>
|
||||
<controls:SettingsCard x:Uid="SettingsPageScrollDuration">
|
||||
<local:ExtendedSlider
|
||||
x:Uid="SettingsPageLyricsScrollDurationExtendedSlider"
|
||||
Default="500"
|
||||
Frequency="50"
|
||||
Maximum="1000"
|
||||
Minimum="50"
|
||||
Unit="ms"
|
||||
Value="{x:Bind LyricsEffectSettings.LyricsScrollDuration, Mode=TwoWay}" />
|
||||
</controls:SettingsCard>
|
||||
<controls:SettingsCard x:Uid="SettingsPageScrollBottomDuration">
|
||||
<local:ExtendedSlider
|
||||
x:Uid="SettingsPageLyricsScrollBottomDurationExtendedSlider"
|
||||
Default="500"
|
||||
Frequency="50"
|
||||
Maximum="1000"
|
||||
Minimum="50"
|
||||
Unit="ms"
|
||||
Value="{x:Bind LyricsEffectSettings.LyricsScrollBottomDuration, Mode=TwoWay}" />
|
||||
</controls:SettingsCard>
|
||||
</controls:SettingsExpander.Items>
|
||||
</controls:SettingsExpander>
|
||||
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</ScrollViewer>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,53 @@
|
||||
using BetterLyrics.WinUI3.Helper;
|
||||
using BetterLyrics.WinUI3.Models.Settings;
|
||||
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.Collections.ObjectModel;
|
||||
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.Controls
|
||||
{
|
||||
public sealed partial class LyricsSettingsControl : UserControl
|
||||
{
|
||||
public ObservableCollection<string> SystemFontNames { get; set; } = [.. FontHelper.SystemFontFamilies];
|
||||
|
||||
public LyricsSettingsControl()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty LyricsStyleSettingsProperty =
|
||||
DependencyProperty.Register(nameof(LyricsStyleSettings), typeof(LyricsStyleSettings), typeof(LyricsSettingsControl), new PropertyMetadata(default));
|
||||
|
||||
public LyricsStyleSettings LyricsStyleSettings
|
||||
{
|
||||
get => (LyricsStyleSettings)GetValue(LyricsStyleSettingsProperty);
|
||||
set => SetValue(LyricsStyleSettingsProperty, value);
|
||||
}
|
||||
|
||||
|
||||
public static readonly DependencyProperty LyricsEffectSettingsProperty =
|
||||
DependencyProperty.Register(nameof(LyricsEffectSettings), typeof(LyricsEffectSettings), typeof(LyricsSettingsControl), new PropertyMetadata(default));
|
||||
|
||||
public LyricsEffectSettings LyricsEffectSettings
|
||||
{
|
||||
get => (LyricsEffectSettings)GetValue(LyricsEffectSettingsProperty);
|
||||
set => SetValue(LyricsEffectSettingsProperty, value);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<UserControl
|
||||
x:Class="BetterLyrics.WinUI3.Controls.MediaSettingsControl"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:controls="using:CommunityToolkit.WinUI.Controls"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:interactivity="using:Microsoft.Xaml.Interactivity"
|
||||
xmlns:local="using:BetterLyrics.WinUI3.Controls"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:ui="using:CommunityToolkit.WinUI"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<Grid>
|
||||
<ScrollViewer Style="{StaticResource SettingsScrollViewerStyle}">
|
||||
<Grid Style="{StaticResource SettingsGridStyle}">
|
||||
<StackPanel>
|
||||
|
||||
<TextBlock Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" />
|
||||
|
||||
<controls:SettingsCard x:Uid="SettingsPageMusicLib" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}" />
|
||||
|
||||
<InfoBar
|
||||
x:Uid="SettingsPageRemoveInfo"
|
||||
BorderThickness="0"
|
||||
CornerRadius="0"
|
||||
IsClosable="False"
|
||||
IsOpen="True"
|
||||
Severity="Success">
|
||||
<interactivity:Interaction.Behaviors>
|
||||
<interactivity:DataTriggerBehavior
|
||||
Binding="{x:Bind ViewModel.AppSettings.LocalMediaFolders.Count, Mode=OneWay}"
|
||||
ComparisonCondition="Equal"
|
||||
Value="0">
|
||||
<interactivity:ChangePropertyAction PropertyName="Visibility" Value="Collapsed" />
|
||||
</interactivity:DataTriggerBehavior>
|
||||
<interactivity:DataTriggerBehavior
|
||||
Binding="{x:Bind ViewModel.AppSettings.LocalMediaFolders.Count, Mode=OneWay}"
|
||||
ComparisonCondition="NotEqual"
|
||||
Value="0">
|
||||
<interactivity:ChangePropertyAction PropertyName="Visibility" Value="Visible" />
|
||||
</interactivity:DataTriggerBehavior>
|
||||
</interactivity:Interaction.Behaviors>
|
||||
</InfoBar>
|
||||
|
||||
<ListView
|
||||
ItemContainerStyle="{StaticResource ListViewStretchedItemContainerStyle}"
|
||||
ItemsSource="{x:Bind ViewModel.AppSettings.LocalMediaFolders, Mode=OneWay}"
|
||||
SelectionMode="None">
|
||||
<ListView.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<controls:SettingsExpander>
|
||||
<controls:SettingsExpander.Header>
|
||||
<HyperlinkButton
|
||||
Click="LocalFolderHyperlinkButton_Click"
|
||||
Content="{Binding Path, Mode=OneWay}"
|
||||
Tag="{Binding Path, Mode=OneWay}" />
|
||||
</controls:SettingsExpander.Header>
|
||||
<ToggleSwitch IsOn="{Binding IsEnabled, Mode=TwoWay}" />
|
||||
<controls:SettingsExpander.Items>
|
||||
<controls:SettingsCard>
|
||||
<controls:SettingsCard.Header>
|
||||
<HyperlinkButton
|
||||
x:Uid="SettingsPageRemovePath"
|
||||
Click="SettingsPageRemovePathButton_Click"
|
||||
Tag="{Binding}" />
|
||||
</controls:SettingsCard.Header>
|
||||
</controls:SettingsCard>
|
||||
<controls:SettingsCard x:Uid="SettingsPageMusicLibRealTimeWatch">
|
||||
<ToggleSwitch IsOn="{Binding IsRealTimeWatchEnabled, Mode=TwoWay}" />
|
||||
</controls:SettingsCard>
|
||||
</controls:SettingsExpander.Items>
|
||||
</controls:SettingsExpander>
|
||||
</DataTemplate>
|
||||
</ListView.ItemTemplate>
|
||||
</ListView>
|
||||
|
||||
<controls:SettingsCard x:Uid="SettingsPageAddFolder" Style="{StaticResource DefaultSettingsExpanderItemStyle}">
|
||||
<Button
|
||||
x:Uid="SettingsPageAddFolderButton"
|
||||
Command="{x:Bind ViewModel.SelectAndAddFolderCommand}"
|
||||
CommandParameter="{Binding ElementName=RootGrid}" />
|
||||
</controls:SettingsCard>
|
||||
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</ScrollViewer>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,50 @@
|
||||
using BetterLyrics.WinUI3.Models;
|
||||
using BetterLyrics.WinUI3.ViewModels;
|
||||
using CommunityToolkit.Mvvm.DependencyInjection;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Controls.Primitives;
|
||||
using Microsoft.UI.Xaml.Data;
|
||||
using Microsoft.UI.Xaml.Input;
|
||||
using Microsoft.UI.Xaml.Media;
|
||||
using Microsoft.UI.Xaml.Navigation;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices.WindowsRuntime;
|
||||
using Windows.Foundation;
|
||||
using Windows.Foundation.Collections;
|
||||
using Windows.System;
|
||||
|
||||
// To learn more about WinUI, the WinUI project structure,
|
||||
// and more about our project templates, see: http://aka.ms/winui-project-info.
|
||||
|
||||
namespace BetterLyrics.WinUI3.Controls
|
||||
{
|
||||
public sealed partial class MediaSettingsControl : UserControl
|
||||
{
|
||||
public MediaSettingsControlViewModel ViewModel => (MediaSettingsControlViewModel)DataContext;
|
||||
public MediaSettingsControl()
|
||||
{
|
||||
InitializeComponent();
|
||||
DataContext = Ioc.Default.GetRequiredService<MediaSettingsControlViewModel>();
|
||||
}
|
||||
|
||||
private void SettingsPageRemovePathButton_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
|
||||
{
|
||||
ViewModel.RemoveFolderAsync((LocalMediaFolder)(sender as HyperlinkButton)!.Tag);
|
||||
}
|
||||
|
||||
private async void LocalFolderHyperlinkButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (sender is HyperlinkButton button && button.Tag is string uriStr)
|
||||
{
|
||||
if (Uri.TryCreate(uriStr, UriKind.Absolute, out var uri))
|
||||
{
|
||||
await Launcher.LaunchUriAsync(uri);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,320 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<UserControl
|
||||
x:Class="BetterLyrics.WinUI3.Controls.PlaybackSettingsControl"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:controls="using:CommunityToolkit.WinUI.Controls"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:interactivity="using:Microsoft.Xaml.Interactivity"
|
||||
xmlns:local="using:BetterLyrics.WinUI3.Controls"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:models="using:BetterLyrics.WinUI3.Models"
|
||||
xmlns:ui="using:CommunityToolkit.WinUI"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<Grid ColumnSpacing="6">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid Grid.Column="0">
|
||||
<ScrollViewer Margin="0,72,0,0" Style="{StaticResource SettingsScrollViewerStyle}">
|
||||
<Grid Style="{StaticResource SettingsGridStyle}">
|
||||
<StackPanel Spacing="{StaticResource SettingsCardSpacing}">
|
||||
|
||||
<controls:SettingsCard x:Uid="SettingsPageMediaSourceProvidersConfig">
|
||||
<ToggleSwitch IsOn="{x:Bind ViewModel.SelectedMediaSourceProvider.IsEnabled, Mode=TwoWay}" />
|
||||
</controls:SettingsCard>
|
||||
|
||||
<controls:SettingsCard x:Uid="SettingsPageLastFMTrack" IsEnabled="{x:Bind ViewModel.IsLastFMAuthenticated, Mode=OneWay}">
|
||||
<ToggleSwitch IsOn="{x:Bind ViewModel.SelectedMediaSourceProvider.IsLastFMTrackEnabled, Mode=TwoWay}" />
|
||||
</controls:SettingsCard>
|
||||
|
||||
<!-- 时间轴相关配置 -->
|
||||
<controls:SettingsCard x:Uid="SettingsPageLyricsTimelineThreshold">
|
||||
<local:ExtendedSlider
|
||||
x:Uid="SettingsPageLyricsTimelineThresholdReset"
|
||||
Frequency="100"
|
||||
Maximum="1000"
|
||||
Minimum="0"
|
||||
ResetButtonVisibility="Collapsed"
|
||||
Unit="ms"
|
||||
Value="{x:Bind ViewModel.SelectedMediaSourceProvider.TimelineSyncThreshold, Mode=TwoWay}" />
|
||||
</controls:SettingsCard>
|
||||
<controls:SettingsExpander x:Uid="MainPagePositionOffsetSlider" IsExpanded="True">
|
||||
<local:ExtendedSlider
|
||||
x:Uid="SettingsPagePositionOffsetReset"
|
||||
Default="0"
|
||||
Frequency="100"
|
||||
Maximum="5000"
|
||||
Minimum="-5000"
|
||||
Unit="ms"
|
||||
Value="{x:Bind ViewModel.SelectedMediaSourceProvider.PositionOffset, Mode=TwoWay}" />
|
||||
<controls:SettingsExpander.Items>
|
||||
<controls:SettingsCard x:Uid="LyricsPagePositionOffsetHint">
|
||||
<ToggleSwitch IsOn="{x:Bind ViewModel.SelectedMediaSourceProvider.ResetPositionOffsetOnSongChanged, Mode=TwoWay}" />
|
||||
</controls:SettingsCard>
|
||||
</controls:SettingsExpander.Items>
|
||||
</controls:SettingsExpander>
|
||||
|
||||
<!-- 专辑封面源配置 -->
|
||||
<TextBlock x:Uid="SettingsPageAlbumArtSearchProvidersConfig" Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" />
|
||||
<ListView
|
||||
x:Name="AlbumArtSearchProvidersListView"
|
||||
AllowDrop="True"
|
||||
CanDragItems="True"
|
||||
CanReorderItems="True"
|
||||
DragItemsCompleted="AlbumArtSearchProvidersListView_DragItemsCompleted"
|
||||
ItemContainerStyle="{StaticResource ListViewStretchedItemContainerStyle}"
|
||||
ItemsSource="{x:Bind ViewModel.SelectedMediaSourceProvider.AlbumArtSearchProvidersInfo, Mode=OneWay}"
|
||||
SelectionMode="None">
|
||||
<ListView.OpacityTransition>
|
||||
<ScalarTransition />
|
||||
</ListView.OpacityTransition>
|
||||
<ListView.ItemTemplate>
|
||||
<DataTemplate x:DataType="models:AlbumArtSearchProviderInfo">
|
||||
<controls:SettingsCard Header="{Binding Provider, Converter={StaticResource AlbumArtSearchProviderToDisplayNameConverter}, Mode=OneWay}">
|
||||
<controls:SettingsCard.HeaderIcon>
|
||||
<FontIcon FontFamily="Segoe UI Symbol" Glyph="⠿" />
|
||||
</controls:SettingsCard.HeaderIcon>
|
||||
<ToggleSwitch IsOn="{Binding IsEnabled, Mode=TwoWay}" />
|
||||
</controls:SettingsCard>
|
||||
</DataTemplate>
|
||||
</ListView.ItemTemplate>
|
||||
</ListView>
|
||||
|
||||
<!-- 歌词源配置 -->
|
||||
<TextBlock x:Uid="SettingsPageLyricsSearchProvidersConfig" Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" />
|
||||
<ListView
|
||||
x:Name="LyricsSearchProvidersListView"
|
||||
AllowDrop="True"
|
||||
CanDragItems="True"
|
||||
CanReorderItems="True"
|
||||
DragItemsCompleted="LyricsSearchProvidersListView_DragItemsCompleted"
|
||||
ItemsSource="{x:Bind ViewModel.SelectedMediaSourceProvider.LyricsSearchProvidersInfo, Mode=OneWay}"
|
||||
SelectionMode="None">
|
||||
<ListView.OpacityTransition>
|
||||
<ScalarTransition />
|
||||
</ListView.OpacityTransition>
|
||||
<ListView.ItemContainerStyle>
|
||||
<Style TargetType="ListViewItem">
|
||||
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
|
||||
<Setter Property="Margin" Value="0" />
|
||||
<Setter Property="Padding" Value="0" />
|
||||
</Style>
|
||||
</ListView.ItemContainerStyle>
|
||||
<ListView.ItemTemplate>
|
||||
<DataTemplate x:DataType="models:LyricsSearchProviderInfo">
|
||||
<controls:SettingsCard Header="{Binding Provider, Converter={StaticResource LyricsSearchProviderToDisplayNameConverter}, Mode=OneWay}">
|
||||
<controls:SettingsCard.HeaderIcon>
|
||||
<FontIcon FontFamily="Segoe UI Symbol" Glyph="⠿" />
|
||||
</controls:SettingsCard.HeaderIcon>
|
||||
<ToggleSwitch IsOn="{Binding IsEnabled, Mode=TwoWay}" />
|
||||
</controls:SettingsCard>
|
||||
</DataTemplate>
|
||||
</ListView.ItemTemplate>
|
||||
</ListView>
|
||||
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</ScrollViewer>
|
||||
<ListView
|
||||
VerticalAlignment="Top"
|
||||
ItemsSource="{x:Bind ViewModel.AppSettings.MediaSourceProvidersInfo, Mode=OneWay}"
|
||||
ScrollViewer.HorizontalScrollBarVisibility="Auto"
|
||||
ScrollViewer.HorizontalScrollMode="Enabled"
|
||||
ScrollViewer.VerticalScrollBarVisibility="Disabled"
|
||||
ScrollViewer.VerticalScrollMode="Disabled"
|
||||
SelectedItem="{x:Bind ViewModel.SelectedMediaSourceProvider, Mode=TwoWay}">
|
||||
<ListView.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<ItemsStackPanel Orientation="Horizontal" />
|
||||
</ItemsPanelTemplate>
|
||||
</ListView.ItemsPanel>
|
||||
<ListView.ItemTemplate>
|
||||
<DataTemplate x:DataType="models:MediaSourceProviderInfo">
|
||||
<StackPanel Orientation="Horizontal" Spacing="6">
|
||||
<ImageIcon Height="16" Source="{Binding Provider, Converter={StaticResource MediaSourceProviderToLogoUriConverter}, Mode=OneWay}" />
|
||||
<TextBlock
|
||||
MaxWidth="200"
|
||||
Text="{Binding Provider, Converter={StaticResource MediaSourceProviderToDisplayedNameConverter}, Mode=OneWay}"
|
||||
TextWrapping="Wrap" />
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
</ListView.ItemTemplate>
|
||||
</ListView>
|
||||
<interactivity:Interaction.Behaviors>
|
||||
<interactivity:DataTriggerBehavior
|
||||
Binding="{x:Bind ViewModel.AppSettings.MediaSourceProvidersInfo.Count, Mode=OneWay}"
|
||||
ComparisonCondition="NotEqual"
|
||||
Value="0">
|
||||
<interactivity:ChangePropertyAction PropertyName="Visibility" Value="Visible" />
|
||||
</interactivity:DataTriggerBehavior>
|
||||
<interactivity:DataTriggerBehavior
|
||||
Binding="{x:Bind ViewModel.AppSettings.MediaSourceProvidersInfo.Count, Mode=OneWay}"
|
||||
ComparisonCondition="Equal"
|
||||
Value="0">
|
||||
<interactivity:ChangePropertyAction PropertyName="Visibility" Value="Collapsed" />
|
||||
</interactivity:DataTriggerBehavior>
|
||||
</interactivity:Interaction.Behaviors>
|
||||
</Grid>
|
||||
<StackPanel
|
||||
Grid.Column="0"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Spacing="12">
|
||||
<interactivity:Interaction.Behaviors>
|
||||
<interactivity:DataTriggerBehavior
|
||||
Binding="{x:Bind ViewModel.AppSettings.MediaSourceProvidersInfo.Count, Mode=OneWay}"
|
||||
ComparisonCondition="Equal"
|
||||
Value="0">
|
||||
<interactivity:ChangePropertyAction PropertyName="Visibility" Value="Visible" />
|
||||
</interactivity:DataTriggerBehavior>
|
||||
<interactivity:DataTriggerBehavior
|
||||
Binding="{x:Bind ViewModel.AppSettings.MediaSourceProvidersInfo.Count, Mode=OneWay}"
|
||||
ComparisonCondition="NotEqual"
|
||||
Value="0">
|
||||
<interactivity:ChangePropertyAction PropertyName="Visibility" Value="Collapsed" />
|
||||
</interactivity:DataTriggerBehavior>
|
||||
</interactivity:Interaction.Behaviors>
|
||||
<Image MaxWidth="200" Source="/Assets/Leaf.png" />
|
||||
<TextBlock
|
||||
x:Uid="SettingsPagePlaybackNotFound"
|
||||
HorizontalAlignment="Center"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}" />
|
||||
</StackPanel>
|
||||
<Grid Grid.Column="1">
|
||||
<ScrollViewer Style="{StaticResource SettingsScrollViewerStyle}">
|
||||
<Grid Style="{StaticResource SettingsGridStyle}">
|
||||
<StackPanel Spacing="{StaticResource SettingsCardSpacing}">
|
||||
<!-- Last.fm -->
|
||||
<TextBlock x:Uid="SettingsPageLastFM" Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" />
|
||||
<controls:SettingsExpander
|
||||
x:Uid="SettingsPageLastFMManager"
|
||||
HeaderIcon="{ui:BitmapIcon Source=ms-appx:///Assets/LastFM.png}"
|
||||
IsExpanded="{x:Bind ViewModel.IsLastFMAuthenticated, Mode=OneWay}">
|
||||
<StackPanel Orientation="Horizontal" Spacing="6">
|
||||
<Button
|
||||
x:Uid="SettingsPageLastFMAuth"
|
||||
Command="{x:Bind ViewModel.LastFMAuthCommand}"
|
||||
IsEnabled="{x:Bind ViewModel.IsLastFMAuthenticated, Mode=OneWay, Converter={StaticResource BoolNegationConverter}}" />
|
||||
<Button
|
||||
x:Uid="SettingsPageLastFMUnAuth"
|
||||
Command="{x:Bind ViewModel.LastFMUnAuthCommand}"
|
||||
IsEnabled="{x:Bind ViewModel.IsLastFMAuthenticated, Mode=OneWay}" />
|
||||
</StackPanel>
|
||||
<controls:SettingsExpander.Items>
|
||||
<controls:SettingsCard x:Uid="SettingsPageLastFMUsername" IsEnabled="{x:Bind ViewModel.IsLastFMAuthenticated, Mode=OneWay}">
|
||||
<HyperlinkButton Content="{x:Bind ViewModel.LastFMUser.Name, Mode=OneWay}" NavigateUri="{x:Bind ViewModel.LastFMUser.Url, Mode=OneWay}" />
|
||||
</controls:SettingsCard>
|
||||
<controls:SettingsCard x:Uid="SettingsPageLastFMPlaycount" IsEnabled="{x:Bind ViewModel.IsLastFMAuthenticated, Mode=OneWay}">
|
||||
<TextBlock Text="{x:Bind ViewModel.LastFMUser.Playcount, Mode=OneWay}" />
|
||||
</controls:SettingsCard>
|
||||
<controls:SettingsCard x:Uid="SettingsPageLastFMRegistered" IsEnabled="{x:Bind ViewModel.IsLastFMAuthenticated, Mode=OneWay}">
|
||||
<TextBlock Text="{x:Bind ViewModel.LastFMUser.Registered.ToLongDateString(), Mode=OneWay}" />
|
||||
</controls:SettingsCard>
|
||||
<controls:SettingsCard IsEnabled="{x:Bind ViewModel.IsLastFMAuthenticated, Mode=OneWay}">
|
||||
<Button x:Uid="SettingsPageLastFMRefresh" Command="{x:Bind ViewModel.LastFMRefreshCommand}" />
|
||||
</controls:SettingsCard>
|
||||
</controls:SettingsExpander.Items>
|
||||
</controls:SettingsExpander>
|
||||
<!-- Lyrics translation -->
|
||||
<TextBlock x:Uid="SettingsPageTranslation" Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" />
|
||||
<controls:SettingsExpander
|
||||
x:Uid="LyricsPageTranslationEnabled"
|
||||
HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
|
||||
Glyph=}"
|
||||
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}">
|
||||
<ComboBoxItem Content="العربية" Tag="ar" />
|
||||
<ComboBoxItem Content="Azərbaycan dili" Tag="az" />
|
||||
<ComboBoxItem Content="简体中文" Tag="zh-Hans" />
|
||||
<ComboBoxItem Content="繁體中文" Tag="zh-Hant" />
|
||||
<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="עברית" 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="Polski" Tag="pl" />
|
||||
<ComboBoxItem Content="Português" Tag="pt" />
|
||||
<ComboBoxItem Content="Русский" Tag="ru" />
|
||||
<ComboBoxItem Content="Slovenčina" Tag="sk" />
|
||||
<ComboBoxItem Content="Español" Tag="es" />
|
||||
<ComboBoxItem Content="Svenska" Tag="sv" />
|
||||
<ComboBoxItem Content="Türkçe" Tag="tr" />
|
||||
<ComboBoxItem Content="Українська" Tag="uk" />
|
||||
<ComboBoxItem Content="Tiếng Việt" Tag="vi" />
|
||||
</ComboBox>
|
||||
</controls:SettingsCard>
|
||||
<controls:SettingsCard x:Uid="SettingsPageTranslationConfig">
|
||||
<controls:SettingsCard.Description>
|
||||
<HyperlinkButton Margin="0,6,0,0" NavigateUri="https://github.com/LibreTranslate/LibreTranslate">
|
||||
<TextBlock
|
||||
x:Uid="SettingsPageTranslationInfoLink"
|
||||
FontSize="14"
|
||||
TextWrapping="Wrap" />
|
||||
</HyperlinkButton>
|
||||
</controls:SettingsCard.Description>
|
||||
<ToggleSwitch IsOn="{x:Bind ViewModel.AppSettings.TranslationSettings.IsLibreTranslateEnabled, Mode=TwoWay}" />
|
||||
</controls:SettingsCard>
|
||||
<controls:SettingsCard x:Uid="SettingsPageLibreTranslateServer" IsEnabled="{x:Bind ViewModel.AppSettings.TranslationSettings.IsLibreTranslateEnabled, Mode=OneWay}">
|
||||
<StackPanel Orientation="Horizontal" Spacing="12">
|
||||
<TextBox
|
||||
x:Name="LibreTranslateServerTextBox"
|
||||
IsEnabled="{x:Bind ViewModel.IsLibreTranslateServerTesting, Converter={StaticResource BoolNegationConverter}, Mode=OneWay}"
|
||||
PlaceholderText="http://localhost:5000"
|
||||
Text="{x:Bind ViewModel.AppSettings.TranslationSettings.LibreTranslateServer, Mode=TwoWay}" />
|
||||
<Button
|
||||
x:Uid="SettingsPageServerTestButton"
|
||||
Command="{x:Bind ViewModel.LibreTranslateServerTestCommand}"
|
||||
IsEnabled="{x:Bind ViewModel.IsLibreTranslateServerTesting, Converter={StaticResource BoolNegationConverter}, Mode=OneWay}" />
|
||||
</StackPanel>
|
||||
</controls:SettingsCard>
|
||||
<controls:SettingsCard x:Uid="LyricsPageTranslationOnly" IsEnabled="{x:Bind ViewModel.AppSettings.TranslationSettings.IsTranslationEnabled, Mode=OneWay}">
|
||||
<ToggleSwitch IsOn="{x:Bind ViewModel.AppSettings.TranslationSettings.ShowTranslationOnly, Mode=TwoWay}" />
|
||||
</controls:SettingsCard>
|
||||
</controls:SettingsExpander.Items>
|
||||
</controls:SettingsExpander>
|
||||
<controls:SettingsCard x:Uid="LyricsPageLyricsProviderPrefix">
|
||||
<TextBlock Foreground="{ThemeResource TextFillColorSecondaryBrush}" Text="{x:Bind ViewModel.LyricsSearchProvider, Mode=OneWay, Converter={StaticResource LyricsSearchProviderToDisplayNameConverter}}" />
|
||||
</controls:SettingsCard>
|
||||
<controls:SettingsCard x:Uid="LyricsPageTranslationProviderPrefix">
|
||||
<TextBlock Foreground="{ThemeResource TextFillColorSecondaryBrush}" Text="{x:Bind ViewModel.TranslationSearchProvider, Mode=OneWay, Converter={StaticResource TranslationSearchProviderToDisplayNameConverter}}" />
|
||||
</controls:SettingsCard>
|
||||
<!-- LX music server -->
|
||||
<TextBlock x:Uid="SettingsPageLXMusicServer" Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" />
|
||||
<controls:SettingsCard>
|
||||
<StackPanel Orientation="Horizontal" Spacing="6">
|
||||
<TextBox
|
||||
IsEnabled="{x:Bind ViewModel.IsLXMusicServerTesting, Converter={StaticResource BoolNegationConverter}, Mode=OneWay}"
|
||||
PlaceholderText="http://127.0.0.1:23330"
|
||||
Text="{x:Bind ViewModel.AppSettings.GeneralSettings.LXMusicServer, Mode=TwoWay}" />
|
||||
<Button
|
||||
x:Uid="SettingsPageServerTestButton"
|
||||
Command="{x:Bind ViewModel.LXMusicServerTestCommand}"
|
||||
IsEnabled="{x:Bind ViewModel.IsLXMusicServerTesting, Converter={StaticResource BoolNegationConverter}, Mode=OneWay}" />
|
||||
</StackPanel>
|
||||
</controls:SettingsCard>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</ScrollViewer>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
</UserControl>
|
||||
@@ -0,0 +1,45 @@
|
||||
using BetterLyrics.WinUI3.ViewModels;
|
||||
using CommunityToolkit.Mvvm.DependencyInjection;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Controls.Primitives;
|
||||
using Microsoft.UI.Xaml.Data;
|
||||
using Microsoft.UI.Xaml.Input;
|
||||
using Microsoft.UI.Xaml.Media;
|
||||
using Microsoft.UI.Xaml.Navigation;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices.WindowsRuntime;
|
||||
using Windows.Foundation;
|
||||
using Windows.Foundation.Collections;
|
||||
|
||||
// To learn more about WinUI, the WinUI project structure,
|
||||
// and more about our project templates, see: http://aka.ms/winui-project-info.
|
||||
|
||||
namespace BetterLyrics.WinUI3.Controls
|
||||
{
|
||||
public sealed partial class PlaybackSettingsControl : UserControl
|
||||
{
|
||||
public PlaybackSettingsControlViewModel ViewModel => (PlaybackSettingsControlViewModel)DataContext;
|
||||
|
||||
public PlaybackSettingsControl()
|
||||
{
|
||||
InitializeComponent();
|
||||
DataContext = Ioc.Default.GetRequiredService<PlaybackSettingsControlViewModel>();
|
||||
}
|
||||
|
||||
private void AlbumArtSearchProvidersListView_DragItemsCompleted(ListViewBase sender, DragItemsCompletedEventArgs args)
|
||||
{
|
||||
// <20><> AlbumArtSearchProvidersInfo <20><><EFBFBD><EFBFBD> CollectionChanged <20>¼<EFBFBD>
|
||||
ViewModel.SelectedMediaSourceProvider?.AlbumArtSearchProvidersInfo?.Refresh();
|
||||
}
|
||||
|
||||
private void LyricsSearchProvidersListView_DragItemsCompleted(ListViewBase sender, DragItemsCompletedEventArgs args)
|
||||
{
|
||||
// <20><> LyricsSearchProvidersInfo <20><><EFBFBD><EFBFBD> CollectionChanged <20>¼<EFBFBD>
|
||||
ViewModel.SelectedMediaSourceProvider?.LyricsSearchProvidersInfo?.Refresh();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<UserControl
|
||||
x:Class="BetterLyrics.WinUI3.Controls.ShortcutTextBox"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="using:BetterLyrics.WinUI3.Controls"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:ui="using:CommunityToolkit.WinUI"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<Grid>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBox
|
||||
x:Name="TextBox"
|
||||
IsReadOnly="True"
|
||||
KeyDown="TextBox_KeyDown"
|
||||
Loaded="TextBox_Loaded" />
|
||||
<Button
|
||||
Margin="3,0,0,0"
|
||||
HorizontalAlignment="Right"
|
||||
Click="ClearButton_Click"
|
||||
Content="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
|
||||
FontSize=12,
|
||||
Glyph=}"
|
||||
Style="{StaticResource GhostButtonStyle}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,95 @@
|
||||
using Microsoft.UI.Input;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Controls.Primitives;
|
||||
using Microsoft.UI.Xaml.Data;
|
||||
using Microsoft.UI.Xaml.Input;
|
||||
using Microsoft.UI.Xaml.Media;
|
||||
using Microsoft.UI.Xaml.Navigation;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices.WindowsRuntime;
|
||||
using Windows.Foundation;
|
||||
using Windows.Foundation.Collections;
|
||||
using Windows.UI.Core;
|
||||
|
||||
// To learn more about WinUI, the WinUI project structure,
|
||||
// and more about our project templates, see: http://aka.ms/winui-project-info.
|
||||
|
||||
namespace BetterLyrics.WinUI3.Controls
|
||||
{
|
||||
public sealed partial class ShortcutTextBox : UserControl
|
||||
{
|
||||
public ShortcutTextBox()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ShortcutProperty =
|
||||
DependencyProperty.Register(nameof(Shortcut), typeof(List<string>), typeof(ShortcutTextBox), new PropertyMetadata(default));
|
||||
|
||||
public List<string> Shortcut
|
||||
{
|
||||
get => (List<string>)GetValue(ShortcutProperty);
|
||||
set => SetValue(ShortcutProperty, value);
|
||||
}
|
||||
|
||||
private void TextBox_KeyDown(object sender, KeyRoutedEventArgs e)
|
||||
{
|
||||
List<string> shortcut = [];
|
||||
|
||||
bool ctrl = InputKeyboardSource.GetKeyStateForCurrentThread(Windows.System.VirtualKey.Control).HasFlag(CoreVirtualKeyStates.Down);
|
||||
bool shift = InputKeyboardSource.GetKeyStateForCurrentThread(Windows.System.VirtualKey.Shift).HasFlag(CoreVirtualKeyStates.Down);
|
||||
bool alt = InputKeyboardSource.GetKeyStateForCurrentThread(Windows.System.VirtualKey.Menu).HasFlag(CoreVirtualKeyStates.Down);
|
||||
bool win = InputKeyboardSource.GetKeyStateForCurrentThread(Windows.System.VirtualKey.LeftWindows).HasFlag(CoreVirtualKeyStates.Down) ||
|
||||
InputKeyboardSource.GetKeyStateForCurrentThread(Windows.System.VirtualKey.RightWindows).HasFlag(CoreVirtualKeyStates.Down);
|
||||
|
||||
if (ctrl)
|
||||
{
|
||||
shortcut.Add("Ctrl");
|
||||
}
|
||||
if (shift)
|
||||
{
|
||||
shortcut.Add("Shift");
|
||||
}
|
||||
if (alt)
|
||||
{
|
||||
shortcut.Add("Alt");
|
||||
}
|
||||
if (win)
|
||||
{
|
||||
shortcut.Add("Win");
|
||||
}
|
||||
|
||||
if (e.Key != Windows.System.VirtualKey.Control &&
|
||||
e.Key != Windows.System.VirtualKey.Shift &&
|
||||
e.Key != Windows.System.VirtualKey.Menu &&
|
||||
e.Key != Windows.System.VirtualKey.LeftWindows &&
|
||||
e.Key != Windows.System.VirtualKey.RightWindows)
|
||||
{
|
||||
shortcut.Add(e.Key.ToString());
|
||||
}
|
||||
Shortcut = shortcut;
|
||||
|
||||
UpdateTextBox();
|
||||
}
|
||||
|
||||
private void UpdateTextBox()
|
||||
{
|
||||
TextBox.Text = string.Join(" + ", Shortcut);
|
||||
}
|
||||
|
||||
private void TextBox_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
UpdateTextBox();
|
||||
}
|
||||
|
||||
private void ClearButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
Shortcut = [];
|
||||
UpdateTextBox();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,9 +14,9 @@
|
||||
x:Name="TrayIcon"
|
||||
x:FieldModifier="public"
|
||||
ContextMenuMode="SecondWindow"
|
||||
DoubleClickCommand="{x:Bind ViewModel.OpenLyricsWindowCommand}"
|
||||
DoubleClickCommand="{x:Bind ViewModel.OpenLyricsCommand}"
|
||||
IconSource="ms-appx:///Assets/Logo.ico"
|
||||
LeftClickCommand="{x:Bind ViewModel.OpenLyricsWindowCommand}"
|
||||
LeftClickCommand="{x:Bind ViewModel.OpenLyricsCommand}"
|
||||
NoLeftClickDelay="True"
|
||||
ToolTipText="{x:Bind ViewModel.ToolTipText, Mode=OneWay}">
|
||||
<tb:TaskbarIcon.ContextFlyout>
|
||||
@@ -24,15 +24,49 @@
|
||||
AreOpenCloseAnimationsEnabled="True"
|
||||
LightDismissOverlayMode="On"
|
||||
ShowMode="TransientWithDismissOnPointerMoveAway">
|
||||
<MenuFlyoutItem x:Uid="SystemTrayMusicGallery" Command="{x:Bind ViewModel.OpenMusicGalleryCommand}" />
|
||||
<MenuFlyoutItem x:Uid="SystemTraySettings" Command="{x:Bind ViewModel.OpenSettingsCommand}" />
|
||||
<MenuFlyoutItem x:Uid="SystemTrayResetWindowPosition" Command="{x:Bind ViewModel.ResetWindowPositionCommand}" />
|
||||
<MenuFlyoutItem x:Uid="SystemTrayRestart" Command="{x:Bind ViewModel.RestartAppCommand}" />
|
||||
<MenuFlyoutItem x:Uid="SystemTrayExit" Command="{x:Bind ViewModel.ExitAppCommand}" />
|
||||
<MenuFlyout.MenuFlyoutPresenterStyle>
|
||||
<Style BasedOn="{StaticResource DefaultMenuFlyoutPresenterStyle}" TargetType="MenuFlyoutPresenter">
|
||||
<Setter Property="MinWidth" Value="600" />
|
||||
</Style>
|
||||
</MenuFlyout.MenuFlyoutPresenterStyle>
|
||||
<MenuFlyoutItem
|
||||
x:Uid="SystemTrayLyrics"
|
||||
Command="{x:Bind ViewModel.OpenLyricsCommand}"
|
||||
Icon="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
|
||||
Glyph=}" />
|
||||
<MenuFlyoutItem
|
||||
x:Uid="SystemTrayMusicGallery"
|
||||
Command="{x:Bind ViewModel.OpenMusicGalleryCommand}"
|
||||
Icon="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
|
||||
Glyph=}" />
|
||||
<MenuFlyoutItem
|
||||
x:Uid="SystemTraySettings"
|
||||
Command="{x:Bind ViewModel.OpenSettingsCommand}"
|
||||
Icon="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
|
||||
Glyph=}" />
|
||||
<MenuFlyoutSeparator />
|
||||
<MenuFlyoutItem
|
||||
x:Uid="SystemTrayResetWindowPosition"
|
||||
Command="{x:Bind ViewModel.ResetWindowPositionCommand}"
|
||||
Icon="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
|
||||
Glyph=}" />
|
||||
<MenuFlyoutItem
|
||||
x:Uid="SystemTrayUnlock"
|
||||
Command="{x:Bind ViewModel.UnlockWindowCommand}"
|
||||
Icon="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
|
||||
Glyph=}"
|
||||
Visibility="{x:Bind ViewModel.IsLyricsWindowLocked, Mode=OneWay, Converter={StaticResource BoolToVisibilityConverter}}" />
|
||||
<MenuFlyoutSeparator />
|
||||
<MenuFlyoutItem
|
||||
x:Uid="SystemTrayRestart"
|
||||
Command="{x:Bind ViewModel.RestartAppCommand}"
|
||||
Icon="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
|
||||
Glyph=}" />
|
||||
<MenuFlyoutItem
|
||||
x:Uid="SystemTrayExit"
|
||||
Command="{x:Bind ViewModel.ExitAppCommand}"
|
||||
Icon="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
|
||||
Glyph=}" />
|
||||
</MenuFlyout>
|
||||
</tb:TaskbarIcon.ContextFlyout>
|
||||
</tb:TaskbarIcon>
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
using Microsoft.UI.Xaml.Data;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Converter
|
||||
{
|
||||
public class FPSToTimeSpanConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
if (value is int fps)
|
||||
{
|
||||
return TimeSpan.FromSeconds(1.0 / fps);
|
||||
}
|
||||
return TimeSpan.FromSeconds(1.0 / 60);
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
using Microsoft.UI.Xaml.Data;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Converter
|
||||
{
|
||||
public class ShortcutToStringConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
if (value is List<string> shortcut)
|
||||
{
|
||||
return string.Join(" + ", shortcut);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,9 +15,9 @@ namespace BetterLyrics.WinUI3.Converter
|
||||
return provider switch
|
||||
{
|
||||
TranslationSearchProvider.LrcLib => "LrcLib",
|
||||
TranslationSearchProvider.QQ => "QQ",
|
||||
TranslationSearchProvider.Netease => "Netease",
|
||||
TranslationSearchProvider.Kugou => "Kugou",
|
||||
TranslationSearchProvider.QQ => "QQ 音乐",
|
||||
TranslationSearchProvider.Netease => "网易云音乐",
|
||||
TranslationSearchProvider.Kugou => "酷狗音乐",
|
||||
TranslationSearchProvider.AmllTtmlDb => "amll-ttml-db",
|
||||
TranslationSearchProvider.LocalLrcFile => App.ResourceLoader!.GetString("LyricsSearchProviderLocalLrcFile"),
|
||||
TranslationSearchProvider.LocalMusicFile => App.ResourceLoader!.GetString("LyricsSearchProviderLocalMusicFile"),
|
||||
|
||||
@@ -2,10 +2,11 @@
|
||||
|
||||
namespace BetterLyrics.WinUI3.Enums
|
||||
{
|
||||
public enum AutoStartWindowType
|
||||
public enum LyricsWindowMode
|
||||
{
|
||||
StandardMode,
|
||||
DockMode,
|
||||
DesktopMode,
|
||||
PictureInPictureMode,
|
||||
}
|
||||
}
|
||||
@@ -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 SettingsStoreType
|
||||
{
|
||||
Container,
|
||||
JSON
|
||||
}
|
||||
}
|
||||
19
BetterLyrics.WinUI3/BetterLyrics.WinUI3/Enums/ShortcutID.cs
Normal file
19
BetterLyrics.WinUI3/BetterLyrics.WinUI3/Enums/ShortcutID.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Enums
|
||||
{
|
||||
public enum ShortcutID
|
||||
{
|
||||
DesktopLock,
|
||||
DesktopToggle,
|
||||
DockToggle,
|
||||
PictureInPictureToggle,
|
||||
PlayOrPauseSong,
|
||||
NextSong,
|
||||
PreviousSong,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Collections.Specialized;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Extensions
|
||||
{
|
||||
// https://stackoverflow.com/a/32013610/11048731
|
||||
public class FullyObservableCollection<T> : ObservableCollection<T>
|
||||
where T : INotifyPropertyChanged
|
||||
{
|
||||
/// <summary>
|
||||
/// Occurs when a property is changed within an item.
|
||||
/// </summary>
|
||||
public event EventHandler<ItemPropertyChangedEventArgs> ItemPropertyChanged;
|
||||
|
||||
public FullyObservableCollection() : base()
|
||||
{ }
|
||||
|
||||
public FullyObservableCollection(List<T> list) : base(list)
|
||||
{
|
||||
ObserveAll();
|
||||
}
|
||||
|
||||
public FullyObservableCollection(IEnumerable<T> enumerable) : base(enumerable)
|
||||
{
|
||||
ObserveAll();
|
||||
}
|
||||
|
||||
protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
if (e.Action == NotifyCollectionChangedAction.Remove ||
|
||||
e.Action == NotifyCollectionChangedAction.Replace)
|
||||
{
|
||||
foreach (T item in e.OldItems)
|
||||
item.PropertyChanged -= ChildPropertyChanged;
|
||||
}
|
||||
|
||||
if (e.Action == NotifyCollectionChangedAction.Add ||
|
||||
e.Action == NotifyCollectionChangedAction.Replace)
|
||||
{
|
||||
foreach (T item in e.NewItems)
|
||||
item.PropertyChanged += ChildPropertyChanged;
|
||||
}
|
||||
|
||||
base.OnCollectionChanged(e);
|
||||
}
|
||||
|
||||
protected void OnItemPropertyChanged(ItemPropertyChangedEventArgs e)
|
||||
{
|
||||
ItemPropertyChanged?.Invoke(this, e);
|
||||
}
|
||||
|
||||
protected void OnItemPropertyChanged(int index, PropertyChangedEventArgs e)
|
||||
{
|
||||
OnItemPropertyChanged(new ItemPropertyChangedEventArgs(index, e));
|
||||
}
|
||||
|
||||
protected override void ClearItems()
|
||||
{
|
||||
foreach (T item in Items)
|
||||
item.PropertyChanged -= ChildPropertyChanged;
|
||||
|
||||
base.ClearItems();
|
||||
}
|
||||
|
||||
private void ObserveAll()
|
||||
{
|
||||
foreach (T item in Items)
|
||||
item.PropertyChanged += ChildPropertyChanged;
|
||||
}
|
||||
|
||||
private void ChildPropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
T typedSender = (T)sender;
|
||||
int i = Items.IndexOf(typedSender);
|
||||
|
||||
if (i < 0)
|
||||
throw new ArgumentException("Received property notification from item not in collection");
|
||||
|
||||
OnItemPropertyChanged(i, e);
|
||||
}
|
||||
|
||||
public void Refresh()
|
||||
{
|
||||
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Provides data for the <see cref="FullyObservableCollection{T}.ItemPropertyChanged"/> event.
|
||||
/// </summary>
|
||||
public class ItemPropertyChangedEventArgs : PropertyChangedEventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the index in the collection for which the property change has occurred.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// Index in parent collection.
|
||||
/// </value>
|
||||
public int CollectionIndex { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ItemPropertyChangedEventArgs"/> class.
|
||||
/// </summary>
|
||||
/// <param name="index">The index in the collection of changed item.</param>
|
||||
/// <param name="name">The name of the property that changed.</param>
|
||||
public ItemPropertyChangedEventArgs(int index, string name) : base(name)
|
||||
{
|
||||
CollectionIndex = index;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ItemPropertyChangedEventArgs"/> class.
|
||||
/// </summary>
|
||||
/// <param name="index">The index.</param>
|
||||
/// <param name="args">The <see cref="PropertyChangedEventArgs"/> instance containing the event data.</param>
|
||||
public ItemPropertyChangedEventArgs(int index, PropertyChangedEventArgs args) : this(index, args.PropertyName)
|
||||
{ }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Helper
|
||||
{
|
||||
public class BackgroundTaskRunner
|
||||
{
|
||||
private CancellationTokenSource? _cts;
|
||||
|
||||
public void Run(Func<CancellationToken, Task> taskFactory)
|
||||
{
|
||||
_cts?.Cancel();
|
||||
_cts?.Dispose();
|
||||
|
||||
_cts = new CancellationTokenSource();
|
||||
var token = _cts.Token;
|
||||
|
||||
_ = Task.Run(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
await taskFactory(token);
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
}, token);
|
||||
}
|
||||
}
|
||||
}
|
||||
306
BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/CanvasHelper.cs
Normal file
306
BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/CanvasHelper.cs
Normal file
@@ -0,0 +1,306 @@
|
||||
using BetterLyrics.WinUI3.Enums;
|
||||
using BetterLyrics.WinUI3.Models;
|
||||
using Microsoft.Graphics.Canvas;
|
||||
using Microsoft.Graphics.Canvas.Brushes;
|
||||
using Microsoft.Graphics.Canvas.Effects;
|
||||
using Microsoft.Graphics.Canvas.Text;
|
||||
using Microsoft.Graphics.Canvas.UI.Xaml;
|
||||
using Microsoft.UI;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.Foundation;
|
||||
using Windows.Graphics.Effects;
|
||||
using Windows.UI;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Helper
|
||||
{
|
||||
public class CanvasHelper
|
||||
{
|
||||
public static CanvasLinearGradientBrush CreateHorizontalFillBrush(
|
||||
ICanvasAnimatedControl control,
|
||||
List<(double position, double opacity)> stops,
|
||||
double startX,
|
||||
double width
|
||||
)
|
||||
{
|
||||
return new CanvasLinearGradientBrush(control, stops.Select(stops => new CanvasGradientStop
|
||||
{
|
||||
Position = (float)stops.position,
|
||||
Color = Color.FromArgb((byte)(stops.opacity * 255), 128, 128, 128),
|
||||
}).ToArray())
|
||||
{
|
||||
StartPoint = new Vector2((float)startX, 0),
|
||||
EndPoint = new Vector2((float)(startX + width), 0),
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 背景层
|
||||
/// </summary>
|
||||
/// <param name="lyricsLayerOpacity">_lyricsOpacityTransition.Value</param>
|
||||
public static OpacityEffect CreateBackgroundEffect(LyricsLine lyricsLine, CanvasCommandList backgroundFontEffect, double lyricsLayerOpacity)
|
||||
{
|
||||
if (lyricsLine.BlurAmountTransition.Value == 0)
|
||||
{
|
||||
return new OpacityEffect
|
||||
{
|
||||
Source = backgroundFontEffect,
|
||||
Opacity = (float)(lyricsLine.OpacityTransition.Value * lyricsLayerOpacity),
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
return new OpacityEffect
|
||||
{
|
||||
Source = new GaussianBlurEffect
|
||||
{
|
||||
Source = backgroundFontEffect,
|
||||
BlurAmount = (float)lyricsLine.BlurAmountTransition.Value,
|
||||
BorderMode = EffectBorderMode.Soft,
|
||||
Optimization = EffectOptimization.Speed,
|
||||
},
|
||||
Opacity = (float)(lyricsLine.OpacityTransition.Value * lyricsLayerOpacity),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public static CanvasCommandList CreateFontEffect(LyricsLine lyricsLine, ICanvasAnimatedControl control, Color strokeColor, int strokeWidth, Color fontColor)
|
||||
{
|
||||
CanvasCommandList list = new(control);
|
||||
using var ds = list.CreateDrawingSession();
|
||||
if (strokeWidth > 0)
|
||||
{
|
||||
ds.DrawGeometry(lyricsLine.TextGeometry, lyricsLine.Position, strokeColor, strokeWidth); // 描边
|
||||
}
|
||||
ds.FillGeometry(lyricsLine.TextGeometry, lyricsLine.Position, fontColor); // 填充
|
||||
return list;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建辉光效果层
|
||||
/// 仅需在布局重构 (Relayout) 时调用
|
||||
/// </summary>
|
||||
/// <param name="lineRenderingType">_lyricsGlowEffectScope</param>
|
||||
/// <param name="glowEffectAmount">_lyricsGlowEffectAmount</param>
|
||||
public static GaussianBlurEffect CreateForegroundBlurEffect(CanvasCommandList foregroundFontEffect, IGraphicsEffectSource mask, double glowEffectAmount)
|
||||
{
|
||||
return new GaussianBlurEffect
|
||||
{
|
||||
Source = new AlphaMaskEffect
|
||||
{
|
||||
Source = foregroundFontEffect,
|
||||
AlphaMask = mask,
|
||||
},
|
||||
BlurAmount = (float)glowEffectAmount,
|
||||
Optimization = EffectOptimization.Speed,
|
||||
};
|
||||
}
|
||||
|
||||
public static CanvasCommandList CreateCharMask(ICanvasAnimatedControl control, LyricsLine lyricsLine, int charStartIndex, int charLength, double charProgress)
|
||||
{
|
||||
var mask = new CanvasCommandList(control);
|
||||
using var ds = mask.CreateDrawingSession();
|
||||
|
||||
if (lyricsLine.CanvasTextLayout == null)
|
||||
{
|
||||
return mask;
|
||||
}
|
||||
|
||||
var highlightRegion = lyricsLine.CanvasTextLayout.GetCharacterRegions(charStartIndex, charLength).FirstOrDefault();
|
||||
|
||||
double highlightTotalWidth = (double)highlightRegion.LayoutBounds.Width;
|
||||
// Draw the highlight for the current character
|
||||
double highlightWidth = highlightTotalWidth * charProgress;
|
||||
|
||||
double fadingWidth = (double)highlightRegion.LayoutBounds.Height / 2;
|
||||
|
||||
// Rects
|
||||
var highlightRect = new Rect(
|
||||
highlightRegion.LayoutBounds.X,
|
||||
highlightRegion.LayoutBounds.Y + lyricsLine.Position.Y,
|
||||
highlightWidth,
|
||||
highlightRegion.LayoutBounds.Height
|
||||
);
|
||||
|
||||
var fadeInRect = new Rect(
|
||||
highlightRect.Right - fadingWidth,
|
||||
highlightRegion.LayoutBounds.Y + lyricsLine.Position.Y,
|
||||
fadingWidth,
|
||||
highlightRegion.LayoutBounds.Height
|
||||
);
|
||||
var fadeOutRect = new Rect(
|
||||
highlightRect.Right,
|
||||
highlightRegion.LayoutBounds.Y + lyricsLine.Position.Y,
|
||||
fadingWidth,
|
||||
highlightRegion.LayoutBounds.Height
|
||||
);
|
||||
|
||||
// Brushes
|
||||
using var fadeInBrush = CanvasHelper.CreateHorizontalFillBrush(
|
||||
control,
|
||||
[(0f, 0f), (1f, 1f)],
|
||||
(double)highlightRect.Right - fadingWidth,
|
||||
fadingWidth
|
||||
);
|
||||
using var fadeOutBrush = CanvasHelper.CreateHorizontalFillBrush(
|
||||
control,
|
||||
[(0f, 1f), (1f, 0f)],
|
||||
(double)highlightRect.Right,
|
||||
fadingWidth
|
||||
);
|
||||
|
||||
ds.FillRectangle(fadeInRect, fadeInBrush);
|
||||
ds.FillRectangle(fadeOutRect, fadeOutBrush);
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
public static CanvasCommandList CreateLineStartToCharMask(ICanvasAnimatedControl control, LyricsLine lyricsLine, int charStartIndex, int charLength, double charProgress, bool fade)
|
||||
{
|
||||
var mask = new CanvasCommandList(control);
|
||||
|
||||
if (lyricsLine.CanvasTextLayout == null)
|
||||
{
|
||||
return mask;
|
||||
}
|
||||
|
||||
using var ds = mask.CreateDrawingSession();
|
||||
|
||||
var regions = lyricsLine.CanvasTextLayout.GetCharacterRegions(0, charStartIndex);
|
||||
var highlightRegion = lyricsLine.CanvasTextLayout
|
||||
.GetCharacterRegions(charStartIndex, charLength)
|
||||
.FirstOrDefault();
|
||||
if (regions.Length > 0)
|
||||
{
|
||||
// Draw the mask for the current line
|
||||
for (int j = 0; j < regions.Length; j++)
|
||||
{
|
||||
var region = regions[j];
|
||||
var rect = new Rect(
|
||||
region.LayoutBounds.X,
|
||||
region.LayoutBounds.Y + lyricsLine.Position.Y,
|
||||
region.LayoutBounds.Width,
|
||||
region.LayoutBounds.Height
|
||||
);
|
||||
ds.FillRectangle(rect, Color.FromArgb(255, 128, 128, 128));
|
||||
}
|
||||
}
|
||||
|
||||
double highlightTotalWidth = (double)highlightRegion.LayoutBounds.Width;
|
||||
// Draw the highlight for the current character
|
||||
double highlightWidth = highlightTotalWidth * charProgress;
|
||||
|
||||
double fadingWidth = (double)highlightRegion.LayoutBounds.Height / 2;
|
||||
|
||||
// Rects
|
||||
var highlightRect = new Rect(
|
||||
highlightRegion.LayoutBounds.X,
|
||||
highlightRegion.LayoutBounds.Y + lyricsLine.Position.Y,
|
||||
highlightWidth,
|
||||
highlightRegion.LayoutBounds.Height
|
||||
);
|
||||
|
||||
var fadeInRect = new Rect(
|
||||
highlightRect.Right - fadingWidth,
|
||||
highlightRegion.LayoutBounds.Y + lyricsLine.Position.Y,
|
||||
fadingWidth,
|
||||
highlightRegion.LayoutBounds.Height
|
||||
);
|
||||
|
||||
ds.FillRectangle(highlightRect, Color.FromArgb(255, 128, 128, 128));
|
||||
|
||||
if (fade)
|
||||
{
|
||||
var fadeOutRect = new Rect(
|
||||
highlightRect.Right,
|
||||
highlightRegion.LayoutBounds.Y + lyricsLine.Position.Y,
|
||||
fadingWidth,
|
||||
highlightRegion.LayoutBounds.Height
|
||||
);
|
||||
using var fadeOutBrush = CreateHorizontalFillBrush(
|
||||
control,
|
||||
[(0f, 1f), (1f, 0f)],
|
||||
(double)highlightRect.Right,
|
||||
fadingWidth
|
||||
);
|
||||
ds.FillRectangle(fadeOutRect, fadeOutBrush);
|
||||
}
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
public static CanvasCommandList CreateLineMask(ICanvasAnimatedControl control, LyricsLine lyricsLine)
|
||||
{
|
||||
var mask = new CanvasCommandList(control);
|
||||
using var ds = mask.CreateDrawingSession();
|
||||
|
||||
if (lyricsLine.CanvasTextLayout == null)
|
||||
{
|
||||
return mask;
|
||||
}
|
||||
|
||||
var regions = lyricsLine.CanvasTextLayout.GetCharacterRegions(0, lyricsLine.OriginalText.Length);
|
||||
if (regions.Length > 0)
|
||||
{
|
||||
for (int j = 0; j < regions.Length; j++)
|
||||
{
|
||||
var region = regions[j];
|
||||
var rect = new Rect(
|
||||
region.LayoutBounds.X,
|
||||
region.LayoutBounds.Y + lyricsLine.Position.Y,
|
||||
region.LayoutBounds.Width,
|
||||
region.LayoutBounds.Height
|
||||
);
|
||||
ds.FillRectangle(rect, Colors.White);
|
||||
}
|
||||
}
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建高亮效果层
|
||||
/// </summary>
|
||||
/// <param name="control"></param>
|
||||
/// <param name="lineRenderingType"></param>
|
||||
public static AlphaMaskEffect CreateForegroundHighlightEffect(CanvasCommandList foregroundFontEffect, IGraphicsEffectSource mask)
|
||||
{
|
||||
return new AlphaMaskEffect
|
||||
{
|
||||
Source = foregroundFontEffect,
|
||||
AlphaMask = mask,
|
||||
};
|
||||
}
|
||||
|
||||
public static ShadowEffect CreateForegroundShadowEffect(CanvasCommandList foregroundFontEffect, IGraphicsEffectSource mask, Color shadowColor, double shadowAmount)
|
||||
{
|
||||
return new ShadowEffect
|
||||
{
|
||||
Source = new AlphaMaskEffect
|
||||
{
|
||||
Source = foregroundFontEffect,
|
||||
AlphaMask = mask,
|
||||
},
|
||||
ShadowColor = shadowColor,
|
||||
BlurAmount = (float)shadowAmount,
|
||||
Optimization = EffectOptimization.Speed,
|
||||
};
|
||||
}
|
||||
|
||||
public static IGraphicsEffectSource GetAlphaMask(ICanvasAnimatedControl control, IGraphicsEffectSource charMask, IGraphicsEffectSource lineStartToCharMask, IGraphicsEffectSource lineMask, LineRenderingType lineRenderingType)
|
||||
{
|
||||
var result = lineRenderingType switch
|
||||
{
|
||||
LineRenderingType.CurrentChar => charMask,
|
||||
LineRenderingType.LineStartToCurrentChar => lineStartToCharMask,
|
||||
LineRenderingType.CurrentLine => lineMask,
|
||||
_ => new CanvasCommandList(control),
|
||||
};
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -52,7 +52,7 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
return Color.FromArgb(255, fg.R, fg.G, fg.B);
|
||||
}
|
||||
|
||||
public static Color GetInterpolatedColor(float progress, Color startColor, Color targetColor)
|
||||
public static Color GetInterpolatedColor(double progress, Color startColor, Color targetColor)
|
||||
{
|
||||
byte Lerp(byte a, byte b) => (byte)(a + (progress * (b - a)));
|
||||
return Color.FromArgb(
|
||||
|
||||
@@ -67,21 +67,8 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
);
|
||||
}
|
||||
|
||||
// <20>Ӵ洢<D3B4><E6B4A2><EFBFBD><EFBFBD>ȡĿ<C8A1><C4BF><EFBFBD><EFBFBD><EFBFBD>ߺ<EFBFBD>λ<EFBFBD><CEBB>
|
||||
int targetWidth = _settingsService.DesktopWindowWidth;
|
||||
int targetHeight = _settingsService.DesktopWindowHeight;
|
||||
int targetX = _settingsService.DesktopWindowLeft;
|
||||
int targetY = _settingsService.DesktopWindowTop;
|
||||
|
||||
// <20><><EFBFBD>ô<EFBFBD><C3B4>ڴ<EFBFBD>С<EFBFBD><D0A1>λ<EFBFBD><CEBB>
|
||||
window.AppWindow.MoveAndResize(
|
||||
new Windows.Graphics.RectInt32(
|
||||
targetX,
|
||||
targetY,
|
||||
targetWidth,
|
||||
targetHeight
|
||||
)
|
||||
);
|
||||
window.AppWindow.MoveAndResize(_settingsService.AppSettings.DesktopModeSettings.WindowBounds.ToRectInt32());
|
||||
|
||||
// <20><><EFBFBD><EFBFBD>ԭTopMost״̬
|
||||
if (!_originalTopmostStates.ContainsKey(hwnd))
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Helper
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Helper
|
||||
{
|
||||
public class DirectoryHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// 递归查找指定文件夹下所有文件(包括子文件夹)。
|
||||
/// </summary>
|
||||
/// <param name="folderPath">要查找的文件夹路径</param>
|
||||
/// <returns>所有文件的完整路径列表</returns>
|
||||
public static List<string> GetAllFiles(string folderPath, string searchPattern = "*")
|
||||
{
|
||||
var files = new List<string>();
|
||||
if (!Directory.Exists(folderPath))
|
||||
return files;
|
||||
|
||||
try
|
||||
{
|
||||
files.AddRange(Directory.GetFiles(folderPath, searchPattern));
|
||||
foreach (var dir in Directory.GetDirectories(folderPath))
|
||||
{
|
||||
files.AddRange(GetAllFiles(dir, searchPattern));
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// 可根据需要处理异常,如权限不足等
|
||||
}
|
||||
return files;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -24,6 +24,11 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
private static readonly Dictionary<IntPtr, RECT> _originalPositions = [];
|
||||
private static readonly Dictionary<IntPtr, WindowStyle> _originalWindowStyle = [];
|
||||
|
||||
public static bool IsEnabled(IntPtr hwnd)
|
||||
{
|
||||
return _registered.Contains(hwnd);
|
||||
}
|
||||
|
||||
public static void Disable(Window window)
|
||||
{
|
||||
IntPtr hwnd = WindowNative.GetWindowHandle(window);
|
||||
@@ -78,7 +83,7 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
|
||||
RegisterAppBar(hwnd, monitorDeviceName, appBarHeight, dockPlacement);
|
||||
|
||||
var monitorInfo = MonitorHelper.GetMonitorInfoExFromDeviceName(_settingsService.DockMonitorDeviceName);
|
||||
var monitorInfo = MonitorHelper.GetMonitorInfoExFromDeviceName(_settingsService.AppSettings.DockModeSettings.DockMonitorDeviceName);
|
||||
|
||||
int screenWidth = monitorInfo.rcMonitor.Width;
|
||||
int screenHeight = monitorInfo.rcMonitor.Bottom - monitorInfo.rcMonitor.Top;
|
||||
|
||||
@@ -10,67 +10,67 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
{
|
||||
public class EasingHelper
|
||||
{
|
||||
public static float EaseInOutSine(float t)
|
||||
public static double EaseInOutSine(double t)
|
||||
{
|
||||
return -(MathF.Cos(MathF.PI * t) - 1f) / 2f;
|
||||
return -(Math.Cos(Math.PI * t) - 1f) / 2f;
|
||||
}
|
||||
public static float EaseInOutQuad(float t)
|
||||
public static double EaseInOutQuad(double t)
|
||||
{
|
||||
return t < 0.5f ? 2 * t * t : -1 + (4 - 2 * t) * t;
|
||||
}
|
||||
|
||||
public static float EaseInOutCubic(float t)
|
||||
public static double EaseInOutCubic(double t)
|
||||
{
|
||||
return t < 0.5f ? 4 * t * t * t : 1 - MathF.Pow(-2 * t + 2, 3) / 2;
|
||||
return t < 0.5f ? 4 * t * t * t : 1 - Math.Pow(-2 * t + 2, 3) / 2;
|
||||
}
|
||||
public static float EaseInOutQuart(float t)
|
||||
public static double EaseInOutQuart(double t)
|
||||
{
|
||||
return t < 0.5f ? 8 * t * t * t * t : 1 - MathF.Pow(-2 * t + 2, 4) / 2;
|
||||
return t < 0.5f ? 8 * t * t * t * t : 1 - Math.Pow(-2 * t + 2, 4) / 2;
|
||||
}
|
||||
|
||||
public static float EaseInOutQuint(float t)
|
||||
public static double EaseInOutQuint(double t)
|
||||
{
|
||||
return t < 0.5f ? 16 * t * t * t * t * t : 1 - MathF.Pow(-2 * t + 2, 5) / 2;
|
||||
return t < 0.5f ? 16 * t * t * t * t * t : 1 - Math.Pow(-2 * t + 2, 5) / 2;
|
||||
}
|
||||
|
||||
public static float EaseInOutExpo(float t)
|
||||
public static double EaseInOutExpo(double t)
|
||||
{
|
||||
return t == 0
|
||||
? 0
|
||||
: t == 1
|
||||
? 1
|
||||
: t < 0.5 ? MathF.Pow(2, 20 * t - 10) / 2
|
||||
: (2 - MathF.Pow(2, -20 * t + 10)) / 2;
|
||||
: t < 0.5 ? Math.Pow(2, 20 * t - 10) / 2
|
||||
: (2 - Math.Pow(2, -20 * t + 10)) / 2;
|
||||
}
|
||||
|
||||
public static float EaseInOutCirc(float t)
|
||||
public static double EaseInOutCirc(double t)
|
||||
{
|
||||
return t < 0.5f
|
||||
? (1 - MathF.Sqrt(1 - MathF.Pow(2 * t, 2))) / 2
|
||||
: (MathF.Sqrt(1 - MathF.Pow(-2 * t + 2, 2)) + 1) / 2;
|
||||
? (1 - Math.Sqrt(1 - Math.Pow(2 * t, 2))) / 2
|
||||
: (Math.Sqrt(1 - Math.Pow(-2 * t + 2, 2)) + 1) / 2;
|
||||
}
|
||||
|
||||
public static float EaseInOutBack(float t)
|
||||
public static double EaseInOutBack(double t)
|
||||
{
|
||||
float c1 = 1.70158f;
|
||||
float c2 = c1 * 1.525f;
|
||||
double c1 = 1.70158f;
|
||||
double c2 = c1 * 1.525f;
|
||||
|
||||
return t < 0.5
|
||||
? (MathF.Pow(2 * t, 2) * ((c2 + 1) * 2 * t - c2)) / 2
|
||||
: (MathF.Pow(2 * t - 2, 2) * ((c2 + 1) * (t * 2 - 2) + c2) + 2) / 2;
|
||||
? (Math.Pow(2 * t, 2) * ((c2 + 1) * 2 * t - c2)) / 2
|
||||
: (Math.Pow(2 * t - 2, 2) * ((c2 + 1) * (t * 2 - 2) + c2) + 2) / 2;
|
||||
}
|
||||
|
||||
public static float EaseInOutElastic(float t)
|
||||
public static double EaseInOutElastic(double t)
|
||||
{
|
||||
if (t == 0 || t == 1) return t;
|
||||
float p = 0.3f;
|
||||
float s = p / 4;
|
||||
double p = 0.3f;
|
||||
double s = p / 4;
|
||||
return t < 0.5f
|
||||
? -(MathF.Pow(2, 20 * t - 10) * MathF.Sin((20 * t - 11.125f) * (2 * MathF.PI) / p)) / 2
|
||||
: (MathF.Pow(2, -20 * t + 10) * MathF.Sin((20 * t - 11.125f) * (2 * MathF.PI) / p)) / 2 + 1;
|
||||
? -(Math.Pow(2, 20 * t - 10) * Math.Sin((20 * t - 11.125f) * (2 * Math.PI) / p)) / 2
|
||||
: (Math.Pow(2, -20 * t + 10) * Math.Sin((20 * t - 11.125f) * (2 * Math.PI) / p)) / 2 + 1;
|
||||
}
|
||||
|
||||
private static float EaseOutBounce(float t)
|
||||
private static double EaseOutBounce(double t)
|
||||
{
|
||||
if (t < 4 / 11f)
|
||||
{
|
||||
@@ -90,7 +90,7 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
}
|
||||
}
|
||||
|
||||
public static float EaseInOutBounce(float t)
|
||||
public static double EaseInOutBounce(double t)
|
||||
{
|
||||
if (t < 0.5f)
|
||||
{
|
||||
@@ -102,17 +102,17 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
}
|
||||
}
|
||||
|
||||
public static float SmoothStep(float t)
|
||||
public static double SmoothStep(double t)
|
||||
{
|
||||
return t * t * (3f - 2f * t);
|
||||
}
|
||||
|
||||
public static float CubicBezier(float t, float p0, float p1, float p2, float p3)
|
||||
public static double CubicBezier(double t, double p0, double p1, double p2, double p3)
|
||||
{
|
||||
float u = 1 - t;
|
||||
double u = 1 - t;
|
||||
return u * u * u * p0 + 3 * u * u * t * p1 + 3 * u * t * t * p2 + t * t * t * p3;
|
||||
}
|
||||
|
||||
public static float Linear(float t) => t;
|
||||
public static double Linear(double t) => t;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
|
||||
using BetterLyrics.WinUI3.Enums;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Ude;
|
||||
|
||||
@@ -69,7 +71,7 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
|
||||
public static bool IsSwitchableNormalizedMatch(string fileName, string q1, string q2)
|
||||
{
|
||||
var normFileName = StringHelper.Normalize(fileName.Normalize());
|
||||
var normFileName = StringHelper.Normalize(fileName);
|
||||
var normQ1 = StringHelper.Normalize(q1);
|
||||
var normQ2 = StringHelper.Normalize(q2);
|
||||
|
||||
@@ -78,5 +80,13 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
|| normFileName == normQ2 + normQ1;
|
||||
}
|
||||
|
||||
public static readonly string[] MusicExtensions = {
|
||||
".mp3", ".aac", ".m4a", ".ogg", ".opus", ".wma", ".amr",
|
||||
".flac", ".alac", ".ape", ".wv", ".tak",
|
||||
".wav", ".aiff", ".aif", ".pcm", ".cda", ".dsf", ".dff", ".au", ".snd",
|
||||
".mid", ".midi", ".mod", ".xm", ".it", ".s3m"
|
||||
};
|
||||
|
||||
public static string MusicSearchPattern => string.Join("|", MusicExtensions.Select(x => $"*{x}"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,10 +11,6 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
{
|
||||
public static class FontHelper
|
||||
{
|
||||
private static readonly ISettingsService _settingsService = Ioc.Default.GetRequiredService<ISettingsService>();
|
||||
|
||||
public static string[] SystemFontFamilies => CanvasTextFormat.GetSystemFontFamilies();
|
||||
|
||||
public static string GetUserPreferredFontFamily() => SystemFontFamilies.ElementAtOrDefault(_settingsService.SelectedFontFamilyIndex) ?? "Segoe UI";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Microsoft.UI.Xaml;
|
||||
using BetterLyrics.WinUI3.Enums;
|
||||
using Microsoft.UI.Xaml;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
@@ -13,24 +14,70 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
public class GlobalHotKeyHelper
|
||||
{
|
||||
private static Dictionary<int, Action> _hotKeyActions = [];
|
||||
private static int _nextId = 0;
|
||||
|
||||
public static void RegisterHotKey(Window window, User32.HotKeyModifiers modifiers, uint key, Action action)
|
||||
/// <summary>
|
||||
/// Register a global hotkey for a specific window type
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Target window type</typeparam>
|
||||
/// <param name="id"></param>
|
||||
/// <param name="keys"></param>
|
||||
/// <param name="action"></param>
|
||||
public static void RegisterHotKey<T>(ShortcutID id, List<string> keys, Action action)
|
||||
{
|
||||
if (keys.Count == 0) return;
|
||||
|
||||
var window = WindowHelper.GetWindowByWindowType<T>();
|
||||
if (window == null) return;
|
||||
|
||||
HWND hwnd = WindowNative.GetWindowHandle(window);
|
||||
int id = _nextId++;
|
||||
User32.RegisterHotKey(hwnd, id, modifiers, key);
|
||||
_hotKeyActions[id] = action;
|
||||
User32.HotKeyModifiers modifiers = User32.HotKeyModifiers.MOD_NONE;
|
||||
VirtualKey key = VirtualKey.None;
|
||||
foreach (var item in keys)
|
||||
{
|
||||
if (item == "Ctrl")
|
||||
{
|
||||
modifiers |= User32.HotKeyModifiers.MOD_CONTROL;
|
||||
}
|
||||
else if (item == "Shift")
|
||||
{
|
||||
modifiers |= User32.HotKeyModifiers.MOD_SHIFT;
|
||||
}
|
||||
else if (item == "Alt")
|
||||
{
|
||||
modifiers |= User32.HotKeyModifiers.MOD_ALT;
|
||||
}
|
||||
else if (item == "Win")
|
||||
{
|
||||
modifiers |= User32.HotKeyModifiers.MOD_WIN;
|
||||
}
|
||||
else
|
||||
{
|
||||
key = (VirtualKey)Enum.Parse(typeof(VirtualKey), item, true);
|
||||
}
|
||||
}
|
||||
User32.RegisterHotKey(hwnd, (int)id, modifiers, (uint)key);
|
||||
_hotKeyActions[(int)id] = action;
|
||||
}
|
||||
|
||||
public static void UnregisterAllHotKeys(Window window)
|
||||
public static void UnregisterHotKey<T>(ShortcutID id)
|
||||
{
|
||||
var window = WindowHelper.GetWindowByWindowType<T>();
|
||||
if (window == null) return;
|
||||
|
||||
HWND hwnd = WindowNative.GetWindowHandle(window);
|
||||
foreach (var id in _hotKeyActions.Keys.ToList())
|
||||
{
|
||||
User32.UnregisterHotKey(hwnd, id);
|
||||
_hotKeyActions.Remove(id);
|
||||
}
|
||||
User32.UnregisterHotKey(hwnd, (int)id);
|
||||
_hotKeyActions.Remove((int)id);
|
||||
}
|
||||
|
||||
public static void UpdateHotKey<T>(ShortcutID id, List<string> keys, Action action)
|
||||
{
|
||||
UnregisterHotKey<T>(id);
|
||||
RegisterHotKey<T>(id, keys, action);
|
||||
}
|
||||
|
||||
public static bool TryInvokeAction(ShortcutID id)
|
||||
{
|
||||
return TryInvokeAction((int)id);
|
||||
}
|
||||
|
||||
public static bool TryInvokeAction(int id)
|
||||
|
||||
@@ -138,7 +138,7 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
return buffer;
|
||||
}
|
||||
|
||||
public static float GetAverageLuminance(CanvasBitmap bitmap)
|
||||
public static double GetAverageLuminance(CanvasBitmap bitmap)
|
||||
{
|
||||
var pixels = bitmap.GetPixelBytes();
|
||||
double sum = 0;
|
||||
@@ -152,7 +152,7 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
double y = 0.299 * r + 0.587 * g + 0.114 * b;
|
||||
sum += y / 255.0;
|
||||
}
|
||||
return (float)(sum / (pixels.Length / 4));
|
||||
return (double)(sum / (pixels.Length / 4));
|
||||
}
|
||||
|
||||
public static byte[] MakeSquareWithThemeColor(byte[] imageBytes)
|
||||
@@ -185,7 +185,7 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
{
|
||||
using (Image image = Image.Load(imageBytes))
|
||||
{
|
||||
var factor = Math.Max((float)size / image.Width, (float)size / image.Height);
|
||||
var factor = Math.Max((double)size / image.Width, (double)size / image.Height);
|
||||
|
||||
int width = (int)(image.Width * factor);
|
||||
int height = (int)(image.Height * factor);
|
||||
|
||||
@@ -5,6 +5,7 @@ using Lyricify.Lyrics.Helpers.General;
|
||||
using NTextCat;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using TinyPinyin;
|
||||
@@ -16,7 +17,6 @@ namespace BetterLyrics.WinUI3.Services
|
||||
{
|
||||
private static readonly RankedLanguageIdentifierFactory _factory = new();
|
||||
private static readonly RankedLanguageIdentifier _identifier;
|
||||
private static readonly ISettingsService _settingsService = Ioc.Default.GetRequiredService<ISettingsService>();
|
||||
|
||||
public static List<Models.LanguageInfo> SupportedTargetLanguages =>
|
||||
[
|
||||
@@ -69,7 +69,7 @@ namespace BetterLyrics.WinUI3.Services
|
||||
"simple" => "en",
|
||||
"zh_classical" => "zh-Hant",
|
||||
"zh_yue" => "zh-Hant",
|
||||
"zh" => "zh-Hans",
|
||||
"zh" => text == ChineseConverter.ConvertToSimplifiedChinese(text) ? "zh-Hans" : "zh-Hant",
|
||||
_ => code
|
||||
};
|
||||
return code;
|
||||
@@ -99,11 +99,6 @@ namespace BetterLyrics.WinUI3.Services
|
||||
};
|
||||
}
|
||||
|
||||
public static string GetUserTargetLanguageCode()
|
||||
{
|
||||
return SupportedTargetLanguages[_settingsService.SelectedTargetLanguageIndex].Code;
|
||||
}
|
||||
|
||||
public static int GetDefaultTargetLanguageIndex()
|
||||
{
|
||||
int found = SupportedTargetLanguages.FindIndex(x => ApplicationLanguages.Languages.FirstOrDefault()?.Contains(x.Code) == true);
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
using Nito.AsyncEx;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Helper
|
||||
{
|
||||
public class LatestOnlyTaskRunner
|
||||
{
|
||||
private readonly AsyncLock _mutex = new();
|
||||
private CancellationTokenSource _cts;
|
||||
|
||||
public async Task RunAsync(Func<CancellationToken, Task> action)
|
||||
{
|
||||
CancellationTokenSource oldCts;
|
||||
|
||||
// 使用 AsyncLock 保证线程安全
|
||||
using (await _mutex.LockAsync())
|
||||
{
|
||||
// 取消旧的
|
||||
oldCts = _cts;
|
||||
_cts = new CancellationTokenSource();
|
||||
}
|
||||
|
||||
oldCts?.Cancel();
|
||||
oldCts?.Dispose();
|
||||
|
||||
CancellationToken token = _cts.Token;
|
||||
|
||||
try
|
||||
{
|
||||
await action(token);
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
// 可以选择忽略取消异常
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@
|
||||
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;
|
||||
@@ -47,10 +48,57 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
break;
|
||||
}
|
||||
}
|
||||
FillChineseLyricsData();
|
||||
_lyricsDataArr.Add(new LyricsData()); // 为机翻预留
|
||||
return _lyricsDataArr;
|
||||
}
|
||||
|
||||
private void FillChineseLyricsData()
|
||||
{
|
||||
var simplifiedChinese = _lyricsDataArr.Where(x => x.LanguageCode == "zh-Hans").FirstOrDefault();
|
||||
var traditionalChinese = _lyricsDataArr.Where(x => x.LanguageCode == "zh-Hant").FirstOrDefault();
|
||||
if (simplifiedChinese != null && traditionalChinese == null)
|
||||
{
|
||||
// 如果没有繁体中文歌词,则将简体中文歌词转换为繁体中文
|
||||
_lyricsDataArr.Add(new LyricsData
|
||||
{
|
||||
LyricsLines = simplifiedChinese.LyricsLines.Select(line => new LyricsLine
|
||||
{
|
||||
StartMs = line.StartMs,
|
||||
EndMs = line.EndMs,
|
||||
OriginalText = ChineseConverter.ConvertToTraditionalChinese(line.OriginalText),
|
||||
LyricsChars = line.LyricsChars.Select(c => new LyricsChar
|
||||
{
|
||||
StartMs = c.StartMs,
|
||||
EndMs = c.EndMs,
|
||||
Text = ChineseConverter.ConvertToTraditionalChinese(c.Text),
|
||||
StartIndex = c.StartIndex
|
||||
}).ToList()
|
||||
}).ToList()
|
||||
});
|
||||
}
|
||||
else if (traditionalChinese != null && simplifiedChinese == null)
|
||||
{
|
||||
// 如果没有简体中文歌词,则将繁体中文歌词转换为简体中文
|
||||
_lyricsDataArr.Add(new LyricsData
|
||||
{
|
||||
LyricsLines = traditionalChinese.LyricsLines.Select(line => new LyricsLine
|
||||
{
|
||||
StartMs = line.StartMs,
|
||||
EndMs = line.EndMs,
|
||||
OriginalText = ChineseConverter.ConvertToSimplifiedChinese(line.OriginalText),
|
||||
LyricsChars = line.LyricsChars.Select(c => new LyricsChar
|
||||
{
|
||||
StartMs = c.StartMs,
|
||||
EndMs = c.EndMs,
|
||||
Text = ChineseConverter.ConvertToSimplifiedChinese(c.Text),
|
||||
StartIndex = c.StartIndex
|
||||
}).ToList()
|
||||
}).ToList()
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void ParseLrc(string raw)
|
||||
{
|
||||
var lines = raw.Split(["\r\n", "\n"], StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
@@ -1,17 +1,9 @@
|
||||
// 2025/6/23 by Zhe Fang
|
||||
|
||||
using Windows.ApplicationModel;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Helper
|
||||
{
|
||||
using BetterLyrics.WinUI3.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.ApplicationModel;
|
||||
using Windows.Storage;
|
||||
using Windows.Storage.FileProperties;
|
||||
|
||||
public static class MetadataHelper
|
||||
{
|
||||
public static string AppVersion
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.Security.Credentials;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Helper
|
||||
{
|
||||
public static class PasswordVaultHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// 保存敏感数据到 PasswordVault
|
||||
/// </summary>
|
||||
/// <param name="resource">资源标识,比如 "MyApp"</param>
|
||||
/// <param name="key">键名,比如 "SessionKey"</param>
|
||||
/// <param name="value">要保存的值</param>
|
||||
public static void Save(string resource, string key, string value)
|
||||
{
|
||||
var vault = new PasswordVault();
|
||||
|
||||
// 删除旧值(避免重复存储)
|
||||
try
|
||||
{
|
||||
var oldCredential = vault.Retrieve(resource, key);
|
||||
if (oldCredential != null)
|
||||
{
|
||||
vault.Remove(oldCredential);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// 没有旧值就忽略
|
||||
}
|
||||
|
||||
vault.Add(new PasswordCredential(resource, key, value));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从 PasswordVault 获取敏感数据
|
||||
/// </summary>
|
||||
/// <param name="resource">资源标识</param>
|
||||
/// <param name="key">键名</param>
|
||||
/// <returns>存储的值,若不存在则返回 null</returns>
|
||||
public static string? Get(string resource, string key)
|
||||
{
|
||||
var vault = new PasswordVault();
|
||||
try
|
||||
{
|
||||
var credential = vault.Retrieve(resource, key);
|
||||
credential.RetrievePassword();
|
||||
return credential.Password;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除指定的敏感数据
|
||||
/// </summary>
|
||||
public static void Delete(string resource, string key)
|
||||
{
|
||||
var vault = new PasswordVault();
|
||||
try
|
||||
{
|
||||
var credential = vault.Retrieve(resource, key);
|
||||
vault.Remove(credential);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// 不存在就忽略
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,11 +11,13 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
{
|
||||
public class PathHelper
|
||||
{
|
||||
private static string LocalFolder => ApplicationData.Current.LocalFolder.Path;
|
||||
public static string LocalFolder => ApplicationData.Current.LocalFolder.Path;
|
||||
public static string CacheFolder => ApplicationData.Current.LocalCacheFolder.Path;
|
||||
public static string AssetsFolder => Path.Combine(Package.Current.InstalledPath, "Assets");
|
||||
|
||||
//public static string LanguageProfilePath => Path.Combine(AssetsFolder, "Core14.profile.xml");
|
||||
public static string SettingsDirectory => Path.Combine(LocalFolder, "settings");
|
||||
public static string SettingsFilePath => Path.Combine(SettingsDirectory, "settings.json");
|
||||
|
||||
public static string LanguageProfilePath => Path.Combine(AssetsFolder, "Wiki82.profile.xml");
|
||||
public static string LogoPath => Path.Combine(AssetsFolder, "Logo.ico");
|
||||
public static string AIMPLogoPath => Path.Combine(AssetsFolder, "AIMP.png");
|
||||
@@ -58,6 +60,8 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
|
||||
public static void EnsureDirectories()
|
||||
{
|
||||
Directory.CreateDirectory(SettingsDirectory);
|
||||
|
||||
Directory.CreateDirectory(LogDirectory);
|
||||
|
||||
Directory.CreateDirectory(LrcLibLyricsCacheDirectory);
|
||||
|
||||
22
BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/RectHelper.cs
Normal file
22
BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/RectHelper.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.Graphics;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Helper
|
||||
{
|
||||
public static class RectHelper
|
||||
{
|
||||
public static RectInt32 ToRectInt32(this Windows.Foundation.Rect rect)
|
||||
{
|
||||
return new RectInt32(
|
||||
(int)rect.X,
|
||||
(int)rect.Y,
|
||||
(int)rect.Width,
|
||||
(int)rect.Height
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -38,7 +38,7 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
{
|
||||
if (_endpointVolume != null)
|
||||
{
|
||||
float level = _endpointVolume.GetMasterVolumeLevelScalar();
|
||||
double level = _endpointVolume.GetMasterVolumeLevelScalar();
|
||||
_masterVolume = (int)(level * 100);
|
||||
}
|
||||
|
||||
|
||||
@@ -10,21 +10,22 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
where T : struct
|
||||
{
|
||||
private T _currentValue;
|
||||
private float _durationSeconds;
|
||||
private double _durationSeconds;
|
||||
private EasingType? _easingType;
|
||||
private Func<T, T, float, T> _interpolator;
|
||||
private Func<T, T, double, T> _interpolator;
|
||||
private bool _isTransitioning;
|
||||
private float _progress;
|
||||
private double _progress;
|
||||
private T _startValue;
|
||||
private T _targetValue;
|
||||
|
||||
public float DurationSeconds => _durationSeconds;
|
||||
public double DurationSeconds => _durationSeconds;
|
||||
|
||||
public bool IsTransitioning => _isTransitioning;
|
||||
public T Value => _currentValue;
|
||||
public T TargetValue => _targetValue;
|
||||
public EasingType? EasingType => _easingType;
|
||||
|
||||
public ValueTransition(T initialValue, float durationSeconds, Func<T, T, float, T>? interpolator = null, EasingType? easingType = null)
|
||||
public ValueTransition(T initialValue, double durationSeconds, Func<T, T, double, T>? interpolator = null, EasingType? easingType = null)
|
||||
{
|
||||
_currentValue = initialValue;
|
||||
_startValue = initialValue;
|
||||
@@ -45,12 +46,12 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
}
|
||||
else
|
||||
{
|
||||
_easingType = EasingType.Linear;
|
||||
_easingType = Enums.EasingType.EaseInOutQuad;
|
||||
_interpolator = GetInterpolatorByEasingType(_easingType.Value);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetDuration(float seconds)
|
||||
public void SetDuration(double seconds)
|
||||
{
|
||||
if (seconds <= 0)
|
||||
throw new ArgumentOutOfRangeException(nameof(seconds), "Duration must be positive.");
|
||||
@@ -102,7 +103,7 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
{
|
||||
if (!_isTransitioning) return;
|
||||
|
||||
_progress += (float)(elapsedTime / TimeSpan.FromSeconds(_durationSeconds));
|
||||
_progress += (double)(elapsedTime / TimeSpan.FromSeconds(_durationSeconds));
|
||||
if (_progress >= 1f)
|
||||
{
|
||||
_progress = 1f;
|
||||
@@ -115,51 +116,51 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
}
|
||||
}
|
||||
|
||||
private Func<T, T, float, T> GetInterpolatorByEasingType(EasingType type)
|
||||
private Func<T, T, double, T> GetInterpolatorByEasingType(EasingType type)
|
||||
{
|
||||
if (typeof(T) == typeof(float))
|
||||
if (typeof(T) == typeof(double))
|
||||
{
|
||||
return (start, end, progress) =>
|
||||
{
|
||||
float s = (float)(object)start;
|
||||
float e = (float)(object)end;
|
||||
float t = progress;
|
||||
double s = (double)(object)start;
|
||||
double e = (double)(object)end;
|
||||
double t = progress;
|
||||
switch (type)
|
||||
{
|
||||
case EasingType.EaseInOutSine:
|
||||
case Enums.EasingType.EaseInOutSine:
|
||||
t = EasingHelper.EaseInOutSine(t);
|
||||
break;
|
||||
case EasingType.EaseInOutQuad:
|
||||
case Enums.EasingType.EaseInOutQuad:
|
||||
t = EasingHelper.EaseInOutQuad(t);
|
||||
break;
|
||||
case EasingType.EaseInOutCubic:
|
||||
case Enums.EasingType.EaseInOutCubic:
|
||||
t = EasingHelper.EaseInOutCubic(t);
|
||||
break;
|
||||
case EasingType.EaseInOutQuart:
|
||||
case Enums.EasingType.EaseInOutQuart:
|
||||
t = EasingHelper.EaseInOutQuart(t);
|
||||
break;
|
||||
case EasingType.EaseInOutQuint:
|
||||
case Enums.EasingType.EaseInOutQuint:
|
||||
t = EasingHelper.EaseInOutQuint(t);
|
||||
break;
|
||||
case EasingType.EaseInOutExpo:
|
||||
case Enums.EasingType.EaseInOutExpo:
|
||||
t = EasingHelper.EaseInOutExpo(t);
|
||||
break;
|
||||
case EasingType.EaseInOutCirc:
|
||||
case Enums.EasingType.EaseInOutCirc:
|
||||
t = EasingHelper.EaseInOutCirc(t);
|
||||
break;
|
||||
case EasingType.EaseInOutBack:
|
||||
case Enums.EasingType.EaseInOutBack:
|
||||
t = EasingHelper.EaseInOutBack(t);
|
||||
break;
|
||||
case EasingType.EaseInOutElastic:
|
||||
case Enums.EasingType.EaseInOutElastic:
|
||||
t = EasingHelper.EaseInOutElastic(t);
|
||||
break;
|
||||
case EasingType.EaseInOutBounce:
|
||||
case Enums.EasingType.EaseInOutBounce:
|
||||
t = EasingHelper.EaseInOutBounce(t);
|
||||
break;
|
||||
case EasingType.SmoothStep:
|
||||
case Enums.EasingType.SmoothStep:
|
||||
t = EasingHelper.SmoothStep(t);
|
||||
break;
|
||||
case EasingType.Linear:
|
||||
case Enums.EasingType.Linear:
|
||||
t = EasingHelper.Linear(t);
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -18,6 +18,10 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
|
||||
public static void CloseWindow<T>()
|
||||
{
|
||||
if (typeof(T) == typeof(LyricsWindow))
|
||||
{
|
||||
EnsureDockModeReleased();
|
||||
}
|
||||
var window = _activeWindows.Find(w => w is T);
|
||||
if (window is Window w)
|
||||
{
|
||||
@@ -60,10 +64,31 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
throw new ArgumentException("Unsupported window type", nameof(T));
|
||||
}
|
||||
TrackWindow(window);
|
||||
var castedWindow = (Window)window;
|
||||
castedWindow.Restore();
|
||||
castedWindow.Activate();
|
||||
|
||||
if (typeof(T) == typeof(LyricsWindow))
|
||||
{
|
||||
var lyricsWindow = (LyricsWindow)window;
|
||||
lyricsWindow.ViewModel.InitShortcuts();
|
||||
lyricsWindow.AutoSelectLyricsMode();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var castedWindow = (Window)window;
|
||||
if (typeof(T) == typeof(LyricsWindow))
|
||||
{
|
||||
var lyricsWindow = (LyricsWindow)window;
|
||||
lyricsWindow.Show();
|
||||
}
|
||||
else
|
||||
{
|
||||
castedWindow.Restore();
|
||||
castedWindow.Activate();
|
||||
}
|
||||
}
|
||||
var castedWindow = (Window)window;
|
||||
castedWindow.Restore();
|
||||
castedWindow.Activate();
|
||||
}
|
||||
|
||||
public static void RestartApp(string args = "")
|
||||
@@ -88,12 +113,17 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
|
||||
public static void ExitApp()
|
||||
{
|
||||
LyricsWindow? lyricsWindow = WindowHelper.GetWindowByWindowType<LyricsWindow>();
|
||||
EnsureDockModeReleased();
|
||||
Environment.Exit(0);
|
||||
}
|
||||
|
||||
private static void EnsureDockModeReleased()
|
||||
{
|
||||
LyricsWindow? lyricsWindow = GetWindowByWindowType<LyricsWindow>();
|
||||
if (lyricsWindow != null)
|
||||
{
|
||||
DockModeHelper.Disable(lyricsWindow);
|
||||
}
|
||||
Environment.Exit(0);
|
||||
}
|
||||
|
||||
private static void TrackWindow(object window)
|
||||
|
||||
@@ -5,13 +5,11 @@ using CommunityToolkit.Mvvm.ComponentModel;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Models
|
||||
{
|
||||
public partial class AlbumArtSearchProviderInfo : ObservableObject
|
||||
public partial class AlbumArtSearchProviderInfo : ObservableRecipient
|
||||
{
|
||||
[ObservableProperty]
|
||||
public partial bool IsEnabled { get; set; }
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsEnabled { get; set; }
|
||||
|
||||
[ObservableProperty]
|
||||
public partial AlbumArtSearchProvider Provider { get; set; }
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial AlbumArtSearchProvider Provider { get; set; }
|
||||
|
||||
public AlbumArtSearchProviderInfo() { }
|
||||
|
||||
|
||||
39
BetterLyrics.WinUI3/BetterLyrics.WinUI3/Models/LiveStates.cs
Normal file
39
BetterLyrics.WinUI3/BetterLyrics.WinUI3/Models/LiveStates.cs
Normal file
@@ -0,0 +1,39 @@
|
||||
using BetterLyrics.WinUI3.Enums;
|
||||
using BetterLyrics.WinUI3.Models.Settings;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Models
|
||||
{
|
||||
public partial class LiveStates : ObservableRecipient
|
||||
{
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial LyricsWindowMode CurrentLyricsWindowMode { get; set; }
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial LyricsDisplayType CurrentLyricsDisplayType { get; set; }
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial LyricsStyleSettings CurrentLyricsStyleSettings { get; set; }
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial LyricsEffectSettings CurrentLyricsEffectSettings { get; set; }
|
||||
|
||||
public LiveStates(AppSettings appSettings)
|
||||
{
|
||||
CurrentLyricsWindowMode = LyricsWindowMode.StandardMode;
|
||||
CurrentLyricsDisplayType = appSettings.StandardModeSettings.LyricsDisplayType;
|
||||
CurrentLyricsStyleSettings = appSettings.StandardLyricsStyleSettings;
|
||||
CurrentLyricsEffectSettings = appSettings.StandardLyricsEffectSettings;
|
||||
}
|
||||
|
||||
public void ToggleLyricsWindowMode(LyricsWindowMode mode)
|
||||
{
|
||||
if (CurrentLyricsWindowMode == mode)
|
||||
{
|
||||
CurrentLyricsWindowMode = LyricsWindowMode.StandardMode;
|
||||
}
|
||||
else
|
||||
{
|
||||
CurrentLyricsWindowMode = mode;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,20 +4,17 @@ using CommunityToolkit.Mvvm.ComponentModel;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Models
|
||||
{
|
||||
public partial class LocalMediaFolder : ObservableObject
|
||||
public partial class LocalMediaFolder : ObservableRecipient
|
||||
{
|
||||
[ObservableProperty]
|
||||
public partial bool IsEnabled { get; set; }
|
||||
|
||||
[ObservableProperty]
|
||||
public partial string Path { get; set; }
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsEnabled { get; set; } = true;
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsRealTimeWatchEnabled { get; set; } = false;
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial string Path { get; set; }
|
||||
|
||||
public LocalMediaFolder() { }
|
||||
|
||||
public LocalMediaFolder(string path, bool isEnabled)
|
||||
public LocalMediaFolder(string path)
|
||||
{
|
||||
Path = path;
|
||||
IsEnabled = isEnabled;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,23 +36,7 @@ namespace BetterLyrics.WinUI3.Models
|
||||
|
||||
if (transLine != null)
|
||||
{
|
||||
if (translationData.LanguageCode?.StartsWith("zh") == true)
|
||||
{
|
||||
string tmp = "";
|
||||
if (LanguageHelper.GetUserTargetLanguageCode() == "zh-Hant")
|
||||
{
|
||||
tmp = ChineseConverter.ConvertToTraditionalChinese(transLine.OriginalText);
|
||||
}
|
||||
else if (LanguageHelper.GetUserTargetLanguageCode() == "zh-Hans")
|
||||
{
|
||||
tmp = ChineseConverter.ConvertToSimplifiedChinese(transLine.OriginalText);
|
||||
}
|
||||
line.DisplayedText = $"{line.OriginalText}{separator}{tmp}";
|
||||
}
|
||||
else
|
||||
{
|
||||
line.DisplayedText = $"{line.OriginalText}{separator}{transLine.OriginalText}";
|
||||
}
|
||||
line.DisplayedText = $"{line.OriginalText}{separator}{transLine.OriginalText}";
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -3,42 +3,54 @@
|
||||
using BetterLyrics.WinUI3.Enums;
|
||||
using BetterLyrics.WinUI3.Helper;
|
||||
using Microsoft.Graphics.Canvas;
|
||||
using Microsoft.Graphics.Canvas.Effects;
|
||||
using Microsoft.Graphics.Canvas.Geometry;
|
||||
using Microsoft.Graphics.Canvas.Text;
|
||||
using Microsoft.Graphics.Canvas.UI.Xaml;
|
||||
using Microsoft.UI;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Shapes;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using Windows.Foundation;
|
||||
using Windows.Graphics.Effects;
|
||||
using Windows.UI;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Models
|
||||
{
|
||||
public class LyricsLine
|
||||
{
|
||||
private const float _animationDuration = 0.3f;
|
||||
public ValueTransition<float> AngleTransition { get; set; } = new(
|
||||
initialValue: 0f,
|
||||
private const double _animationDuration = 0.3;
|
||||
public ValueTransition<double> AngleTransition { get; set; } = new(
|
||||
initialValue: 0,
|
||||
durationSeconds: _animationDuration,
|
||||
easingType: EasingType.EaseInOutSine
|
||||
easingType: EasingType.EaseInOutQuad
|
||||
);
|
||||
public ValueTransition<float> BlurAmountTransition { get; set; } = new(
|
||||
initialValue: 0f,
|
||||
public ValueTransition<double> BlurAmountTransition { get; set; } = new(
|
||||
initialValue: 0,
|
||||
durationSeconds: _animationDuration,
|
||||
easingType: EasingType.EaseInOutSine
|
||||
easingType: EasingType.EaseInOutQuad
|
||||
);
|
||||
public ValueTransition<float> HighlightOpacityTransition { get; set; } = new(
|
||||
initialValue: 0f,
|
||||
public ValueTransition<double> HighlightOpacityTransition { get; set; } = new(
|
||||
initialValue: 0,
|
||||
durationSeconds: _animationDuration,
|
||||
easingType: EasingType.EaseInOutSine
|
||||
easingType: EasingType.EaseInOutQuad
|
||||
);
|
||||
public ValueTransition<float> OpacityTransition { get; set; } = new(
|
||||
initialValue: 0f,
|
||||
public ValueTransition<double> OpacityTransition { get; set; } = new(
|
||||
initialValue: 0,
|
||||
durationSeconds: _animationDuration,
|
||||
easingType: EasingType.EaseInOutSine
|
||||
easingType: EasingType.EaseInOutQuad
|
||||
);
|
||||
public ValueTransition<float> ScaleTransition { get; set; } = new(
|
||||
initialValue: 0f,
|
||||
public ValueTransition<double> ScaleTransition { get; set; } = new(
|
||||
initialValue: 0.75,
|
||||
durationSeconds: _animationDuration,
|
||||
easingType: EasingType.EaseInOutSine
|
||||
easingType: EasingType.EaseInOutQuad
|
||||
);
|
||||
public ValueTransition<double> YOffsetTransition { get; set; } = new(
|
||||
initialValue: 0,
|
||||
durationSeconds: 0.5,
|
||||
easingType: EasingType.EaseInOutQuad
|
||||
);
|
||||
|
||||
public CanvasTextLayout? CanvasTextLayout { get; private set; }
|
||||
@@ -57,30 +69,32 @@ namespace BetterLyrics.WinUI3.Models
|
||||
|
||||
public CanvasGeometry? TextGeometry { get; private set; }
|
||||
|
||||
public CanvasCommandList? BackgroundFontEffect { get; private set; }
|
||||
public CanvasCommandList? ForegroundFontEffect { get; private set; }
|
||||
|
||||
public void UpdateCenterPosition(float maxWidth, TextAlignmentType type)
|
||||
public void UpdateCenterPosition(double maxWidth, TextAlignmentType type)
|
||||
{
|
||||
if (CanvasTextLayout == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
float centerY = Position.Y + (float)CanvasTextLayout.LayoutBounds.Height;
|
||||
double centerY = Position.Y + (double)CanvasTextLayout.LayoutBounds.Height;
|
||||
CenterPosition = type switch
|
||||
{
|
||||
TextAlignmentType.Left => new Vector2(Position.X, centerY),
|
||||
TextAlignmentType.Center => new Vector2(Position.X + maxWidth / 2, centerY),
|
||||
TextAlignmentType.Right => new Vector2(Position.X + maxWidth, centerY),
|
||||
TextAlignmentType.Left => new Vector2(Position.X, (float)centerY),
|
||||
TextAlignmentType.Center => new Vector2((float)(Position.X + maxWidth / 2.0), (float)centerY),
|
||||
TextAlignmentType.Right => new Vector2((float)(Position.X + maxWidth), (float)centerY),
|
||||
_ => throw new System.ArgumentOutOfRangeException(nameof(type), type, null),
|
||||
};
|
||||
}
|
||||
|
||||
public void UpdateTextLayout(ICanvasAnimatedControl control, CanvasTextFormat textFormat, float maxWidth, float maxHeight, TextAlignmentType type)
|
||||
public void DisposeTextLayout()
|
||||
{
|
||||
CanvasTextLayout?.Dispose();
|
||||
CanvasTextLayout = null;
|
||||
CanvasTextLayout = new CanvasTextLayout(control, DisplayedText, textFormat, maxWidth, maxHeight);
|
||||
}
|
||||
|
||||
public void RecreateTextLayout(ICanvasAnimatedControl control, CanvasTextFormat textFormat, double maxWidth, double maxHeight, TextAlignmentType type)
|
||||
{
|
||||
DisposeTextLayout();
|
||||
CanvasTextLayout = new CanvasTextLayout(control, DisplayedText, textFormat, (float)maxWidth, (float)maxHeight);
|
||||
CanvasTextLayout.HorizontalAlignment = type.ToCanvasHorizontalAlignment();
|
||||
}
|
||||
|
||||
@@ -90,7 +104,7 @@ namespace BetterLyrics.WinUI3.Models
|
||||
TextGeometry = null;
|
||||
}
|
||||
|
||||
public void UpdateTextGeometry()
|
||||
public void RecreateTextGeometry()
|
||||
{
|
||||
DisposeTextGeometry();
|
||||
if (CanvasTextLayout == null)
|
||||
@@ -99,33 +113,5 @@ namespace BetterLyrics.WinUI3.Models
|
||||
}
|
||||
TextGeometry = CanvasGeometry.CreateText(CanvasTextLayout);
|
||||
}
|
||||
|
||||
public void DisposeFontEffects()
|
||||
{
|
||||
BackgroundFontEffect?.Dispose();
|
||||
BackgroundFontEffect = null;
|
||||
ForegroundFontEffect?.Dispose();
|
||||
ForegroundFontEffect = null;
|
||||
}
|
||||
|
||||
public void UpdateFontEffect(ICanvasAnimatedControl control, bool drawStroke, Color strokeColor, int strokeWidth, Color fontColor)
|
||||
{
|
||||
DisposeFontEffects();
|
||||
if (TextGeometry == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
BackgroundFontEffect = new CanvasCommandList(control);
|
||||
using var bgFontEffectDs = BackgroundFontEffect.CreateDrawingSession();
|
||||
ForegroundFontEffect = new CanvasCommandList(control);
|
||||
using var fgFontEffectDs = ForegroundFontEffect.CreateDrawingSession();
|
||||
if (drawStroke)
|
||||
{
|
||||
bgFontEffectDs.DrawGeometry(TextGeometry, Position, strokeColor, strokeWidth); // 描边
|
||||
fgFontEffectDs.DrawGeometry(TextGeometry, Position, strokeColor, strokeWidth); // 描边
|
||||
}
|
||||
bgFontEffectDs.FillGeometry(TextGeometry, Position, fontColor); // 填充
|
||||
fgFontEffectDs.FillGeometry(TextGeometry, Position, fontColor); // 填充
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,13 +5,11 @@ using CommunityToolkit.Mvvm.ComponentModel;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Models
|
||||
{
|
||||
public partial class LyricsSearchProviderInfo : ObservableObject
|
||||
public partial class LyricsSearchProviderInfo : ObservableRecipient
|
||||
{
|
||||
[ObservableProperty]
|
||||
public partial bool IsEnabled { get; set; }
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsEnabled { get; set; }
|
||||
|
||||
[ObservableProperty]
|
||||
public partial LyricsSearchProvider Provider { get; set; }
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial LyricsSearchProvider Provider { get; set; }
|
||||
|
||||
public LyricsSearchProviderInfo() { }
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// 2025/6/23 by Zhe Fang
|
||||
|
||||
using BetterLyrics.WinUI3.Enums;
|
||||
using BetterLyrics.WinUI3.Extensions;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@@ -9,47 +10,84 @@ using System.Linq;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Models
|
||||
{
|
||||
public partial class MediaSourceProviderInfo : ObservableObject
|
||||
public partial class MediaSourceProviderInfo : ObservableRecipient
|
||||
{
|
||||
[ObservableProperty]
|
||||
public partial bool IsEnabled { get; set; }
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsEnabled { get; set; }
|
||||
|
||||
[ObservableProperty]
|
||||
public partial string Provider { get; set; }
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial string Provider { get; set; }
|
||||
|
||||
[ObservableProperty]
|
||||
public partial bool IsLastFMTrackEnabled { get; set; }
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsLastFMTrackEnabled { get; set; }
|
||||
|
||||
[ObservableProperty]
|
||||
public partial int TimelineSyncThreshold { get; set; }
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial int TimelineSyncThreshold { get; set; }
|
||||
|
||||
[ObservableProperty]
|
||||
public partial int PositionOffset { get; set; }
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial int PositionOffset { get; set; }
|
||||
|
||||
[ObservableProperty]
|
||||
public partial bool ResetPositionOffsetOnSongChanged { get; set; }
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool ResetPositionOffsetOnSongChanged { get; set; }
|
||||
|
||||
[ObservableProperty]
|
||||
public partial ObservableCollection<LyricsSearchProviderInfo> LyricsSearchProvidersInfo { get; set; }
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial FullyObservableCollection<LyricsSearchProviderInfo> LyricsSearchProvidersInfo { get; set; }
|
||||
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial FullyObservableCollection<AlbumArtSearchProviderInfo> AlbumArtSearchProvidersInfo { get; set; }
|
||||
|
||||
public MediaSourceProviderInfo() { }
|
||||
|
||||
public MediaSourceProviderInfo(string provider)
|
||||
public MediaSourceProviderInfo(string provider) : base()
|
||||
{
|
||||
switch (provider)
|
||||
{
|
||||
case Constants.PlayerID.AppleMusic:
|
||||
// Apple Music 的特性
|
||||
TimelineSyncThreshold = 1000;
|
||||
PositionOffset = 1000;
|
||||
break;
|
||||
default:
|
||||
// 设置 100 以防不必要的重复同步
|
||||
TimelineSyncThreshold = 100;
|
||||
PositionOffset = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
Provider = provider;
|
||||
IsEnabled = true;
|
||||
IsLastFMTrackEnabled = false;
|
||||
if (provider == Constants.PlayerID.AppleMusic)
|
||||
{
|
||||
TimelineSyncThreshold = PositionOffset = 1000;
|
||||
}
|
||||
else
|
||||
{
|
||||
TimelineSyncThreshold = 0;
|
||||
PositionOffset = 0;
|
||||
}
|
||||
ResetPositionOffsetOnSongChanged = false;
|
||||
LyricsSearchProvidersInfo = [.. Enum.GetValues<LyricsSearchProvider>().Select(p => new LyricsSearchProviderInfo(p, true))];
|
||||
AlbumArtSearchProvidersInfo = [.. Enum.GetValues<AlbumArtSearchProvider>().Select(p => new AlbumArtSearchProviderInfo(p, true))];
|
||||
}
|
||||
|
||||
partial void OnAlbumArtSearchProvidersInfoChanged(FullyObservableCollection<AlbumArtSearchProviderInfo> oldValue, FullyObservableCollection<AlbumArtSearchProviderInfo> newValue)
|
||||
{
|
||||
oldValue?.CollectionChanged -= AlbumArtSearchProvidersInfo_CollectionChanged;
|
||||
oldValue?.ItemPropertyChanged -= AlbumArtSearchProvidersInfo_ItemPropertyChanged;
|
||||
newValue?.CollectionChanged += AlbumArtSearchProvidersInfo_CollectionChanged;
|
||||
newValue?.ItemPropertyChanged += AlbumArtSearchProvidersInfo_ItemPropertyChanged;
|
||||
}
|
||||
|
||||
partial void OnLyricsSearchProvidersInfoChanged(FullyObservableCollection<LyricsSearchProviderInfo> oldValue, FullyObservableCollection<LyricsSearchProviderInfo> newValue)
|
||||
{
|
||||
oldValue?.CollectionChanged -= LyricsSearchProvidersInfo_CollectionChanged;
|
||||
oldValue?.ItemPropertyChanged -= LyricsSearchProvidersInfo_ItemPropertyChanged;
|
||||
newValue?.CollectionChanged += LyricsSearchProvidersInfo_CollectionChanged;
|
||||
newValue?.ItemPropertyChanged += LyricsSearchProvidersInfo_ItemPropertyChanged;
|
||||
}
|
||||
|
||||
private void AlbumArtSearchProvidersInfo_ItemPropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
|
||||
{
|
||||
OnPropertyChanged(nameof(AlbumArtSearchProvidersInfo));
|
||||
}
|
||||
|
||||
private void AlbumArtSearchProvidersInfo_CollectionChanged(object? sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
OnPropertyChanged(nameof(AlbumArtSearchProvidersInfo));
|
||||
}
|
||||
|
||||
private void LyricsSearchProvidersInfo_CollectionChanged(object? sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
OnPropertyChanged(nameof(LyricsSearchProvidersInfo));
|
||||
}
|
||||
|
||||
private void LyricsSearchProvidersInfo_ItemPropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
|
||||
{
|
||||
OnPropertyChanged(nameof(LyricsSearchProvidersInfo));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
using BetterLyrics.WinUI3.Enums;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Models.Settings
|
||||
{
|
||||
public partial class AdvancedSettings : ObservableRecipient
|
||||
{
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsFixedTimeStep { get; set; } = false;
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial int FPS { get; set; } = 60;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using BetterLyrics.WinUI3.Enums;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Models.Settings
|
||||
{
|
||||
public partial class AlbumArtLayoutSettings : ObservableRecipient
|
||||
{
|
||||
[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;
|
||||
|
||||
public AlbumArtLayoutSettings() { }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
using BetterLyrics.WinUI3.Enums;
|
||||
using BetterLyrics.WinUI3.Extensions;
|
||||
using BetterLyrics.WinUI3.Services;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using System.Collections.ObjectModel;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Models.Settings
|
||||
{
|
||||
public partial class AppSettings : ObservableRecipient
|
||||
{
|
||||
public string Version { get; set; } = Helper.MetadataHelper.AppVersion;
|
||||
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial LyricsStyleSettings StandardLyricsStyleSettings { get; set; } = new LyricsStyleSettings(32, TextAlignmentType.Left, 0);
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial LyricsStyleSettings DesktopLyricsStyleSettings { get; set; } = new LyricsStyleSettings(28, TextAlignmentType.Center, 2);
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial LyricsStyleSettings DockLyricsStyleSettings { get; set; } = new LyricsStyleSettings(16, TextAlignmentType.Center, 0);
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial LyricsStyleSettings PictureInPictureLyricsStyleSettings { get; set; } = new LyricsStyleSettings(28, TextAlignmentType.Left, 0);
|
||||
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial LyricsEffectSettings StandardLyricsEffectSettings { get; set; } = new LyricsEffectSettings(100, 500, 1000, EasingType.EaseInOutQuad);
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial LyricsEffectSettings DesktopLyricsEffectSettings { get; set; } = new LyricsEffectSettings(500, 500, 500, EasingType.EaseInOutQuad);
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial LyricsEffectSettings DockLyricsEffectSettings { get; set; } = new LyricsEffectSettings(500, 500, 500, EasingType.EaseInOutQuad);
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial LyricsEffectSettings PictureInPictureLyricsEffectSettings { get; set; } = new LyricsEffectSettings(500, 500, 500, EasingType.EaseInOutQuad);
|
||||
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial StandardModeSettings StandardModeSettings { get; set; } = new StandardModeSettings();
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial DesktopModeSettings DesktopModeSettings { get; set; } = new DesktopModeSettings();
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial DockModeSettings DockModeSettings { get; set; } = new DockModeSettings();
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial PictureInPictureModeSettings PictureInPictureModeSettings { get; set; } = new PictureInPictureModeSettings();
|
||||
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial LyricsBackgroundSettings LyricsBackgroundSettings { get; set; } = new LyricsBackgroundSettings();
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial AlbumArtLayoutSettings AlbumArtLayoutSettings { get; set; } = new AlbumArtLayoutSettings();
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial TranslationSettings TranslationSettings { get; set; } = new TranslationSettings();
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial GeneralSettings GeneralSettings { get; set; } = new GeneralSettings();
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial MusicGallerySettings MusicGallerySettings { get; set; } = new MusicGallerySettings();
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial AdvancedSettings AdvancedSettings { get; set; } = new AdvancedSettings();
|
||||
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial FullyObservableCollection<LocalMediaFolder> LocalMediaFolders { get; set; } = [];
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial FullyObservableCollection<MediaSourceProviderInfo> MediaSourceProvidersInfo { get; set; } = [];
|
||||
|
||||
public AppSettings() { }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using BetterLyrics.WinUI3.Enums;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Models.Settings
|
||||
{
|
||||
public partial class BaseModeSettings : ObservableRecipient
|
||||
{
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial LyricsDisplayType LyricsDisplayType { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.Foundation;
|
||||
using Windows.Graphics;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Models.Settings
|
||||
{
|
||||
public partial class DesktopModeSettings : BaseModeSettings
|
||||
{
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial Rect WindowBounds { get; set; } = new Rect(100, 100, 400, 200);
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool AutoLockOnDesktopMode { get; set; } = false;
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial List<string> LockShortcut { get; set; } = new List<string>() { "Ctrl", "Alt", "U" };
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial List<string> ToggleShortcut { get; set; } = new List<string>() { "Ctrl", "Alt", "D" };
|
||||
|
||||
public DesktopModeSettings()
|
||||
{
|
||||
LyricsDisplayType = Enums.LyricsDisplayType.LyricsOnly;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using BetterLyrics.WinUI3.Enums;
|
||||
using BetterLyrics.WinUI3.Helper;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Models.Settings
|
||||
{
|
||||
public partial class DockModeSettings : BaseModeSettings
|
||||
{
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial DockPlacement DockPlacement { get; set; } = DockPlacement.Top;
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial int DockWindowHeight { get; set; } = 64;
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial string DockMonitorDeviceName { get; set; } = MonitorHelper.GetPrimaryMonitorDeviceName();
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial List<string> ToggleShortcut { get; set; } = new List<string> { "Ctrl", "Shift", "D" };
|
||||
|
||||
public DockModeSettings()
|
||||
{
|
||||
LyricsDisplayType = LyricsDisplayType.LyricsOnly;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using BetterLyrics.WinUI3.Enums;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Models.Settings
|
||||
{
|
||||
public partial class GeneralSettings : ObservableRecipient
|
||||
{
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial LyricsWindowMode AutoStartWindowType { get; set; } = LyricsWindowMode.StandardMode;
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial Language Language { get; set; } = Language.FollowSystem;
|
||||
[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 bool IsDragEverywhereEnabled { get; set; } = false;
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsImmersiveMode { get; set; } = false;
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool ExitOnLyricsWindowClosed { get; set; } = true;
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial List<string> PlayOrPauseShortcut { get; set; } = new List<string> { "Ctrl", "Alt", "P" };
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial List<string> NextSongShortcut { get; set; } = new List<string> { "Ctrl", "Alt", "Right" };
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial List<string> PreviousSongShortcut { get; set; } = new List<string> { "Ctrl", "Alt", "Left" };
|
||||
|
||||
public GeneralSettings() { }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Models.Settings
|
||||
{
|
||||
public partial class LastFMSettings : ObservableRecipient
|
||||
{
|
||||
public LastFMSettings() { }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Microsoft.UI.Xaml;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Models.Settings
|
||||
{
|
||||
public partial class LyricsBackgroundSettings : ObservableRecipient
|
||||
{
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial ElementTheme LyricsBackgroundTheme { get; set; } = ElementTheme.Dark;
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial int CoverOverlayBlurAmount { get; set; } = 100; // 100 % of the cover image size
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial int CoverOverlayOpacity { get; set; } = 100; // 100 % = 1.0
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial int PureColorOverlayOpacity { get; set; } = 100; // 100 % = 1.0
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial int CoverOverlaySpeed { get; set; } = 50; // 50 % of the base rotate speed
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial int CoverAcrylicEffectAmount { get; set; } = 0;
|
||||
|
||||
public LyricsBackgroundSettings() { }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
using BetterLyrics.WinUI3.Enums;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Models.Settings
|
||||
{
|
||||
public partial class LyricsEffectSettings : ObservableRecipient
|
||||
{
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial int LyricsBlurAmount { get; set; } = 5;
|
||||
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsLyricsLineFadeEnabled { get; set; } = false;
|
||||
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsLyricsGlowEffectEnabled { get; set; } = true;
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial LineRenderingType LyricsGlowEffectScope { get; set; } = LineRenderingType.CurrentChar;
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial int LyricsGlowEffectAmount { get; set; } = 8;
|
||||
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsLyricsShadowEnabled { get; set; } = false;
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial LineRenderingType LyricsShadowScope { get; set; } = LineRenderingType.LineStartToCurrentChar;
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial int LyricsShadowAmount { get; set; } = 8;
|
||||
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial LineRenderingType LyricsHighlightScope { get; set; } = LineRenderingType.LineStartToCurrentChar;
|
||||
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsLyricsFloatAnimationEnabled { get; set; } = true;
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial int LyricsFloatAmount { get; set; } = 1;
|
||||
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial EasingType LyricsScrollEasingType { get; set; }
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial int LyricsScrollDuration { get; set; }
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial int LyricsScrollTopDuration { get; set; }
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial int LyricsScrollBottomDuration { get; set; }
|
||||
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial int LyricsVerticalEdgeOpacity { get; set; } = 0; // 0% opacity
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsFanLyricsEnabled { get; set; } = false;
|
||||
|
||||
public LyricsEffectSettings(int lyricsScrollTopDuration, int lyricsScrollDuration, int lyricsScrollBottomDuration, EasingType lyricsScrollEasingType)
|
||||
{
|
||||
LyricsScrollTopDuration = lyricsScrollTopDuration;
|
||||
LyricsScrollDuration = lyricsScrollDuration;
|
||||
LyricsScrollBottomDuration = lyricsScrollBottomDuration;
|
||||
LyricsScrollEasingType = lyricsScrollEasingType;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
using BetterLyrics.WinUI3.Enums;
|
||||
using BetterLyrics.WinUI3.Helper;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Microsoft.UI;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.UI;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Models.Settings
|
||||
{
|
||||
public partial class LyricsStyleSettings : ObservableRecipient
|
||||
{
|
||||
[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
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial int LyricsFontStrokeWidth { get; set; }
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial Color LyricsCustomBgFontColor { get; set; } = Colors.White;
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial Color LyricsCustomFgFontColor { get; set; } = Colors.White;
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial Color LyricsCustomStrokeFontColor { get; set; } = Colors.White;
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial LyricsFontColorType LyricsBgFontColorType { get; set; } = LyricsFontColorType.AdaptiveGrayed;
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial LyricsFontColorType LyricsFgFontColorType { get; set; } = LyricsFontColorType.AdaptiveGrayed;
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial LyricsFontColorType LyricsStrokeFontColorType { get; set; } = LyricsFontColorType.AdaptiveGrayed;
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial LyricsFontWeight LyricsFontWeight { get; set; } = LyricsFontWeight.Bold;
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial double LyricsLineSpacingFactor { get; set; } = 0.5;
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial string LyricsTranslationSeparator { get; set; } = StringHelper.NewLine;
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial string LyricsFontFamily { get; set; } = FontHelper.SystemFontFamilies.FirstOrDefault() ?? "";
|
||||
|
||||
public LyricsStyleSettings() { }
|
||||
|
||||
public LyricsStyleSettings(int lyricsFontSize, TextAlignmentType lyricsAlignmentType, int lyricsFontStrokeWidth)
|
||||
{
|
||||
LyricsFontSize = lyricsFontSize;
|
||||
LyricsAlignmentType = lyricsAlignmentType;
|
||||
LyricsFontStrokeWidth = lyricsFontStrokeWidth;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using BetterLyrics.WinUI3.Enums;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Models.Settings
|
||||
{
|
||||
public partial class MusicGallerySettings : ObservableRecipient
|
||||
{
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial PlaybackOrder PlaybackOrder { get; set; } = PlaybackOrder.RepeatAll;
|
||||
|
||||
public MusicGallerySettings() { }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Models.Settings
|
||||
{
|
||||
public partial class PictureInPictureModeSettings : BaseModeSettings
|
||||
{
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial List<string> ToggleShortcut { get; set; } = new List<string>() { "Ctrl", "Shift", "P" };
|
||||
|
||||
public PictureInPictureModeSettings()
|
||||
{
|
||||
LyricsDisplayType = Enums.LyricsDisplayType.SplitView;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
using BetterLyrics.WinUI3.Enums;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.Foundation;
|
||||
using Windows.Graphics;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Models.Settings
|
||||
{
|
||||
public partial class StandardModeSettings : BaseModeSettings
|
||||
{
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial Rect WindowBounds { get; set; } = new Rect(100, 100, 1000, 600);
|
||||
|
||||
public StandardModeSettings()
|
||||
{
|
||||
LyricsDisplayType = LyricsDisplayType.SplitView;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using BetterLyrics.WinUI3.Services;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Models.Settings
|
||||
{
|
||||
public partial class TranslationSettings : ObservableRecipient
|
||||
{
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsLibreTranslateEnabled { get; set; } = false;
|
||||
[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();
|
||||
|
||||
public TranslationSettings() { }
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@
|
||||
xmlns:interactivity="using:Microsoft.Xaml.Interactivity"
|
||||
xmlns:local="using:BetterLyrics.WinUI3.Renderer"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
Unloaded="LyricsCanvas_Unloaded"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<Grid>
|
||||
|
||||
@@ -25,5 +25,11 @@ namespace BetterLyrics.WinUI3.Renderer
|
||||
{
|
||||
ViewModel.Update(sender, args);
|
||||
}
|
||||
|
||||
private void LyricsCanvas_Unloaded(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
|
||||
{
|
||||
LyricsCanvas.RemoveFromVisualTree();
|
||||
LyricsCanvas = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,20 +1,15 @@
|
||||
// 2025/6/23 by Zhe Fang
|
||||
|
||||
using System.Collections.Generic;
|
||||
using BetterLyrics.WinUI3.Models;
|
||||
using BetterLyrics.WinUI3.Models.Settings;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using BetterLyrics.WinUI3.Models;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Serialization
|
||||
{
|
||||
|
||||
[JsonSerializable(typeof(List<AlbumArtSearchProviderInfo>))]
|
||||
[JsonSerializable(typeof(List<LyricsSearchProviderInfo>))]
|
||||
[JsonSerializable(typeof(List<MediaSourceProviderInfo>))]
|
||||
[JsonSerializable(typeof(List<LocalMediaFolder>))]
|
||||
[JsonSerializable(typeof(List<string>))]
|
||||
[JsonSerializable(typeof(TranslateResponse))]
|
||||
[JsonSerializable(typeof(JsonElement))]
|
||||
[JsonSerializable(typeof(AppSettings))]
|
||||
[JsonSourceGenerationOptions(WriteIndented = true)]
|
||||
internal partial class SourceGenerationContext : JsonSerializerContext { }
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using ATL;
|
||||
using BetterLyrics.WinUI3.Enums;
|
||||
using BetterLyrics.WinUI3.Helper;
|
||||
using BetterLyrics.WinUI3.Helper.BetterLyrics.WinUI3.Helper;
|
||||
using BetterLyrics.WinUI3.Services.SettingsService;
|
||||
using CommunityToolkit.Mvvm.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
@@ -10,8 +11,6 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Text.Encodings.Web;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
@@ -31,56 +30,66 @@ namespace BetterLyrics.WinUI3.Services.AlbumArtSearchService
|
||||
_iTunesHttpClinet = new();
|
||||
}
|
||||
|
||||
public async Task<byte[]?> SearchAsync(string title, string artist, string album, byte[]? bytesFromSMTC = null)
|
||||
public async Task<byte[]?> SearchAsync(string mediaSessionId, string title, string artist, string album, byte[]? bytesFromSMTC = null)
|
||||
{
|
||||
byte[]? result = null;
|
||||
|
||||
foreach (var provider in _settingsService.AlbumArtSearchProvidersInfo)
|
||||
try
|
||||
{
|
||||
if (!provider.IsEnabled)
|
||||
foreach (var provider in _settingsService.AppSettings.MediaSourceProvidersInfo.Where(x => x.Provider == mediaSessionId).FirstOrDefault()?.AlbumArtSearchProvidersInfo ?? [])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (!provider.IsEnabled)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (provider.Provider)
|
||||
{
|
||||
case AlbumArtSearchProvider.Local:
|
||||
result = SearchFile(artist, album);
|
||||
break;
|
||||
case AlbumArtSearchProvider.SMTC:
|
||||
result = bytesFromSMTC;
|
||||
break;
|
||||
case AlbumArtSearchProvider.iTunes:
|
||||
foreach (string countryCode in new List<string>() { "us", "cn", "jp", "kr" })
|
||||
{
|
||||
result = await SearchiTunesAsync(artist, album, title, countryCode);
|
||||
if (result != null) break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
switch (provider.Provider)
|
||||
{
|
||||
case AlbumArtSearchProvider.Local:
|
||||
result = SearchFile(artist, title);
|
||||
break;
|
||||
case AlbumArtSearchProvider.SMTC:
|
||||
result = bytesFromSMTC;
|
||||
break;
|
||||
case AlbumArtSearchProvider.iTunes:
|
||||
foreach (string countryCode in new List<string>() { "us", "cn", "jp", "kr" })
|
||||
{
|
||||
result = await SearchiTunesAsync(artist, album, title, countryCode);
|
||||
if (result != null) break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (result != null) return result;
|
||||
if (result != null) return result;
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private byte[]? SearchFile(string artist, string album)
|
||||
private byte[]? SearchFile(string artist, string title)
|
||||
{
|
||||
foreach (var folder in _settingsService.LocalMediaFolders)
|
||||
foreach (var folder in _settingsService.AppSettings.LocalMediaFolders)
|
||||
{
|
||||
if (Directory.Exists(folder.Path) && folder.IsEnabled)
|
||||
{
|
||||
foreach (var file in Directory.GetFiles(folder.Path, $"*.*", SearchOption.AllDirectories))
|
||||
foreach (var file in DirectoryHelper.GetAllFiles(folder.Path))
|
||||
{
|
||||
if (FileHelper.IsSwitchableNormalizedMatch(Path.GetFileNameWithoutExtension(file), album, artist))
|
||||
if (FileHelper.MusicExtensions.Contains(Path.GetExtension(file)))
|
||||
{
|
||||
Track track = new(file);
|
||||
var bytes = track.EmbeddedPictures.FirstOrDefault()?.PictureData;
|
||||
if (bytes != null)
|
||||
if ((track.Title == title && track.Artist == artist) || FileHelper.IsSwitchableNormalizedMatch(Path.GetFileNameWithoutExtension(file), artist, title))
|
||||
{
|
||||
return bytes;
|
||||
var bytes = track.EmbeddedPictures.FirstOrDefault()?.PictureData;
|
||||
if (bytes != null)
|
||||
{
|
||||
return bytes;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,6 @@ namespace BetterLyrics.WinUI3.Services.AlbumArtSearchService
|
||||
{
|
||||
public interface IAlbumArtSearchService
|
||||
{
|
||||
Task<byte[]?> SearchAsync(string title, string artist, string album, byte[]? bytesFromSMTC = null);
|
||||
Task<byte[]?> SearchAsync(string mediaSessionId, string title, string artist, string album, byte[]? bytesFromSMTC = null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ using BetterLyrics.WinUI3.Helper;
|
||||
using BetterLyrics.WinUI3.Models;
|
||||
using BetterLyrics.WinUI3.Services.SettingsService;
|
||||
using BetterLyrics.WinUI3.ViewModels;
|
||||
using BetterLyrics.WinUI3.ViewModels.SettingsPageViewModel;
|
||||
using BetterLyrics.WinUI3.Views;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
@@ -40,7 +39,7 @@ namespace BetterLyrics.WinUI3.Services.LastFMService
|
||||
_settingsService = settingsService;
|
||||
|
||||
_client = new LastfmClient(Constants.LastFM.ApiKey, Constants.LastFM.SharedSecret);
|
||||
_client.Session.SessionKey = _settingsService.LastFMSessionKey;
|
||||
_client.Session.SessionKey = PasswordVaultHelper.Get(Constants.App.AppName, Constants.LastFM.SessionKeyCredentialKey) ?? string.Empty;
|
||||
UpdateAuthStatusAsync();
|
||||
}
|
||||
|
||||
@@ -49,7 +48,7 @@ namespace BetterLyrics.WinUI3.Services.LastFMService
|
||||
try
|
||||
{
|
||||
await _client.AuthenticateViaWebAsync();
|
||||
_settingsService.LastFMSessionKey = _client.Session.SessionKey;
|
||||
PasswordVaultHelper.Save(Constants.App.AppName, Constants.LastFM.SessionKeyCredentialKey, _client.Session.SessionKey);
|
||||
await UpdateAuthStatusAsync();
|
||||
}
|
||||
catch (Exception)
|
||||
@@ -61,7 +60,7 @@ namespace BetterLyrics.WinUI3.Services.LastFMService
|
||||
public async Task ConfirmUnAuthAsync()
|
||||
{
|
||||
_client.Session.SessionKey = "";
|
||||
_settingsService.LastFMSessionKey = "";
|
||||
PasswordVaultHelper.Delete(Constants.App.AppName, Constants.LastFM.SessionKeyCredentialKey);
|
||||
await UpdateAuthStatusAsync();
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,5 @@ namespace BetterLyrics.WinUI3.Services.LibWatcherService
|
||||
public interface ILibWatcherService
|
||||
{
|
||||
event EventHandler<LibChangedEventArgs>? MusicLibraryFilesChanged;
|
||||
|
||||
public void UpdateWatchers(List<LocalMediaFolder> folders);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,11 +14,25 @@ namespace BetterLyrics.WinUI3.Services.LibWatcherService
|
||||
{
|
||||
public class LibWatcherService : BaseViewModel, IDisposable, ILibWatcherService
|
||||
{
|
||||
private readonly ISettingsService _settingsService;
|
||||
private readonly Dictionary<string, FileSystemWatcher> _watchers = [];
|
||||
|
||||
public LibWatcherService(ISettingsService settingsService) : base(settingsService)
|
||||
public LibWatcherService(ISettingsService settingsService)
|
||||
{
|
||||
UpdateWatchers(_settingsService.LocalMediaFolders);
|
||||
_settingsService = settingsService;
|
||||
_settingsService.AppSettings.LocalMediaFolders.CollectionChanged += LocalMediaFolders_CollectionChanged;
|
||||
_settingsService.AppSettings.LocalMediaFolders.ItemPropertyChanged += LocalMediaFolders_ItemPropertyChanged;
|
||||
UpdateWatchers();
|
||||
}
|
||||
|
||||
private void LocalMediaFolders_ItemPropertyChanged(object? sender, Extensions.ItemPropertyChangedEventArgs e)
|
||||
{
|
||||
UpdateWatchers();
|
||||
}
|
||||
|
||||
private void LocalMediaFolders_CollectionChanged(object? sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
UpdateWatchers();
|
||||
}
|
||||
|
||||
public event EventHandler<LibChangedEventArgs>? MusicLibraryFilesChanged;
|
||||
@@ -32,12 +46,13 @@ namespace BetterLyrics.WinUI3.Services.LibWatcherService
|
||||
_watchers.Clear();
|
||||
}
|
||||
|
||||
public void UpdateWatchers(List<LocalMediaFolder> folders)
|
||||
private void UpdateWatchers()
|
||||
{
|
||||
var folders = _settingsService.AppSettings.LocalMediaFolders;
|
||||
// 移除不再监听的
|
||||
foreach (var key in _watchers.Keys.ToList())
|
||||
{
|
||||
if (!folders.Any(x => x.Path == key && x.IsEnabled))
|
||||
if (!folders.Any(x => x.Path == key && x.IsEnabled && x.IsRealTimeWatchEnabled))
|
||||
{
|
||||
_watchers[key].Dispose();
|
||||
_watchers.Remove(key);
|
||||
@@ -47,11 +62,7 @@ namespace BetterLyrics.WinUI3.Services.LibWatcherService
|
||||
// 添加新的监听
|
||||
foreach (var folder in folders)
|
||||
{
|
||||
if (
|
||||
!_watchers.ContainsKey(folder.Path)
|
||||
&& Directory.Exists(folder.Path)
|
||||
&& folder.IsEnabled
|
||||
)
|
||||
if (!_watchers.ContainsKey(folder.Path) && Directory.Exists(folder.Path) && folder.IsEnabled && folder.IsRealTimeWatchEnabled)
|
||||
{
|
||||
var watcher = new FileSystemWatcher(folder.Path)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
using BetterLyrics.WinUI3.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Services.LiveStatesService
|
||||
{
|
||||
public interface ILiveStatesService
|
||||
{
|
||||
LiveStates LiveStates { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
using BetterLyrics.WinUI3.Enums;
|
||||
using BetterLyrics.WinUI3.Models;
|
||||
using BetterLyrics.WinUI3.Models.Settings;
|
||||
using BetterLyrics.WinUI3.Services.SettingsService;
|
||||
using BetterLyrics.WinUI3.ViewModels;
|
||||
using CommunityToolkit.Mvvm.Messaging;
|
||||
using CommunityToolkit.Mvvm.Messaging.Messages;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Services.LiveStatesService
|
||||
{
|
||||
public class LiveStatesService : BaseViewModel, ILiveStatesService,
|
||||
IRecipient<PropertyChangedMessage<LyricsWindowMode>>,
|
||||
IRecipient<PropertyChangedMessage<LyricsDisplayType>>
|
||||
{
|
||||
private readonly ISettingsService _settingsService;
|
||||
|
||||
public LiveStates LiveStates { get; set; }
|
||||
|
||||
public LiveStatesService(ISettingsService settingsService)
|
||||
{
|
||||
_settingsService = settingsService;
|
||||
|
||||
LiveStates = new LiveStates(_settingsService.AppSettings);
|
||||
}
|
||||
|
||||
public void Receive(PropertyChangedMessage<LyricsWindowMode> message)
|
||||
{
|
||||
if (message.Sender is LiveStates)
|
||||
{
|
||||
if (message.PropertyName == nameof(LiveStates.CurrentLyricsWindowMode))
|
||||
{
|
||||
switch (message.NewValue)
|
||||
{
|
||||
case LyricsWindowMode.StandardMode:
|
||||
LiveStates.CurrentLyricsStyleSettings = _settingsService.AppSettings.StandardLyricsStyleSettings;
|
||||
LiveStates.CurrentLyricsEffectSettings = _settingsService.AppSettings.StandardLyricsEffectSettings;
|
||||
LiveStates.CurrentLyricsDisplayType = _settingsService.AppSettings.StandardModeSettings.LyricsDisplayType;
|
||||
break;
|
||||
case LyricsWindowMode.DockMode:
|
||||
LiveStates.CurrentLyricsStyleSettings = _settingsService.AppSettings.DockLyricsStyleSettings;
|
||||
LiveStates.CurrentLyricsEffectSettings = _settingsService.AppSettings.DockLyricsEffectSettings;
|
||||
LiveStates.CurrentLyricsDisplayType = _settingsService.AppSettings.DockModeSettings.LyricsDisplayType;
|
||||
break;
|
||||
case LyricsWindowMode.DesktopMode:
|
||||
LiveStates.CurrentLyricsStyleSettings = _settingsService.AppSettings.DesktopLyricsStyleSettings;
|
||||
LiveStates.CurrentLyricsEffectSettings = _settingsService.AppSettings.DesktopLyricsEffectSettings;
|
||||
LiveStates.CurrentLyricsDisplayType = _settingsService.AppSettings.DesktopModeSettings.LyricsDisplayType;
|
||||
break;
|
||||
case LyricsWindowMode.PictureInPictureMode:
|
||||
LiveStates.CurrentLyricsStyleSettings = _settingsService.AppSettings.PictureInPictureLyricsStyleSettings;
|
||||
LiveStates.CurrentLyricsEffectSettings = _settingsService.AppSettings.PictureInPictureLyricsEffectSettings;
|
||||
LiveStates.CurrentLyricsDisplayType = _settingsService.AppSettings.PictureInPictureModeSettings.LyricsDisplayType;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Receive(PropertyChangedMessage<LyricsDisplayType> message)
|
||||
{
|
||||
if (message.Sender is StandardModeSettings)
|
||||
{
|
||||
if (message.PropertyName == nameof(StandardModeSettings.LyricsDisplayType))
|
||||
{
|
||||
if (LiveStates.CurrentLyricsWindowMode == LyricsWindowMode.StandardMode)
|
||||
{
|
||||
LiveStates.CurrentLyricsDisplayType = message.NewValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (message.Sender is DockModeSettings)
|
||||
{
|
||||
if (message.PropertyName == nameof(DockModeSettings.LyricsDisplayType))
|
||||
{
|
||||
if (LiveStates.CurrentLyricsWindowMode == LyricsWindowMode.DockMode)
|
||||
{
|
||||
LiveStates.CurrentLyricsDisplayType = message.NewValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (message.Sender is DesktopModeSettings)
|
||||
{
|
||||
if (message.PropertyName == nameof(DesktopModeSettings.LyricsDisplayType))
|
||||
{
|
||||
if (LiveStates.CurrentLyricsWindowMode == LyricsWindowMode.DesktopMode)
|
||||
{
|
||||
LiveStates.CurrentLyricsDisplayType = message.NewValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (message.Sender is PictureInPictureModeSettings)
|
||||
{
|
||||
if (message.PropertyName == nameof(PictureInPictureModeSettings.LyricsDisplayType))
|
||||
{
|
||||
if (LiveStates.CurrentLyricsWindowMode == LyricsWindowMode.PictureInPictureMode)
|
||||
{
|
||||
LiveStates.CurrentLyricsDisplayType = message.NewValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@
|
||||
using ATL;
|
||||
using BetterLyrics.WinUI3.Enums;
|
||||
using BetterLyrics.WinUI3.Helper;
|
||||
using BetterLyrics.WinUI3.Helper.BetterLyrics.WinUI3.Helper;
|
||||
using BetterLyrics.WinUI3.Services.SettingsService;
|
||||
using CommunityToolkit.Mvvm.DependencyInjection;
|
||||
using Lyricify.Lyrics.Providers.Web.Kugou;
|
||||
@@ -92,7 +93,7 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
|
||||
|
||||
try
|
||||
{
|
||||
foreach (var provider in _settingsService.MediaSourceProvidersInfo.Where(x => x.Provider == mediaSessionId).FirstOrDefault()?.LyricsSearchProvidersInfo ?? [])
|
||||
foreach (var provider in _settingsService.AppSettings.MediaSourceProvidersInfo.Where(x => x.Provider == mediaSessionId).FirstOrDefault()?.LyricsSearchProvidersInfo ?? [])
|
||||
{
|
||||
if (!provider.IsEnabled)
|
||||
{
|
||||
@@ -169,21 +170,27 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
|
||||
|
||||
private async Task<string?> SearchFile(string title, string artist, LyricsFormat format)
|
||||
{
|
||||
foreach (var folder in _settingsService.LocalMediaFolders)
|
||||
foreach (var folder in _settingsService.AppSettings.LocalMediaFolders)
|
||||
{
|
||||
if (Directory.Exists(folder.Path) && folder.IsEnabled)
|
||||
{
|
||||
foreach (var file in Directory.GetFiles(folder.Path, $"*{format.ToFileExtension()}", SearchOption.AllDirectories))
|
||||
try
|
||||
{
|
||||
if (FileHelper.IsSwitchableNormalizedMatch(Path.GetFileNameWithoutExtension(file), title, artist))
|
||||
foreach (var file in DirectoryHelper.GetAllFiles(folder.Path, $"*{format.ToFileExtension()}"))
|
||||
{
|
||||
string? raw = await File.ReadAllTextAsync(file, FileHelper.GetEncoding(file));
|
||||
if (raw != null)
|
||||
if (FileHelper.IsSwitchableNormalizedMatch(Path.GetFileNameWithoutExtension(file), title, artist))
|
||||
{
|
||||
return raw;
|
||||
string? raw = await File.ReadAllTextAsync(file, FileHelper.GetEncoding(file));
|
||||
if (raw != null)
|
||||
{
|
||||
return raw;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
@@ -191,28 +198,27 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
|
||||
|
||||
private string? SearchEmbedded(string title, string artist)
|
||||
{
|
||||
foreach (var folder in _settingsService.LocalMediaFolders)
|
||||
foreach (var folder in _settingsService.AppSettings.LocalMediaFolders)
|
||||
{
|
||||
if (Directory.Exists(folder.Path) && folder.IsEnabled)
|
||||
{
|
||||
foreach (var file in Directory.GetFiles(folder.Path, $"*.*", SearchOption.AllDirectories))
|
||||
foreach (var file in DirectoryHelper.GetAllFiles(folder.Path))
|
||||
{
|
||||
if (FileHelper.IsSwitchableNormalizedMatch(Path.GetFileNameWithoutExtension(file), title, artist))
|
||||
if (FileHelper.MusicExtensions.Contains(Path.GetExtension(file)))
|
||||
{
|
||||
try
|
||||
var track = new Track(file);
|
||||
if ((track.Title == title && track.Artist == artist) || FileHelper.IsSwitchableNormalizedMatch(Path.GetFileNameWithoutExtension(file), title, artist))
|
||||
{
|
||||
var plain = TagLib.File.Create(file).Tag.Lyrics;
|
||||
if (plain != null && plain != string.Empty)
|
||||
if (!plain.IsNullOrEmpty())
|
||||
{
|
||||
return plain;
|
||||
}
|
||||
}
|
||||
catch (Exception) { }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,8 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
Task NextAsync();
|
||||
Task ChangePosition(double seconds);
|
||||
|
||||
MediaSourceProviderInfo? GetCurrentMediaSourceProviderInfo();
|
||||
|
||||
bool IsPlaying { get; }
|
||||
SongInfo? SongInfo { get; }
|
||||
TimeSpan Position { get; }
|
||||
|
||||
@@ -2,18 +2,21 @@
|
||||
|
||||
using BetterLyrics.WinUI3.Enums;
|
||||
using BetterLyrics.WinUI3.Events;
|
||||
using BetterLyrics.WinUI3.Extensions;
|
||||
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.SettingsService;
|
||||
using BetterLyrics.WinUI3.ViewModels;
|
||||
using BetterLyrics.WinUI3.ViewModels.SettingsPageViewModel;
|
||||
using BetterLyrics.WinUI3.Views;
|
||||
using CommunityToolkit.Mvvm.DependencyInjection;
|
||||
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;
|
||||
@@ -33,11 +36,13 @@ using WindowsMediaController;
|
||||
namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
{
|
||||
public partial class MediaSessionsService : BaseViewModel, IMediaSessionsService,
|
||||
IRecipient<PropertyChangedMessage<ObservableCollection<MediaSourceProviderInfo>>>,
|
||||
IRecipient<PropertyChangedMessage<ObservableCollection<AlbumArtSearchProviderInfo>>>
|
||||
IRecipient<PropertyChangedMessage<bool>>,
|
||||
IRecipient<PropertyChangedMessage<List<string>>>,
|
||||
IRecipient<PropertyChangedMessage<FullyObservableCollection<AlbumArtSearchProviderInfo>>>
|
||||
{
|
||||
private readonly IAlbumArtSearchService _albumArtSearchService;
|
||||
private readonly ILogger<MediaSessionsService> _logger;
|
||||
private readonly ISettingsService _settingsService;
|
||||
|
||||
private double _lxMusicPositionSeconds = 0;
|
||||
private double _lxMusicDurationSeconds = 0;
|
||||
@@ -49,13 +54,11 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
|
||||
private readonly MediaManager _mediaManager = new();
|
||||
|
||||
private readonly LatestOnlyTaskRunner _albumArtRefreshRunner = new();
|
||||
private readonly LatestOnlyTaskRunner _onAnyMediaPropertyChangedRunner = new();
|
||||
private readonly BackgroundTaskRunner _albumArtRefreshRunner = new();
|
||||
private readonly BackgroundTaskRunner _onAnyMediaPropertyChangedRunner = new();
|
||||
|
||||
private SongInfo? _cachedSongInfo;
|
||||
private List<MediaSourceProviderInfo> _mediaSourceProvidersInfo;
|
||||
private byte[]? _SMTCAlbumArtBytes = null;
|
||||
private int _targetAlbumArtSize = 400;
|
||||
|
||||
public event EventHandler<IsPlayingChangedEventArgs>? IsPlayingChanged;
|
||||
public event EventHandler<TimelineChangedEventArgs>? TimelineChanged;
|
||||
@@ -63,13 +66,78 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
public event EventHandler<AlbumArtChangedEventArgs>? AlbumArtChangedChanged;
|
||||
public event EventHandler<MediaSourceProvidersInfoEventArgs>? MediaSourceProvidersInfoChanged;
|
||||
|
||||
public MediaSessionsService(ISettingsService settingsService, IAlbumArtSearchService albumArtSearchService) : base(settingsService)
|
||||
public MediaSessionsService(ISettingsService settingsService, IAlbumArtSearchService albumArtSearchService)
|
||||
{
|
||||
_settingsService = settingsService;
|
||||
_albumArtSearchService = albumArtSearchService;
|
||||
_logger = Ioc.Default.GetRequiredService<ILogger<MediaSessionsService>>();
|
||||
|
||||
_mediaSourceProvidersInfo = _settingsService.MediaSourceProvidersInfo;
|
||||
_settingsService.AppSettings.MediaSourceProvidersInfo.ItemPropertyChanged += MediaSourceProvidersInfo_ItemPropertyChanged;
|
||||
_settingsService.AppSettings.LocalMediaFolders.CollectionChanged += LocalMediaFolders_CollectionChanged;
|
||||
_settingsService.AppSettings.LocalMediaFolders.ItemPropertyChanged += LocalMediaFolders_ItemPropertyChanged;
|
||||
|
||||
InitMediaManager();
|
||||
InitPlaybackShortcuts();
|
||||
}
|
||||
|
||||
private void InitPlaybackShortcuts()
|
||||
{
|
||||
UpdatePlayOrPauseSongShortcut();
|
||||
UpdatePreviousSongShortcut();
|
||||
UpdateNextSongShortcut();
|
||||
}
|
||||
|
||||
private void UpdatePlayOrPauseSongShortcut()
|
||||
{
|
||||
GlobalHotKeyHelper.UpdateHotKey<LyricsWindow>(ShortcutID.PlayOrPauseSong, _settingsService.AppSettings.GeneralSettings.PlayOrPauseShortcut, () =>
|
||||
{
|
||||
if (_cachedIsPlaying)
|
||||
{
|
||||
_ = PauseAsync();
|
||||
}
|
||||
else
|
||||
{
|
||||
_ = PlayAsync();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void UpdatePreviousSongShortcut()
|
||||
{
|
||||
GlobalHotKeyHelper.UpdateHotKey<LyricsWindow>(ShortcutID.PreviousSong, _settingsService.AppSettings.GeneralSettings.PreviousSongShortcut, () =>
|
||||
{
|
||||
_ = PreviousAsync();
|
||||
});
|
||||
}
|
||||
|
||||
private void UpdateNextSongShortcut()
|
||||
{
|
||||
GlobalHotKeyHelper.UpdateHotKey<LyricsWindow>(ShortcutID.NextSong, _settingsService.AppSettings.GeneralSettings.NextSongShortcut, () =>
|
||||
{
|
||||
_ = NextAsync();
|
||||
});
|
||||
}
|
||||
|
||||
private void LocalMediaFolders_ItemPropertyChanged(object? sender, ItemPropertyChangedEventArgs e)
|
||||
{
|
||||
UpdateAlbumArtRelated();
|
||||
}
|
||||
|
||||
private void LocalMediaFolders_CollectionChanged(object? sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
UpdateAlbumArtRelated();
|
||||
}
|
||||
|
||||
private void MediaSourceProvidersInfo_ItemPropertyChanged(object? sender, ItemPropertyChangedEventArgs e)
|
||||
{
|
||||
switch (e.PropertyName)
|
||||
{
|
||||
case nameof(MediaSourceProviderInfo.AlbumArtSearchProvidersInfo):
|
||||
UpdateAlbumArtRelated();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsPlaying => _cachedIsPlaying;
|
||||
@@ -78,7 +146,7 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
|
||||
private bool IsMediaSourceEnabled(string id)
|
||||
{
|
||||
return _mediaSourceProvidersInfo.FirstOrDefault(s => s.Provider == id)?.IsEnabled ?? true;
|
||||
return _settingsService.AppSettings.MediaSourceProvidersInfo.FirstOrDefault(s => s.Provider == id)?.IsEnabled ?? true;
|
||||
}
|
||||
|
||||
private void InitMediaManager()
|
||||
@@ -94,6 +162,7 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
Task.Run(() =>
|
||||
{
|
||||
MediaManager_OnFocusedSessionChanged(null);
|
||||
_mediaManager.CurrentMediaSessions.ToList().ForEach(x => RecordMediaSourceProviderInfo(x.Value));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -138,7 +207,7 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
|
||||
var focusedSession = _mediaManager.GetFocusedSession();
|
||||
|
||||
RecordMediaSourceProviderInfo(mediaSession);
|
||||
//RecordMediaSourceProviderInfo(mediaSession);
|
||||
if (mediaSession != focusedSession) return;
|
||||
|
||||
if (!IsMediaSourceEnabled(mediaSession.Id))
|
||||
@@ -169,14 +238,14 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
|
||||
var focusedSession = _mediaManager.GetFocusedSession();
|
||||
|
||||
RecordMediaSourceProviderInfo(mediaSession);
|
||||
//RecordMediaSourceProviderInfo(mediaSession);
|
||||
if (mediaSession != focusedSession) return;
|
||||
|
||||
if (!IsMediaSourceEnabled(id))
|
||||
{
|
||||
_cachedSongInfo = null;
|
||||
|
||||
_onAnyMediaPropertyChangedRunner.RunAsync(async token =>
|
||||
_onAnyMediaPropertyChangedRunner.Run(async token =>
|
||||
{
|
||||
_logger.LogInformation("Media properties changed: Title: {Title}, Artist: {Artist}, Album: {Album}",
|
||||
mediaProperties.Title, mediaProperties.Artist, mediaProperties.AlbumTitle);
|
||||
@@ -188,10 +257,7 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
|
||||
_SMTCAlbumArtBytes = null;
|
||||
|
||||
await _albumArtRefreshRunner.RunAsync(async tokne =>
|
||||
{
|
||||
await UpdateAlbumArtRelated(tokne);
|
||||
});
|
||||
UpdateAlbumArtRelated();
|
||||
|
||||
if (!token.IsCancellationRequested)
|
||||
{
|
||||
@@ -200,10 +266,19 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
SongInfoChanged?.Invoke(this, new SongInfoChangedEventArgs(_cachedSongInfo));
|
||||
});
|
||||
}
|
||||
}).ConfigureAwait(false);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
_dispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, () =>
|
||||
{
|
||||
var currentMediaSourceProviderInfo = GetCurrentMediaSourceProviderInfo();
|
||||
if (currentMediaSourceProviderInfo?.ResetPositionOffsetOnSongChanged == true)
|
||||
{
|
||||
currentMediaSourceProviderInfo?.PositionOffset = 0;
|
||||
}
|
||||
});
|
||||
|
||||
_cachedSongInfo = new SongInfo
|
||||
{
|
||||
Title = mediaProperties.Title,
|
||||
@@ -215,7 +290,7 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
|
||||
_cachedSongInfo.Duration = (int)(_cachedSongInfo.DurationMs / 1000f);
|
||||
|
||||
_onAnyMediaPropertyChangedRunner.RunAsync(async token =>
|
||||
_onAnyMediaPropertyChangedRunner.Run(async token =>
|
||||
{
|
||||
_logger.LogInformation("Media properties changed: Title: {Title}, Artist: {Artist}, Album: {Album}",
|
||||
mediaProperties.Title, mediaProperties.Artist, mediaProperties.AlbumTitle);
|
||||
@@ -238,10 +313,7 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
_SMTCAlbumArtBytes = null;
|
||||
}
|
||||
|
||||
await _albumArtRefreshRunner.RunAsync(async tokne =>
|
||||
{
|
||||
await UpdateAlbumArtRelated(tokne);
|
||||
});
|
||||
UpdateAlbumArtRelated();
|
||||
|
||||
if (!token.IsCancellationRequested)
|
||||
{
|
||||
@@ -250,7 +322,7 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
SongInfoChanged?.Invoke(this, new SongInfoChangedEventArgs(_cachedSongInfo));
|
||||
});
|
||||
}
|
||||
}).ConfigureAwait(false);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -282,18 +354,14 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
var id = mediaSession?.Id;
|
||||
if (string.IsNullOrEmpty(id)) return;
|
||||
|
||||
var found = _mediaSourceProvidersInfo.FirstOrDefault(x => x.Provider == id);
|
||||
if (found == null)
|
||||
_dispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, () =>
|
||||
{
|
||||
_mediaSourceProvidersInfo.Add(new MediaSourceProviderInfo(id));
|
||||
// 在这里就写进设置
|
||||
// 因为 SettingsPageViewModel 可能还没有初始化
|
||||
_settingsService.MediaSourceProvidersInfo = _mediaSourceProvidersInfo;
|
||||
_dispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, () =>
|
||||
var found = _settingsService.AppSettings.MediaSourceProvidersInfo.FirstOrDefault(x => x.Provider == id);
|
||||
if (found == null)
|
||||
{
|
||||
MediaSourceProvidersInfoChanged?.Invoke(this, new MediaSourceProvidersInfoEventArgs(_mediaSourceProvidersInfo));
|
||||
});
|
||||
}
|
||||
_settingsService.AppSettings.MediaSourceProvidersInfo.Add(new MediaSourceProviderInfo(id));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void SendNullMessages()
|
||||
@@ -319,47 +387,51 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
MediaManager_OnAnyPlaybackStateChanged(focusedSession, focusedSession.ControlSession.GetPlaybackInfo());
|
||||
}
|
||||
|
||||
private async Task UpdateAlbumArtRelated(CancellationToken token)
|
||||
private void UpdateAlbumArtRelated()
|
||||
{
|
||||
if (_cachedSongInfo == null)
|
||||
_albumArtRefreshRunner.Run(async (token) =>
|
||||
{
|
||||
_logger.LogWarning("Cached song info is null, cannot update album art.");
|
||||
return;
|
||||
}
|
||||
if (_cachedSongInfo == null)
|
||||
{
|
||||
_logger.LogWarning("Cached song info is null, cannot update album art.");
|
||||
return;
|
||||
}
|
||||
|
||||
byte[]? bytes = await _albumArtSearchService.SearchAsync(
|
||||
_cachedSongInfo.Title,
|
||||
_cachedSongInfo.Artist,
|
||||
_cachedSongInfo?.Album ?? string.Empty,
|
||||
_SMTCAlbumArtBytes
|
||||
);
|
||||
token.ThrowIfCancellationRequested();
|
||||
|
||||
if (bytes == null)
|
||||
{
|
||||
bytes = await ImageHelper.CreateTextPlaceholderBytesAsync(_targetAlbumArtSize, _targetAlbumArtSize);
|
||||
byte[]? bytes = await _albumArtSearchService.SearchAsync(
|
||||
SongInfo?.SourceAppUserModelId ?? "",
|
||||
_cachedSongInfo.Title,
|
||||
_cachedSongInfo.Artist,
|
||||
_cachedSongInfo?.Album ?? string.Empty,
|
||||
_SMTCAlbumArtBytes
|
||||
);
|
||||
token.ThrowIfCancellationRequested();
|
||||
}
|
||||
|
||||
bytes = ImageHelper.Resize(bytes, _targetAlbumArtSize);
|
||||
bytes = ImageHelper.MakeSquareWithThemeColor(bytes);
|
||||
if (bytes == null)
|
||||
{
|
||||
bytes = await ImageHelper.CreateTextPlaceholderBytesAsync(500, 500);
|
||||
token.ThrowIfCancellationRequested();
|
||||
}
|
||||
|
||||
using var stream = new InMemoryRandomAccessStream();
|
||||
await stream.WriteAsync(bytes.AsBuffer());
|
||||
token.ThrowIfCancellationRequested();
|
||||
bytes = ImageHelper.MakeSquareWithThemeColor(bytes);
|
||||
|
||||
var decoder = await BitmapDecoder.CreateAsync(stream);
|
||||
token.ThrowIfCancellationRequested();
|
||||
using var stream = new InMemoryRandomAccessStream();
|
||||
await stream.WriteAsync(bytes.AsBuffer());
|
||||
token.ThrowIfCancellationRequested();
|
||||
|
||||
var albumArtSwBitmap = await decoder.GetSoftwareBitmapAsync(BitmapPixelFormat.Rgba8, BitmapAlphaMode.Premultiplied);
|
||||
token.ThrowIfCancellationRequested();
|
||||
var decoder = await BitmapDecoder.CreateAsync(stream);
|
||||
token.ThrowIfCancellationRequested();
|
||||
|
||||
var albumArtLightAccentColor = ImageHelper.GetAccentColorsFromByte(bytes, 1, false).FirstOrDefault();
|
||||
var albumArtDarkAccentColor = ImageHelper.GetAccentColorsFromByte(bytes, 1, true).FirstOrDefault();
|
||||
var albumArtSwBitmap = await decoder.GetSoftwareBitmapAsync(BitmapPixelFormat.Rgba8, BitmapAlphaMode.Premultiplied);
|
||||
token.ThrowIfCancellationRequested();
|
||||
|
||||
var albumArtLightAccentColor = ImageHelper.GetAccentColorsFromByte(bytes, 1, false).FirstOrDefault();
|
||||
var albumArtDarkAccentColor = ImageHelper.GetAccentColorsFromByte(bytes, 1, true).FirstOrDefault();
|
||||
|
||||
_dispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, () =>
|
||||
{
|
||||
AlbumArtChangedChanged?.Invoke(this, new AlbumArtChangedEventArgs(null, albumArtSwBitmap, albumArtLightAccentColor, albumArtDarkAccentColor));
|
||||
});
|
||||
|
||||
_dispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, () =>
|
||||
{
|
||||
AlbumArtChangedChanged?.Invoke(this, new AlbumArtChangedEventArgs(null, albumArtSwBitmap, albumArtLightAccentColor, albumArtDarkAccentColor));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -367,7 +439,7 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
{
|
||||
try
|
||||
{
|
||||
_sse = new EventSourceReader(new Uri($"{_settingsService.LXMusicServer}{Constants.LXMusic.QuerySuffix}")).Start();
|
||||
_sse = new EventSourceReader(new Uri($"{_settingsService.AppSettings.GeneralSettings.LXMusicServer}{Constants.LXMusic.QuerySuffix}")).Start();
|
||||
_sse.MessageReceived += Sse_MessageReceived;
|
||||
_sse.Disconnected += Sse_Disconnected;
|
||||
}
|
||||
@@ -470,30 +542,48 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
}
|
||||
}
|
||||
|
||||
public void Receive(PropertyChangedMessage<ObservableCollection<MediaSourceProviderInfo>> message)
|
||||
public MediaSourceProviderInfo? GetCurrentMediaSourceProviderInfo()
|
||||
{
|
||||
if (message.Sender is SettingsPageViewModel)
|
||||
return _settingsService.AppSettings.MediaSourceProvidersInfo.Where(x => x.Provider == _cachedSongInfo?.SourceAppUserModelId)?.FirstOrDefault();
|
||||
}
|
||||
|
||||
public void Receive(PropertyChangedMessage<bool> message)
|
||||
{
|
||||
if (message.Sender is MediaSourceProviderInfo)
|
||||
{
|
||||
if (message.PropertyName == nameof(SettingsPageViewModel.MediaSourceProvidersInfo))
|
||||
if (message.PropertyName == nameof(MediaSourceProviderInfo.IsEnabled))
|
||||
{
|
||||
_mediaSourceProvidersInfo = [.. message.NewValue];
|
||||
MediaManager_OnFocusedSessionChanged(null);
|
||||
}
|
||||
}
|
||||
else if (message.Sender is AlbumArtSearchProviderInfo)
|
||||
{
|
||||
if (message.PropertyName == nameof(AlbumArtSearchProviderInfo.IsEnabled))
|
||||
{
|
||||
UpdateAlbumArtRelated();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public async void Receive(PropertyChangedMessage<ObservableCollection<AlbumArtSearchProviderInfo>> message)
|
||||
public void Receive(PropertyChangedMessage<FullyObservableCollection<AlbumArtSearchProviderInfo>> message)
|
||||
{
|
||||
if (message.Sender is SettingsPageViewModel)
|
||||
}
|
||||
|
||||
public void Receive(PropertyChangedMessage<List<string>> message)
|
||||
{
|
||||
if (message.Sender is GeneralSettings)
|
||||
{
|
||||
if (message.PropertyName == nameof(SettingsPageViewModel.AlbumArtSearchProvidersInfo))
|
||||
if (message.PropertyName == nameof(GeneralSettings.PlayOrPauseShortcut))
|
||||
{
|
||||
// Album art search providers info changed, re-fetch album art
|
||||
_logger.LogInformation("Album art search providers info changed, refreshing album art.");
|
||||
await _albumArtRefreshRunner.RunAsync(async tokne =>
|
||||
{
|
||||
await UpdateAlbumArtRelated(tokne);
|
||||
});
|
||||
UpdatePlayOrPauseSongShortcut();
|
||||
}
|
||||
else if (message.PropertyName == nameof(GeneralSettings.PreviousSongShortcut))
|
||||
{
|
||||
UpdatePreviousSongShortcut();
|
||||
}
|
||||
else if (message.PropertyName == nameof(GeneralSettings.NextSongShortcut))
|
||||
{
|
||||
UpdateNextSongShortcut();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
using System.Collections.Generic;
|
||||
using BetterLyrics.WinUI3.Enums;
|
||||
using BetterLyrics.WinUI3.Models;
|
||||
using BetterLyrics.WinUI3.Models.Settings;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Windows.UI;
|
||||
|
||||
@@ -10,104 +11,10 @@ namespace BetterLyrics.WinUI3.Services.SettingsService
|
||||
{
|
||||
public interface ISettingsService
|
||||
{
|
||||
AppSettings AppSettings { get; set; }
|
||||
// App behavior
|
||||
|
||||
AutoStartWindowType AutoStartWindowType { get; set; }
|
||||
|
||||
int CoverImageRadius { get; set; }
|
||||
|
||||
int CoverOverlayBlurAmount { get; set; }
|
||||
int CoverOverlayOpacity { get; set; }
|
||||
bool IsDynamicCoverOverlayEnabled { get; set; }
|
||||
int CoverAcrylicEffectAmount { get; set; }
|
||||
bool IsFanLyricsEnabled { get; set; }
|
||||
bool IsFirstRun { get; set; }
|
||||
bool IsLyricsGlowEffectEnabled { get; set; }
|
||||
Language Language { get; set; }
|
||||
int DesktopWindowLeft { get; set; }
|
||||
int DesktopWindowTop { get; set; }
|
||||
int DesktopWindowWidth { get; set; }
|
||||
int DesktopWindowHeight { get; set; }
|
||||
|
||||
int StandardWindowWidth { get; set; }
|
||||
int StandardWindowHeight { get; set; }
|
||||
int StandardWindowLeft { get; set; }
|
||||
int StandardWindowTop { get; set; }
|
||||
|
||||
bool AutoLockOnDesktopMode { get; set; }
|
||||
|
||||
string LibreTranslateServer { get; set; }
|
||||
int SelectedTargetLanguageIndex { get; set; }
|
||||
int PositionOffset { get; set; }
|
||||
// Lyrics lib
|
||||
|
||||
List<LocalMediaFolder> LocalMediaFolders { get; set; }
|
||||
|
||||
// Lyrics style and effetc
|
||||
|
||||
TextAlignmentType LyricsAlignmentType { get; set; }
|
||||
TextAlignmentType SongInfoAlignmentType { get; set; }
|
||||
|
||||
int LyricsBlurAmount { get; set; }
|
||||
|
||||
Color LyricsCustomBgFontColor { get; set; }
|
||||
Color LyricsCustomFgFontColor { get; set; }
|
||||
Color LyricsCustomStrokeFontColor { get; set; }
|
||||
|
||||
int LyricsBgFontOpacity { get; set; }
|
||||
|
||||
LyricsFontColorType LyricsBgFontColorType { get; set; }
|
||||
LyricsFontColorType LyricsFgFontColorType { get; set; }
|
||||
LyricsFontColorType LyricsStrokeFontColorType { get; set; }
|
||||
|
||||
int LyricsStandardFontSize { get; set; }
|
||||
int LyricsDockFontSize { get; set; }
|
||||
int LyricsDesktopFontSize { get; set; }
|
||||
|
||||
ElementTheme LyricsBackgroundTheme { get; set; }
|
||||
|
||||
int LyricsFontStrokeWidth { get; set; }
|
||||
|
||||
LyricsFontWeight LyricsFontWeight { get; set; }
|
||||
|
||||
LineRenderingType LyricsGlowEffectScope { get; set; }
|
||||
LineRenderingType LyricsHighlightScope { get; set; }
|
||||
|
||||
bool IsLyricsFloatAnimationEnabled { get; set; }
|
||||
|
||||
float LyricsLineSpacingFactor { get; set; }
|
||||
|
||||
List<AlbumArtSearchProviderInfo> AlbumArtSearchProvidersInfo { get; set; }
|
||||
List<MediaSourceProviderInfo> MediaSourceProvidersInfo { get; set; }
|
||||
|
||||
EasingType LyricsScrollEasingType { get; set; }
|
||||
int LyricsScrollDuration { get; set; }
|
||||
|
||||
int LyricsVerticalEdgeOpacity { get; set; }
|
||||
|
||||
bool IgnoreFullscreenWindow { get; set; }
|
||||
|
||||
bool IsTranslationEnabled { get; set; }
|
||||
bool ShowTranslationOnly { get; set; }
|
||||
|
||||
LyricsDisplayType DisplayType { get; set; }
|
||||
|
||||
int LockHotKeyIndex { get; set; }
|
||||
bool IsImmersiveMode { get; set; }
|
||||
string LXMusicServer { get; set; }
|
||||
DockPlacement DockPlacement { get; set; }
|
||||
bool HideWindowWhenNotPlaying { get; set; }
|
||||
int DockWindowHeight { get; set; }
|
||||
int SelectedFontFamilyIndex { get; set; }
|
||||
string LyricsFontFamily { get; set; }
|
||||
bool IsDragEverywhereEnabled { get; set; }
|
||||
PlaybackOrder PlaybackOrder { get; set; }
|
||||
bool IsLibreTranslateEnabled { get; set; }
|
||||
string DockMonitorDeviceName { get; set; }
|
||||
|
||||
// LastFM
|
||||
string LastFMSessionKey { get; set; }
|
||||
|
||||
string LyricsTranslationSeparator { get; set; }
|
||||
bool ImportSettings(string importPath);
|
||||
void ExportSettings(string exportPath);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,708 +1,217 @@
|
||||
// 2025/6/23 by Zhe Fang
|
||||
|
||||
using BetterLyrics.WinUI3.Enums;
|
||||
using BetterLyrics.WinUI3.Extensions;
|
||||
using BetterLyrics.WinUI3.Helper;
|
||||
using BetterLyrics.WinUI3.Models;
|
||||
using BetterLyrics.WinUI3.Models.Settings;
|
||||
using BetterLyrics.WinUI3.Serialization;
|
||||
using CommunityToolkit.WinUI.Helpers;
|
||||
using Microsoft.UI;
|
||||
using Microsoft.UI.Xaml;
|
||||
using BetterLyrics.WinUI3.ViewModels;
|
||||
using BetterLyrics.WinUI3.Views;
|
||||
using CommunityToolkit.WinUI;
|
||||
using Microsoft.UI.Dispatching;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Windows.Media.Core;
|
||||
using Windows.Storage;
|
||||
using Windows.UI;
|
||||
using Windows.Globalization;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Services.SettingsService
|
||||
{
|
||||
public class SettingsService : ISettingsService
|
||||
// TODO 初始化时从文件读取到对象,后续独写操作先操纵对象,写入用 Debounce 写入文件
|
||||
// 新建一个 AppSettings 类
|
||||
public partial class SettingsService : BaseViewModel, ISettingsService
|
||||
{
|
||||
public const string LyricsCustomBgFontColorKey = "LyricsCustomBgFontColor";
|
||||
public const string LyricsCustomFgFontColorKey = "LyricsCustomFgFontColor";
|
||||
public const string LyricsCustomStrokeFontColorKey = "LyricsCustomStrokeFontColor";
|
||||
|
||||
// App behavior
|
||||
|
||||
private const string AutoStartWindowTypeKey = "AutoStartWindowType";
|
||||
|
||||
private const string CoverImageRadiusKey = "AlbumArtCornerRadius";
|
||||
private const string CoverOverlayBlurAmountKey = "CoverOverlayBlurAmount";
|
||||
private const string CoverOverlayOpacityKey = "CoverOverlayOpacity";
|
||||
private const string IsCoverOverlayEnabledKey = "IsCoverOverlayEnabled";
|
||||
|
||||
private const string CoverAcrylicEffectAmountKey = "CoverAcrylicEffectAmount";
|
||||
|
||||
private const string DesktopWindowLeftKey = "DesktopWindowLeft";
|
||||
private const string DesktopWindowTopKey = "DesktopWindowTop";
|
||||
private const string DesktopWindowWidthKey = "DesktopWindowWidth";
|
||||
private const string DesktopWindowHeightKey = "DesktopWindowHeight";
|
||||
|
||||
private const string StandardWindowLeftKey = "StandardWindowLeft";
|
||||
private const string StandardWindowTopKey = "StandardWindowTop";
|
||||
private const string StandardWindowWidthKey = "StandardWindowWidth";
|
||||
private const string StandardWindowHeightKey = "StandardWindowHeight";
|
||||
|
||||
private const string AutoLockOnDesktopModeKey = "AutoLockOnDesktopMode";
|
||||
private const string IsImmersiveModeKey = "IsImmersiveMode";
|
||||
|
||||
private const string IsDynamicCoverOverlayEnabledKey = "IsDynamicCoverOverlayEnabled";
|
||||
private const string IsFanLyricsEnabledKey = "IsFanLyricsEnabled";
|
||||
private const string IsFirstRunKey = "IsFirstRun";
|
||||
private const string IsLyricsGlowEffectEnabledKey = "IsLyricsGlowEffectEnabled";
|
||||
private const string LanguageKey = "Language";
|
||||
|
||||
private const string LocalMediaFoldersKey = "LocalLyricsFolders";
|
||||
private const string LyricsAlignmentTypeKey = "TextAlignmentType";
|
||||
private const string SongInfoAlignmentTypeKey = "SongInfoAlignmentType";
|
||||
private const string LyricsBlurAmountKey = "LyricsBlurAmount";
|
||||
|
||||
private const string LyricsBgFontColorTypeKey = "_lyricsBgFontColorType";
|
||||
private const string LyricsFgFontColorTypeKey = "LyricsFgFontColorType";
|
||||
private const string LyricsStrokeFontColorTypeKey = "LyricsStrokeFontColorType";
|
||||
|
||||
private const string LyricsFontStrokeWidthKey = "LyricsFontStrokeWidth";
|
||||
|
||||
// Lyrics font size
|
||||
private const string LyricsStandardFontSizeKey = "LyricsStandardFontSize";
|
||||
private const string LyricsDockFontSizeKey = "LyricsDockFontSize";
|
||||
private const string LyricsDesktopFontSizeKey = "LyricsDesktopFontSize";
|
||||
|
||||
private const string LyricsFontWeightKey = "LyricsFontWeightKey";
|
||||
private const string LyricsGlowEffectScopeKey = "LyricsGlowEffectScope";
|
||||
private const string LyricsHighlightSopeKey = "LyricsHighlightSope";
|
||||
private const string LyricsLineSpacingFactorKey = "LyricsLineSpacingFactor";
|
||||
private const string AlbumArtSearchProvidersInfoKey = "AlbumArtSearchProvidersInfo";
|
||||
private const string LyricsVerticalEdgeOpacityKey = "LyricsVerticalEdgeOpacity";
|
||||
|
||||
private const string MediaSourceProvidersInfoKey = "MediaSourceProvidersInfo";
|
||||
|
||||
// Translation
|
||||
private const string IsTranslationEnabledKey = "IsTranslationEnabled";
|
||||
private const string ShowTranslationOnlyKey = "ShowTranslationOnly";
|
||||
private const string IsLibreTranslateEnabledKey = "IsLibreTranslateEnabled";
|
||||
private const string LibreTranslateServerKey = "LibreTranslateServer";
|
||||
private const string SelectedTargetLanguageIndexKey = "SelectedTargetLanguageIndex";
|
||||
|
||||
// LX Music
|
||||
private const string LXMusicServerKey = "LXMusicServer";
|
||||
|
||||
private const string LyricsBackgroundThemeKey = "LyricsBackgroundTheme";
|
||||
private const string IgnoreFullscreenWindowKey = "IgnoreFullscreenWindow";
|
||||
private const string PreferredDisplayTypeKey = "PreferredDisplayTypeKey";
|
||||
|
||||
private const string LyricsScrollEasingTypeKey = "LyricsScrollEasingType";
|
||||
private const string LyricsScrollDurationKey = "LyricsScrollDuration";
|
||||
|
||||
private const string IsLyricsFloatAnimationEnabledKey = "IsLyricsFloatAnimationEnabled";
|
||||
|
||||
private const string PlaybackOrderKey = "PlaybackOrder";
|
||||
|
||||
private const string PositionOffsetKey = "PositionOffset";
|
||||
|
||||
private const string LockHotKeyIndexKey = "LockHotKeyIndex";
|
||||
private const string DockPlacementKey = "DockPlacement";
|
||||
private const string LyricsBgFontOpacityKey = "LyricsBgFontOpacity";
|
||||
private const string HideWindowWhenNotPlayingKey = "HideWindowWhenNotPlaying";
|
||||
private const string DockWindowHeightKey = "DockWindowHeight";
|
||||
|
||||
private const string SelectedFontFamilyIndexKey = "SelectedFontFamilyIndex";
|
||||
private const string LyricsFontFamilyKey = "LyricsFontFamily";
|
||||
private const string IsDragEverywhereEnabledKey = "IsDragEverywhereEnabled";
|
||||
|
||||
private const string DockMonitorDeviceNameKey = "DockMonitorDeviceName";
|
||||
|
||||
// LastFM
|
||||
private const string LastFMSessionKeyKey = "LastFMSessionKey";
|
||||
|
||||
private const string LyricsTranslationSeparatorKey = "LyricsTranslationSeparator";
|
||||
|
||||
private readonly ApplicationDataContainer _localSettings;
|
||||
public AppSettings AppSettings { get; set; }
|
||||
|
||||
public SettingsService()
|
||||
{
|
||||
_localSettings = ApplicationData.Current.LocalSettings;
|
||||
AppSettings = ReadAppSettings();
|
||||
|
||||
SetDefault(IsFirstRunKey, true);
|
||||
// Lyrics lib
|
||||
SetDefault(LocalMediaFoldersKey, "[]");
|
||||
SetDefault(
|
||||
AlbumArtSearchProvidersInfoKey,
|
||||
System.Text.Json.JsonSerializer.Serialize(
|
||||
Enum.GetValues<AlbumArtSearchProvider>()
|
||||
.Select(p => new AlbumArtSearchProviderInfo(p, true))
|
||||
.ToList(),
|
||||
SourceGenerationContext.Default.ListAlbumArtSearchProviderInfo
|
||||
)
|
||||
);
|
||||
if (AlbumArtSearchProvidersInfo.Count != Enum.GetValues<AlbumArtSearchProvider>().Length)
|
||||
{
|
||||
AlbumArtSearchProvidersInfo = Enum.GetValues<AlbumArtSearchProvider>()
|
||||
.Select(p => new AlbumArtSearchProviderInfo(
|
||||
p,
|
||||
AlbumArtSearchProvidersInfo
|
||||
.Where(x => x.Provider == p)
|
||||
.FirstOrDefault()
|
||||
?.IsEnabled ?? true
|
||||
))
|
||||
.ToList();
|
||||
}
|
||||
AppSettings.PropertyChanged += AppSettings_PropertyChanged;
|
||||
|
||||
SetDefault(MediaSourceProvidersInfoKey, "[]");
|
||||
var tmp = MediaSourceProvidersInfo;
|
||||
for (int i = 0; i < tmp.Count; i++)
|
||||
AppSettings.StandardModeSettings.PropertyChanged += AppSettings_PropertyChanged;
|
||||
AppSettings.DesktopModeSettings.PropertyChanged += AppSettings_PropertyChanged;
|
||||
AppSettings.DockModeSettings.PropertyChanged += AppSettings_PropertyChanged;
|
||||
AppSettings.PictureInPictureModeSettings.PropertyChanged += AppSettings_PropertyChanged;
|
||||
|
||||
AppSettings.StandardLyricsStyleSettings.PropertyChanged += AppSettings_PropertyChanged;
|
||||
AppSettings.DesktopLyricsStyleSettings.PropertyChanged += AppSettings_PropertyChanged;
|
||||
AppSettings.DockLyricsStyleSettings.PropertyChanged += AppSettings_PropertyChanged;
|
||||
AppSettings.PictureInPictureLyricsStyleSettings.PropertyChanged += AppSettings_PropertyChanged;
|
||||
|
||||
AppSettings.StandardLyricsEffectSettings.PropertyChanged += AppSettings_PropertyChanged;
|
||||
AppSettings.DesktopLyricsEffectSettings.PropertyChanged += AppSettings_PropertyChanged;
|
||||
AppSettings.DockLyricsEffectSettings.PropertyChanged += AppSettings_PropertyChanged;
|
||||
AppSettings.PictureInPictureLyricsEffectSettings.PropertyChanged += AppSettings_PropertyChanged;
|
||||
|
||||
AppSettings.LyricsBackgroundSettings.PropertyChanged += AppSettings_PropertyChanged;
|
||||
AppSettings.AlbumArtLayoutSettings.PropertyChanged += AppSettings_PropertyChanged;
|
||||
AppSettings.TranslationSettings.PropertyChanged += AppSettings_PropertyChanged;
|
||||
AppSettings.GeneralSettings.PropertyChanged += AppSettings_PropertyChanged;
|
||||
AppSettings.MusicGallerySettings.PropertyChanged += AppSettings_PropertyChanged;
|
||||
AppSettings.AdvancedSettings.PropertyChanged += AppSettings_PropertyChanged;
|
||||
|
||||
AppSettings.MediaSourceProvidersInfo.CollectionChanged += AppSettings_CollectionChanged;
|
||||
AppSettings.MediaSourceProvidersInfo.ItemPropertyChanged += AppSettings_ItemPropertyChanged;
|
||||
|
||||
AppSettings.LocalMediaFolders.CollectionChanged += AppSettings_CollectionChanged;
|
||||
AppSettings.LocalMediaFolders.ItemPropertyChanged += AppSettings_ItemPropertyChanged;
|
||||
|
||||
AppSettings.Version = MetadataHelper.AppVersion;
|
||||
|
||||
EnsureMediaSourceProvidersInfo();
|
||||
}
|
||||
|
||||
private void EnsureMediaSourceProvidersInfo()
|
||||
{
|
||||
// 确保当 LyricsSearchProvider 和 AlbumArtSearchProvider 枚举更新时,AppSettings 中的相关信息也能更新
|
||||
foreach (var x in AppSettings.MediaSourceProvidersInfo)
|
||||
{
|
||||
var mediaSource = tmp[i];
|
||||
if (mediaSource.LyricsSearchProvidersInfo == null || mediaSource.LyricsSearchProvidersInfo.Count != Enum.GetValues<LyricsSearchProvider>().Length)
|
||||
// 更新 LyricsSearchProvidersInfo
|
||||
foreach (var p in Enum.GetValues<LyricsSearchProvider>())
|
||||
{
|
||||
mediaSource.LyricsSearchProvidersInfo = [..Enum.GetValues<LyricsSearchProvider>()
|
||||
.Select(p => new LyricsSearchProviderInfo(
|
||||
p,
|
||||
mediaSource.LyricsSearchProvidersInfo?
|
||||
.Where(x => x.Provider == p)
|
||||
.FirstOrDefault()
|
||||
?.IsEnabled ?? true
|
||||
))];
|
||||
var item = x.LyricsSearchProvidersInfo.FirstOrDefault(i => i.Provider == p);
|
||||
if (item == null)
|
||||
{
|
||||
x.LyricsSearchProvidersInfo.Add(new LyricsSearchProviderInfo(p, true));
|
||||
}
|
||||
// 可根据需要更新 item.IsEnabled
|
||||
}
|
||||
// 移除多余项
|
||||
for (int i = x.LyricsSearchProvidersInfo.Count - 1; i >= 0; i--)
|
||||
{
|
||||
if (!Enum.IsDefined(typeof(LyricsSearchProvider), x.LyricsSearchProvidersInfo[i].Provider))
|
||||
x.LyricsSearchProvidersInfo.RemoveAt(i);
|
||||
}
|
||||
|
||||
// 更新 AlbumArtSearchProvidersInfo
|
||||
foreach (var p in Enum.GetValues<AlbumArtSearchProvider>())
|
||||
{
|
||||
var item = x.AlbumArtSearchProvidersInfo.FirstOrDefault(i => i.Provider == p);
|
||||
if (item == null)
|
||||
{
|
||||
x.AlbumArtSearchProvidersInfo.Add(new AlbumArtSearchProviderInfo(p, true));
|
||||
}
|
||||
// 可根据需要更新 item.IsEnabled
|
||||
}
|
||||
for (int i = x.AlbumArtSearchProvidersInfo.Count - 1; i >= 0; i--)
|
||||
{
|
||||
if (!Enum.IsDefined(typeof(AlbumArtSearchProvider), x.AlbumArtSearchProvidersInfo[i].Provider))
|
||||
x.AlbumArtSearchProvidersInfo.RemoveAt(i);
|
||||
}
|
||||
}
|
||||
MediaSourceProvidersInfo = tmp;
|
||||
|
||||
// App appearance
|
||||
SetDefault(LanguageKey, (int)Language.FollowSystem);
|
||||
|
||||
SetDefault(DesktopWindowHeightKey, 600);
|
||||
SetDefault(DesktopWindowLeftKey, 200);
|
||||
SetDefault(DesktopWindowTopKey, 200);
|
||||
SetDefault(DesktopWindowWidthKey, 1200);
|
||||
|
||||
SetDefault(StandardWindowHeightKey, 800);
|
||||
SetDefault(StandardWindowLeftKey, 200);
|
||||
SetDefault(StandardWindowTopKey, 200);
|
||||
SetDefault(StandardWindowWidthKey, 1600);
|
||||
|
||||
SetDefault(AutoLockOnDesktopModeKey, false);
|
||||
SetDefault(IsImmersiveModeKey, false);
|
||||
// App behavior
|
||||
SetDefault(AutoStartWindowTypeKey, (int)AutoStartWindowType.StandardMode);
|
||||
// Album art
|
||||
SetDefault(IsCoverOverlayEnabledKey, true);
|
||||
SetDefault(IsDynamicCoverOverlayEnabledKey, true);
|
||||
SetDefault(CoverOverlayOpacityKey, 100); // 100 % = 1.0
|
||||
SetDefault(CoverOverlayBlurAmountKey, 100);
|
||||
SetDefault(CoverImageRadiusKey, 12); // 12 %
|
||||
SetDefault(CoverAcrylicEffectAmountKey, 0);
|
||||
// Lyrics
|
||||
SetDefault(LyricsAlignmentTypeKey, (int)TextAlignmentType.Left);
|
||||
SetDefault(SongInfoAlignmentTypeKey, (int)TextAlignmentType.Left);
|
||||
SetDefault(LyricsFontWeightKey, (int)LyricsFontWeight.Bold);
|
||||
SetDefault(LyricsBlurAmountKey, 5);
|
||||
|
||||
SetDefault(LyricsBackgroundThemeKey, (int)ElementTheme.Dark);
|
||||
|
||||
SetDefault(LyricsBgFontColorTypeKey, (int)LyricsFontColorType.AdaptiveGrayed);
|
||||
SetDefault(LyricsFgFontColorTypeKey, (int)LyricsFontColorType.AdaptiveGrayed);
|
||||
SetDefault(LyricsStrokeFontColorTypeKey, (int)LyricsFontColorType.AdaptiveGrayed);
|
||||
|
||||
SetDefault(LyricsCustomBgFontColorKey, Colors.White.ToInt());
|
||||
SetDefault(LyricsCustomFgFontColorKey, Colors.White.ToInt());
|
||||
SetDefault(LyricsCustomStrokeFontColorKey, Colors.White.ToInt());
|
||||
|
||||
SetDefault(LyricsStandardFontSizeKey, 32);
|
||||
SetDefault(LyricsDockFontSizeKey, 16);
|
||||
SetDefault(LyricsDesktopFontSizeKey, 28);
|
||||
|
||||
SetDefault(LyricsLineSpacingFactorKey, 0.5f);
|
||||
SetDefault(LyricsVerticalEdgeOpacityKey, 0);
|
||||
SetDefault(IsLyricsGlowEffectEnabledKey, true);
|
||||
SetDefault(LyricsGlowEffectScopeKey, (int)LineRenderingType.CurrentChar);
|
||||
SetDefault(LyricsHighlightSopeKey, (int)LineRenderingType.LineStartToCurrentChar);
|
||||
SetDefault(IsFanLyricsEnabledKey, false);
|
||||
|
||||
SetDefault(LibreTranslateServerKey, "");
|
||||
SetDefault(IsLibreTranslateEnabledKey, false);
|
||||
SetDefault(IsTranslationEnabledKey, true);
|
||||
SetDefault(ShowTranslationOnlyKey, false);
|
||||
SetDefault(SelectedTargetLanguageIndexKey, LanguageHelper.GetDefaultTargetLanguageIndex());
|
||||
|
||||
SetDefault(LXMusicServerKey, "");
|
||||
|
||||
SetDefault(LyricsFontStrokeWidthKey, 3);
|
||||
SetDefault(IgnoreFullscreenWindowKey, false);
|
||||
SetDefault(PreferredDisplayTypeKey, (int)LyricsDisplayType.SplitView);
|
||||
|
||||
SetDefault(LyricsScrollEasingTypeKey, (int)EasingType.EaseInOutSine);
|
||||
SetDefault(LyricsScrollDurationKey, 500); // 500ms
|
||||
|
||||
SetDefault(IsLyricsFloatAnimationEnabledKey, true);
|
||||
|
||||
SetDefault(PositionOffsetKey, 0);
|
||||
SetDefault(LockHotKeyIndexKey, 'U' - 'A');
|
||||
SetDefault(DockPlacementKey, (int)DockPlacement.Top);
|
||||
SetDefault(LyricsBgFontOpacityKey, 30); // 30%
|
||||
SetDefault(HideWindowWhenNotPlayingKey, false);
|
||||
SetDefault(DockWindowHeightKey, 64); // 64px
|
||||
SetDefault(SelectedFontFamilyIndexKey, 0);
|
||||
SetDefault(LyricsFontFamilyKey, FontHelper.SystemFontFamilies.ElementAtOrDefault(0));
|
||||
SetDefault(IsDragEverywhereEnabledKey, false);
|
||||
SetDefault(DockMonitorDeviceNameKey, MonitorHelper.GetPrimaryMonitorDeviceName());
|
||||
|
||||
SetDefault(LastFMSessionKeyKey, "");
|
||||
|
||||
SetDefault(LyricsTranslationSeparatorKey, StringHelper.NewLine);
|
||||
}
|
||||
|
||||
public bool IsDragEverywhereEnabled
|
||||
{
|
||||
get => GetValue<bool>(IsDragEverywhereEnabledKey);
|
||||
set => SetValue(IsDragEverywhereEnabledKey, value);
|
||||
}
|
||||
|
||||
public string LyricsFontFamily
|
||||
{
|
||||
get => GetValue<string>(LyricsFontFamilyKey)!;
|
||||
set => SetValue(LyricsFontFamilyKey, value);
|
||||
}
|
||||
|
||||
public int SelectedFontFamilyIndex
|
||||
{
|
||||
get => GetValue<int>(SelectedFontFamilyIndexKey);
|
||||
set => SetValue(SelectedFontFamilyIndexKey, value);
|
||||
}
|
||||
|
||||
public bool HideWindowWhenNotPlaying
|
||||
{
|
||||
get => GetValue<bool>(HideWindowWhenNotPlayingKey);
|
||||
set => SetValue(HideWindowWhenNotPlayingKey, value);
|
||||
}
|
||||
|
||||
public int DockWindowHeight
|
||||
{
|
||||
get => GetValue<int>(DockWindowHeightKey);
|
||||
set => SetValue(DockWindowHeightKey, value);
|
||||
}
|
||||
|
||||
public int LyricsBgFontOpacity
|
||||
{
|
||||
get => GetValue<int>(LyricsBgFontOpacityKey);
|
||||
set => SetValue(LyricsBgFontOpacityKey, value);
|
||||
}
|
||||
|
||||
public bool ShowTranslationOnly
|
||||
{
|
||||
get => GetValue<bool>(ShowTranslationOnlyKey);
|
||||
set => SetValue(ShowTranslationOnlyKey, value);
|
||||
}
|
||||
|
||||
public DockPlacement DockPlacement
|
||||
{
|
||||
get => (DockPlacement)GetValue<int>(DockPlacementKey);
|
||||
set => SetValue(DockPlacementKey, (int)value);
|
||||
}
|
||||
|
||||
public int LockHotKeyIndex
|
||||
{
|
||||
get => GetValue<int>(LockHotKeyIndexKey);
|
||||
set => SetValue(LockHotKeyIndexKey, value);
|
||||
}
|
||||
|
||||
public EasingType LyricsScrollEasingType
|
||||
{
|
||||
get => (EasingType)GetValue<int>(LyricsScrollEasingTypeKey);
|
||||
set => SetValue(LyricsScrollEasingTypeKey, (int)value);
|
||||
}
|
||||
|
||||
public int LyricsScrollDuration
|
||||
{
|
||||
get => GetValue<int>(LyricsScrollDurationKey);
|
||||
set => SetValue(LyricsScrollDurationKey, value);
|
||||
}
|
||||
|
||||
public LyricsDisplayType DisplayType
|
||||
{
|
||||
get => (LyricsDisplayType)GetValue<int>(PreferredDisplayTypeKey);
|
||||
set => SetValue(PreferredDisplayTypeKey, (int)value);
|
||||
}
|
||||
|
||||
public ElementTheme LyricsBackgroundTheme
|
||||
private void AppSettings_ItemPropertyChanged(object? sender, ItemPropertyChangedEventArgs e)
|
||||
{
|
||||
get => (ElementTheme)GetValue<int>(LyricsBackgroundThemeKey);
|
||||
set => SetValue(LyricsBackgroundThemeKey, (int)value);
|
||||
WriteAppSettingsDebounce();
|
||||
}
|
||||
|
||||
public AutoStartWindowType AutoStartWindowType
|
||||
private void AppSettings_CollectionChanged(object? sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
get => (AutoStartWindowType)GetValue<int>(AutoStartWindowTypeKey);
|
||||
set => SetValue(AutoStartWindowTypeKey, (int)value);
|
||||
WriteAppSettingsDebounce();
|
||||
}
|
||||
|
||||
public int DesktopWindowLeft
|
||||
{
|
||||
get => GetValue<int>(DesktopWindowLeftKey);
|
||||
set => SetValue(DesktopWindowLeftKey, value);
|
||||
}
|
||||
|
||||
public int DesktopWindowTop
|
||||
{
|
||||
get => GetValue<int>(DesktopWindowTopKey);
|
||||
set => SetValue(DesktopWindowTopKey, value);
|
||||
}
|
||||
|
||||
public int DesktopWindowWidth
|
||||
{
|
||||
get => GetValue<int>(DesktopWindowWidthKey);
|
||||
set => SetValue(DesktopWindowWidthKey, value);
|
||||
}
|
||||
|
||||
public int DesktopWindowHeight
|
||||
{
|
||||
get => GetValue<int>(DesktopWindowHeightKey);
|
||||
set => SetValue(DesktopWindowHeightKey, value);
|
||||
}
|
||||
|
||||
public int StandardWindowLeft
|
||||
{
|
||||
get => GetValue<int>(StandardWindowLeftKey);
|
||||
set => SetValue(StandardWindowLeftKey, value);
|
||||
}
|
||||
|
||||
public int StandardWindowTop
|
||||
{
|
||||
get => GetValue<int>(StandardWindowTopKey);
|
||||
set => SetValue(StandardWindowTopKey, value);
|
||||
}
|
||||
|
||||
public int StandardWindowWidth
|
||||
{
|
||||
get => GetValue<int>(StandardWindowWidthKey);
|
||||
set => SetValue(StandardWindowWidthKey, value);
|
||||
}
|
||||
|
||||
public int StandardWindowHeight
|
||||
{
|
||||
get => GetValue<int>(StandardWindowHeightKey);
|
||||
set => SetValue(StandardWindowHeightKey, value);
|
||||
}
|
||||
|
||||
public bool AutoLockOnDesktopMode
|
||||
{
|
||||
get => GetValue<bool>(AutoLockOnDesktopModeKey);
|
||||
set => SetValue(AutoLockOnDesktopModeKey, value);
|
||||
}
|
||||
|
||||
public int CoverImageRadius
|
||||
{
|
||||
get => GetValue<int>(CoverImageRadiusKey);
|
||||
set => SetValue(CoverImageRadiusKey, value);
|
||||
}
|
||||
|
||||
public int CoverOverlayBlurAmount
|
||||
{
|
||||
get => GetValue<int>(CoverOverlayBlurAmountKey);
|
||||
set => SetValue(CoverOverlayBlurAmountKey, value);
|
||||
}
|
||||
|
||||
public int CoverOverlayOpacity
|
||||
{
|
||||
get => GetValue<int>(CoverOverlayOpacityKey);
|
||||
set => SetValue(CoverOverlayOpacityKey, value);
|
||||
}
|
||||
|
||||
public bool IsDynamicCoverOverlayEnabled
|
||||
{
|
||||
get => GetValue<bool>(IsDynamicCoverOverlayEnabledKey);
|
||||
set => SetValue(IsDynamicCoverOverlayEnabledKey, value);
|
||||
}
|
||||
|
||||
public int CoverAcrylicEffectAmount
|
||||
{
|
||||
get => GetValue<int>(CoverAcrylicEffectAmountKey);
|
||||
set => SetValue(CoverAcrylicEffectAmountKey, value);
|
||||
}
|
||||
|
||||
public bool IsFanLyricsEnabled
|
||||
{
|
||||
get => GetValue<bool>(IsFanLyricsEnabledKey);
|
||||
set => SetValue(IsFanLyricsEnabledKey, value);
|
||||
}
|
||||
|
||||
public bool IsFirstRun
|
||||
{
|
||||
get => GetValue<bool>(IsFirstRunKey);
|
||||
set => SetValue(IsFirstRunKey, value);
|
||||
}
|
||||
|
||||
public bool IsLyricsGlowEffectEnabled
|
||||
{
|
||||
get => GetValue<bool>(IsLyricsGlowEffectEnabledKey);
|
||||
set => SetValue(IsLyricsGlowEffectEnabledKey, value);
|
||||
}
|
||||
|
||||
public Language Language
|
||||
{
|
||||
get => (Language)GetValue<int>(LanguageKey);
|
||||
set => SetValue(LanguageKey, (int)value);
|
||||
}
|
||||
|
||||
public List<LocalMediaFolder> LocalMediaFolders
|
||||
{
|
||||
get =>
|
||||
System.Text.Json.JsonSerializer.Deserialize(
|
||||
GetValue<string>(LocalMediaFoldersKey) ?? "[]",
|
||||
SourceGenerationContext.Default.ListLocalMediaFolder
|
||||
)!;
|
||||
set =>
|
||||
SetValue(
|
||||
LocalMediaFoldersKey,
|
||||
System.Text.Json.JsonSerializer.Serialize(
|
||||
value,
|
||||
SourceGenerationContext.Default.ListLocalMediaFolder
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public TextAlignmentType LyricsAlignmentType
|
||||
{
|
||||
get => (TextAlignmentType)GetValue<int>(LyricsAlignmentTypeKey);
|
||||
set => SetValue(LyricsAlignmentTypeKey, (int)value);
|
||||
}
|
||||
|
||||
public TextAlignmentType SongInfoAlignmentType
|
||||
{
|
||||
get => (TextAlignmentType)GetValue<int>(SongInfoAlignmentTypeKey);
|
||||
set => SetValue(SongInfoAlignmentTypeKey, (int)value);
|
||||
}
|
||||
|
||||
public int LyricsBlurAmount
|
||||
{
|
||||
get => GetValue<int>(LyricsBlurAmountKey);
|
||||
set => SetValue(LyricsBlurAmountKey, value);
|
||||
}
|
||||
|
||||
public Color LyricsCustomBgFontColor
|
||||
{
|
||||
get => GetValue<int>(LyricsCustomBgFontColorKey)!.ToColor();
|
||||
set => SetValue(LyricsCustomBgFontColorKey, value.ToInt());
|
||||
}
|
||||
|
||||
public Color LyricsCustomFgFontColor
|
||||
{
|
||||
get => GetValue<int>(LyricsCustomFgFontColorKey)!.ToColor();
|
||||
set => SetValue(LyricsCustomFgFontColorKey, value.ToInt());
|
||||
}
|
||||
|
||||
public Color LyricsCustomStrokeFontColor
|
||||
{
|
||||
get => GetValue<int>(LyricsCustomStrokeFontColorKey)!.ToColor();
|
||||
set => SetValue(LyricsCustomStrokeFontColorKey, value.ToInt());
|
||||
}
|
||||
|
||||
public LyricsFontColorType LyricsBgFontColorType
|
||||
{
|
||||
get => (LyricsFontColorType)GetValue<int>(LyricsBgFontColorTypeKey);
|
||||
set => SetValue(LyricsBgFontColorTypeKey, (int)value);
|
||||
}
|
||||
|
||||
public LyricsFontColorType LyricsFgFontColorType
|
||||
{
|
||||
get => (LyricsFontColorType)GetValue<int>(LyricsFgFontColorTypeKey);
|
||||
set => SetValue(LyricsFgFontColorTypeKey, (int)value);
|
||||
}
|
||||
|
||||
public LyricsFontColorType LyricsStrokeFontColorType
|
||||
{
|
||||
get => (LyricsFontColorType)GetValue<int>(LyricsStrokeFontColorTypeKey);
|
||||
set => SetValue(LyricsStrokeFontColorTypeKey, (int)value);
|
||||
}
|
||||
|
||||
public int LyricsFontStrokeWidth
|
||||
{
|
||||
get => GetValue<int>(LyricsFontStrokeWidthKey);
|
||||
set => SetValue(LyricsFontStrokeWidthKey, value);
|
||||
}
|
||||
|
||||
public int LyricsStandardFontSize
|
||||
{
|
||||
get => GetValue<int>(LyricsStandardFontSizeKey);
|
||||
set => SetValue(LyricsStandardFontSizeKey, value);
|
||||
}
|
||||
|
||||
public int LyricsDockFontSize
|
||||
{
|
||||
get => GetValue<int>(LyricsDockFontSizeKey);
|
||||
set => SetValue(LyricsDockFontSizeKey, value);
|
||||
}
|
||||
|
||||
public int LyricsDesktopFontSize
|
||||
{
|
||||
get => GetValue<int>(LyricsDesktopFontSizeKey);
|
||||
set => SetValue(LyricsDesktopFontSizeKey, value);
|
||||
}
|
||||
|
||||
public LyricsFontWeight LyricsFontWeight
|
||||
{
|
||||
get => (LyricsFontWeight)GetValue<int>(LyricsFontWeightKey);
|
||||
set => SetValue(LyricsFontWeightKey, (int)value);
|
||||
}
|
||||
|
||||
public LineRenderingType LyricsGlowEffectScope
|
||||
{
|
||||
get => (LineRenderingType)GetValue<int>(LyricsGlowEffectScopeKey);
|
||||
set => SetValue(LyricsGlowEffectScopeKey, (int)value);
|
||||
}
|
||||
|
||||
public LineRenderingType LyricsHighlightScope
|
||||
{
|
||||
get => (LineRenderingType)GetValue<int>(LyricsHighlightSopeKey);
|
||||
set => SetValue(LyricsHighlightSopeKey, (int)value);
|
||||
}
|
||||
|
||||
public float LyricsLineSpacingFactor
|
||||
{
|
||||
get => GetValue<float>(LyricsLineSpacingFactorKey);
|
||||
set => SetValue(LyricsLineSpacingFactorKey, value);
|
||||
}
|
||||
|
||||
public List<AlbumArtSearchProviderInfo> AlbumArtSearchProvidersInfo
|
||||
{
|
||||
get =>
|
||||
System.Text.Json.JsonSerializer.Deserialize(
|
||||
GetValue<string>(AlbumArtSearchProvidersInfoKey) ?? "[]",
|
||||
SourceGenerationContext.Default.ListAlbumArtSearchProviderInfo
|
||||
)!;
|
||||
set =>
|
||||
SetValue(
|
||||
AlbumArtSearchProvidersInfoKey,
|
||||
System.Text.Json.JsonSerializer.Serialize(
|
||||
value,
|
||||
SourceGenerationContext.Default.ListAlbumArtSearchProviderInfo
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public List<MediaSourceProviderInfo> MediaSourceProvidersInfo
|
||||
{
|
||||
get =>
|
||||
System.Text.Json.JsonSerializer.Deserialize(
|
||||
GetValue<string>(MediaSourceProvidersInfoKey) ?? "[]",
|
||||
SourceGenerationContext.Default.ListMediaSourceProviderInfo
|
||||
)!;
|
||||
set =>
|
||||
SetValue(
|
||||
MediaSourceProvidersInfoKey,
|
||||
System.Text.Json.JsonSerializer.Serialize(
|
||||
value,
|
||||
SourceGenerationContext.Default.ListMediaSourceProviderInfo
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public int LyricsVerticalEdgeOpacity
|
||||
{
|
||||
get => GetValue<int>(LyricsVerticalEdgeOpacityKey);
|
||||
set => SetValue(LyricsVerticalEdgeOpacityKey, value);
|
||||
}
|
||||
|
||||
public string LibreTranslateServer
|
||||
{
|
||||
get => GetValue<string>(LibreTranslateServerKey)!;
|
||||
set => SetValue(LibreTranslateServerKey, value);
|
||||
}
|
||||
|
||||
public bool IsTranslationEnabled
|
||||
{
|
||||
get => GetValue<bool>(IsTranslationEnabledKey);
|
||||
set => SetValue(IsTranslationEnabledKey, value);
|
||||
}
|
||||
|
||||
public bool IsLibreTranslateEnabled
|
||||
{
|
||||
get => GetValue<bool>(IsLibreTranslateEnabledKey);
|
||||
set => SetValue(IsLibreTranslateEnabledKey, value);
|
||||
}
|
||||
|
||||
public int SelectedTargetLanguageIndex
|
||||
{
|
||||
get => GetValue<int>(SelectedTargetLanguageIndexKey);
|
||||
set => SetValue(SelectedTargetLanguageIndexKey, value);
|
||||
}
|
||||
|
||||
public string LXMusicServer
|
||||
{
|
||||
get => GetValue<string>(LXMusicServerKey)!;
|
||||
set => SetValue(LXMusicServerKey, value);
|
||||
}
|
||||
|
||||
public bool IgnoreFullscreenWindow
|
||||
{
|
||||
get => GetValue<bool>(IgnoreFullscreenWindowKey);
|
||||
set => SetValue(IgnoreFullscreenWindowKey, value);
|
||||
}
|
||||
|
||||
public bool IsLyricsFloatAnimationEnabled
|
||||
{
|
||||
get => GetValue<bool>(IsLyricsFloatAnimationEnabledKey);
|
||||
set => SetValue(IsLyricsFloatAnimationEnabledKey, value);
|
||||
}
|
||||
|
||||
public PlaybackOrder PlaybackOrder
|
||||
{
|
||||
get => (PlaybackOrder)GetValue<int>(PlaybackOrderKey);
|
||||
set => SetValue(PlaybackOrderKey, (int)value);
|
||||
}
|
||||
|
||||
public int PositionOffset
|
||||
{
|
||||
get => GetValue<int>(PositionOffsetKey);
|
||||
set => SetValue(PositionOffsetKey, value);
|
||||
}
|
||||
|
||||
public bool IsImmersiveMode
|
||||
{
|
||||
get => GetValue<bool>(IsImmersiveModeKey);
|
||||
set => SetValue(IsImmersiveModeKey, value);
|
||||
}
|
||||
|
||||
public string DockMonitorDeviceName
|
||||
{
|
||||
get => GetValue<string>(DockMonitorDeviceNameKey)!;
|
||||
set => SetValue(DockMonitorDeviceNameKey, value);
|
||||
}
|
||||
|
||||
// LastFM
|
||||
|
||||
public string LastFMSessionKey
|
||||
{
|
||||
get => GetValue<string>(LastFMSessionKeyKey)!;
|
||||
set => SetValue(LastFMSessionKeyKey, value);
|
||||
}
|
||||
|
||||
public string LyricsTranslationSeparator
|
||||
{
|
||||
get => GetValue<string>(LyricsTranslationSeparatorKey)!;
|
||||
set => SetValue(LyricsTranslationSeparatorKey, value);
|
||||
}
|
||||
|
||||
// Common methods
|
||||
|
||||
private T? GetValue<T>(string key)
|
||||
private void AppSettings_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
|
||||
{
|
||||
if (_localSettings.Values.TryGetValue(key, out object? value))
|
||||
switch (e.PropertyName)
|
||||
{
|
||||
return (T)value;
|
||||
case nameof(GeneralSettings.IsDragEverywhereEnabled):
|
||||
LyricsWindow? lyricsWindow = WindowHelper.GetWindowByWindowType<LyricsWindow>();
|
||||
lyricsWindow?.UpdateTitleBarArea();
|
||||
break;
|
||||
case nameof(GeneralSettings.Language):
|
||||
switch (AppSettings.GeneralSettings.Language)
|
||||
{
|
||||
case Enums.Language.FollowSystem:
|
||||
ApplicationLanguages.PrimaryLanguageOverride = "";
|
||||
break;
|
||||
case Enums.Language.English:
|
||||
ApplicationLanguages.PrimaryLanguageOverride = "en-US";
|
||||
break;
|
||||
case Enums.Language.SimplifiedChinese:
|
||||
ApplicationLanguages.PrimaryLanguageOverride = "zh-CN";
|
||||
break;
|
||||
case Enums.Language.TraditionalChinese:
|
||||
ApplicationLanguages.PrimaryLanguageOverride = "zh-TW";
|
||||
break;
|
||||
case Enums.Language.Japanese:
|
||||
ApplicationLanguages.PrimaryLanguageOverride = "ja-JP";
|
||||
break;
|
||||
case Enums.Language.Korean:
|
||||
ApplicationLanguages.PrimaryLanguageOverride = "ko-KR";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return default;
|
||||
WriteAppSettingsDebounce();
|
||||
}
|
||||
|
||||
private void SetDefault<T>(string key, T value)
|
||||
/// <summary>
|
||||
/// Export settings to specific folder
|
||||
/// </summary>
|
||||
/// <param name="exportPath">Target folder path (not file path)</param>
|
||||
public void ExportSettings(string exportPath)
|
||||
{
|
||||
if (_localSettings.Values.ContainsKey(key) && _localSettings.Values[key] is T)
|
||||
return;
|
||||
_localSettings.Values[key] = value;
|
||||
// 导出到文件
|
||||
var exportJson = System.Text.Json.JsonSerializer.Serialize(AppSettings, SourceGenerationContext.Default.AppSettings);
|
||||
File.WriteAllText(Path.Combine(exportPath, $"BetterLyrics_Settings_Export_{DateTime.Now:yyyyMMdd_HHmmss}.json"), exportJson);
|
||||
}
|
||||
|
||||
private void SetValue<T>(string key, T value)
|
||||
/// <summary>
|
||||
/// Indicate a value whether import action is successfullt done
|
||||
/// </summary>
|
||||
/// <param name="importPath"></param>
|
||||
/// <returns></returns>
|
||||
public bool ImportSettings(string importPath)
|
||||
{
|
||||
_localSettings.Values[key] = value;
|
||||
// TODO 导入有问题
|
||||
if (!File.Exists(importPath))
|
||||
return false;
|
||||
|
||||
var importJson = File.ReadAllText(importPath);
|
||||
var importData = System.Text.Json.JsonSerializer.Deserialize(importJson, SourceGenerationContext.Default.AppSettings);
|
||||
|
||||
if (importData == null)
|
||||
return false;
|
||||
|
||||
AppSettings = importData;
|
||||
SaveAppSettings();
|
||||
return true;
|
||||
}
|
||||
|
||||
private static AppSettings ReadAppSettings()
|
||||
{
|
||||
if (!File.Exists(PathHelper.SettingsFilePath))
|
||||
return new AppSettings();
|
||||
|
||||
var json = File.ReadAllText(PathHelper.SettingsFilePath);
|
||||
var data = System.Text.Json.JsonSerializer.Deserialize(json, SourceGenerationContext.Default.AppSettings);
|
||||
|
||||
if (data == null)
|
||||
return new AppSettings();
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
private void WriteAppSettingsDebounce()
|
||||
{
|
||||
_dispatcherQueueTimer.Debounce(() =>
|
||||
{
|
||||
_dispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, () =>
|
||||
{
|
||||
SaveAppSettings();
|
||||
});
|
||||
}, Constants.Time.DebounceTimeout);
|
||||
}
|
||||
|
||||
private void SaveAppSettings()
|
||||
{
|
||||
File.WriteAllText(PathHelper.SettingsFilePath, System.Text.Json.JsonSerializer.Serialize(AppSettings, SourceGenerationContext.Default.AppSettings));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,8 +3,6 @@ using BetterLyrics.WinUI3.Models;
|
||||
using BetterLyrics.WinUI3.Serialization;
|
||||
using BetterLyrics.WinUI3.Services.SettingsService;
|
||||
using BetterLyrics.WinUI3.ViewModels;
|
||||
using Lyricify.Lyrics.Helpers.General;
|
||||
using Microsoft.UI.Dispatching;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
@@ -18,10 +16,12 @@ namespace BetterLyrics.WinUI3.Services.TranslateService
|
||||
{
|
||||
public class TranslateService : BaseViewModel, ITranslateService
|
||||
{
|
||||
private readonly ISettingsService _settingsService;
|
||||
private readonly HttpClient _httpClient;
|
||||
|
||||
public TranslateService(ISettingsService settingsService) : base(settingsService)
|
||||
public TranslateService(ISettingsService settingsService)
|
||||
{
|
||||
_settingsService = settingsService;
|
||||
_httpClient = new HttpClient();
|
||||
}
|
||||
|
||||
@@ -37,21 +37,13 @@ namespace BetterLyrics.WinUI3.Services.TranslateService
|
||||
{
|
||||
return text; // No translation needed
|
||||
}
|
||||
else if (originalLangCode == "zh-Hant" && targetLangCode == "zh-Hans")
|
||||
{
|
||||
return ChineseConverter.ConvertToSimplifiedChinese(text);
|
||||
}
|
||||
else if (originalLangCode == "zh-Hans" && targetLangCode == "zh-Hant")
|
||||
{
|
||||
return ChineseConverter.ConvertToTraditionalChinese(text);
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(_settingsService.LibreTranslateServer))
|
||||
if (string.IsNullOrEmpty(_settingsService.AppSettings.TranslationSettings.LibreTranslateServer))
|
||||
{
|
||||
throw new Exception("LibreTranslate server URL is not set in settings.");
|
||||
}
|
||||
|
||||
var url = $"{_settingsService.LibreTranslateServer}/translate";
|
||||
var url = $"{_settingsService.AppSettings.TranslationSettings.LibreTranslateServer}/translate";
|
||||
var response = await _httpClient.PostAsync(url, new FormUrlEncodedContent(
|
||||
[
|
||||
new("q", text),
|
||||
@@ -70,12 +62,12 @@ namespace BetterLyrics.WinUI3.Services.TranslateService
|
||||
|
||||
public int SearchTranslatedLyricsItself(List<LyricsData> lyricsDataArr)
|
||||
{
|
||||
string targetLangCode = LanguageHelper.GetUserTargetLanguageCode().Substring(0, 2);
|
||||
string targetLangCode = LanguageHelper.SupportedTargetLanguages[_settingsService.AppSettings.TranslationSettings.SelectedTargetLanguageIndex].Code;
|
||||
if (lyricsDataArr.Count > 1)
|
||||
{
|
||||
for (int i = 1; i < lyricsDataArr.Count; i++)
|
||||
{
|
||||
if (lyricsDataArr[i].LanguageCode?.Substring(0, 2) == targetLangCode)
|
||||
if (lyricsDataArr[i].LanguageCode == targetLangCode)
|
||||
{
|
||||
return i; // Translation lyrics data found
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,25 @@
|
||||
using BetterLyrics.WinUI3.Models.Settings;
|
||||
using BetterLyrics.WinUI3.Services.SettingsService;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BetterLyrics.WinUI3.ViewModels
|
||||
{
|
||||
public partial class AlbumArtLayoutSettingsControlViewModel : BaseViewModel
|
||||
{
|
||||
private readonly ISettingsService _settingsService;
|
||||
|
||||
[ObservableProperty]
|
||||
public partial AppSettings AppSettings { get; set; }
|
||||
|
||||
public AlbumArtLayoutSettingsControlViewModel(ISettingsService settingsService)
|
||||
{
|
||||
_settingsService = settingsService;
|
||||
AppSettings = _settingsService.AppSettings;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
using BetterLyrics.WinUI3.Enums;
|
||||
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.Messaging;
|
||||
using CommunityToolkit.Mvvm.Messaging.Messages;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BetterLyrics.WinUI3.ViewModels
|
||||
{
|
||||
public partial class AllLyricsSettingsControlViewModel : BaseViewModel,
|
||||
IRecipient<PropertyChangedMessage<LyricsWindowMode>>
|
||||
{
|
||||
private readonly ISettingsService _settingsService;
|
||||
|
||||
[ObservableProperty]
|
||||
public partial AppSettings AppSettings { get; set; }
|
||||
|
||||
[ObservableProperty]
|
||||
public partial int SelectedTabIndex { get; set; } = 0;
|
||||
|
||||
public AllLyricsSettingsControlViewModel(ISettingsService settingsService)
|
||||
{
|
||||
_settingsService = settingsService;
|
||||
|
||||
AppSettings = _settingsService.AppSettings;
|
||||
}
|
||||
|
||||
public void Receive(PropertyChangedMessage<LyricsWindowMode> message)
|
||||
{
|
||||
if (message.Sender is LiveStates)
|
||||
{
|
||||
if (message.PropertyName == nameof(LiveStates.CurrentLyricsWindowMode))
|
||||
{
|
||||
SelectedTabIndex = (int)message.NewValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
using BetterLyrics.WinUI3.Helper;
|
||||
using BetterLyrics.WinUI3.Models.Settings;
|
||||
using BetterLyrics.WinUI3.Services.SettingsService;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.ApplicationModel;
|
||||
|
||||
namespace BetterLyrics.WinUI3.ViewModels
|
||||
{
|
||||
public partial class AppSettingsControlViewModel : BaseViewModel
|
||||
{
|
||||
private readonly ISettingsService _settingsService;
|
||||
|
||||
[ObservableProperty]
|
||||
public partial AppSettings AppSettings { get; set; }
|
||||
|
||||
[ObservableProperty]
|
||||
public partial ObservableCollection<string> MonitorDeviceNames { get; set; }
|
||||
|
||||
|
||||
public AppSettingsControlViewModel(ISettingsService settingsService)
|
||||
{
|
||||
_settingsService = settingsService;
|
||||
MonitorDeviceNames = [.. MonitorHelper.GetAllMonitorDeviceNames()];
|
||||
AppSettings = _settingsService.AppSettings;
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private static void RestartApp()
|
||||
{
|
||||
WindowHelper.RestartApp();
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void RefreshMonitorDeviceNames()
|
||||
{
|
||||
MonitorDeviceNames = [.. MonitorHelper.GetAllMonitorDeviceNames()];
|
||||
AppSettings.DockModeSettings.DockMonitorDeviceName = MonitorHelper.GetPrimaryMonitorDeviceName();
|
||||
}
|
||||
|
||||
public async Task<bool> ToggleAutoStartupAsync(bool target)
|
||||
{
|
||||
StartupTask startupTask = await StartupTask.GetAsync(Constants.App.AutoStartupTaskId);
|
||||
if (target)
|
||||
{
|
||||
await startupTask.RequestEnableAsync();
|
||||
}
|
||||
else
|
||||
{
|
||||
startupTask.Disable();
|
||||
}
|
||||
return await DetectIsAutoStartupEnabledAsync();
|
||||
}
|
||||
|
||||
public async Task<bool> DetectIsAutoStartupEnabledAsync()
|
||||
{
|
||||
bool result = false;
|
||||
var startupTask = await StartupTask.GetAsync(Constants.App.AutoStartupTaskId);
|
||||
switch (startupTask.State)
|
||||
{
|
||||
case StartupTaskState.Disabled:
|
||||
case StartupTaskState.DisabledByUser:
|
||||
case StartupTaskState.DisabledByPolicy:
|
||||
result = false;
|
||||
break;
|
||||
case StartupTaskState.Enabled:
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -12,15 +12,13 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
{
|
||||
private protected readonly DispatcherQueue _dispatcherQueue;
|
||||
private protected readonly DispatcherQueueTimer _dispatcherQueueTimer;
|
||||
private protected readonly ISettingsService _settingsService;
|
||||
|
||||
public BaseViewModel(ISettingsService settingsService)
|
||||
public BaseViewModel()
|
||||
{
|
||||
IsActive = true;
|
||||
|
||||
_dispatcherQueue = DispatcherQueue.GetForCurrentThread();
|
||||
_dispatcherQueueTimer = _dispatcherQueue.CreateTimer();
|
||||
_settingsService = settingsService;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user