From b718e55a41295f8b6bda5f9ac37d2cd7c784ed5a Mon Sep 17 00:00:00 2001 From: Trevor Rydalch Date: Fri, 22 Nov 2024 18:56:32 -0600 Subject: [PATCH] Uno Sample complete --- samples/todoapp/TodoApp.Uno/.editorconfig | 167 ++++++++ samples/todoapp/TodoApp.Uno/.gitignore | 403 ++++++++++++++++++ samples/todoapp/TodoApp.Uno/.run/Readme.md | 3 + .../TodoApp.Uno/.run/TodoApp.Uno.run.xml | 62 +++ .../TodoApp.Uno/.vscode/extensions.json | 5 + .../todoapp/TodoApp.Uno/.vscode/launch.json | 56 +++ .../todoapp/TodoApp.Uno/.vscode/settings.json | 10 + .../todoapp/TodoApp.Uno/.vscode/tasks.json | 57 +++ samples/todoapp/TodoApp.Uno/.vsconfig | 34 ++ .../todoapp/TodoApp.Uno/Directory.Build.props | 15 + .../TodoApp.Uno/Directory.Build.targets | 2 + .../TodoApp.Uno/Directory.Packages.props | 19 + samples/todoapp/TodoApp.Uno/TodoApp.Uno.sln | 47 ++ .../todoapp/TodoApp.Uno/TodoApp.Uno/App.xaml | 28 ++ .../TodoApp.Uno/TodoApp.Uno/App.xaml.cs | 134 ++++++ .../TodoApp.Uno/Assets/AddItem.png | Bin 0 -> 373 bytes .../TodoApp.Uno/Assets/Icons/icon.svg | 42 ++ .../Assets/Icons/icon_foreground.svg | 137 ++++++ .../TodoApp.Uno/Assets/Images/back.svg | 3 + .../Assets/LockScreenLogo.scale-200.png | Bin 0 -> 432 bytes .../TodoApp.Uno/Assets/RefreshItems.png | Bin 0 -> 866 bytes .../TodoApp.Uno/Assets/SharedAssets.md | 32 ++ .../Assets/Splash/splash_screen.svg | 137 ++++++ .../Assets/SplashScreen.scale-200.png | Bin 0 -> 5372 bytes .../Assets/Square150x150Logo.scale-200.png | Bin 0 -> 1755 bytes .../Assets/Square44x44Logo.scale-200.png | Bin 0 -> 637 bytes ...x44Logo.targetsize-24_altform-unplated.png | Bin 0 -> 283 bytes .../TodoApp.Uno/Assets/StoreLogo.png | Bin 0 -> 456 bytes .../Assets/Wide310x150Logo.scale-200.png | Bin 0 -> 2097 bytes .../TodoApp.Uno/Database/AppDbContext.cs | 65 +++ .../TodoApp.Uno/Database/IDbInitializer.cs | 26 ++ .../Database/OfflineClientEntity.cs | 20 + .../TodoApp.Uno/Database/TodoItem.cs | 16 + .../TodoApp.Uno/TodoApp.Uno/GlobalUsings.cs | 11 + .../TodoApp.Uno/Models/AppConfig.cs | 6 + .../TodoApp.Uno/Package.appxmanifest | 31 ++ .../Platforms/Android/AndroidManifest.xml | 4 + .../Platforms/Android/Assets/AboutAssets.txt | 22 + .../Platforms/Android/Main.Android.cs | 43 ++ .../Platforms/Android/MainActivity.Android.cs | 15 + .../Android/Resources/AboutResources.txt | 47 ++ .../Android/Resources/values/Strings.xml | 5 + .../Android/Resources/values/Styles.xml | 22 + .../Platforms/Android/environment.conf | 2 + .../TodoApp.Uno/Platforms/Desktop/Program.cs | 19 + .../Platforms/MacCatalyst/Entitlements.plist | 6 + .../Platforms/MacCatalyst/Info.plist | 26 ++ .../Platforms/MacCatalyst/Main.maccatalyst.cs | 13 + .../LaunchImages.launchimage/Contents.json | 58 +++ .../Platforms/WebAssembly/LinkerConfig.xml | 10 + .../Platforms/WebAssembly/Program.cs | 13 + .../Platforms/WebAssembly/WasmCSS/Fonts.css | 28 ++ .../WebAssembly/WasmScripts/AppManifest.js | 3 + .../WebAssembly/manifest.webmanifest | 10 + .../wwwroot/staticwebapp.config.json | 30 ++ .../Platforms/WebAssembly/wwwroot/web.config | 78 ++++ .../Platforms/iOS/Entitlements.plist | 6 + .../TodoApp.Uno/Platforms/iOS/Info.plist | 43 ++ .../TodoApp.Uno/Platforms/iOS/Main.iOS.cs | 13 + .../LaunchImages.launchimage/Contents.json | 58 +++ .../Platforms/iOS/PrivacyInfo.xcprivacy | 41 ++ .../TodoApp.Uno/Presentation/Shell.xaml | 36 ++ .../TodoApp.Uno/Presentation/Shell.xaml.cs | 10 + .../Presentation/ShellViewModel.cs | 13 + .../PublishProfiles/win-arm64.pubxml | 18 + .../Properties/PublishProfiles/win-x64.pubxml | 18 + .../Properties/PublishProfiles/win-x86.pubxml | 23 + .../Properties/launchSettings.json | 50 +++ .../todoapp/TodoApp.Uno/TodoApp.Uno/ReadMe.md | 7 + .../TodoApp.Uno/Services/LoggingHandler.cs | 49 +++ .../TodoApp.Uno/Strings/en/Resources.resw | 123 ++++++ .../TodoApp.Uno/Strings/es/Resources.resw | 123 ++++++ .../TodoApp.Uno/Strings/fr/Resources.resw | 123 ++++++ .../TodoApp.Uno/Strings/pt-BR/Resources.resw | 123 ++++++ .../Styles/ColorPaletteOverride.json | 76 ++++ .../Styles/ColorPaletteOverride.xaml | 65 +++ .../TodoApp.Uno/TodoApp.Uno.csproj | 90 ++++ .../ViewModels/NotificationEventArgs.cs | 9 + .../ViewModels/TodoItemViewModel.cs | 47 ++ .../ViewModels/TodoListViewModel.cs | 126 ++++++ .../TodoApp.Uno/Views/TodoListPage.xaml | 112 +++++ .../TodoApp.Uno/Views/TodoListPage.xaml.cs | 67 +++ .../TodoApp.Uno/TodoApp.Uno/app.manifest | 25 ++ .../TodoApp.Uno/appsettings.development.json | 9 + .../TodoApp.Uno/TodoApp.Uno/appsettings.json | 16 + samples/todoapp/TodoApp.Uno/global.json | 9 + 86 files changed, 3550 insertions(+) create mode 100644 samples/todoapp/TodoApp.Uno/.editorconfig create mode 100644 samples/todoapp/TodoApp.Uno/.gitignore create mode 100644 samples/todoapp/TodoApp.Uno/.run/Readme.md create mode 100644 samples/todoapp/TodoApp.Uno/.run/TodoApp.Uno.run.xml create mode 100644 samples/todoapp/TodoApp.Uno/.vscode/extensions.json create mode 100644 samples/todoapp/TodoApp.Uno/.vscode/launch.json create mode 100644 samples/todoapp/TodoApp.Uno/.vscode/settings.json create mode 100644 samples/todoapp/TodoApp.Uno/.vscode/tasks.json create mode 100644 samples/todoapp/TodoApp.Uno/.vsconfig create mode 100644 samples/todoapp/TodoApp.Uno/Directory.Build.props create mode 100644 samples/todoapp/TodoApp.Uno/Directory.Build.targets create mode 100644 samples/todoapp/TodoApp.Uno/Directory.Packages.props create mode 100644 samples/todoapp/TodoApp.Uno/TodoApp.Uno.sln create mode 100644 samples/todoapp/TodoApp.Uno/TodoApp.Uno/App.xaml create mode 100644 samples/todoapp/TodoApp.Uno/TodoApp.Uno/App.xaml.cs create mode 100644 samples/todoapp/TodoApp.Uno/TodoApp.Uno/Assets/AddItem.png create mode 100644 samples/todoapp/TodoApp.Uno/TodoApp.Uno/Assets/Icons/icon.svg create mode 100644 samples/todoapp/TodoApp.Uno/TodoApp.Uno/Assets/Icons/icon_foreground.svg create mode 100644 samples/todoapp/TodoApp.Uno/TodoApp.Uno/Assets/Images/back.svg create mode 100644 samples/todoapp/TodoApp.Uno/TodoApp.Uno/Assets/LockScreenLogo.scale-200.png create mode 100644 samples/todoapp/TodoApp.Uno/TodoApp.Uno/Assets/RefreshItems.png create mode 100644 samples/todoapp/TodoApp.Uno/TodoApp.Uno/Assets/SharedAssets.md create mode 100644 samples/todoapp/TodoApp.Uno/TodoApp.Uno/Assets/Splash/splash_screen.svg create mode 100644 samples/todoapp/TodoApp.Uno/TodoApp.Uno/Assets/SplashScreen.scale-200.png create mode 100644 samples/todoapp/TodoApp.Uno/TodoApp.Uno/Assets/Square150x150Logo.scale-200.png create mode 100644 samples/todoapp/TodoApp.Uno/TodoApp.Uno/Assets/Square44x44Logo.scale-200.png create mode 100644 samples/todoapp/TodoApp.Uno/TodoApp.Uno/Assets/Square44x44Logo.targetsize-24_altform-unplated.png create mode 100644 samples/todoapp/TodoApp.Uno/TodoApp.Uno/Assets/StoreLogo.png create mode 100644 samples/todoapp/TodoApp.Uno/TodoApp.Uno/Assets/Wide310x150Logo.scale-200.png create mode 100644 samples/todoapp/TodoApp.Uno/TodoApp.Uno/Database/AppDbContext.cs create mode 100644 samples/todoapp/TodoApp.Uno/TodoApp.Uno/Database/IDbInitializer.cs create mode 100644 samples/todoapp/TodoApp.Uno/TodoApp.Uno/Database/OfflineClientEntity.cs create mode 100644 samples/todoapp/TodoApp.Uno/TodoApp.Uno/Database/TodoItem.cs create mode 100644 samples/todoapp/TodoApp.Uno/TodoApp.Uno/GlobalUsings.cs create mode 100644 samples/todoapp/TodoApp.Uno/TodoApp.Uno/Models/AppConfig.cs create mode 100644 samples/todoapp/TodoApp.Uno/TodoApp.Uno/Package.appxmanifest create mode 100644 samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/Android/AndroidManifest.xml create mode 100644 samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/Android/Assets/AboutAssets.txt create mode 100644 samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/Android/Main.Android.cs create mode 100644 samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/Android/MainActivity.Android.cs create mode 100644 samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/Android/Resources/AboutResources.txt create mode 100644 samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/Android/Resources/values/Strings.xml create mode 100644 samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/Android/Resources/values/Styles.xml create mode 100644 samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/Android/environment.conf create mode 100644 samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/Desktop/Program.cs create mode 100644 samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/MacCatalyst/Entitlements.plist create mode 100644 samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/MacCatalyst/Info.plist create mode 100644 samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/MacCatalyst/Main.maccatalyst.cs create mode 100644 samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/MacCatalyst/Media.xcassets/LaunchImages.launchimage/Contents.json create mode 100644 samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/WebAssembly/LinkerConfig.xml create mode 100644 samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/WebAssembly/Program.cs create mode 100644 samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/WebAssembly/WasmCSS/Fonts.css create mode 100644 samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/WebAssembly/WasmScripts/AppManifest.js create mode 100644 samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/WebAssembly/manifest.webmanifest create mode 100644 samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/WebAssembly/wwwroot/staticwebapp.config.json create mode 100644 samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/WebAssembly/wwwroot/web.config create mode 100644 samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/iOS/Entitlements.plist create mode 100644 samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/iOS/Info.plist create mode 100644 samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/iOS/Main.iOS.cs create mode 100644 samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/iOS/Media.xcassets/LaunchImages.launchimage/Contents.json create mode 100644 samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/iOS/PrivacyInfo.xcprivacy create mode 100644 samples/todoapp/TodoApp.Uno/TodoApp.Uno/Presentation/Shell.xaml create mode 100644 samples/todoapp/TodoApp.Uno/TodoApp.Uno/Presentation/Shell.xaml.cs create mode 100644 samples/todoapp/TodoApp.Uno/TodoApp.Uno/Presentation/ShellViewModel.cs create mode 100644 samples/todoapp/TodoApp.Uno/TodoApp.Uno/Properties/PublishProfiles/win-arm64.pubxml create mode 100644 samples/todoapp/TodoApp.Uno/TodoApp.Uno/Properties/PublishProfiles/win-x64.pubxml create mode 100644 samples/todoapp/TodoApp.Uno/TodoApp.Uno/Properties/PublishProfiles/win-x86.pubxml create mode 100644 samples/todoapp/TodoApp.Uno/TodoApp.Uno/Properties/launchSettings.json create mode 100644 samples/todoapp/TodoApp.Uno/TodoApp.Uno/ReadMe.md create mode 100644 samples/todoapp/TodoApp.Uno/TodoApp.Uno/Services/LoggingHandler.cs create mode 100644 samples/todoapp/TodoApp.Uno/TodoApp.Uno/Strings/en/Resources.resw create mode 100644 samples/todoapp/TodoApp.Uno/TodoApp.Uno/Strings/es/Resources.resw create mode 100644 samples/todoapp/TodoApp.Uno/TodoApp.Uno/Strings/fr/Resources.resw create mode 100644 samples/todoapp/TodoApp.Uno/TodoApp.Uno/Strings/pt-BR/Resources.resw create mode 100644 samples/todoapp/TodoApp.Uno/TodoApp.Uno/Styles/ColorPaletteOverride.json create mode 100644 samples/todoapp/TodoApp.Uno/TodoApp.Uno/Styles/ColorPaletteOverride.xaml create mode 100644 samples/todoapp/TodoApp.Uno/TodoApp.Uno/TodoApp.Uno.csproj create mode 100644 samples/todoapp/TodoApp.Uno/TodoApp.Uno/ViewModels/NotificationEventArgs.cs create mode 100644 samples/todoapp/TodoApp.Uno/TodoApp.Uno/ViewModels/TodoItemViewModel.cs create mode 100644 samples/todoapp/TodoApp.Uno/TodoApp.Uno/ViewModels/TodoListViewModel.cs create mode 100644 samples/todoapp/TodoApp.Uno/TodoApp.Uno/Views/TodoListPage.xaml create mode 100644 samples/todoapp/TodoApp.Uno/TodoApp.Uno/Views/TodoListPage.xaml.cs create mode 100644 samples/todoapp/TodoApp.Uno/TodoApp.Uno/app.manifest create mode 100644 samples/todoapp/TodoApp.Uno/TodoApp.Uno/appsettings.development.json create mode 100644 samples/todoapp/TodoApp.Uno/TodoApp.Uno/appsettings.json create mode 100644 samples/todoapp/TodoApp.Uno/global.json diff --git a/samples/todoapp/TodoApp.Uno/.editorconfig b/samples/todoapp/TodoApp.Uno/.editorconfig new file mode 100644 index 00000000..b947be64 --- /dev/null +++ b/samples/todoapp/TodoApp.Uno/.editorconfig @@ -0,0 +1,167 @@ +; This file is for unifying the coding style for different editors and IDEs. +; More information at http://editorconfig.org + +# This file is the top-most EditorConfig file +root = true + +########################################## +# Common Settings +########################################## + +[*] +indent_style = space +end_of_line = crlf +trim_trailing_whitespace = true +insert_final_newline = true +charset = utf-8 + +########################################## +# File Extension Settings +########################################## + +[*.{yml,yaml}] +indent_size = 2 + +[.vsconfig] +indent_size = 2 +end_of_line = lf + +[*.sln] +indent_style = tab +indent_size = 2 + +[*.{csproj,proj,projitems,shproj}] +indent_size = 2 + +[*.{json,slnf}] +indent_size = 2 +end_of_line = lf + +[*.{props,targets}] +indent_size = 2 + +[*.xaml] +indent_size = 2 +charset = utf-8-bom + +[*.xml] +indent_size = 2 +end_of_line = lf + +[*.plist] +indent_size = 2 +indent_style = tab +end_of_line = lf + +[*.manifest] +indent_size = 2 + +[*.appxmanifest] +indent_size = 2 + +[*.{json,css,webmanifest}] +indent_size = 2 +end_of_line = lf + +[web.config] +indent_size = 2 +end_of_line = lf + +[*.sh] +indent_size = 2 +end_of_line = lf + +[*.cs] +# EOL should be normalized by Git. See https://github.com/dotnet/format/issues/1099 +end_of_line = unset + +# See https://github.com/dotnet/roslyn/issues/20356#issuecomment-310143926 +trim_trailing_whitespace = false + +tab_width = 4 +indent_size = 4 + +# Sort using and Import directives with System.* appearing first +dotnet_sort_system_directives_first = true + +# Avoid "this." and "Me." if not necessary +dotnet_style_qualification_for_field = false:suggestion +dotnet_style_qualification_for_property = false:suggestion +dotnet_style_qualification_for_method = false:suggestion +dotnet_style_qualification_for_event = false:suggestion + +#### Naming styles #### + +# Naming rules + +dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion +dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface +dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i + +dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.types_should_be_pascal_case.symbols = types +dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case + +dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members +dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case + +# Symbol specifications + +dotnet_naming_symbols.interface.applicable_kinds = interface +dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.interface.required_modifiers = + +dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum +dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.types.required_modifiers = + +dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method +dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.non_field_members.required_modifiers = + +# Naming styles + +dotnet_naming_style.begins_with_i.required_prefix = I +dotnet_naming_style.begins_with_i.required_suffix = +dotnet_naming_style.begins_with_i.word_separator = +dotnet_naming_style.begins_with_i.capitalization = pascal_case + +dotnet_naming_style.pascal_case.required_prefix = +dotnet_naming_style.pascal_case.required_suffix = +dotnet_naming_style.pascal_case.word_separator = +dotnet_naming_style.pascal_case.capitalization = pascal_case + +dotnet_naming_style.pascal_case.required_prefix = +dotnet_naming_style.pascal_case.required_suffix = +dotnet_naming_style.pascal_case.word_separator = +dotnet_naming_style.pascal_case.capitalization = pascal_case +dotnet_style_operator_placement_when_wrapping = beginning_of_line +dotnet_style_coalesce_expression = true:suggestion +dotnet_style_null_propagation = true:suggestion +dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion +dotnet_style_prefer_auto_properties = true:silent +dotnet_style_object_initializer = true:suggestion +dotnet_style_collection_initializer = true:suggestion +dotnet_style_prefer_simplified_boolean_expressions = true:suggestion +dotnet_style_prefer_conditional_expression_over_assignment = true:silent +dotnet_style_prefer_conditional_expression_over_return = true:silent +dotnet_style_explicit_tuple_names = true:suggestion +dotnet_style_prefer_inferred_tuple_names = true:suggestion + +csharp_indent_labels = one_less_than_current +csharp_using_directive_placement = outside_namespace:silent +csharp_prefer_simple_using_statement = true:suggestion +csharp_prefer_braces = true:silent +csharp_style_namespace_declarations = file_scoped:warning +csharp_style_prefer_method_group_conversion = true:silent +csharp_style_prefer_top_level_statements = true:silent +csharp_style_prefer_primary_constructors = true:suggestion +csharp_style_expression_bodied_methods = false:silent +csharp_style_expression_bodied_constructors = false:silent +csharp_style_expression_bodied_operators = false:silent +csharp_style_expression_bodied_properties = true:silent +csharp_style_expression_bodied_indexers = true:silent +csharp_style_expression_bodied_accessors = true:silent +csharp_style_expression_bodied_lambdas = true:silent +csharp_style_expression_bodied_local_functions = false:silent diff --git a/samples/todoapp/TodoApp.Uno/.gitignore b/samples/todoapp/TodoApp.Uno/.gitignore new file mode 100644 index 00000000..ef88c205 --- /dev/null +++ b/samples/todoapp/TodoApp.Uno/.gitignore @@ -0,0 +1,403 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ +[Ll]ogs/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.tlog +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*.json +coverage*.xml +coverage*.info + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio 6 auto-generated project file (contains which files were open etc.) +*.vbp + +# Visual Studio 6 workspace and project file (working project files containing files to include in project) +*.dsw +*.dsp + +# Visual Studio 6 technical files +*.ncb +*.aps + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# Visual Studio History (VSHistory) files +.vshistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +# Fody - auto-generated XML schema +FodyWeavers.xsd + +# VS Code files for those working on multiple tools +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +*.code-workspace + +# Local History for Visual Studio Code +.history/ + +# Windows Installer files from build outputs +*.cab +*.msi +*.msix +*.msm +*.msp + +# JetBrains Rider +*.sln.iml + +# Single Target Config +solution-config.props +# Publish Profiles +!**/Properties/PublishProfiles/*.pubxml \ No newline at end of file diff --git a/samples/todoapp/TodoApp.Uno/.run/Readme.md b/samples/todoapp/TodoApp.Uno/.run/Readme.md new file mode 100644 index 00000000..6e72638a --- /dev/null +++ b/samples/todoapp/TodoApp.Uno/.run/Readme.md @@ -0,0 +1,3 @@ +# About the `.run` folder + +This folder is present to add support for the [Rider IDE](https://aka.platform.uno/rider-getstarted). You can remove this folder safely if you're not using Rider. diff --git a/samples/todoapp/TodoApp.Uno/.run/TodoApp.Uno.run.xml b/samples/todoapp/TodoApp.Uno/.run/TodoApp.Uno.run.xml new file mode 100644 index 00000000..6f98af60 --- /dev/null +++ b/samples/todoapp/TodoApp.Uno/.run/TodoApp.Uno.run.xml @@ -0,0 +1,62 @@ + + + + + + + + + + diff --git a/samples/todoapp/TodoApp.Uno/.vscode/extensions.json b/samples/todoapp/TodoApp.Uno/.vscode/extensions.json new file mode 100644 index 00000000..a63ad400 --- /dev/null +++ b/samples/todoapp/TodoApp.Uno/.vscode/extensions.json @@ -0,0 +1,5 @@ +{ + "recommendations": [ + "unoplatform.vscode" + ], +} diff --git a/samples/todoapp/TodoApp.Uno/.vscode/launch.json b/samples/todoapp/TodoApp.Uno/.vscode/launch.json new file mode 100644 index 00000000..339fe686 --- /dev/null +++ b/samples/todoapp/TodoApp.Uno/.vscode/launch.json @@ -0,0 +1,56 @@ +{ + // Use IntelliSense to find out which attributes exist for C# debugging + // Use hover for the description of the existing attributes + // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md + "version": "0.2.0", + "configurations": [ + { + "name": "Uno Platform Mobile Debug", + "type": "Uno", + "request": "launch", + // any Uno* task will do, this is simply to satisfy vscode requirement when a launch.json is present + "preLaunchTask": "Uno: android | Debug | android-x64" + }, + { + // Use IntelliSense to find out which attributes exist for C# debugging + // Use hover for the description of the existing attributes + // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md + "name": "Uno Platform WebAssembly Debug (Chrome)", + "type": "chrome", + "request": "launch", + "url": "http://localhost:5000", + "webRoot": "${workspaceFolder}/TodoApp.Uno", + "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", + "timeout": 30000, + "preLaunchTask": "build-wasm", + "server": { + "runtimeExecutable": "dotnet", + "program": "run", + "args": ["--no-build","-f","net8.0-browserwasm","--launch-profile", "TodoApp.Uno (WebAssembly)"], + "outputCapture": "std", + "timeout": 30000, + "cwd": "${workspaceFolder}/TodoApp.Uno" + } + }, + { + // Use IntelliSense to find out which attributes exist for C# debugging + // Use hover for the description of the existing attributes + // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md + "name": "Uno Platform Desktop Debug", + "type": "coreclr", + "request": "launch", + "preLaunchTask": "build-desktop", + // If you have changed target frameworks, make sure to update the program path. + "program": "${workspaceFolder}/TodoApp.Uno/bin/Debug/net8.0-desktop/TodoApp.Uno.dll", + "args": [], + "launchSettingsProfile": "TodoApp.Uno (Desktop)", + "env": { + "DOTNET_MODIFIABLE_ASSEMBLIES": "debug" + }, + "cwd": "${workspaceFolder}/TodoApp.Uno", + // For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console + "console": "internalConsole", + "stopAtEntry": false + }, + ] +} diff --git a/samples/todoapp/TodoApp.Uno/.vscode/settings.json b/samples/todoapp/TodoApp.Uno/.vscode/settings.json new file mode 100644 index 00000000..3405922d --- /dev/null +++ b/samples/todoapp/TodoApp.Uno/.vscode/settings.json @@ -0,0 +1,10 @@ +{ + "explorer.fileNesting.enabled": true, + "explorer.fileNesting.expand": false, + "explorer.fileNesting.patterns": { + "*.xaml": "$(capture).xaml.cs" + }, + "files.associations": { + "global.json": "jsonc" + } +} diff --git a/samples/todoapp/TodoApp.Uno/.vscode/tasks.json b/samples/todoapp/TodoApp.Uno/.vscode/tasks.json new file mode 100644 index 00000000..6d08f7ee --- /dev/null +++ b/samples/todoapp/TodoApp.Uno/.vscode/tasks.json @@ -0,0 +1,57 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "build-wasm", + "command": "dotnet", + "type": "process", + "args": [ + "build", + "${workspaceFolder}/TodoApp.Uno/TodoApp.Uno.csproj", + "/property:GenerateFullPaths=true", + "/property:TargetFramework=net8.0-browserwasm", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "publish-wasm", + "command": "dotnet", + "type": "process", + "args": [ + "publish", + "${workspaceFolder}/TodoApp.Uno/TodoApp.Uno.csproj", + "/property:GenerateFullPaths=true", + "/property:TargetFramework=net8.0-browserwasm", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "build-desktop", + "command": "dotnet", + "type": "process", + "args": [ + "build", + "${workspaceFolder}/TodoApp.Uno/TodoApp.Uno.csproj", + "/property:GenerateFullPaths=true", + "/property:TargetFramework=net8.0-desktop", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "publish-desktop", + "command": "dotnet", + "type": "process", + "args": [ + "publish", + "${workspaceFolder}/TodoApp.Uno/TodoApp.Uno.csproj", + "/property:GenerateFullPaths=true", + "/property:TargetFramework=net8.0-desktop", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + } + ] +} diff --git a/samples/todoapp/TodoApp.Uno/.vsconfig b/samples/todoapp/TodoApp.Uno/.vsconfig new file mode 100644 index 00000000..0439670d --- /dev/null +++ b/samples/todoapp/TodoApp.Uno/.vsconfig @@ -0,0 +1,34 @@ +{ + "version": "1.0", + "components": [ + "Microsoft.VisualStudio.Component.CoreEditor", + "Microsoft.VisualStudio.Workload.CoreEditor", + "Microsoft.NetCore.Component.SDK", + "Microsoft.NetCore.Component.DevelopmentTools", + "Microsoft.Net.ComponentGroup.DevelopmentPrerequisites", + "Microsoft.VisualStudio.Component.TextTemplating", + "Microsoft.VisualStudio.ComponentGroup.WebToolsExtensions", + "Microsoft.NetCore.Component.Web", + "Microsoft.VisualStudio.Component.IISExpress", + "Component.Microsoft.Web.LibraryManager", + "Microsoft.VisualStudio.ComponentGroup.Web", + "Microsoft.VisualStudio.Component.Web", + "Microsoft.VisualStudio.ComponentGroup.Web.Client", + "Microsoft.VisualStudio.Workload.NetWeb", + "Microsoft.VisualStudio.ComponentGroup.WebToolsExtensions.TemplateEngine", + "Microsoft.VisualStudio.ComponentGroup.MSIX.Packaging", + "Microsoft.VisualStudio.Component.ManagedDesktop.Prerequisites", + "Microsoft.VisualStudio.Component.Debugger.JustInTime", + "Microsoft.VisualStudio.Workload.ManagedDesktop", + "Component.Xamarin.RemotedSimulator", + "Microsoft.VisualStudio.Component.MonoDebugger", + "Microsoft.VisualStudio.ComponentGroup.Maui.All", + "Component.Android.SDK34", + "Component.OpenJDK", + "Microsoft.VisualStudio.Workload.NetCrossPlat", + "Microsoft.VisualStudio.Workload.NetCoreTools" + ], + "extensions": [ + "https://marketplace.visualstudio.com/items?itemName=unoplatform.uno-platform-addin-2022" + ] +} diff --git a/samples/todoapp/TodoApp.Uno/Directory.Build.props b/samples/todoapp/TodoApp.Uno/Directory.Build.props new file mode 100644 index 00000000..3e51b4ea --- /dev/null +++ b/samples/todoapp/TodoApp.Uno/Directory.Build.props @@ -0,0 +1,15 @@ + + + enable + enable + true + true + + $(NoWarn);NU1507;NETSDK1201;PRI257 + + diff --git a/samples/todoapp/TodoApp.Uno/Directory.Build.targets b/samples/todoapp/TodoApp.Uno/Directory.Build.targets new file mode 100644 index 00000000..f75adf7e --- /dev/null +++ b/samples/todoapp/TodoApp.Uno/Directory.Build.targets @@ -0,0 +1,2 @@ + + diff --git a/samples/todoapp/TodoApp.Uno/Directory.Packages.props b/samples/todoapp/TodoApp.Uno/Directory.Packages.props new file mode 100644 index 00000000..f0ec5d86 --- /dev/null +++ b/samples/todoapp/TodoApp.Uno/Directory.Packages.props @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/samples/todoapp/TodoApp.Uno/TodoApp.Uno.sln b/samples/todoapp/TodoApp.Uno/TodoApp.Uno.sln new file mode 100644 index 00000000..cc4fa640 --- /dev/null +++ b/samples/todoapp/TodoApp.Uno/TodoApp.Uno.sln @@ -0,0 +1,47 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.10.35201.131 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TodoApp.Uno", "TodoApp.Uno\TodoApp.Uno.csproj", "{5FD4876C-302E-42DF-B28B-55035009E545}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{F20ED0E3-BD89-4202-A1C8-E809AA315AFB}" + ProjectSection(SolutionItems) = preProject + .gitignore = .gitignore + Directory.Build.props = Directory.Build.props + Directory.Build.targets = Directory.Build.targets + Directory.Packages.props = Directory.Packages.props + global.json = global.json + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "library", "library", "{0AAB65A5-8A90-47AF-AAED-AF27E82D50A4}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CommunityToolkit.Datasync.Client", "..\..\..\src\CommunityToolkit.Datasync.Client\CommunityToolkit.Datasync.Client.csproj", "{2D6F113F-D3A1-43A5-BF57-E72E5D5F5963}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {5FD4876C-302E-42DF-B28B-55035009E545}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5FD4876C-302E-42DF-B28B-55035009E545}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5FD4876C-302E-42DF-B28B-55035009E545}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {5FD4876C-302E-42DF-B28B-55035009E545}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5FD4876C-302E-42DF-B28B-55035009E545}.Release|Any CPU.Build.0 = Release|Any CPU + {5FD4876C-302E-42DF-B28B-55035009E545}.Release|Any CPU.Deploy.0 = Release|Any CPU + {2D6F113F-D3A1-43A5-BF57-E72E5D5F5963}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2D6F113F-D3A1-43A5-BF57-E72E5D5F5963}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2D6F113F-D3A1-43A5-BF57-E72E5D5F5963}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2D6F113F-D3A1-43A5-BF57-E72E5D5F5963}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {2D6F113F-D3A1-43A5-BF57-E72E5D5F5963} = {0AAB65A5-8A90-47AF-AAED-AF27E82D50A4} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {EA315B6A-4F6C-4482-A88B-61900C1B6934} + EndGlobalSection +EndGlobal diff --git a/samples/todoapp/TodoApp.Uno/TodoApp.Uno/App.xaml b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/App.xaml new file mode 100644 index 00000000..fe2094c7 --- /dev/null +++ b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/App.xaml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + diff --git a/samples/todoapp/TodoApp.Uno/TodoApp.Uno/App.xaml.cs b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/App.xaml.cs new file mode 100644 index 00000000..9a55a5af --- /dev/null +++ b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/App.xaml.cs @@ -0,0 +1,134 @@ +using System; +using Microsoft.Data.Sqlite; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; +using TodoApp.Uno.Database; +using TodoApp.Uno.ViewModels; +using TodoApp.Uno.Views; +using Uno.Resizetizer; + +namespace TodoApp.Uno; +public partial class App : Application +{ + /// + /// Initializes the singleton application object. This is the first line of authored code + /// executed, and as such is the logical equivalent of main() or WinMain(). + /// + public App() + { + this.InitializeComponent(); + + + } + + protected Window? MainWindow { get; private set; } + public IHost? Host { get; private set; } + + private SqliteConnection dbConnection; + + protected async override void OnLaunched(LaunchActivatedEventArgs args) + { + AppContext.SetSwitch("System.Reflection.NullabilityInfoContext.IsSupported", true); + + this.dbConnection = new SqliteConnection("Data Source=:memory:"); + this.dbConnection.Open(); + + var builder = this.CreateBuilder(args) + // Add navigation support for toolkit controls such as TabBar and NavigationView + .UseToolkitNavigation() + .Configure(host => host +#if DEBUG + // Switch to Development environment when running in DEBUG + .UseEnvironment(Environments.Development) +#endif + .UseLogging(configure: (context, logBuilder) => + { + // Configure log levels for different categories of logging + logBuilder + .SetMinimumLevel( + context.HostingEnvironment.IsDevelopment() ? + LogLevel.Information : + LogLevel.Warning) + + // Default filters for core Uno Platform namespaces + .CoreLogLevel(LogLevel.Warning); + + // Uno Platform namespace filter groups + // Uncomment individual methods to see more detailed logging + //// Generic Xaml events + //logBuilder.XamlLogLevel(LogLevel.Debug); + //// Layout specific messages + //logBuilder.XamlLayoutLogLevel(LogLevel.Debug); + //// Storage messages + //logBuilder.StorageLogLevel(LogLevel.Debug); + //// Binding related messages + //logBuilder.XamlBindingLogLevel(LogLevel.Debug); + //// Binder memory references tracking + //logBuilder.BinderMemoryReferenceLogLevel(LogLevel.Debug); + //// DevServer and HotReload related + //logBuilder.HotReloadCoreLogLevel(LogLevel.Information); + //// Debug JS interop + //logBuilder.WebAssemblyLogLevel(LogLevel.Debug); + + }, enableUnoLogging: true) + .UseConfiguration(configure: configBuilder => + configBuilder + .EmbeddedSource() + .Section() + ) + + .ConfigureServices((context, services) => + { + // TODO: Register your services + //services.AddSingleton(); + services.AddDbContext(options => options.UseSqlite(this.dbConnection)); + services.AddScoped(); + services.AddTransient(); + + }) + .UseNavigation(RegisterRoutes) + ); + MainWindow = builder.Window; + +#if DEBUG + MainWindow.EnableHotReload(); +#endif + MainWindow.SetWindowIcon(); + + // We have to build here so that the services are initialized and we can call InitializeDatabase + // before navigating. This enables us to load the data when the page is loaded + Host = builder.Build(); + + InitializeDatabase(); + + // We still make this navigation call so we use the Uno Navigation extension, which automatically wires + // up view models with their page using the ViewMap and RouteMap below. + Host = await builder.NavigateAsync(); + + } + + private void InitializeDatabase() + { + IDbInitializer? initializer = Host?.Services?.GetRequiredService(); + initializer?.Initialize(); + } + + private static void RegisterRoutes(IViewRegistry views, IRouteRegistry routes) + { + views.Register( + new ViewMap(ViewModel: typeof(ShellViewModel)), + new ViewMap() + ); + + routes.Register( + new RouteMap("", View: views.FindByViewModel(), + Nested: + [ + new ("TodoList", View: views.FindByViewModel(), IsDefault: true) + ] + ) + ); + } +} diff --git a/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Assets/AddItem.png b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Assets/AddItem.png new file mode 100644 index 0000000000000000000000000000000000000000..336647933fe4599d80f75fdb1fde84a11b007f44 GIT binary patch literal 373 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpTCmUKs7M+SzC{oH>NS%G|oWRD45dJguM!v-tY$DUh!@P+6=(yLU`z6LcLCBs@Y8vBJ&@uo z@Q5sCVBk9f!i-b3`J{n@L7py-AsP4HUU%d>ARyx4`1bGnHR&53xLR!%yWh>5%)l@= z{qeoeN7j@l9}r~9fGPW`{);2J(GBA);em4n4LvDUbW?Cg~ z4LNmTdO!`5ARB`7(@M${i&7cN%ggmL^RkPR6AM!H@{7`Ezq647Dq`?-^>bP0l+XkK DhrDoO literal 0 HcmV?d00001 diff --git a/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Assets/Icons/icon.svg b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Assets/Icons/icon.svg new file mode 100644 index 00000000..a15af53a --- /dev/null +++ b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Assets/Icons/icon.svg @@ -0,0 +1,42 @@ + + + + + + diff --git a/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Assets/Icons/icon_foreground.svg b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Assets/Icons/icon_foreground.svg new file mode 100644 index 00000000..8ffc41ae --- /dev/null +++ b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Assets/Icons/icon_foreground.svg @@ -0,0 +1,137 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Assets/Images/back.svg b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Assets/Images/back.svg new file mode 100644 index 00000000..bcd7851b --- /dev/null +++ b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Assets/Images/back.svg @@ -0,0 +1,3 @@ + + + diff --git a/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Assets/LockScreenLogo.scale-200.png b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Assets/LockScreenLogo.scale-200.png new file mode 100644 index 0000000000000000000000000000000000000000..7440f0d4bf7c7e26e4e36328738c68e624ee851e GIT binary patch literal 432 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezr3(FqV6|IEGZ*x-#9g>~Mkr+x6^F zy~CDX2QIMs&Gcs3RnRBoxBA!*(Mfw0KTCYuYk0WlEIV>qBmPl! zq4ukrvfADX@#p8fbLY(H47N+k`FZ(FZh?cDro7>{8mkBO3>^oaIx`3!Jl)Qq)HI!+ z(S=1{o~eT)&W^=Ea8C`-17(Jv5(nHFJ{dOjGdxLVkY_y6&S1whfuFI4MM0kF0f&cO zPDVpV%nz;Id$>+0Ga5e9625-JcI)oq=#Pa3p^>8BB}21BUw@eN!-6@w%X+^`+Vn?! zryu|3T>kVWNBYyBc=7Y6H#s1Ah!OI_nezW zXTqOdkv2Az6KKBV=$yHdF^R3Fqw(TZEoNSZX>reXJ#bwX42%f|Pgg&ebxsLQ010xn AssI20 literal 0 HcmV?d00001 diff --git a/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Assets/RefreshItems.png b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Assets/RefreshItems.png new file mode 100644 index 0000000000000000000000000000000000000000..51748eddc844cf9b3171899c9a02611217e23c78 GIT binary patch literal 866 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpTCmUKs7M+SzC{oH>NS%G|oWRD45dJguM!v-tY$DUh!@P+6=(yLU`z6LcLCBs@Y8vBJ&@uo z@Q5sCVBk9f!i-b3`J@>bnCv}W978hhy}fZdOTVI(R zb=+pb{OouK!Mk2Aynz#ExL=qc9&n*mqCoJD_o8E`cNn>SU@N@Hd1RK{+nMX$Mc$}i z;mZ4E<@?o^rLUY^!9b?Uu&2;xahv?7$@({aW&@IFrpSsOi3o zd*6(?Gc*q$Snw;$cxJH8SMF^F%)+mV_f6fB8CE00y!Vy)N@LZ|{-gv84h!|@t(}T? zU5y_V9%OVrS}ZYxk4a815UA>5o3Vs)#>^Uio+oSV0#8OCzwIZ+%zlsI-Ps>-%b`gKpys_^H#~#nWfsbMs+5Fg(uc$1)s&R+E zX@9JlShw!0{4DdNbLSeKRHl4o2!1r>A)gILlKzk1-LBp-!TZnNKb5)2`IqgFpq!5z z$o@;tw_+r)1~PWvHx?cu5?b2o=Ryk8L5XgR;t?oQ^V z6X`M2mxSqEb1}K3Y^g4Lr0&hJv_FU3YbMxiw4Y>?p(|#+UK9lWGw)|yyt15q%7m}o z!1SeB;u=wsl30>zm0Xkxq!^40j0|)QjdTqyLX3>842-OdEwl{`tPBh;#y%HA(U6;; zl9^VCTf+i|_*Fm+k{}y`^V3So6N^$A%FE03GV`*FlM@S4_413-XTP(N0xDwgboFyt I=akR{0ExO?!vFvP literal 0 HcmV?d00001 diff --git a/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Assets/SharedAssets.md b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Assets/SharedAssets.md new file mode 100644 index 00000000..1b84a74a --- /dev/null +++ b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Assets/SharedAssets.md @@ -0,0 +1,32 @@ +# Shared Assets + +See documentation about assets here: https://github.com/unoplatform/uno/blob/master/doc/articles/features/working-with-assets.md + +## Here is a cheat sheet + +1. Add the image file to the `Assets` directory of a shared project. +2. Set the build action to `Content`. +3. (Recommended) Provide an asset for various scales/dpi + +### Examples + +```text +\Assets\Images\logo.scale-100.png +\Assets\Images\logo.scale-200.png +\Assets\Images\logo.scale-400.png + +\Assets\Images\scale-100\logo.png +\Assets\Images\scale-200\logo.png +\Assets\Images\scale-400\logo.png +``` + +### Table of scales + +| Scale | WinUI | iOS/MacCatalyst | Android | +|-------|:-----------:|:---------------:|:-------:| +| `100` | scale-100 | @1x | mdpi | +| `125` | scale-125 | N/A | N/A | +| `150` | scale-150 | N/A | hdpi | +| `200` | scale-200 | @2x | xhdpi | +| `300` | scale-300 | @3x | xxhdpi | +| `400` | scale-400 | N/A | xxxhdpi | diff --git a/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Assets/Splash/splash_screen.svg b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Assets/Splash/splash_screen.svg new file mode 100644 index 00000000..8ffc41ae --- /dev/null +++ b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Assets/Splash/splash_screen.svg @@ -0,0 +1,137 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Assets/SplashScreen.scale-200.png b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Assets/SplashScreen.scale-200.png new file mode 100644 index 0000000000000000000000000000000000000000..32f486a86792a5e34cd9a8261b394c49b48f86be GIT binary patch literal 5372 zcmd5=Z){Ul6u)iv53sCbIJKLzl(EF%0tzcEY@|pLrfgF~2Dk$KFtU+$kbYqDN5W%7 z>?DBo!@y06eh{Oux>brrNT^{MO(tkiC@nH(2}}G_1|uvcMD(0{?|W^Gxo!tG~hW2Rn&7%b`-Kd_^`BCrb>XVtRKONoEw6%NswzMxk+kbocuk&}kJ#hSP z>8uR{r%LJ?I#)aaWW;uEixz+DzyTpp)MTEo&R%nEA92~g{^eXQwKV1m{xl5K<@k3FacT+Z zrwfy=VocIptI>t%@p5a;Rt=WXVnU;2SUdr7Yk>gw_2z_ICK^23$|Cg7{3Eg5j@N*F zetT?>30(*S_7ld-Yt&u7T{(hEjjM#vPlXibjrq?;pBBx3*>_2~VFGdsH5L zQKme_LAebV}aOX#+rQafZtp+4jK}V!>pn1?+eUH$0%6}z(Kul9!^2z zXi+d@jnx)RW7!j9uFEdv5N&1sCW#Z6Ej5Y7c;o28Q7i%U0(2v5J>o9P zl$#C8&9r)nL;?J65^GIeSOHYr3B7}}R~}@2Tx_xo5*YdU#g1bO}95cq69J!efdlE+xj1qG#ZUqh~1Sn#dBsZfDvcupM zXOFoyJ0$s+RHQKpzr#T>c&EUbq)lGvZDxuI!9unMI=#;ob2&gT)WqOjt6^X`_N21r`&eh6h0xpT!n6Z9rvE&+bFU$vTJO2? z#^tBNOx*2N)~(+TH8d>ep6``8V=3JEfdUUahVZ-xN+k#V&32x|%qnX(XBii5<@`%^ zV#Ky4f1!6RJqJXBU3M4~tmj2;;r`8_j&w?h5g35uMH(QI$Xpesb zG|*XRT?kh6M(jj0Y&vF^M*9g-iDMW%G%9%Pa}6ERQ9b0%6z1v}Ja=|L@G#5ZI>JS9 z*(K12nMvS?oyG8s9|q~{w`ajtI`KSHSiJ;)%X@M&eCE(VqI#F(XL?L@A$TUT?6av5 zkPWIR391XjSC%d6L}7F71Qpw(;c_~)mSZo-&Fm^FHlPX|Fu}1B3E+9j0}o1a(4HFS zUItE22CC%XZi!b4%~vWn>rpV9&CUEvt!?Q{Pr*L~51&(0Sz{VJJFrJtWw2PwXd|J{ zgH%3vAY$flodH=4&ruCHX;(3t;o}n?!0~3EE|5qRz$!VIkphxa4@_jyfiE9m;0 zjcYJ2;26N&MTB8X4joZ&?SUe|VS$^I%dt{!c2O;%3SdqW@K_14r8eyC1s&VcU5+2~ z_O1Cc*w|aIA=VC6AT_EFoL}W#Rl;7CZe)e}RS*e;8CVyM6i8a(yO@|S709VYY(y2g zc+QxB>Bw^B^2Db~*o)=i$m-aUNQFkYy5(eJW$cez>C{POds*p3cy#tHnvActP;dBP zdEf)C;lq}&#PE?XCD<~ngrzYUg|nS`#MS`Rd7cT>xlR19P#~4Qg5!J}@glCUq)z_2 zjvyv%aSq0 z)njao1dV0XNw&c@qmj1e*jgQ$l@_urW5G4RSY#rT1z`#%3;{EB`aJK|TH^lb_3nAT z-_Q4X-(K&IS8UyqsnjYdippfmN-HT!X2MT;Dpcy~-#$k6V z|MR4vU#O&p7TC46pTflb3 zoUJ;ZRf#&8&EwXy5s%!&(q6cN62swD#FH%O-RJsjWPZN3^^@FCIQ&MxXIFo7!I#VI zkpIstuWqUV5uhgs07?k$*!`uiZ=5b#$lI|0c+XJvj(}zSE3MN#EyOK zql(#yA}~Ibl*r(s1}Z^5mmn*-n93g?-ccM+^PN?6HH~h0hjy6@XY*^i<-V)+OZ;p7 z7j`p_sT55xnYsedNIIel^QIIg7i@`2Qi}x5$!tk29$2OQI zs^kQXAKE}5ZJu$)2@Dxn?}}O@f@6@^!%9Tj+o>=jd!^ZuvBE4jb4g}Z5WMBtcmy^~ zoFGVS5|0FA!(1Q%fL?Bj*L+9ZL{mjSO8lzqrQ0UCZ)X zPwk$1HNFgaK%NxGpuXz}#ywXvf2JQ?BQ5uOZM2up4S#ieaxS$!o9o6Z=czNQb} zwAh|xLZ>+WyN%o?^uCAQw&&4o?S$DJ`WP(Hr*grL*qNXlqU0osCQ(Up5F(^$Z5;n&oJIO4uF`k&QL*j{f zU=;#MZ5{@b%qMbjTB3dh-5#mqY>%{0jgS+WdHyG literal 0 HcmV?d00001 diff --git a/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Assets/Square44x44Logo.scale-200.png b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Assets/Square44x44Logo.scale-200.png new file mode 100644 index 0000000000000000000000000000000000000000..f713bba67f551ef91020b75716a4dc8ebd744b1c GIT binary patch literal 637 zcmeAS@N?(olHy`uVBq!ia0vp^5g^RL1|$oo8kjIJFu8cTIEGZ*dUI*J;2{SImxtDO zm%3!R$UazoY}x{$j0P5ABYXWr(l=jxJ6ps1W{tV=^>{Dl><3nv3A}sm=EZ)#l3`NR zpZda3^rNox*D1%NC98Z~L*6zipLw~Gxn&(Y-;KmJ+aR6eLabU-L#y8HW%7P-E_-VlLqIabbHPHKT*)fT@9iWJ7iWgOT9%0}Lrj>lztPxWq6sPw3pi z#-<=#$jjrP_DD*i!RLsn0mIA=>4~N)IMYWIf=j%-zuKCdMG%tHYot70D1| zvWa0wMhauW#S>1CnI_;>!1Q3zMA17@DOVq{MQ+{U7^a&yA+%dMCG;WNPV0i;w$tu; zX^b}UKziPM)(<;)ruW;-`)bBN+rQNM*Zs_>?n$|FVFo-e*PZb*@U7VAd+tHb4e?=Blc~}S6K)wL}r*Gf`BM#QB z+y>N$mCswb4d{^{S9v_!eQj4fTRMOwOCi?lSk9%<=vAz}jM-*PQtH@Odn1LZcd^j#o> hW$4xn+CT+ep9lJ{OAO?njobhL002ovPDHLkV1nYebbkN< literal 0 HcmV?d00001 diff --git a/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Assets/StoreLogo.png b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Assets/StoreLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..a4586f26bdf7841cad10f39cdffe2aca3af252c1 GIT binary patch literal 456 zcmeAS@N?(olHy`uVBq!ia0vp^Mj*_=1|;R|J2o;fF!p=8IEGZ*dUM0H=rDtTTVkd2 z(%lbKn@VS_lUaADVB&;Z6F#LM+mPsa?e>FnHo;HND^!P`-lX%BH~FOg%y&x+t*x!? zg$#_1A1kgsSvO(fw`bOmo;lrJX8byO1j^gf7qohR%mmt z@L)WX;>gqgK|tWJvQ5j;4;=gt4HXVKSMYRv5RhY5vS~TqfK_NAP*r{h!!g^BZ;w4r z7CGdsai)y;fJQc`7{Zc2b==h%o`Op$|bg6a&nL{*m7-=0>k4M4-PXlU;G-?%*(*g>iFt^ U$m#7DfHB12>FVdQ&MBb@0G`#n8vpc0sq%A~kJcD9FY~qQRMt?ZR3YyDZt}Od;|mgpc{2dv9AHF){kXU%k({ z=Y8JidEayHTkG@twPZ|U3_^%3ct-OgLSiFAqDN!|tbCX@c@?4P`2x*TMK!+Q4b?k0 ziW7!!KF6dPWcF<%I|iznM~`QJ_V7sHGV_D`dhgpA9Vd@&X}ErK+j~_rdv;Bp?OA@a zFXOk7eWOJe5NcK;6h$FaM&7JxNc#-@QTwzW6x#d_zmQNkz5) zPI;kh;3d;5UCJU+9a(cOxX(|edWoOiAEdGU#kPJ&xnc2||3vDbuhBCkj-pb0as$Zl z5;}4n=**n6(1g`JEtSy;SG6X;#-F~Oz3lESG2b5`j@wAwY4Yp<=4Xeb>iH=6aicF?DxD&q{`!&}ct zBI)aycwuobQAf&678Uf+Mmh-@9RUhyH~>?w0dixO0#jZjEc9R^=5NZw=|a(kcB?9^ zfnTiEFXp-q#B;Tn>(O%$A*ud^Rg&eVH6Y_5Y%!E39RR&s?XpG`gKwU!6FE1 z7X)DC7)*(5g}lh`4`{i~DZcWupZI`K)_4P)VE{@gc7@Xsd^86zl~_mOYH?I4!aGeX z^E(_=L6?PgveDQ+r%P@UISEXrkn`LHJZ##+!-anV>6h)IkKp;E@p8+3&(5%kS2)ld*J*rJccZM0iyaAx7+F~GW1UWFK&3X$PE1^}NH zgAG9ck5K!{07OwU@j@Do>TbH=CDEo#4m0cEyAuXy_<&jlzJVcKweSJ5 z&=q~iIn18$w8yb=rmEmHxVEUA^?RwnB?6Qlp1os8@*dWTGL2bhzZ!s*xqScR?EPL` zo(JwNdKUUYy7GtvZ3asXm)cgFvCx9EmAi;|w=a0iGiv%%VYKh`P0Wma4y`Xyx|T~( zAmfGbgbEEC7)j8b@WA@+5W3a61HJXC1dX@6_T|Czk0I0zBk%tnW~()VWITGI!`$c< gARL?UBrYYkwoDw4eo*CrzXGTrZ@;GF>596)00d&n@&Et; literal 0 HcmV?d00001 diff --git a/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Database/AppDbContext.cs b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Database/AppDbContext.cs new file mode 100644 index 00000000..b29abca4 --- /dev/null +++ b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Database/AppDbContext.cs @@ -0,0 +1,65 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using CommunityToolkit.Datasync.Client.Http; +using CommunityToolkit.Datasync.Client.Offline; +using Microsoft.EntityFrameworkCore; +using TodoApp.Uno.Services; + +namespace TodoApp.Uno.Database; + +public class AppDbContext(DbContextOptions options) : DbContext(options) +//public class AppDbContext(DbContextOptions options) : OfflineDbContext(options) +{ + public DbSet TodoItems => Set(); + + //protected override void OnDatasyncInitialization(DatasyncOfflineOptionsBuilder optionsBuilder) + //{ + // HttpClientOptions clientOptions = new() + // { + // Endpoint = new Uri("https://yoursite.azurewebsites.net/"), + // HttpPipeline = [new LoggingHandler()] + // }; + // _ = optionsBuilder.UseHttpClientOptions(clientOptions); + //} + + public async Task SynchronizeAsync(CancellationToken cancellationToken = default) + { + //PushResult pushResult = await this.PushAsync(cancellationToken); + //if (!pushResult.IsSuccessful) + //{ + // throw new ApplicationException($"Push failed: {pushResult.FailedRequests.FirstOrDefault().Value.ReasonPhrase}"); + //} + + //PullResult pullResult = await this.PullAsync(cancellationToken); + //if (!pullResult.IsSuccessful) + //{ + // throw new ApplicationException($"Pull failed: {pullResult.FailedRequests.FirstOrDefault().Value.ReasonPhrase}"); + //} + } +} + +/// +/// Use this class to initialize the database. In this sample, we just create +/// the database using . However, you +/// may want to use migrations. +/// +/// The context for the database. +public class DbContextInitializer(AppDbContext context) : IDbInitializer +{ + /// + public void Initialize() + { + _ = context.Database.EnsureCreated(); + Task.Run(async () => await context.SynchronizeAsync()); + } + + /// + public Task InitializeAsync(CancellationToken cancellationToken = default) + => context.Database.EnsureCreatedAsync(cancellationToken); +} diff --git a/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Database/IDbInitializer.cs b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Database/IDbInitializer.cs new file mode 100644 index 00000000..2f845444 --- /dev/null +++ b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Database/IDbInitializer.cs @@ -0,0 +1,26 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Threading; +using System.Threading.Tasks; + +namespace TodoApp.Uno.Database; + +/// +/// An interface to initialize a database. +/// +public interface IDbInitializer +{ + /// + /// Synchronously initialize the database. + /// + void Initialize(); + + /// + /// Asynchronously initialize the database. + /// + /// A to observe. + /// A task that resolves when complete. + Task InitializeAsync(CancellationToken cancellationToken = default); +} diff --git a/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Database/OfflineClientEntity.cs b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Database/OfflineClientEntity.cs new file mode 100644 index 00000000..cf244bf9 --- /dev/null +++ b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Database/OfflineClientEntity.cs @@ -0,0 +1,20 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.ComponentModel.DataAnnotations; + +namespace TodoApp.Uno.Database; + +/// +/// An abstract class for working with offline entities. +/// +public abstract class OfflineClientEntity +{ + [System.ComponentModel.DataAnnotations.Key] + public string Id { get; set; } + public DateTimeOffset? UpdatedAt { get; set; } + public string? Version { get; set; } + public bool Deleted { get; set; } +} diff --git a/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Database/TodoItem.cs b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Database/TodoItem.cs new file mode 100644 index 00000000..bc0ecba1 --- /dev/null +++ b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Database/TodoItem.cs @@ -0,0 +1,16 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Text.Json; + +namespace TodoApp.Uno.Database; + +public class TodoItem : OfflineClientEntity +{ + public string Title { get; set; } = string.Empty; + public bool IsComplete { get; set; } = false; + + public override string ToString() + => JsonSerializer.Serialize(this); +} diff --git a/samples/todoapp/TodoApp.Uno/TodoApp.Uno/GlobalUsings.cs b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/GlobalUsings.cs new file mode 100644 index 00000000..b3669d5f --- /dev/null +++ b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/GlobalUsings.cs @@ -0,0 +1,11 @@ +global using System.Collections.Immutable; +global using CommunityToolkit.Mvvm.ComponentModel; +global using CommunityToolkit.Mvvm.Input; +global using Microsoft.Extensions.DependencyInjection; +global using Microsoft.Extensions.Hosting; +global using Microsoft.Extensions.Localization; +global using Microsoft.Extensions.Logging; +global using Microsoft.Extensions.Options; +global using TodoApp.Uno.Models; +global using TodoApp.Uno.Presentation; +global using ApplicationExecutionState = Windows.ApplicationModel.Activation.ApplicationExecutionState; diff --git a/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Models/AppConfig.cs b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Models/AppConfig.cs new file mode 100644 index 00000000..74aab031 --- /dev/null +++ b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Models/AppConfig.cs @@ -0,0 +1,6 @@ +namespace TodoApp.Uno.Models; + +public record AppConfig +{ + public string? Environment { get; init; } +} diff --git a/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Package.appxmanifest b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Package.appxmanifest new file mode 100644 index 00000000..9ef38146 --- /dev/null +++ b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Package.appxmanifest @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/Android/AndroidManifest.xml b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/Android/AndroidManifest.xml new file mode 100644 index 00000000..95ae0753 --- /dev/null +++ b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/Android/AndroidManifest.xml @@ -0,0 +1,4 @@ + + + + diff --git a/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/Android/Assets/AboutAssets.txt b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/Android/Assets/AboutAssets.txt new file mode 100644 index 00000000..89ab409d --- /dev/null +++ b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/Android/Assets/AboutAssets.txt @@ -0,0 +1,22 @@ +To add cross-platform image assets for your Uno Platform app, use the Assets folder +in the shared project instead. Assets in this folder are Android-only assets. + +Any raw assets you want to be deployed with your application can be placed in +this directory (and child directories) and given a Build Action of "AndroidAsset". + +These files will be deployed with your package and will be accessible using Android's +AssetManager, like this: + +public class ReadAsset : Activity +{ + protected override void OnCreate (Bundle bundle) + { + base.OnCreate (bundle); + + InputStream input = Assets.Open ("my_asset.txt"); + } +} + +Additionally, some Android functions will automatically load asset files: + +Typeface tf = Typeface.CreateFromAsset (Context.Assets, "fonts/samplefont.ttf"); diff --git a/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/Android/Main.Android.cs b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/Android/Main.Android.cs new file mode 100644 index 00000000..8fc5119a --- /dev/null +++ b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/Android/Main.Android.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Android.App; +using Android.Content; +using Android.OS; +using Android.Runtime; +using Android.Views; +using Android.Widget; +using Com.Nostra13.Universalimageloader.Core; +using Microsoft.UI.Xaml.Media; + +namespace TodoApp.Uno.Droid; +[global::Android.App.ApplicationAttribute( + Label = "@string/ApplicationName", + Icon = "@mipmap/icon", + LargeHeap = true, + HardwareAccelerated = true, + Theme = "@style/AppTheme" +)] +public class Application : Microsoft.UI.Xaml.NativeApplication +{ + + public Application(IntPtr javaReference, JniHandleOwnership transfer) + : base(() => new App(), javaReference, transfer) + { + ConfigureUniversalImageLoader(); + } + + private static void ConfigureUniversalImageLoader() + { + // Create global configuration and initialize ImageLoader with this config + ImageLoaderConfiguration config = new ImageLoaderConfiguration + .Builder(Context) + .Build(); + + ImageLoader.Instance.Init(config); + + ImageSource.DefaultImageLoader = ImageLoader.Instance.LoadImageAsync; + } +} + diff --git a/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/Android/MainActivity.Android.cs b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/Android/MainActivity.Android.cs new file mode 100644 index 00000000..dbea655b --- /dev/null +++ b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/Android/MainActivity.Android.cs @@ -0,0 +1,15 @@ +using Android.App; +using Android.Content.PM; +using Android.OS; +using Android.Views; +using Android.Widget; + +namespace TodoApp.Uno.Droid; +[Activity( + MainLauncher = true, + ConfigurationChanges = global::Uno.UI.ActivityHelper.AllConfigChanges, + WindowSoftInputMode = SoftInput.AdjustNothing | SoftInput.StateHidden +)] +public class MainActivity : Microsoft.UI.Xaml.ApplicationActivity +{ +} diff --git a/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/Android/Resources/AboutResources.txt b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/Android/Resources/AboutResources.txt new file mode 100644 index 00000000..17e3b133 --- /dev/null +++ b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/Android/Resources/AboutResources.txt @@ -0,0 +1,47 @@ +To add cross-platform image assets for your Uno Platform app, use the Assets folder +in the shared project instead. Resources in this folder are Android-only. + +Images, layout descriptions, binary blobs and string dictionaries can be included +in your application as resource files. Various Android APIs are designed to +operate on the resource IDs instead of dealing with images, strings or binary blobs +directly. + +For example, a sample Android app that contains a user interface layout (main.axml), +an internationalization string table (strings.xml) and some icons (drawable-XXX/icon.png) +would keep its resources in the "Resources" directory of the application: + +Resources/ + drawable/ + icon.png + + layout/ + main.axml + + values/ + strings.xml + +In order to get the build system to recognize Android resources, set the build action to +"AndroidResource". The native Android APIs do not operate directly with filenames, but +instead operate on resource IDs. When you compile an Android application that uses resources, +the build system will package the resources for distribution and generate a class called "R" +(this is an Android convention) that contains the tokens for each one of the resources +included. For example, for the above Resources layout, this is what the R class would expose: + +public class R { + public class drawable { + public const int icon = 0x123; + } + + public class layout { + public const int main = 0x456; + } + + public class strings { + public const int first_string = 0xabc; + public const int second_string = 0xbcd; + } +} + +You would then use R.drawable.icon to reference the drawable/icon.png file, or R.layout.main +to reference the layout/main.axml file, or R.strings.first_string to reference the first +string in the dictionary file values/strings.xml. diff --git a/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/Android/Resources/values/Strings.xml b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/Android/Resources/values/Strings.xml new file mode 100644 index 00000000..188b899a --- /dev/null +++ b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/Android/Resources/values/Strings.xml @@ -0,0 +1,5 @@ + + + Hello World, Click Me! + TodoApp.Uno + diff --git a/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/Android/Resources/values/Styles.xml b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/Android/Resources/values/Styles.xml new file mode 100644 index 00000000..c02bd06f --- /dev/null +++ b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/Android/Resources/values/Styles.xml @@ -0,0 +1,22 @@ + + + + + + diff --git a/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/Android/environment.conf b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/Android/environment.conf new file mode 100644 index 00000000..fa6c2e32 --- /dev/null +++ b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/Android/environment.conf @@ -0,0 +1,2 @@ +# See this for more details: http://developer.xamarin.com/guides/android/advanced_topics/garbage_collection/ +MONO_GC_PARAMS=bridge-implementation=tarjan,nursery-size=32m,soft-heap-limit=256m \ No newline at end of file diff --git a/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/Desktop/Program.cs b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/Desktop/Program.cs new file mode 100644 index 00000000..648eb542 --- /dev/null +++ b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/Desktop/Program.cs @@ -0,0 +1,19 @@ +using Uno.UI.Runtime.Skia; + +namespace TodoApp.Uno; +public class Program +{ + [STAThread] + public static void Main(string[] args) + { + var host = SkiaHostBuilder.Create() + .App(() => new App()) + .UseX11() + .UseLinuxFrameBuffer() + .UseMacOS() + .UseWindows() + .Build(); + + host.Run(); + } +} diff --git a/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/MacCatalyst/Entitlements.plist b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/MacCatalyst/Entitlements.plist new file mode 100644 index 00000000..24c31036 --- /dev/null +++ b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/MacCatalyst/Entitlements.plist @@ -0,0 +1,6 @@ + + + + + + diff --git a/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/MacCatalyst/Info.plist b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/MacCatalyst/Info.plist new file mode 100644 index 00000000..1bb02ddc --- /dev/null +++ b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/MacCatalyst/Info.plist @@ -0,0 +1,26 @@ + + + + + UIDeviceFamily + + 2 + + LSApplicationCategoryType + public.app-category.utilities + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + XSAppIconAssets + Assets.xcassets/icon.appiconset + + + + diff --git a/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/MacCatalyst/Main.maccatalyst.cs b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/MacCatalyst/Main.maccatalyst.cs new file mode 100644 index 00000000..a2e34523 --- /dev/null +++ b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/MacCatalyst/Main.maccatalyst.cs @@ -0,0 +1,13 @@ +using UIKit; + +namespace TodoApp.Uno.MacCatalyst; +public class EntryPoint +{ + // This is the main entry point of the application. + public static void Main(string[] args) + { + // if you want to use a different Application Delegate class from "AppDelegate" + // you can specify it here. + UIApplication.Main(args, null, typeof(App)); + } +} diff --git a/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/MacCatalyst/Media.xcassets/LaunchImages.launchimage/Contents.json b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/MacCatalyst/Media.xcassets/LaunchImages.launchimage/Contents.json new file mode 100644 index 00000000..69555e44 --- /dev/null +++ b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/MacCatalyst/Media.xcassets/LaunchImages.launchimage/Contents.json @@ -0,0 +1,58 @@ +{ + "images": [ + { + "orientation": "portrait", + "extent": "full-screen", + "minimum-system-version": "7.0", + "scale": "2x", + "size": "640x960", + "idiom": "iphone" + }, + { + "orientation": "portrait", + "extent": "full-screen", + "minimum-system-version": "7.0", + "subtype": "retina4", + "scale": "2x", + "size": "640x1136", + "idiom": "iphone" + }, + { + "orientation": "portrait", + "extent": "full-screen", + "minimum-system-version": "7.0", + "scale": "1x", + "size": "768x1024", + "idiom": "ipad" + }, + { + "orientation": "landscape", + "extent": "full-screen", + "minimum-system-version": "7.0", + "scale": "1x", + "size": "1024x768", + "idiom": "ipad" + }, + { + "orientation": "portrait", + "extent": "full-screen", + "minimum-system-version": "7.0", + "scale": "2x", + "size": "1536x2048", + "idiom": "ipad" + }, + { + "orientation": "landscape", + "extent": "full-screen", + "minimum-system-version": "7.0", + "scale": "2x", + "size": "2048x1536", + "idiom": "ipad" + } + ], + "properties": {}, + "info": { + "version": 1, + "author": "" + } +} \ No newline at end of file diff --git a/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/WebAssembly/LinkerConfig.xml b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/WebAssembly/LinkerConfig.xml new file mode 100644 index 00000000..6947a56c --- /dev/null +++ b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/WebAssembly/LinkerConfig.xml @@ -0,0 +1,10 @@ + + + + + diff --git a/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/WebAssembly/Program.cs b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/WebAssembly/Program.cs new file mode 100644 index 00000000..10e4a9fc --- /dev/null +++ b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/WebAssembly/Program.cs @@ -0,0 +1,13 @@ +namespace TodoApp.Uno; + +public class Program +{ + private static App? _app; + + public static int Main(string[] args) + { + Microsoft.UI.Xaml.Application.Start(_ => _app = new App()); + + return 0; + } +} diff --git a/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/WebAssembly/WasmCSS/Fonts.css b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/WebAssembly/WasmCSS/Fonts.css new file mode 100644 index 00000000..4fdd6055 --- /dev/null +++ b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/WebAssembly/WasmCSS/Fonts.css @@ -0,0 +1,28 @@ +/** + When adding fonts here, make sure to add them using a base64 data uri, otherwise + fonts loading are delayed, and text may get displayed incorrectly. +*/ + +/* https://github.com/unoplatform/uno/issues/3954 */ +@font-face { + font-family: 'Segoe UI'; + src: local('Segoe UI'), local('-apple-system'), local('BlinkMacSystemFont'), local('Inter'), local('Cantarell'), local('Ubuntu'), local('Roboto'), local('Open Sans'), local('Noto Sans'), local('Helvetica Neue'), local('sans-serif'); +} + +@font-face { + font-family: 'Roboto'; + src: url(./Uno.Fonts.Roboto/Fonts/Roboto-Light.ttf) format('truetype'); + font-weight: 300; +} + +@font-face { + font-family: 'Roboto'; + src: url(./Uno.Fonts.Roboto/Fonts/Roboto-Regular.ttf) format('truetype'); + font-weight: 400; +} + +@font-face { + font-family: 'Roboto'; + src: url(./Uno.Fonts.Roboto/Fonts/Roboto-Medium.ttf) format('truetype'); + font-weight: 500; +} diff --git a/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/WebAssembly/WasmScripts/AppManifest.js b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/WebAssembly/WasmScripts/AppManifest.js new file mode 100644 index 00000000..9fccab4c --- /dev/null +++ b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/WebAssembly/WasmScripts/AppManifest.js @@ -0,0 +1,3 @@ +var UnoAppManifest = { + displayName: "TodoApp.Uno" +} diff --git a/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/WebAssembly/manifest.webmanifest b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/WebAssembly/manifest.webmanifest new file mode 100644 index 00000000..d1f86976 --- /dev/null +++ b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/WebAssembly/manifest.webmanifest @@ -0,0 +1,10 @@ +{ + "background_color": "#ffffff", + "description": "TodoApp.Uno", + "display": "standalone", + "name": "TodoApp.Uno", + "short_name": "TodoApp.Uno", + "start_url": "/index.html", + "theme_color": "#ffffff", + "scope": "/" +} diff --git a/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/WebAssembly/wwwroot/staticwebapp.config.json b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/WebAssembly/wwwroot/staticwebapp.config.json new file mode 100644 index 00000000..79c1b17c --- /dev/null +++ b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/WebAssembly/wwwroot/staticwebapp.config.json @@ -0,0 +1,30 @@ +{ + "navigationFallback": { + "rewrite": "/index.html", + "exclude": [ + "*.{css,js}", + "*.{png}", + "*.{c,h,wasm,clr,pdb,dat,txt}" + ] + }, + "routes": [ + { + "route": "/package_*", + "headers": { + "cache-control": "public, immutable, max-age=31536000" + } + }, + { + "route": "/*.ttf", + "headers": { + "cache-control": "public, immutable, max-age=31536000" + } + }, + { + "route": "/*", + "headers": { + "cache-control": "must-revalidate, max-age=3600" + } + } + ] +} diff --git a/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/WebAssembly/wwwroot/web.config b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/WebAssembly/wwwroot/web.config new file mode 100644 index 00000000..8f5a860f --- /dev/null +++ b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/WebAssembly/wwwroot/web.config @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/iOS/Entitlements.plist b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/iOS/Entitlements.plist new file mode 100644 index 00000000..24c31036 --- /dev/null +++ b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/iOS/Entitlements.plist @@ -0,0 +1,6 @@ + + + + + + diff --git a/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/iOS/Info.plist b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/iOS/Info.plist new file mode 100644 index 00000000..ea3dcb4b --- /dev/null +++ b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/iOS/Info.plist @@ -0,0 +1,43 @@ + + + + + LSRequiresIPhoneOS + + UIDeviceFamily + + 1 + 2 + + UIRequiredDeviceCapabilities + + armv7 + arm64 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIViewControllerBasedStatusBarAppearance + + XSAppIconAssets + Assets.xcassets/icon.appiconset + UIApplicationSupportsIndirectInputEvents + + + + + diff --git a/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/iOS/Main.iOS.cs b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/iOS/Main.iOS.cs new file mode 100644 index 00000000..f3fa2955 --- /dev/null +++ b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/iOS/Main.iOS.cs @@ -0,0 +1,13 @@ +using UIKit; + +namespace TodoApp.Uno.iOS; +public class EntryPoint +{ + // This is the main entry point of the application. + public static void Main(string[] args) + { + // if you want to use a different Application Delegate class from "AppDelegate" + // you can specify it here. + UIApplication.Main(args, null, typeof(App)); + } +} diff --git a/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/iOS/Media.xcassets/LaunchImages.launchimage/Contents.json b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/iOS/Media.xcassets/LaunchImages.launchimage/Contents.json new file mode 100644 index 00000000..69555e44 --- /dev/null +++ b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/iOS/Media.xcassets/LaunchImages.launchimage/Contents.json @@ -0,0 +1,58 @@ +{ + "images": [ + { + "orientation": "portrait", + "extent": "full-screen", + "minimum-system-version": "7.0", + "scale": "2x", + "size": "640x960", + "idiom": "iphone" + }, + { + "orientation": "portrait", + "extent": "full-screen", + "minimum-system-version": "7.0", + "subtype": "retina4", + "scale": "2x", + "size": "640x1136", + "idiom": "iphone" + }, + { + "orientation": "portrait", + "extent": "full-screen", + "minimum-system-version": "7.0", + "scale": "1x", + "size": "768x1024", + "idiom": "ipad" + }, + { + "orientation": "landscape", + "extent": "full-screen", + "minimum-system-version": "7.0", + "scale": "1x", + "size": "1024x768", + "idiom": "ipad" + }, + { + "orientation": "portrait", + "extent": "full-screen", + "minimum-system-version": "7.0", + "scale": "2x", + "size": "1536x2048", + "idiom": "ipad" + }, + { + "orientation": "landscape", + "extent": "full-screen", + "minimum-system-version": "7.0", + "scale": "2x", + "size": "2048x1536", + "idiom": "ipad" + } + ], + "properties": {}, + "info": { + "version": 1, + "author": "" + } +} \ No newline at end of file diff --git a/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/iOS/PrivacyInfo.xcprivacy b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/iOS/PrivacyInfo.xcprivacy new file mode 100644 index 00000000..902abb05 --- /dev/null +++ b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/iOS/PrivacyInfo.xcprivacy @@ -0,0 +1,41 @@ + + + + + + + + NSPrivacyAccessedAPIType + NSPrivacyAccessedAPICategoryFileTimestamp + NSPrivacyAccessedAPITypeReasons + + C617.1 + + + + NSPrivacyAccessedAPIType + NSPrivacyAccessedAPICategorySystemBootTime + NSPrivacyAccessedAPITypeReasons + + 35F9.1 + + + + NSPrivacyAccessedAPIType + NSPrivacyAccessedAPICategoryDiskSpace + NSPrivacyAccessedAPITypeReasons + + E174.1 + + + + + + NSPrivacyAccessedAPIType + NSPrivacyAccessedAPICategoryUserDefaults + NSPrivacyAccessedAPITypeReasons + + CA92.1 + + + diff --git a/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Presentation/Shell.xaml b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Presentation/Shell.xaml new file mode 100644 index 00000000..72b978f4 --- /dev/null +++ b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Presentation/Shell.xaml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + diff --git a/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Presentation/Shell.xaml.cs b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Presentation/Shell.xaml.cs new file mode 100644 index 00000000..2226fd10 --- /dev/null +++ b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Presentation/Shell.xaml.cs @@ -0,0 +1,10 @@ +namespace TodoApp.Uno.Presentation; + +public sealed partial class Shell : UserControl, IContentControlProvider +{ + public Shell() + { + this.InitializeComponent(); + } + public ContentControl ContentControl => Splash; +} diff --git a/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Presentation/ShellViewModel.cs b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Presentation/ShellViewModel.cs new file mode 100644 index 00000000..8bc20f1e --- /dev/null +++ b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Presentation/ShellViewModel.cs @@ -0,0 +1,13 @@ +namespace TodoApp.Uno.Presentation; + +public class ShellViewModel +{ + private readonly INavigator _navigator; + + public ShellViewModel( + INavigator navigator) + { + _navigator = navigator; + // Add code here to initialize or attach event handlers to singleton services + } +} diff --git a/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Properties/PublishProfiles/win-arm64.pubxml b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Properties/PublishProfiles/win-arm64.pubxml new file mode 100644 index 00000000..5d5632ab --- /dev/null +++ b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Properties/PublishProfiles/win-arm64.pubxml @@ -0,0 +1,18 @@ + + + + + FileSystem + arm64 + win-arm64 + bin\$(Configuration)\$(TargetFramework)\$(RuntimeIdentifier)\publish\ + true + False + False + True + False + True + + diff --git a/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Properties/PublishProfiles/win-x64.pubxml b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Properties/PublishProfiles/win-x64.pubxml new file mode 100644 index 00000000..12b83447 --- /dev/null +++ b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Properties/PublishProfiles/win-x64.pubxml @@ -0,0 +1,18 @@ + + + + + FileSystem + x64 + win-x64 + bin\$(Configuration)\$(TargetFramework)\$(RuntimeIdentifier)\publish\ + true + False + False + True + False + True + + diff --git a/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Properties/PublishProfiles/win-x86.pubxml b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Properties/PublishProfiles/win-x86.pubxml new file mode 100644 index 00000000..65b8f1db --- /dev/null +++ b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Properties/PublishProfiles/win-x86.pubxml @@ -0,0 +1,23 @@ + + + + + FileSystem + x86 + win-x86 + bin\$(Configuration)\$(TargetFramework)\$(RuntimeIdentifier)\publish\ + true + False + False + True + False + True + + + diff --git a/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Properties/launchSettings.json b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Properties/launchSettings.json new file mode 100644 index 00000000..415af151 --- /dev/null +++ b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Properties/launchSettings.json @@ -0,0 +1,50 @@ +{ + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:8080", + "sslPort": 0 + } + }, + "profiles": { + // This profile is first in order for dotnet run to pick it up by default + "TodoApp.Uno (WebAssembly)": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "applicationUrl": "http://localhost:5000", + "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "TodoApp.Uno (WebAssembly IIS Express)": { + "commandName": "IISExpress", + "launchBrowser": true, + "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + // Note: In order to select this profile, you'll need to comment the `Packaged` profile below until this is fixed: https://aka.platform.uno/wasdk-maui-debug-profile-issue + "TodoApp.Uno (WinAppSDK Unpackaged)": { + "commandName": "Project", + "compatibleTargetFramework": "windows" + }, + "TodoApp.Uno (WinAppSDK Packaged)": { + "commandName": "MsixPackage", + "compatibleTargetFramework": "windows" + }, + "TodoApp.Uno (Desktop)": { + "commandName": "Project", + "compatibleTargetFramework": "desktop" + }, + "TodoApp.Uno (Desktop WSL2)": { + "commandName": "WSL2", + "commandLineArgs": "{ProjectDir}/bin/Debug/net8.0-desktop/TodoApp.Uno.dll", + "distributionName": "", + "compatibleTargetFramework": "desktop" + } + } +} diff --git a/samples/todoapp/TodoApp.Uno/TodoApp.Uno/ReadMe.md b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/ReadMe.md new file mode 100644 index 00000000..93482da2 --- /dev/null +++ b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/ReadMe.md @@ -0,0 +1,7 @@ +# Getting Started + +Welcome to the Uno Platform! + +To discover how to get started with your new app: https://aka.platform.uno/get-started + +For more information on how to use the Uno.Sdk or upgrade Uno Platform packages in your solution: https://aka.platform.uno/using-uno-sdk \ No newline at end of file diff --git a/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Services/LoggingHandler.cs b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Services/LoggingHandler.cs new file mode 100644 index 00000000..67eac603 --- /dev/null +++ b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Services/LoggingHandler.cs @@ -0,0 +1,49 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Net.Http; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace TodoApp.Uno.Services; + +/// +/// A delegating handler that logs the request/response to stdout. +/// +public class LoggingHandler : DelegatingHandler +{ + public LoggingHandler() : base() + { + } + + public LoggingHandler(HttpMessageHandler innerHandler) : base(innerHandler) + { + } + + protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) + { + Debug.WriteLine($"[HTTP] >>> {request.Method} {request.RequestUri}"); + await WriteContentAsync(request.Content, cancellationToken); + + HttpResponseMessage response = await base.SendAsync(request, cancellationToken); + + Debug.WriteLine($"[HTTP] <<< {response.StatusCode} {response.ReasonPhrase}"); + await WriteContentAsync(response.Content, cancellationToken); + + return response; + } + + private static async Task WriteContentAsync(HttpContent content, CancellationToken cancellationToken = default) + { + if (content != null) + { + Debug.WriteLine($"[HTTP] >>> {await content.ReadAsStringAsync(cancellationToken)}"); + } + } +} diff --git a/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Strings/en/Resources.resw b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Strings/en/Resources.resw new file mode 100644 index 00000000..be03cf9b --- /dev/null +++ b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Strings/en/Resources.resw @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + TodoApp.Uno-en + + diff --git a/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Strings/es/Resources.resw b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Strings/es/Resources.resw new file mode 100644 index 00000000..61da9ea1 --- /dev/null +++ b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Strings/es/Resources.resw @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + TodoApp.Uno-es + + diff --git a/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Strings/fr/Resources.resw b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Strings/fr/Resources.resw new file mode 100644 index 00000000..7d3ea6a7 --- /dev/null +++ b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Strings/fr/Resources.resw @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + TodoApp.Uno-fr + + diff --git a/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Strings/pt-BR/Resources.resw b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Strings/pt-BR/Resources.resw new file mode 100644 index 00000000..8aabbc06 --- /dev/null +++ b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Strings/pt-BR/Resources.resw @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + TodoApp.Uno-pt-BR + + diff --git a/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Styles/ColorPaletteOverride.json b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Styles/ColorPaletteOverride.json new file mode 100644 index 00000000..cd154921 --- /dev/null +++ b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Styles/ColorPaletteOverride.json @@ -0,0 +1,76 @@ +{ + "description": "Default Uno Material colors", + "seed": "#5946d2", + "coreColors": { + "primary": "#5946d2", + "secondary": "#6b4ea2" + }, + "extendedColors": [], + "schemes": { + "light": { + "primary": "#5946d2", + "surfaceTint": "#5946d2", + "onPrimary": "#ffffff", + "primaryContainer": "#e5deff", + "onPrimaryContainer": "#170065", + "secondary": "#6b4ea2", + "onSecondary": "#ffffff", + "secondaryContainer": "#ebddff", + "onSecondaryContainer": "#220555", + "tertiary": "#0061a4", + "onTertiary": "#ffffff", + "tertiaryContainer": "#cfe4ff", + "onTertiaryContainer": "#001d36", + "error": "#b3261e", + "onError": "#ffffff", + "errorContainer": "#f9dedc", + "onErrorContainer": "#410e0b", + "background": "#fcfbff", + "onBackground": "#1c1b1f", + "surface": "#ffffff", + "onSurface": "#1c1b1f", + "surfaceVariant": "#f2eff5", + "onSurfaceVariant": "#8b8494", + "outline": "#79747e", + "outlineVariant": "#c9c5d0", + "shadow": "#000000", + "scrim": "#000000", + "inverseSurface": "#e6e1e5", + "inverseOnSurface": "#1c1b1f", + "inversePrimary": "#2a009f" + }, + "dark": { + "primary": "#c7bfff", + "surfaceTint": "#c7bfff", + "onPrimary": "#2a009f", + "primaryContainer": "#4129ba", + "onPrimaryContainer": "#e4dfff", + "secondary": "#cdc2dc", + "onSecondary": "#332d41", + "secondaryContainer": "#433c52", + "onSecondaryContainer": "#eddfff", + "tertiary": "#9fcaff", + "onTertiary": "#003258", + "tertiaryContainer": "#00497d", + "onTertiaryContainer": "#d1e4ff", + "error": "#ffb4ab", + "onError": "#690005", + "errorContainer": "#93000a", + "onErrorContainer": "#ffdad6", + "background": "#1c1b1f", + "onBackground": "#e5e1e6", + "surface": "#302d37", + "onSurface": "#e6e1e5", + "surfaceVariant": "#47464f", + "onSurfaceVariant": "#c9c5d0", + "outline": "#928f99", + "outlineVariant": "#57545d", + "shadow": "#000000", + "scrim": "#000000", + "inverseSurface": "#e6e1e5", + "inverseOnSurface": "#1c1b1f", + "inversePrimary": "#2a009f" + } + }, + "palettes": {} +} diff --git a/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Styles/ColorPaletteOverride.xaml b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Styles/ColorPaletteOverride.xaml new file mode 100644 index 00000000..b47f3309 --- /dev/null +++ b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Styles/ColorPaletteOverride.xaml @@ -0,0 +1,65 @@ + + + + + #5946D2 + #FFFFFF + #E5DEFF + #170065 + #6B4EA2 + #FFFFFF + #EBDDFF + #220555 + #0061A4 + #FFFFFF + #CFE4FF + #001D36 + #B3261E + #F9DEDC + #FFFFFF + #410E0B + #FCFBFF + #1C1B1F + #FFFFFF + #1C1B1F + #F2EFF5 + #8B8494 + #79747E + #F4EFF4 + #313033 + #C8BFFF + #5946D2 + #C9C5D0 + + + #C7BFFF + #2A009F + #4129BA + #E4DFFF + #CDC2DC + #332D41 + #433C52 + #EDDFFF + #9FCAFF + #003258 + #00497D + #D1E4FF + #FFB4AB + #93000A + #690005 + #FFDAD6 + #1C1B1F + #E5E1E6 + #302D37 + #E6E1E5 + #47464F + #C9C5D0 + #928F99 + #1C1B1F + #E6E1E5 + #2A009F + #C7BFFF + #57545D + + + diff --git a/samples/todoapp/TodoApp.Uno/TodoApp.Uno/TodoApp.Uno.csproj b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/TodoApp.Uno.csproj new file mode 100644 index 00000000..986128df --- /dev/null +++ b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/TodoApp.Uno.csproj @@ -0,0 +1,90 @@ + + + net8.0-android;net8.0-ios;net8.0-maccatalyst;net8.0-windows10.0.26100;net8.0-browserwasm;net8.0-desktop + + Exe + true + + + TodoApp.Uno + + com.companyname.TodoApp.Uno + + 1.0 + 1 + + Your.Name + + TodoApp.Uno powered by Uno Platform. + + + 10.0.26100.57 + + + + + Dsp; + Hosting; + Toolkit; + Logging; + Lottie; + Mvvm; + Configuration; + + + + Navigation; + + + True + + + + manual + VS: WildCard Development + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + MSBuild:Compile + + + + diff --git a/samples/todoapp/TodoApp.Uno/TodoApp.Uno/ViewModels/NotificationEventArgs.cs b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/ViewModels/NotificationEventArgs.cs new file mode 100644 index 00000000..439cca78 --- /dev/null +++ b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/ViewModels/NotificationEventArgs.cs @@ -0,0 +1,9 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace TodoApp.Uno.ViewModels; + +internal record NotificationEventArgs(string Title, string Message, bool IsError) +{ +} diff --git a/samples/todoapp/TodoApp.Uno/TodoApp.Uno/ViewModels/TodoItemViewModel.cs b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/ViewModels/TodoItemViewModel.cs new file mode 100644 index 00000000..bfd471af --- /dev/null +++ b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/ViewModels/TodoItemViewModel.cs @@ -0,0 +1,47 @@ +using CommunityToolkit.Mvvm.ComponentModel; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using TodoApp.Uno.Database; + +namespace TodoApp.Uno.ViewModels +{ + public partial class TodoItemViewModel(TodoItem todoItem) : ObservableObject + { + public readonly TodoItem _todoItem = todoItem; + + public string Title + { + get => _todoItem.Title; + set => SetProperty(_todoItem.Title, value, _todoItem, (item, value) => item.Title = value); + } + + public bool IsComplete + { + get => _todoItem.IsComplete; + set => SetProperty(_todoItem.IsComplete, value, _todoItem, (item, value) => item.IsComplete = value); + } + + public string Version + { + get => _todoItem.Version; + set => SetProperty(_todoItem.Version, value, _todoItem, (item, value) => item.Version = value); + } + + public string Id => _todoItem.Id; + + public DateTimeOffset? UpdatedAt + { + get => _todoItem.UpdatedAt; + set => SetProperty(_todoItem.UpdatedAt, value, _todoItem, (item, value) => item.UpdatedAt = value); + } + + public bool Deleted + { + get => _todoItem.Deleted; + set => SetProperty(_todoItem.Deleted, value, _todoItem, (item, value) => item.Deleted = value); + } + } +} diff --git a/samples/todoapp/TodoApp.Uno/TodoApp.Uno/ViewModels/TodoListViewModel.cs b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/ViewModels/TodoListViewModel.cs new file mode 100644 index 00000000..c39f2d9d --- /dev/null +++ b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/ViewModels/TodoListViewModel.cs @@ -0,0 +1,126 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using CommunityToolkit.Datasync.Client; +using CommunityToolkit.Mvvm.ComponentModel; +using CommunityToolkit.Mvvm.Input; +using Microsoft.EntityFrameworkCore; +using TodoApp.Uno.Database; + +namespace TodoApp.Uno.ViewModels; + +/// +/// The view model for the TodoListWindow. +/// +public partial class TodoListViewModel(AppDbContext service) : ObservableRecipient +{ + internal event EventHandler NotificationHandler; + + [ObservableProperty] + private bool isRefreshing; + + [ObservableProperty] + private ConcurrentObservableCollection items = []; + + [ObservableProperty] + private string title = string.Empty; + + [RelayCommand] + public async Task AddItemAsync(CancellationToken cancellationToken = default) + { + try + { + // Create a new item + TodoItem addition = new() + { + Id = Guid.NewGuid().ToString("N"), + Title = Title, + }; + + // Add te item to the database + _ = service.TodoItems.Add(addition); + _ = await service.SaveChangesAsync(cancellationToken); + + // Add the item to the end of the list. + Items.Add(new TodoItemViewModel(addition)); + + // Update the title field ready for ext insertion. + Title = string.Empty; + } + catch (Exception ex) + { + NotificationHandler?.Invoke(this, new NotificationEventArgs(ex.GetType().Name, ex.Message, true)); + } + finally + { + NotificationHandler?.Invoke(this, new NotificationEventArgs("Item Added", "", false)); + } + } + + [RelayCommand] + public async Task EditItemAsync(string itemId, CancellationToken cancellationToken = default) + { + try + { + // Retrieve the item (by ID) from the service. + TodoItem item = await service.TodoItems.FindAsync([itemId], cancellationToken) + ?? throw new ApplicationException($"Item with ID '{itemId}' not found."); + + // Update the item in the database + item.IsComplete = !item.IsComplete; + _ = service.TodoItems.Update(item); + _ = await service.SaveChangesAsync(cancellationToken); + + // Update the item in the list + _ = Items.ReplaceIf(x => x.Id == itemId, new TodoItemViewModel(item)); + } + catch (Exception ex) + { + NotificationHandler?.Invoke(this, new NotificationEventArgs(ex.GetType().Name, ex.Message, true)); + } + finally + { + NotificationHandler?.Invoke(this, new NotificationEventArgs("Item Updated", "", false)); + } + } + + [RelayCommand] + public async Task LoadPageAsync(CancellationToken cancellationToken = default) + { + await RefreshItemsAsync(cancellationToken); + } + + [RelayCommand] + public async Task RefreshItemsAsync(CancellationToken cancellationToken = default) + { + try + { + IsRefreshing = true; + + // Synchronize data with the remote service (if any). + await service.SynchronizeAsync(cancellationToken); + + // Pull all items from the database. + IEnumerable itemsFromDatabase = await service.TodoItems.ToListAsync(cancellationToken); + + IEnumerable items = itemsFromDatabase.OrderBy(item => item.Id).Select(x => new TodoItemViewModel(x)); + + // Replace all the items in the collection. + Items.ReplaceAll(items); + } + catch (Exception ex) + { + NotificationHandler?.Invoke(this, new NotificationEventArgs(ex.GetType().Name, ex.Message, true)); + } + finally + { + IsRefreshing = false; + NotificationHandler?.Invoke(this, new NotificationEventArgs("Items Refreshed", "", false)); + } + } +} diff --git a/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Views/TodoListPage.xaml b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Views/TodoListPage.xaml new file mode 100644 index 00000000..90ce4871 --- /dev/null +++ b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Views/TodoListPage.xaml @@ -0,0 +1,112 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Views/TodoListPage.xaml.cs b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Views/TodoListPage.xaml.cs new file mode 100644 index 00000000..5b1529ff --- /dev/null +++ b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Views/TodoListPage.xaml.cs @@ -0,0 +1,67 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices.WindowsRuntime; +using CommunityToolkit.WinUI.Behaviors; +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; +using Microsoft.UI.Xaml.Controls.Primitives; +using Microsoft.UI.Xaml.Data; +using Microsoft.UI.Xaml.Input; +using Microsoft.UI.Xaml.Media; +using Microsoft.UI.Xaml.Navigation; +using TodoApp.Uno.ViewModels; +using Windows.Foundation; +using Windows.Foundation.Collections; +using Windows.UI.ViewManagement; + +namespace TodoApp.Uno.Views; + +public sealed partial class TodoListPage : Page +{ + public TodoListViewModel ViewModel => (TodoListViewModel)DataContext!; + + public TodoListPage() + { + this.InitializeComponent(); + + DataContextChanged += DataContextChangedHandler; + } + + + + // on loaded override + private async void DataContextChangedHandler(object sender, DataContextChangedEventArgs e) + { + // Ensure e.NewValue is not null and is a TodoListViewModel (for some reason on iOS it is the ShellViewModel on one of the calls) + if (e.NewValue != null && e.NewValue is TodoListViewModel && ViewModel.LoadPageCommand.CanExecute(null)) + { + ViewModel.NotificationHandler += PublishNotification; + await ViewModel.LoadPageCommand.ExecuteAsync(null); + } + } + + internal void PublishNotification(object sender, NotificationEventArgs args) + { + Notification notification = new() + { + Title = args.Title, + Message = args.Message, + Severity = args.IsError ? InfoBarSeverity.Error : InfoBarSeverity.Informational, + Duration = args.IsError ? null : TimeSpan.FromSeconds(2) + }; + _ = this.NotificationQueue.Show(notification); + } + + private void TextBox_KeyDown(object sender, KeyRoutedEventArgs e) + { + // if key is enter, run AddItem command on ViewModel + if (e.Key == Windows.System.VirtualKey.Enter) + { + e.Handled = true; + ViewModel.AddItemCommand.Execute(null); + ViewModel.Title = string.Empty; + } + } +} diff --git a/samples/todoapp/TodoApp.Uno/TodoApp.Uno/app.manifest b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/app.manifest new file mode 100644 index 00000000..bde52249 --- /dev/null +++ b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/app.manifest @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + true/PM + PerMonitorV2, PerMonitor + + + diff --git a/samples/todoapp/TodoApp.Uno/TodoApp.Uno/appsettings.development.json b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/appsettings.development.json new file mode 100644 index 00000000..2cf8df52 --- /dev/null +++ b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/appsettings.development.json @@ -0,0 +1,9 @@ +{ + "AppConfig": { + "Environment": "Development" + }, + "ApiClient": { + "Url": "https://localhost:5002", + "UseNativeHandler": true + } +} diff --git a/samples/todoapp/TodoApp.Uno/TodoApp.Uno/appsettings.json b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/appsettings.json new file mode 100644 index 00000000..aa890ef1 --- /dev/null +++ b/samples/todoapp/TodoApp.Uno/TodoApp.Uno/appsettings.json @@ -0,0 +1,16 @@ +{ + "AppConfig": { + "Environment": "Production" + }, + "ApiClient": { + "UseNativeHandler": true + }, + "LocalizationConfiguration": { + "Cultures": [ + "es", + "fr", + "pt-BR", + "en" + ] + } +} diff --git a/samples/todoapp/TodoApp.Uno/global.json b/samples/todoapp/TodoApp.Uno/global.json new file mode 100644 index 00000000..694b05a7 --- /dev/null +++ b/samples/todoapp/TodoApp.Uno/global.json @@ -0,0 +1,9 @@ +{ + // To update the version of Uno please update the version of the Uno.Sdk here. See https://aka.platform.uno/upgrade-uno-packages for more information. + "msbuild-sdks": { + "Uno.Sdk": "5.4.5" + }, + "sdk":{ + "allowPrerelease": false + } +}