├── .editorconfig ├── .gitattributes ├── .gitignore ├── .vsconfig ├── App2.Core ├── App2.Core.csproj ├── Contracts │ └── Services │ │ └── IFileService.cs ├── Helpers │ └── Json.cs ├── README.md └── Services │ └── FileService.cs ├── App2.sln ├── App2 ├── Activation │ ├── ActivationHandler.cs │ ├── AppNotificationActivationHandler.cs │ ├── DefaultActivationHandler.cs │ └── IActivationHandler.cs ├── App.xaml ├── App.xaml.cs ├── App2 - Backup.csproj ├── App2.csproj ├── Assets │ ├── LockScreenLogo.scale-200.png │ ├── SplashScreen.scale-200.png │ ├── Square150x150Logo.scale-200.png │ ├── Square44x44Logo.scale-200.png │ ├── Square44x44Logo.targetsize-24_altform-unplated.png │ ├── StoreLogo.png │ ├── Wide310x150Logo.scale-200.png │ └── WindowIcon.ico ├── Behaviors │ ├── NavigationViewHeaderBehavior.cs │ └── NavigationViewHeaderMode.cs ├── Contracts │ ├── Services │ │ ├── IActivationService.cs │ │ ├── IAppNotificationService.cs │ │ ├── ILocalSettingsService.cs │ │ ├── INavigationService.cs │ │ ├── INavigationViewService.cs │ │ ├── IPageService.cs │ │ └── IThemeSelectorService.cs │ └── ViewModels │ │ └── INavigationAware.cs ├── Helpers │ ├── EnumToBooleanConverter.cs │ ├── FrameExtensions.cs │ ├── NavigationHelper.cs │ ├── ResourceExtensions.cs │ ├── RuntimeHelper.cs │ ├── SettingsStorageExtensions.cs │ └── TitleBarHelper.cs ├── MainWindow.xaml ├── MainWindow.xaml.cs ├── Models │ └── LocalSettingsOptions.cs ├── Package.appinstaller ├── Package.appxmanifest ├── Properties │ └── launchsettings.json ├── README.md ├── Services │ ├── ActivationService.cs │ ├── AppNotificationService.cs │ ├── LocalSettingsService.cs │ ├── NavigationService.cs │ ├── NavigationViewService.cs │ ├── PageService.cs │ └── ThemeSelectorService.cs ├── Strings │ ├── en-us │ │ └── Resources.resw │ └── pl-pl │ │ └── Resources.resw ├── Styles │ ├── FontSizes.xaml │ ├── TextBlock.xaml │ └── Thickness.xaml ├── TemplateStudio.xml ├── Usings.cs ├── ViewModels │ ├── MainViewModel.cs │ ├── SettingsViewModel.cs │ └── ShellViewModel.cs ├── Views │ ├── MainPage.xaml │ ├── MainPage.xaml.cs │ ├── SettingsPage.xaml │ ├── SettingsPage.xaml.cs │ ├── ShellPage.xaml │ └── ShellPage.xaml.cs ├── app.manifest └── appsettings.json ├── LICENSE ├── LICENSE.txt └── README.md /.editorconfig: -------------------------------------------------------------------------------- 1 | # Rules in this file were initially inferred by Visual Studio IntelliCode from the Template Studio codebase. 2 | # You can modify the rules from these initially generated values to suit your own policies. 3 | # You can learn more about editorconfig here: https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-code-style-settings-reference. 4 | 5 | [*.cs] 6 | 7 | #Core editorconfig formatting - indentation 8 | 9 | #use soft tabs (spaces) for indentation 10 | indent_style = space 11 | 12 | #Formatting - new line options 13 | 14 | #place else statements on a new line 15 | csharp_new_line_before_else = true 16 | #require braces to be on a new line for lambdas, methods, control_blocks, types, properties, and accessors (also known as "Allman" style) 17 | csharp_new_line_before_open_brace = all 18 | 19 | #Formatting - organize using options 20 | 21 | #sort System.* using directives alphabetically, and place them before other usings 22 | dotnet_sort_system_directives_first = true 23 | 24 | #Formatting - spacing options 25 | 26 | #require NO space between a cast and the value 27 | csharp_space_after_cast = false 28 | #require a space before the colon for bases or interfaces in a type declaration 29 | csharp_space_after_colon_in_inheritance_clause = true 30 | #require a space after a keyword in a control flow statement such as a for loop 31 | csharp_space_after_keywords_in_control_flow_statements = true 32 | #require a space before the colon for bases or interfaces in a type declaration 33 | csharp_space_before_colon_in_inheritance_clause = true 34 | #remove space within empty argument list parentheses 35 | csharp_space_between_method_call_empty_parameter_list_parentheses = false 36 | #remove space between method call name and opening parenthesis 37 | csharp_space_between_method_call_name_and_opening_parenthesis = false 38 | #do not place space characters after the opening parenthesis and before the closing parenthesis of a method call 39 | csharp_space_between_method_call_parameter_list_parentheses = false 40 | #remove space within empty parameter list parentheses for a method declaration 41 | csharp_space_between_method_declaration_empty_parameter_list_parentheses = false 42 | #place a space character after the opening parenthesis and before the closing parenthesis of a method declaration parameter list. 43 | csharp_space_between_method_declaration_parameter_list_parentheses = false 44 | 45 | #Formatting - wrapping options 46 | 47 | #leave code block on separate lines 48 | csharp_preserve_single_line_blocks = false 49 | 50 | #Style - Code block preferences 51 | 52 | #prefer curly braces even for one line of code 53 | csharp_prefer_braces = true:suggestion 54 | 55 | #Style - expression bodied member options 56 | 57 | #prefer expression bodies for accessors 58 | csharp_style_expression_bodied_accessors = true:warning 59 | #prefer block bodies for constructors 60 | csharp_style_expression_bodied_constructors = false:suggestion 61 | #prefer expression bodies for methods 62 | csharp_style_expression_bodied_methods = when_on_single_line:silent 63 | #prefer expression-bodied members for properties 64 | csharp_style_expression_bodied_properties = true:warning 65 | 66 | #Style - expression level options 67 | 68 | #prefer out variables to be declared before the method call 69 | csharp_style_inlined_variable_declaration = false:suggestion 70 | #prefer the language keyword for member access expressions, instead of the type name, for types that have a keyword to represent them 71 | dotnet_style_predefined_type_for_member_access = true:suggestion 72 | 73 | #Style - Expression-level preferences 74 | 75 | #prefer default over default(T) 76 | csharp_prefer_simple_default_expression = true:suggestion 77 | #prefer objects to be initialized using object initializers when possible 78 | dotnet_style_object_initializer = true:suggestion 79 | 80 | #Style - implicit and explicit types 81 | 82 | #prefer var over explicit type in all cases, unless overridden by another code style rule 83 | csharp_style_var_elsewhere = true:suggestion 84 | #prefer var is used to declare variables with built-in system types such as int 85 | csharp_style_var_for_built_in_types = true:suggestion 86 | #prefer var when the type is already mentioned on the right-hand side of a declaration expression 87 | csharp_style_var_when_type_is_apparent = true:suggestion 88 | 89 | #Style - language keyword and framework type options 90 | 91 | #prefer the language keyword for local variables, method parameters, and class members, instead of the type name, for types that have a keyword to represent them 92 | dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion 93 | 94 | #Style - Language rules 95 | csharp_style_implicit_object_creation_when_type_is_apparent = true:warning 96 | csharp_style_var_for_built_in_types = true:warning 97 | 98 | #Style - modifier options 99 | 100 | #prefer accessibility modifiers to be declared except for public interface members. This will currently not differ from always and will act as future proofing for if C# adds default interface methods. 101 | dotnet_style_require_accessibility_modifiers = for_non_interface_members:suggestion 102 | 103 | #Style - Modifier preferences 104 | 105 | #when this rule is set to a list of modifiers, prefer the specified ordering. 106 | csharp_preferred_modifier_order = public,private,protected,internal,static,async,readonly,override,sealed,abstract,virtual:warning 107 | dotnet_style_readonly_field = true:warning 108 | 109 | #Style - Pattern matching 110 | 111 | #prefer pattern matching instead of is expression with type casts 112 | csharp_style_pattern_matching_over_as_with_null_check = true:warning 113 | 114 | #Style - qualification options 115 | 116 | #prefer events not to be prefaced with this. or Me. in Visual Basic 117 | dotnet_style_qualification_for_event = false:suggestion 118 | #prefer fields not to be prefaced with this. or Me. in Visual Basic 119 | dotnet_style_qualification_for_field = false:suggestion 120 | #prefer methods not to be prefaced with this. or Me. in Visual Basic 121 | dotnet_style_qualification_for_method = false:suggestion 122 | #prefer properties not to be prefaced with this. or Me. in Visual Basic 123 | dotnet_style_qualification_for_property = false:suggestion 124 | csharp_indent_labels = one_less_than_current 125 | csharp_using_directive_placement = outside_namespace:silent 126 | csharp_prefer_simple_using_statement = true:warning 127 | csharp_style_namespace_declarations = file_scoped:warning 128 | csharp_style_expression_bodied_operators = false:silent 129 | csharp_style_expression_bodied_indexers = true:silent 130 | csharp_style_expression_bodied_lambdas = true:silent 131 | csharp_style_expression_bodied_local_functions = false:silent 132 | 133 | [*.{cs,vb}] 134 | dotnet_style_operator_placement_when_wrapping = beginning_of_line 135 | tab_width = 4 136 | indent_size = 4 137 | end_of_line = crlf 138 | dotnet_style_coalesce_expression = true:suggestion 139 | dotnet_style_null_propagation = true:suggestion 140 | dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion 141 | dotnet_style_prefer_auto_properties = true:silent 142 | dotnet_style_object_initializer = true:suggestion 143 | dotnet_style_collection_initializer = true:suggestion 144 | dotnet_style_prefer_simplified_boolean_expressions = true:suggestion 145 | dotnet_style_prefer_conditional_expression_over_assignment = true:silent 146 | dotnet_style_prefer_conditional_expression_over_return = true:silent 147 | [*.{cs,vb}] 148 | 149 | #Style - Unnecessary code rules 150 | csharp_style_unused_value_assignment_preference = discard_variable:warning 151 | 152 | #### Naming styles #### 153 | 154 | # Naming rules 155 | 156 | dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion 157 | dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface 158 | dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i 159 | 160 | dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion 161 | dotnet_naming_rule.types_should_be_pascal_case.symbols = types 162 | dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case 163 | 164 | dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion 165 | dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members 166 | dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case 167 | 168 | # Symbol specifications 169 | 170 | dotnet_naming_symbols.interface.applicable_kinds = interface 171 | dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected 172 | dotnet_naming_symbols.interface.required_modifiers = 173 | 174 | dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum 175 | dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected 176 | dotnet_naming_symbols.types.required_modifiers = 177 | 178 | dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method 179 | dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected 180 | dotnet_naming_symbols.non_field_members.required_modifiers = 181 | 182 | # Naming styles 183 | 184 | dotnet_naming_style.begins_with_i.required_prefix = I 185 | dotnet_naming_style.begins_with_i.required_suffix = 186 | dotnet_naming_style.begins_with_i.word_separator = 187 | dotnet_naming_style.begins_with_i.capitalization = pascal_case 188 | 189 | dotnet_naming_style.pascal_case.required_prefix = 190 | dotnet_naming_style.pascal_case.required_suffix = 191 | dotnet_naming_style.pascal_case.word_separator = 192 | dotnet_naming_style.pascal_case.capitalization = pascal_case 193 | 194 | dotnet_naming_style.pascal_case.required_prefix = 195 | dotnet_naming_style.pascal_case.required_suffix = 196 | dotnet_naming_style.pascal_case.word_separator = 197 | dotnet_naming_style.pascal_case.capitalization = pascal_case 198 | dotnet_style_explicit_tuple_names = true:suggestion 199 | dotnet_style_prefer_inferred_tuple_names = true:suggestion 200 | dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion 201 | dotnet_style_prefer_compound_assignment = true:warning 202 | dotnet_style_prefer_simplified_interpolation = true:suggestion 203 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /.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 | # Mono auto generated files 17 | mono_crash.* 18 | 19 | # Build results 20 | [Dd]ebug/ 21 | [Dd]ebugPublic/ 22 | [Rr]elease/ 23 | [Rr]eleases/ 24 | x64/ 25 | x86/ 26 | [Ww][Ii][Nn]32/ 27 | [Aa][Rr][Mm]/ 28 | [Aa][Rr][Mm]64/ 29 | bld/ 30 | [Bb]in/ 31 | [Oo]bj/ 32 | [Oo]ut/ 33 | [Ll]og/ 34 | [Ll]ogs/ 35 | 36 | # Visual Studio 2015/2017 cache/options directory 37 | .vs/ 38 | # Uncomment if you have tasks that create the project's static files in wwwroot 39 | #wwwroot/ 40 | 41 | # Visual Studio 2017 auto generated files 42 | Generated\ Files/ 43 | 44 | # MSTest test Results 45 | [Tt]est[Rr]esult*/ 46 | [Bb]uild[Ll]og.* 47 | 48 | # NUnit 49 | *.VisualState.xml 50 | TestResult.xml 51 | nunit-*.xml 52 | 53 | # Build Results of an ATL Project 54 | [Dd]ebugPS/ 55 | [Rr]eleasePS/ 56 | dlldata.c 57 | 58 | # Benchmark Results 59 | BenchmarkDotNet.Artifacts/ 60 | 61 | # .NET Core 62 | project.lock.json 63 | project.fragment.lock.json 64 | artifacts/ 65 | 66 | # ASP.NET Scaffolding 67 | ScaffoldingReadMe.txt 68 | 69 | # StyleCop 70 | StyleCopReport.xml 71 | 72 | # Files built by Visual Studio 73 | *_i.c 74 | *_p.c 75 | *_h.h 76 | *.ilk 77 | *.meta 78 | *.obj 79 | *.iobj 80 | *.pch 81 | *.pdb 82 | *.ipdb 83 | *.pgc 84 | *.pgd 85 | *.rsp 86 | *.sbr 87 | *.tlb 88 | *.tli 89 | *.tlh 90 | *.tmp 91 | *.tmp_proj 92 | *_wpftmp.csproj 93 | *.log 94 | *.vspscc 95 | *.vssscc 96 | .builds 97 | *.pidb 98 | *.svclog 99 | *.scc 100 | 101 | # Chutzpah Test files 102 | _Chutzpah* 103 | 104 | # Visual C++ cache files 105 | ipch/ 106 | *.aps 107 | *.ncb 108 | *.opendb 109 | *.opensdf 110 | *.sdf 111 | *.cachefile 112 | *.VC.db 113 | *.VC.VC.opendb 114 | 115 | # Visual Studio profiler 116 | *.psess 117 | *.vsp 118 | *.vspx 119 | *.sap 120 | 121 | # Visual Studio Trace Files 122 | *.e2e 123 | 124 | # TFS 2012 Local Workspace 125 | $tf/ 126 | 127 | # Guidance Automation Toolkit 128 | *.gpState 129 | 130 | # ReSharper is a .NET coding add-in 131 | _ReSharper*/ 132 | *.[Rr]e[Ss]harper 133 | *.DotSettings.user 134 | 135 | # TeamCity is a build add-in 136 | _TeamCity* 137 | 138 | # DotCover is a Code Coverage Tool 139 | *.dotCover 140 | 141 | # AxoCover is a Code Coverage Tool 142 | .axoCover/* 143 | !.axoCover/settings.json 144 | 145 | # Coverlet is a free, cross platform Code Coverage Tool 146 | coverage*.json 147 | coverage*.xml 148 | coverage*.info 149 | 150 | # Visual Studio code coverage results 151 | *.coverage 152 | *.coveragexml 153 | 154 | # NCrunch 155 | _NCrunch_* 156 | .*crunch*.local.xml 157 | nCrunchTemp_* 158 | 159 | # MightyMoose 160 | *.mm.* 161 | AutoTest.Net/ 162 | 163 | # Web workbench (sass) 164 | .sass-cache/ 165 | 166 | # Installshield output folder 167 | [Ee]xpress/ 168 | 169 | # DocProject is a documentation generator add-in 170 | DocProject/buildhelp/ 171 | DocProject/Help/*.HxT 172 | DocProject/Help/*.HxC 173 | DocProject/Help/*.hhc 174 | DocProject/Help/*.hhk 175 | DocProject/Help/*.hhp 176 | DocProject/Help/Html2 177 | DocProject/Help/html 178 | 179 | # Click-Once directory 180 | publish/ 181 | 182 | # Publish Web Output 183 | *.[Pp]ublish.xml 184 | *.azurePubxml 185 | # Note: Comment the next line if you want to checkin your web deploy settings, 186 | # but database connection strings (with potential passwords) will be unencrypted 187 | *.pubxml 188 | *.publishproj 189 | 190 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 191 | # checkin your Azure Web App publish settings, but sensitive information contained 192 | # in these scripts will be unencrypted 193 | PublishScripts/ 194 | 195 | # NuGet Packages 196 | *.nupkg 197 | # NuGet Symbol Packages 198 | *.snupkg 199 | # The packages folder can be ignored because of Package Restore 200 | **/[Pp]ackages/* 201 | # except build/, which is used as an MSBuild target. 202 | !**/[Pp]ackages/build/ 203 | # Uncomment if necessary however generally it will be regenerated when needed 204 | #!**/[Pp]ackages/repositories.config 205 | # NuGet v3's project.json files produces more ignorable files 206 | *.nuget.props 207 | *.nuget.targets 208 | 209 | # Microsoft Azure Build Output 210 | csx/ 211 | *.build.csdef 212 | 213 | # Microsoft Azure Emulator 214 | ecf/ 215 | rcf/ 216 | 217 | # Windows Store app package directories and files 218 | AppPackages/ 219 | BundleArtifacts/ 220 | Package.StoreAssociation.xml 221 | _pkginfo.txt 222 | *.appx 223 | *.appxbundle 224 | *.appxupload 225 | 226 | # Visual Studio cache files 227 | # files ending in .cache can be ignored 228 | *.[Cc]ache 229 | # but keep track of directories ending in .cache 230 | !?*.[Cc]ache/ 231 | 232 | # Others 233 | ClientBin/ 234 | ~$* 235 | *~ 236 | *.dbmdl 237 | *.dbproj.schemaview 238 | *.jfm 239 | *.pfx 240 | *.publishsettings 241 | orleans.codegen.cs 242 | 243 | # Including strong name files can present a security risk 244 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 245 | #*.snk 246 | 247 | # Since there are multiple workflows, uncomment next line to ignore bower_components 248 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 249 | #bower_components/ 250 | 251 | # RIA/Silverlight projects 252 | Generated_Code/ 253 | 254 | # Backup & report files from converting an old project file 255 | # to a newer Visual Studio version. Backup files are not needed, 256 | # because we have git ;-) 257 | _UpgradeReport_Files/ 258 | Backup*/ 259 | UpgradeLog*.XML 260 | UpgradeLog*.htm 261 | ServiceFabricBackup/ 262 | *.rptproj.bak 263 | 264 | # SQL Server files 265 | *.mdf 266 | *.ldf 267 | *.ndf 268 | 269 | # Business Intelligence projects 270 | *.rdl.data 271 | *.bim.layout 272 | *.bim_*.settings 273 | *.rptproj.rsuser 274 | *- [Bb]ackup.rdl 275 | *- [Bb]ackup ([0-9]).rdl 276 | *- [Bb]ackup ([0-9][0-9]).rdl 277 | 278 | # Microsoft Fakes 279 | FakesAssemblies/ 280 | 281 | # GhostDoc plugin setting file 282 | *.GhostDoc.xml 283 | 284 | # Node.js Tools for Visual Studio 285 | .ntvs_analysis.dat 286 | node_modules/ 287 | 288 | # Visual Studio 6 build log 289 | *.plg 290 | 291 | # Visual Studio 6 workspace options file 292 | *.opt 293 | 294 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 295 | *.vbw 296 | 297 | # Visual Studio LightSwitch build output 298 | **/*.HTMLClient/GeneratedArtifacts 299 | **/*.DesktopClient/GeneratedArtifacts 300 | **/*.DesktopClient/ModelManifest.xml 301 | **/*.Server/GeneratedArtifacts 302 | **/*.Server/ModelManifest.xml 303 | _Pvt_Extensions 304 | 305 | # Paket dependency manager 306 | .paket/paket.exe 307 | paket-files/ 308 | 309 | # FAKE - F# Make 310 | .fake/ 311 | 312 | # CodeRush personal settings 313 | .cr/personal 314 | 315 | # Python Tools for Visual Studio (PTVS) 316 | __pycache__/ 317 | *.pyc 318 | 319 | # Cake - Uncomment if you are using it 320 | # tools/** 321 | # !tools/packages.config 322 | 323 | # Tabs Studio 324 | *.tss 325 | 326 | # Telerik's JustMock configuration file 327 | *.jmconfig 328 | 329 | # BizTalk build output 330 | *.btp.cs 331 | *.btm.cs 332 | *.odx.cs 333 | *.xsd.cs 334 | 335 | # OpenCover UI analysis results 336 | OpenCover/ 337 | 338 | # Azure Stream Analytics local run output 339 | ASALocalRun/ 340 | 341 | # MSBuild Binary and Structured Log 342 | *.binlog 343 | 344 | # NVidia Nsight GPU debugger configuration file 345 | *.nvuser 346 | 347 | # MFractors (Xamarin productivity tool) working folder 348 | .mfractor/ 349 | 350 | # Local History for Visual Studio 351 | .localhistory/ 352 | 353 | # BeatPulse healthcheck temp database 354 | healthchecksdb 355 | 356 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 357 | MigrationBackup/ 358 | 359 | # Ionide (cross platform F# VS Code tools) working folder 360 | .ionide/ 361 | 362 | # Fody - auto-generated XML schema 363 | FodyWeavers.xsd -------------------------------------------------------------------------------- /.vsconfig: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0", 3 | "components": [ 4 | "Microsoft.Component.MSBuild", 5 | "Microsoft.NetCore.Component.Runtime.7.0", 6 | "Microsoft.NetCore.Component.SDK", 7 | "Microsoft.VisualStudio.Component.ManagedDesktop.Core", 8 | "Microsoft.VisualStudio.Component.ManagedDesktop.Prerequisites", 9 | "Microsoft.VisualStudio.Component.NuGet", 10 | "Microsoft.VisualStudio.Component.Windows10SDK.19041", 11 | "Microsoft.VisualStudio.Component.Windows10SDK", 12 | "Microsoft.VisualStudio.ComponentGroup.MSIX.Packaging", 13 | "Microsoft.VisualStudio.ComponentGroup.WindowsAppSDK.Cs", 14 | "Microsoft.VisualStudio.Workload.ManagedDesktop" 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /App2.Core/App2.Core.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | net7.0 4 | App2.Core 5 | AnyCPU;x64;x86 6 | x86;x64;arm64;AnyCPU 7 | enable 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /App2.Core/Contracts/Services/IFileService.cs: -------------------------------------------------------------------------------- 1 | namespace App2.Core.Contracts.Services; 2 | 3 | public interface IFileService 4 | { 5 | T Read(string folderPath, string fileName); 6 | 7 | void Save(string folderPath, string fileName, T content); 8 | 9 | void Delete(string folderPath, string fileName); 10 | } 11 | -------------------------------------------------------------------------------- /App2.Core/Helpers/Json.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | namespace App2.Core.Helpers; 4 | 5 | public static class Json 6 | { 7 | public static async Task ToObjectAsync(string value) 8 | { 9 | return await Task.Run(() => 10 | { 11 | return JsonConvert.DeserializeObject(value); 12 | }); 13 | } 14 | 15 | public static async Task StringifyAsync(object value) 16 | { 17 | return await Task.Run(() => 18 | { 19 | return JsonConvert.SerializeObject(value); 20 | }); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /App2.Core/README.md: -------------------------------------------------------------------------------- 1 | *Recommended Markdown Viewer: [Markdown Editor](https://marketplace.visualstudio.com/items?itemName=MadsKristensen.MarkdownEditor2)* 2 | 3 | ## Getting Started 4 | 5 | The Core project contains code that can be [reused across multiple application projects](https://docs.microsoft.com/dotnet/standard/net-standard#net-5-and-net-standard). 6 | -------------------------------------------------------------------------------- /App2.Core/Services/FileService.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | 3 | using App2.Core.Contracts.Services; 4 | 5 | using Newtonsoft.Json; 6 | 7 | namespace App2.Core.Services; 8 | 9 | public class FileService : IFileService 10 | { 11 | public T Read(string folderPath, string fileName) 12 | { 13 | var path = Path.Combine(folderPath, fileName); 14 | if (File.Exists(path)) 15 | { 16 | var json = File.ReadAllText(path); 17 | return JsonConvert.DeserializeObject(json); 18 | } 19 | 20 | return default; 21 | } 22 | 23 | public void Save(string folderPath, string fileName, T content) 24 | { 25 | if (!Directory.Exists(folderPath)) 26 | { 27 | Directory.CreateDirectory(folderPath); 28 | } 29 | 30 | var fileContent = JsonConvert.SerializeObject(content); 31 | File.WriteAllText(Path.Combine(folderPath, fileName), fileContent, Encoding.UTF8); 32 | } 33 | 34 | public void Delete(string folderPath, string fileName) 35 | { 36 | if (fileName != null && File.Exists(Path.Combine(folderPath, fileName))) 37 | { 38 | File.Delete(Path.Combine(folderPath, fileName)); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /App2.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.5.33424.131 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "App2", "App2\App2.csproj", "{046388C1-751B-464B-ACD3-25952F02A2E2}" 7 | EndProject 8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "App2.Core", "App2.Core\App2.Core.csproj", "{97A41FBD-898A-4818-B60C-0A8598D099BB}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Debug|arm64 = Debug|arm64 14 | Debug|x64 = Debug|x64 15 | Debug|x86 = Debug|x86 16 | Release|Any CPU = Release|Any CPU 17 | Release|arm64 = Release|arm64 18 | Release|x64 = Release|x64 19 | Release|x86 = Release|x86 20 | EndGlobalSection 21 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 22 | {046388C1-751B-464B-ACD3-25952F02A2E2}.Debug|Any CPU.ActiveCfg = Debug|x64 23 | {046388C1-751B-464B-ACD3-25952F02A2E2}.Debug|Any CPU.Build.0 = Debug|x64 24 | {046388C1-751B-464B-ACD3-25952F02A2E2}.Debug|Any CPU.Deploy.0 = Debug|x64 25 | {046388C1-751B-464B-ACD3-25952F02A2E2}.Debug|arm64.ActiveCfg = Debug|arm64 26 | {046388C1-751B-464B-ACD3-25952F02A2E2}.Debug|arm64.Build.0 = Debug|arm64 27 | {046388C1-751B-464B-ACD3-25952F02A2E2}.Debug|arm64.Deploy.0 = Debug|arm64 28 | {046388C1-751B-464B-ACD3-25952F02A2E2}.Debug|x64.ActiveCfg = Debug|x64 29 | {046388C1-751B-464B-ACD3-25952F02A2E2}.Debug|x64.Build.0 = Debug|x64 30 | {046388C1-751B-464B-ACD3-25952F02A2E2}.Debug|x64.Deploy.0 = Debug|x64 31 | {046388C1-751B-464B-ACD3-25952F02A2E2}.Debug|x86.ActiveCfg = Debug|x86 32 | {046388C1-751B-464B-ACD3-25952F02A2E2}.Debug|x86.Build.0 = Debug|x86 33 | {046388C1-751B-464B-ACD3-25952F02A2E2}.Debug|x86.Deploy.0 = Debug|x86 34 | {046388C1-751B-464B-ACD3-25952F02A2E2}.Release|Any CPU.ActiveCfg = Release|x64 35 | {046388C1-751B-464B-ACD3-25952F02A2E2}.Release|Any CPU.Build.0 = Release|x64 36 | {046388C1-751B-464B-ACD3-25952F02A2E2}.Release|Any CPU.Deploy.0 = Release|x64 37 | {046388C1-751B-464B-ACD3-25952F02A2E2}.Release|arm64.ActiveCfg = Release|arm64 38 | {046388C1-751B-464B-ACD3-25952F02A2E2}.Release|arm64.Build.0 = Release|arm64 39 | {046388C1-751B-464B-ACD3-25952F02A2E2}.Release|arm64.Deploy.0 = Release|arm64 40 | {046388C1-751B-464B-ACD3-25952F02A2E2}.Release|x64.ActiveCfg = Release|x64 41 | {046388C1-751B-464B-ACD3-25952F02A2E2}.Release|x64.Build.0 = Release|x64 42 | {046388C1-751B-464B-ACD3-25952F02A2E2}.Release|x64.Deploy.0 = Release|x64 43 | {046388C1-751B-464B-ACD3-25952F02A2E2}.Release|x86.ActiveCfg = Release|x86 44 | {046388C1-751B-464B-ACD3-25952F02A2E2}.Release|x86.Build.0 = Release|x86 45 | {046388C1-751B-464B-ACD3-25952F02A2E2}.Release|x86.Deploy.0 = Release|x86 46 | {97A41FBD-898A-4818-B60C-0A8598D099BB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 47 | {97A41FBD-898A-4818-B60C-0A8598D099BB}.Debug|Any CPU.Build.0 = Debug|Any CPU 48 | {97A41FBD-898A-4818-B60C-0A8598D099BB}.Debug|arm64.ActiveCfg = Debug|arm64 49 | {97A41FBD-898A-4818-B60C-0A8598D099BB}.Debug|arm64.Build.0 = Debug|arm64 50 | {97A41FBD-898A-4818-B60C-0A8598D099BB}.Debug|x64.ActiveCfg = Debug|x64 51 | {97A41FBD-898A-4818-B60C-0A8598D099BB}.Debug|x64.Build.0 = Debug|x64 52 | {97A41FBD-898A-4818-B60C-0A8598D099BB}.Debug|x86.ActiveCfg = Debug|x86 53 | {97A41FBD-898A-4818-B60C-0A8598D099BB}.Debug|x86.Build.0 = Debug|x86 54 | {97A41FBD-898A-4818-B60C-0A8598D099BB}.Release|Any CPU.ActiveCfg = Release|Any CPU 55 | {97A41FBD-898A-4818-B60C-0A8598D099BB}.Release|Any CPU.Build.0 = Release|Any CPU 56 | {97A41FBD-898A-4818-B60C-0A8598D099BB}.Release|arm64.ActiveCfg = Release|arm64 57 | {97A41FBD-898A-4818-B60C-0A8598D099BB}.Release|arm64.Build.0 = Release|arm64 58 | {97A41FBD-898A-4818-B60C-0A8598D099BB}.Release|x64.ActiveCfg = Release|x64 59 | {97A41FBD-898A-4818-B60C-0A8598D099BB}.Release|x64.Build.0 = Release|x64 60 | {97A41FBD-898A-4818-B60C-0A8598D099BB}.Release|x86.ActiveCfg = Release|x86 61 | {97A41FBD-898A-4818-B60C-0A8598D099BB}.Release|x86.Build.0 = Release|x86 62 | EndGlobalSection 63 | GlobalSection(SolutionProperties) = preSolution 64 | HideSolutionNode = FALSE 65 | EndGlobalSection 66 | GlobalSection(ExtensibilityGlobals) = postSolution 67 | SolutionGuid = {320F7C2B-D8DB-4A16-9E40-6863E6627EAC} 68 | EndGlobalSection 69 | EndGlobal 70 | -------------------------------------------------------------------------------- /App2/Activation/ActivationHandler.cs: -------------------------------------------------------------------------------- 1 | namespace App2.Activation; 2 | 3 | // Extend this class to implement new ActivationHandlers. See DefaultActivationHandler for an example. 4 | // https://github.com/microsoft/TemplateStudio/blob/main/docs/WinUI/activation.md 5 | public abstract class ActivationHandler : IActivationHandler 6 | where T : class 7 | { 8 | // Override this method to add the logic for whether to handle the activation. 9 | protected virtual bool CanHandleInternal(T args) => true; 10 | 11 | // Override this method to add the logic for your activation handler. 12 | protected abstract Task HandleInternalAsync(T args); 13 | 14 | public bool CanHandle(object args) => args is T && CanHandleInternal((args as T)!); 15 | 16 | public async Task HandleAsync(object args) => await HandleInternalAsync((args as T)!); 17 | } 18 | -------------------------------------------------------------------------------- /App2/Activation/AppNotificationActivationHandler.cs: -------------------------------------------------------------------------------- 1 | using App2.Contracts.Services; 2 | using App2.ViewModels; 3 | 4 | using Microsoft.UI.Dispatching; 5 | using Microsoft.UI.Xaml; 6 | using Microsoft.Windows.AppLifecycle; 7 | using Microsoft.Windows.AppNotifications; 8 | 9 | namespace App2.Activation; 10 | 11 | public class AppNotificationActivationHandler : ActivationHandler 12 | { 13 | private readonly INavigationService _navigationService; 14 | private readonly IAppNotificationService _notificationService; 15 | 16 | public AppNotificationActivationHandler(INavigationService navigationService, IAppNotificationService notificationService) 17 | { 18 | _navigationService = navigationService; 19 | _notificationService = notificationService; 20 | } 21 | 22 | protected override bool CanHandleInternal(LaunchActivatedEventArgs args) 23 | { 24 | return AppInstance.GetCurrent().GetActivatedEventArgs()?.Kind == ExtendedActivationKind.AppNotification; 25 | } 26 | 27 | protected async override Task HandleInternalAsync(LaunchActivatedEventArgs args) 28 | { 29 | // TODO: Handle notification activations. 30 | 31 | //// // Access the AppNotificationActivatedEventArgs. 32 | //// var activatedEventArgs = (AppNotificationActivatedEventArgs)AppInstance.GetCurrent().GetActivatedEventArgs().Data; 33 | 34 | //// // Navigate to a specific page based on the notification arguments. 35 | //// if (_notificationService.ParseArguments(activatedEventArgs.Argument)["action"] == "Settings") 36 | //// { 37 | //// // Queue navigation with low priority to allow the UI to initialize. 38 | //// App.MainWindow.DispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, () => 39 | //// { 40 | //// _navigationService.NavigateTo(typeof(SettingsViewModel).FullName!); 41 | //// }); 42 | //// } 43 | 44 | App.MainWindow.DispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, () => 45 | { 46 | App.MainWindow.ShowMessageDialogAsync("TODO: Handle notification activations.", "Notification Activation"); 47 | }); 48 | 49 | await Task.CompletedTask; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /App2/Activation/DefaultActivationHandler.cs: -------------------------------------------------------------------------------- 1 | using App2.Contracts.Services; 2 | using App2.ViewModels; 3 | 4 | using Microsoft.UI.Xaml; 5 | 6 | namespace App2.Activation; 7 | 8 | public class DefaultActivationHandler : ActivationHandler 9 | { 10 | private readonly INavigationService _navigationService; 11 | 12 | public DefaultActivationHandler(INavigationService navigationService) 13 | { 14 | _navigationService = navigationService; 15 | } 16 | 17 | protected override bool CanHandleInternal(LaunchActivatedEventArgs args) 18 | { 19 | // None of the ActivationHandlers has handled the activation. 20 | return _navigationService.Frame?.Content == null; 21 | } 22 | 23 | protected async override Task HandleInternalAsync(LaunchActivatedEventArgs args) 24 | { 25 | _navigationService.NavigateTo(typeof(MainViewModel).FullName!, args.Arguments); 26 | 27 | await Task.CompletedTask; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /App2/Activation/IActivationHandler.cs: -------------------------------------------------------------------------------- 1 | namespace App2.Activation; 2 | 3 | public interface IActivationHandler 4 | { 5 | bool CanHandle(object args); 6 | 7 | Task HandleAsync(object args); 8 | } 9 | -------------------------------------------------------------------------------- /App2/App.xaml: -------------------------------------------------------------------------------- 1 |  5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /App2/App.xaml.cs: -------------------------------------------------------------------------------- 1 | using App2.Activation; 2 | using App2.Contracts.Services; 3 | using App2.Core.Contracts.Services; 4 | using App2.Core.Services; 5 | using App2.Helpers; 6 | using App2.Models; 7 | using App2.Notifications; 8 | using App2.Services; 9 | using App2.ViewModels; 10 | using App2.Views; 11 | 12 | using Microsoft.Extensions.DependencyInjection; 13 | using Microsoft.Extensions.Hosting; 14 | using Microsoft.UI.Xaml; 15 | 16 | namespace App2; 17 | 18 | // To learn more about WinUI 3, see https://docs.microsoft.com/windows/apps/winui/winui3/. 19 | public partial class App : Application 20 | { 21 | // The .NET Generic Host provides dependency injection, configuration, logging, and other services. 22 | // https://docs.microsoft.com/dotnet/core/extensions/generic-host 23 | // https://docs.microsoft.com/dotnet/core/extensions/dependency-injection 24 | // https://docs.microsoft.com/dotnet/core/extensions/configuration 25 | // https://docs.microsoft.com/dotnet/core/extensions/logging 26 | public IHost Host 27 | { 28 | get; 29 | } 30 | 31 | public static T GetService() 32 | where T : class 33 | { 34 | if ((App.Current as App)!.Host.Services.GetService(typeof(T)) is not T service) 35 | { 36 | throw new ArgumentException($"{typeof(T)} needs to be registered in ConfigureServices within App.xaml.cs."); 37 | } 38 | 39 | return service; 40 | } 41 | 42 | public static WindowEx MainWindow { get; } = new MainWindow(); 43 | 44 | public static UIElement? AppTitlebar { get; set; } 45 | 46 | public App() 47 | { 48 | InitializeComponent(); 49 | 50 | Host = Microsoft.Extensions.Hosting.Host. 51 | CreateDefaultBuilder(). 52 | UseContentRoot(AppContext.BaseDirectory). 53 | ConfigureServices((context, services) => 54 | { 55 | // Default Activation Handler 56 | services.AddTransient, DefaultActivationHandler>(); 57 | 58 | // Other Activation Handlers 59 | services.AddTransient(); 60 | 61 | // Services 62 | services.AddSingleton(); 63 | services.AddSingleton(); 64 | services.AddSingleton(); 65 | services.AddTransient(); 66 | 67 | services.AddSingleton(); 68 | services.AddSingleton(); 69 | services.AddSingleton(); 70 | 71 | // Core Services 72 | services.AddSingleton(); 73 | 74 | // Views and ViewModels 75 | services.AddTransient(); 76 | services.AddTransient(); 77 | services.AddTransient(); 78 | services.AddTransient(); 79 | services.AddTransient(); 80 | services.AddTransient(); 81 | 82 | // Configuration 83 | services.Configure(context.Configuration.GetSection(nameof(LocalSettingsOptions))); 84 | }). 85 | Build(); 86 | 87 | App.GetService().Initialize(); 88 | 89 | UnhandledException += App_UnhandledException; 90 | } 91 | 92 | private void App_UnhandledException(object sender, Microsoft.UI.Xaml.UnhandledExceptionEventArgs e) 93 | { 94 | // TODO: Log and handle exceptions as appropriate. 95 | // https://docs.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.application.unhandledexception. 96 | } 97 | 98 | protected async override void OnLaunched(LaunchActivatedEventArgs args) 99 | { 100 | base.OnLaunched(args); 101 | 102 | App.GetService().Show(string.Format("AppNotificationSamplePayload".GetLocalized(), AppContext.BaseDirectory)); 103 | 104 | await App.GetService().ActivateAsync(args); 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /App2/App2 - Backup.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | WinExe 4 | net8.0-windows10.0.22621.0 5 | 10.0.17763.0 6 | App2 7 | Assets\WindowIcon.ico 8 | app.manifest 9 | x86;x64;arm64 10 | win-x86;win-x64;win-arm64 11 | Properties\PublishProfiles\win-$(Platform).pubxml 12 | enable 13 | enable 14 | true 15 | true 16 | true 17 | Axela 18 | 11.2401.2.0 19 | Axela 20 | False 21 | True 22 | A78C852FB829FC05329DF894AF8A7534805F315D 23 | SHA256 24 | False 25 | False 26 | True 27 | Never 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | Always 54 | 55 | 56 | MSBuild:Compile 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | true 66 | 67 | 68 | -------------------------------------------------------------------------------- /App2/App2.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | WinExe 4 | net8.0-windows10.0.22621.0 5 | 10.0.17763.0 6 | App2 7 | Assets\WindowIcon.ico 8 | app.manifest 9 | x86;x64;arm64 10 | win-x86;win-x64;win-arm64 11 | Properties\PublishProfiles\win-$(Platform).pubxml 12 | enable 13 | enable 14 | true 15 | true 16 | true 17 | Axela 18 | 11.2406.1.0 19 | Axela 20 | False 21 | True 22 | A78C852FB829FC05329DF894AF8A7534805F315D 23 | SHA256 24 | False 25 | False 26 | True 27 | Never 28 | 10.0.22621.35-preview 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | Always 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | true 66 | 67 | 68 | -------------------------------------------------------------------------------- /App2/Assets/LockScreenLogo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/errortek/Axela/4c3e60347fdb218f0fb217facc9ddf5b7c780603/App2/Assets/LockScreenLogo.scale-200.png -------------------------------------------------------------------------------- /App2/Assets/SplashScreen.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/errortek/Axela/4c3e60347fdb218f0fb217facc9ddf5b7c780603/App2/Assets/SplashScreen.scale-200.png -------------------------------------------------------------------------------- /App2/Assets/Square150x150Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/errortek/Axela/4c3e60347fdb218f0fb217facc9ddf5b7c780603/App2/Assets/Square150x150Logo.scale-200.png -------------------------------------------------------------------------------- /App2/Assets/Square44x44Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/errortek/Axela/4c3e60347fdb218f0fb217facc9ddf5b7c780603/App2/Assets/Square44x44Logo.scale-200.png -------------------------------------------------------------------------------- /App2/Assets/Square44x44Logo.targetsize-24_altform-unplated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/errortek/Axela/4c3e60347fdb218f0fb217facc9ddf5b7c780603/App2/Assets/Square44x44Logo.targetsize-24_altform-unplated.png -------------------------------------------------------------------------------- /App2/Assets/StoreLogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/errortek/Axela/4c3e60347fdb218f0fb217facc9ddf5b7c780603/App2/Assets/StoreLogo.png -------------------------------------------------------------------------------- /App2/Assets/Wide310x150Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/errortek/Axela/4c3e60347fdb218f0fb217facc9ddf5b7c780603/App2/Assets/Wide310x150Logo.scale-200.png -------------------------------------------------------------------------------- /App2/Assets/WindowIcon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/errortek/Axela/4c3e60347fdb218f0fb217facc9ddf5b7c780603/App2/Assets/WindowIcon.ico -------------------------------------------------------------------------------- /App2/Behaviors/NavigationViewHeaderBehavior.cs: -------------------------------------------------------------------------------- 1 | using App2.Contracts.Services; 2 | 3 | using Microsoft.UI.Xaml; 4 | using Microsoft.UI.Xaml.Controls; 5 | using Microsoft.UI.Xaml.Navigation; 6 | using Microsoft.Xaml.Interactivity; 7 | 8 | namespace App2.Behaviors; 9 | 10 | public class NavigationViewHeaderBehavior : Behavior 11 | { 12 | private static NavigationViewHeaderBehavior? _current; 13 | 14 | private Page? _currentPage; 15 | 16 | public DataTemplate? DefaultHeaderTemplate 17 | { 18 | get; set; 19 | } 20 | 21 | public object DefaultHeader 22 | { 23 | get => GetValue(DefaultHeaderProperty); 24 | set => SetValue(DefaultHeaderProperty, value); 25 | } 26 | 27 | public static readonly DependencyProperty DefaultHeaderProperty = 28 | DependencyProperty.Register("DefaultHeader", typeof(object), typeof(NavigationViewHeaderBehavior), new PropertyMetadata(null, (d, e) => _current!.UpdateHeader())); 29 | 30 | public static NavigationViewHeaderMode GetHeaderMode(Page item) => (NavigationViewHeaderMode)item.GetValue(HeaderModeProperty); 31 | 32 | public static void SetHeaderMode(Page item, NavigationViewHeaderMode value) => item.SetValue(HeaderModeProperty, value); 33 | 34 | public static readonly DependencyProperty HeaderModeProperty = 35 | DependencyProperty.RegisterAttached("HeaderMode", typeof(bool), typeof(NavigationViewHeaderBehavior), new PropertyMetadata(NavigationViewHeaderMode.Always, (d, e) => _current!.UpdateHeader())); 36 | 37 | public static object GetHeaderContext(Page item) => item.GetValue(HeaderContextProperty); 38 | 39 | public static void SetHeaderContext(Page item, object value) => item.SetValue(HeaderContextProperty, value); 40 | 41 | public static readonly DependencyProperty HeaderContextProperty = 42 | DependencyProperty.RegisterAttached("HeaderContext", typeof(object), typeof(NavigationViewHeaderBehavior), new PropertyMetadata(null, (d, e) => _current!.UpdateHeader())); 43 | 44 | public static DataTemplate GetHeaderTemplate(Page item) => (DataTemplate)item.GetValue(HeaderTemplateProperty); 45 | 46 | public static void SetHeaderTemplate(Page item, DataTemplate value) => item.SetValue(HeaderTemplateProperty, value); 47 | 48 | public static readonly DependencyProperty HeaderTemplateProperty = 49 | DependencyProperty.RegisterAttached("HeaderTemplate", typeof(DataTemplate), typeof(NavigationViewHeaderBehavior), new PropertyMetadata(null, (d, e) => _current!.UpdateHeaderTemplate())); 50 | 51 | protected override void OnAttached() 52 | { 53 | base.OnAttached(); 54 | 55 | var navigationService = App.GetService(); 56 | navigationService.Navigated += OnNavigated; 57 | 58 | _current = this; 59 | } 60 | 61 | protected override void OnDetaching() 62 | { 63 | base.OnDetaching(); 64 | 65 | var navigationService = App.GetService(); 66 | navigationService.Navigated -= OnNavigated; 67 | } 68 | 69 | private void OnNavigated(object sender, NavigationEventArgs e) 70 | { 71 | if (sender is Frame frame && frame.Content is Page page) 72 | { 73 | _currentPage = page; 74 | 75 | UpdateHeader(); 76 | UpdateHeaderTemplate(); 77 | } 78 | } 79 | 80 | private void UpdateHeader() 81 | { 82 | if (_currentPage != null) 83 | { 84 | var headerMode = GetHeaderMode(_currentPage); 85 | if (headerMode == NavigationViewHeaderMode.Never) 86 | { 87 | AssociatedObject.Header = null; 88 | AssociatedObject.AlwaysShowHeader = false; 89 | } 90 | else 91 | { 92 | var headerFromPage = GetHeaderContext(_currentPage); 93 | if (headerFromPage != null) 94 | { 95 | AssociatedObject.Header = headerFromPage; 96 | } 97 | else 98 | { 99 | AssociatedObject.Header = DefaultHeader; 100 | } 101 | 102 | if (headerMode == NavigationViewHeaderMode.Always) 103 | { 104 | AssociatedObject.AlwaysShowHeader = true; 105 | } 106 | else 107 | { 108 | AssociatedObject.AlwaysShowHeader = false; 109 | } 110 | } 111 | } 112 | } 113 | 114 | private void UpdateHeaderTemplate() 115 | { 116 | if (_currentPage != null) 117 | { 118 | var headerTemplate = GetHeaderTemplate(_currentPage); 119 | AssociatedObject.HeaderTemplate = headerTemplate ?? DefaultHeaderTemplate; 120 | } 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /App2/Behaviors/NavigationViewHeaderMode.cs: -------------------------------------------------------------------------------- 1 | namespace App2.Behaviors; 2 | 3 | public enum NavigationViewHeaderMode 4 | { 5 | Always, 6 | Never, 7 | Minimal 8 | } 9 | -------------------------------------------------------------------------------- /App2/Contracts/Services/IActivationService.cs: -------------------------------------------------------------------------------- 1 | namespace App2.Contracts.Services; 2 | 3 | public interface IActivationService 4 | { 5 | Task ActivateAsync(object activationArgs); 6 | } 7 | -------------------------------------------------------------------------------- /App2/Contracts/Services/IAppNotificationService.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Specialized; 2 | 3 | namespace App2.Contracts.Services; 4 | 5 | public interface IAppNotificationService 6 | { 7 | void Initialize(); 8 | 9 | bool Show(string payload); 10 | 11 | NameValueCollection ParseArguments(string arguments); 12 | 13 | void Unregister(); 14 | } 15 | -------------------------------------------------------------------------------- /App2/Contracts/Services/ILocalSettingsService.cs: -------------------------------------------------------------------------------- 1 | namespace App2.Contracts.Services; 2 | 3 | public interface ILocalSettingsService 4 | { 5 | Task ReadSettingAsync(string key); 6 | 7 | Task SaveSettingAsync(string key, T value); 8 | } 9 | -------------------------------------------------------------------------------- /App2/Contracts/Services/INavigationService.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.UI.Xaml.Controls; 2 | using Microsoft.UI.Xaml.Navigation; 3 | 4 | namespace App2.Contracts.Services; 5 | 6 | public interface INavigationService 7 | { 8 | event NavigatedEventHandler Navigated; 9 | 10 | bool CanGoBack 11 | { 12 | get; 13 | } 14 | 15 | Frame? Frame 16 | { 17 | get; set; 18 | } 19 | 20 | bool NavigateTo(string pageKey, object? parameter = null, bool clearNavigation = false); 21 | 22 | bool GoBack(); 23 | } 24 | -------------------------------------------------------------------------------- /App2/Contracts/Services/INavigationViewService.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.UI.Xaml.Controls; 2 | 3 | namespace App2.Contracts.Services; 4 | 5 | public interface INavigationViewService 6 | { 7 | IList? MenuItems 8 | { 9 | get; 10 | } 11 | 12 | object? SettingsItem 13 | { 14 | get; 15 | } 16 | 17 | void Initialize(NavigationView navigationView); 18 | 19 | void UnregisterEvents(); 20 | 21 | NavigationViewItem? GetSelectedItem(Type pageType); 22 | } 23 | -------------------------------------------------------------------------------- /App2/Contracts/Services/IPageService.cs: -------------------------------------------------------------------------------- 1 | namespace App2.Contracts.Services; 2 | 3 | public interface IPageService 4 | { 5 | Type GetPageType(string key); 6 | } 7 | -------------------------------------------------------------------------------- /App2/Contracts/Services/IThemeSelectorService.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.UI.Xaml; 2 | 3 | namespace App2.Contracts.Services; 4 | 5 | public interface IThemeSelectorService 6 | { 7 | ElementTheme Theme 8 | { 9 | get; 10 | } 11 | 12 | Task InitializeAsync(); 13 | 14 | Task SetThemeAsync(ElementTheme theme); 15 | 16 | Task SetRequestedThemeAsync(); 17 | } 18 | -------------------------------------------------------------------------------- /App2/Contracts/ViewModels/INavigationAware.cs: -------------------------------------------------------------------------------- 1 | namespace App2.Contracts.ViewModels; 2 | 3 | public interface INavigationAware 4 | { 5 | void OnNavigatedTo(object parameter); 6 | 7 | void OnNavigatedFrom(); 8 | } 9 | -------------------------------------------------------------------------------- /App2/Helpers/EnumToBooleanConverter.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.UI.Xaml; 2 | using Microsoft.UI.Xaml.Data; 3 | 4 | namespace App2.Helpers; 5 | 6 | public class EnumToBooleanConverter : IValueConverter 7 | { 8 | public EnumToBooleanConverter() 9 | { 10 | } 11 | 12 | public object Convert(object value, Type targetType, object parameter, string language) 13 | { 14 | if (parameter is string enumString) 15 | { 16 | if (!Enum.IsDefined(typeof(ElementTheme), value)) 17 | { 18 | throw new ArgumentException("ExceptionEnumToBooleanConverterValueMustBeAnEnum"); 19 | } 20 | 21 | var enumValue = Enum.Parse(typeof(ElementTheme), enumString); 22 | 23 | return enumValue.Equals(value); 24 | } 25 | 26 | throw new ArgumentException("ExceptionEnumToBooleanConverterParameterMustBeAnEnumName"); 27 | } 28 | 29 | public object ConvertBack(object value, Type targetType, object parameter, string language) 30 | { 31 | if (parameter is string enumString) 32 | { 33 | return Enum.Parse(typeof(ElementTheme), enumString); 34 | } 35 | 36 | throw new ArgumentException("ExceptionEnumToBooleanConverterParameterMustBeAnEnumName"); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /App2/Helpers/FrameExtensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.UI.Xaml.Controls; 2 | 3 | namespace App2.Helpers; 4 | 5 | public static class FrameExtensions 6 | { 7 | public static object? GetPageViewModel(this Frame frame) => frame?.Content?.GetType().GetProperty("ViewModel")?.GetValue(frame.Content, null); 8 | } 9 | -------------------------------------------------------------------------------- /App2/Helpers/NavigationHelper.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.UI.Xaml; 2 | using Microsoft.UI.Xaml.Controls; 3 | 4 | namespace App2.Helpers; 5 | 6 | // Helper class to set the navigation target for a NavigationViewItem. 7 | // 8 | // Usage in XAML: 9 | // 10 | // 11 | // Usage in code: 12 | // NavigationHelper.SetNavigateTo(navigationViewItem, typeof(MainViewModel).FullName); 13 | public class NavigationHelper 14 | { 15 | public static string GetNavigateTo(NavigationViewItem item) => (string)item.GetValue(NavigateToProperty); 16 | 17 | public static void SetNavigateTo(NavigationViewItem item, string value) => item.SetValue(NavigateToProperty, value); 18 | 19 | public static readonly DependencyProperty NavigateToProperty = 20 | DependencyProperty.RegisterAttached("NavigateTo", typeof(string), typeof(NavigationHelper), new PropertyMetadata(null)); 21 | } 22 | -------------------------------------------------------------------------------- /App2/Helpers/ResourceExtensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Windows.ApplicationModel.Resources; 2 | 3 | namespace App2.Helpers; 4 | 5 | public static class ResourceExtensions 6 | { 7 | private static readonly ResourceLoader _resourceLoader = new(); 8 | 9 | public static string GetLocalized(this string resourceKey) => _resourceLoader.GetString(resourceKey); 10 | } 11 | -------------------------------------------------------------------------------- /App2/Helpers/RuntimeHelper.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.InteropServices; 2 | using System.Text; 3 | 4 | namespace App2.Helpers; 5 | 6 | public class RuntimeHelper 7 | { 8 | [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)] 9 | private static extern int GetCurrentPackageFullName(ref int packageFullNameLength, StringBuilder? packageFullName); 10 | 11 | public static bool IsMSIX 12 | { 13 | get 14 | { 15 | var length = 0; 16 | 17 | return GetCurrentPackageFullName(ref length, null) != 15700L; 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /App2/Helpers/SettingsStorageExtensions.cs: -------------------------------------------------------------------------------- 1 | using App2.Core.Helpers; 2 | 3 | using Windows.Storage; 4 | using Windows.Storage.Streams; 5 | 6 | namespace App2.Helpers; 7 | 8 | // Use these extension methods to store and retrieve local and roaming app data 9 | // More details regarding storing and retrieving app data at https://docs.microsoft.com/windows/apps/design/app-settings/store-and-retrieve-app-data 10 | public static class SettingsStorageExtensions 11 | { 12 | private const string FileExtension = ".json"; 13 | 14 | public static bool IsRoamingStorageAvailable(this ApplicationData appData) 15 | { 16 | return appData.RoamingStorageQuota == 0; 17 | } 18 | 19 | public static async Task SaveAsync(this StorageFolder folder, string name, T content) 20 | { 21 | var file = await folder.CreateFileAsync(GetFileName(name), CreationCollisionOption.ReplaceExisting); 22 | var fileContent = await Json.StringifyAsync(content); 23 | 24 | await FileIO.WriteTextAsync(file, fileContent); 25 | } 26 | 27 | public static async Task ReadAsync(this StorageFolder folder, string name) 28 | { 29 | if (!File.Exists(Path.Combine(folder.Path, GetFileName(name)))) 30 | { 31 | return default; 32 | } 33 | 34 | var file = await folder.GetFileAsync($"{name}.json"); 35 | var fileContent = await FileIO.ReadTextAsync(file); 36 | 37 | return await Json.ToObjectAsync(fileContent); 38 | } 39 | 40 | public static async Task SaveAsync(this ApplicationDataContainer settings, string key, T value) 41 | { 42 | settings.SaveString(key, await Json.StringifyAsync(value)); 43 | } 44 | 45 | public static void SaveString(this ApplicationDataContainer settings, string key, string value) 46 | { 47 | settings.Values[key] = value; 48 | } 49 | 50 | public static async Task ReadAsync(this ApplicationDataContainer settings, string key) 51 | { 52 | object? obj; 53 | 54 | if (settings.Values.TryGetValue(key, out obj)) 55 | { 56 | return await Json.ToObjectAsync((string)obj); 57 | } 58 | 59 | return default; 60 | } 61 | 62 | public static async Task SaveFileAsync(this StorageFolder folder, byte[] content, string fileName, CreationCollisionOption options = CreationCollisionOption.ReplaceExisting) 63 | { 64 | if (content == null) 65 | { 66 | throw new ArgumentNullException(nameof(content)); 67 | } 68 | 69 | if (string.IsNullOrEmpty(fileName)) 70 | { 71 | throw new ArgumentException("File name is null or empty. Specify a valid file name", nameof(fileName)); 72 | } 73 | 74 | var storageFile = await folder.CreateFileAsync(fileName, options); 75 | await FileIO.WriteBytesAsync(storageFile, content); 76 | return storageFile; 77 | } 78 | 79 | public static async Task ReadFileAsync(this StorageFolder folder, string fileName) 80 | { 81 | var item = await folder.TryGetItemAsync(fileName).AsTask().ConfigureAwait(false); 82 | 83 | if ((item != null) && item.IsOfType(StorageItemTypes.File)) 84 | { 85 | var storageFile = await folder.GetFileAsync(fileName); 86 | var content = await storageFile.ReadBytesAsync(); 87 | return content; 88 | } 89 | 90 | return null; 91 | } 92 | 93 | public static async Task ReadBytesAsync(this StorageFile file) 94 | { 95 | if (file != null) 96 | { 97 | using IRandomAccessStream stream = await file.OpenReadAsync(); 98 | using var reader = new DataReader(stream.GetInputStreamAt(0)); 99 | await reader.LoadAsync((uint)stream.Size); 100 | var bytes = new byte[stream.Size]; 101 | reader.ReadBytes(bytes); 102 | return bytes; 103 | } 104 | 105 | return null; 106 | } 107 | 108 | private static string GetFileName(string name) 109 | { 110 | return string.Concat(name, FileExtension); 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /App2/Helpers/TitleBarHelper.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.InteropServices; 2 | 3 | using Microsoft.UI; 4 | using Microsoft.UI.Xaml; 5 | using Microsoft.UI.Xaml.Media; 6 | 7 | using Windows.UI; 8 | using Windows.UI.ViewManagement; 9 | 10 | namespace App2.Helpers; 11 | 12 | // Helper class to workaround custom title bar bugs. 13 | // DISCLAIMER: The resource key names and color values used below are subject to change. Do not depend on them. 14 | // https://github.com/microsoft/TemplateStudio/issues/4516 15 | internal class TitleBarHelper 16 | { 17 | private const int WAINACTIVE = 0x00; 18 | private const int WAACTIVE = 0x01; 19 | private const int WMACTIVATE = 0x0006; 20 | 21 | [DllImport("user32.dll")] 22 | private static extern IntPtr GetActiveWindow(); 23 | 24 | [DllImport("user32.dll", CharSet = CharSet.Auto)] 25 | private static extern IntPtr SendMessage(IntPtr hWnd, int msg, int wParam, IntPtr lParam); 26 | 27 | public static void UpdateTitleBar(ElementTheme theme) 28 | { 29 | if (App.MainWindow.ExtendsContentIntoTitleBar) 30 | { 31 | if (theme == ElementTheme.Default) 32 | { 33 | var uiSettings = new UISettings(); 34 | var background = uiSettings.GetColorValue(UIColorType.Background); 35 | 36 | theme = background == Colors.White ? ElementTheme.Light : ElementTheme.Dark; 37 | } 38 | 39 | if (theme == ElementTheme.Default) 40 | { 41 | theme = Application.Current.RequestedTheme == ApplicationTheme.Light ? ElementTheme.Light : ElementTheme.Dark; 42 | } 43 | 44 | Application.Current.Resources["WindowCaptionForeground"] = theme switch 45 | { 46 | ElementTheme.Dark => new SolidColorBrush(Colors.White), 47 | ElementTheme.Light => new SolidColorBrush(Colors.Black), 48 | _ => new SolidColorBrush(Colors.Transparent) 49 | }; 50 | 51 | Application.Current.Resources["WindowCaptionForegroundDisabled"] = theme switch 52 | { 53 | ElementTheme.Dark => new SolidColorBrush(Color.FromArgb(0x66, 0xFF, 0xFF, 0xFF)), 54 | ElementTheme.Light => new SolidColorBrush(Color.FromArgb(0x66, 0x00, 0x00, 0x00)), 55 | _ => new SolidColorBrush(Colors.Transparent) 56 | }; 57 | 58 | Application.Current.Resources["WindowCaptionButtonBackgroundPointerOver"] = theme switch 59 | { 60 | ElementTheme.Dark => new SolidColorBrush(Color.FromArgb(0x33, 0xFF, 0xFF, 0xFF)), 61 | ElementTheme.Light => new SolidColorBrush(Color.FromArgb(0x33, 0x00, 0x00, 0x00)), 62 | _ => new SolidColorBrush(Colors.Transparent) 63 | }; 64 | 65 | Application.Current.Resources["WindowCaptionButtonBackgroundPressed"] = theme switch 66 | { 67 | ElementTheme.Dark => new SolidColorBrush(Color.FromArgb(0x66, 0xFF, 0xFF, 0xFF)), 68 | ElementTheme.Light => new SolidColorBrush(Color.FromArgb(0x66, 0x00, 0x00, 0x00)), 69 | _ => new SolidColorBrush(Colors.Transparent) 70 | }; 71 | 72 | Application.Current.Resources["WindowCaptionButtonStrokePointerOver"] = theme switch 73 | { 74 | ElementTheme.Dark => new SolidColorBrush(Colors.White), 75 | ElementTheme.Light => new SolidColorBrush(Colors.Black), 76 | _ => new SolidColorBrush(Colors.Transparent) 77 | }; 78 | 79 | Application.Current.Resources["WindowCaptionButtonStrokePressed"] = theme switch 80 | { 81 | ElementTheme.Dark => new SolidColorBrush(Colors.White), 82 | ElementTheme.Light => new SolidColorBrush(Colors.Black), 83 | _ => new SolidColorBrush(Colors.Transparent) 84 | }; 85 | 86 | Application.Current.Resources["WindowCaptionBackground"] = new SolidColorBrush(Colors.Transparent); 87 | Application.Current.Resources["WindowCaptionBackgroundDisabled"] = new SolidColorBrush(Colors.Transparent); 88 | 89 | var hwnd = WinRT.Interop.WindowNative.GetWindowHandle(App.MainWindow); 90 | if (hwnd == GetActiveWindow()) 91 | { 92 | SendMessage(hwnd, WMACTIVATE, WAINACTIVE, IntPtr.Zero); 93 | SendMessage(hwnd, WMACTIVATE, WAACTIVE, IntPtr.Zero); 94 | } 95 | else 96 | { 97 | SendMessage(hwnd, WMACTIVATE, WAACTIVE, IntPtr.Zero); 98 | SendMessage(hwnd, WMACTIVATE, WAINACTIVE, IntPtr.Zero); 99 | } 100 | } 101 | } 102 | 103 | public static void ApplySystemThemeToCaptionButtons() 104 | { 105 | var res = Application.Current.Resources; 106 | var frame = App.AppTitlebar as FrameworkElement; 107 | if (frame != null) 108 | { 109 | if (frame.ActualTheme == ElementTheme.Dark) 110 | { 111 | res["WindowCaptionForeground"] = Colors.White; 112 | } 113 | else 114 | { 115 | res["WindowCaptionForeground"] = Colors.Black; 116 | } 117 | 118 | UpdateTitleBar(frame.ActualTheme); 119 | } 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /App2/MainWindow.xaml: -------------------------------------------------------------------------------- 1 |  13 | 14 | -------------------------------------------------------------------------------- /App2/MainWindow.xaml.cs: -------------------------------------------------------------------------------- 1 | using App2.Helpers; 2 | using Microsoft.UI; 3 | using Microsoft.UI.Composition.SystemBackdrops; 4 | using Microsoft.UI.Windowing; 5 | using Microsoft.UI.Xaml.Media; 6 | using Windows.UI; 7 | using Windows.UI.ViewManagement; 8 | namespace App2; 9 | 10 | public sealed partial class MainWindow : WindowEx 11 | { 12 | private Microsoft.UI.Dispatching.DispatcherQueue dispatcherQueue; 13 | 14 | private UISettings settings; 15 | 16 | public MainWindow() 17 | { 18 | InitializeComponent(); 19 | 20 | AppWindow.SetIcon(Path.Combine(AppContext.BaseDirectory, "Assets/WindowIcon.ico")); 21 | Content = null; 22 | Title = "AppDisplayName".GetLocalized(); 23 | 24 | SystemBackdrop = new MicaBackdrop() 25 | { 26 | Kind = MicaKind.BaseAlt 27 | }; 28 | var appWindow = AppWindow; 29 | var titleBar = appWindow.TitleBar; 30 | titleBar.ExtendsContentIntoTitleBar = true; 31 | bool isTallTitleBar = true; 32 | if (AppWindowTitleBar.IsCustomizationSupported() && appWindow.TitleBar.ExtendsContentIntoTitleBar) 33 | { 34 | AppWindow.TitleBar.ButtonBackgroundColor = Colors.Transparent; 35 | AppWindow.TitleBar.ButtonInactiveBackgroundColor = Colors.Transparent; 36 | AppWindow.TitleBar.ButtonHoverBackgroundColor = Color.FromArgb(25, 255, 255, 255); 37 | AppWindow.TitleBar.ButtonPressedBackgroundColor = Color.FromArgb(25, 200, 200, 200); 38 | if (isTallTitleBar) 39 | { 40 | appWindow.TitleBar.PreferredHeightOption = TitleBarHeightOption.Tall; 41 | } 42 | else 43 | { 44 | appWindow.TitleBar.PreferredHeightOption = TitleBarHeightOption.Standard; 45 | } 46 | } 47 | 48 | // Theme change code picked from https://github.com/microsoft/WinUI-Gallery/pull/1239 49 | dispatcherQueue = Microsoft.UI.Dispatching.DispatcherQueue.GetForCurrentThread(); 50 | settings = new UISettings(); 51 | settings.ColorValuesChanged += Settings_ColorValuesChanged; // cannot use FrameworkElement.ActualThemeChanged event 52 | } 53 | 54 | // this handles updating the caption button colors correctly when indows system theme is changed 55 | // while the app is open 56 | private void Settings_ColorValuesChanged(UISettings sender, object args) 57 | { 58 | // This calls comes off-thread, hence we will need to dispatch it to current app's thread 59 | dispatcherQueue.TryEnqueue(() => 60 | { 61 | TitleBarHelper.ApplySystemThemeToCaptionButtons(); 62 | }); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /App2/Models/LocalSettingsOptions.cs: -------------------------------------------------------------------------------- 1 | namespace App2.Models; 2 | 3 | public class LocalSettingsOptions 4 | { 5 | public string? ApplicationDataFolder 6 | { 7 | get; set; 8 | } 9 | 10 | public string? LocalSettingsFile 11 | { 12 | get; set; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /App2/Package.appinstaller: -------------------------------------------------------------------------------- 1 |  2 | 5 | 6 | 7 | 8 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /App2/Package.appxmanifest: -------------------------------------------------------------------------------- 1 |  2 | 3 | 12 | 13 | 17 | 18 | 19 | 20 | 21 | App2 22 | jpb 23 | Assets\StoreLogo.png 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 39 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /App2/Properties/launchsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | "App2 (Package)": { 4 | "commandName": "MsixPackage" 5 | }, 6 | "App2 (Unpackaged)": { 7 | "commandName": "Project" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /App2/README.md: -------------------------------------------------------------------------------- 1 | *Recommended Markdown Viewer: [Markdown Editor](https://marketplace.visualstudio.com/items?itemName=MadsKristensen.MarkdownEditor2)* 2 | 3 | ## Getting Started 4 | 5 | Browse and address `TODO:` comments in `View -> Task List` to learn the codebase and understand next steps for turning the generated code into production code. 6 | 7 | Explore the [WinUI Gallery](https://www.microsoft.com/store/productId/9P3JFPWWDZRC) to learn about available controls and design patterns. 8 | 9 | Relaunch Template Studio to modify the project by right-clicking on the project in `View -> Solution Explorer` then selecting `Add -> New Item (Template Studio)`. 10 | 11 | ## Publishing 12 | 13 | For projects with MSIX packaging, right-click on the application project and select `Package and Publish -> Create App Packages...` to create an MSIX package. 14 | 15 | For projects without MSIX packaging, follow the [deployment guide](https://docs.microsoft.com/windows/apps/windows-app-sdk/deploy-unpackaged-apps) or add the `Self-Contained` Feature to enable xcopy deployment. 16 | 17 | ## CI Pipelines 18 | 19 | See [README.md](https://github.com/microsoft/TemplateStudio/blob/main/docs/WinUI/pipelines/README.md) for guidance on building and testing projects in CI pipelines. 20 | 21 | ## Changelog 22 | 23 | See [releases](https://github.com/microsoft/TemplateStudio/releases) and [milestones](https://github.com/microsoft/TemplateStudio/milestones). 24 | 25 | ## Feedback 26 | 27 | Bugs and feature requests should be filed at https://aka.ms/templatestudio. 28 | -------------------------------------------------------------------------------- /App2/Services/ActivationService.cs: -------------------------------------------------------------------------------- 1 | using App2.Activation; 2 | using App2.Contracts.Services; 3 | using App2.Views; 4 | 5 | using Microsoft.UI.Xaml; 6 | using Microsoft.UI.Xaml.Controls; 7 | 8 | namespace App2.Services; 9 | 10 | public class ActivationService : IActivationService 11 | { 12 | private readonly ActivationHandler _defaultHandler; 13 | private readonly IEnumerable _activationHandlers; 14 | private readonly IThemeSelectorService _themeSelectorService; 15 | private UIElement? _shell = null; 16 | 17 | public ActivationService(ActivationHandler defaultHandler, IEnumerable activationHandlers, IThemeSelectorService themeSelectorService) 18 | { 19 | _defaultHandler = defaultHandler; 20 | _activationHandlers = activationHandlers; 21 | _themeSelectorService = themeSelectorService; 22 | } 23 | 24 | public async Task ActivateAsync(object activationArgs) 25 | { 26 | // Execute tasks before activation. 27 | await InitializeAsync(); 28 | 29 | // Set the MainWindow Content. 30 | if (App.MainWindow.Content == null) 31 | { 32 | _shell = App.GetService(); 33 | App.MainWindow.Content = _shell ?? new Frame(); 34 | } 35 | 36 | // Handle activation via ActivationHandlers. 37 | await HandleActivationAsync(activationArgs); 38 | 39 | // Activate the MainWindow. 40 | App.MainWindow.Activate(); 41 | 42 | // Execute tasks after activation. 43 | await StartupAsync(); 44 | } 45 | 46 | private async Task HandleActivationAsync(object activationArgs) 47 | { 48 | var activationHandler = _activationHandlers.FirstOrDefault(h => h.CanHandle(activationArgs)); 49 | 50 | if (activationHandler != null) 51 | { 52 | await activationHandler.HandleAsync(activationArgs); 53 | } 54 | 55 | if (_defaultHandler.CanHandle(activationArgs)) 56 | { 57 | await _defaultHandler.HandleAsync(activationArgs); 58 | } 59 | } 60 | 61 | private async Task InitializeAsync() 62 | { 63 | await _themeSelectorService.InitializeAsync().ConfigureAwait(false); 64 | await Task.CompletedTask; 65 | } 66 | 67 | private async Task StartupAsync() 68 | { 69 | await _themeSelectorService.SetRequestedThemeAsync(); 70 | await Task.CompletedTask; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /App2/Services/AppNotificationService.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Specialized; 2 | using System.Web; 3 | 4 | using App2.Contracts.Services; 5 | using App2.ViewModels; 6 | 7 | using Microsoft.Windows.AppNotifications; 8 | 9 | namespace App2.Notifications; 10 | 11 | public class AppNotificationService : IAppNotificationService 12 | { 13 | private readonly INavigationService _navigationService; 14 | 15 | public AppNotificationService(INavigationService navigationService) 16 | { 17 | _navigationService = navigationService; 18 | } 19 | 20 | ~AppNotificationService() 21 | { 22 | Unregister(); 23 | } 24 | 25 | public void Initialize() 26 | { 27 | AppNotificationManager.Default.NotificationInvoked += OnNotificationInvoked; 28 | 29 | //AppNotificationManager.Default.Register(); 30 | } 31 | 32 | public void OnNotificationInvoked(AppNotificationManager sender, AppNotificationActivatedEventArgs args) 33 | { 34 | // TODO: Handle notification invocations when your app is already running. 35 | 36 | //// // Navigate to a specific page based on the notification arguments. 37 | //// if (ParseArguments(args.Argument)["action"] == "Settings") 38 | //// { 39 | //// App.MainWindow.DispatcherQueue.TryEnqueue(() => 40 | //// { 41 | //// _navigationService.NavigateTo(typeof(SettingsViewModel).FullName!); 42 | //// }); 43 | //// } 44 | 45 | App.MainWindow.DispatcherQueue.TryEnqueue(() => 46 | { 47 | App.MainWindow.ShowMessageDialogAsync("TODO: Handle notification invocations when your app is already running.", "Notification Invoked"); 48 | 49 | App.MainWindow.BringToFront(); 50 | }); 51 | } 52 | 53 | public bool Show(string payload) 54 | { 55 | var appNotification = new AppNotification(payload); 56 | 57 | //AppNotificationManager.Default.Show(appNotification); 58 | 59 | return appNotification.Id != 0; 60 | } 61 | 62 | public NameValueCollection ParseArguments(string arguments) 63 | { 64 | return HttpUtility.ParseQueryString(arguments); 65 | } 66 | 67 | public void Unregister() 68 | { 69 | AppNotificationManager.Default.Unregister(); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /App2/Services/LocalSettingsService.cs: -------------------------------------------------------------------------------- 1 | using App2.Contracts.Services; 2 | using App2.Core.Contracts.Services; 3 | using App2.Core.Helpers; 4 | using App2.Helpers; 5 | using App2.Models; 6 | 7 | using Microsoft.Extensions.Options; 8 | 9 | using Windows.ApplicationModel; 10 | using Windows.Storage; 11 | 12 | namespace App2.Services; 13 | 14 | public class LocalSettingsService : ILocalSettingsService 15 | { 16 | private const string _defaultApplicationDataFolder = "App2/ApplicationData"; 17 | private const string _defaultLocalSettingsFile = "LocalSettings.json"; 18 | 19 | private readonly IFileService _fileService; 20 | private readonly LocalSettingsOptions _options; 21 | 22 | private readonly string _localApplicationData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); 23 | private readonly string _applicationDataFolder; 24 | private readonly string _localsettingsFile; 25 | 26 | private IDictionary _settings; 27 | 28 | private bool _isInitialized; 29 | 30 | public LocalSettingsService(IFileService fileService, IOptions options) 31 | { 32 | _fileService = fileService; 33 | _options = options.Value; 34 | 35 | _applicationDataFolder = Path.Combine(_localApplicationData, _options.ApplicationDataFolder ?? _defaultApplicationDataFolder); 36 | _localsettingsFile = _options.LocalSettingsFile ?? _defaultLocalSettingsFile; 37 | 38 | _settings = new Dictionary(); 39 | } 40 | 41 | private async Task InitializeAsync() 42 | { 43 | if (!_isInitialized) 44 | { 45 | _settings = await Task.Run(() => _fileService.Read>(_applicationDataFolder, _localsettingsFile)) ?? new Dictionary(); 46 | 47 | _isInitialized = true; 48 | } 49 | } 50 | 51 | public async Task ReadSettingAsync(string key) 52 | { 53 | if (RuntimeHelper.IsMSIX) 54 | { 55 | if (ApplicationData.Current.LocalSettings.Values.TryGetValue(key, out var obj)) 56 | { 57 | return await Json.ToObjectAsync((string)obj); 58 | } 59 | } 60 | else 61 | { 62 | await InitializeAsync(); 63 | 64 | if (_settings != null && _settings.TryGetValue(key, out var obj)) 65 | { 66 | return await Json.ToObjectAsync((string)obj); 67 | } 68 | } 69 | 70 | return default; 71 | } 72 | 73 | public async Task SaveSettingAsync(string key, T value) 74 | { 75 | if (RuntimeHelper.IsMSIX) 76 | { 77 | ApplicationData.Current.LocalSettings.Values[key] = await Json.StringifyAsync(value); 78 | } 79 | else 80 | { 81 | await InitializeAsync(); 82 | 83 | _settings[key] = await Json.StringifyAsync(value); 84 | 85 | await Task.Run(() => _fileService.Save(_applicationDataFolder, _localsettingsFile, _settings)); 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /App2/Services/NavigationService.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics.CodeAnalysis; 2 | 3 | using App2.Contracts.Services; 4 | using App2.Contracts.ViewModels; 5 | using App2.Helpers; 6 | 7 | using Microsoft.UI.Xaml.Controls; 8 | using Microsoft.UI.Xaml.Navigation; 9 | 10 | namespace App2.Services; 11 | 12 | // For more information on navigation between pages see 13 | // https://github.com/microsoft/TemplateStudio/blob/main/docs/WinUI/navigation.md 14 | public class NavigationService : INavigationService 15 | { 16 | private readonly IPageService _pageService; 17 | private object? _lastParameterUsed; 18 | private Frame? _frame; 19 | 20 | public event NavigatedEventHandler? Navigated; 21 | 22 | public Frame? Frame 23 | { 24 | get 25 | { 26 | if (_frame == null) 27 | { 28 | _frame = App.MainWindow.Content as Frame; 29 | RegisterFrameEvents(); 30 | } 31 | 32 | return _frame; 33 | } 34 | 35 | set 36 | { 37 | UnregisterFrameEvents(); 38 | _frame = value; 39 | RegisterFrameEvents(); 40 | } 41 | } 42 | 43 | [MemberNotNullWhen(true, nameof(Frame), nameof(_frame))] 44 | public bool CanGoBack => Frame != null && Frame.CanGoBack; 45 | 46 | public NavigationService(IPageService pageService) 47 | { 48 | _pageService = pageService; 49 | } 50 | 51 | private void RegisterFrameEvents() 52 | { 53 | if (_frame != null) 54 | { 55 | _frame.Navigated += OnNavigated; 56 | } 57 | } 58 | 59 | private void UnregisterFrameEvents() 60 | { 61 | if (_frame != null) 62 | { 63 | _frame.Navigated -= OnNavigated; 64 | } 65 | } 66 | 67 | public bool GoBack() 68 | { 69 | if (CanGoBack) 70 | { 71 | var vmBeforeNavigation = _frame.GetPageViewModel(); 72 | _frame.GoBack(); 73 | if (vmBeforeNavigation is INavigationAware navigationAware) 74 | { 75 | navigationAware.OnNavigatedFrom(); 76 | } 77 | 78 | return true; 79 | } 80 | 81 | return false; 82 | } 83 | 84 | public bool NavigateTo(string pageKey, object? parameter = null, bool clearNavigation = false) 85 | { 86 | var pageType = _pageService.GetPageType(pageKey); 87 | 88 | if (_frame != null && (_frame.Content?.GetType() != pageType || (parameter != null && !parameter.Equals(_lastParameterUsed)))) 89 | { 90 | _frame.Tag = clearNavigation; 91 | var vmBeforeNavigation = _frame.GetPageViewModel(); 92 | var navigated = _frame.Navigate(pageType, parameter); 93 | if (navigated) 94 | { 95 | _lastParameterUsed = parameter; 96 | if (vmBeforeNavigation is INavigationAware navigationAware) 97 | { 98 | navigationAware.OnNavigatedFrom(); 99 | } 100 | } 101 | 102 | return navigated; 103 | } 104 | 105 | return false; 106 | } 107 | 108 | private void OnNavigated(object sender, NavigationEventArgs e) 109 | { 110 | if (sender is Frame frame) 111 | { 112 | var clearNavigation = (bool)frame.Tag; 113 | if (clearNavigation) 114 | { 115 | frame.BackStack.Clear(); 116 | } 117 | 118 | if (frame.GetPageViewModel() is INavigationAware navigationAware) 119 | { 120 | navigationAware.OnNavigatedTo(e.Parameter); 121 | } 122 | 123 | Navigated?.Invoke(sender, e); 124 | } 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /App2/Services/NavigationViewService.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics.CodeAnalysis; 2 | 3 | using App2.Contracts.Services; 4 | using App2.Helpers; 5 | using App2.ViewModels; 6 | 7 | using Microsoft.UI.Xaml.Controls; 8 | 9 | namespace App2.Services; 10 | 11 | public class NavigationViewService : INavigationViewService 12 | { 13 | private readonly INavigationService _navigationService; 14 | 15 | private readonly IPageService _pageService; 16 | 17 | private NavigationView? _navigationView; 18 | 19 | public IList? MenuItems => _navigationView?.MenuItems; 20 | 21 | public object? SettingsItem => _navigationView?.SettingsItem; 22 | 23 | public NavigationViewService(INavigationService navigationService, IPageService pageService) 24 | { 25 | _navigationService = navigationService; 26 | _pageService = pageService; 27 | } 28 | 29 | [MemberNotNull(nameof(_navigationView))] 30 | public void Initialize(NavigationView navigationView) 31 | { 32 | _navigationView = navigationView; 33 | _navigationView.BackRequested += OnBackRequested; 34 | _navigationView.ItemInvoked += OnItemInvoked; 35 | } 36 | 37 | public void UnregisterEvents() 38 | { 39 | if (_navigationView != null) 40 | { 41 | _navigationView.BackRequested -= OnBackRequested; 42 | _navigationView.ItemInvoked -= OnItemInvoked; 43 | } 44 | } 45 | 46 | public NavigationViewItem? GetSelectedItem(Type pageType) 47 | { 48 | if (_navigationView != null) 49 | { 50 | return GetSelectedItem(_navigationView.MenuItems, pageType) ?? GetSelectedItem(_navigationView.FooterMenuItems, pageType); 51 | } 52 | 53 | return null; 54 | } 55 | 56 | private void OnBackRequested(NavigationView sender, NavigationViewBackRequestedEventArgs args) => _navigationService.GoBack(); 57 | 58 | private void OnItemInvoked(NavigationView sender, NavigationViewItemInvokedEventArgs args) 59 | { 60 | if (args.IsSettingsInvoked) 61 | { 62 | _navigationService.NavigateTo(typeof(SettingsViewModel).FullName!); 63 | } 64 | else 65 | { 66 | var selectedItem = args.InvokedItemContainer as NavigationViewItem; 67 | 68 | if (selectedItem?.GetValue(NavigationHelper.NavigateToProperty) is string pageKey) 69 | { 70 | _navigationService.NavigateTo(pageKey); 71 | } 72 | } 73 | } 74 | 75 | private NavigationViewItem? GetSelectedItem(IEnumerable menuItems, Type pageType) 76 | { 77 | foreach (var item in menuItems.OfType()) 78 | { 79 | if (IsMenuItemForPageType(item, pageType)) 80 | { 81 | return item; 82 | } 83 | 84 | var selectedChild = GetSelectedItem(item.MenuItems, pageType); 85 | if (selectedChild != null) 86 | { 87 | return selectedChild; 88 | } 89 | } 90 | 91 | return null; 92 | } 93 | 94 | private bool IsMenuItemForPageType(NavigationViewItem menuItem, Type sourcePageType) 95 | { 96 | if (menuItem.GetValue(NavigationHelper.NavigateToProperty) is string pageKey) 97 | { 98 | return _pageService.GetPageType(pageKey) == sourcePageType; 99 | } 100 | 101 | return false; 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /App2/Services/PageService.cs: -------------------------------------------------------------------------------- 1 | using App2.Contracts.Services; 2 | using App2.ViewModels; 3 | using App2.Views; 4 | 5 | using CommunityToolkit.Mvvm.ComponentModel; 6 | 7 | using Microsoft.UI.Xaml.Controls; 8 | 9 | namespace App2.Services; 10 | 11 | public class PageService : IPageService 12 | { 13 | private readonly Dictionary _pages = new(); 14 | 15 | public PageService() 16 | { 17 | Configure(); 18 | Configure(); 19 | } 20 | 21 | public Type GetPageType(string key) 22 | { 23 | Type? pageType; 24 | lock (_pages) 25 | { 26 | if (!_pages.TryGetValue(key, out pageType)) 27 | { 28 | throw new ArgumentException($"Page not found: {key}. Did you forget to call PageService.Configure?"); 29 | } 30 | } 31 | 32 | return pageType; 33 | } 34 | 35 | private void Configure() 36 | where VM : ObservableObject 37 | where V : Page 38 | { 39 | lock (_pages) 40 | { 41 | var key = typeof(VM).FullName!; 42 | if (_pages.ContainsKey(key)) 43 | { 44 | throw new ArgumentException($"The key {key} is already configured in PageService"); 45 | } 46 | 47 | var type = typeof(V); 48 | if (_pages.ContainsValue(type)) 49 | { 50 | throw new ArgumentException($"This type is already configured with key {_pages.First(p => p.Value == type).Key}"); 51 | } 52 | 53 | _pages.Add(key, type); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /App2/Services/ThemeSelectorService.cs: -------------------------------------------------------------------------------- 1 | using App2.Contracts.Services; 2 | using App2.Helpers; 3 | 4 | using Microsoft.UI.Xaml; 5 | 6 | namespace App2.Services; 7 | 8 | public class ThemeSelectorService : IThemeSelectorService 9 | { 10 | private const string SettingsKey = "AppBackgroundRequestedTheme"; 11 | 12 | public ElementTheme Theme { get; set; } = ElementTheme.Default; 13 | 14 | private readonly ILocalSettingsService _localSettingsService; 15 | 16 | public ThemeSelectorService(ILocalSettingsService localSettingsService) 17 | { 18 | _localSettingsService = localSettingsService; 19 | } 20 | 21 | public async Task InitializeAsync() 22 | { 23 | Theme = await LoadThemeFromSettingsAsync(); 24 | await Task.CompletedTask; 25 | } 26 | 27 | public async Task SetThemeAsync(ElementTheme theme) 28 | { 29 | Theme = theme; 30 | 31 | await SetRequestedThemeAsync(); 32 | await SaveThemeInSettingsAsync(Theme); 33 | } 34 | 35 | public async Task SetRequestedThemeAsync() 36 | { 37 | if (App.MainWindow.Content is FrameworkElement rootElement) 38 | { 39 | rootElement.RequestedTheme = Theme; 40 | 41 | TitleBarHelper.UpdateTitleBar(Theme); 42 | } 43 | 44 | await Task.CompletedTask; 45 | } 46 | 47 | private async Task LoadThemeFromSettingsAsync() 48 | { 49 | var themeName = await _localSettingsService.ReadSettingAsync(SettingsKey); 50 | 51 | if (Enum.TryParse(themeName, out ElementTheme cacheTheme)) 52 | { 53 | return cacheTheme; 54 | } 55 | 56 | return ElementTheme.Default; 57 | } 58 | 59 | private async Task SaveThemeInSettingsAsync(ElementTheme theme) 60 | { 61 | await _localSettingsService.SaveSettingAsync(SettingsKey, theme.ToString()); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /App2/Strings/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 | Axela 122 | 123 | 124 | Axela 125 | 126 | 127 | Axela AI Chat 128 | 129 | 130 | Personalization 131 | 132 | 133 | Theme 134 | 135 | 136 | Light 137 | 138 | 139 | Dark 140 | 141 | 142 | Default 143 | 144 | 145 | About this application 146 | 147 | 148 | Axela is an AI chatbot for Windows, that is NOT dependent on ChatGPT in any way - Axela is its own, unique chatbot (one of the main reasons why there aren't much commands yet) 149 | There are plans to port Axela to Android and AOSP-based custom ROMs, such as jpbROM, where it will probably be preinstalled (jpbROM is my custom rom) 150 | Additionally, new features like TTS output and STT input are planned to be added for ease of use and to put Axela up as a true AI chatbot and personal assistant. 151 | 152 | 153 | Privacy Statement 154 | 155 | 156 | https://YourPrivacyUrlGoesHere/ 157 | 158 | 159 | <toast launch="action=ToastClick"> 160 | <visual> 161 | <binding template="ToastGeneric"> 162 | <text>App Notification</text> 163 | <text></text> 164 | <image placement="appLogoOverride" hint-crop="circle" src="{0}Assets/WindowIcon.ico"/> 165 | </binding> 166 | </visual> 167 | <actions> 168 | <action content="Settings" arguments="action=Settings"/> 169 | </actions> 170 | </toast> 171 | 172 | 173 | Change Backdrop 174 | 175 | 176 | Current backdrop: 177 | 178 | 179 | Axela (the AI model) is only available in English for now. Please input data in English, not in any other language, as Axela's query detection system and responses will be updated in a later release. 180 | 181 | 182 | Axela (the AI model) is only available in English for now 183 | 184 | 185 | Settings 186 | 187 | 188 | Submit 189 | 190 | 191 | Type here to talk to Axela! ;D 192 | 193 | -------------------------------------------------------------------------------- /App2/Strings/pl-pl/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 | Axela 122 | 123 | 124 | Axela 125 | 126 | 127 | Czat AI Axela 128 | 129 | 130 | Personalizacja 131 | 132 | 133 | Motyw 134 | 135 | 136 | Jasny 137 | 138 | 139 | Ciemny 140 | 141 | 142 | Domyślny 143 | 144 | 145 | O tej aplikacji 146 | 147 | 148 | Axela jest czatbotem AI dla Windows, który NIE jest oparty na ChatGPT - Axela jest swoim własnym, unikalnym chatbotem (jeden z powodów dlaczego nie ma jeszcze dużo komend) 149 | Są plany żeby stworzyć wersję (port) na Androida i inne nakładki oprogramowania bazowane na kodzie AOSP, jak jpbROM. gdzie będzie pewnie zainstalowane jako aplikacja fabryczna/systemowa. (jpbROM jest moim oprogramowaniem bazowanym na AOSP) 150 | Dodatkowo, nowe funkcje tak jak input STT (speech-to-text) i output TTS (text-to-speech/synteza mowy) są planowane żeby było łatwiej używać Axelę i żeby upozycjonować Axelę jako prawdziwy czatbot AI i personalny asystent. 151 | 152 | 153 | Prywatność 154 | 155 | 156 | https://YourPrivacyUrlGoesHere/ 157 | 158 | 159 | <toast launch="action=ToastClick"> 160 | <visual> 161 | <binding template="ToastGeneric"> 162 | <text>App Notification</text> 163 | <text></text> 164 | <image placement="appLogoOverride" hint-crop="circle" src="{0}Assets/WindowIcon.ico"/> 165 | </binding> 166 | </visual> 167 | <actions> 168 | <action content="Settings" arguments="action=Settings"/> 169 | </actions> 170 | </toast> 171 | 172 | 173 | Zmień Tło 174 | 175 | 176 | Aktualne tło: 177 | 178 | 179 | Axela (model AI) jest dostępna na razie tylko w języku angielskim. Proszę wpisywać dane w angielskim, nie w innym języku (np. polskim), bo system detekcji komend i odpowiedzi będzie zaktualizowany w późniejszej wersji. 180 | 181 | 182 | Axela (model AI) jest dostępna na razie tylko w języku angielskim. 183 | 184 | 185 | Ustawienia 186 | 187 | 188 | Wyślij do Axeli 189 | 190 | 191 | Pisz tutaj żeby komunikować się z Axelą! ;D 192 | 193 | -------------------------------------------------------------------------------- /App2/Styles/FontSizes.xaml: -------------------------------------------------------------------------------- 1 |  4 | 5 | 24 6 | 7 | 16 8 | 9 | 10 | -------------------------------------------------------------------------------- /App2/Styles/TextBlock.xaml: -------------------------------------------------------------------------------- 1 |  4 | 5 | 12 | 13 | 19 | 20 | -------------------------------------------------------------------------------- /App2/Styles/Thickness.xaml: -------------------------------------------------------------------------------- 1 |  4 | 5 | 0,36,0,0 6 | 0,36,0,36 7 | 8 | 0,24,0,0 9 | 0,24,0,24 10 | 24,0,24,0 11 | 0,0,0,24 12 | 13 | 12,0,0,0 14 | 12,0,12,0 15 | 0,12,0,0 16 | 0,0,12,0 17 | 0,12,0,12 18 | 19 | 8,0,0,0 20 | 0,8,0,0 21 | 8,8,8,8 22 | 23 | 0,4,0,0 24 | 4,4,4,4 25 | 26 | 1,1,0,0 27 | 8,0,0,0 28 | 0,48,0,0 29 | 56,34,0,0 30 | 56,24,56,0 31 | 32 | 36,24,36,0 33 | 34 | -12,4,0,0 35 | 36 | 37 | -------------------------------------------------------------------------------- /App2/TemplateStudio.xml: -------------------------------------------------------------------------------- 1 |  3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /App2/Usings.cs: -------------------------------------------------------------------------------- 1 | global using WinUIEx; 2 | -------------------------------------------------------------------------------- /App2/ViewModels/MainViewModel.cs: -------------------------------------------------------------------------------- 1 | using CommunityToolkit.Mvvm.ComponentModel; 2 | 3 | namespace App2.ViewModels; 4 | 5 | public partial class MainViewModel : ObservableRecipient 6 | { 7 | public MainViewModel() 8 | { 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /App2/ViewModels/SettingsViewModel.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Windows.Input; 3 | 4 | using App2.Contracts.Services; 5 | using App2.Helpers; 6 | 7 | using CommunityToolkit.Mvvm.ComponentModel; 8 | using CommunityToolkit.Mvvm.Input; 9 | 10 | using Microsoft.UI.Xaml; 11 | 12 | using Windows.ApplicationModel; 13 | 14 | namespace App2.ViewModels; 15 | 16 | public partial class SettingsViewModel : ObservableRecipient 17 | { 18 | private readonly IThemeSelectorService _themeSelectorService; 19 | 20 | [ObservableProperty] 21 | private ElementTheme _elementTheme; 22 | 23 | [ObservableProperty] 24 | private string _versionDescription; 25 | 26 | public ICommand SwitchThemeCommand 27 | { 28 | get; 29 | } 30 | 31 | public SettingsViewModel(IThemeSelectorService themeSelectorService) 32 | { 33 | _themeSelectorService = themeSelectorService; 34 | _elementTheme = _themeSelectorService.Theme; 35 | _versionDescription = GetVersionDescription(); 36 | 37 | SwitchThemeCommand = new RelayCommand( 38 | async (param) => 39 | { 40 | if (ElementTheme != param) 41 | { 42 | ElementTheme = param; 43 | await _themeSelectorService.SetThemeAsync(param); 44 | } 45 | }); 46 | } 47 | 48 | private static string GetVersionDescription() 49 | { 50 | Version version; 51 | 52 | if (RuntimeHelper.IsMSIX) 53 | { 54 | var packageVersion = Package.Current.Id.Version; 55 | 56 | version = new(packageVersion.Major, packageVersion.Minor, packageVersion.Build, packageVersion.Revision); 57 | } 58 | else 59 | { 60 | version = Assembly.GetExecutingAssembly().GetName().Version!; 61 | } 62 | 63 | return $"{"AppDisplayName".GetLocalized()} - {version.Major}.{version.Minor}.{version.Build}.{version.Revision}"; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /App2/ViewModels/ShellViewModel.cs: -------------------------------------------------------------------------------- 1 | using App2.Contracts.Services; 2 | using App2.Views; 3 | 4 | using CommunityToolkit.Mvvm.ComponentModel; 5 | 6 | using Microsoft.UI.Xaml.Navigation; 7 | 8 | namespace App2.ViewModels; 9 | 10 | public partial class ShellViewModel : ObservableRecipient 11 | { 12 | [ObservableProperty] 13 | private bool isBackEnabled; 14 | 15 | [ObservableProperty] 16 | private object? selected; 17 | 18 | public INavigationService NavigationService 19 | { 20 | get; 21 | } 22 | 23 | public INavigationViewService NavigationViewService 24 | { 25 | get; 26 | } 27 | 28 | public ShellViewModel(INavigationService navigationService, INavigationViewService navigationViewService) 29 | { 30 | NavigationService = navigationService; 31 | NavigationService.Navigated += OnNavigated; 32 | NavigationViewService = navigationViewService; 33 | } 34 | 35 | private void OnNavigated(object sender, NavigationEventArgs e) 36 | { 37 | IsBackEnabled = NavigationService.CanGoBack; 38 | 39 | if (e.SourcePageType == typeof(SettingsPage)) 40 | { 41 | Selected = NavigationViewService.SettingsItem; 42 | return; 43 | } 44 | 45 | var selectedItem = NavigationViewService.GetSelectedItem(e.SourcePageType); 46 | if (selectedItem != null) 47 | { 48 | Selected = selectedItem; 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /App2/Views/MainPage.xaml: -------------------------------------------------------------------------------- 1 |  9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /App2/Views/SettingsPage.xaml.cs: -------------------------------------------------------------------------------- 1 | using App2.ViewModels; 2 | 3 | using Microsoft.UI.Xaml.Controls; 4 | using Windows.ApplicationModel.DataTransfer; 5 | 6 | namespace App2.Views; 7 | 8 | // TODO: Set the URL for your privacy policy by updating SettingsPage_PrivacyTermsLink.NavigateUri in Resources.resw. 9 | public sealed partial class SettingsPage : Page 10 | { 11 | public SettingsViewModel ViewModel 12 | { 13 | get; 14 | } 15 | 16 | public SettingsPage() 17 | { 18 | ViewModel = App.GetService(); 19 | InitializeComponent(); 20 | } 21 | 22 | private void CopyVerInfo(object sender, Microsoft.UI.Xaml.RoutedEventArgs e) 23 | { 24 | var data = new DataPackage 25 | { 26 | RequestedOperation = DataPackageOperation.Copy 27 | }; 28 | data.SetText(aboutblock.Header + " version " + aboutblock.Description); 29 | 30 | Clipboard.SetContentWithOptions(data, new ClipboardContentOptions() { IsAllowedInHistory = true, IsRoamable = true }); 31 | Clipboard.Flush(); 32 | } 33 | } -------------------------------------------------------------------------------- /App2/Views/ShellPage.xaml: -------------------------------------------------------------------------------- 1 |  11 | 12 | 13 | 18 | 22 | 27 | 28 | 38 | 39 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 58 | 59 | 60 | 61 | 62 | 64 | 65 | 66 | 67 | 70 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /App2/Views/ShellPage.xaml.cs: -------------------------------------------------------------------------------- 1 | using App2.Contracts.Services; 2 | using App2.Helpers; 3 | using App2.ViewModels; 4 | 5 | using Microsoft.UI.Xaml; 6 | using Microsoft.UI.Xaml.Controls; 7 | using Microsoft.UI.Xaml.Input; 8 | using Microsoft.UI.Xaml.Media; 9 | 10 | using Windows.System; 11 | 12 | namespace App2.Views; 13 | 14 | // TODO: Update NavigationViewItem titles and icons in ShellPage.xaml. 15 | public sealed partial class ShellPage : Page 16 | { 17 | public ShellViewModel ViewModel 18 | { 19 | get; 20 | } 21 | 22 | public ShellPage(ShellViewModel viewModel) 23 | { 24 | ViewModel = viewModel; 25 | InitializeComponent(); 26 | 27 | ViewModel.NavigationService.Frame = NavigationFrame; 28 | ViewModel.NavigationViewService.Initialize(NavigationViewControl); 29 | 30 | // TODO: Set the title bar icon by updating /Assets/WindowIcon.ico. 31 | // A custom title bar is required for full window theme and Mica support. 32 | // https://docs.microsoft.com/windows/apps/develop/title-bar?tabs=winui3#full-customization 33 | App.MainWindow.ExtendsContentIntoTitleBar = true; 34 | App.MainWindow.SetTitleBar(AppTitleBar); 35 | App.MainWindow.Activated += MainWindow_Activated; 36 | AppTitleBarText.Text = "AppDisplayName".GetLocalized(); 37 | } 38 | 39 | private void OnLoaded(object sender, Microsoft.UI.Xaml.RoutedEventArgs e) 40 | { 41 | TitleBarHelper.UpdateTitleBar(RequestedTheme); 42 | 43 | KeyboardAccelerators.Add(BuildKeyboardAccelerator(VirtualKey.Left, VirtualKeyModifiers.Menu)); 44 | KeyboardAccelerators.Add(BuildKeyboardAccelerator(VirtualKey.GoBack)); 45 | } 46 | 47 | private void MainWindow_Activated(object sender, WindowActivatedEventArgs args) 48 | { 49 | var resource = args.WindowActivationState == WindowActivationState.Deactivated ? "WindowCaptionForegroundDisabled" : "WindowCaptionForeground"; 50 | 51 | AppTitleBarText.Foreground = (SolidColorBrush)App.Current.Resources[resource]; 52 | App.AppTitlebar = AppTitleBarText as UIElement; 53 | } 54 | 55 | private void NavigationViewControl_DisplayModeChanged(NavigationView sender, NavigationViewDisplayModeChangedEventArgs args) 56 | { 57 | AppTitleBar.Margin = new Thickness() 58 | { 59 | Left = sender.CompactPaneLength * (sender.DisplayMode == NavigationViewDisplayMode.Minimal ? 2 : 1), 60 | Top = AppTitleBar.Margin.Top, 61 | Right = AppTitleBar.Margin.Right, 62 | Bottom = AppTitleBar.Margin.Bottom 63 | }; 64 | } 65 | 66 | private static KeyboardAccelerator BuildKeyboardAccelerator(VirtualKey key, VirtualKeyModifiers? modifiers = null) 67 | { 68 | var keyboardAccelerator = new KeyboardAccelerator() { Key = key }; 69 | 70 | if (modifiers.HasValue) 71 | { 72 | keyboardAccelerator.Modifiers = modifiers.Value; 73 | } 74 | 75 | keyboardAccelerator.Invoked += OnKeyboardAcceleratorInvoked; 76 | 77 | return keyboardAccelerator; 78 | } 79 | 80 | private static void OnKeyboardAcceleratorInvoked(KeyboardAccelerator sender, KeyboardAcceleratorInvokedEventArgs args) 81 | { 82 | var navigationService = App.GetService(); 83 | 84 | var result = navigationService.GoBack(); 85 | 86 | args.Handled = result; 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /App2/app.manifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | true/PM 12 | PerMonitorV2, PerMonitor 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /App2/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "LocalSettingsOptions": { 3 | "ApplicationDataFolder": "App2/ApplicationData", 4 | "LocalSettingsFile": "LocalSettings.json" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 jpb/jpbandroid 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) [year] [fullname] 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Axela. 2 | An AI chatbot to help you with anything!! 😄 3 |
In case you wondered, Axela is *not* a ChatGPT client and uses its own (simple) AI engine that is coded into the program itself (included inside MainPage.xaml.cs, in a function), not as a separate module. This approach enables Axela to work offline, though Wikipedia support (run by the Wikipedia support Python module) requires an Internet connection to get data from Wikipedia. These unique features set it apart, as the majority of chatbot apps today are just chatGPT clients... 4 |
Currently in Stable, don't expect *loads* of functionality from it yet (as it is not fully featured yet), but please check here regularly, as there will be new features and commands added! 5 | 6 |

Get support, sneak peeks and exclusive development updates n the official Discord server!
Discord