diff --git a/.github/workflows/ci-build.yml b/.github/workflows/ci-build.yml index 9c54731..6e4637d 100644 --- a/.github/workflows/ci-build.yml +++ b/.github/workflows/ci-build.yml @@ -10,13 +10,31 @@ env: productNamespacePrefix: "ReactiveMvvm" jobs: - build: - uses: reactiveui/actions-common/.github/workflows/workflow-common-setup-and-build.yml@main - with: - configuration: Release - productNamespacePrefix: "ReactiveMvvm" - useVisualStudioPreview: false - useMauiCheckDotNetTool: false - installWindowsSdk: false - installWorkflows: false - solutionFile: 'ReactiveMvvm.sln' + windows-latest: + name: windows-latest + runs-on: windows-latest + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: 'Setup Java JDK 11' + uses: actions/setup-java@v4.0.0 + with: + distribution: 'microsoft' + java-version: '11' + + - name: 'Install DotNet workloads' + shell: bash + run: | + dotnet workload install android ios tvos macos maui maccatalyst wasm-tools-net7 + + - name: 'Cache: .nuke/temp, ~/.nuget/packages' + uses: actions/cache@v3 + with: + path: | + .nuke/temp + ~/.nuget/packages + key: ${{ runner.os }}-${{ hashFiles('**/global.json', '**/*.csproj', '**/Directory.Packages.props') }} + - name: 'Run: RunInteractive' + run: ./build.cmd RunInteractive diff --git a/.nuke/build.schema.json b/.nuke/build.schema.json new file mode 100644 index 0000000..999f476 --- /dev/null +++ b/.nuke/build.schema.json @@ -0,0 +1,124 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/build", + "title": "Build Schema", + "definitions": { + "build": { + "type": "object", + "properties": { + "Configuration": { + "type": "string", + "description": "Configuration to build - Default is 'Debug' (local) or 'Release' (server)", + "enum": [ + "Debug", + "Release" + ] + }, + "Continue": { + "type": "boolean", + "description": "Indicates to continue a previously failed build attempt" + }, + "Full": { + "type": "boolean" + }, + "Help": { + "type": "boolean", + "description": "Shows the help text for this build assembly" + }, + "Host": { + "type": "string", + "description": "Host for execution. Default is 'automatic'", + "enum": [ + "AppVeyor", + "AzurePipelines", + "Bamboo", + "Bitbucket", + "Bitrise", + "GitHubActions", + "GitLab", + "Jenkins", + "Rider", + "SpaceAutomation", + "TeamCity", + "Terminal", + "TravisCI", + "VisualStudio", + "VSCode" + ] + }, + "Interactive": { + "type": "boolean" + }, + "NoLogo": { + "type": "boolean", + "description": "Disables displaying the NUKE logo" + }, + "Partition": { + "type": "string", + "description": "Partition to use on CI" + }, + "Plan": { + "type": "boolean", + "description": "Shows the execution plan (HTML)" + }, + "Profile": { + "type": "array", + "description": "Defines the profiles to load", + "items": { + "type": "string" + } + }, + "Root": { + "type": "string", + "description": "Root directory during build execution" + }, + "Skip": { + "type": "array", + "description": "List of targets to be skipped. Empty list skips all dependencies", + "items": { + "type": "string", + "enum": [ + "Clean", + "CompileAvaloniaApp", + "CompileBlazorApp", + "CompileMauiApp", + "CompileTerminalApp", + "CompileWindowsFormsApp", + "CompileWindowsPresentationApp", + "RunInteractive", + "RunUnitTests" + ] + } + }, + "Target": { + "type": "array", + "description": "List of targets to be invoked. Default is '{default_target}'", + "items": { + "type": "string", + "enum": [ + "Clean", + "CompileAvaloniaApp", + "CompileBlazorApp", + "CompileMauiApp", + "CompileTerminalApp", + "CompileWindowsFormsApp", + "CompileWindowsPresentationApp", + "RunInteractive", + "RunUnitTests" + ] + } + }, + "Verbosity": { + "type": "string", + "description": "Logging verbosity during build execution. Default is 'Normal'", + "enum": [ + "Minimal", + "Normal", + "Quiet", + "Verbose" + ] + } + } + } + } +} diff --git a/.nuke/parameters.json b/.nuke/parameters.json new file mode 100644 index 0000000..fb74bba --- /dev/null +++ b/.nuke/parameters.json @@ -0,0 +1,4 @@ +{ + "$schema": "./build.schema.json", + "Solution": "src/ReactiveMvvm.sln" +} diff --git a/build.cmd b/build.cmd new file mode 100644 index 0000000..b08cc59 --- /dev/null +++ b/build.cmd @@ -0,0 +1,7 @@ +:; set -eo pipefail +:; SCRIPT_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd) +:; ${SCRIPT_DIR}/build.sh "$@" +:; exit $? + +@ECHO OFF +powershell -ExecutionPolicy ByPass -NoProfile -File "%~dp0build.ps1" %* diff --git a/build.ps1 b/build.ps1 new file mode 100644 index 0000000..4634dc0 --- /dev/null +++ b/build.ps1 @@ -0,0 +1,74 @@ +[CmdletBinding()] +Param( + [Parameter(Position=0,Mandatory=$false,ValueFromRemainingArguments=$true)] + [string[]]$BuildArguments +) + +Write-Output "PowerShell $($PSVersionTable.PSEdition) version $($PSVersionTable.PSVersion)" + +Set-StrictMode -Version 2.0; $ErrorActionPreference = "Stop"; $ConfirmPreference = "None"; trap { Write-Error $_ -ErrorAction Continue; exit 1 } +$PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent + +########################################################################### +# CONFIGURATION +########################################################################### + +$BuildProjectFile = "$PSScriptRoot\build\_build.csproj" +$TempDirectory = "$PSScriptRoot\\.nuke\temp" + +$DotNetGlobalFile = "$PSScriptRoot\\global.json" +$DotNetInstallUrl = "https://dot.net/v1/dotnet-install.ps1" +$DotNetChannel = "STS" + +$env:DOTNET_CLI_TELEMETRY_OPTOUT = 1 +$env:DOTNET_NOLOGO = 1 + +########################################################################### +# EXECUTION +########################################################################### + +function ExecSafe([scriptblock] $cmd) { + & $cmd + if ($LASTEXITCODE) { exit $LASTEXITCODE } +} + +# If dotnet CLI is installed globally and it matches requested version, use for execution +if ($null -ne (Get-Command "dotnet" -ErrorAction SilentlyContinue) -and ` + $(dotnet --version) -and $LASTEXITCODE -eq 0) { + $env:DOTNET_EXE = (Get-Command "dotnet").Path +} +else { + # Download install script + $DotNetInstallFile = "$TempDirectory\dotnet-install.ps1" + New-Item -ItemType Directory -Path $TempDirectory -Force | Out-Null + [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 + (New-Object System.Net.WebClient).DownloadFile($DotNetInstallUrl, $DotNetInstallFile) + + # If global.json exists, load expected version + if (Test-Path $DotNetGlobalFile) { + $DotNetGlobal = $(Get-Content $DotNetGlobalFile | Out-String | ConvertFrom-Json) + if ($DotNetGlobal.PSObject.Properties["sdk"] -and $DotNetGlobal.sdk.PSObject.Properties["version"]) { + $DotNetVersion = $DotNetGlobal.sdk.version + } + } + + # Install by channel or version + $DotNetDirectory = "$TempDirectory\dotnet-win" + if (!(Test-Path variable:DotNetVersion)) { + ExecSafe { & powershell $DotNetInstallFile -InstallDir $DotNetDirectory -Channel $DotNetChannel -NoPath } + } else { + ExecSafe { & powershell $DotNetInstallFile -InstallDir $DotNetDirectory -Version $DotNetVersion -NoPath } + } + $env:DOTNET_EXE = "$DotNetDirectory\dotnet.exe" + $env:PATH = "$DotNetDirectory;$env:PATH" +} + +Write-Output "Microsoft (R) .NET SDK version $(& $env:DOTNET_EXE --version)" + +if (Test-Path env:NUKE_ENTERPRISE_TOKEN) { + & $env:DOTNET_EXE nuget remove source "nuke-enterprise" > $null + & $env:DOTNET_EXE nuget add source "https://f.feedz.io/nuke/enterprise/nuget" --name "nuke-enterprise" --username "PAT" --password $env:NUKE_ENTERPRISE_TOKEN > $null +} + +ExecSafe { & $env:DOTNET_EXE build $BuildProjectFile /nodeReuse:false /p:UseSharedCompilation=false -nologo -clp:NoSummary --verbosity quiet } +ExecSafe { & $env:DOTNET_EXE run --project $BuildProjectFile --no-build -- $BuildArguments } diff --git a/build.sh b/build.sh new file mode 100644 index 0000000..fdff0c6 --- /dev/null +++ b/build.sh @@ -0,0 +1,67 @@ +#!/usr/bin/env bash + +bash --version 2>&1 | head -n 1 + +set -eo pipefail +SCRIPT_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd) + +########################################################################### +# CONFIGURATION +########################################################################### + +BUILD_PROJECT_FILE="$SCRIPT_DIR/build/_build.csproj" +TEMP_DIRECTORY="$SCRIPT_DIR//.nuke/temp" + +DOTNET_GLOBAL_FILE="$SCRIPT_DIR//global.json" +DOTNET_INSTALL_URL="https://dot.net/v1/dotnet-install.sh" +DOTNET_CHANNEL="STS" + +export DOTNET_CLI_TELEMETRY_OPTOUT=1 +export DOTNET_NOLOGO=1 + +########################################################################### +# EXECUTION +########################################################################### + +function FirstJsonValue { + perl -nle 'print $1 if m{"'"$1"'": "([^"]+)",?}' <<< "${@:2}" +} + +# If dotnet CLI is installed globally and it matches requested version, use for execution +if [ -x "$(command -v dotnet)" ] && dotnet --version &>/dev/null; then + export DOTNET_EXE="$(command -v dotnet)" +else + # Download install script + DOTNET_INSTALL_FILE="$TEMP_DIRECTORY/dotnet-install.sh" + mkdir -p "$TEMP_DIRECTORY" + curl -Lsfo "$DOTNET_INSTALL_FILE" "$DOTNET_INSTALL_URL" + chmod +x "$DOTNET_INSTALL_FILE" + + # If global.json exists, load expected version + if [[ -f "$DOTNET_GLOBAL_FILE" ]]; then + DOTNET_VERSION=$(FirstJsonValue "version" "$(cat "$DOTNET_GLOBAL_FILE")") + if [[ "$DOTNET_VERSION" == "" ]]; then + unset DOTNET_VERSION + fi + fi + + # Install by channel or version + DOTNET_DIRECTORY="$TEMP_DIRECTORY/dotnet-unix" + if [[ -z ${DOTNET_VERSION+x} ]]; then + "$DOTNET_INSTALL_FILE" --install-dir "$DOTNET_DIRECTORY" --channel "$DOTNET_CHANNEL" --no-path + else + "$DOTNET_INSTALL_FILE" --install-dir "$DOTNET_DIRECTORY" --version "$DOTNET_VERSION" --no-path + fi + export DOTNET_EXE="$DOTNET_DIRECTORY/dotnet" + export PATH="$DOTNET_DIRECTORY:$PATH" +fi + +echo "Microsoft (R) .NET SDK version $("$DOTNET_EXE" --version)" + +if [[ ! -z ${NUKE_ENTERPRISE_TOKEN+x} && "$NUKE_ENTERPRISE_TOKEN" != "" ]]; then + "$DOTNET_EXE" nuget remove source "nuke-enterprise" &>/dev/null || true + "$DOTNET_EXE" nuget add source "https://f.feedz.io/nuke/enterprise/nuget" --name "nuke-enterprise" --username "PAT" --password "$NUKE_ENTERPRISE_TOKEN" --store-password-in-clear-text &>/dev/null || true +fi + +"$DOTNET_EXE" build "$BUILD_PROJECT_FILE" /nodeReuse:false /p:UseSharedCompilation=false -nologo -clp:NoSummary --verbosity quiet +"$DOTNET_EXE" run --project "$BUILD_PROJECT_FILE" --no-build -- "$@" diff --git a/build/.editorconfig b/build/.editorconfig new file mode 100644 index 0000000..31e43dc --- /dev/null +++ b/build/.editorconfig @@ -0,0 +1,11 @@ +[*.cs] +dotnet_style_qualification_for_field = false:warning +dotnet_style_qualification_for_property = false:warning +dotnet_style_qualification_for_method = false:warning +dotnet_style_qualification_for_event = false:warning +dotnet_style_require_accessibility_modifiers = never:warning + +csharp_style_expression_bodied_methods = true:silent +csharp_style_expression_bodied_properties = true:warning +csharp_style_expression_bodied_indexers = true:warning +csharp_style_expression_bodied_accessors = true:warning diff --git a/build/Build.cs b/build/Build.cs index ed4c808..81bc8e5 100644 --- a/build/Build.cs +++ b/build/Build.cs @@ -1,28 +1,23 @@ -using System; using System.Linq; using Nuke.Common; -using Nuke.Common.Execution; using Nuke.Common.IO; using Nuke.Common.Tools.DotNet; -using Nuke.Common.Tools.MSBuild; using Nuke.Common.Utilities.Collections; +using Serilog; using static Nuke.Common.IO.FileSystemTasks; -using static Nuke.Common.IO.PathConstruction; using static Nuke.Common.Tools.DotNet.DotNetTasks; using static Nuke.Common.Tools.MSBuild.MSBuildTasks; +using Nuke.Common.Tools.MSBuild; -// ReSharper disable ArrangeTypeMemberModifiers - -[CheckBuildProjectConfigurations] -[UnsetVisualStudioEnvironmentVariables] -internal class Build : NukeBuild +class Build : NukeBuild { const string InteractiveProjectName = "ReactiveMvvm.Avalonia"; const string CoverageFileName = "coverage.cobertura.xml"; public static int Main() => Execute(x => x.RunInteractive); - - [Parameter] readonly string Configuration = IsLocalBuild ? "Debug" : "Release"; + + [Parameter("Configuration to build - Default is 'Debug' (local) or 'Release' (server)")] + readonly Configuration Configuration = IsLocalBuild ? Configuration.Debug : Configuration.Release; [Parameter] readonly bool Interactive; [Parameter] readonly bool Full; @@ -34,8 +29,8 @@ internal class Build : NukeBuild .Executes(() => SourceDirectory .GlobDirectories("**/bin", "**/obj", "**/AppPackages", "**/BundleArtifacts") .Concat(RootDirectory.GlobDirectories("**/artifacts")) - .ForEach(DeleteDirectory)); - + .ForEach(ap => ap.DeleteDirectory())); + Target RunUnitTests => _ => _ .DependsOn(Clean) .Executes(() => SourceDirectory @@ -44,7 +39,7 @@ internal class Build : NukeBuild DotNetTest(settings => settings .SetProjectFile(path) .SetConfiguration(Configuration) - .SetLogger($"trx;LogFileName={ArtifactsDirectory / "report.trx"}") + .SetLoggers($"trx;LogFileName={ArtifactsDirectory / "report.trx"}") .AddProperty("CollectCoverage", true) .AddProperty("CoverletOutputFormat", "cobertura") .AddProperty("Exclude", "[xunit.*]*") @@ -77,108 +72,36 @@ internal class Build : NukeBuild .SetProjectFile(path) .SetConfiguration(Configuration)))); - Target CompileUniversalWindowsApp => _ => _ - .DependsOn(RunUnitTests) - .Executes(() => - { - var execute = EnvironmentInfo.IsWin && Full; - Logger.Info($"Should compile for Universal Windows: {execute}"); - if (!execute) return; - - Logger.Normal("Restoring packages required by UAP..."); - var project = SourceDirectory.GlobFiles("**/*.Uwp.csproj").First(); - MSBuild(settings => settings - .SetProjectFile(project) - .SetTargets("Restore")); - Logger.Success("Successfully restored UAP packages."); - - new[] { MSBuildTargetPlatform.x86, - MSBuildTargetPlatform.x64, - MSBuildTargetPlatform.arm } - .ForEach(BuildApp); - - void BuildApp(MSBuildTargetPlatform platform) - { - Logger.Normal("Cleaning UAP project..."); - MSBuild(settings => settings - .SetProjectFile(project) - .SetTargets("Clean")); - Logger.Success("Successfully managed to clean UAP project."); - - Logger.Normal($"Building UAP project for {platform}..."); - MSBuild(settings => settings - .SetProjectFile(project) - .SetTargets("Build") - .SetConfiguration(Configuration) - .SetTargetPlatform(platform) - .SetProperty("AppxPackageSigningEnabled", false) - .SetProperty("AppxPackageDir", ArtifactsDirectory) - .SetProperty("UapAppxPackageBuildMode", "CI") - .SetProperty("AppxBundle", "Always")); - Logger.Success($"Successfully built UAP project for {platform}."); - } - }); - - Target CompileXamarinAndroidApp => _ => _ + Target CompileMauiApp => _ => _ .DependsOn(RunUnitTests) - .Executes(() => - { - var execute = EnvironmentInfo.IsWin && Full; - Logger.Info($"Should compile for Android: {execute}"); - if (!execute) return; - - Logger.Normal("Restoring packages required by Xamarin Android..."); - var project = SourceDirectory.GlobFiles("**/*.Xamarin.Android.csproj").First(); - MSBuild(settings => settings - .SetProjectFile(project) - .SetTargets("Restore")); - Logger.Success("Successfully restored Xamarin Android packages."); - - Logger.Normal("Building Xamarin Android project..."); - var java = Environment.GetEnvironmentVariable("JAVA_HOME"); - MSBuild(settings => settings - .SetProjectFile(project) - .SetTargets("Build") - .SetConfiguration(Configuration) - .SetProperty("JavaSdkDirectory", java)); - Logger.Success("Successfully built Xamarin Android project."); - - Logger.Normal("Signing Android package..."); - MSBuild(settings => settings - .SetProjectFile(project) - .SetTargets("SignAndroidPackage") - .SetConfiguration(Configuration) - .SetProperty("JavaSdkDirectory", java)); - Logger.Success("Successfully signed Xamarin Android APK."); - - Logger.Normal("Moving APK files to artifacts directory..."); - SourceDirectory - .GlobFiles("**/bin/**/*-Signed.apk") - .ForEach(file => MoveFileToDirectory(file, ArtifactsDirectory)); - Logger.Success("Successfully moved APK files."); - }); + .Executes(() => SourceDirectory + .GlobFiles("**/*.Maui.csproj") + .ForEach(path => + DotNetBuild(settings => settings + .SetProjectFile(path) + .SetConfiguration(Configuration)))); Target CompileWindowsPresentationApp => _ => _ .DependsOn(RunUnitTests) .Executes(() => { var execute = EnvironmentInfo.IsWin && Full; - Logger.Info($"Should compile for WPF: {execute}"); + Log.Information($"Should compile for WPF: {execute}"); if (!execute) return; - Logger.Normal("Restoring packages required by WPF app..."); + Log.Debug("Restoring packages required by WPF app..."); var project = SourceDirectory.GlobFiles("**/*.Wpf.csproj").First(); MSBuild(settings => settings .SetProjectFile(project) .SetTargets("Restore")); - Logger.Success("Successfully restored Wpf packages."); + Log.Debug("Successfully restored Wpf packages."); - Logger.Normal("Building WPF project..."); + Log.Debug("Building WPF project..."); MSBuild(settings => settings .SetProjectFile(project) .SetTargets("Build") .SetConfiguration(Configuration)); - Logger.Success("Successfully built WPF project."); + Log.Debug("Successfully built WPF project."); }); Target CompileWindowsFormsApp => _ => _ @@ -186,38 +109,39 @@ void BuildApp(MSBuildTargetPlatform platform) .Executes(() => { var execute = EnvironmentInfo.IsWin && Full; - Logger.Info($"Should compile for Windows Forms: {execute}"); + Log.Information($"Should compile for Windows Forms: {execute}"); if (!execute) return; - Logger.Normal("Restoring packages required by Windows Forms app..."); + Log.Debug("Restoring packages required by Windows Forms app..."); var project = SourceDirectory.GlobFiles("**/*.WinForms.csproj").First(); MSBuild(settings => settings .SetProjectFile(project) .SetTargets("Restore")); - Logger.Success("Successfully restored Windows Forms packages."); + Log.Debug("Successfully restored Windows Forms packages."); - Logger.Normal("Building Windows Forms project..."); + Log.Debug("Building Windows Forms project..."); MSBuild(settings => settings .SetProjectFile(project) .SetTargets("Build") .SetConfiguration(Configuration)); - Logger.Success("Successfully built Windows Forms project."); + Log.Debug("Successfully built Windows Forms project."); }); Target RunInteractive => _ => _ .DependsOn(CompileAvaloniaApp) + .DependsOn(CompileBlazorApp) + .DependsOn(CompileMauiApp) .DependsOn(CompileTerminalApp) - .DependsOn(CompileUniversalWindowsApp) - .DependsOn(CompileXamarinAndroidApp) .DependsOn(CompileWindowsPresentationApp) .DependsOn(CompileWindowsFormsApp) .Executes(() => SourceDirectory .GlobFiles($"**/{InteractiveProjectName}.csproj") .Where(x => Interactive) - .ForEach(path => + .ForEach(path => DotNetRun(settings => settings .SetProjectFile(path) .SetConfiguration(Configuration) .EnableNoRestore() .EnableNoBuild()))); + } diff --git a/build/Configuration.cs b/build/Configuration.cs new file mode 100644 index 0000000..fc04a65 --- /dev/null +++ b/build/Configuration.cs @@ -0,0 +1,11 @@ +using System.ComponentModel; +using Nuke.Common.Tooling; + +[TypeConverter(typeof(TypeConverter))] +public class Configuration : Enumeration +{ + public static Configuration Debug = new Configuration { Value = nameof(Debug) }; + public static Configuration Release = new Configuration { Value = nameof(Release) }; + + public static implicit operator string(Configuration configuration) => configuration.Value; +} diff --git a/build/Directory.Build.props b/build/Directory.Build.props new file mode 100644 index 0000000..e147d63 --- /dev/null +++ b/build/Directory.Build.props @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/build/Directory.Build.targets b/build/Directory.Build.targets new file mode 100644 index 0000000..2532609 --- /dev/null +++ b/build/Directory.Build.targets @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/build/_build.csproj b/build/_build.csproj new file mode 100644 index 0000000..b1965fa --- /dev/null +++ b/build/_build.csproj @@ -0,0 +1,18 @@ + + + + Exe + net8.0 + + CS0649;CS0169;CA1050;CA1822;CA2211;IDE1006 + .. + .. + 1 + false + + + + + + + diff --git a/build/_build.csproj.DotSettings b/build/_build.csproj.DotSettings new file mode 100644 index 0000000..a778f33 --- /dev/null +++ b/build/_build.csproj.DotSettings @@ -0,0 +1,27 @@ + + DO_NOT_SHOW + DO_NOT_SHOW + DO_NOT_SHOW + DO_NOT_SHOW + DO_NOT_SHOW + Implicit + Implicit + ExpressionBody + 0 + NEXT_LINE + True + False + 120 + IF_OWNER_IS_SINGLE_LINE + WRAP_IF_LONG + False + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + True + True + True + True + True + True + True + True diff --git a/build/build.csproj b/build/build.csproj deleted file mode 100644 index fc18030..0000000 --- a/build/build.csproj +++ /dev/null @@ -1,34 +0,0 @@ - - - - Exe - netcoreapp3.1 - false - - False - CS0649;CS0169 - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/ReactiveMvvm.Avalonia/App.xaml.cs b/src/ReactiveMvvm.Avalonia/App.xaml.cs index dd5cbc1..77bbdc6 100644 --- a/src/ReactiveMvvm.Avalonia/App.xaml.cs +++ b/src/ReactiveMvvm.Avalonia/App.xaml.cs @@ -1,11 +1,10 @@ using Avalonia; -using Avalonia.Logging.Serilog; +using Avalonia.Logging; using Avalonia.Markup.Xaml; using ReactiveMvvm.Avalonia.Services; using ReactiveMvvm.Avalonia.Views; using ReactiveMvvm.Services; using ReactiveMvvm.ViewModels; -using Serilog; namespace ReactiveMvvm.Avalonia { @@ -19,12 +18,6 @@ public override void Initialize() public override void OnFrameworkInitializationCompleted() { -#if DEBUG - SerilogLogger.Initialize(new LoggerConfiguration() - .MinimumLevel.Warning() - .WriteTo.Trace(outputTemplate: "{Area}: {Message}") - .CreateLogger()); -#endif var view = new FeedbackView(); var context = new FeedbackViewModel( new AvaloniaSender(view), diff --git a/src/ReactiveMvvm.Avalonia/Program.cs b/src/ReactiveMvvm.Avalonia/Program.cs index 8ff5c02..6409278 100644 --- a/src/ReactiveMvvm.Avalonia/Program.cs +++ b/src/ReactiveMvvm.Avalonia/Program.cs @@ -1,5 +1,4 @@ using Avalonia; -using Avalonia.Logging.Serilog; using Avalonia.ReactiveUI; namespace ReactiveMvvm.Avalonia @@ -11,7 +10,6 @@ public sealed class Program public static AppBuilder BuildAvaloniaApp() => AppBuilder.Configure() .UseReactiveUI() - .UsePlatformDetect() - .LogToDebug(); + .UsePlatformDetect(); } } diff --git a/src/ReactiveMvvm.Avalonia/ReactiveMvvm.Avalonia.csproj b/src/ReactiveMvvm.Avalonia/ReactiveMvvm.Avalonia.csproj index cbcbacd..88b8399 100644 --- a/src/ReactiveMvvm.Avalonia/ReactiveMvvm.Avalonia.csproj +++ b/src/ReactiveMvvm.Avalonia/ReactiveMvvm.Avalonia.csproj @@ -1,22 +1,22 @@  - Exe - netcoreapp3.1 + WinExe + net8.0 + 11.0.7 %(Filename) - + Designer - + - - - - - + + + + diff --git a/src/ReactiveMvvm.Blazor.Server/ReactiveMvvm.Blazor.Server.csproj b/src/ReactiveMvvm.Blazor.Server/ReactiveMvvm.Blazor.Server.csproj index b6c8244..37d371a 100644 --- a/src/ReactiveMvvm.Blazor.Server/ReactiveMvvm.Blazor.Server.csproj +++ b/src/ReactiveMvvm.Blazor.Server/ReactiveMvvm.Blazor.Server.csproj @@ -1,6 +1,6 @@ - netcoreapp3.1 + net8.0 diff --git a/src/ReactiveMvvm.Blazor.Wasm/App.razor b/src/ReactiveMvvm.Blazor.Wasm/App.razor index 825d385..ea064d4 100644 --- a/src/ReactiveMvvm.Blazor.Wasm/App.razor +++ b/src/ReactiveMvvm.Blazor.Wasm/App.razor @@ -1,11 +1,13 @@ - - + + - -

Sorry, there's nothing at this address.

+ Not found + +

Sorry, there's nothing at this address.

-
+ \ No newline at end of file diff --git a/src/ReactiveMvvm.Blazor.Wasm/AppLayout.razor b/src/ReactiveMvvm.Blazor.Wasm/Layout/MainLayout.razor similarity index 98% rename from src/ReactiveMvvm.Blazor.Wasm/AppLayout.razor rename to src/ReactiveMvvm.Blazor.Wasm/Layout/MainLayout.razor index 7a5199d..849065e 100644 --- a/src/ReactiveMvvm.Blazor.Wasm/AppLayout.razor +++ b/src/ReactiveMvvm.Blazor.Wasm/Layout/MainLayout.razor @@ -1,5 +1,4 @@ @inherits LayoutComponentBase - \ No newline at end of file diff --git a/src/ReactiveMvvm.Blazor.Wasm/Program.cs b/src/ReactiveMvvm.Blazor.Wasm/Program.cs index e4def34..3727ac5 100644 --- a/src/ReactiveMvvm.Blazor.Wasm/Program.cs +++ b/src/ReactiveMvvm.Blazor.Wasm/Program.cs @@ -1,16 +1,13 @@ -using System.Threading.Tasks; +using Microsoft.AspNetCore.Components.Web; using Microsoft.AspNetCore.Components.WebAssembly.Hosting; +using ReactiveMvvm.Blazor.Wasm; +using ReactiveMvvm.Blazor; -namespace ReactiveMvvm.Blazor.Wasm -{ - public class Program - { - public static async Task Main(string[] args) - { - var host = WebAssemblyHostBuilder.CreateDefault(args); - host.RootComponents.Add("app"); - host.Services.AddAppServices(); - await host.Build().RunAsync(); - } - } -} +var builder = WebAssemblyHostBuilder.CreateDefault(args); +builder.RootComponents.Add("#app"); +builder.RootComponents.Add("head::after"); + +builder.Services + .AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) }) + .AddAppServices(); +await builder.Build().RunAsync(); diff --git a/src/ReactiveMvvm.Blazor.Wasm/Properties/launchSettings.json b/src/ReactiveMvvm.Blazor.Wasm/Properties/launchSettings.json index 54855e8..5178b9f 100644 --- a/src/ReactiveMvvm.Blazor.Wasm/Properties/launchSettings.json +++ b/src/ReactiveMvvm.Blazor.Wasm/Properties/launchSettings.json @@ -1,26 +1,38 @@ -{ +{ + "$schema": "http://json.schemastore.org/launchsettings.json", "iisSettings": { "windowsAuthentication": false, "anonymousAuthentication": true, "iisExpress": { - "applicationUrl": "http://localhost:46191", - "sslPort": 44383 + "applicationUrl": "http://localhost:30838", + "sslPort": 44365 } }, "profiles": { - "IIS Express": { - "commandName": "IISExpress", + "http": { + "commandName": "Project", + "dotnetRunMessages": true, "launchBrowser": true, "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", + "applicationUrl": "http://localhost:5082", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } }, - "ReactiveMvvm.Blazor.Wasm": { + "https": { "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", + "applicationUrl": "https://localhost:7250;http://localhost:5082", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "IIS Express": { + "commandName": "IISExpress", "launchBrowser": true, "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", - "applicationUrl": "https://localhost:5001;http://localhost:5000", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } diff --git a/src/ReactiveMvvm.Blazor.Wasm/ReactiveMvvm.Blazor.Wasm.csproj b/src/ReactiveMvvm.Blazor.Wasm/ReactiveMvvm.Blazor.Wasm.csproj index ceb90d4..254e119 100644 --- a/src/ReactiveMvvm.Blazor.Wasm/ReactiveMvvm.Blazor.Wasm.csproj +++ b/src/ReactiveMvvm.Blazor.Wasm/ReactiveMvvm.Blazor.Wasm.csproj @@ -1,15 +1,18 @@ - + + - netstandard2.1 - 3.0 + net8.0 + enable + enable - - - - - + + + + + + diff --git a/src/ReactiveMvvm.Blazor.Wasm/_Imports.razor b/src/ReactiveMvvm.Blazor.Wasm/_Imports.razor index b116757..9449d86 100644 --- a/src/ReactiveMvvm.Blazor.Wasm/_Imports.razor +++ b/src/ReactiveMvvm.Blazor.Wasm/_Imports.razor @@ -3,8 +3,10 @@ @using Microsoft.AspNetCore.Components.Forms @using Microsoft.AspNetCore.Components.Routing @using Microsoft.AspNetCore.Components.Web +@using Microsoft.AspNetCore.Components.Web.Virtualization @using Microsoft.AspNetCore.Components.WebAssembly.Http @using Microsoft.JSInterop @using ReactiveMvvm.Blazor.Wasm +@using ReactiveMvvm.Blazor.Wasm.Layout @using ReactiveMvvm.ViewModels -@using ReactiveUI.Blazor \ No newline at end of file +@using ReactiveUI.Blazor diff --git a/src/ReactiveMvvm.Blazor.Wasm/wwwroot/css/app.css b/src/ReactiveMvvm.Blazor.Wasm/wwwroot/css/app.css new file mode 100644 index 0000000..1cb4e4e --- /dev/null +++ b/src/ReactiveMvvm.Blazor.Wasm/wwwroot/css/app.css @@ -0,0 +1,77 @@ +.valid.modified:not([type=checkbox]) { + outline: 1px solid #26b050; +} + +.invalid { + outline: 1px solid red; +} + +.validation-message { + color: red; +} + +#blazor-error-ui { + background: lightyellow; + bottom: 0; + box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2); + display: none; + left: 0; + padding: 0.6rem 1.25rem 0.7rem 1.25rem; + position: fixed; + width: 100%; + z-index: 1000; +} + + #blazor-error-ui .dismiss { + cursor: pointer; + position: absolute; + right: 0.75rem; + top: 0.5rem; + } + +.blazor-error-boundary { + background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121; + padding: 1rem 1rem 1rem 3.7rem; + color: white; +} + + .blazor-error-boundary::after { + content: "An error has occurred." + } + +.loading-progress { + position: relative; + display: block; + width: 8rem; + height: 8rem; + margin: 20vh auto 1rem auto; +} + + .loading-progress circle { + fill: none; + stroke: #e0e0e0; + stroke-width: 0.6rem; + transform-origin: 50% 50%; + transform: rotate(-90deg); + } + + .loading-progress circle:last-child { + stroke: #1b6ec2; + stroke-dasharray: calc(3.141 * var(--blazor-load-percentage, 0%) * 0.8), 500%; + transition: stroke-dasharray 0.05s ease-in-out; + } + +.loading-progress-text { + position: absolute; + text-align: center; + font-weight: bold; + inset: calc(20vh + 3.25rem) 0 auto 0.2rem; +} + + .loading-progress-text:after { + content: var(--blazor-load-percentage-text, "Loading"); + } + +code { + color: #c02d76; +} diff --git a/src/ReactiveMvvm.Blazor.Wasm/wwwroot/icon-192.png b/src/ReactiveMvvm.Blazor.Wasm/wwwroot/icon-192.png new file mode 100644 index 0000000..166f56d Binary files /dev/null and b/src/ReactiveMvvm.Blazor.Wasm/wwwroot/icon-192.png differ diff --git a/src/ReactiveMvvm.Blazor.Wasm/wwwroot/index.html b/src/ReactiveMvvm.Blazor.Wasm/wwwroot/index.html index c5136de..e690e42 100644 --- a/src/ReactiveMvvm.Blazor.Wasm/wwwroot/index.html +++ b/src/ReactiveMvvm.Blazor.Wasm/wwwroot/index.html @@ -1,17 +1,24 @@ - + - + ReactiveMvvm.Blazor.Wasm - - - + + + - Loading... +
+ + + + +
+
An unhandled error has occurred. diff --git a/src/ReactiveMvvm.Blazor/ReactiveMvvm.Blazor.csproj b/src/ReactiveMvvm.Blazor/ReactiveMvvm.Blazor.csproj index 683f099..cd6a77a 100644 --- a/src/ReactiveMvvm.Blazor/ReactiveMvvm.Blazor.csproj +++ b/src/ReactiveMvvm.Blazor/ReactiveMvvm.Blazor.csproj @@ -1,11 +1,11 @@ - netstandard2.1 + net8.0 3.0 - - + + diff --git a/src/ReactiveMvvm.Maui/App.xaml b/src/ReactiveMvvm.Maui/App.xaml new file mode 100644 index 0000000..3e8bcb1 --- /dev/null +++ b/src/ReactiveMvvm.Maui/App.xaml @@ -0,0 +1,15 @@ + + + + + + + + + + + diff --git a/src/ReactiveMvvm.Maui/App.xaml.cs b/src/ReactiveMvvm.Maui/App.xaml.cs new file mode 100644 index 0000000..ff4d236 --- /dev/null +++ b/src/ReactiveMvvm.Maui/App.xaml.cs @@ -0,0 +1,12 @@ +namespace ReactiveMvvm.Maui +{ + public partial class App : Application + { + public App() + { + InitializeComponent(); + + MainPage = new AppShell(); + } + } +} diff --git a/src/ReactiveMvvm.Maui/AppShell.xaml b/src/ReactiveMvvm.Maui/AppShell.xaml new file mode 100644 index 0000000..2822806 --- /dev/null +++ b/src/ReactiveMvvm.Maui/AppShell.xaml @@ -0,0 +1,15 @@ + + + + + + diff --git a/src/ReactiveMvvm.Maui/AppShell.xaml.cs b/src/ReactiveMvvm.Maui/AppShell.xaml.cs new file mode 100644 index 0000000..9cd164b --- /dev/null +++ b/src/ReactiveMvvm.Maui/AppShell.xaml.cs @@ -0,0 +1,10 @@ +namespace ReactiveMvvm.Maui +{ + public partial class AppShell : Shell + { + public AppShell() + { + InitializeComponent(); + } + } +} diff --git a/src/ReactiveMvvm.Maui/MauiProgram.cs b/src/ReactiveMvvm.Maui/MauiProgram.cs new file mode 100644 index 0000000..7aa8e2c --- /dev/null +++ b/src/ReactiveMvvm.Maui/MauiProgram.cs @@ -0,0 +1,25 @@ +using Microsoft.Extensions.Logging; + +namespace ReactiveMvvm.Maui +{ + public static class MauiProgram + { + public static MauiApp CreateMauiApp() + { + var builder = MauiApp.CreateBuilder(); + builder + .UseMauiApp() + .ConfigureFonts(fonts => + { + fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular"); + fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold"); + }); + +#if DEBUG + builder.Logging.AddDebug(); +#endif + + return builder.Build(); + } + } +} diff --git a/src/ReactiveMvvm.Maui/Platforms/Android/AndroidManifest.xml b/src/ReactiveMvvm.Maui/Platforms/Android/AndroidManifest.xml new file mode 100644 index 0000000..0ecc98f --- /dev/null +++ b/src/ReactiveMvvm.Maui/Platforms/Android/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/src/ReactiveMvvm.Maui/Platforms/Android/MainActivity.cs b/src/ReactiveMvvm.Maui/Platforms/Android/MainActivity.cs new file mode 100644 index 0000000..aced559 --- /dev/null +++ b/src/ReactiveMvvm.Maui/Platforms/Android/MainActivity.cs @@ -0,0 +1,11 @@ +using Android.App; +using Android.Content.PM; +using Android.OS; + +namespace ReactiveMvvm.Maui +{ + [Activity(Theme = "@style/Maui.SplashTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize | ConfigChanges.Density)] + public class MainActivity : MauiAppCompatActivity + { + } +} diff --git a/src/ReactiveMvvm.Maui/Platforms/Android/MainApplication.cs b/src/ReactiveMvvm.Maui/Platforms/Android/MainApplication.cs new file mode 100644 index 0000000..31e9706 --- /dev/null +++ b/src/ReactiveMvvm.Maui/Platforms/Android/MainApplication.cs @@ -0,0 +1,16 @@ +using Android.App; +using Android.Runtime; + +namespace ReactiveMvvm.Maui +{ + [Application] + public class MainApplication : MauiApplication + { + public MainApplication(IntPtr handle, JniHandleOwnership ownership) + : base(handle, ownership) + { + } + + protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp(); + } +} diff --git a/src/ReactiveMvvm.Maui/Platforms/Android/Resources/values/colors.xml b/src/ReactiveMvvm.Maui/Platforms/Android/Resources/values/colors.xml new file mode 100644 index 0000000..c04d749 --- /dev/null +++ b/src/ReactiveMvvm.Maui/Platforms/Android/Resources/values/colors.xml @@ -0,0 +1,6 @@ + + + #512BD4 + #2B0B98 + #2B0B98 + \ No newline at end of file diff --git a/src/ReactiveMvvm.Maui/Platforms/MacCatalyst/AppDelegate.cs b/src/ReactiveMvvm.Maui/Platforms/MacCatalyst/AppDelegate.cs new file mode 100644 index 0000000..f7c01fa --- /dev/null +++ b/src/ReactiveMvvm.Maui/Platforms/MacCatalyst/AppDelegate.cs @@ -0,0 +1,10 @@ +using Foundation; + +namespace ReactiveMvvm.Maui +{ + [Register("AppDelegate")] + public class AppDelegate : MauiUIApplicationDelegate + { + protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp(); + } +} diff --git a/src/ReactiveMvvm.Maui/Platforms/MacCatalyst/Entitlements.plist b/src/ReactiveMvvm.Maui/Platforms/MacCatalyst/Entitlements.plist new file mode 100644 index 0000000..de4adc9 --- /dev/null +++ b/src/ReactiveMvvm.Maui/Platforms/MacCatalyst/Entitlements.plist @@ -0,0 +1,14 @@ + + + + + + + com.apple.security.app-sandbox + + + com.apple.security.network.client + + + + diff --git a/src/ReactiveMvvm.Maui/Platforms/MacCatalyst/Info.plist b/src/ReactiveMvvm.Maui/Platforms/MacCatalyst/Info.plist new file mode 100644 index 0000000..7268977 --- /dev/null +++ b/src/ReactiveMvvm.Maui/Platforms/MacCatalyst/Info.plist @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + UIDeviceFamily + + 2 + + UIRequiredDeviceCapabilities + + arm64 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + XSAppIconAssets + Assets.xcassets/appicon.appiconset + + diff --git a/src/ReactiveMvvm.Maui/Platforms/MacCatalyst/Program.cs b/src/ReactiveMvvm.Maui/Platforms/MacCatalyst/Program.cs new file mode 100644 index 0000000..c6ce2c2 --- /dev/null +++ b/src/ReactiveMvvm.Maui/Platforms/MacCatalyst/Program.cs @@ -0,0 +1,16 @@ +using ObjCRuntime; +using UIKit; + +namespace ReactiveMvvm.Maui +{ + public class Program + { + // This is the main entry point of the application. + 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(AppDelegate)); + } + } +} diff --git a/src/ReactiveMvvm.Maui/Platforms/Tizen/Main.cs b/src/ReactiveMvvm.Maui/Platforms/Tizen/Main.cs new file mode 100644 index 0000000..ad7f4f2 --- /dev/null +++ b/src/ReactiveMvvm.Maui/Platforms/Tizen/Main.cs @@ -0,0 +1,17 @@ +using Microsoft.Maui; +using Microsoft.Maui.Hosting; +using System; + +namespace ReactiveMvvm.Maui +{ + internal class Program : MauiApplication + { + protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp(); + + static void Main(string[] args) + { + var app = new Program(); + app.Run(args); + } + } +} diff --git a/src/ReactiveMvvm.Maui/Platforms/Tizen/tizen-manifest.xml b/src/ReactiveMvvm.Maui/Platforms/Tizen/tizen-manifest.xml new file mode 100644 index 0000000..d8eecf1 --- /dev/null +++ b/src/ReactiveMvvm.Maui/Platforms/Tizen/tizen-manifest.xml @@ -0,0 +1,15 @@ + + + + + + maui-appicon-placeholder + + + + + http://tizen.org/privilege/internet + + + + \ No newline at end of file diff --git a/src/ReactiveMvvm.Maui/Platforms/Windows/App.xaml b/src/ReactiveMvvm.Maui/Platforms/Windows/App.xaml new file mode 100644 index 0000000..56b83ce --- /dev/null +++ b/src/ReactiveMvvm.Maui/Platforms/Windows/App.xaml @@ -0,0 +1,8 @@ + + + diff --git a/src/ReactiveMvvm.Maui/Platforms/Windows/App.xaml.cs b/src/ReactiveMvvm.Maui/Platforms/Windows/App.xaml.cs new file mode 100644 index 0000000..b061a38 --- /dev/null +++ b/src/ReactiveMvvm.Maui/Platforms/Windows/App.xaml.cs @@ -0,0 +1,25 @@ +using Microsoft.UI.Xaml; + +// To learn more about WinUI, the WinUI project structure, +// and more about our project templates, see: http://aka.ms/winui-project-info. + +namespace ReactiveMvvm.Maui.WinUI +{ + /// + /// Provides application-specific behavior to supplement the default Application class. + /// + public partial class App : MauiWinUIApplication + { + /// + /// 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 override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp(); + } + +} diff --git a/src/ReactiveMvvm.Maui/Platforms/Windows/Package.appxmanifest b/src/ReactiveMvvm.Maui/Platforms/Windows/Package.appxmanifest new file mode 100644 index 0000000..eec7af0 --- /dev/null +++ b/src/ReactiveMvvm.Maui/Platforms/Windows/Package.appxmanifest @@ -0,0 +1,46 @@ + + + + + + + + + $placeholder$ + User Name + $placeholder$.png + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/ReactiveMvvm.Maui/Platforms/Windows/app.manifest b/src/ReactiveMvvm.Maui/Platforms/Windows/app.manifest new file mode 100644 index 0000000..e38fd6d --- /dev/null +++ b/src/ReactiveMvvm.Maui/Platforms/Windows/app.manifest @@ -0,0 +1,15 @@ + + + + + + + + true/PM + PerMonitorV2, PerMonitor + + + diff --git a/src/ReactiveMvvm.Maui/Platforms/iOS/AppDelegate.cs b/src/ReactiveMvvm.Maui/Platforms/iOS/AppDelegate.cs new file mode 100644 index 0000000..f7c01fa --- /dev/null +++ b/src/ReactiveMvvm.Maui/Platforms/iOS/AppDelegate.cs @@ -0,0 +1,10 @@ +using Foundation; + +namespace ReactiveMvvm.Maui +{ + [Register("AppDelegate")] + public class AppDelegate : MauiUIApplicationDelegate + { + protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp(); + } +} diff --git a/src/ReactiveMvvm.Maui/Platforms/iOS/Info.plist b/src/ReactiveMvvm.Maui/Platforms/iOS/Info.plist new file mode 100644 index 0000000..0004a4f --- /dev/null +++ b/src/ReactiveMvvm.Maui/Platforms/iOS/Info.plist @@ -0,0 +1,32 @@ + + + + + LSRequiresIPhoneOS + + UIDeviceFamily + + 1 + 2 + + UIRequiredDeviceCapabilities + + arm64 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + XSAppIconAssets + Assets.xcassets/appicon.appiconset + + diff --git a/src/ReactiveMvvm.Maui/Platforms/iOS/Program.cs b/src/ReactiveMvvm.Maui/Platforms/iOS/Program.cs new file mode 100644 index 0000000..c6ce2c2 --- /dev/null +++ b/src/ReactiveMvvm.Maui/Platforms/iOS/Program.cs @@ -0,0 +1,16 @@ +using ObjCRuntime; +using UIKit; + +namespace ReactiveMvvm.Maui +{ + public class Program + { + // This is the main entry point of the application. + 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(AppDelegate)); + } + } +} diff --git a/src/ReactiveMvvm.Maui/ReactiveMvvm.Maui.csproj b/src/ReactiveMvvm.Maui/ReactiveMvvm.Maui.csproj new file mode 100644 index 0000000..be3ef88 --- /dev/null +++ b/src/ReactiveMvvm.Maui/ReactiveMvvm.Maui.csproj @@ -0,0 +1,76 @@ + + + + net8.0-android;net8.0-ios;net8.0-maccatalyst + $(TargetFrameworks);net8.0-windows10.0.19041.0 + + + + + + + Exe + ReactiveMvvm.Maui + true + true + enable + enable + + + ReactiveMvvm.Maui + + + com.companyname.reactivemvvm.maui + + + 1.0 + 1 + + 11.0 + 13.1 + 21.0 + 10.0.17763.0 + 10.0.17763.0 + 6.5 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + MSBuild:Compile + + + + diff --git a/src/ReactiveMvvm.Maui/Resources/AppIcon/appicon.svg b/src/ReactiveMvvm.Maui/Resources/AppIcon/appicon.svg new file mode 100644 index 0000000..9d63b65 --- /dev/null +++ b/src/ReactiveMvvm.Maui/Resources/AppIcon/appicon.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/ReactiveMvvm.Maui/Resources/AppIcon/appiconfg.svg b/src/ReactiveMvvm.Maui/Resources/AppIcon/appiconfg.svg new file mode 100644 index 0000000..21dfb25 --- /dev/null +++ b/src/ReactiveMvvm.Maui/Resources/AppIcon/appiconfg.svg @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/src/ReactiveMvvm.Maui/Resources/Fonts/OpenSans-Regular.ttf b/src/ReactiveMvvm.Maui/Resources/Fonts/OpenSans-Regular.ttf new file mode 100644 index 0000000..9ab655d Binary files /dev/null and b/src/ReactiveMvvm.Maui/Resources/Fonts/OpenSans-Regular.ttf differ diff --git a/src/ReactiveMvvm.Maui/Resources/Fonts/OpenSans-Semibold.ttf b/src/ReactiveMvvm.Maui/Resources/Fonts/OpenSans-Semibold.ttf new file mode 100644 index 0000000..2b7468e Binary files /dev/null and b/src/ReactiveMvvm.Maui/Resources/Fonts/OpenSans-Semibold.ttf differ diff --git a/src/ReactiveMvvm.Maui/Resources/Images/dotnet_bot.png b/src/ReactiveMvvm.Maui/Resources/Images/dotnet_bot.png new file mode 100644 index 0000000..f93ce02 Binary files /dev/null and b/src/ReactiveMvvm.Maui/Resources/Images/dotnet_bot.png differ diff --git a/src/ReactiveMvvm.Maui/Resources/Raw/AboutAssets.txt b/src/ReactiveMvvm.Maui/Resources/Raw/AboutAssets.txt new file mode 100644 index 0000000..15d6244 --- /dev/null +++ b/src/ReactiveMvvm.Maui/Resources/Raw/AboutAssets.txt @@ -0,0 +1,15 @@ +Any raw assets you want to be deployed with your application can be placed in +this directory (and child directories). Deployment of the asset to your application +is automatically handled by the following `MauiAsset` Build Action within your `.csproj`. + + + +These files will be deployed with you package and will be accessible using Essentials: + + async Task LoadMauiAsset() + { + using var stream = await FileSystem.OpenAppPackageFileAsync("AboutAssets.txt"); + using var reader = new StreamReader(stream); + + var contents = reader.ReadToEnd(); + } diff --git a/src/ReactiveMvvm.Maui/Resources/Splash/splash.svg b/src/ReactiveMvvm.Maui/Resources/Splash/splash.svg new file mode 100644 index 0000000..21dfb25 --- /dev/null +++ b/src/ReactiveMvvm.Maui/Resources/Splash/splash.svg @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/src/ReactiveMvvm.Maui/Resources/Styles/Colors.xaml b/src/ReactiveMvvm.Maui/Resources/Styles/Colors.xaml new file mode 100644 index 0000000..30307a5 --- /dev/null +++ b/src/ReactiveMvvm.Maui/Resources/Styles/Colors.xaml @@ -0,0 +1,45 @@ + + + + + + + #512BD4 + #ac99ea + #242424 + #DFD8F7 + #9880e5 + #2B0B98 + + White + Black + #D600AA + #190649 + #1f1f1f + + #E1E1E1 + #C8C8C8 + #ACACAC + #919191 + #6E6E6E + #404040 + #212121 + #141414 + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/ReactiveMvvm.Maui/Resources/Styles/Styles.xaml b/src/ReactiveMvvm.Maui/Resources/Styles/Styles.xaml new file mode 100644 index 0000000..e0d36bb --- /dev/null +++ b/src/ReactiveMvvm.Maui/Resources/Styles/Styles.xaml @@ -0,0 +1,426 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/ReactiveMvvm.Xamarin/Services/XamarinSender.cs b/src/ReactiveMvvm.Maui/Services/XamarinSender.cs similarity index 54% rename from src/ReactiveMvvm.Xamarin/Services/XamarinSender.cs rename to src/ReactiveMvvm.Maui/Services/XamarinSender.cs index 2593dde..f5a7a01 100644 --- a/src/ReactiveMvvm.Xamarin/Services/XamarinSender.cs +++ b/src/ReactiveMvvm.Maui/Services/XamarinSender.cs @@ -1,15 +1,9 @@ using ReactiveMvvm.Interfaces; -using System.Threading.Tasks; -using Xamarin.Forms; -namespace ReactiveMvvm.Xamarin.Services +namespace ReactiveMvvm.Maui.Services { - public sealed class XamarinSender : ISender + public sealed class XamarinSender(Page view) : ISender { - private readonly Page view; - - public XamarinSender(Page view) => this.view = view; - public async Task Send(string title, string message, int section, bool bug) { var content = $"{message}, Bug: {bug}, Section: {section}"; diff --git a/src/ReactiveMvvm.Xamarin/Views/FeedbackView.xaml b/src/ReactiveMvvm.Maui/Views/FeedbackView.xaml similarity index 72% rename from src/ReactiveMvvm.Xamarin/Views/FeedbackView.xaml rename to src/ReactiveMvvm.Maui/Views/FeedbackView.xaml index 7566a12..7fd53cc 100644 --- a/src/ReactiveMvvm.Xamarin/Views/FeedbackView.xaml +++ b/src/ReactiveMvvm.Maui/Views/FeedbackView.xaml @@ -1,13 +1,13 @@ - + xmlns:rxui="clr-namespace:ReactiveUI.Maui;assembly=ReactiveUI.Maui" + xmlns:vm="clr-namespace:ReactiveMvvm.ViewModels;assembly=ReactiveMvvm" + x:TypeArguments="vm:FeedbackViewModel"> - -