├── Work-Timer ├── Assets │ ├── AppLogo.png │ ├── StoreLogo.png │ ├── SplashScreen.scale-200.png │ ├── LockScreenLogo.scale-200.png │ ├── Logo │ │ ├── LargeTile.scale-100.png │ │ ├── LargeTile.scale-125.png │ │ ├── LargeTile.scale-150.png │ │ ├── LargeTile.scale-200.png │ │ ├── LargeTile.scale-400.png │ │ ├── SmallTile.scale-100.png │ │ ├── SmallTile.scale-125.png │ │ ├── SmallTile.scale-150.png │ │ ├── SmallTile.scale-200.png │ │ ├── SmallTile.scale-400.png │ │ ├── StoreLogo.scale-100.png │ │ ├── StoreLogo.scale-125.png │ │ ├── StoreLogo.scale-150.png │ │ ├── StoreLogo.scale-200.png │ │ ├── StoreLogo.scale-400.png │ │ ├── SplashScreen.scale-100.png │ │ ├── SplashScreen.scale-125.png │ │ ├── SplashScreen.scale-150.png │ │ ├── SplashScreen.scale-200.png │ │ ├── SplashScreen.scale-400.png │ │ ├── Square44x44Logo.scale-100.png │ │ ├── Square44x44Logo.scale-125.png │ │ ├── Square44x44Logo.scale-150.png │ │ ├── Square44x44Logo.scale-200.png │ │ ├── Square44x44Logo.scale-400.png │ │ ├── Wide310x150Logo.scale-100.png │ │ ├── Wide310x150Logo.scale-125.png │ │ ├── Wide310x150Logo.scale-150.png │ │ ├── Wide310x150Logo.scale-200.png │ │ ├── Wide310x150Logo.scale-400.png │ │ ├── Square150x150Logo.scale-100.png │ │ ├── Square150x150Logo.scale-125.png │ │ ├── Square150x150Logo.scale-150.png │ │ ├── Square150x150Logo.scale-200.png │ │ ├── Square150x150Logo.scale-400.png │ │ ├── Square44x44Logo.targetsize-16.png │ │ ├── Square44x44Logo.targetsize-24.png │ │ ├── Square44x44Logo.targetsize-256.png │ │ ├── Square44x44Logo.targetsize-32.png │ │ ├── Square44x44Logo.targetsize-48.png │ │ ├── Square44x44Logo.altform-unplated_targetsize-16.png │ │ ├── Square44x44Logo.altform-unplated_targetsize-24.png │ │ ├── Square44x44Logo.altform-unplated_targetsize-256.png │ │ ├── Square44x44Logo.altform-unplated_targetsize-32.png │ │ ├── Square44x44Logo.altform-unplated_targetsize-48.png │ │ ├── Square44x44Logo.altform-lightunplated_targetsize-16.png │ │ ├── Square44x44Logo.altform-lightunplated_targetsize-24.png │ │ ├── Square44x44Logo.altform-lightunplated_targetsize-256.png │ │ ├── Square44x44Logo.altform-lightunplated_targetsize-32.png │ │ └── Square44x44Logo.altform-lightunplated_targetsize-48.png │ ├── Square44x44Logo.scale-200.png │ ├── Wide310x150Logo.scale-200.png │ ├── Square150x150Logo.scale-200.png │ └── Square44x44Logo.targetsize-24_altform-unplated.png ├── Others │ ├── Update_zh_CN.txt │ └── Update_en_US.txt ├── Template │ ├── Converter.xaml │ ├── Text.xaml │ └── Button.xaml ├── Models │ ├── Enums │ │ ├── Settings.cs │ │ ├── StyleName.cs │ │ ├── ColorName.cs │ │ └── LanguageName.cs │ ├── UI │ │ ├── DateTimeConverter.cs │ │ ├── CustomResourceLoader.cs │ │ └── SelectedColorConverter.cs │ └── Core │ │ ├── AppViewModel.Properties.cs │ │ └── AppViewModel.cs ├── Components │ ├── Dialog │ │ ├── ConfirmDialog.xaml │ │ ├── ConfirmDialog.xaml.cs │ │ ├── FolderSelectionDialog.xaml │ │ ├── FolderSelectionDialog.xaml.cs │ │ ├── FolderDialog.xaml │ │ └── FolderDialog.xaml.cs │ ├── Layout │ │ ├── HistoryPanel.xaml.cs │ │ ├── FolderPanel.xaml.cs │ │ ├── SettingPanel.xaml │ │ ├── HistoryPanel.xaml │ │ ├── FolderPanel.xaml │ │ └── SettingPanel.xaml.cs │ └── Widget │ │ ├── WorkDurationBlock.xaml │ │ └── WorkDurationBlock.xaml.cs ├── Properties │ ├── AssemblyInfo.cs │ └── Default.rd.xml ├── App.xaml ├── Package.appxmanifest ├── Theme │ ├── Light.xaml │ └── Dark.xaml ├── MainPage.xaml.cs ├── App.xaml.cs ├── MainPage.xaml ├── Language │ ├── zh-CN │ │ └── Resources.resw │ └── en-US │ │ └── Resources.resw └── Work-Timer.csproj ├── Lib_Share ├── Models │ ├── StaticExtension.cs │ ├── StaticString.cs │ ├── FolderItem.cs │ └── HistoryItem.cs ├── Properties │ ├── AssemblyInfo.cs │ └── Lib_Share.rd.xml └── Lib_Share.csproj ├── README.md ├── .gitattributes ├── Work-Timer.sln └── .gitignore /Work-Timer/Assets/AppLogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Richasy/Work-Timer/HEAD/Work-Timer/Assets/AppLogo.png -------------------------------------------------------------------------------- /Work-Timer/Assets/StoreLogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Richasy/Work-Timer/HEAD/Work-Timer/Assets/StoreLogo.png -------------------------------------------------------------------------------- /Work-Timer/Others/Update_zh_CN.txt: -------------------------------------------------------------------------------- 1 | 您已经更新到新版本的《工作计时器》 2 | 3 | 更新内容如下: 4 | 5 | 1. 添加总工作时长设置,并进行UI调整 6 | 2. 添加Github开源地址 -------------------------------------------------------------------------------- /Work-Timer/Assets/SplashScreen.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Richasy/Work-Timer/HEAD/Work-Timer/Assets/SplashScreen.scale-200.png -------------------------------------------------------------------------------- /Work-Timer/Assets/LockScreenLogo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Richasy/Work-Timer/HEAD/Work-Timer/Assets/LockScreenLogo.scale-200.png -------------------------------------------------------------------------------- /Work-Timer/Assets/Logo/LargeTile.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Richasy/Work-Timer/HEAD/Work-Timer/Assets/Logo/LargeTile.scale-100.png -------------------------------------------------------------------------------- /Work-Timer/Assets/Logo/LargeTile.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Richasy/Work-Timer/HEAD/Work-Timer/Assets/Logo/LargeTile.scale-125.png -------------------------------------------------------------------------------- /Work-Timer/Assets/Logo/LargeTile.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Richasy/Work-Timer/HEAD/Work-Timer/Assets/Logo/LargeTile.scale-150.png -------------------------------------------------------------------------------- /Work-Timer/Assets/Logo/LargeTile.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Richasy/Work-Timer/HEAD/Work-Timer/Assets/Logo/LargeTile.scale-200.png -------------------------------------------------------------------------------- /Work-Timer/Assets/Logo/LargeTile.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Richasy/Work-Timer/HEAD/Work-Timer/Assets/Logo/LargeTile.scale-400.png -------------------------------------------------------------------------------- /Work-Timer/Assets/Logo/SmallTile.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Richasy/Work-Timer/HEAD/Work-Timer/Assets/Logo/SmallTile.scale-100.png -------------------------------------------------------------------------------- /Work-Timer/Assets/Logo/SmallTile.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Richasy/Work-Timer/HEAD/Work-Timer/Assets/Logo/SmallTile.scale-125.png -------------------------------------------------------------------------------- /Work-Timer/Assets/Logo/SmallTile.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Richasy/Work-Timer/HEAD/Work-Timer/Assets/Logo/SmallTile.scale-150.png -------------------------------------------------------------------------------- /Work-Timer/Assets/Logo/SmallTile.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Richasy/Work-Timer/HEAD/Work-Timer/Assets/Logo/SmallTile.scale-200.png -------------------------------------------------------------------------------- /Work-Timer/Assets/Logo/SmallTile.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Richasy/Work-Timer/HEAD/Work-Timer/Assets/Logo/SmallTile.scale-400.png -------------------------------------------------------------------------------- /Work-Timer/Assets/Logo/StoreLogo.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Richasy/Work-Timer/HEAD/Work-Timer/Assets/Logo/StoreLogo.scale-100.png -------------------------------------------------------------------------------- /Work-Timer/Assets/Logo/StoreLogo.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Richasy/Work-Timer/HEAD/Work-Timer/Assets/Logo/StoreLogo.scale-125.png -------------------------------------------------------------------------------- /Work-Timer/Assets/Logo/StoreLogo.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Richasy/Work-Timer/HEAD/Work-Timer/Assets/Logo/StoreLogo.scale-150.png -------------------------------------------------------------------------------- /Work-Timer/Assets/Logo/StoreLogo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Richasy/Work-Timer/HEAD/Work-Timer/Assets/Logo/StoreLogo.scale-200.png -------------------------------------------------------------------------------- /Work-Timer/Assets/Logo/StoreLogo.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Richasy/Work-Timer/HEAD/Work-Timer/Assets/Logo/StoreLogo.scale-400.png -------------------------------------------------------------------------------- /Work-Timer/Assets/Square44x44Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Richasy/Work-Timer/HEAD/Work-Timer/Assets/Square44x44Logo.scale-200.png -------------------------------------------------------------------------------- /Work-Timer/Assets/Wide310x150Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Richasy/Work-Timer/HEAD/Work-Timer/Assets/Wide310x150Logo.scale-200.png -------------------------------------------------------------------------------- /Work-Timer/Assets/Logo/SplashScreen.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Richasy/Work-Timer/HEAD/Work-Timer/Assets/Logo/SplashScreen.scale-100.png -------------------------------------------------------------------------------- /Work-Timer/Assets/Logo/SplashScreen.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Richasy/Work-Timer/HEAD/Work-Timer/Assets/Logo/SplashScreen.scale-125.png -------------------------------------------------------------------------------- /Work-Timer/Assets/Logo/SplashScreen.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Richasy/Work-Timer/HEAD/Work-Timer/Assets/Logo/SplashScreen.scale-150.png -------------------------------------------------------------------------------- /Work-Timer/Assets/Logo/SplashScreen.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Richasy/Work-Timer/HEAD/Work-Timer/Assets/Logo/SplashScreen.scale-200.png -------------------------------------------------------------------------------- /Work-Timer/Assets/Logo/SplashScreen.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Richasy/Work-Timer/HEAD/Work-Timer/Assets/Logo/SplashScreen.scale-400.png -------------------------------------------------------------------------------- /Work-Timer/Assets/Square150x150Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Richasy/Work-Timer/HEAD/Work-Timer/Assets/Square150x150Logo.scale-200.png -------------------------------------------------------------------------------- /Work-Timer/Assets/Logo/Square44x44Logo.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Richasy/Work-Timer/HEAD/Work-Timer/Assets/Logo/Square44x44Logo.scale-100.png -------------------------------------------------------------------------------- /Work-Timer/Assets/Logo/Square44x44Logo.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Richasy/Work-Timer/HEAD/Work-Timer/Assets/Logo/Square44x44Logo.scale-125.png -------------------------------------------------------------------------------- /Work-Timer/Assets/Logo/Square44x44Logo.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Richasy/Work-Timer/HEAD/Work-Timer/Assets/Logo/Square44x44Logo.scale-150.png -------------------------------------------------------------------------------- /Work-Timer/Assets/Logo/Square44x44Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Richasy/Work-Timer/HEAD/Work-Timer/Assets/Logo/Square44x44Logo.scale-200.png -------------------------------------------------------------------------------- /Work-Timer/Assets/Logo/Square44x44Logo.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Richasy/Work-Timer/HEAD/Work-Timer/Assets/Logo/Square44x44Logo.scale-400.png -------------------------------------------------------------------------------- /Work-Timer/Assets/Logo/Wide310x150Logo.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Richasy/Work-Timer/HEAD/Work-Timer/Assets/Logo/Wide310x150Logo.scale-100.png -------------------------------------------------------------------------------- /Work-Timer/Assets/Logo/Wide310x150Logo.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Richasy/Work-Timer/HEAD/Work-Timer/Assets/Logo/Wide310x150Logo.scale-125.png -------------------------------------------------------------------------------- /Work-Timer/Assets/Logo/Wide310x150Logo.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Richasy/Work-Timer/HEAD/Work-Timer/Assets/Logo/Wide310x150Logo.scale-150.png -------------------------------------------------------------------------------- /Work-Timer/Assets/Logo/Wide310x150Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Richasy/Work-Timer/HEAD/Work-Timer/Assets/Logo/Wide310x150Logo.scale-200.png -------------------------------------------------------------------------------- /Work-Timer/Assets/Logo/Wide310x150Logo.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Richasy/Work-Timer/HEAD/Work-Timer/Assets/Logo/Wide310x150Logo.scale-400.png -------------------------------------------------------------------------------- /Work-Timer/Assets/Logo/Square150x150Logo.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Richasy/Work-Timer/HEAD/Work-Timer/Assets/Logo/Square150x150Logo.scale-100.png -------------------------------------------------------------------------------- /Work-Timer/Assets/Logo/Square150x150Logo.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Richasy/Work-Timer/HEAD/Work-Timer/Assets/Logo/Square150x150Logo.scale-125.png -------------------------------------------------------------------------------- /Work-Timer/Assets/Logo/Square150x150Logo.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Richasy/Work-Timer/HEAD/Work-Timer/Assets/Logo/Square150x150Logo.scale-150.png -------------------------------------------------------------------------------- /Work-Timer/Assets/Logo/Square150x150Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Richasy/Work-Timer/HEAD/Work-Timer/Assets/Logo/Square150x150Logo.scale-200.png -------------------------------------------------------------------------------- /Work-Timer/Assets/Logo/Square150x150Logo.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Richasy/Work-Timer/HEAD/Work-Timer/Assets/Logo/Square150x150Logo.scale-400.png -------------------------------------------------------------------------------- /Work-Timer/Assets/Logo/Square44x44Logo.targetsize-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Richasy/Work-Timer/HEAD/Work-Timer/Assets/Logo/Square44x44Logo.targetsize-16.png -------------------------------------------------------------------------------- /Work-Timer/Assets/Logo/Square44x44Logo.targetsize-24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Richasy/Work-Timer/HEAD/Work-Timer/Assets/Logo/Square44x44Logo.targetsize-24.png -------------------------------------------------------------------------------- /Work-Timer/Assets/Logo/Square44x44Logo.targetsize-256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Richasy/Work-Timer/HEAD/Work-Timer/Assets/Logo/Square44x44Logo.targetsize-256.png -------------------------------------------------------------------------------- /Work-Timer/Assets/Logo/Square44x44Logo.targetsize-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Richasy/Work-Timer/HEAD/Work-Timer/Assets/Logo/Square44x44Logo.targetsize-32.png -------------------------------------------------------------------------------- /Work-Timer/Assets/Logo/Square44x44Logo.targetsize-48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Richasy/Work-Timer/HEAD/Work-Timer/Assets/Logo/Square44x44Logo.targetsize-48.png -------------------------------------------------------------------------------- /Work-Timer/Assets/Square44x44Logo.targetsize-24_altform-unplated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Richasy/Work-Timer/HEAD/Work-Timer/Assets/Square44x44Logo.targetsize-24_altform-unplated.png -------------------------------------------------------------------------------- /Work-Timer/Assets/Logo/Square44x44Logo.altform-unplated_targetsize-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Richasy/Work-Timer/HEAD/Work-Timer/Assets/Logo/Square44x44Logo.altform-unplated_targetsize-16.png -------------------------------------------------------------------------------- /Work-Timer/Assets/Logo/Square44x44Logo.altform-unplated_targetsize-24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Richasy/Work-Timer/HEAD/Work-Timer/Assets/Logo/Square44x44Logo.altform-unplated_targetsize-24.png -------------------------------------------------------------------------------- /Work-Timer/Assets/Logo/Square44x44Logo.altform-unplated_targetsize-256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Richasy/Work-Timer/HEAD/Work-Timer/Assets/Logo/Square44x44Logo.altform-unplated_targetsize-256.png -------------------------------------------------------------------------------- /Work-Timer/Assets/Logo/Square44x44Logo.altform-unplated_targetsize-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Richasy/Work-Timer/HEAD/Work-Timer/Assets/Logo/Square44x44Logo.altform-unplated_targetsize-32.png -------------------------------------------------------------------------------- /Work-Timer/Assets/Logo/Square44x44Logo.altform-unplated_targetsize-48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Richasy/Work-Timer/HEAD/Work-Timer/Assets/Logo/Square44x44Logo.altform-unplated_targetsize-48.png -------------------------------------------------------------------------------- /Work-Timer/Assets/Logo/Square44x44Logo.altform-lightunplated_targetsize-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Richasy/Work-Timer/HEAD/Work-Timer/Assets/Logo/Square44x44Logo.altform-lightunplated_targetsize-16.png -------------------------------------------------------------------------------- /Work-Timer/Assets/Logo/Square44x44Logo.altform-lightunplated_targetsize-24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Richasy/Work-Timer/HEAD/Work-Timer/Assets/Logo/Square44x44Logo.altform-lightunplated_targetsize-24.png -------------------------------------------------------------------------------- /Work-Timer/Assets/Logo/Square44x44Logo.altform-lightunplated_targetsize-256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Richasy/Work-Timer/HEAD/Work-Timer/Assets/Logo/Square44x44Logo.altform-lightunplated_targetsize-256.png -------------------------------------------------------------------------------- /Work-Timer/Assets/Logo/Square44x44Logo.altform-lightunplated_targetsize-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Richasy/Work-Timer/HEAD/Work-Timer/Assets/Logo/Square44x44Logo.altform-lightunplated_targetsize-32.png -------------------------------------------------------------------------------- /Work-Timer/Assets/Logo/Square44x44Logo.altform-lightunplated_targetsize-48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Richasy/Work-Timer/HEAD/Work-Timer/Assets/Logo/Square44x44Logo.altform-lightunplated_targetsize-48.png -------------------------------------------------------------------------------- /Work-Timer/Template/Converter.xaml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Work-Timer/Models/Enums/Settings.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace WorkTimer.Models.Enums 8 | { 9 | public enum Settings 10 | { 11 | Theme, 12 | AppVersion, 13 | Language, 14 | FontFamily, 15 | LastSelectFolderId, 16 | PresetDuration 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Lib_Share/Models/StaticExtension.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Lib.Share.Models 8 | { 9 | public static class StaticExtension 10 | { 11 | public static bool IsNullOrEmpty(this IEnumerable collection) 12 | { 13 | return collection == null || collection.Count() == 0; 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Work-Timer/Models/Enums/StyleName.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace WorkTimer.Models.Enums 8 | { 9 | public enum StyleName 10 | { 11 | DefaultActionButtonStyle, 12 | SubtitleTextStyle, 13 | PopupHeaderButtonStyle, 14 | PrimaryActionButtonStyle, 15 | BasicMarkdownTextBlock, 16 | BasicCenterPopupStyle 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Work-Timer/Models/Enums/ColorName.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace WorkTimer.Models.Enums 8 | { 9 | public enum ColorName 10 | { 11 | PageBackground, 12 | PrimaryColor, 13 | PrimaryColorOver, 14 | PrimaryColorOpacity, 15 | SecondaryColor, 16 | SecondaryColorOver, 17 | SecondaryColorOpacity, 18 | ErrorColor, 19 | MaskBackground, 20 | CardBackground 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Work-Timer/Others/Update_en_US.txt: -------------------------------------------------------------------------------- 1 | You have updated to the new version of 《Working Timer》 2 | 3 | The application is a simple timing tool, and only one timer can exist at a time. 4 | 5 | In the new version, you can create a folder on the left side (click the button in the lower left corner to call out) to classify the timer. 6 | 7 | You can check the timer history of the current folder on the right (click the button in the lower right corner to call out). 8 | 9 | There is no *pause* in the timer. Once stopped, it will be recorded under the currently selected folder. You can view the currently selected folder name at the bottom of the interface. -------------------------------------------------------------------------------- /Work-Timer/Models/Enums/LanguageName.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace WorkTimer.Models.Enums 8 | { 9 | public enum LanguageName 10 | { 11 | Default, 12 | HasAddedHistoryItem, 13 | FolderDialogTitle, 14 | FolderDialogDescription, 15 | Confirm, 16 | Cancel, 17 | Warning, 18 | FieldEmpty, 19 | ConfirmRemoveFolder, 20 | NeedOneFolder, 21 | ConfirmRemoveHistory, 22 | StaticResourceRestart, 23 | RestartNow, 24 | Settings, 25 | UpdateTitle, 26 | Waiting, 27 | MoveHistory 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Work-Timer/Models/UI/DateTimeConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Windows.UI.Xaml.Data; 7 | 8 | namespace WorkTimer.Models.UI 9 | { 10 | public class DateTimeConverter:IValueConverter 11 | { 12 | public object Convert(object value, Type targetType, object parameter, string language) 13 | { 14 | var date = (DateTime)value; 15 | return date.ToString("yyyy/MM/dd"); 16 | } 17 | 18 | public object ConvertBack(object value, Type targetType, object parameter, string language) 19 | { 20 | throw new NotImplementedException(); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Work-Timer/Models/UI/CustomResourceLoader.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Windows.UI.Xaml.Media; 7 | using Windows.UI.Xaml.Resources; 8 | using WorkTimer.Models.Enums; 9 | 10 | namespace WorkTimer.Models.UI 11 | { 12 | public class CustomResourceLoader : CustomXamlResourceLoader 13 | { 14 | protected override object GetResource(string resourceId, string objectType, string propertyName, string propertyType) 15 | { 16 | if (resourceId == "Basic") 17 | { 18 | return new FontFamily(App._instance.App.GetLocalSetting(Settings.FontFamily, "Microsoft YaHei UI")); 19 | } 20 | return null; 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Work-Timer/Components/Dialog/ConfirmDialog.xaml: -------------------------------------------------------------------------------- 1 | 12 | 13 | 14 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /Work-Timer/Models/UI/SelectedColorConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Windows.UI; 3 | using Windows.UI.Xaml.Data; 4 | using Windows.UI.Xaml.Media; 5 | using WorkTimer.Models.Enums; 6 | 7 | namespace WorkTimer.Models.UI 8 | { 9 | public class SelectedColorConverter:IValueConverter 10 | { 11 | public object Convert(object value, Type targetType, object parameter, string language) 12 | { 13 | bool isSelected = System.Convert.ToBoolean(value); 14 | return isSelected ? App._instance.App.GetThemeBrushFromResource(ColorName.PrimaryColor) : new SolidColorBrush(Colors.Transparent); 15 | } 16 | 17 | public object ConvertBack(object value, Type targetType, object parameter, string language) 18 | { 19 | throw new NotImplementedException(); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Lib_Share/Models/StaticString.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Windows.UI.Composition.Scenes; 7 | 8 | namespace Lib.Share.Models 9 | { 10 | public static class StaticString 11 | { 12 | public const string AppName = "WorkTimer"; 13 | 14 | public const string FolderListFileName = "FolderList.json"; 15 | public const string HistoryListFileName = "HistoryList.json"; 16 | 17 | public const string ThemeSystem = "System"; 18 | public const string ThemeLight = "Light"; 19 | public const string ThemeDark = "Dark"; 20 | 21 | public const string LanZh = "zh_CN"; 22 | public const string LanEn = "en_US"; 23 | 24 | public const string FontDefault = "Microsoft YaHei UI"; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Lib_Share/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // 有关程序集的一般信息由以下 6 | // 控制。更改这些特性值可修改 7 | // 与程序集关联的信息。 8 | [assembly: AssemblyTitle("Lib_Share")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("Lib_Share")] 13 | [assembly: AssemblyCopyright("Copyright © 2020")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // 程序集的版本信息由下列四个值组成: 18 | // 19 | // 主版本 20 | // 次版本 21 | // 生成号 22 | // 修订号 23 | // 24 | //可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值 25 | //通过使用 "*",如下所示: 26 | // [assembly: AssemblyVersion("1.0.*")] 27 | [assembly: AssemblyVersion("1.0.0.0")] 28 | [assembly: AssemblyFileVersion("1.0.0.0")] 29 | [assembly: ComVisible(false)] -------------------------------------------------------------------------------- /Lib_Share/Properties/Lib_Share.rd.xml: -------------------------------------------------------------------------------- 1 | 2 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /Lib_Share/Models/FolderItem.cs: -------------------------------------------------------------------------------- 1 | using Richasy.Font.UWP.Enums; 2 | using System; 3 | using System.Collections.Generic; 4 | 5 | namespace Lib.Share.Models 6 | { 7 | public class FolderItem 8 | { 9 | public string Name { get; set; } 10 | public DateTime CreateTime { get; set; } 11 | public string Id { get; set; } 12 | public FeatherSymbol Icon { get; set; } 13 | public FolderItem() 14 | { 15 | 16 | } 17 | public FolderItem(string name,FeatherSymbol icon) 18 | { 19 | Name = name; 20 | CreateTime = DateTime.Now; 21 | Id = Guid.NewGuid().ToString("N"); 22 | Icon = icon; 23 | } 24 | 25 | public override bool Equals(object obj) 26 | { 27 | return obj is FolderItem item && 28 | Id == item.Id; 29 | } 30 | 31 | public override int GetHashCode() 32 | { 33 | return 2108858624 + EqualityComparer.Default.GetHashCode(Id); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Work-Timer/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Work-Timer")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("Work-Timer")] 13 | [assembly: AssemblyCopyright("Copyright © 2020")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Version information for an assembly consists of the following four values: 18 | // 19 | // Major Version 20 | // Minor Version 21 | // Build Number 22 | // Revision 23 | // 24 | // You can specify all the values or you can default the Build and Revision Numbers 25 | // by using the '*' as shown below: 26 | // [assembly: AssemblyVersion("1.0.*")] 27 | [assembly: AssemblyVersion("1.0.0.0")] 28 | [assembly: AssemblyFileVersion("1.0.0.0")] 29 | [assembly: ComVisible(false)] -------------------------------------------------------------------------------- /Work-Timer/App.xaml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /Lib_Share/Models/HistoryItem.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Lib.Share.Models 8 | { 9 | public class HistoryItem 10 | { 11 | public string Name { get; set; } 12 | public string FolderId { get; set; } 13 | public string Id { get; set; } 14 | public int TotalSeconds { get; set; } 15 | public DateTime CreateTime { get; set; } 16 | public HistoryItem() 17 | { 18 | 19 | } 20 | public HistoryItem(string name, string folderId, int totalSeconds = 0) 21 | { 22 | Name = name; 23 | FolderId = folderId; 24 | Id = Guid.NewGuid().ToString("N"); 25 | TotalSeconds = totalSeconds; 26 | CreateTime = DateTime.Now; 27 | } 28 | public string GetReadTime() 29 | { 30 | var ts = TimeSpan.FromSeconds(TotalSeconds); 31 | string result = ""; 32 | if (ts.Hours > 0) 33 | result += ts.Hours + "h "; 34 | if (ts.Minutes > 0) 35 | result += ts.Minutes + "m "; 36 | else if (ts.Hours > 0) 37 | result += "00m "; 38 | result += ts.Seconds.ToString("00") + "s"; 39 | return result; 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Work-Timer/Properties/Default.rd.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 19 | 20 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /Work-Timer/Components/Layout/HistoryPanel.xaml.cs: -------------------------------------------------------------------------------- 1 | using Lib.Share.Models; 2 | using System; 3 | using Windows.UI.Xaml.Controls; 4 | using WorkTimer.Components.Dialog; 5 | using WorkTimer.Models.Core; 6 | 7 | // The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236 8 | 9 | namespace WorkTimer.Components.Layout 10 | { 11 | public sealed partial class HistoryPanel : UserControl 12 | { 13 | AppViewModel vm = App._vm; 14 | public HistoryPanel() 15 | { 16 | this.InitializeComponent(); 17 | vm.HistoryPanel = this; 18 | vm.CurrentSelectedFolderChanged += SelectedFolderChanged; 19 | } 20 | 21 | private void SelectedFolderChanged(object sender, FolderItem e) 22 | { 23 | TitleBlock.Text = e.Name; 24 | } 25 | 26 | private void HistoryListView_ItemClick(object sender, ItemClickEventArgs e) 27 | { 28 | 29 | } 30 | 31 | private async void RemoveItem_Click(object sender, Windows.UI.Xaml.RoutedEventArgs e) 32 | { 33 | var item = (sender as MenuFlyoutItem).Tag as HistoryItem; 34 | await vm.RemoveHistory(item); 35 | } 36 | 37 | private async void TransferItem_Click(object sender, Windows.UI.Xaml.RoutedEventArgs e) 38 | { 39 | var item = (sender as MenuFlyoutItem).Tag as HistoryItem; 40 | var dialog = new FolderSelectionDialog(item); 41 | await dialog.ShowAsync(); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Work-Timer/Components/Widget/WorkDurationBlock.xaml: -------------------------------------------------------------------------------- 1 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 20 | 21 | 22 | 23 | 24 | 26 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /Work-Timer/Components/Dialog/ConfirmDialog.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Runtime.InteropServices.WindowsRuntime; 6 | using Windows.Foundation; 7 | using Windows.Foundation.Collections; 8 | using Windows.UI.Xaml; 9 | using Windows.UI.Xaml.Controls; 10 | using Windows.UI.Xaml.Controls.Primitives; 11 | using Windows.UI.Xaml.Data; 12 | using Windows.UI.Xaml.Input; 13 | using Windows.UI.Xaml.Media; 14 | using Windows.UI.Xaml.Navigation; 15 | using WorkTimer.Models.Enums; 16 | 17 | // https://go.microsoft.com/fwlink/?LinkId=234238 上介绍了“内容对话框”项模板 18 | 19 | namespace WorkTimer.Components.Dialog 20 | { 21 | public sealed partial class ConfirmDialog : ContentDialog 22 | { 23 | public ConfirmDialog() 24 | { 25 | this.InitializeComponent(); 26 | Title = App._instance.App.GetLocalizationTextFromResource(LanguageName.Warning); 27 | PrimaryButtonText = App._instance.App.GetLocalizationTextFromResource(LanguageName.Confirm); 28 | CloseButtonText = App._instance.App.GetLocalizationTextFromResource(LanguageName.Cancel); 29 | } 30 | public ConfirmDialog(string msg):this() 31 | { 32 | DisplayBlock.Text = msg; 33 | } 34 | public ConfirmDialog(LanguageName language):this() 35 | { 36 | DisplayBlock.Text = App._instance.App.GetLocalizationTextFromResource(language); 37 | } 38 | private void ContentDialog_PrimaryButtonClick(ContentDialog sender, ContentDialogButtonClickEventArgs args) 39 | { 40 | } 41 | 42 | private void ContentDialog_SecondaryButtonClick(ContentDialog sender, ContentDialogButtonClickEventArgs args) 43 | { 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Work-Timer/Components/Widget/WorkDurationBlock.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Runtime.InteropServices.WindowsRuntime; 6 | using Windows.Foundation; 7 | using Windows.Foundation.Collections; 8 | using Windows.UI.Xaml; 9 | using Windows.UI.Xaml.Controls; 10 | using Windows.UI.Xaml.Controls.Primitives; 11 | using Windows.UI.Xaml.Data; 12 | using Windows.UI.Xaml.Input; 13 | using Windows.UI.Xaml.Media; 14 | using Windows.UI.Xaml.Navigation; 15 | using WorkTimer.Models.Enums; 16 | 17 | //https://go.microsoft.com/fwlink/?LinkId=234236 上介绍了“用户控件”项模板 18 | 19 | namespace WorkTimer.Components.Widget 20 | { 21 | public sealed partial class WorkDurationBlock : UserControl 22 | { 23 | public WorkDurationBlock() 24 | { 25 | this.InitializeComponent(); 26 | UpdatePresetDuration(); 27 | App._vm.WorkDurationBlock = this; 28 | App._vm.HistoryChanged += HistoryChanged; 29 | } 30 | 31 | private void HistoryChanged(object sender, EventArgs e) 32 | { 33 | var todayList = App._vm.AllHistoryList.Where(p => p.CreateTime.Date == DateTime.Now.Date).ToList(); 34 | if (todayList.Count > 0) 35 | { 36 | int totalSeconds = 0; 37 | todayList.ForEach(p => totalSeconds += p.TotalSeconds); 38 | ActualDurationBlock.Text = (totalSeconds / 60.0).ToString("0") + " m"; 39 | } 40 | else 41 | ActualDurationBlock.Text = "0 m"; 42 | } 43 | public void UpdatePresetDuration() 44 | { 45 | string presetDuration = App._instance.App.GetLocalSetting(Settings.PresetDuration, "360"); 46 | PresetDurationBlock.Text = presetDuration + " m"; 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Work-Timer/Components/Dialog/FolderSelectionDialog.xaml: -------------------------------------------------------------------------------- 1 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /Work-Timer/Template/Text.xaml: -------------------------------------------------------------------------------- 1 | 5 | 9 | 14 | 19 | 23 | 26 | 31 | 36 | 37 | -------------------------------------------------------------------------------- /Work-Timer/Components/Dialog/FolderSelectionDialog.xaml.cs: -------------------------------------------------------------------------------- 1 | using Lib.Share.Models; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Collections.ObjectModel; 5 | using System.IO; 6 | using System.Linq; 7 | using System.Runtime.InteropServices.WindowsRuntime; 8 | using Windows.Foundation; 9 | using Windows.Foundation.Collections; 10 | using Windows.UI.Xaml; 11 | using Windows.UI.Xaml.Controls; 12 | using Windows.UI.Xaml.Controls.Primitives; 13 | using Windows.UI.Xaml.Data; 14 | using Windows.UI.Xaml.Input; 15 | using Windows.UI.Xaml.Media; 16 | using Windows.UI.Xaml.Navigation; 17 | using WorkTimer.Models.Enums; 18 | 19 | // https://go.microsoft.com/fwlink/?LinkId=234238 上介绍了“内容对话框”项模板 20 | 21 | namespace WorkTimer.Components.Dialog 22 | { 23 | public sealed partial class FolderSelectionDialog : ContentDialog 24 | { 25 | private ObservableCollection FolderCollection = App._vm.FolderCollection; 26 | private HistoryItem _source = null; 27 | public FolderSelectionDialog() 28 | { 29 | this.InitializeComponent(); 30 | Title = App._instance.App.GetLocalizationTextFromResource(LanguageName.MoveHistory); 31 | PrimaryButtonText = App._instance.App.GetLocalizationTextFromResource(LanguageName.Confirm); 32 | CloseButtonText = App._instance.App.GetLocalizationTextFromResource(LanguageName.Cancel); 33 | } 34 | 35 | public FolderSelectionDialog(HistoryItem item):this() 36 | { 37 | _source = item; 38 | FolderComboBox.SelectedItem = FolderCollection.Where(p => p.Id == item.FolderId).FirstOrDefault(); 39 | } 40 | 41 | private void ContentDialog_PrimaryButtonClick(ContentDialog sender, ContentDialogButtonClickEventArgs args) 42 | { 43 | args.Cancel = true; 44 | var newFolder = FolderComboBox.SelectedItem as FolderItem; 45 | if (newFolder.Id != _source.Id) 46 | { 47 | App._vm.MoveHistory(_source, newFolder.Id); 48 | } 49 | Hide(); 50 | } 51 | 52 | private void ContentDialog_SecondaryButtonClick(ContentDialog sender, ContentDialogButtonClickEventArgs args) 53 | { 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![applogo](https://i.loli.net/2020/07/08/hBNLW5H7YlJfqZF.png) 2 | 3 | # 工作计时器 4 | 5 | 该应用本为我实际工作需要而做,做出来之后发现并没有我想象中那么趁手,但却因为我没有想到的用途而帮助到了其它人。 6 | 7 | 于是在整理旧项目的时候,重新设计了应用的UI与功能,去掉与我工作绑定的部分,将之变得更为通用,让它作为一个正计时器继续发光发热。 8 | 9 | ## 应用截图 10 | 11 | ![首页](https://i.loli.net/2020/07/11/5DqsmxAXp2Rzhfl.png) 12 | 13 | ## 如何安装 14 | 15 | 应用已在微软应用商店上架,您可以访问 [微软应用商店](https://www.microsoft.com/store/productId/9N71W9G714RK) 进行下载。 16 | 17 | 应用要求您的系统为:**Windows 10 ver.1809** 及以上。 18 | 19 | 您也可以将该仓库克隆到本地并通过 Visual Studio 2019 运行它。 20 | 21 | 在克隆之后,需要先打开项目内的`package.appxmanifest`文件,在打包选项卡下,将证书改为自签名的证书,然后重新生成应用并部署。 22 | 23 | ## 使用说明 24 | 25 | ### 计时器 26 | 27 | 应用功能不多,核心就是一个计时器。 28 | 29 | 计时器是正向计时而非倒计时,意即你可以通过它记录你完成某件事花了多长时间,而不是要在规定时间内完成某件事。 30 | 31 | 计时器在同一时间只能存在一个,它的理想使用场景是一种单线程的工作模式,即只有一件事做完了才去做下一件事。 32 | 33 | 计时器没有暂停的功能 *(你可以观察到时间的流逝,却不能阻挡它的脚步)* ,当你停止计时后,意味着与该计时器对应的工作已经完成。这段计时记录会被保存。 34 | 35 | 你可以点击计时器按钮下方的文本(鼠标移上去会有背景色及光标变化),修改它的内容以记述你当前正在做的事。它将作为计时器的标题被保存。 36 | 37 | 在标题下面还有一个按钮,点击该按钮可以切换应用为小窗模式,即悬浮置顶于屏幕右上角,再次点击则会退出小窗模式。 38 | 39 | ### 分组与历史记录 40 | 41 | 考虑到可能有归纳整理的需求,应用在重制后添加了分组和历史记录的功能。 42 | 43 | **分组** 44 | 45 | 分组用于划分使用场景或者筛选范围。举例而言,你可以为今天创建一个分组,分组的名字就是今天的日期。你也可以给自己要做的事情进行分组,比如分为阅读,休闲等。 46 | 47 | 在应用中,你需要点击左下角的按钮来展示分组信息。当前选中的分组会高亮显示。 48 | 49 | ![分组](https://i.loli.net/2020/07/08/7zd4emhPUSVMvC9.png) 50 | 51 | **历史记录** 52 | 53 | 当计时器停止计时时,计时记录会被保存到当前选择的分组下,形成历史记录。 54 | 55 | ![历史记录](https://i.loli.net/2020/07/08/jJslYTLpdfNHDah.png) 56 | 57 | 历史记录主要包括:`花费时间`、`标题`、`创建时间`这三条信息。如果你想移动该记录到另外的分组,则可以点击卡片的更多按钮(三个点)进行操作。 58 | 59 | ### 工作时长 60 | 61 | 既然名为工作计时器,总要有些和工作有关的内容。 62 | 63 | 您可以预设一个总的工作时长,默认是360分钟,即6个小时,您可以在设置里对其进行修改。 64 | 65 | 在配置之后,您每次添加或删除计时器记录,应用都会自动统计当天总的计时时长,并显示在应用界面下方。 66 | 67 | ### 应用设置 68 | 69 | 应用提供四个基础的设置项: 70 | 71 | 1. 主题设置 72 | 73 | 可选`Light`, `Dark`和`跟随系统`,跟随系统即与当前系统主题设置同步。 74 | 75 | 2. 字体设置 76 | 77 | 应用支持全局调整字体,您可以选择您喜欢的字体进行显示。 78 | 79 | 3. 语言设置 80 | 81 | 应用支持中文、英文两种语言,可按需取用。 82 | 83 | 4. 预设时长 84 | 85 | 用于配置每天要工作的时长,以便进行统计。 86 | 87 | *由于应用已经开源,所以在设置中额外提供了一个导向本仓库的开源地址按钮* 88 | 89 | ## 工具引用 90 | 91 | - [Windows Community Toolkit](https://github.com/windows-toolkit/WindowsCommunityToolkit) 92 | - [Richasy.Helper.UWP](https://github.com/Richasy/Richasy-Helper-UWP) 93 | - [Richasy.Font.UWP](https://github.com/Richasy/Richasy-Font-UWP) 94 | - [Richasy.Controls.UWP](https://github.com/Richasy/Richasy-Controls-UWP) -------------------------------------------------------------------------------- /Work-Timer/Components/Layout/FolderPanel.xaml.cs: -------------------------------------------------------------------------------- 1 | using Lib.Share.Models; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Runtime.InteropServices.WindowsRuntime; 7 | using Windows.Foundation; 8 | using Windows.Foundation.Collections; 9 | using Windows.UI.Xaml; 10 | using Windows.UI.Xaml.Controls; 11 | using Windows.UI.Xaml.Controls.Primitives; 12 | using Windows.UI.Xaml.Data; 13 | using Windows.UI.Xaml.Input; 14 | using Windows.UI.Xaml.Media; 15 | using Windows.UI.Xaml.Navigation; 16 | using WorkTimer.Components.Dialog; 17 | using WorkTimer.Models.Core; 18 | using WorkTimer.Models.Enums; 19 | 20 | //https://go.microsoft.com/fwlink/?LinkId=234236 上介绍了“用户控件”项模板 21 | 22 | namespace WorkTimer.Components.Layout 23 | { 24 | public sealed partial class FolderPanel : UserControl 25 | { 26 | AppViewModel vm = App._vm; 27 | public FolderPanel() 28 | { 29 | this.InitializeComponent(); 30 | vm.FolderPanel = this; 31 | vm.CurrentSelectedFolderChanged += SelectedFolder_Changed; 32 | } 33 | 34 | private void SelectedFolder_Changed(object sender, FolderItem e) 35 | { 36 | FolderListView.SelectedItem = e; 37 | } 38 | 39 | private async void AddFolderButton_Click(object sender, RoutedEventArgs e) 40 | { 41 | var dialog = new FolderDialog(); 42 | await dialog.ShowAsync(); 43 | } 44 | 45 | private void FolderListView_ItemClick(object sender, ItemClickEventArgs e) 46 | { 47 | var folder = e.ClickedItem as FolderItem; 48 | if (!vm.CurrentSelectedFolder.Equals(folder)) 49 | { 50 | vm.CurrentSelectedFolder = folder; 51 | } 52 | } 53 | 54 | private async void ModifyItem_Click(object sender, RoutedEventArgs e) 55 | { 56 | var item = (sender as MenuFlyoutItem).Tag as FolderItem; 57 | var dialog = new FolderDialog(item); 58 | await dialog.ShowAsync(); 59 | } 60 | 61 | private async void RemoveItem_Click(object sender, RoutedEventArgs e) 62 | { 63 | var item = (sender as MenuFlyoutItem).Tag as FolderItem; 64 | await vm.RemoveFolder(item); 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /Work-Timer/Package.appxmanifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 10 | 14 | 15 | 16 | 17 | 18 | Working Timer 19 | 云之幻 20 | Assets\Logo\StoreLogo.png 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 35 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /Work-Timer/Theme/Light.xaml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | #AAAAAA 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /Work-Timer/Theme/Dark.xaml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | #111111 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /Work-Timer/Components/Dialog/FolderDialog.xaml: -------------------------------------------------------------------------------- 1 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 20 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 42 | 43 | 44 | 45 | 46 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /Work-Timer/Components/Dialog/FolderDialog.xaml.cs: -------------------------------------------------------------------------------- 1 | using Lib.Share.Models; 2 | using Richasy.Font.UWP.Enums; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Collections.ObjectModel; 6 | using System.IO; 7 | using System.Linq; 8 | using System.Runtime.InteropServices.WindowsRuntime; 9 | using Windows.Foundation; 10 | using Windows.Foundation.Collections; 11 | using Windows.UI.Xaml; 12 | using Windows.UI.Xaml.Controls; 13 | using Windows.UI.Xaml.Controls.Primitives; 14 | using Windows.UI.Xaml.Data; 15 | using Windows.UI.Xaml.Input; 16 | using Windows.UI.Xaml.Media; 17 | using Windows.UI.Xaml.Navigation; 18 | using WorkTimer.Models.Enums; 19 | 20 | // https://go.microsoft.com/fwlink/?LinkId=234238 上介绍了“内容对话框”项模板 21 | 22 | namespace WorkTimer.Components.Dialog 23 | { 24 | public sealed partial class FolderDialog : ContentDialog 25 | { 26 | public ObservableCollection SymbolCollection = App._vm.SymbolCollection; 27 | private FolderItem _source = null; 28 | public FolderDialog() 29 | { 30 | this.InitializeComponent(); 31 | Title = App._instance.App.GetLocalizationTextFromResource(LanguageName.FolderDialogTitle); 32 | DescriptionBlock.Text = App._instance.App.GetLocalizationTextFromResource(LanguageName.FolderDialogDescription); 33 | PrimaryButtonText= App._instance.App.GetLocalizationTextFromResource(LanguageName.Confirm); 34 | CloseButtonText = App._instance.App.GetLocalizationTextFromResource(LanguageName.Cancel); 35 | } 36 | 37 | public FolderDialog(FolderItem item):this() 38 | { 39 | _source = item; 40 | ShowIcon.Symbol = (FeatherSymbol)item.Icon; 41 | SymbolGridView.SelectedItem = (FeatherSymbol)item.Icon; 42 | NameBox.Text = item.Name; 43 | } 44 | 45 | private void ContentDialog_PrimaryButtonClick(ContentDialog sender, ContentDialogButtonClickEventArgs args) 46 | { 47 | args.Cancel = true; 48 | if (string.IsNullOrEmpty(NameBox.Text)) 49 | { 50 | App._vm.ShowPopup(LanguageName.FieldEmpty, true); 51 | return; 52 | } 53 | FolderItem item = null; 54 | if (_source == null) 55 | item = new FolderItem(NameBox.Text, ShowIcon.Symbol); 56 | else 57 | { 58 | item = _source; 59 | item.Name = NameBox.Text; 60 | item.Icon = ShowIcon.Symbol; 61 | } 62 | App._vm.AddOrUpdateFolderItem(item); 63 | Hide(); 64 | } 65 | 66 | private void ContentDialog_SecondaryButtonClick(ContentDialog sender, ContentDialogButtonClickEventArgs args) 67 | { 68 | } 69 | 70 | private void SymbolGridView_ItemClick(object sender, ItemClickEventArgs e) 71 | { 72 | var icon = (FeatherSymbol)e.ClickedItem; 73 | ShowIcon.Symbol = icon; 74 | SymbolFlyout.Hide(); 75 | } 76 | 77 | private void SymbolFlyout_Opened(object sender, object e) 78 | { 79 | if (SymbolGridView.SelectedItem != null) 80 | { 81 | SymbolGridView.ScrollIntoView(SymbolGridView.SelectedItem); 82 | } 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /Work-Timer.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30225.117 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Work-Timer", "Work-Timer\Work-Timer.csproj", "{B91BF1A1-0D7A-40B8-AA3E-C1F7D7F2DE88}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lib_Share", "Lib_Share\Lib_Share.csproj", "{55CE1B3E-4D23-4566-881B-C4F463671785}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Debug|ARM = Debug|ARM 14 | Debug|ARM64 = Debug|ARM64 15 | Debug|x64 = Debug|x64 16 | Debug|x86 = Debug|x86 17 | Release|Any CPU = Release|Any CPU 18 | Release|ARM = Release|ARM 19 | Release|ARM64 = Release|ARM64 20 | Release|x64 = Release|x64 21 | Release|x86 = Release|x86 22 | EndGlobalSection 23 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 24 | {B91BF1A1-0D7A-40B8-AA3E-C1F7D7F2DE88}.Debug|Any CPU.ActiveCfg = Debug|x86 25 | {B91BF1A1-0D7A-40B8-AA3E-C1F7D7F2DE88}.Debug|ARM.ActiveCfg = Debug|ARM 26 | {B91BF1A1-0D7A-40B8-AA3E-C1F7D7F2DE88}.Debug|ARM.Build.0 = Debug|ARM 27 | {B91BF1A1-0D7A-40B8-AA3E-C1F7D7F2DE88}.Debug|ARM.Deploy.0 = Debug|ARM 28 | {B91BF1A1-0D7A-40B8-AA3E-C1F7D7F2DE88}.Debug|ARM64.ActiveCfg = Debug|ARM64 29 | {B91BF1A1-0D7A-40B8-AA3E-C1F7D7F2DE88}.Debug|ARM64.Build.0 = Debug|ARM64 30 | {B91BF1A1-0D7A-40B8-AA3E-C1F7D7F2DE88}.Debug|ARM64.Deploy.0 = Debug|ARM64 31 | {B91BF1A1-0D7A-40B8-AA3E-C1F7D7F2DE88}.Debug|x64.ActiveCfg = Debug|x64 32 | {B91BF1A1-0D7A-40B8-AA3E-C1F7D7F2DE88}.Debug|x64.Build.0 = Debug|x64 33 | {B91BF1A1-0D7A-40B8-AA3E-C1F7D7F2DE88}.Debug|x64.Deploy.0 = Debug|x64 34 | {B91BF1A1-0D7A-40B8-AA3E-C1F7D7F2DE88}.Debug|x86.ActiveCfg = Debug|x86 35 | {B91BF1A1-0D7A-40B8-AA3E-C1F7D7F2DE88}.Debug|x86.Build.0 = Debug|x86 36 | {B91BF1A1-0D7A-40B8-AA3E-C1F7D7F2DE88}.Debug|x86.Deploy.0 = Debug|x86 37 | {B91BF1A1-0D7A-40B8-AA3E-C1F7D7F2DE88}.Release|Any CPU.ActiveCfg = Release|x86 38 | {B91BF1A1-0D7A-40B8-AA3E-C1F7D7F2DE88}.Release|ARM.ActiveCfg = Release|ARM 39 | {B91BF1A1-0D7A-40B8-AA3E-C1F7D7F2DE88}.Release|ARM.Build.0 = Release|ARM 40 | {B91BF1A1-0D7A-40B8-AA3E-C1F7D7F2DE88}.Release|ARM.Deploy.0 = Release|ARM 41 | {B91BF1A1-0D7A-40B8-AA3E-C1F7D7F2DE88}.Release|ARM64.ActiveCfg = Release|ARM64 42 | {B91BF1A1-0D7A-40B8-AA3E-C1F7D7F2DE88}.Release|ARM64.Build.0 = Release|ARM64 43 | {B91BF1A1-0D7A-40B8-AA3E-C1F7D7F2DE88}.Release|ARM64.Deploy.0 = Release|ARM64 44 | {B91BF1A1-0D7A-40B8-AA3E-C1F7D7F2DE88}.Release|x64.ActiveCfg = Release|x64 45 | {B91BF1A1-0D7A-40B8-AA3E-C1F7D7F2DE88}.Release|x64.Build.0 = Release|x64 46 | {B91BF1A1-0D7A-40B8-AA3E-C1F7D7F2DE88}.Release|x64.Deploy.0 = Release|x64 47 | {B91BF1A1-0D7A-40B8-AA3E-C1F7D7F2DE88}.Release|x86.ActiveCfg = Release|x86 48 | {B91BF1A1-0D7A-40B8-AA3E-C1F7D7F2DE88}.Release|x86.Build.0 = Release|x86 49 | {B91BF1A1-0D7A-40B8-AA3E-C1F7D7F2DE88}.Release|x86.Deploy.0 = Release|x86 50 | {55CE1B3E-4D23-4566-881B-C4F463671785}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 51 | {55CE1B3E-4D23-4566-881B-C4F463671785}.Debug|Any CPU.Build.0 = Debug|Any CPU 52 | {55CE1B3E-4D23-4566-881B-C4F463671785}.Debug|ARM.ActiveCfg = Debug|ARM 53 | {55CE1B3E-4D23-4566-881B-C4F463671785}.Debug|ARM.Build.0 = Debug|ARM 54 | {55CE1B3E-4D23-4566-881B-C4F463671785}.Debug|ARM64.ActiveCfg = Debug|ARM64 55 | {55CE1B3E-4D23-4566-881B-C4F463671785}.Debug|ARM64.Build.0 = Debug|ARM64 56 | {55CE1B3E-4D23-4566-881B-C4F463671785}.Debug|x64.ActiveCfg = Debug|x64 57 | {55CE1B3E-4D23-4566-881B-C4F463671785}.Debug|x64.Build.0 = Debug|x64 58 | {55CE1B3E-4D23-4566-881B-C4F463671785}.Debug|x86.ActiveCfg = Debug|x86 59 | {55CE1B3E-4D23-4566-881B-C4F463671785}.Debug|x86.Build.0 = Debug|x86 60 | {55CE1B3E-4D23-4566-881B-C4F463671785}.Release|Any CPU.ActiveCfg = Release|Any CPU 61 | {55CE1B3E-4D23-4566-881B-C4F463671785}.Release|Any CPU.Build.0 = Release|Any CPU 62 | {55CE1B3E-4D23-4566-881B-C4F463671785}.Release|ARM.ActiveCfg = Release|ARM 63 | {55CE1B3E-4D23-4566-881B-C4F463671785}.Release|ARM.Build.0 = Release|ARM 64 | {55CE1B3E-4D23-4566-881B-C4F463671785}.Release|ARM64.ActiveCfg = Release|ARM64 65 | {55CE1B3E-4D23-4566-881B-C4F463671785}.Release|ARM64.Build.0 = Release|ARM64 66 | {55CE1B3E-4D23-4566-881B-C4F463671785}.Release|x64.ActiveCfg = Release|x64 67 | {55CE1B3E-4D23-4566-881B-C4F463671785}.Release|x64.Build.0 = Release|x64 68 | {55CE1B3E-4D23-4566-881B-C4F463671785}.Release|x86.ActiveCfg = Release|x86 69 | {55CE1B3E-4D23-4566-881B-C4F463671785}.Release|x86.Build.0 = Release|x86 70 | EndGlobalSection 71 | GlobalSection(SolutionProperties) = preSolution 72 | HideSolutionNode = FALSE 73 | EndGlobalSection 74 | GlobalSection(ExtensibilityGlobals) = postSolution 75 | SolutionGuid = {FEEFA813-1666-4A7E-850A-1844A4EE0126} 76 | EndGlobalSection 77 | EndGlobal 78 | -------------------------------------------------------------------------------- /Work-Timer/Models/Core/AppViewModel.Properties.cs: -------------------------------------------------------------------------------- 1 | using Lib.Share.Models; 2 | using Richasy.Controls.UWP.Popups; 3 | using Richasy.Font.UWP; 4 | using Richasy.Font.UWP.Enums; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Collections.ObjectModel; 8 | using System.Linq; 9 | using Windows.UI.Xaml; 10 | using WorkTimer.Components.Layout; 11 | using WorkTimer.Components.Widget; 12 | using WorkTimer.Models.Enums; 13 | 14 | namespace WorkTimer.Models.Core 15 | { 16 | public partial class AppViewModel : DependencyObject 17 | { 18 | public ObservableCollection FolderCollection = new ObservableCollection(); 19 | public ObservableCollection DisplayHistoryCollection = new ObservableCollection(); 20 | public List AllHistoryList = new List(); 21 | private bool IsFolderListChanged = false; 22 | private bool _isHisotryListChanged = false; 23 | private bool IsHistoryListChanged 24 | { 25 | get => _isHisotryListChanged; 26 | set 27 | { 28 | if (value) 29 | HistoryChanged?.Invoke(this, EventArgs.Empty); 30 | _isHisotryListChanged = value; 31 | } 32 | } 33 | private DispatcherTimer _changeTimer = new DispatcherTimer() { Interval = TimeSpan.FromSeconds(10) }; 34 | private DispatcherTimer _durationTimer = new DispatcherTimer() { Interval = TimeSpan.FromSeconds(0.5) }; 35 | 36 | public event EventHandler CurrentSelectedFolderChanged; 37 | public event EventHandler HistoryChanged; 38 | private FolderItem _currentSelectedFolder = null; 39 | 40 | public FolderPanel FolderPanel; 41 | public HistoryPanel HistoryPanel; 42 | public WorkDurationBlock WorkDurationBlock; 43 | 44 | public CenterPopup SettingPopup; 45 | public FolderItem CurrentSelectedFolder 46 | { 47 | get => _currentSelectedFolder; 48 | set 49 | { 50 | _currentSelectedFolder = value; 51 | var history = AllHistoryList.Where(p => p.FolderId == value.Id).ToList(); 52 | DisplayHistoryCollection.Clear(); 53 | history.ForEach(p => DisplayHistoryCollection.Add(p)); 54 | App._instance.App.WriteLocalSetting(Settings.LastSelectFolderId, value.Id); 55 | CurrentSelectedFolderChanged?.Invoke(this, value); 56 | } 57 | } 58 | public DateTime BeginStamp { get; set; } 59 | 60 | public event EventHandler IsTimingChanged; 61 | private bool _isTiming = false; 62 | public bool IsTiming 63 | { 64 | get => _isTiming; 65 | set 66 | { 67 | _isTiming = value; 68 | IsTimingChanged?.Invoke(this, value); 69 | if (value) 70 | _durationTimer.Start(); 71 | else 72 | _durationTimer.Stop(); 73 | } 74 | } 75 | 76 | public string DurationText 77 | { 78 | get { return (string)GetValue(DurationTextProperty); } 79 | set { SetValue(DurationTextProperty, value); } 80 | } 81 | 82 | public static readonly DependencyProperty DurationTextProperty = 83 | DependencyProperty.Register("DurationText", typeof(string), typeof(AppViewModel), new PropertyMetadata("00:00:00")); 84 | 85 | 86 | public ObservableCollection SymbolCollection = new ObservableCollection 87 | { 88 | FeatherSymbol.Activity,FeatherSymbol.Airplay, 89 | FeatherSymbol.AlertTriangle,FeatherSymbol.Anchor, 90 | FeatherSymbol.Aperture,FeatherSymbol.Archive, 91 | FeatherSymbol.Award,FeatherSymbol.BarChart, 92 | FeatherSymbol.BarChart2,FeatherSymbol.Battery, 93 | FeatherSymbol.Bluetooth,FeatherSymbol.Book, 94 | FeatherSymbol.Bookmark,FeatherSymbol.Box, 95 | FeatherSymbol.Briefcase,FeatherSymbol.Calendar, 96 | FeatherSymbol.Camera,FeatherSymbol.Cast, 97 | FeatherSymbol.Chrome,FeatherSymbol.Clipboard, 98 | FeatherSymbol.Clock,FeatherSymbol.Cloud, 99 | FeatherSymbol.Code,FeatherSymbol.Coffee, 100 | FeatherSymbol.Cpu,FeatherSymbol.CreditCard, 101 | FeatherSymbol.Disc,FeatherSymbol.Edit, 102 | FeatherSymbol.Eye,FeatherSymbol.Facebook, 103 | FeatherSymbol.Feather,FeatherSymbol.Figma, 104 | FeatherSymbol.File,FeatherSymbol.Folder, 105 | FeatherSymbol.Framer,FeatherSymbol.Gift, 106 | FeatherSymbol.Image,FeatherSymbol.Home, 107 | FeatherSymbol.Inbox,FeatherSymbol.Info 108 | }; 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /Work-Timer/MainPage.xaml.cs: -------------------------------------------------------------------------------- 1 | using Lib.Share.Models; 2 | using Richasy.Controls.UWP.Models.UI; 3 | using Richasy.Font.UWP; 4 | using Richasy.Font.UWP.Enums; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.IO; 8 | using System.Linq; 9 | using System.Runtime.InteropServices.WindowsRuntime; 10 | using Windows.Foundation; 11 | using Windows.Foundation.Collections; 12 | using Windows.UI.Core.Preview; 13 | using Windows.UI.ViewManagement; 14 | using Windows.UI.Xaml; 15 | using Windows.UI.Xaml.Controls; 16 | using Windows.UI.Xaml.Controls.Primitives; 17 | using Windows.UI.Xaml.Data; 18 | using Windows.UI.Xaml.Input; 19 | using Windows.UI.Xaml.Media; 20 | using Windows.UI.Xaml.Navigation; 21 | using WorkTimer.Models.Core; 22 | 23 | // The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409 24 | 25 | namespace WorkTimer 26 | { 27 | /// 28 | /// An empty page that can be used on its own or navigated to within a Frame. 29 | /// 30 | public sealed partial class MainPage : RichasyPage 31 | { 32 | public AppViewModel vm = App._vm; 33 | public MainPage():base() 34 | { 35 | this.InitializeComponent(); 36 | TitleBox.Text = "Untitled"; 37 | vm.IsTimingChanged += IsTiming_Changed; 38 | vm.CurrentSelectedFolderChanged += CurrentSelectedFolder_Changed; 39 | SystemNavigationManagerPreview.GetForCurrentView().CloseRequested += CloseRequested; 40 | } 41 | 42 | private async void CloseRequested(object sender, SystemNavigationCloseRequestedPreviewEventArgs e) 43 | { 44 | e.Handled = true; 45 | await vm.SaveData(); 46 | App.Current.Exit(); 47 | } 48 | 49 | private void CurrentSelectedFolder_Changed(object sender, FolderItem e) 50 | { 51 | GroupNameBlock.Text = e.Name; 52 | } 53 | 54 | private void IsTiming_Changed(object sender, bool e) 55 | { 56 | var icon = e ? FeatherSymbol.Pause : FeatherSymbol.Play; 57 | StatusIcon.Symbol = icon; 58 | if (e) 59 | { 60 | vm.BeginStamp = DateTime.Now; 61 | } 62 | else 63 | { 64 | var ts = DateTime.Now - vm.BeginStamp; 65 | var historyItem = new HistoryItem(TitleBox.Text ?? "Untitled", vm.CurrentSelectedFolder.Id, Convert.ToInt32(ts.TotalSeconds)); 66 | vm.AddHistoryItem(historyItem); 67 | TitleBox.Text = "Untitled"; 68 | } 69 | } 70 | 71 | private void SettingButton_Click(object sender, RoutedEventArgs e) 72 | { 73 | vm.ShowSettingPopup(); 74 | } 75 | 76 | private void StatusButton_Click(object sender, RoutedEventArgs e) 77 | { 78 | vm.IsTiming = !vm.IsTiming; 79 | } 80 | 81 | private void FolderButton_Click(object sender, RoutedEventArgs e) 82 | { 83 | MainSplitView.IsPaneOpen = !MainSplitView.IsPaneOpen; 84 | } 85 | 86 | private void HistoryButton_Click(object sender, RoutedEventArgs e) 87 | { 88 | SubSplitView.IsPaneOpen = !SubSplitView.IsPaneOpen; 89 | } 90 | 91 | private async void RichasyPage_Loaded(object sender, RoutedEventArgs e) 92 | { 93 | vm.CheckUpdate(); 94 | await App._vm.Init(); 95 | } 96 | 97 | private async void CompactButton_Click(object sender, RoutedEventArgs e) 98 | { 99 | var view = ApplicationView.GetForCurrentView(); 100 | if (view.ViewMode == ApplicationViewMode.CompactOverlay) 101 | { 102 | await view.TryEnterViewModeAsync(ApplicationViewMode.Default); 103 | VisualStateManager.GoToState(this, "Default",false); 104 | } 105 | else 106 | { 107 | await view.TryEnterViewModeAsync(ApplicationViewMode.CompactOverlay); 108 | VisualStateManager.GoToState(this, "Compact", false); 109 | } 110 | 111 | } 112 | 113 | private void RichasyPage_SizeChanged(object sender, SizeChangedEventArgs e) 114 | { 115 | double width = e.NewSize.Width; 116 | if (width > 1300) 117 | { 118 | MainSplitView.DisplayMode = SplitViewDisplayMode.CompactInline; 119 | SubSplitView.DisplayMode = SplitViewDisplayMode.CompactInline; 120 | } 121 | else if (width > 900) 122 | { 123 | MainSplitView.DisplayMode = SplitViewDisplayMode.CompactOverlay; 124 | SubSplitView.DisplayMode = SplitViewDisplayMode.CompactInline; 125 | } 126 | else 127 | { 128 | MainSplitView.DisplayMode = SplitViewDisplayMode.CompactOverlay; 129 | SubSplitView.DisplayMode = SplitViewDisplayMode.CompactOverlay; 130 | } 131 | } 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /Work-Timer/Components/Layout/SettingPanel.xaml: -------------------------------------------------------------------------------- 1 | 11 | 12 | 13 | 14 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 24 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 36 | 42 | 43 | 44 | 45 | 47 | 51 | 52 | 53 | 54 | 55 | 56 | 58 | 59 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 71 | 72 | 73 | 74 | 76 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /Work-Timer/Components/Layout/HistoryPanel.xaml: -------------------------------------------------------------------------------- 1 | 11 | 12 | 13 | 14 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 25 | 26 | 27 | 29 | 31 | 33 | 34 | 36 | 37 | 38 | 39 | 40 | 41 | 43 | 44 | 45 | 46 | 47 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 68 | 69 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /Work-Timer/Components/Layout/FolderPanel.xaml: -------------------------------------------------------------------------------- 1 | 11 | 12 | 13 | 14 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 25 | 26 | 27 | 29 | 31 | 32 | 34 | 35 | 36 | 37 | 38 | 39 | 41 | 42 | 43 | 44 | 45 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 70 | 73 | 74 | 75 | 76 | 77 | 78 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /Work-Timer/Components/Layout/SettingPanel.xaml.cs: -------------------------------------------------------------------------------- 1 | using Lib.Share.Models; 2 | using Richasy.Font.UWP; 3 | using System; 4 | using System.Collections.ObjectModel; 5 | using System.Linq; 6 | using System.Threading.Tasks; 7 | using Windows.ApplicationModel.Core; 8 | using Windows.Globalization; 9 | using Windows.System; 10 | using Windows.UI.Xaml; 11 | using Windows.UI.Xaml.Controls; 12 | using WorkTimer.Components.Dialog; 13 | using WorkTimer.Models.Enums; 14 | 15 | //https://go.microsoft.com/fwlink/?LinkId=234236 上介绍了“用户控件”项模板 16 | 17 | namespace WorkTimer.Components.Layout 18 | { 19 | public sealed partial class SettingPanel : UserControl 20 | { 21 | private ObservableCollection FontCollection = new ObservableCollection(); 22 | private bool _isInit = false; 23 | public SettingPanel() 24 | { 25 | this.InitializeComponent(); 26 | string lan = ApplicationLanguages.PrimaryLanguageOverride.Equals("zh-CN", StringComparison.OrdinalIgnoreCase) ? "zh-Hans-CN" : "en-US"; 27 | var fonts = SystemFont.GetSystemFonts(lan); 28 | fonts.ForEach(p => FontCollection.Add(p)); 29 | } 30 | 31 | private async void ThemeComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e) 32 | { 33 | if (!_isInit) 34 | return; 35 | var item = (ThemeComboBox.SelectedItem as ComboBoxItem).Tag.ToString(); 36 | string oldTheme = App._instance.App.GetLocalSetting(Settings.Theme, StaticString.ThemeSystem); 37 | if (oldTheme != item) 38 | { 39 | App._instance.App.WriteLocalSetting(Settings.Theme, item); 40 | await ShowRestartDialog(); 41 | } 42 | } 43 | 44 | private async void FontComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e) 45 | { 46 | if (!_isInit) 47 | return; 48 | var item = FontComboBox.SelectedItem as SystemFont; 49 | string oldFont = App._instance.App.GetLocalSetting(Settings.FontFamily, StaticString.FontDefault); 50 | if (item.Name != oldFont) 51 | { 52 | App._instance.App.WriteLocalSetting(Settings.FontFamily, item.Name); 53 | await ShowRestartDialog(); 54 | } 55 | } 56 | 57 | private void UserControl_Loaded(object sender, RoutedEventArgs e) 58 | { 59 | string theme = App._instance.App.GetLocalSetting(Settings.Theme, StaticString.ThemeSystem); 60 | switch (theme) 61 | { 62 | case StaticString.ThemeSystem: 63 | ThemeComboBox.SelectedIndex = 0; 64 | break; 65 | case StaticString.ThemeLight: 66 | ThemeComboBox.SelectedIndex = 1; 67 | break; 68 | case StaticString.ThemeDark: 69 | ThemeComboBox.SelectedIndex = 2; 70 | break; 71 | default: 72 | break; 73 | } 74 | FontInit(); 75 | string lan = App._instance.App.GetLocalSetting(Settings.Language, StaticString.LanZh); 76 | LanguageComboBox.SelectedIndex = lan == StaticString.LanZh ? 0 : 1; 77 | string presetDuration = App._instance.App.GetLocalSetting(Settings.PresetDuration, "360"); 78 | PresetDurationBox.Value = Convert.ToDouble(presetDuration); 79 | _isInit = true; 80 | } 81 | private async Task ShowRestartDialog() 82 | { 83 | var dialog = new ConfirmDialog(LanguageName.StaticResourceRestart) { PrimaryButtonText = App._instance.App.GetLocalizationTextFromResource(LanguageName.RestartNow) }; 84 | dialog.PrimaryButtonClick += async (_s, _e) => 85 | { 86 | await CoreApplication.RequestRestartAsync("restart"); 87 | }; 88 | await dialog.ShowAsync(); 89 | } 90 | private void FontInit() 91 | { 92 | FontComboBox.IsEnabled = false; 93 | if (FontCollection != null && FontCollection.Count > 0) 94 | { 95 | string fontName = App._instance.App.GetLocalSetting(Settings.FontFamily, StaticString.FontDefault); 96 | var font = FontCollection.Where(p => p.Name == fontName).FirstOrDefault(); 97 | if (font != null) 98 | { 99 | FontComboBox.SelectedItem = font; 100 | } 101 | } 102 | FontComboBox.IsEnabled = true; 103 | } 104 | 105 | private async void LanguageComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e) 106 | { 107 | if (!_isInit) 108 | return; 109 | var item = (LanguageComboBox.SelectedItem as ComboBoxItem).Tag.ToString(); 110 | string oldLan = App._instance.App.GetLocalSetting(Settings.Language, StaticString.LanZh); 111 | if (oldLan != item) 112 | { 113 | App._instance.App.WriteLocalSetting(Settings.Language, item); 114 | await ShowRestartDialog(); 115 | } 116 | } 117 | 118 | private void PresetDurationBox_ValueChanged(object sender, double e) 119 | { 120 | if (!_isInit) 121 | return; 122 | App._instance.App.WriteLocalSetting(Settings.PresetDuration, e.ToString()); 123 | App._vm.WorkDurationBlock.UpdatePresetDuration(); 124 | } 125 | 126 | private async void OpenSourceButton_Click(object sender, RoutedEventArgs e) 127 | { 128 | await Launcher.LaunchUriAsync(new Uri("https://github.com/Richasy/Work-Timer")); 129 | } 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /Work-Timer/App.xaml.cs: -------------------------------------------------------------------------------- 1 | using Lib.Share.Models; 2 | using Richasy.Helper.UWP; 3 | using System; 4 | using Windows.ApplicationModel; 5 | using Windows.ApplicationModel.Activation; 6 | using Windows.Globalization; 7 | using Windows.UI.Xaml; 8 | using Windows.UI.Xaml.Controls; 9 | using Windows.UI.Xaml.Navigation; 10 | using Windows.UI.Xaml.Resources; 11 | using WorkTimer.Models.Core; 12 | using WorkTimer.Models.Enums; 13 | using WorkTimer.Models.UI; 14 | 15 | namespace WorkTimer 16 | { 17 | /// 18 | /// Provides application-specific behavior to supplement the default Application class. 19 | /// 20 | sealed partial class App : Application 21 | { 22 | /// 23 | /// Initializes the singleton application object. This is the first line of authored code 24 | /// executed, and as such is the logical equivalent of main() or WinMain(). 25 | /// 26 | public static Instance _instance = new Instance(StaticString.AppName); 27 | public static AppViewModel _vm = new AppViewModel(); 28 | public App() 29 | { 30 | this.InitializeComponent(); 31 | ChangeLanguage(); 32 | this.Suspending += OnSuspending; 33 | CustomXamlResourceLoader.Current = new CustomResourceLoader(); 34 | string theme = _instance.App.GetLocalSetting(Settings.Theme, StaticString.ThemeSystem); 35 | if (theme != StaticString.ThemeSystem) 36 | { 37 | RequestedTheme = theme == StaticString.ThemeLight ? ApplicationTheme.Light : ApplicationTheme.Dark; 38 | } 39 | UnhandledException += UnhandleExceptionHandle; 40 | } 41 | 42 | private void UnhandleExceptionHandle(object sender, Windows.UI.Xaml.UnhandledExceptionEventArgs e) 43 | { 44 | e.Handled = true; 45 | _vm.ShowPopup(e.Message, true); 46 | } 47 | /// 48 | /// 更改语言首选项 49 | /// 50 | private void ChangeLanguage() 51 | { 52 | string lan = _instance.App.GetLocalSetting(Settings.Language, ""); 53 | 54 | if (lan == "") 55 | { 56 | var Languages = Windows.System.UserProfile.GlobalizationPreferences.Languages; 57 | if (Languages.Count > 0) 58 | { 59 | var language = Languages[0]; 60 | if (language.ToLower().IndexOf("zh") != -1) 61 | { 62 | _instance.App.WriteLocalSetting(Settings.Language, StaticString.LanZh); 63 | } 64 | else 65 | { 66 | _instance.App.WriteLocalSetting(Settings.Language, StaticString.LanEn); 67 | } 68 | } 69 | else 70 | { 71 | _instance.App.WriteLocalSetting(Settings.Language, StaticString.LanEn); 72 | } 73 | } 74 | lan = _instance.App.GetLocalSetting(Settings.Language, StaticString.LanEn); 75 | string code = ""; 76 | switch (lan) 77 | { 78 | case StaticString.LanZh: 79 | code = "zh-CN"; 80 | break; 81 | case StaticString.LanEn: 82 | code = "en-US"; 83 | break; 84 | default: 85 | code = "en-US"; 86 | break; 87 | } 88 | ApplicationLanguages.PrimaryLanguageOverride = code; 89 | } 90 | protected override void OnActivated(IActivatedEventArgs args) 91 | { 92 | OnLaunchedOrActivated(args); 93 | } 94 | /// 95 | /// Invoked when the application is launched normally by the end user. Other entry points 96 | /// will be used such as when the application is launched to open a specific file. 97 | /// 98 | /// Details about the launch request and process. 99 | protected override void OnLaunched(LaunchActivatedEventArgs e) 100 | { 101 | OnLaunchedOrActivated(e); 102 | } 103 | private void OnLaunchedOrActivated(IActivatedEventArgs e) 104 | { 105 | Frame rootFrame = Window.Current.Content as Frame; 106 | _instance = new Instance(StaticString.AppName); 107 | // Do not repeat app initialization when the Window already has content, 108 | // just ensure that the window is active 109 | if (rootFrame == null) 110 | { 111 | // Create a Frame to act as the navigation context and navigate to the first page 112 | rootFrame = new Frame(); 113 | 114 | rootFrame.NavigationFailed += OnNavigationFailed; 115 | 116 | if (e.PreviousExecutionState == ApplicationExecutionState.Terminated) 117 | { 118 | //TODO: Load state from previously suspended application 119 | } 120 | 121 | // Place the frame in the current Window 122 | Window.Current.Content = rootFrame; 123 | } 124 | 125 | if (e is LaunchActivatedEventArgs && (e as LaunchActivatedEventArgs).PrelaunchActivated == false) 126 | { 127 | if (rootFrame.Content == null) 128 | { 129 | rootFrame.Navigate(typeof(MainPage), (e as LaunchActivatedEventArgs).Arguments); 130 | } 131 | } 132 | else if (e is ProtocolActivatedEventArgs protocalArgs) 133 | { 134 | string arg = protocalArgs.Uri.Query.Replace("?", ""); 135 | if (rootFrame.Content == null) 136 | { 137 | rootFrame.Navigate(typeof(MainPage), arg); 138 | } 139 | } 140 | 141 | Window.Current.Activate(); 142 | _instance.App.SetTitleBarColor(); 143 | } 144 | /// 145 | /// Invoked when Navigation to a certain page fails 146 | /// 147 | /// The Frame which failed navigation 148 | /// Details about the navigation failure 149 | void OnNavigationFailed(object sender, NavigationFailedEventArgs e) 150 | { 151 | throw new Exception("Failed to load Page " + e.SourcePageType.FullName); 152 | } 153 | 154 | /// 155 | /// Invoked when application execution is being suspended. Application state is saved 156 | /// without knowing whether the application will be terminated or resumed with the contents 157 | /// of memory still intact. 158 | /// 159 | /// The source of the suspend request. 160 | /// Details about the suspend request. 161 | private void OnSuspending(object sender, SuspendingEventArgs e) 162 | { 163 | var deferral = e.SuspendingOperation.GetDeferral(); 164 | //TODO: Save application state and stop any background activity 165 | deferral.Complete(); 166 | } 167 | } 168 | } 169 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.rsuser 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Build results 17 | [Dd]ebug/ 18 | [Dd]ebugPublic/ 19 | [Rr]elease/ 20 | [Rr]eleases/ 21 | x64/ 22 | x86/ 23 | [Aa][Rr][Mm]/ 24 | [Aa][Rr][Mm]64/ 25 | bld/ 26 | [Bb]in/ 27 | [Oo]bj/ 28 | [Ll]og/ 29 | 30 | # Visual Studio 2015/2017 cache/options directory 31 | .vs/ 32 | # Uncomment if you have tasks that create the project's static files in wwwroot 33 | #wwwroot/ 34 | 35 | # Visual Studio 2017 auto generated files 36 | Generated\ Files/ 37 | 38 | # MSTest test Results 39 | [Tt]est[Rr]esult*/ 40 | [Bb]uild[Ll]og.* 41 | 42 | # NUNIT 43 | *.VisualState.xml 44 | TestResult.xml 45 | 46 | # Build Results of an ATL Project 47 | [Dd]ebugPS/ 48 | [Rr]eleasePS/ 49 | dlldata.c 50 | 51 | # Benchmark Results 52 | BenchmarkDotNet.Artifacts/ 53 | 54 | # .NET Core 55 | project.lock.json 56 | project.fragment.lock.json 57 | artifacts/ 58 | 59 | # StyleCop 60 | StyleCopReport.xml 61 | 62 | # Files built by Visual Studio 63 | *_i.c 64 | *_p.c 65 | *_h.h 66 | *.ilk 67 | *.meta 68 | *.obj 69 | *.iobj 70 | *.pch 71 | *.pdb 72 | *.ipdb 73 | *.pgc 74 | *.pgd 75 | *.rsp 76 | *.sbr 77 | *.tlb 78 | *.tli 79 | *.tlh 80 | *.tmp 81 | *.tmp_proj 82 | *_wpftmp.csproj 83 | *.log 84 | *.vspscc 85 | *.vssscc 86 | .builds 87 | *.pidb 88 | *.svclog 89 | *.scc 90 | 91 | # Chutzpah Test files 92 | _Chutzpah* 93 | 94 | # Visual C++ cache files 95 | ipch/ 96 | *.aps 97 | *.ncb 98 | *.opendb 99 | *.opensdf 100 | *.sdf 101 | *.cachefile 102 | *.VC.db 103 | *.VC.VC.opendb 104 | 105 | # Visual Studio profiler 106 | *.psess 107 | *.vsp 108 | *.vspx 109 | *.sap 110 | 111 | # Visual Studio Trace Files 112 | *.e2e 113 | 114 | # TFS 2012 Local Workspace 115 | $tf/ 116 | 117 | # Guidance Automation Toolkit 118 | *.gpState 119 | 120 | # ReSharper is a .NET coding add-in 121 | _ReSharper*/ 122 | *.[Rr]e[Ss]harper 123 | *.DotSettings.user 124 | 125 | # JustCode is a .NET coding add-in 126 | .JustCode 127 | 128 | # TeamCity is a build add-in 129 | _TeamCity* 130 | 131 | # DotCover is a Code Coverage Tool 132 | *.dotCover 133 | 134 | # AxoCover is a Code Coverage Tool 135 | .axoCover/* 136 | !.axoCover/settings.json 137 | 138 | # Visual Studio code coverage results 139 | *.coverage 140 | *.coveragexml 141 | 142 | # NCrunch 143 | _NCrunch_* 144 | .*crunch*.local.xml 145 | nCrunchTemp_* 146 | 147 | # MightyMoose 148 | *.mm.* 149 | AutoTest.Net/ 150 | 151 | # Web workbench (sass) 152 | .sass-cache/ 153 | 154 | # Installshield output folder 155 | [Ee]xpress/ 156 | 157 | # DocProject is a documentation generator add-in 158 | DocProject/buildhelp/ 159 | DocProject/Help/*.HxT 160 | DocProject/Help/*.HxC 161 | DocProject/Help/*.hhc 162 | DocProject/Help/*.hhk 163 | DocProject/Help/*.hhp 164 | DocProject/Help/Html2 165 | DocProject/Help/html 166 | 167 | # Click-Once directory 168 | publish/ 169 | 170 | # Publish Web Output 171 | *.[Pp]ublish.xml 172 | *.azurePubxml 173 | # Note: Comment the next line if you want to checkin your web deploy settings, 174 | # but database connection strings (with potential passwords) will be unencrypted 175 | *.pubxml 176 | *.publishproj 177 | 178 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 179 | # checkin your Azure Web App publish settings, but sensitive information contained 180 | # in these scripts will be unencrypted 181 | PublishScripts/ 182 | 183 | # NuGet Packages 184 | *.nupkg 185 | # The packages folder can be ignored because of Package Restore 186 | **/[Pp]ackages/* 187 | # except build/, which is used as an MSBuild target. 188 | !**/[Pp]ackages/build/ 189 | # Uncomment if necessary however generally it will be regenerated when needed 190 | #!**/[Pp]ackages/repositories.config 191 | # NuGet v3's project.json files produces more ignorable files 192 | *.nuget.props 193 | *.nuget.targets 194 | 195 | # Microsoft Azure Build Output 196 | csx/ 197 | *.build.csdef 198 | 199 | # Microsoft Azure Emulator 200 | ecf/ 201 | rcf/ 202 | 203 | # Windows Store app package directories and files 204 | AppPackages/ 205 | BundleArtifacts/ 206 | Package.StoreAssociation.xml 207 | _pkginfo.txt 208 | *.appx 209 | 210 | # Visual Studio cache files 211 | # files ending in .cache can be ignored 212 | *.[Cc]ache 213 | # but keep track of directories ending in .cache 214 | !?*.[Cc]ache/ 215 | 216 | # Others 217 | ClientBin/ 218 | ~$* 219 | *~ 220 | *.dbmdl 221 | *.dbproj.schemaview 222 | *.jfm 223 | *.pfx 224 | *.publishsettings 225 | orleans.codegen.cs 226 | 227 | # Including strong name files can present a security risk 228 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 229 | #*.snk 230 | 231 | # Since there are multiple workflows, uncomment next line to ignore bower_components 232 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 233 | #bower_components/ 234 | 235 | # RIA/Silverlight projects 236 | Generated_Code/ 237 | 238 | # Backup & report files from converting an old project file 239 | # to a newer Visual Studio version. Backup files are not needed, 240 | # because we have git ;-) 241 | _UpgradeReport_Files/ 242 | Backup*/ 243 | UpgradeLog*.XML 244 | UpgradeLog*.htm 245 | ServiceFabricBackup/ 246 | *.rptproj.bak 247 | 248 | # SQL Server files 249 | *.mdf 250 | *.ldf 251 | *.ndf 252 | 253 | # Business Intelligence projects 254 | *.rdl.data 255 | *.bim.layout 256 | *.bim_*.settings 257 | *.rptproj.rsuser 258 | *- Backup*.rdl 259 | 260 | # Microsoft Fakes 261 | FakesAssemblies/ 262 | 263 | # GhostDoc plugin setting file 264 | *.GhostDoc.xml 265 | 266 | # Node.js Tools for Visual Studio 267 | .ntvs_analysis.dat 268 | node_modules/ 269 | 270 | # Visual Studio 6 build log 271 | *.plg 272 | 273 | # Visual Studio 6 workspace options file 274 | *.opt 275 | 276 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 277 | *.vbw 278 | 279 | # Visual Studio LightSwitch build output 280 | **/*.HTMLClient/GeneratedArtifacts 281 | **/*.DesktopClient/GeneratedArtifacts 282 | **/*.DesktopClient/ModelManifest.xml 283 | **/*.Server/GeneratedArtifacts 284 | **/*.Server/ModelManifest.xml 285 | _Pvt_Extensions 286 | 287 | # Paket dependency manager 288 | .paket/paket.exe 289 | paket-files/ 290 | 291 | # FAKE - F# Make 292 | .fake/ 293 | 294 | # JetBrains Rider 295 | .idea/ 296 | *.sln.iml 297 | 298 | # CodeRush personal settings 299 | .cr/personal 300 | 301 | # Python Tools for Visual Studio (PTVS) 302 | __pycache__/ 303 | *.pyc 304 | 305 | # Cake - Uncomment if you are using it 306 | # tools/** 307 | # !tools/packages.config 308 | 309 | # Tabs Studio 310 | *.tss 311 | 312 | # Telerik's JustMock configuration file 313 | *.jmconfig 314 | 315 | # BizTalk build output 316 | *.btp.cs 317 | *.btm.cs 318 | *.odx.cs 319 | *.xsd.cs 320 | 321 | # OpenCover UI analysis results 322 | OpenCover/ 323 | 324 | # Azure Stream Analytics local run output 325 | ASALocalRun/ 326 | 327 | # MSBuild Binary and Structured Log 328 | *.binlog 329 | 330 | # NVidia Nsight GPU debugger configuration file 331 | *.nvuser 332 | 333 | # MFractors (Xamarin productivity tool) working folder 334 | .mfractor/ 335 | 336 | # Local History for Visual Studio 337 | .localhistory/ 338 | 339 | # BeatPulse healthcheck temp database 340 | healthchecksdb -------------------------------------------------------------------------------- /Lib_Share/Lib_Share.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {55CE1B3E-4D23-4566-881B-C4F463671785} 8 | Library 9 | Properties 10 | Lib.Share 11 | Lib_Share 12 | zh-CN 13 | UAP 14 | 10.0.19041.0 15 | 10.0.17763.0 16 | 14 17 | 512 18 | {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 19 | 20 | 21 | AnyCPU 22 | true 23 | full 24 | false 25 | bin\Debug\ 26 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP 27 | prompt 28 | 4 29 | 30 | 31 | AnyCPU 32 | pdbonly 33 | true 34 | bin\Release\ 35 | TRACE;NETFX_CORE;WINDOWS_UWP 36 | prompt 37 | 4 38 | 39 | 40 | x86 41 | true 42 | bin\x86\Debug\ 43 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP 44 | ;2008 45 | full 46 | false 47 | prompt 48 | 49 | 50 | x86 51 | bin\x86\Release\ 52 | TRACE;NETFX_CORE;WINDOWS_UWP 53 | true 54 | ;2008 55 | pdbonly 56 | false 57 | prompt 58 | 59 | 60 | ARM 61 | true 62 | bin\ARM\Debug\ 63 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP 64 | ;2008 65 | full 66 | false 67 | prompt 68 | 69 | 70 | ARM 71 | bin\ARM\Release\ 72 | TRACE;NETFX_CORE;WINDOWS_UWP 73 | true 74 | ;2008 75 | pdbonly 76 | false 77 | prompt 78 | 79 | 80 | ARM64 81 | true 82 | bin\ARM64\Debug\ 83 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP 84 | ;2008 85 | full 86 | false 87 | prompt 88 | 89 | 90 | ARM64 91 | bin\ARM64\Release\ 92 | TRACE;NETFX_CORE;WINDOWS_UWP 93 | true 94 | ;2008 95 | pdbonly 96 | false 97 | prompt 98 | 99 | 100 | x64 101 | true 102 | bin\x64\Debug\ 103 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP 104 | ;2008 105 | full 106 | false 107 | prompt 108 | 109 | 110 | x64 111 | bin\x64\Release\ 112 | TRACE;NETFX_CORE;WINDOWS_UWP 113 | true 114 | ;2008 115 | pdbonly 116 | false 117 | prompt 118 | 119 | 120 | PackageReference 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 6.2.10 133 | 134 | 135 | 1.0.7 136 | 137 | 138 | 139 | 14.0 140 | 141 | 142 | 149 | -------------------------------------------------------------------------------- /Work-Timer/MainPage.xaml: -------------------------------------------------------------------------------- 1 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 56 | 58 | 59 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 81 | 83 | 87 | 88 | 89 | 90 | 91 | 93 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 112 | 113 | 114 | 115 | 116 | 117 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | -------------------------------------------------------------------------------- /Work-Timer/Language/zh-CN/Resources.resw: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | 工作计时器 122 | 123 | 124 | 工作时长 125 | 126 | 127 | 添加分组 128 | 129 | 130 | 工作计时器 131 | 132 | 133 | 暗色主题 134 | 135 | 136 | 您可以将该计时器历史记录转移至其它分组,在下方的下拉框中选择目标分组 137 | 138 | 139 | 计时器分组 140 | 141 | 142 | 跟随系统 143 | 144 | 145 | 字体设置 146 | 147 | 148 | 语言设置 149 | 150 | 151 | 亮色主题 152 | 153 | 154 | 修改 155 | 156 | 157 | 开源地址 158 | 159 | 160 | 预设时长 161 | 162 | 163 | 移除 164 | 165 | 166 | 主题设置 167 | 168 | 169 | 转移 170 | 171 | 172 | 取消 173 | 174 | 175 | 确认 176 | 177 | 178 | 是否要移除该分组?该分组下的所有计时器记录都将被移除 179 | 180 | 181 | 是否要移除该计时器记录? 182 | 183 | 184 | 默认 185 | 186 | 187 | 请将字段填写完整 188 | 189 | 190 | 您可以创建不同的分组,以便对不同情景下的计时进行分类。只需添加一个图标,并起一个易识别的名字 191 | 192 | 193 | 计时器分组 194 | 195 | 196 | 已将计时添加到历史记录 197 | 198 | 199 | 转移历史记录 200 | 201 | 202 | 至少需要一个计时器分组 203 | 204 | 205 | 立即重启 206 | 207 | 208 | 应用设置 209 | 210 | 211 | 您更改了静态资源设置,请重启应用以生效 212 | 213 | 214 | 更新说明 215 | 216 | 217 | 等待中 218 | 219 | 220 | 提醒 221 | 222 | -------------------------------------------------------------------------------- /Work-Timer/Models/Core/AppViewModel.cs: -------------------------------------------------------------------------------- 1 | using Lib.Share.Models; 2 | using Newtonsoft.Json; 3 | using Richasy.Controls.UWP.Popups; 4 | using Richasy.Controls.UWP.Widgets; 5 | using Richasy.Font.UWP; 6 | using Richasy.Font.UWP.Enums; 7 | using System; 8 | using System.Collections.Generic; 9 | using System.Linq; 10 | using System.Threading.Tasks; 11 | using Windows.Storage; 12 | using Windows.UI; 13 | using Windows.UI.Xaml; 14 | using WorkTimer.Components.Dialog; 15 | using WorkTimer.Components.Layout; 16 | using WorkTimer.Models.Enums; 17 | 18 | namespace WorkTimer.Models.Core 19 | { 20 | public partial class AppViewModel 21 | { 22 | public AppViewModel() 23 | { 24 | _changeTimer.Tick += ChangeTimer_Tick; 25 | _durationTimer.Tick += DurationTimer_Tick; 26 | _changeTimer.Start(); 27 | } 28 | 29 | private void DurationTimer_Tick(object sender, object e) 30 | { 31 | if (BeginStamp == DateTime.MinValue) 32 | return; 33 | var ts = DateTime.Now - BeginStamp; 34 | string display = $"{ts.Hours:00}:{ts.Minutes:00}:{ts.Seconds:00}"; 35 | DurationText = display; 36 | } 37 | 38 | public async Task Init() 39 | { 40 | var folderList = await App._instance.IO.GetLocalDataAsync>(StaticString.FolderListFileName); 41 | var historyList = await App._instance.IO.GetLocalDataAsync>(StaticString.HistoryListFileName); 42 | FolderCollection.Clear(); 43 | DisplayHistoryCollection.Clear(); 44 | if(!folderList.IsNullOrEmpty()) 45 | folderList.ForEach(p => FolderCollection.Add(p)); 46 | else 47 | { 48 | var folderItem = new FolderItem(App._instance.App.GetLocalizationTextFromResource(LanguageName.Default), FeatherSymbol.Activity); 49 | FolderCollection.Add(folderItem); 50 | await SaveFolderList(); 51 | } 52 | 53 | string lastSelectedFolderId = App._instance.App.GetLocalSetting(Settings.LastSelectFolderId, ""); 54 | if (!FolderCollection.Any(p=>p.Id==lastSelectedFolderId)) 55 | lastSelectedFolderId = FolderCollection.First().Id; 56 | 57 | CurrentSelectedFolder = FolderCollection.Where(p => p.Id == lastSelectedFolderId).First(); 58 | 59 | if (!historyList.IsNullOrEmpty()) 60 | { 61 | AllHistoryList = historyList; 62 | historyList.Where(p => p.FolderId == lastSelectedFolderId).ToList().ForEach(p=>DisplayHistoryCollection.Add(p)); 63 | HistoryChanged?.Invoke(this, EventArgs.Empty); 64 | } 65 | } 66 | public async Task SaveFolderList() 67 | { 68 | IsFolderListChanged = false; 69 | List folderList = new List(); 70 | folderList = FolderCollection.ToList(); 71 | await App._instance.IO.SetLocalDataAsync(StaticString.FolderListFileName, JsonConvert.SerializeObject(folderList)); 72 | } 73 | public async Task SaveHistoryList() 74 | { 75 | IsHistoryListChanged = false; 76 | await App._instance.IO.SetLocalDataAsync(StaticString.HistoryListFileName, JsonConvert.SerializeObject(AllHistoryList)); 77 | } 78 | private async void ChangeTimer_Tick(object sender, object e) 79 | { 80 | await SaveData(); 81 | } 82 | public void AddHistoryItem(HistoryItem item) 83 | { 84 | AllHistoryList.Add(item); 85 | if (item.FolderId == CurrentSelectedFolder.Id) 86 | DisplayHistoryCollection.Add(item); 87 | DurationText = "00:00:00"; 88 | BeginStamp = DateTime.MinValue; 89 | ShowPopup(LanguageName.HasAddedHistoryItem); 90 | IsHistoryListChanged = true; 91 | } 92 | public void AddOrUpdateFolderItem(FolderItem item) 93 | { 94 | if (FolderCollection.Contains(item)) 95 | { 96 | int sourceIndex = FolderCollection.IndexOf(item); 97 | FolderCollection.Remove(item); 98 | FolderCollection.Insert(sourceIndex, item); 99 | if (CurrentSelectedFolder != null && CurrentSelectedFolder.Equals(item)) 100 | CurrentSelectedFolderChanged?.Invoke(this, item); 101 | IsFolderListChanged = true; 102 | } 103 | else 104 | { 105 | FolderCollection.Add(item); 106 | IsFolderListChanged = true; 107 | } 108 | } 109 | public async Task RemoveFolder(FolderItem item) 110 | { 111 | if (FolderCollection.Count == 1) 112 | { 113 | ShowPopup(LanguageName.NeedOneFolder, true); 114 | return; 115 | } 116 | var confirmDialog = new ConfirmDialog(LanguageName.ConfirmRemoveFolder); 117 | confirmDialog.PrimaryButtonClick += (_s, _e) => 118 | { 119 | FolderCollection.Remove(item); 120 | AllHistoryList.RemoveAll(p => p.FolderId == item.Id); 121 | if (CurrentSelectedFolder.Equals(item)) 122 | { 123 | var first = FolderCollection.First(); 124 | CurrentSelectedFolder = first; 125 | } 126 | IsFolderListChanged = true; 127 | IsHistoryListChanged = true; 128 | }; 129 | await confirmDialog.ShowAsync(); 130 | } 131 | public async Task RemoveHistory(HistoryItem item) 132 | { 133 | var confirmDialog = new ConfirmDialog(LanguageName.ConfirmRemoveHistory); 134 | confirmDialog.PrimaryButtonClick += (_s, _e) => 135 | { 136 | AllHistoryList.Remove(item); 137 | DisplayHistoryCollection.Remove(item); 138 | IsHistoryListChanged = true; 139 | }; 140 | await confirmDialog.ShowAsync(); 141 | } 142 | public void MoveHistory(HistoryItem source,string newFolderId) 143 | { 144 | foreach (var item in AllHistoryList) 145 | { 146 | if (item.Id == source.Id) 147 | { 148 | item.FolderId = newFolderId; 149 | break; 150 | } 151 | } 152 | DisplayHistoryCollection.Remove(source); 153 | IsHistoryListChanged = true; 154 | } 155 | public async Task SaveData() 156 | { 157 | if (IsFolderListChanged) 158 | await SaveFolderList(); 159 | if (IsHistoryListChanged) 160 | await SaveHistoryList(); 161 | } 162 | public void ShowPopup(LanguageName name,bool isError = false) 163 | { 164 | ShowPopup(App._instance.App.GetLocalizationTextFromResource(name), isError); 165 | } 166 | public void ShowPopup(string msg, bool isError = false) 167 | { 168 | var popup = new TipPopup(App._instance, msg); 169 | ColorName color = isError ? ColorName.ErrorColor : ColorName.PrimaryColor; 170 | popup.Show(color); 171 | } 172 | 173 | public void ShowSettingPopup() 174 | { 175 | if (SettingPopup == null) 176 | { 177 | var header = new CenterPopupHeader(); 178 | header.Padding = new Thickness(20, 10, 20, 10); 179 | header.Title = App._instance.App.GetLocalizationTextFromResource(LanguageName.Settings); 180 | header.CloseButtonStyle = App._instance.App.GetStyleFromResource(StyleName.PopupHeaderButtonStyle); 181 | header.TitleTextStyle = App._instance.App.GetStyleFromResource(StyleName.SubtitleTextStyle); 182 | header.CloseIcon = new FeatherIcon(FeatherSymbol.X) { FontSize = 13 }; 183 | var settingPanel = new SettingPanel(); 184 | SettingPopup = CenterPopup.CreatePopup(App._instance, header, settingPanel); 185 | header.CloseButtonClick += (_s, _e) => 186 | { 187 | SettingPopup.Hide(); 188 | }; 189 | SettingPopup.Style = App._instance.App.GetStyleFromResource(StyleName.BasicCenterPopupStyle); 190 | } 191 | SettingPopup.Show(); 192 | } 193 | 194 | public async void CheckUpdate() 195 | { 196 | string localVersion = App._instance.App.GetLocalSetting(Settings.AppVersion, ""); 197 | if (localVersion != VersionBlock.Version) 198 | { 199 | var main = new VersionBlock(); 200 | main.Title = App._instance.App.GetLocalizationTextFromResource(LanguageName.UpdateTitle); 201 | string lan = App._instance.App.GetLocalSetting(Settings.Language, "zh_CN"); 202 | var file = await StorageFile.GetFileFromApplicationUriAsync(new Uri($"ms-appx:///Others/Update_{lan}.txt")); 203 | string content = await FileIO.ReadTextAsync(file); 204 | main.Description = content; 205 | main.LogoUri = "ms-appx:///Assets/AppLogo.png"; 206 | main.ActionButtonStyle = App._instance.App.GetStyleFromResource(StyleName.PrimaryActionButtonStyle); 207 | main.ActionIcon = new FeatherIcon(FeatherSymbol.X); 208 | main.TitleTextStyle = App._instance.App.GetStyleFromResource(StyleName.SubtitleTextStyle); 209 | main.DescriptionTextStyle = App._instance.App.GetStyleFromResource(StyleName.BasicMarkdownTextBlock); 210 | var popup = new CenterPopup(App._instance); 211 | popup.Style = App._instance.App.GetStyleFromResource(StyleName.BasicCenterPopupStyle); 212 | popup.Main = main; 213 | main.ActionButtonClick += (_s, _e) => 214 | { 215 | popup.Hide(); 216 | App._instance.App.WriteLocalSetting(Settings.AppVersion, VersionBlock.Version); 217 | }; 218 | popup.Show(); 219 | } 220 | } 221 | } 222 | } 223 | -------------------------------------------------------------------------------- /Work-Timer/Language/en-US/Resources.resw: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | Work Timer 122 | 123 | 124 | Work Duration 125 | 126 | 127 | Add folder 128 | 129 | 130 | Work Timer 131 | 132 | 133 | Dark 134 | 135 | 136 | You can transfer the timer history to other folder, select the target folder in the combo box below 137 | 138 | 139 | Timer Folder 140 | 141 | 142 | System 143 | 144 | 145 | Font 146 | 147 | 148 | Language 149 | 150 | 151 | Light 152 | 153 | 154 | Modify 155 | 156 | 157 | Open source link 158 | 159 | 160 | Preset Duration 161 | 162 | 163 | Remove 164 | 165 | 166 | Theme 167 | 168 | 169 | Transfer 170 | 171 | 172 | Cancel 173 | 174 | 175 | Confirm 176 | 177 | 178 | Do you want to remove the folder? All timer records in this folder will be removed 179 | 180 | 181 | Do you want to remove the timer record? 182 | 183 | 184 | Default 185 | 186 | 187 | Please complete the fields 188 | 189 | 190 | You can create different folders to categorize the timing in different scenarios. Just add an icon and give it an easily recognizable name 191 | 192 | 193 | Timer Folder 194 | 195 | 196 | Added timing to history 197 | 198 | 199 | Transfer History 200 | 201 | 202 | At least one timer folder is required 203 | 204 | 205 | Restart 206 | 207 | 208 | App Settings 209 | 210 | 211 | You changed the static resource settings, please restart the application to take effect 212 | 213 | 214 | Update Information 215 | 216 | 217 | Waiting 218 | 219 | 220 | Warning 221 | 222 | -------------------------------------------------------------------------------- /Work-Timer/Template/Button.xaml: -------------------------------------------------------------------------------- 1 | 6 | 17 | 29 | 42 | 45 | 55 | 65 | 78 | 79 | 141 | 215 | 216 | -------------------------------------------------------------------------------- /Work-Timer/Work-Timer.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | x86 7 | {B91BF1A1-0D7A-40B8-AA3E-C1F7D7F2DE88} 8 | AppContainerExe 9 | Properties 10 | WorkTimer 11 | Work-Timer 12 | en-US 13 | UAP 14 | 10.0.19041.0 15 | 10.0.17763.0 16 | 14 17 | 512 18 | {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 19 | true 20 | false 21 | False 22 | False 23 | D:\Package\Work-Timer\ 24 | False 25 | Always 26 | x86|x64|arm|arm64 27 | 0 28 | 29 | 30 | true 31 | bin\x86\Debug\ 32 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP 33 | ;2008 34 | full 35 | x86 36 | false 37 | prompt 38 | true 39 | 40 | 41 | bin\x86\Release\ 42 | TRACE;NETFX_CORE;WINDOWS_UWP 43 | true 44 | ;2008 45 | pdbonly 46 | x86 47 | false 48 | prompt 49 | true 50 | true 51 | 52 | 53 | true 54 | bin\ARM\Debug\ 55 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP 56 | ;2008 57 | full 58 | ARM 59 | false 60 | prompt 61 | true 62 | 63 | 64 | bin\ARM\Release\ 65 | TRACE;NETFX_CORE;WINDOWS_UWP 66 | true 67 | ;2008 68 | pdbonly 69 | ARM 70 | false 71 | prompt 72 | true 73 | true 74 | 75 | 76 | true 77 | bin\ARM64\Debug\ 78 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP 79 | ;2008 80 | full 81 | ARM64 82 | false 83 | prompt 84 | true 85 | true 86 | 87 | 88 | bin\ARM64\Release\ 89 | TRACE;NETFX_CORE;WINDOWS_UWP 90 | true 91 | ;2008 92 | pdbonly 93 | ARM64 94 | false 95 | prompt 96 | true 97 | true 98 | 99 | 100 | true 101 | bin\x64\Debug\ 102 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP 103 | ;2008 104 | full 105 | x64 106 | false 107 | prompt 108 | true 109 | 110 | 111 | bin\x64\Release\ 112 | TRACE;NETFX_CORE;WINDOWS_UWP 113 | true 114 | ;2008 115 | pdbonly 116 | x64 117 | false 118 | prompt 119 | true 120 | true 121 | 122 | 123 | PackageReference 124 | 125 | 126 | 127 | App.xaml 128 | 129 | 130 | ConfirmDialog.xaml 131 | 132 | 133 | FolderDialog.xaml 134 | 135 | 136 | FolderSelectionDialog.xaml 137 | 138 | 139 | FolderPanel.xaml 140 | 141 | 142 | HistoryPanel.xaml 143 | 144 | 145 | SettingPanel.xaml 146 | 147 | 148 | WorkDurationBlock.xaml 149 | 150 | 151 | MainPage.xaml 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | Designer 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | MSBuild:Compile 236 | Designer 237 | 238 | 239 | Designer 240 | MSBuild:Compile 241 | 242 | 243 | Designer 244 | MSBuild:Compile 245 | 246 | 247 | Designer 248 | MSBuild:Compile 249 | 250 | 251 | Designer 252 | MSBuild:Compile 253 | 254 | 255 | Designer 256 | MSBuild:Compile 257 | 258 | 259 | Designer 260 | MSBuild:Compile 261 | 262 | 263 | Designer 264 | MSBuild:Compile 265 | 266 | 267 | MSBuild:Compile 268 | Designer 269 | 270 | 271 | Designer 272 | MSBuild:Compile 273 | 274 | 275 | Designer 276 | MSBuild:Compile 277 | 278 | 279 | Designer 280 | MSBuild:Compile 281 | 282 | 283 | Designer 284 | MSBuild:Compile 285 | 286 | 287 | Designer 288 | MSBuild:Compile 289 | 290 | 291 | Designer 292 | MSBuild:Compile 293 | 294 | 295 | Designer 296 | MSBuild:Compile 297 | 298 | 299 | 300 | 301 | 6.2.10 302 | 303 | 304 | 6.1.0 305 | 306 | 307 | 12.0.3 308 | 309 | 310 | 1.0.9 311 | 312 | 313 | 1.0.7 314 | 315 | 316 | 1.0.5 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | {55CE1B3E-4D23-4566-881B-C4F463671785} 328 | Lib_Share 329 | 330 | 331 | 332 | 14.0 333 | 334 | 335 | 342 | --------------------------------------------------------------------------------