diff --git a/src/AmbientSounds.Uwp/AmbientSounds.Uwp.csproj b/src/AmbientSounds.Uwp/AmbientSounds.Uwp.csproj index b9965918..4139fee0 100644 --- a/src/AmbientSounds.Uwp/AmbientSounds.Uwp.csproj +++ b/src/AmbientSounds.Uwp/AmbientSounds.Uwp.csproj @@ -227,6 +227,9 @@ Shimmer.xaml + + SleepTimerButton.xaml + SoundGridControl.xaml @@ -584,6 +587,10 @@ Designer MSBuild:Compile + + Designer + MSBuild:Compile + Designer MSBuild:Compile diff --git a/src/AmbientSounds.Uwp/App.Configuration.xaml.cs b/src/AmbientSounds.Uwp/App.Configuration.xaml.cs index 8726ee3b..87c90e22 100644 --- a/src/AmbientSounds.Uwp/App.Configuration.xaml.cs +++ b/src/AmbientSounds.Uwp/App.Configuration.xaml.cs @@ -181,5 +181,6 @@ private static IServiceProvider ConfigureServices(IAppSettings? appsettings = nu [Singleton(typeof(StreakHistoryCache), typeof(IStreakHistoryCache))] [Singleton(typeof(StreakHistoryRepository), typeof(IStreakHistoryRepository))] [Singleton(typeof(MicrosoftStoreUpdater), typeof(IAppStoreUpdater))] + [Singleton(typeof(SleepTimerService), typeof(ISleepTimerService))] private static partial void ConfigureServices(IServiceCollection services); } diff --git a/src/AmbientSounds.Uwp/App.xaml b/src/AmbientSounds.Uwp/App.xaml index 423d6e37..ad81cc45 100644 --- a/src/AmbientSounds.Uwp/App.xaml +++ b/src/AmbientSounds.Uwp/App.xaml @@ -294,6 +294,8 @@ + + 540 diff --git a/src/AmbientSounds.Uwp/Controls/SleepTimerButton.xaml b/src/AmbientSounds.Uwp/Controls/SleepTimerButton.xaml new file mode 100644 index 00000000..061e75b8 --- /dev/null +++ b/src/AmbientSounds.Uwp/Controls/SleepTimerButton.xaml @@ -0,0 +1,162 @@ + + + + + + diff --git a/src/AmbientSounds.Uwp/Controls/SleepTimerButton.xaml.cs b/src/AmbientSounds.Uwp/Controls/SleepTimerButton.xaml.cs new file mode 100644 index 00000000..ebbbb6d5 --- /dev/null +++ b/src/AmbientSounds.Uwp/Controls/SleepTimerButton.xaml.cs @@ -0,0 +1,20 @@ +using AmbientSounds.ViewModels; +using Microsoft.Extensions.DependencyInjection; +using Windows.UI.Xaml.Controls; + +namespace AmbientSounds.Controls; + +public sealed partial class SleepTimerButton : UserControl +{ + public SleepTimerButton() + { + this.InitializeComponent(); + this.DataContext = App.Services.GetRequiredService(); + } + + public SleepTimerViewModel ViewModel => (SleepTimerViewModel)this.DataContext; + + public void Initialize() => ViewModel.Initialize(); + + public void Uninitialize() => ViewModel.Uninitialize(); +} diff --git a/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.ar.xlf b/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.ar.xlf index 6052a9a9..7a440b48 100644 --- a/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.ar.xlf +++ b/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.ar.xlf @@ -1113,6 +1113,14 @@ Restart اعاده تشغيل + + Ambie will pause when the timer ends + سيتوقف Ambie مؤقتا عند انتهاء المؤقت + + + Sleep Timer + مؤقت النوم + diff --git a/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.bg.xlf b/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.bg.xlf index 6eec5ad1..f2f98749 100644 --- a/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.bg.xlf +++ b/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.bg.xlf @@ -1113,6 +1113,14 @@ Restart Рестартирате + + Ambie will pause when the timer ends + Ambie ще направи пауза, когато таймерът свърши + + + Sleep Timer + Таймер за заспиване + diff --git a/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.cs-CZ.xlf b/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.cs-CZ.xlf index e08d65a3..1ea3800a 100644 --- a/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.cs-CZ.xlf +++ b/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.cs-CZ.xlf @@ -1117,6 +1117,14 @@ Restart Restartovat + + Ambie will pause when the timer ends + Ambie se po skončení časovače pozastaví + + + Sleep Timer + Časovač vypnutí + diff --git a/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.da-DK.xlf b/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.da-DK.xlf index 433b5fa6..a9d3153b 100644 --- a/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.da-DK.xlf +++ b/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.da-DK.xlf @@ -1122,6 +1122,14 @@ Restart Genstarte + + Ambie will pause when the timer ends + Ambie holder pause, når timeren slutter + + + Sleep Timer + Sleep-timer + diff --git a/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.de-DE.xlf b/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.de-DE.xlf index 4a724aa9..917bd1f3 100644 --- a/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.de-DE.xlf +++ b/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.de-DE.xlf @@ -1118,6 +1118,14 @@ Restart Neustarten + + Ambie will pause when the timer ends + Ambie pausiert, wenn der Timer endet + + + Sleep Timer + Sleep-Timer + diff --git a/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.el.xlf b/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.el.xlf index ed8d37a1..efc0927f 100644 --- a/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.el.xlf +++ b/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.el.xlf @@ -1113,6 +1113,14 @@ Restart Επανεκκίνηση + + Ambie will pause when the timer ends + Το Ambie θα σταματήσει όταν τελειώσει το χρονόμετρο + + + Sleep Timer + Χρονοδιακόπτης ύπνου + diff --git a/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.es-ES.xlf b/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.es-ES.xlf index eedb8d9b..bc596eaf 100644 --- a/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.es-ES.xlf +++ b/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.es-ES.xlf @@ -1120,6 +1120,14 @@ Restart Reanudar + + Ambie will pause when the timer ends + Ambie se detendrá cuando finalice el temporizador + + + Sleep Timer + Temporizador + diff --git a/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.fa-IR.xlf b/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.fa-IR.xlf index 571adeca..3dce9c73 100644 --- a/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.fa-IR.xlf +++ b/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.fa-IR.xlf @@ -1113,6 +1113,14 @@ Restart راه اندازی مجدد + + Ambie will pause when the timer ends + Ambie مکث خواهد کرد زمانی که تایمر به پایان می رسد + + + Sleep Timer + تایمر خواب + diff --git a/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.fr-FR.xlf b/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.fr-FR.xlf index ea2c6731..a6e16633 100644 --- a/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.fr-FR.xlf +++ b/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.fr-FR.xlf @@ -1126,6 +1126,14 @@ Restart Redémarrer + + Ambie will pause when the timer ends + Ambie s’arrêtera à la fin de la minuterie + + + Sleep Timer + Minuterie de mise en veille + diff --git a/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.he-IL.xlf b/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.he-IL.xlf index 5e409700..e0f46ceb 100644 --- a/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.he-IL.xlf +++ b/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.he-IL.xlf @@ -1116,6 +1116,14 @@ Restart להפעיל מחדש + + Ambie will pause when the timer ends + אמבי ישהה כשהטיימר יסתיים + + + Sleep Timer + טיימר שינה + diff --git a/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.hr-HR.xlf b/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.hr-HR.xlf index 50c27080..8d6a72d9 100644 --- a/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.hr-HR.xlf +++ b/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.hr-HR.xlf @@ -1120,6 +1120,14 @@ Restart Ponovno pokretanje + + Ambie will pause when the timer ends + Ambie će pauzirati kada tajmer završi + + + Sleep Timer + Mjerač vremena spavanja + diff --git a/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.hu-HU.xlf b/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.hu-HU.xlf index e012ad9a..c7ffdbb9 100644 --- a/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.hu-HU.xlf +++ b/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.hu-HU.xlf @@ -1127,6 +1127,14 @@ Restart Újraindítás + + Ambie will pause when the timer ends + Az Ambie szünetel, amikor az időzítő véget ér + + + Sleep Timer + Elalvás időzítő + diff --git a/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.it-IT.xlf b/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.it-IT.xlf index 59e8ed09..251bac92 100644 --- a/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.it-IT.xlf +++ b/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.it-IT.xlf @@ -1125,6 +1125,14 @@ Restart Riavviare + + Ambie will pause when the timer ends + Ambie si fermerà al termine del timer + + + Sleep Timer + Timer + diff --git a/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.ja-JP.xlf b/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.ja-JP.xlf index 3b3ab0b2..764de14c 100644 --- a/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.ja-JP.xlf +++ b/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.ja-JP.xlf @@ -1113,6 +1113,14 @@ Restart 再起動 + + Ambie will pause when the timer ends + タイマーが終了すると、Ambie は一時停止します + + + Sleep Timer + スリープタイマー + diff --git a/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.ko-KR.xlf b/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.ko-KR.xlf index 99b6413d..6f6b1e62 100644 --- a/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.ko-KR.xlf +++ b/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.ko-KR.xlf @@ -1117,6 +1117,14 @@ Restart 다시 시작할 + + Ambie will pause when the timer ends + 타이머가 끝나면 Ambie가 일시 중지됩니다. + + + Sleep Timer + 취침 타이머 + diff --git a/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.nl-BE.xlf b/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.nl-BE.xlf index de49d00b..c92711c6 100644 --- a/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.nl-BE.xlf +++ b/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.nl-BE.xlf @@ -1122,6 +1122,14 @@ Restart Herstarten + + Ambie will pause when the timer ends + Ambie pauzeert wanneer de timer afloopt + + + Sleep Timer + Slaap Timer + diff --git a/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.pl-PL.xlf b/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.pl-PL.xlf index 42f7d8c0..3bd6be98 100644 --- a/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.pl-PL.xlf +++ b/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.pl-PL.xlf @@ -1118,6 +1118,14 @@ Restart Restart + + Ambie will pause when the timer ends + Ambie zatrzyma się, gdy skończy się odliczanie + + + Sleep Timer + Wyłącznik czasowy + diff --git a/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.pt-PT.xlf b/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.pt-PT.xlf index 402ae622..d0b961f0 100644 --- a/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.pt-PT.xlf +++ b/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.pt-PT.xlf @@ -1117,6 +1117,14 @@ Restart Reiniciar + + Ambie will pause when the timer ends + O Ambie será pausado quando o temporizador terminar + + + Sleep Timer + Temporizador de sono + diff --git a/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.ro-MD.xlf b/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.ro-MD.xlf index 0a8fe4f0..0fbc4efb 100644 --- a/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.ro-MD.xlf +++ b/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.ro-MD.xlf @@ -1113,6 +1113,14 @@ Restart Reîncepe + + Ambie will pause when the timer ends + Ambie se va întrerupe când cronometrul se termină + + + Sleep Timer + Temporizator de oprire + diff --git a/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.ro-RO.xlf b/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.ro-RO.xlf index 00f28732..bc3c8060 100644 --- a/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.ro-RO.xlf +++ b/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.ro-RO.xlf @@ -1113,6 +1113,14 @@ Restart Reîncepe + + Ambie will pause when the timer ends + Ambie se va întrerupe când cronometrul se termină + + + Sleep Timer + Temporizator de oprire + diff --git a/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.sv-SE.xlf b/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.sv-SE.xlf index 044c8391..92a2dd2a 100644 --- a/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.sv-SE.xlf +++ b/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.sv-SE.xlf @@ -1119,6 +1119,14 @@ Restart Starta om + + Ambie will pause when the timer ends + Ambie pausar när timern slutar + + + Sleep Timer + Insomningstimer + diff --git a/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.tr.xlf b/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.tr.xlf index 1e8bebc0..5573250d 100644 --- a/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.tr.xlf +++ b/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.tr.xlf @@ -1127,6 +1127,14 @@ Restart Yeni -den başlatın + + Ambie will pause when the timer ends + Zamanlayıcı sona erdiğinde Ambie duraklayacaktır + + + Sleep Timer + Uyku Zamanlayıcısı + diff --git a/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.uk-UA.xlf b/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.uk-UA.xlf index 016e2d57..370bb428 100644 --- a/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.uk-UA.xlf +++ b/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.uk-UA.xlf @@ -1118,6 +1118,14 @@ Restart Перезавантажувати + + Ambie will pause when the timer ends + Ambie зробить паузу, коли таймер закінчиться + + + Sleep Timer + Таймер сну + diff --git a/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.zh-CN.xlf b/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.zh-CN.xlf index 8dc3bfa1..9fd404a8 100644 --- a/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.zh-CN.xlf +++ b/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.zh-CN.xlf @@ -1116,6 +1116,14 @@ Restart 重新启动 + + Ambie will pause when the timer ends + 当计时器结束时,Ambie 将暂停 + + + Sleep Timer + 睡眠定时器 + diff --git a/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.zh-Hant.xlf b/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.zh-Hant.xlf index 6e9aef63..e2b99bf2 100644 --- a/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.zh-Hant.xlf +++ b/src/AmbientSounds.Uwp/MultilingualResources/AmbientSounds.Uwp.zh-Hant.xlf @@ -1116,6 +1116,14 @@ Restart 重新啟動 + + Ambie will pause when the timer ends + 當計時器結束時,Ambie 將暫停 + + + Sleep Timer + 睡眠定時器 + diff --git a/src/AmbientSounds.Uwp/Strings/ar/Resources.resw b/src/AmbientSounds.Uwp/Strings/ar/Resources.resw index f2392f51..90585424 100644 --- a/src/AmbientSounds.Uwp/Strings/ar/Resources.resw +++ b/src/AmbientSounds.Uwp/Strings/ar/Resources.resw @@ -845,4 +845,10 @@ اعاده تشغيل + + سيتوقف Ambie مؤقتا عند انتهاء المؤقت + + + مؤقت النوم + \ No newline at end of file diff --git a/src/AmbientSounds.Uwp/Strings/bg/Resources.resw b/src/AmbientSounds.Uwp/Strings/bg/Resources.resw index 1301092c..88a60a0d 100644 --- a/src/AmbientSounds.Uwp/Strings/bg/Resources.resw +++ b/src/AmbientSounds.Uwp/Strings/bg/Resources.resw @@ -845,4 +845,10 @@ Рестартирате + + Ambie ще направи пауза, когато таймерът свърши + + + Таймер за заспиване + \ No newline at end of file diff --git a/src/AmbientSounds.Uwp/Strings/cs-CZ/Resources.resw b/src/AmbientSounds.Uwp/Strings/cs-CZ/Resources.resw index e51c1824..95790a69 100644 --- a/src/AmbientSounds.Uwp/Strings/cs-CZ/Resources.resw +++ b/src/AmbientSounds.Uwp/Strings/cs-CZ/Resources.resw @@ -845,4 +845,10 @@ Restartovat + + Ambie se po skončení časovače pozastaví + + + Časovač vypnutí + \ No newline at end of file diff --git a/src/AmbientSounds.Uwp/Strings/da-DK/Resources.resw b/src/AmbientSounds.Uwp/Strings/da-DK/Resources.resw index 15bc481c..0afb7643 100644 --- a/src/AmbientSounds.Uwp/Strings/da-DK/Resources.resw +++ b/src/AmbientSounds.Uwp/Strings/da-DK/Resources.resw @@ -845,4 +845,10 @@ Genstarte + + Ambie holder pause, når timeren slutter + + + Sleep-timer + \ No newline at end of file diff --git a/src/AmbientSounds.Uwp/Strings/de-DE/Resources.resw b/src/AmbientSounds.Uwp/Strings/de-DE/Resources.resw index 8babd6fd..fb430473 100644 --- a/src/AmbientSounds.Uwp/Strings/de-DE/Resources.resw +++ b/src/AmbientSounds.Uwp/Strings/de-DE/Resources.resw @@ -845,4 +845,10 @@ Neustarten + + Ambie pausiert, wenn der Timer endet + + + Sleep-Timer + \ No newline at end of file diff --git a/src/AmbientSounds.Uwp/Strings/el/Resources.resw b/src/AmbientSounds.Uwp/Strings/el/Resources.resw index ee3fd5aa..6fc62221 100644 --- a/src/AmbientSounds.Uwp/Strings/el/Resources.resw +++ b/src/AmbientSounds.Uwp/Strings/el/Resources.resw @@ -830,4 +830,10 @@ Επανεκκίνηση + + Το Ambie θα σταματήσει όταν τελειώσει το χρονόμετρο + + + Χρονοδιακόπτης ύπνου + \ No newline at end of file diff --git a/src/AmbientSounds.Uwp/Strings/en-US/Resources.generated.cs b/src/AmbientSounds.Uwp/Strings/en-US/Resources.generated.cs index bb8e2469..05e61e64 100644 --- a/src/AmbientSounds.Uwp/Strings/en-US/Resources.generated.cs +++ b/src/AmbientSounds.Uwp/Strings/en-US/Resources.generated.cs @@ -2809,6 +2809,32 @@ public static string RestartText } } #endregion + + #region SleepTimerDescription + /// + /// Looks up a localized string similar to: Ambie will pause when the timer ends + /// + public static string SleepTimerDescription + { + get + { + return _resourceLoader.GetString("SleepTimerDescription"); + } + } + #endregion + + #region SleepTimerText + /// + /// Looks up a localized string similar to: Sleep Timer + /// + public static string SleepTimerText + { + get + { + return _resourceLoader.GetString("SleepTimerText"); + } + } + #endregion } [global::System.CodeDom.Compiler.GeneratedCodeAttribute("DotNetPlus.ReswPlus", "2.1.3")] @@ -3035,6 +3061,8 @@ public enum KeyEnum SettingsModifySubDescription, AppUpdateDescription, RestartText, + SleepTimerDescription, + SleepTimerText, } private static ResourceLoader _resourceLoader; diff --git a/src/AmbientSounds.Uwp/Strings/en-US/Resources.resw b/src/AmbientSounds.Uwp/Strings/en-US/Resources.resw index 35553592..24dfa4ae 100644 --- a/src/AmbientSounds.Uwp/Strings/en-US/Resources.resw +++ b/src/AmbientSounds.Uwp/Strings/en-US/Resources.resw @@ -950,4 +950,10 @@ Restart + + Ambie will pause when the timer ends + + + Sleep Timer + \ No newline at end of file diff --git a/src/AmbientSounds.Uwp/Strings/es-ES/Resources.resw b/src/AmbientSounds.Uwp/Strings/es-ES/Resources.resw index 55e7fc77..c78a16a4 100644 --- a/src/AmbientSounds.Uwp/Strings/es-ES/Resources.resw +++ b/src/AmbientSounds.Uwp/Strings/es-ES/Resources.resw @@ -845,4 +845,10 @@ Reanudar + + Ambie se detendrá cuando finalice el temporizador + + + Temporizador + \ No newline at end of file diff --git a/src/AmbientSounds.Uwp/Strings/fa-IR/Resources.resw b/src/AmbientSounds.Uwp/Strings/fa-IR/Resources.resw index ab3ffa0d..06c17f5e 100644 --- a/src/AmbientSounds.Uwp/Strings/fa-IR/Resources.resw +++ b/src/AmbientSounds.Uwp/Strings/fa-IR/Resources.resw @@ -845,4 +845,10 @@ راه اندازی مجدد + + Ambie مکث خواهد کرد زمانی که تایمر به پایان می رسد + + + تایمر خواب + \ No newline at end of file diff --git a/src/AmbientSounds.Uwp/Strings/fr-FR/Resources.resw b/src/AmbientSounds.Uwp/Strings/fr-FR/Resources.resw index e9b9d1c1..b5965938 100644 --- a/src/AmbientSounds.Uwp/Strings/fr-FR/Resources.resw +++ b/src/AmbientSounds.Uwp/Strings/fr-FR/Resources.resw @@ -842,4 +842,10 @@ Redémarrer + + Ambie s’arrêtera à la fin de la minuterie + + + Minuterie de mise en veille + \ No newline at end of file diff --git a/src/AmbientSounds.Uwp/Strings/he-IL/Resources.resw b/src/AmbientSounds.Uwp/Strings/he-IL/Resources.resw index a13affbb..2f8650fc 100644 --- a/src/AmbientSounds.Uwp/Strings/he-IL/Resources.resw +++ b/src/AmbientSounds.Uwp/Strings/he-IL/Resources.resw @@ -845,4 +845,10 @@ להפעיל מחדש + + אמבי ישהה כשהטיימר יסתיים + + + טיימר שינה + \ No newline at end of file diff --git a/src/AmbientSounds.Uwp/Strings/hr-HR/Resources.resw b/src/AmbientSounds.Uwp/Strings/hr-HR/Resources.resw index 10c4b7e9..dcd169c4 100644 --- a/src/AmbientSounds.Uwp/Strings/hr-HR/Resources.resw +++ b/src/AmbientSounds.Uwp/Strings/hr-HR/Resources.resw @@ -833,4 +833,10 @@ Ponovno pokretanje + + Ambie će pauzirati kada tajmer završi + + + Mjerač vremena spavanja + \ No newline at end of file diff --git a/src/AmbientSounds.Uwp/Strings/hu-HU/Resources.resw b/src/AmbientSounds.Uwp/Strings/hu-HU/Resources.resw index 1ac78f6c..afcd502f 100644 --- a/src/AmbientSounds.Uwp/Strings/hu-HU/Resources.resw +++ b/src/AmbientSounds.Uwp/Strings/hu-HU/Resources.resw @@ -833,4 +833,10 @@ Újraindítás + + Az Ambie szünetel, amikor az időzítő véget ér + + + Elalvás időzítő + \ No newline at end of file diff --git a/src/AmbientSounds.Uwp/Strings/it-IT/Resources.resw b/src/AmbientSounds.Uwp/Strings/it-IT/Resources.resw index ec2aa246..3c5f743a 100644 --- a/src/AmbientSounds.Uwp/Strings/it-IT/Resources.resw +++ b/src/AmbientSounds.Uwp/Strings/it-IT/Resources.resw @@ -845,4 +845,10 @@ Riavviare + + Ambie si fermerà al termine del timer + + + Timer + \ No newline at end of file diff --git a/src/AmbientSounds.Uwp/Strings/ja-JP/Resources.resw b/src/AmbientSounds.Uwp/Strings/ja-JP/Resources.resw index 62c96966..2e1910a6 100644 --- a/src/AmbientSounds.Uwp/Strings/ja-JP/Resources.resw +++ b/src/AmbientSounds.Uwp/Strings/ja-JP/Resources.resw @@ -845,4 +845,10 @@ 再起動 + + タイマーが終了すると、Ambie は一時停止します + + + スリープタイマー + \ No newline at end of file diff --git a/src/AmbientSounds.Uwp/Strings/ko-KR/Resources.resw b/src/AmbientSounds.Uwp/Strings/ko-KR/Resources.resw index bb90af96..bdc88692 100644 --- a/src/AmbientSounds.Uwp/Strings/ko-KR/Resources.resw +++ b/src/AmbientSounds.Uwp/Strings/ko-KR/Resources.resw @@ -845,4 +845,10 @@ 다시 시작할 + + 타이머가 끝나면 Ambie가 일시 중지됩니다. + + + 취침 타이머 + \ No newline at end of file diff --git a/src/AmbientSounds.Uwp/Strings/nl-BE/Resources.resw b/src/AmbientSounds.Uwp/Strings/nl-BE/Resources.resw index d6ab9827..d6657c4c 100644 --- a/src/AmbientSounds.Uwp/Strings/nl-BE/Resources.resw +++ b/src/AmbientSounds.Uwp/Strings/nl-BE/Resources.resw @@ -815,4 +815,10 @@ Herstarten + + Ambie pauzeert wanneer de timer afloopt + + + Slaap Timer + \ No newline at end of file diff --git a/src/AmbientSounds.Uwp/Strings/pl-PL/Resources.resw b/src/AmbientSounds.Uwp/Strings/pl-PL/Resources.resw index 733d4449..5e7f4d4d 100644 --- a/src/AmbientSounds.Uwp/Strings/pl-PL/Resources.resw +++ b/src/AmbientSounds.Uwp/Strings/pl-PL/Resources.resw @@ -842,4 +842,10 @@ Dostępna jest nowa aktualizacja! Uruchom ponownie teraz, aby zastosować aktualizację. + + Ambie zatrzyma się, gdy skończy się odliczanie + + + Wyłącznik czasowy + \ No newline at end of file diff --git a/src/AmbientSounds.Uwp/Strings/pt-PT/Resources.resw b/src/AmbientSounds.Uwp/Strings/pt-PT/Resources.resw index 0a1052e7..1c4d8dc7 100644 --- a/src/AmbientSounds.Uwp/Strings/pt-PT/Resources.resw +++ b/src/AmbientSounds.Uwp/Strings/pt-PT/Resources.resw @@ -845,4 +845,10 @@ Reiniciar + + O Ambie será pausado quando o temporizador terminar + + + Temporizador de sono + \ No newline at end of file diff --git a/src/AmbientSounds.Uwp/Strings/ro-MD/Resources.resw b/src/AmbientSounds.Uwp/Strings/ro-MD/Resources.resw index f6ed02e0..c2e8894f 100644 --- a/src/AmbientSounds.Uwp/Strings/ro-MD/Resources.resw +++ b/src/AmbientSounds.Uwp/Strings/ro-MD/Resources.resw @@ -845,4 +845,10 @@ Reîncepe + + Ambie se va întrerupe când cronometrul se termină + + + Temporizator de oprire + \ No newline at end of file diff --git a/src/AmbientSounds.Uwp/Strings/ro-RO/Resources.resw b/src/AmbientSounds.Uwp/Strings/ro-RO/Resources.resw index f6ed02e0..c2e8894f 100644 --- a/src/AmbientSounds.Uwp/Strings/ro-RO/Resources.resw +++ b/src/AmbientSounds.Uwp/Strings/ro-RO/Resources.resw @@ -845,4 +845,10 @@ Reîncepe + + Ambie se va întrerupe când cronometrul se termină + + + Temporizator de oprire + \ No newline at end of file diff --git a/src/AmbientSounds.Uwp/Strings/sv-SE/Resources.resw b/src/AmbientSounds.Uwp/Strings/sv-SE/Resources.resw index ea2351ab..5e256bae 100644 --- a/src/AmbientSounds.Uwp/Strings/sv-SE/Resources.resw +++ b/src/AmbientSounds.Uwp/Strings/sv-SE/Resources.resw @@ -845,4 +845,10 @@ Starta om + + Ambie pausar när timern slutar + + + Insomningstimer + \ No newline at end of file diff --git a/src/AmbientSounds.Uwp/Strings/tr/Resources.resw b/src/AmbientSounds.Uwp/Strings/tr/Resources.resw index 78709811..a24d771b 100644 --- a/src/AmbientSounds.Uwp/Strings/tr/Resources.resw +++ b/src/AmbientSounds.Uwp/Strings/tr/Resources.resw @@ -839,4 +839,10 @@ Yeni -den başlatın + + Zamanlayıcı sona erdiğinde Ambie duraklayacaktır + + + Uyku Zamanlayıcısı + \ No newline at end of file diff --git a/src/AmbientSounds.Uwp/Strings/uk-UA/Resources.resw b/src/AmbientSounds.Uwp/Strings/uk-UA/Resources.resw index bdab6579..eb5b99c4 100644 --- a/src/AmbientSounds.Uwp/Strings/uk-UA/Resources.resw +++ b/src/AmbientSounds.Uwp/Strings/uk-UA/Resources.resw @@ -845,4 +845,10 @@ Перезавантажувати + + Ambie зробить паузу, коли таймер закінчиться + + + Таймер сну + \ No newline at end of file diff --git a/src/AmbientSounds.Uwp/Strings/zh-CN/Resources.resw b/src/AmbientSounds.Uwp/Strings/zh-CN/Resources.resw index d131e58c..0e78bc1b 100644 --- a/src/AmbientSounds.Uwp/Strings/zh-CN/Resources.resw +++ b/src/AmbientSounds.Uwp/Strings/zh-CN/Resources.resw @@ -845,4 +845,10 @@ 重新启动 + + 当计时器结束时,Ambie 将暂停 + + + 睡眠定时器 + \ No newline at end of file diff --git a/src/AmbientSounds.Uwp/Strings/zh-Hant/Resources.resw b/src/AmbientSounds.Uwp/Strings/zh-Hant/Resources.resw index 48a880db..e7bae59f 100644 --- a/src/AmbientSounds.Uwp/Strings/zh-Hant/Resources.resw +++ b/src/AmbientSounds.Uwp/Strings/zh-Hant/Resources.resw @@ -845,4 +845,10 @@ 重新啟動 + + 當計時器結束時,Ambie 將暫停 + + + 睡眠定時器 + \ No newline at end of file diff --git a/src/AmbientSounds.Uwp/Views/ShellPage.xaml b/src/AmbientSounds.Uwp/Views/ShellPage.xaml index ad8d73c5..23e2f977 100644 --- a/src/AmbientSounds.Uwp/Views/ShellPage.xaml +++ b/src/AmbientSounds.Uwp/Views/ShellPage.xaml @@ -195,6 +195,7 @@ Duration="0:0:0.6" /> + + + diff --git a/src/AmbientSounds.Uwp/Views/ShellPage.xaml.cs b/src/AmbientSounds.Uwp/Views/ShellPage.xaml.cs index fe647d14..953fa654 100644 --- a/src/AmbientSounds.Uwp/Views/ShellPage.xaml.cs +++ b/src/AmbientSounds.Uwp/Views/ShellPage.xaml.cs @@ -62,12 +62,14 @@ protected override async void OnNavigatedTo(NavigationEventArgs e) } } + SleepTimer.Initialize(); await ViewModel.InitializeAsync(); } protected override void OnNavigatedFrom(NavigationEventArgs e) { App.Services.GetRequiredService().Frame = null; + SleepTimer.Uninitialize(); ViewModel.Uninitialize(); } diff --git a/src/AmbientSounds/Services/ISleepTimerService.cs b/src/AmbientSounds/Services/ISleepTimerService.cs new file mode 100644 index 00000000..108a7e9a --- /dev/null +++ b/src/AmbientSounds/Services/ISleepTimerService.cs @@ -0,0 +1,56 @@ +using System; + +namespace AmbientSounds.Services +{ + public interface ISleepTimerService + { + /// + /// Time left in the sleep timer in the form of a + /// decrementing percentage. E.g. 100 > 99 > 98... + /// + double PercentLeft { get; } + + /// + /// Time left in the sleep timer in the form of a TimeSpan. + /// + TimeSpan TimeLeft { get; } + + /// + /// The current . + /// + SleepTimerState State { get; } + + /// + /// Raised when the timer is running and its interval elapses. + /// + event EventHandler? TimerIntervalElapsed; + + /// + /// Raised when the state of the timer changes. + /// + event EventHandler? StateChanged; + + /// + /// Pauses the timer. + /// + void PauseTimer(); + + /// + /// Resumes the timer. If + /// had not been run yet, then this is a no-op. + /// + void ResumeTimer(); + + /// + /// Starts the timer using the given number of minutes as the + /// countdown time. + /// + /// The length of the timer in minutes. + void StartTimer(int minutes); + + /// + /// Stops the timer and resets the countdown to 0. + /// + void StopTimer(); + } +} \ No newline at end of file diff --git a/src/AmbientSounds/Services/PlaybackModeObserver.cs b/src/AmbientSounds/Services/PlaybackModeObserver.cs index e4d6bdc2..3c6d963d 100644 --- a/src/AmbientSounds/Services/PlaybackModeObserver.cs +++ b/src/AmbientSounds/Services/PlaybackModeObserver.cs @@ -9,16 +9,28 @@ public class PlaybackModeObserver { private readonly IFocusService _focusService; private readonly IGuideService _guideService; + private readonly ISleepTimerService _sleepTimerService; public PlaybackModeObserver( IFocusService focusService, - IGuideService guideService) + IGuideService guideService, + ISleepTimerService sleepTimerService) { _focusService = focusService; _guideService = guideService; + _sleepTimerService = sleepTimerService; _focusService.FocusStateChanged += OnFocusStateChanged; _guideService.GuideStarted += OnGuideStarted; + _sleepTimerService.StateChanged += OnSleepTimerStateChanged; + } + + private void OnSleepTimerStateChanged(object sender, SleepTimerState e) + { + if (e is SleepTimerState.Running) + { + _focusService.StopTimer(pauseSounds: false); + } } private void OnGuideStarted(object sender, string e) @@ -34,6 +46,7 @@ private void OnFocusStateChanged(object sender, FocusState e) if (e == FocusState.Active) { _guideService.Stop(); + _sleepTimerService.StopTimer(); } } } diff --git a/src/AmbientSounds/Services/SleepTimerService.cs b/src/AmbientSounds/Services/SleepTimerService.cs new file mode 100644 index 00000000..c414138f --- /dev/null +++ b/src/AmbientSounds/Services/SleepTimerService.cs @@ -0,0 +1,132 @@ +using AmbientSounds.Tools; +using System; + +namespace AmbientSounds.Services; + +public sealed class SleepTimerService : ISleepTimerService +{ + private const int DefaultTimerInterval = 1000; // ms + private readonly IMixMediaPlayerService _player; + private readonly ITimerService _timer; + private double _originalTime; + private SleepTimerState _state; + + /// + public event EventHandler? TimerIntervalElapsed; + + /// + public event EventHandler? StateChanged; + + public SleepTimerService(IMixMediaPlayerService player, ITimerService timer) + { + _player = player; + _timer = timer; + _timer.Interval = DefaultTimerInterval; + + _timer.IntervalElapsed += OnTimerIntervalElapsed; + _player.PlaybackStateChanged += OnPlaybackStateChanged; + } + + /// + public SleepTimerState State + { + get => _state; + private set + { + if (value != _state) + { + _state = value; + StateChanged?.Invoke(this, _state); + } + } + } + + /// + public TimeSpan TimeLeft => _timer.Remaining; + + /// + public double PercentLeft => _originalTime == 0 + ? 0 + : TimeLeft.TotalMinutes / _originalTime * 100; + + /// + public void StartTimer(int minutes) + { + if (minutes == 0) + { + StopTimer(); + return; + } + + _originalTime = minutes; + var timeLeft = TimeSpan.FromMinutes(minutes); + _timer.Remaining = timeLeft; + State = SleepTimerState.Running; + + if (_player.PlaybackState is MediaPlaybackState.Playing) + { + _timer.Start(); + } + } + + /// + public void StopTimer() + { + _timer.Stop(); + _timer.Remaining = TimeSpan.Zero; + _originalTime = 0; + State = SleepTimerState.Off; + } + + /// + public void ResumeTimer() + { + if (_timer.Remaining > TimeSpan.Zero) + { + _timer.Start(); + State = SleepTimerState.Running; + } + } + + /// + public void PauseTimer() + { + _timer.Stop(); + State = SleepTimerState.Paused; + } + + private void OnTimerIntervalElapsed(object sender, TimeSpan remaining) + { + if (remaining < TimeSpan.FromSeconds(1)) + { + StopTimer(); + _player.Pause(); + } + + TimerIntervalElapsed?.Invoke(sender, remaining); + } + + private void OnPlaybackStateChanged(object sender, MediaPlaybackState e) + { + if (State is SleepTimerState.Off) + { + return; + } + + if (e is MediaPlaybackState.Paused) + { + PauseTimer(); + } + else if (e is MediaPlaybackState.Opening or MediaPlaybackState.Playing) + { + ResumeTimer(); + } + } +} + +public enum SleepTimerState +{ + Off, + Running, + Paused, +} diff --git a/src/AmbientSounds/ViewModels/SleepTimerViewModel.cs b/src/AmbientSounds/ViewModels/SleepTimerViewModel.cs index 1fb3cb13..2845a1d0 100644 --- a/src/AmbientSounds/ViewModels/SleepTimerViewModel.cs +++ b/src/AmbientSounds/ViewModels/SleepTimerViewModel.cs @@ -1,29 +1,45 @@ using AmbientSounds.Constants; using AmbientSounds.Services; -using AmbientSounds.Tools; -using CommunityToolkit.Diagnostics; using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; -using System; -using System.Collections.Generic; +using Humanizer; +using Humanizer.Localisation; using JeniusApps.Common.Telemetry; using JeniusApps.Common.Tools; +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; namespace AmbientSounds.ViewModels; public partial class SleepTimerViewModel : ObservableObject { - private const int DefaultTimerInterval = 1000; // ms - private readonly IMixMediaPlayerService _player; + private readonly ISleepTimerService _sleepTimerService; private readonly ITelemetry _telemetry; - private readonly ITimerService _timer; private readonly IDispatcherQueue _dispatcherQueue; + private readonly ILocalizer _localizer; + private readonly int[] _timeOptions = [15, 30, 45, 60, 90, 120]; - [ObservableProperty] - private bool _playVisible; + public SleepTimerViewModel( + ISleepTimerService sleepTimerService, + ITelemetry telemetry, + IDispatcherQueue dispatcherQueue, + ILocalizer localizer) + { + _sleepTimerService = sleepTimerService; + _telemetry = telemetry; + _dispatcherQueue = dispatcherQueue; + _localizer = localizer; - [ObservableProperty] - private bool _stopVisible; + Options.Add(new SleepTimerOptionsViewModel(0, _localizer.GetString("OffTextBlock/Text"), StartTimerCommand)); + + foreach (var option in _timeOptions) + { + Options.Add(new SleepTimerOptionsViewModel(option, TimeSpan.FromMinutes(option).Humanize(maxUnit: TimeUnit.Minute), StartTimerCommand)); + } + + Options[0].IsActive = true; + } /// /// Determines if the sleep timer's countdown is visible. @@ -31,110 +47,115 @@ public partial class SleepTimerViewModel : ObservableObject [ObservableProperty] private bool _countdownVisible; - public SleepTimerViewModel( - IMixMediaPlayerService player, - ITimerService timer, - ITelemetry telemetry, - IDispatcherQueue dispatcherQueue) - { - Guard.IsNotNull(player); - Guard.IsNotNull(timer); - Guard.IsNotNull(telemetry); - Guard.IsNotNull(dispatcherQueue); - - _player = player; - _timer = timer; - _telemetry = telemetry; - _dispatcherQueue = dispatcherQueue; - _timer.Interval = DefaultTimerInterval; - } - - private void OnPlaybackStateChanged(object sender, MediaPlaybackState e) - { - if (e == MediaPlaybackState.Paused) - PauseTimer(); - else if (e == MediaPlaybackState.Opening || e == MediaPlaybackState.Playing) - PlayTimer(); - } - /// /// String representation of time remaining. /// E.g. 0:59:12 for 59 minutes and 12 seconds left. /// - public string TimeLeft => _timer.Remaining.ToString("g"); + [ObservableProperty] + private string _timeLeft = string.Empty; + + /// + /// Time left in the sleep timer in the form of a + /// decrementing percentage. E.g. 100 > 99 > 98... + /// + [ObservableProperty] + private double _percentLeft; + public ObservableCollection Options { get; } = []; + [RelayCommand] private void StartTimer(int minutes) { + if (minutes == 0) + { + StopTimer(); + return; + } + + foreach (var option in Options) + { + option.IsActive = option.Minutes == minutes; + } + + _sleepTimerService.StartTimer(minutes); + UpdateTimeLeft(); + CountdownVisible = true; + _telemetry.TrackEvent(TelemetryConstants.TimeSelected, new Dictionary { { "length", minutes.ToString() } }); - - _timer.Remaining = TimeSpan.FromMinutes(minutes); - OnPropertyChanged(nameof(TimeLeft)); - CountdownVisible = true; - _timer.Start(); - StopVisible = true; - PlayVisible = false; } [RelayCommand] - private void PlayTimer() + private void StopTimer() { - if (_timer.Remaining > TimeSpan.Zero) + foreach (var option in Options) { - _timer.Start(); - StopVisible = true; - PlayVisible = false; + option.IsActive = option.Minutes == 0; } + + _sleepTimerService.StopTimer(); + UpdateTimeLeft(); + CountdownVisible = false; } - [RelayCommand] - private void PauseTimer() + private void TimerElapsed(object sender, TimeSpan remaining) { - _timer.Stop(); - StopVisible = false; + _dispatcherQueue.TryEnqueue(UpdateTimeLeft); + } - if (_timer.Remaining > TimeSpan.Zero) - { - PlayVisible = true; - } + public void Initialize() + { + _sleepTimerService.TimerIntervalElapsed += TimerElapsed; + _sleepTimerService.StateChanged += StateChanged; } - [RelayCommand] - private void StopTimer() + public void Uninitialize() { - _timer.Stop(); - _timer.Remaining = TimeSpan.Zero; - OnPropertyChanged(nameof(TimeLeft)); - CountdownVisible = false; - StopVisible = false; - PlayVisible = false; + _sleepTimerService.TimerIntervalElapsed -= TimerElapsed; + _sleepTimerService.StateChanged -= StateChanged; } - private void TimerElapsed(object sender, TimeSpan remaining) + private void UpdateTimeLeft() { - _dispatcherQueue.TryEnqueue(() => + TimeLeft = _sleepTimerService.TimeLeft.ToString("g"); + PercentLeft = _sleepTimerService.PercentLeft; + } + + private void StateChanged(object sender, SleepTimerState e) + { + if (e is SleepTimerState.Off) { - OnPropertyChanged(nameof(TimeLeft)); - if (remaining < TimeSpan.FromSeconds(1)) - { - StopTimer(); - _player.Pause(); - } - }); + CountdownVisible = false; + } } +} - public void Initialize() +public sealed partial class SleepTimerOptionsViewModel : ObservableObject +{ + private readonly IRelayCommand _startCommand; + + public SleepTimerOptionsViewModel( + int minutes, + string label, + IRelayCommand startCommand) { - _timer.IntervalElapsed += TimerElapsed; - _player.PlaybackStateChanged += OnPlaybackStateChanged; + Minutes = minutes; + Label = label; + _startCommand = startCommand; } - public void Dispose() + [ObservableProperty] + private bool _isActive; + + public string Label { get; } = string.Empty; + + public int Minutes { get; } + + [RelayCommand] + public void Start() { - _timer.IntervalElapsed -= TimerElapsed; - _player.PlaybackStateChanged -= OnPlaybackStateChanged; + _startCommand.Execute(Minutes); } }