mirror of
https://github.com/jayfunc/BetterLyrics.git
synced 2026-01-13 03:34:55 +08:00
Enhance application functionality to support single instance and multiple languages
Added single instance support in `App.xaml.cs` to ensure that only one instance of the application can run, and introduced `Mutex` and `EnsureSingleInstance()` methods. Updated multi-language support and added new string resources to serve users of different languages. Refactored the play queue processing logic, using `PlayQueueItem` instead of `Track`, and introduced a new song tag information class in `SongsTabInfo.cs`. Updated UI components, replaced old image resources, and improved user experience. In addition, removed the unused `BuildDate` property and simplified the logic of the settings page. Together, these changes improve the stability, usability, and maintainability of the application.
This commit is contained in:
@@ -20,6 +20,7 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Vanara.PInvoke;
|
||||
|
||||
namespace BetterLyrics.WinUI3
|
||||
{
|
||||
@@ -36,6 +37,8 @@ namespace BetterLyrics.WinUI3
|
||||
public NotificationPanel? LyricsWindowNotificationPanel { get; set; }
|
||||
public NotificationPanel? SettingsWindowNotificationPanel { get; set; }
|
||||
|
||||
private static Mutex? _instanceMutex;
|
||||
|
||||
public App()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
@@ -44,6 +47,8 @@ namespace BetterLyrics.WinUI3
|
||||
DispatcherQueueTimer = DispatcherQueue.CreateTimer();
|
||||
ResourceLoader = new ResourceLoader();
|
||||
|
||||
EnsureSingleInstance();
|
||||
|
||||
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
|
||||
PathHelper.EnsureDirectories();
|
||||
ConfigureServices();
|
||||
@@ -56,6 +61,18 @@ namespace BetterLyrics.WinUI3
|
||||
TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;
|
||||
}
|
||||
|
||||
private void EnsureSingleInstance()
|
||||
{
|
||||
bool createdNew;
|
||||
_instanceMutex = new Mutex(true, MetadataHelper.AppName, out createdNew);
|
||||
|
||||
if (!createdNew)
|
||||
{
|
||||
User32.MessageBox(HWND.NULL, ResourceLoader!.GetString("TryRunMultipleInstance"), null, User32.MB_FLAGS.MB_APPLMODAL);
|
||||
Environment.Exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnLaunched(LaunchActivatedEventArgs args)
|
||||
{
|
||||
Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.RealTime;
|
||||
|
||||
BIN
BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/EmptyBox.png
Normal file
BIN
BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/EmptyBox.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 33 KiB |
BIN
BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/EmptyState.png
Normal file
BIN
BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/EmptyState.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 30 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 29 KiB |
BIN
BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/Telegram.png
Normal file
BIN
BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/Telegram.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 192 KiB |
@@ -6,7 +6,7 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Enums
|
||||
{
|
||||
public enum SongOrderType
|
||||
public enum CommonSongProperty
|
||||
{
|
||||
Title,
|
||||
Album,
|
||||
@@ -29,6 +29,7 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
public const string GithubUrl = "https://github.com/jayfunc/BetterLyrics";
|
||||
public const string QQGroupUrl = "https://qun.qq.com/universal-share/share?ac=1&authKey=4Q%2BYTq3wZldYpF5SbS5c19ECFsiYoLZFAIcBNNzYpBUtiEjaZ8sZ%2F%2BnFN0qw3lad&busi_data=eyJncm91cENvZGUiOiIxMDU0NzAwMzg4IiwidG9rZW4iOiJiVnhqemVYN0N5QVc3b1ZkR24wWmZOTUtvUkJoWm1JRWlaWW5iZnlBcXJtZUtGc2FFTHNlUlFZMi9iRm03cWF5IiwidWluIjoiMTM5NTczOTY2MCJ9&data=39UmAihyH_o6CZaOs7nk2mO_lz2ruODoDou6pxxh7utcxP4WF5sbDBDOPvZ_Wqfzeey4441anegsLYQJxkrBAA&svctype=4&tempid=h5_group_info";
|
||||
public const string DiscordUrl = "https://discord.gg/5yAQPnyCKv";
|
||||
public const string TelegramUrl = "https://t.me/+svhSLZ7awPsxNGY1";
|
||||
|
||||
public static async Task<DateTime> GetBuildDate()
|
||||
{
|
||||
|
||||
@@ -26,36 +26,39 @@ namespace BetterLyrics.WinUI3.Models
|
||||
LyricsLines = lyricsLines;
|
||||
}
|
||||
|
||||
public void SetDisplayedTextAlongWith(LyricsData translationData)
|
||||
public void SetDisplayedTextAlongWith(LyricsData translationData, int toleranceMs = 0)
|
||||
{
|
||||
int i = 0;
|
||||
foreach (var line in LyricsLines)
|
||||
{
|
||||
if (i >= translationData.LyricsLines.Count)
|
||||
// 在翻译歌词中查找与当前行开始时间最接近且在容忍范围内的行
|
||||
var transLine = translationData.LyricsLines
|
||||
.FirstOrDefault(t => Math.Abs(t.StartMs - line.StartMs) <= toleranceMs);
|
||||
|
||||
if (transLine != null)
|
||||
{
|
||||
line.DisplayedText = line.OriginalText; // No translation available, keep original text
|
||||
}
|
||||
else
|
||||
{
|
||||
if (translationData.LanguageCode?.Substring(0, 2) == "zh")
|
||||
if (translationData.LanguageCode?.StartsWith("zh") == true)
|
||||
{
|
||||
string tmp = "";
|
||||
if (LanguageHelper.GetUserTargetLanguageCode() == "zh-Hant")
|
||||
{
|
||||
tmp = ChineseConverter.ConvertToTraditionalChinese(translationData.LyricsLines[i].OriginalText);
|
||||
tmp = ChineseConverter.ConvertToTraditionalChinese(transLine.OriginalText);
|
||||
}
|
||||
else if (LanguageHelper.GetUserTargetLanguageCode() == "zh-Hans")
|
||||
{
|
||||
tmp = ChineseConverter.ConvertToSimplifiedChinese(translationData.LyricsLines[i].OriginalText);
|
||||
tmp = ChineseConverter.ConvertToSimplifiedChinese(transLine.OriginalText);
|
||||
}
|
||||
line.DisplayedText = $"{line.OriginalText}\n{tmp}";
|
||||
}
|
||||
else
|
||||
{
|
||||
line.DisplayedText = $"{line.OriginalText}\n{translationData.LyricsLines[i].OriginalText}";
|
||||
line.DisplayedText = $"{line.OriginalText}\n{transLine.OriginalText}";
|
||||
}
|
||||
}
|
||||
i++;
|
||||
else
|
||||
{
|
||||
// 没有匹配的翻译,翻译部分留空
|
||||
line.DisplayedText = $"{line.OriginalText}\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
using ATL;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Models
|
||||
{
|
||||
public class PlayQueueItem
|
||||
{
|
||||
public Track Track { get; set; }
|
||||
|
||||
public PlayQueueItem(Track track)
|
||||
{
|
||||
Track = track;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
using BetterLyrics.WinUI3.Enums;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Models
|
||||
{
|
||||
public class SongsTabInfo
|
||||
{
|
||||
public string Name { get; set; }
|
||||
|
||||
public string Icon { get; set; }
|
||||
|
||||
public bool IsClosable { get; set; }
|
||||
|
||||
public CommonSongProperty FilterProperty { get; set; }
|
||||
|
||||
public string FilterValue { get; set; }
|
||||
|
||||
public SongsTabInfo()
|
||||
{
|
||||
Name = string.Empty;
|
||||
Icon = string.Empty;
|
||||
IsClosable = true;
|
||||
FilterProperty = CommonSongProperty.Title;
|
||||
FilterValue = string.Empty;
|
||||
}
|
||||
|
||||
public SongsTabInfo(string name, string icon, bool isClosable, CommonSongProperty filterProperty, string filterValue)
|
||||
{
|
||||
Name = name;
|
||||
Icon = icon;
|
||||
IsClosable = isClosable;
|
||||
FilterProperty = filterProperty;
|
||||
FilterValue = filterValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -348,7 +348,7 @@ namespace BetterLyrics.WinUI3.Services
|
||||
else if (result is NeteaseSearchResult neteaseResult)
|
||||
{
|
||||
var response = await Lyricify.Lyrics.Helpers.ProviderHelper.NeteaseApi.GetLyric(neteaseResult.Id);
|
||||
var translated = response?.Tlyric.Lyric;
|
||||
var translated = response?.Tlyric?.Lyric;
|
||||
if (!string.IsNullOrEmpty(translated))
|
||||
{
|
||||
FileHelper.WriteLyricsCache(
|
||||
|
||||
@@ -869,13 +869,13 @@ If you encounter any problems, please go to the Settings page, About tab, and vi
|
||||
<value>List loop</value>
|
||||
</data>
|
||||
<data name="MusicGalleryPageSingleLoop.Content" xml:space="preserve">
|
||||
<value>Single Loop</value>
|
||||
<value>Single loop</value>
|
||||
</data>
|
||||
<data name="MusicGalleryPageQueueRandom.Content" xml:space="preserve">
|
||||
<value>random</value>
|
||||
<value>Random</value>
|
||||
</data>
|
||||
<data name="MusicGalleryPageRemoveFromPlayingQueue.Text" xml:space="preserve">
|
||||
<value>Remove from the Play queue</value>
|
||||
<value>Remove from play queue</value>
|
||||
</data>
|
||||
<data name="MusicGalleryPagePlayingQueueEmpty.Text" xml:space="preserve">
|
||||
<value>Play queue is empty</value>
|
||||
@@ -901,4 +901,13 @@ If you encounter any problems, please go to the Settings page, About tab, and vi
|
||||
<data name="SystemTrayMusicGallery.Text" xml:space="preserve">
|
||||
<value>Open music gallery</value>
|
||||
</data>
|
||||
<data name="TryRunMultipleInstance" xml:space="preserve">
|
||||
<value>BetterLyrics is already running</value>
|
||||
</data>
|
||||
<data name="MusicGalleryPageAllSongs" xml:space="preserve">
|
||||
<value>All songs</value>
|
||||
</data>
|
||||
<data name="SettingsPageTelegram.Header" xml:space="preserve">
|
||||
<value>Telegram</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -901,4 +901,13 @@
|
||||
<data name="SystemTrayMusicGallery.Text" xml:space="preserve">
|
||||
<value>オープンミュージックギャラリー</value>
|
||||
</data>
|
||||
<data name="TryRunMultipleInstance" xml:space="preserve">
|
||||
<value>BetterLyrics はすでに実行されています!</value>
|
||||
</data>
|
||||
<data name="MusicGalleryPageAllSongs" xml:space="preserve">
|
||||
<value>すべての曲</value>
|
||||
</data>
|
||||
<data name="SettingsPageTelegram.Header" xml:space="preserve">
|
||||
<value>Telegram</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -901,4 +901,13 @@
|
||||
<data name="SystemTrayMusicGallery.Text" xml:space="preserve">
|
||||
<value>오픈 음악 갤러리</value>
|
||||
</data>
|
||||
<data name="TryRunMultipleInstance" xml:space="preserve">
|
||||
<value>BetterLyrics 가 이미 실행 중입니다</value>
|
||||
</data>
|
||||
<data name="MusicGalleryPageAllSongs" xml:space="preserve">
|
||||
<value>모든 노래</value>
|
||||
</data>
|
||||
<data name="SettingsPageTelegram.Header" xml:space="preserve">
|
||||
<value>Telegram</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -901,4 +901,13 @@
|
||||
<data name="SystemTrayMusicGallery.Text" xml:space="preserve">
|
||||
<value>打开音乐库</value>
|
||||
</data>
|
||||
<data name="TryRunMultipleInstance" xml:space="preserve">
|
||||
<value>BetterLyrics 已经在运行</value>
|
||||
</data>
|
||||
<data name="MusicGalleryPageAllSongs" xml:space="preserve">
|
||||
<value>所有歌曲</value>
|
||||
</data>
|
||||
<data name="SettingsPageTelegram.Header" xml:space="preserve">
|
||||
<value>Telegram</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -901,4 +901,13 @@
|
||||
<data name="SystemTrayMusicGallery.Text" xml:space="preserve">
|
||||
<value>開啟音樂庫</value>
|
||||
</data>
|
||||
<data name="TryRunMultipleInstance" xml:space="preserve">
|
||||
<value>BetterLyrics 已經在運作</value>
|
||||
</data>
|
||||
<data name="MusicGalleryPageAllSongs" xml:space="preserve">
|
||||
<value>所有歌曲</value>
|
||||
</data>
|
||||
<data name="SettingsPageTelegram.Header" xml:space="preserve">
|
||||
<value>Telegram</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -10,15 +10,15 @@ public class SongOrderTemplateSelector : DataTemplateSelector
|
||||
public DataTemplate ByAlbumTemplate { get; set; }
|
||||
public DataTemplate ByArtistTemplate { get; set; }
|
||||
|
||||
public SongOrderType SongOrderType { get; set; }
|
||||
public CommonSongProperty SongOrderType { get; set; }
|
||||
|
||||
protected override DataTemplate SelectTemplateCore(object item)
|
||||
{
|
||||
return SongOrderType switch
|
||||
{
|
||||
SongOrderType.Title => ByTitleTemplate,
|
||||
SongOrderType.Album => ByAlbumTemplate,
|
||||
SongOrderType.Artist => ByArtistTemplate,
|
||||
CommonSongProperty.Title => ByTitleTemplate,
|
||||
CommonSongProperty.Album => ByAlbumTemplate,
|
||||
CommonSongProperty.Artist => ByArtistTemplate,
|
||||
_ => ByTitleTemplate
|
||||
};
|
||||
}
|
||||
|
||||
@@ -193,6 +193,7 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
else if (message.PropertyName == nameof(SettingsPageViewModel.CoverAcrylicEffectAmount))
|
||||
{
|
||||
_coverAcrylicEffectAmount = message.NewValue;
|
||||
_isCoverAcrylicEffectAmountChanged = true;
|
||||
}
|
||||
else if (message.PropertyName == nameof(SettingsPageViewModel.LyricsVerticalEdgeOpacity))
|
||||
{
|
||||
|
||||
@@ -74,6 +74,11 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
|
||||
_titleY = _albumArtY + _albumArtSize * 1.05f;
|
||||
|
||||
_isCoverAcrylicEffectAmountChanged = true;
|
||||
}
|
||||
|
||||
if (_isCoverAcrylicEffectAmountChanged)
|
||||
{
|
||||
UpdateCoverAcrylicOverlay(control);
|
||||
}
|
||||
|
||||
@@ -446,14 +451,18 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
|
||||
private void UpdateCoverAcrylicOverlay(ICanvasAnimatedControl control)
|
||||
{
|
||||
var ret = NoiseOverlayHelper.GenerateNoiseBitmapBGRA((int)_canvasWidth, (int)_canvasHeight);
|
||||
_coverAcrylicNoiseCanvasBitmap = CanvasBitmap.CreateFromBytes(
|
||||
control,
|
||||
ret,
|
||||
(int)_canvasWidth,
|
||||
(int)_canvasHeight,
|
||||
Windows.Graphics.DirectX.DirectXPixelFormat.B8G8R8A8UIntNormalized
|
||||
);
|
||||
if (_coverAcrylicEffectAmount > 0)
|
||||
{
|
||||
var ret = NoiseOverlayHelper.GenerateNoiseBitmapBGRA((int)_canvasWidth, (int)_canvasHeight);
|
||||
_coverAcrylicNoiseCanvasBitmap = CanvasBitmap.CreateFromBytes(
|
||||
control,
|
||||
ret,
|
||||
(int)_canvasWidth,
|
||||
(int)_canvasHeight,
|
||||
Windows.Graphics.DirectX.DirectXPixelFormat.B8G8R8A8UIntNormalized
|
||||
);
|
||||
}
|
||||
_isCoverAcrylicEffectAmountChanged = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,6 +47,7 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
private CanvasBitmap? _albumArtCanvasBitmap = null;
|
||||
|
||||
private CanvasBitmap? _coverAcrylicNoiseCanvasBitmap = null;
|
||||
private bool _isCoverAcrylicEffectAmountChanged = false;
|
||||
|
||||
private float _albumArtSize = 0f;
|
||||
private int _albumArtCornerRadius = 0;
|
||||
@@ -444,7 +445,7 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
}
|
||||
else
|
||||
{
|
||||
_lyricsDataArr[0].SetDisplayedTextAlongWith(_lyricsDataArr[found]);
|
||||
_lyricsDataArr[0].SetDisplayedTextAlongWith(_lyricsDataArr[found], 50);
|
||||
_langIndex = 0;
|
||||
}
|
||||
}
|
||||
@@ -550,7 +551,6 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
{
|
||||
foreach (var data in translationData)
|
||||
{
|
||||
data.LyricsLines = data.LyricsLines.Where(line => !string.IsNullOrWhiteSpace(line.OriginalText)).ToList();
|
||||
foreach (var item in data.LyricsLines)
|
||||
{
|
||||
if (item.OriginalText == "//")
|
||||
|
||||
@@ -30,12 +30,19 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
private readonly MediaPlayer _mediaPlayer = new();
|
||||
private readonly MediaTimelineController _timelineController = new();
|
||||
private readonly SystemMediaTransportControls _smtc;
|
||||
// All songs
|
||||
private List<Track> _tracks = [];
|
||||
// Songs in current playlist
|
||||
private List<Track> _playlistTracks = [];
|
||||
// Filtered songs based on search query for current playlist
|
||||
private List<Track> _filteredTracks = [];
|
||||
|
||||
[ObservableProperty]
|
||||
public partial bool IsLocalMediaNotFound { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Grouped tracks after filtering and sorting for current playlist
|
||||
/// </summary>
|
||||
[ObservableProperty]
|
||||
public partial ObservableCollection<GroupInfoList> GroupedTracks { get; set; } = [];
|
||||
|
||||
@@ -43,15 +50,23 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
public partial List<Track> SelectedTracks { get; set; } = [];
|
||||
|
||||
[ObservableProperty]
|
||||
public partial ObservableCollection<Track> TrackPlayingQueue { get; set; } = [];
|
||||
public partial ObservableCollection<PlayQueueItem> TrackPlayingQueue { get; set; } = [];
|
||||
|
||||
public Track? PlayingTrack => TrackPlayingQueue.ElementAtOrDefault(PlayingSongIndex);
|
||||
public PlayQueueItem? PlayingQueueItem => TrackPlayingQueue.ElementAtOrDefault(PlayingSongIndex);
|
||||
|
||||
[ObservableProperty]
|
||||
public partial PlaybackOrder PlaybackOrder { get; set; }
|
||||
|
||||
[ObservableProperty]
|
||||
public partial SongOrderType SongOrderType { get; set; } = SongOrderType.Title;
|
||||
public partial CommonSongProperty SongOrderType { get; set; } = CommonSongProperty.Title;
|
||||
|
||||
[ObservableProperty]
|
||||
public partial ObservableCollection<SongsTabInfo> SongsTabInfoList { get; set; } = [];
|
||||
|
||||
[ObservableProperty]
|
||||
public partial int SelectedSongsTabInfoIndex { get; set; } = 0;
|
||||
|
||||
public SongsTabInfo? SelectedSongsTabInfo => SongsTabInfoList.ElementAtOrDefault(SelectedSongsTabInfoIndex);
|
||||
|
||||
[ObservableProperty]
|
||||
public partial bool IsDataLoading { get; set; } = false;
|
||||
@@ -70,6 +85,8 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
|
||||
public MusicGalleryViewModel(ISettingsService settingsService, ILibWatcherService libWatcherService) : base(settingsService)
|
||||
{
|
||||
SongsTabInfoList.Add(new SongsTabInfo(App.ResourceLoader!.GetString("MusicGalleryPageAllSongs"), "\uE8A9", false, CommonSongProperty.Title, string.Empty));
|
||||
|
||||
RefreshSongs();
|
||||
|
||||
PlaybackOrder = _settingsService.PlaybackOrder;
|
||||
@@ -111,7 +128,7 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
{
|
||||
PlayingSongIndex = 0;
|
||||
}
|
||||
PlayTrack(PlayingTrack);
|
||||
PlayTrack(PlayingQueueItem);
|
||||
});
|
||||
break;
|
||||
case PlaybackOrder.RepeatOne:
|
||||
@@ -124,7 +141,7 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
{
|
||||
PlayingSongIndex = new Random().Next(0, TrackPlayingQueue.Count);
|
||||
}
|
||||
PlayTrack(PlayingTrack);
|
||||
PlayTrack(PlayingQueueItem);
|
||||
});
|
||||
break;
|
||||
default:
|
||||
@@ -147,7 +164,7 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
{
|
||||
PlayingSongIndex = TrackPlayingQueue.Count - 1;
|
||||
}
|
||||
PlayTrack(PlayingTrack);
|
||||
PlayTrack(PlayingQueueItem);
|
||||
});
|
||||
break;
|
||||
case PlaybackOrder.RepeatOne:
|
||||
@@ -160,7 +177,7 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
{
|
||||
PlayingSongIndex = new Random().Next(0, TrackPlayingQueue.Count);
|
||||
}
|
||||
PlayTrack(PlayingTrack);
|
||||
PlayTrack(PlayingQueueItem);
|
||||
});
|
||||
break;
|
||||
default:
|
||||
@@ -236,10 +253,10 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
ApplySongSearchQuery();
|
||||
|
||||
_dispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, () =>
|
||||
{
|
||||
ApplyPlaylist();
|
||||
ApplySongSearchQuery();
|
||||
IsLocalMediaNotFound = !_filteredTracks.Any();
|
||||
ApplySongOrderType();
|
||||
IsDataLoading = false;
|
||||
@@ -248,37 +265,64 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
}, TimeSpan.FromMilliseconds(100));
|
||||
}
|
||||
|
||||
public void ApplyPlaylist()
|
||||
{
|
||||
if (SelectedSongsTabInfo?.FilterValue == string.Empty)
|
||||
{
|
||||
_playlistTracks = _tracks;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (SelectedSongsTabInfo?.FilterProperty)
|
||||
{
|
||||
case CommonSongProperty.Title:
|
||||
_playlistTracks = _tracks.Where(t => t.Title.Equals(SelectedSongsTabInfo.FilterValue, StringComparison.OrdinalIgnoreCase)).ToList();
|
||||
break;
|
||||
case CommonSongProperty.Album:
|
||||
_playlistTracks = _tracks.Where(t => t.Album.Equals(SelectedSongsTabInfo.FilterValue, StringComparison.OrdinalIgnoreCase)).ToList();
|
||||
break;
|
||||
case CommonSongProperty.Artist:
|
||||
_playlistTracks = _tracks.Where(t => t.Artist.Equals(SelectedSongsTabInfo.FilterValue, StringComparison.OrdinalIgnoreCase)).ToList();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
ApplySongSearchQuery();
|
||||
IsLocalMediaNotFound = !_filteredTracks.Any();
|
||||
ApplySongOrderType();
|
||||
}
|
||||
|
||||
public void ApplySongSearchQuery()
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(SongSearchQuery))
|
||||
{
|
||||
_filteredTracks = _tracks;
|
||||
_filteredTracks = _playlistTracks;
|
||||
return;
|
||||
}
|
||||
_filteredTracks = new List<Track>(
|
||||
_tracks.Where(t => t.Title.Contains(SongSearchQuery, StringComparison.OrdinalIgnoreCase) ||
|
||||
t.Artist.Contains(SongSearchQuery, StringComparison.OrdinalIgnoreCase) ||
|
||||
t.Album.Contains(SongSearchQuery, StringComparison.OrdinalIgnoreCase))
|
||||
);
|
||||
_filteredTracks = _playlistTracks.Where(t =>
|
||||
t.Title.Contains(SongSearchQuery, StringComparison.OrdinalIgnoreCase) ||
|
||||
t.Artist.Contains(SongSearchQuery, StringComparison.OrdinalIgnoreCase) ||
|
||||
t.Album.Contains(SongSearchQuery, StringComparison.OrdinalIgnoreCase)).ToList();
|
||||
}
|
||||
|
||||
private void ApplySongOrderType()
|
||||
{
|
||||
switch (SongOrderType)
|
||||
{
|
||||
case SongOrderType.Title:
|
||||
case CommonSongProperty.Title:
|
||||
GroupedTracks = _filteredTracks.GetGroupedBy(
|
||||
t => LanguageHelper.GetOrderChar(t.Title),
|
||||
o => ((Track)o).Title
|
||||
);
|
||||
break;
|
||||
case SongOrderType.Artist:
|
||||
case CommonSongProperty.Artist:
|
||||
GroupedTracks = _filteredTracks.GetGroupedBy(
|
||||
t => LanguageHelper.GetOrderChar(t.Artist),
|
||||
o => ((Track)o).Artist
|
||||
);
|
||||
break;
|
||||
case SongOrderType.Album:
|
||||
case CommonSongProperty.Album:
|
||||
GroupedTracks = _filteredTracks.GetGroupedBy(
|
||||
t => LanguageHelper.GetOrderChar(t.Album),
|
||||
o => ((Track)o).Album
|
||||
@@ -287,21 +331,38 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateSelectedPlaylist(SongsTabInfo playlist)
|
||||
{
|
||||
var found = SongsTabInfoList.Where(x => x.FilterProperty == playlist.FilterProperty && x.FilterValue == playlist.FilterValue)
|
||||
.ToList().FirstOrDefault();
|
||||
if (found == null)
|
||||
{
|
||||
SongsTabInfoList.Add(playlist);
|
||||
SelectedSongsTabInfoIndex = SongsTabInfoList.Count - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
SelectedSongsTabInfoIndex = SongsTabInfoList.IndexOf(found);
|
||||
}
|
||||
ApplyPlaylist();
|
||||
}
|
||||
|
||||
public void PlayTrackAt(int index)
|
||||
{
|
||||
PlayTrack(TrackPlayingQueue.ElementAtOrDefault(index));
|
||||
}
|
||||
|
||||
public void PlayTrack(Track? track)
|
||||
public void PlayTrack(PlayQueueItem? playQueueItem)
|
||||
{
|
||||
_timelineController.Pause();
|
||||
_mediaPlayer.Source = null;
|
||||
if (track == null)
|
||||
if (playQueueItem == null)
|
||||
{
|
||||
_smtc.IsEnabled = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
var track = playQueueItem.Track;
|
||||
var updater = _smtc.DisplayUpdater;
|
||||
_smtc.IsEnabled = true;
|
||||
_mediaPlayer.Source = MediaSource.CreateFromUri(new Uri(track.Path));
|
||||
@@ -322,7 +383,7 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
partial void OnSongOrderTypeChanged(SongOrderType value)
|
||||
partial void OnSongOrderTypeChanged(CommonSongProperty value)
|
||||
{
|
||||
ApplySongOrderType();
|
||||
IsLocalMediaNotFound = !_filteredTracks.Any();
|
||||
|
||||
@@ -102,11 +102,6 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
IsDragEverywhereEnabled = _settingsService.IsDragEverywhereEnabled;
|
||||
|
||||
_playbackService.MediaSourceProvidersInfoChanged += PlaybackService_SessionIdsChanged;
|
||||
|
||||
Task.Run(async () =>
|
||||
{
|
||||
BuildDate = (await MetadataHelper.GetBuildDate()).ToString("(yyyy/MM/dd HH:mm:ss)");
|
||||
});
|
||||
}
|
||||
|
||||
private void PlaybackService_SessionIdsChanged(object? sender, Events.MediaSourceProvidersInfoEventArgs e)
|
||||
@@ -281,8 +276,6 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
|
||||
public string Version { get; set; } = MetadataHelper.AppVersion;
|
||||
|
||||
public string BuildDate { get; set; } = string.Empty;
|
||||
|
||||
[ObservableProperty]
|
||||
public partial string LibreTranslateServer { get; set; }
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
mc:Ignorable="d">
|
||||
<Page.Resources>
|
||||
<CollectionViewSource
|
||||
x:Name="TracksByTitleCVS"
|
||||
x:Name="GroupedTracksCVS"
|
||||
IsSourceGrouped="True"
|
||||
Source="{x:Bind ViewModel.GroupedTracks, Mode=OneWay}" />
|
||||
</Page.Resources>
|
||||
@@ -28,7 +28,10 @@
|
||||
<ColumnDefinition Width="3*" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid x:Name="SongViewer" Grid.Column="0">
|
||||
<Grid
|
||||
x:Name="SongViewer"
|
||||
Grid.Column="0"
|
||||
Padding="12">
|
||||
<Grid.Tag>
|
||||
<Flyout
|
||||
x:Name="SongFileInfoFlyout"
|
||||
@@ -88,7 +91,58 @@
|
||||
</Flyout>
|
||||
</Grid.Tag>
|
||||
|
||||
<Grid Margin="12" VerticalAlignment="Top">
|
||||
<ListView
|
||||
VerticalAlignment="Top"
|
||||
ItemsSource="{x:Bind ViewModel.SongsTabInfoList, Mode=OneWay}"
|
||||
ScrollViewer.HorizontalScrollBarVisibility="Auto"
|
||||
ScrollViewer.VerticalScrollBarVisibility="Disabled"
|
||||
SelectedIndex="{x:Bind ViewModel.SelectedSongsTabInfoIndex, Mode=TwoWay}">
|
||||
<ListView.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<ItemsStackPanel Orientation="Horizontal" />
|
||||
</ItemsPanelTemplate>
|
||||
</ListView.ItemsPanel>
|
||||
<ListView.ItemTemplate>
|
||||
<DataTemplate x:DataType="models:SongsTabInfo">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="1*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid
|
||||
Grid.Column="0"
|
||||
Background="Transparent"
|
||||
ColumnSpacing="6"
|
||||
Tapped="PlaylistGrid_Tapped">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="1*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<FontIcon
|
||||
Grid.Column="0"
|
||||
FontFamily="{StaticResource IconFontFamily}"
|
||||
FontSize="16"
|
||||
Glyph="{Binding Icon}" />
|
||||
<TextBlock
|
||||
Grid.Column="1"
|
||||
VerticalAlignment="Center"
|
||||
Text="{Binding Name}" />
|
||||
</Grid>
|
||||
<Button
|
||||
Grid.Column="1"
|
||||
Click="PlaylistCloseButton_Click"
|
||||
Content="{ui:FontIcon FontSize=10,
|
||||
FontFamily={StaticResource IconFontFamily},
|
||||
Glyph=}"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
Style="{StaticResource GhostButtonStyle}"
|
||||
Visibility="{Binding IsClosable, Converter={StaticResource BoolToVisibilityConverter}}" />
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ListView.ItemTemplate>
|
||||
</ListView>
|
||||
|
||||
<Grid Margin="0,48,0,0" VerticalAlignment="Top">
|
||||
<AutoSuggestBox
|
||||
x:Name="SongSearchBox"
|
||||
x:Uid="MusicGalleryPageSongSearchBox"
|
||||
@@ -97,7 +151,7 @@
|
||||
Text="{x:Bind ViewModel.SongSearchQuery, Mode=TwoWay}" />
|
||||
</Grid>
|
||||
|
||||
<Grid Margin="12,58,12,0" VerticalAlignment="Top">
|
||||
<Grid Margin="0,96,0,0" VerticalAlignment="Top">
|
||||
<StackPanel
|
||||
HorizontalAlignment="Left"
|
||||
Orientation="Horizontal"
|
||||
@@ -143,12 +197,11 @@
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
<SemanticZoom Margin="0,96,0,0">
|
||||
<SemanticZoom Margin="0,140,0,0">
|
||||
<SemanticZoom.ZoomedInView>
|
||||
<ListView
|
||||
x:Name="SongListView"
|
||||
Margin="12,0"
|
||||
ItemsSource="{x:Bind TracksByTitleCVS.View, Mode=OneWay}"
|
||||
ItemsSource="{x:Bind GroupedTracksCVS.View, Mode=OneWay}"
|
||||
SelectionChanged="SongListView_SelectionChanged"
|
||||
SelectionMode="Multiple">
|
||||
<ListView.ItemTemplate>
|
||||
@@ -173,7 +226,8 @@
|
||||
<HyperlinkButton
|
||||
Grid.Column="1"
|
||||
VerticalAlignment="Center"
|
||||
IsEnabled="False">
|
||||
Click="ArtistHyperlibkButton_Click"
|
||||
Tag="{Binding Artist}">
|
||||
<TextBlock Text="{Binding Artist}" TextWrapping="Wrap" />
|
||||
</HyperlinkButton>
|
||||
|
||||
@@ -181,7 +235,8 @@
|
||||
<HyperlinkButton
|
||||
Grid.Column="2"
|
||||
VerticalAlignment="Center"
|
||||
IsEnabled="False">
|
||||
Click="AlbumHyperlibkButton_Click"
|
||||
Tag="{Binding Album}">
|
||||
<TextBlock Text="{Binding Album}" TextWrapping="Wrap" />
|
||||
</HyperlinkButton>
|
||||
|
||||
@@ -216,7 +271,7 @@
|
||||
<Border AutomationProperties.AccessibilityView="Raw">
|
||||
<TextBlock
|
||||
AutomationProperties.AccessibilityView="Raw"
|
||||
Style="{ThemeResource TitleTextBlockStyle}"
|
||||
Style="{ThemeResource SubtitleTextBlockStyle}"
|
||||
Text="{Binding}" />
|
||||
</Border>
|
||||
</DataTemplate>
|
||||
@@ -231,7 +286,7 @@
|
||||
MaxWidth="500"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
ItemsSource="{x:Bind TracksByTitleCVS.View.CollectionGroups, Mode=OneWay}"
|
||||
ItemsSource="{x:Bind GroupedTracksCVS.View.CollectionGroups, Mode=OneWay}"
|
||||
ScrollViewer.IsHorizontalScrollChainingEnabled="False"
|
||||
SelectionMode="None">
|
||||
<GridView.ItemTemplate>
|
||||
@@ -243,10 +298,16 @@
|
||||
</SemanticZoom.ZoomedOutView>
|
||||
</SemanticZoom>
|
||||
|
||||
<Grid Margin="0,48,0,0" Visibility="{x:Bind ViewModel.IsLocalMediaNotFound, Mode=OneWay, Converter={StaticResource BoolToVisibilityConverter}}">
|
||||
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
|
||||
<Image MaxWidth="200" Source="/Assets/Planet.png" />
|
||||
<TextBlock x:Uid="MusicGalleryPageFileNotFound" HorizontalAlignment="Center" />
|
||||
<Grid Margin="0,140,0,0" Visibility="{x:Bind ViewModel.IsLocalMediaNotFound, Mode=OneWay, Converter={StaticResource BoolToVisibilityConverter}}">
|
||||
<StackPanel
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Spacing="12">
|
||||
<Image MaxWidth="200" Source="/Assets/EmptyState.png" />
|
||||
<TextBlock
|
||||
x:Uid="MusicGalleryPageFileNotFound"
|
||||
HorizontalAlignment="Center"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
@@ -289,10 +350,10 @@
|
||||
<Grid Padding="0,6">
|
||||
<Grid Tapped="PlayingQueueListVireItemGrid_Tapped">
|
||||
<StackPanel>
|
||||
<TextBlock Text="{Binding Title}" TextWrapping="Wrap" />
|
||||
<TextBlock Text="{Binding Track.Title}" TextWrapping="Wrap" />
|
||||
<TextBlock
|
||||
Foreground="{StaticResource TextFillColorSecondaryBrush}"
|
||||
Text="{Binding Artist}"
|
||||
Text="{Binding Track.Artist}"
|
||||
TextWrapping="Wrap" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
@@ -328,9 +389,15 @@
|
||||
<interactivity:ChangePropertyAction PropertyName="Visibility" Value="Collapsed" />
|
||||
</interactivity:DataTriggerBehavior>
|
||||
</interactivity:Interaction.Behaviors>
|
||||
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
|
||||
<Image MaxWidth="200" Source="/Assets/Planet.png" />
|
||||
<TextBlock x:Uid="MusicGalleryPagePlayingQueueEmpty" HorizontalAlignment="Center" />
|
||||
<StackPanel
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Spacing="12">
|
||||
<Image MaxWidth="100" Source="/Assets/EmptyBox.png" />
|
||||
<TextBlock
|
||||
x:Uid="MusicGalleryPagePlayingQueueEmpty"
|
||||
HorizontalAlignment="Center"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using ATL;
|
||||
using BetterLyrics.WinUI3.Enums;
|
||||
using BetterLyrics.WinUI3.Helper;
|
||||
using BetterLyrics.WinUI3.Models;
|
||||
using BetterLyrics.WinUI3.ViewModels;
|
||||
using CommunityToolkit.Mvvm.DependencyInjection;
|
||||
using CommunityToolkit.WinUI;
|
||||
@@ -51,13 +52,9 @@ namespace BetterLyrics.WinUI3.Views
|
||||
|
||||
private void PlayingQueueListVireItemGrid_Tapped(object sender, TappedRoutedEventArgs e)
|
||||
{
|
||||
var frameworkElement = ((FrameworkElement)sender).Parent;
|
||||
var index = PlayingQueueListView.FindChildIndex(frameworkElement);
|
||||
ViewModel.PlayTrackAt(index);
|
||||
DispatcherQueue.TryEnqueue(async () =>
|
||||
{
|
||||
await PlayingQueueListView.SmoothScrollIntoViewWithIndexAsync(index, ScrollItemPlacement.Center);
|
||||
});
|
||||
var item = (PlayQueueItem)((FrameworkElement)sender).DataContext;
|
||||
ViewModel.PlayTrack(item);
|
||||
PlayingQueueListView.ScrollIntoView(item);
|
||||
}
|
||||
|
||||
private void EmptyPlayingQueueButton_Click(object sender, RoutedEventArgs e)
|
||||
@@ -69,27 +66,32 @@ namespace BetterLyrics.WinUI3.Views
|
||||
|
||||
private void ScrollToPlayingItemButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (ViewModel.PlayingTrack == null) return;
|
||||
DispatcherQueue.TryEnqueue(async () =>
|
||||
{
|
||||
await PlayingQueueListView.SmoothScrollIntoViewWithIndexAsync(ViewModel.PlayingSongIndex, ScrollItemPlacement.Center);
|
||||
});
|
||||
if (ViewModel.PlayingQueueItem == null) return;
|
||||
PlayingQueueListView.ScrollIntoView(ViewModel.PlayingQueueItem);
|
||||
}
|
||||
|
||||
private void RemoveFromPlayingQueueButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var frameworkElement = ((FrameworkElement)((FrameworkElement)sender).Parent).Parent;
|
||||
bool playNext = false;
|
||||
int index = PlayingQueueListView.FindChildIndex(frameworkElement);
|
||||
if (index == ViewModel.PlayingSongIndex)
|
||||
var item = (PlayQueueItem)((FrameworkElement)sender).DataContext;
|
||||
int index = ViewModel.TrackPlayingQueue.IndexOf(item);
|
||||
if (item == ViewModel.PlayingQueueItem)
|
||||
{
|
||||
playNext = true;
|
||||
}
|
||||
ViewModel.TrackPlayingQueue.RemoveAt(index);
|
||||
ViewModel.TrackPlayingQueue.Remove(item);
|
||||
if (playNext)
|
||||
{
|
||||
if (ViewModel.TrackPlayingQueue.Count == 0)
|
||||
{
|
||||
index = -1;
|
||||
}
|
||||
else if (index >= ViewModel.TrackPlayingQueue.Count)
|
||||
{
|
||||
index = ViewModel.TrackPlayingQueue.Count - 1;
|
||||
}
|
||||
ViewModel.PlayingSongIndex = index;
|
||||
ViewModel.PlayTrackAt(index);
|
||||
ViewModel.PlayTrackAt(ViewModel.PlayingSongIndex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,7 +103,7 @@ namespace BetterLyrics.WinUI3.Views
|
||||
private void AddSongToQueueNextMenuFlyoutItem_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
bool startPlaying = ViewModel.TrackPlayingQueue.Count == 0;
|
||||
ViewModel.TrackPlayingQueue.InsertRange(ViewModel.PlayingSongIndex + 1, SongListView.SelectedItems.Cast<Track>());
|
||||
ViewModel.TrackPlayingQueue.InsertRange(ViewModel.PlayingSongIndex + 1, SongListView.SelectedItems.Cast<Track>().Select(x => new PlayQueueItem(x)));
|
||||
if (startPlaying)
|
||||
{
|
||||
ViewModel.PlayingSongIndex = ViewModel.PlayingSongIndex + 1;
|
||||
@@ -112,7 +114,7 @@ namespace BetterLyrics.WinUI3.Views
|
||||
private void AddSongToQueueEndMenuFlyoutItem_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
bool startPlaying = ViewModel.TrackPlayingQueue.Count == 0;
|
||||
ViewModel.TrackPlayingQueue.AddRange(SongListView.SelectedItems.Cast<Track>());
|
||||
ViewModel.TrackPlayingQueue.AddRange(SongListView.SelectedItems.Cast<Track>().Select(x => new PlayQueueItem(x)));
|
||||
if (startPlaying)
|
||||
{
|
||||
ViewModel.PlayingSongIndex = ViewModel.PlayingSongIndex + 1;
|
||||
@@ -137,5 +139,33 @@ namespace BetterLyrics.WinUI3.Views
|
||||
SongListView.SelectedItems.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
private void ArtistHyperlibkButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var artist = (string)((HyperlinkButton)sender).Tag;
|
||||
var playlist = new SongsTabInfo(artist, "\uEFA9", true, CommonSongProperty.Artist, artist);
|
||||
ViewModel.UpdateSelectedPlaylist(playlist);
|
||||
}
|
||||
|
||||
private void AlbumHyperlibkButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var album = (string)((HyperlinkButton)sender).Tag;
|
||||
var playlist = new SongsTabInfo(album, "\uE93C", true, CommonSongProperty.Album, album);
|
||||
ViewModel.UpdateSelectedPlaylist(playlist);
|
||||
}
|
||||
|
||||
private void PlaylistGrid_Tapped(object sender, TappedRoutedEventArgs e)
|
||||
{
|
||||
var playlist = (SongsTabInfo)((FrameworkElement)sender).DataContext;
|
||||
ViewModel.UpdateSelectedPlaylist(playlist);
|
||||
}
|
||||
|
||||
private void PlaylistCloseButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var playlist = (SongsTabInfo)((FrameworkElement)sender).DataContext;
|
||||
ViewModel.SongsTabInfoList.Remove(playlist);
|
||||
ViewModel.SelectedSongsTabInfoIndex = 0;
|
||||
ViewModel.ApplyPlaylist();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -935,7 +935,6 @@
|
||||
<Paragraph>
|
||||
<Run x:Uid="SettingsPageVersion" />
|
||||
<Run Text="{x:Bind ViewModel.Version, Mode=OneWay}" />
|
||||
<Run Text="{x:Bind ViewModel.BuildDate, Mode=OneWay}" />
|
||||
</Paragraph>
|
||||
</RichTextBlock>
|
||||
</controls:SettingsCard.Description>
|
||||
@@ -962,6 +961,10 @@
|
||||
<Button x:Uid="SettingsPageJoinNowButton" Click="DiscodGroupButton_Click" />
|
||||
</controls:SettingsCard>
|
||||
|
||||
<controls:SettingsCard x:Uid="SettingsPageTelegram" HeaderIcon="{ui:BitmapIcon Source=ms-appx:///Assets/Telegram.png}">
|
||||
<Button x:Uid="SettingsPageJoinNowButton" Click="TelegramGroupButton_Click" />
|
||||
</controls:SettingsCard>
|
||||
|
||||
</StackPanel>
|
||||
</controls:Case>
|
||||
|
||||
|
||||
@@ -131,5 +131,10 @@ namespace BetterLyrics.WinUI3.Views
|
||||
{
|
||||
Launcher.LaunchUriAsync(new Uri(MetadataHelper.DiscordUrl));
|
||||
}
|
||||
|
||||
private void TelegramGroupButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
Launcher.LaunchUriAsync(new Uri(MetadataHelper.TelegramUrl));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user