Skip to content

Commit

Permalink
Merge branch 'release/8.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
TimLariviere committed Apr 25, 2024
2 parents 67804e8 + c76cb1f commit b934a43
Show file tree
Hide file tree
Showing 28 changed files with 667 additions and 0 deletions.
7 changes: 7 additions & 0 deletions Fabulous.MauiControls.sln
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "NavigationPath", "samples\N
EndProject
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "ComponentNavigation", "samples\Navigation\ComponentNavigation\ComponentNavigation.fsproj", "{66532A61-1BB8-4BD1-A281-A160ABB0EFE7}"
EndProject
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Calculator", "samples\Calculator\Calculator.fsproj", "{E24F96A8-B1FF-45AA-A7D9-379F3F88F422}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -130,6 +132,10 @@ Global
{5B3F6C4E-82CF-442F-BFB4-216C1CD85700}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5B3F6C4E-82CF-442F-BFB4-216C1CD85700}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5B3F6C4E-82CF-442F-BFB4-216C1CD85700}.Release|Any CPU.Build.0 = Release|Any CPU
{E24F96A8-B1FF-45AA-A7D9-379F3F88F422}.Release|Any CPU.Build.0 = Release|Any CPU
{E24F96A8-B1FF-45AA-A7D9-379F3F88F422}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E24F96A8-B1FF-45AA-A7D9-379F3F88F422}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E24F96A8-B1FF-45AA-A7D9-379F3F88F422}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{66532A61-1BB8-4BD1-A281-A160ABB0EFE7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{66532A61-1BB8-4BD1-A281-A160ABB0EFE7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{66532A61-1BB8-4BD1-A281-A160ABB0EFE7}.Release|Any CPU.ActiveCfg = Release|Any CPU
Expand All @@ -152,6 +158,7 @@ Global
{3A3581BD-4228-49B0-84D5-AF39D620BA34} = {87C8E9E8-497E-46DB-90FE-4402E0CB230A}
{CE61493B-86CC-49CE-9443-F25F1ECB15C9} = {3A3581BD-4228-49B0-84D5-AF39D620BA34}
{5B3F6C4E-82CF-442F-BFB4-216C1CD85700} = {3A3581BD-4228-49B0-84D5-AF39D620BA34}
{E24F96A8-B1FF-45AA-A7D9-379F3F88F422} = {87C8E9E8-497E-46DB-90FE-4402E0CB230A}
{66532A61-1BB8-4BD1-A281-A160ABB0EFE7} = {3A3581BD-4228-49B0-84D5-AF39D620BA34}
EndGlobalSection
EndGlobal
154 changes: 154 additions & 0 deletions samples/Calculator/App.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
namespace Calculator

open System
open Fabulous
open Fabulous.Maui
open Microsoft.Maui.Controls
open Microsoft.Maui.Graphics

open type Fabulous.Maui.View

module App =
type Operator =
| Add
| Subtract
| Multiply
| Divide

/// Represents a calculator button press
type Msg =
| Operator of Operator
| Digit of int
| Equals
| Clear

type Operand = double

// We can't represent an invalid state with this model.
// This greatly reduces the amount of validation required.
type Model =
| Initial
| Operand of Operand // 1
| OperandOperator of Operand * Operator // 1 +
| OperandOperatorOperand of Operand * Operator * Operand // 1 + 1
| Result of double // 2
| Error

let calculateOperation op1 op2 operator =
match operator with
| Add -> op1 + op2
| Subtract -> op1 - op2
| Multiply -> op1 * op2
| Divide -> op1 / op2

let calculate model msg =
match model with
| OperandOperatorOperand(_, Divide, 0.0) -> Error
| OperandOperatorOperand(op1, operator, op2) ->
let res = calculateOperation op1 op2 operator

match msg with
| Equals -> Result(res)
| Operator operator ->
// pass the result in as the start of a new calculation (1 + 1 + -> 2 +)
OperandOperator(res, operator)
| _ -> model
| _ -> model

let update msg model =
match msg with
| Clear -> Initial
| Digit digit ->
match model with
| Initial
| Error
| Result _ -> Operand(double digit)
| Operand op -> Operand(double(string op + string digit))
| OperandOperator(operand, operator) -> OperandOperatorOperand(operand, operator, double digit)
| OperandOperatorOperand(op1, operator, op2) -> OperandOperatorOperand(op1, operator, double(string op2 + string digit))
| Operator operator ->
match model with
| Initial
| Error -> model
| Result operand // previously calculated result is now the first operand
| Operand operand
| OperandOperator(operand, _) -> OperandOperator(operand, operator)
| OperandOperatorOperand _ -> calculate model msg
| Equals -> calculate model msg

let display model =
match model with
| Initial -> "0"
| Operand op
| OperandOperator(op, _)
| OperandOperatorOperand(_, _, op) -> string op
| Result res -> string res
| Error -> "Error"

let view (model: Model) =
let mkButton text (onClicked: 'msg) row column =
Button(text, onClicked)
.gridRow(row)
.gridColumn(column)
.font(size = 36.0)
.cornerRadius(0)

let mkNumberButton number row column =
(mkButton (string number) (Digit number) row column)
.background(Colors.White)
.textColor(Colors.Black)

let orange = Color.FromRgb(0xff, 0xa5, 0)
let gray = Color.FromRgb(0x80, 0x80, 0x80)

let mkOperatorButton text operator row column =
(mkButton text (Operator operator) row column)
.background(orange)
.textColor(Colors.Black)

Application(
ContentPage(
(Grid(rowdefs = [ Star; Star; Star; Star; Star; Star ], coldefs = [ Star; Star; Star; Star ]) {
View
.Label(display model)
.font(size = 48.0, attributes = FontAttributes.Bold)
.background(Colors.Black)
.textColor(Colors.White)
.alignEndTextHorizontal()
.centerTextVertical()
.gridColumnSpan(4)

mkNumberButton 7 1 0
mkNumberButton 8 1 1
mkNumberButton 9 1 2
mkNumberButton 4 2 0
mkNumberButton 5 2 1
mkNumberButton 6 2 2
mkNumberButton 1 3 0
mkNumberButton 2 3 1
mkNumberButton 3 3 2

(mkNumberButton 0 4 0).gridColumnSpan(3)

mkOperatorButton "÷" Divide 1 3
mkOperatorButton "×" Multiply 2 3
mkOperatorButton "-" Subtract 3 3
mkOperatorButton "+" Add 4 3
(mkButton "A" Clear 5 0).background(gray).textColor(Colors.White)
(mkButton "." Equals 5 1).background(orange).textColor(Colors.Black)

(mkButton "=" Equals 5 2)
.background(orange)
.gridColumnSpan(2)
.textColor(Colors.White)
})
.rowSpacing(1.0)
.columnSpacing(1.0)
.background(gray)
)
)

let program =
Program.stateful (fun () -> Initial) update
|> Program.withTrace Console.WriteLine
|> Program.withView view
108 changes: 108 additions & 0 deletions samples/Calculator/Calculator.fsproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net8.0-android;net8.0-ios;net8.0-maccatalyst</TargetFrameworks>
<TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows'))">$(TargetFrameworks);net8.0-windows10.0.19041.0</TargetFrameworks>
<!-- Uncomment to also build the tizen app. You will need to install tizen by following this: https://github.com/Samsung/Tizen.NET -->
<!-- <TargetFrameworks>$(TargetFrameworks);net8.0-tizen</TargetFrameworks> -->
<OutputType>Exe</OutputType>
<RootNamespace>TicTacToe</RootNamespace>
<UseMaui>true</UseMaui>
<SingleProject>true</SingleProject>
<EnableDefaultItems>false</EnableDefaultItems>

<!-- Display name -->
<ApplicationTitle>Calculator</ApplicationTitle>

<!-- App Identifier -->
<ApplicationId>org.fabulous.maui.calculator</ApplicationId>
<ApplicationIdGuid>10ca89bf-7a9c-4cc5-a62a-02cf81ae1708</ApplicationIdGuid>

<!-- Versions -->
<ApplicationDisplayVersion>1.0</ApplicationDisplayVersion>
<ApplicationVersion>1</ApplicationVersion>

<TargetPlatformIdentifier Condition=" $(TargetPlatformIdentifier) == '' ">$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)'))</TargetPlatformIdentifier>

<SupportedOSPlatformVersion Condition="$(TargetPlatformIdentifier) == 'ios'">14.2</SupportedOSPlatformVersion>
<SupportedOSPlatformVersion Condition="$(TargetPlatformIdentifier) == 'maccatalyst'">14.0</SupportedOSPlatformVersion>
<SupportedOSPlatformVersion Condition="$(TargetPlatformIdentifier) == 'android'">21.0</SupportedOSPlatformVersion>
<SupportedOSPlatformVersion Condition="$(TargetPlatformIdentifier) == 'windows'">10.0.17763.0</SupportedOSPlatformVersion>
<TargetPlatformMinVersion Condition="$(TargetPlatformIdentifier) == 'windows'">10.0.17763.0</TargetPlatformMinVersion>
<SupportedOSPlatformVersion Condition="$(TargetPlatformIdentifier) == 'tizen'">6.5</SupportedOSPlatformVersion>
</PropertyGroup>

<ItemGroup>
<Compile Include="App.fs" />
<Compile Include="MauiProgram.fs" />
</ItemGroup>

<ItemGroup>
<!-- App Icon -->
<MauiIcon Include="Resources\AppIcon\appicon.svg" ForegroundFile="Resources\AppIcon\appiconfg.svg" Color="#512BD4" />

<!-- Custom Fonts -->
<MauiFont Include="Resources\Fonts\*" />

<!-- Images -->
<MauiImage Include="Resources\Images\*" />
<MauiImage Update="Resources\Images\dotnet_bot.svg" BaseSize="168,208" />

<!-- Raw Assets (also remove the "Resources\Raw" prefix) -->
<MauiAsset Include="Resources\Raw\*" LogicalName="%(RecursiveDir)%(Filename)%(Extension)" />

<!-- Splash Screen -->
<MauiSplashScreen Include="Resources\Splash\splash.svg" Color="#512BD4" BaseSize="128,128" />
</ItemGroup>

<ItemGroup Condition="$(TargetPlatformIdentifier) == 'android'">
<AndroidResource Include="$(AndroidProjectFolder)Resources/*/*" />
<AndroidResource Remove="$(AndroidProjectFolder)Resources/raw/.*" />
<AndroidResource Update="$(AndroidProjectFolder)Resources/raw/*" />
<AndroidAsset Include="$(AndroidProjectFolder)Assets/**/*" Exclude="$(AndroidProjectFolder)Assets/**/.*/**" />
<AndroidManifest Include="$(AndroidProjectFolder)AndroidManifest.xml" />
<Compile Include="$(AndroidProjectFolder)MainActivity.fs" />
<Compile Include="$(AndroidProjectFolder)MainApplication.fs" />
</ItemGroup>

<ItemGroup Condition="$(TargetPlatformIdentifier) == 'ios'">
<None Include="$(iOSProjectFolder)Info.plist" LogicalName="Info.plist" />
<Compile Include="$(iOSProjectFolder)AppDelegate.fs" />
<Compile Include="$(iOSProjectFolder)Program.fs" />
</ItemGroup>

<ItemGroup Condition="$(TargetPlatformIdentifier) == 'maccatalyst'">
<None Include="$(MacCatalystProjectFolder)Info.plist" LogicalName="Info.plist" />
<Compile Include="$(MacCatalystProjectFolder)AppDelegate.fs" />
<Compile Include="$(MacCatalystProjectFolder)Program.fs" />
</ItemGroup>

<ItemGroup Condition="$(TargetPlatformIdentifier) == 'windows'">
<Manifest Include="$(WindowsProjectFolder)app.manifest" />
<AppxManifest Include="$(WindowsProjectFolder)Package.appxmanifest" />
<Compile Include="$(WindowsProjectFolder)App.fs" />
<Compile Include="$(WindowsProjectFolder)Main.fs" />

<PackageReference Include="FSharp.Maui.WinUICompat" />
</ItemGroup>

<ItemGroup Condition="$(TargetPlatformIdentifier) == 'tizen'">
<TizenManifestFile Include="$(TizenProjectFolder)tizen-manifest.xml" />
<Compile Include="$(TizenProjectFolder)Main.fs" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="FSharp.Core" />
<PackageReference Include="Microsoft.Extensions.Configuration" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" />
<PackageReference Include="Microsoft.Extensions.Logging" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" />
<PackageReference Include="Microsoft.Maui.Controls" />
<PackageReference Include="Microsoft.Maui.Controls.Compatibility" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\src\Fabulous.MauiControls\Fabulous.MauiControls.fsproj" />
</ItemGroup>

</Project>
16 changes: 16 additions & 0 deletions samples/Calculator/MauiProgram.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
namespace Calculator

open Microsoft.Maui.Hosting
open Fabulous.Maui

type MauiProgram =
static member CreateMauiApp() =
MauiApp
.CreateBuilder()
.UseFabulousApp(App.program)
.ConfigureFonts(fun fonts ->
fonts
.AddFont("OpenSans-Regular.ttf", "OpenSansRegular")
.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold")
|> ignore)
.Build()
6 changes: 6 additions & 0 deletions samples/Calculator/Platforms/Android/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application android:allowBackup="true" android:icon="@mipmap/appicon" android:roundIcon="@mipmap/appicon_round" android:supportsRtl="true"></application>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
</manifest>
17 changes: 17 additions & 0 deletions samples/Calculator/Platforms/Android/MainActivity.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
namespace Calculator

open Android.App
open Android.Content.PM
open Microsoft.Maui

[<Activity(Theme = "@style/Maui.SplashTheme",
MainLauncher = true,
ConfigurationChanges =
(ConfigChanges.ScreenSize
||| ConfigChanges.Orientation
||| ConfigChanges.UiMode
||| ConfigChanges.ScreenLayout
||| ConfigChanges.SmallestScreenSize
||| ConfigChanges.Density))>]
type MainActivity() =
inherit MauiAppCompatActivity()
10 changes: 10 additions & 0 deletions samples/Calculator/Platforms/Android/MainApplication.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace Calculator

open Android.App
open Microsoft.Maui

[<Application>]
type MainApplication(handle, ownership) =
inherit MauiApplication(handle, ownership)

override _.CreateMauiApp() = MauiProgram.CreateMauiApp()
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">#512BD4</color>
<color name="colorPrimaryDark">#2B0B98</color>
<color name="colorAccent">#2B0B98</color>
</resources>
10 changes: 10 additions & 0 deletions samples/Calculator/Platforms/MacCatalyst/AppDelegate.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace Calculator

open Foundation
open Microsoft.Maui

[<Register("AppDelegate")>]
type AppDelegate() =
inherit MauiUIApplicationDelegate()

override this.CreateMauiApp() = MauiProgram.CreateMauiApp()
30 changes: 30 additions & 0 deletions samples/Calculator/Platforms/MacCatalyst/Info.plist
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>UIDeviceFamily</key>
<array>
<integer>1</integer>
<integer>2</integer>
</array>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>arm64</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>XSAppIconAssets</key>
<string>Assets.xcassets/appicon.appiconset</string>
</dict>
</plist>
Loading

0 comments on commit b934a43

Please sign in to comment.