├── Resources ├── 吊兰.png ├── 多肉.png ├── 绿箩.png ├── 青松.png ├── icon.ico ├── 仙人掌.png ├── 向日葵.png └── iconfont.ttf ├── App.xaml.cs ├── HourMark.cs ├── README.md ├── AssemblyInfo.cs ├── BindingProxy.cs ├── Behaviors ├── GetTextFocusedBehavior.cs ├── DurationValidataRule.cs ├── ClickToChangeBgBehavior.cs ├── TimeInOrDeBehavior.cs └── TimeButtonExtension.cs ├── Converters ├── RestTimesToStringConverter.cs ├── BoolToVisibilityReverseConverter.cs ├── BoolToVisibilityConverter.cs └── RemainingTimeToStringConverter.cs ├── PomodoroTimer.sln ├── MainWindow.xaml.cs ├── PomodoroTimer.csproj ├── .gitattributes ├── .gitignore ├── WindowAccentCompositor.cs ├── MainWindowViewModel.cs ├── MainWindow.xaml └── App.xaml /Resources/吊兰.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hinadesu39/PomodoroTimer/HEAD/Resources/吊兰.png -------------------------------------------------------------------------------- /Resources/多肉.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hinadesu39/PomodoroTimer/HEAD/Resources/多肉.png -------------------------------------------------------------------------------- /Resources/绿箩.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hinadesu39/PomodoroTimer/HEAD/Resources/绿箩.png -------------------------------------------------------------------------------- /Resources/青松.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hinadesu39/PomodoroTimer/HEAD/Resources/青松.png -------------------------------------------------------------------------------- /Resources/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hinadesu39/PomodoroTimer/HEAD/Resources/icon.ico -------------------------------------------------------------------------------- /Resources/仙人掌.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hinadesu39/PomodoroTimer/HEAD/Resources/仙人掌.png -------------------------------------------------------------------------------- /Resources/向日葵.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hinadesu39/PomodoroTimer/HEAD/Resources/向日葵.png -------------------------------------------------------------------------------- /Resources/iconfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hinadesu39/PomodoroTimer/HEAD/Resources/iconfont.ttf -------------------------------------------------------------------------------- /App.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.Configuration; 2 | using System.Data; 3 | using System.Windows; 4 | 5 | namespace PomodoroTimer 6 | { 7 | /// 8 | /// Interaction logic for App.xaml 9 | /// 10 | public partial class App : Application 11 | { 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /HourMark.cs: -------------------------------------------------------------------------------- 1 | using CommunityToolkit.Mvvm.ComponentModel; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows.Data; 8 | using System.Windows.Media; 9 | 10 | namespace PomodoroTimer 11 | { 12 | public partial class HourMark : ObservableObject 13 | { 14 | private LineGeometry data; 15 | 16 | public LineGeometry Data 17 | { 18 | get { return data; } 19 | set { data = value; } 20 | } 21 | 22 | [ObservableProperty] 23 | private bool isFill = false; 24 | 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PomodoroTimer 2 | ## 复刻win11原生专注工具 3 | ![屏幕截图 2024-04-07 102825](https://github.com/hinadesu39/PomodoroTimer/assets/131540418/ce9d8559-3a1a-485e-87ef-4d24e4170bd0) 4 | ![屏幕截图 2024-04-07 102834](https://github.com/hinadesu39/PomodoroTimer/assets/131540418/a94ba0c1-3648-48fa-8dce-9d8a958785bf) 5 | ![屏幕截图 2024-04-07 102839](https://github.com/hinadesu39/PomodoroTimer/assets/131540418/7ab0c87d-fa67-414f-b3b7-8b851babe0da) 6 | ![屏幕截图 2024-04-07 102848](https://github.com/hinadesu39/PomodoroTimer/assets/131540418/1d370a2c-537f-4291-b22d-edccf08029c4) 7 | ![屏幕截图 2024-04-07 133835](https://github.com/hinadesu39/PomodoroTimer/assets/131540418/30bdfced-d1fe-4f8b-baae-7f1c398a741e) 8 | -------------------------------------------------------------------------------- /AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | 3 | [assembly: ThemeInfo( 4 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located 5 | //(used if a resource is not found in the page, 6 | // or application resource dictionaries) 7 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located 8 | //(used if a resource is not found in the page, 9 | // app, or any theme specific resource dictionaries) 10 | )] 11 | -------------------------------------------------------------------------------- /BindingProxy.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | 8 | namespace PomodoroTimer 9 | { 10 | public class BindingProxy : Freezable 11 | { 12 | public static readonly DependencyProperty ValueProperty = 13 | DependencyProperty.Register( 14 | nameof(Value), 15 | typeof(object), 16 | typeof(BindingProxy)); 17 | 18 | public object Value 19 | { 20 | get => GetValue(ValueProperty); 21 | set => SetValue(ValueProperty, value); 22 | } 23 | 24 | protected override Freezable CreateInstanceCore() 25 | { 26 | return new BindingProxy(); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Behaviors/GetTextFocusedBehavior.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Xaml.Behaviors; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows; 8 | using System.Windows.Controls; 9 | using System.Windows.Media; 10 | 11 | namespace PomodoroTimer.Behaviors 12 | { 13 | class GetTextFocusedBehavior : Behavior 14 | { 15 | protected override void OnAttached() 16 | { 17 | AssociatedObject.GotKeyboardFocus += SelectContents; 18 | } 19 | private void SelectContents(object sender, RoutedEventArgs e) 20 | { 21 | TextBox tb = (sender as TextBox); 22 | if (tb != null) 23 | { 24 | tb.SelectionBrush = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#a94dc1")); 25 | tb.SelectAll(); 26 | } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Converters/RestTimesToStringConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows.Data; 8 | using Windows.Web.Syndication; 9 | 10 | namespace PomodoroTimer.Converters 11 | { 12 | public class RestTimesToStringConverter : IValueConverter 13 | { 14 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 15 | { 16 | int times; 17 | if(value != null && int.TryParse(value.ToString(),out times)) 18 | { 19 | if(times == 0) 20 | { 21 | return "您将没有休息时间。"; 22 | } 23 | else 24 | { 25 | return $"您将有{times}次休息时间。"; 26 | } 27 | } 28 | return string.Empty; 29 | } 30 | 31 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 32 | { 33 | throw new NotImplementedException(); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Converters/BoolToVisibilityReverseConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows; 8 | using System.Windows.Data; 9 | 10 | namespace PomodoroTimer.Converters 11 | { 12 | public class BoolToVisibilityReverseConverter : IValueConverter 13 | { 14 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 15 | { 16 | bool isChecked; 17 | if (value != null && bool.TryParse(value.ToString(), out isChecked)) 18 | { 19 | if (isChecked) 20 | { 21 | return Visibility.Collapsed; 22 | } 23 | else 24 | { 25 | return Visibility.Visible; 26 | } 27 | } 28 | return Visibility.Visible; 29 | } 30 | 31 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 32 | { 33 | throw new NotImplementedException(); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /PomodoroTimer.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.9.34723.18 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PomodoroTimer", "PomodoroTimer.csproj", "{4671F198-386A-4CEB-9A0C-B0796000A4BB}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {4671F198-386A-4CEB-9A0C-B0796000A4BB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {4671F198-386A-4CEB-9A0C-B0796000A4BB}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {4671F198-386A-4CEB-9A0C-B0796000A4BB}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {4671F198-386A-4CEB-9A0C-B0796000A4BB}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {810EDDEC-DB05-4D87-86B4-9CF1C597B3D7} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /Converters/BoolToVisibilityConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows; 8 | using System.Windows.Data; 9 | 10 | namespace PomodoroTimer.Converters 11 | { 12 | public class BoolToVisibilityConverter : IValueConverter 13 | { 14 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 15 | { 16 | bool isChecked; 17 | if (value != null && bool.TryParse(value.ToString(), out isChecked)) 18 | { 19 | if (isChecked) 20 | { 21 | return Visibility.Visible; 22 | } 23 | else 24 | { 25 | return Visibility.Collapsed; 26 | } 27 | } 28 | return Visibility.Collapsed; 29 | } 30 | 31 | public object ConvertBack( 32 | object value, 33 | Type targetType, 34 | object parameter, 35 | CultureInfo culture 36 | ) 37 | { 38 | throw new NotImplementedException(); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Behaviors/DurationValidataRule.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows.Controls; 8 | 9 | namespace PomodoroTimer.Behaviors 10 | { 11 | public class DurationValidataRule : ValidationRule 12 | { 13 | public int MaxDuration { get; set; } = 100; 14 | public int MinDuration { get; set; } = 0; 15 | public override ValidationResult Validate(object value, CultureInfo cultureInfo) 16 | { 17 | int currentDuration; 18 | 19 | if (int.TryParse(value.ToString(), out currentDuration)) 20 | { 21 | if (currentDuration > MaxDuration) 22 | { 23 | return new ValidationResult(false, "DurationTooLong"); 24 | } 25 | else if (currentDuration < MinDuration) 26 | { 27 | return new ValidationResult(false, "DurationTooShort"); 28 | } 29 | return ValidationResult.ValidResult; 30 | } 31 | else 32 | { 33 | return new ValidationResult(false, "Duration Must be a int"); 34 | } 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Converters/RemainingTimeToStringConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows.Data; 8 | 9 | namespace PomodoroTimer.Converters 10 | { 11 | public class RemainingTimeToStringConverter : IValueConverter 12 | { 13 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 14 | { 15 | if (value != null) 16 | { 17 | var remainingTime = (TimeSpan)value; 18 | if (remainingTime == TimeSpan.FromMinutes(0)) 19 | { 20 | return "完成"; 21 | } 22 | else if(remainingTime < TimeSpan.FromMinutes(1)) 23 | { 24 | return remainingTime.ToString("ss'秒'"); 25 | } 26 | else 27 | { 28 | return remainingTime.ToString("mm'分'"); 29 | } 30 | } 31 | return string.Empty; 32 | } 33 | 34 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 35 | { 36 | throw new NotImplementedException(); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /MainWindow.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.ObjectModel; 2 | using System.Text; 3 | using System.Windows; 4 | using System.Windows.Controls; 5 | using System.Windows.Data; 6 | using System.Windows.Documents; 7 | using System.Windows.Input; 8 | using System.Windows.Media; 9 | using System.Windows.Media.Imaging; 10 | using System.Windows.Navigation; 11 | using System.Windows.Shapes; 12 | 13 | namespace PomodoroTimer 14 | { 15 | /// 16 | /// Interaction logic for MainWindow.xaml 17 | /// 18 | public partial class MainWindow : Window 19 | { 20 | public MainWindow() 21 | { 22 | InitializeComponent(); 23 | Loaded += MainWindow_Loaded; 24 | TitleZone.MouseDown += (s, e) => 25 | { 26 | if (e.LeftButton == MouseButtonState.Pressed) 27 | { 28 | this.DragMove(); 29 | } 30 | }; 31 | DragZone.MouseDown += (s, e) => 32 | { 33 | if (e.LeftButton == MouseButtonState.Pressed) 34 | { 35 | this.DragMove(); 36 | } 37 | }; 38 | btn_Min.Click += (s, e) => 39 | { 40 | this.WindowState = WindowState.Minimized; 41 | }; 42 | } 43 | WindowAccentCompositor wac = null; 44 | private void MainWindow_Loaded(object sender, RoutedEventArgs e) 45 | { 46 | wac = new(this, false, (c) => 47 | { 48 | //没有可用的模糊特效 49 | c.A = 255; 50 | Background = new SolidColorBrush(c); 51 | }); 52 | //wac.Color = (bool)DarkModeCheck.IsChecked ? Color.FromArgb(180, 0, 0, 0) : Color.FromArgb(180, 255, 255, 255); 53 | wac.Color = Color.FromArgb(180, 0, 0, 0); 54 | wac.IsEnabled = true; 55 | } 56 | 57 | 58 | } 59 | } -------------------------------------------------------------------------------- /Behaviors/ClickToChangeBgBehavior.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Xaml.Behaviors; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Collections.ObjectModel; 5 | using System.IO; 6 | using System.Linq; 7 | using System.Reflection; 8 | using System.Text; 9 | using System.Threading.Tasks; 10 | using System.Windows; 11 | using System.Windows.Controls; 12 | using System.Windows.Media; 13 | using System.Windows.Media.Imaging; 14 | 15 | namespace PomodoroTimer.Behaviors 16 | { 17 | public class ClickToChangeBgBehavior : Behavior 18 | { 19 | private int bgIndex = 0; 20 | protected override void OnAttached() 21 | { 22 | AssociatedObject.Loaded += InitBg; 23 | AssociatedObject.MouseDown += ChangeBg; 24 | } 25 | 26 | private void InitBg(object sender, RoutedEventArgs e) 27 | { 28 | var bgList = AssociatedObject.Tag as ObservableCollection; 29 | if (bgList != null) 30 | { 31 | BitmapImage logo = new BitmapImage(); 32 | logo.BeginInit(); 33 | logo.UriSource = new Uri(bgList[bgIndex], UriKind.Relative); 34 | logo.EndInit(); 35 | AssociatedObject.Source = logo; 36 | } 37 | } 38 | 39 | private void ChangeBg(object sender, System.Windows.Input.MouseButtonEventArgs e) 40 | { 41 | var bgList = AssociatedObject.Tag as ObservableCollection; 42 | if (bgList != null) 43 | { 44 | BitmapImage logo = new BitmapImage(); 45 | logo.BeginInit(); 46 | if (bgIndex == bgList.Count - 1) 47 | { 48 | bgIndex = 0; 49 | } 50 | else 51 | { 52 | bgIndex++; 53 | } 54 | logo.UriSource = new Uri(bgList[bgIndex], UriKind.Relative); 55 | logo.EndInit(); 56 | AssociatedObject.Source = logo; 57 | } 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /PomodoroTimer.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | WinExe 5 | net8.0-windows10.0.17763.0 6 | enable 7 | enable 8 | true 9 | Resources\icon.ico 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | PreserveNewest 35 | 36 | 37 | PreserveNewest 38 | 39 | 40 | PreserveNewest 41 | 42 | 43 | PreserveNewest 44 | 45 | 46 | PreserveNewest 47 | 48 | 49 | PreserveNewest 50 | 51 | 52 | PreserveNewest 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /Behaviors/TimeInOrDeBehavior.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Xaml.Behaviors; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows; 8 | using System.Windows.Controls; 9 | 10 | namespace PomodoroTimer.Behaviors 11 | { 12 | class TimeInOrDeBehavior : Behavior 222 | 225 | 231 | 237 | 240 | 241 | 242 | 243 | 244 | 245 | 249 | 250 | 251 | 252 | 253 | 254 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 267 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | -------------------------------------------------------------------------------- /App.xaml: -------------------------------------------------------------------------------- 1 | 9 | 10 | pack://application:,,,/Resources/#iconfont 11 | 12 | 51 | 90 | 129 | 180 | 226 | 289 | 327 | 424 | 496 | 497 | 498 | --------------------------------------------------------------------------------