Skip to content

Commit

Permalink
Frontend(XF,Maui): added remaining pages
Browse files Browse the repository at this point in the history
Added PairingToPage, PairingFromPage, Send, Receive pages.

Made PairingFrom page work on Maui by moving configuration
of barcode view from .xaml file to code. Use Grid instead
of StackLayout so that Maui layout is fixed. Upgrade SendPage
layout so that Maui and Xamarin look like each other.

Abstracted creation of barcode scanner page to
FrontendHelpers.GetBarcodeScannerPage function. Moved platform
checking logic to one place (canScanBarcode variable).
This removes code duplication between XF and Maui.

If QR code is invalid, show alert to the user instead of
crashing the app.

Fix crash after scanning barcode by checking if modal stack
is not empty before calling PopModalAsync().

Co-authored-by: Parham <[email protected]>
  • Loading branch information
webwarrior-ws and parhamsaremi committed Dec 10, 2024
1 parent 6610b6b commit 919e40e
Show file tree
Hide file tree
Showing 10 changed files with 203 additions and 60 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -102,3 +102,7 @@ src/GWallet.Frontend.Maui/WelcomePage.xaml
src/GWallet.Frontend.Maui/WelcomePage2.xaml
src/GWallet.Frontend.Maui/LoadingPage.xaml
src/GWallet.Frontend.Maui/BalancesPage.xaml
src/GWallet.Frontend.Maui/PairingFromPage.xaml
src/GWallet.Frontend.Maui/PairingToPage.xaml
src/GWallet.Frontend.Maui/SendPage.xaml
src/GWallet.Frontend.Maui/ReceivePage.xaml
14 changes: 13 additions & 1 deletion scripts/make.fsx
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,17 @@ let BuildSolutionOrProject
// TODO: we have to change this function to be the other way around (i.e. copy from Maui to XF) once we
// have a finished version of Maui and we consider XF as legacy.
let CopyXamlFiles() =
let files = [| "WelcomePage.xaml"; "WelcomePage2.xaml"; "LoadingPage.xaml"; "BalancesPage.xaml" |]
let files =
[|
"WelcomePage.xaml"
"WelcomePage2.xaml"
"LoadingPage.xaml"
"BalancesPage.xaml"
"PairingFromPage.xaml"
"PairingToPage.xaml"
"ReceivePage.xaml"
"SendPage.xaml"
|]
for file in files do
let sourcePath = Path.Combine("src", "GWallet.Frontend.XF", file)
let destPath = Path.Combine("src", "GWallet.Frontend.Maui", file)
Expand All @@ -271,7 +281,9 @@ let CopyXamlFiles() =
destPath,
fileText
.Replace("http://xamarin.com/schemas/2014/forms","http://schemas.microsoft.com/dotnet/2021/maui")
.Replace("clr-namespace:ZXing.Net.Mobile.Forms;assembly=ZXing.Net.Mobile.Forms","clr-namespace:ZXing.Net.Maui.Controls;assembly=ZXing.Net.MAUI.Controls")
.Replace("GWallet.Frontend.XF", "GWallet.Frontend.Maui")
.Replace("ZXingBarcodeImageView", "BarcodeGeneratorView")
)


Expand Down
16 changes: 16 additions & 0 deletions src/GWallet.Frontend.Maui/GWallet.Frontend.Maui.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -143,13 +143,29 @@
</ItemGroup>

<ItemGroup>
<EmbeddedResource Include="PairingFromPage.xaml" />
<EmbeddedResource Include="PairingToPage.xaml" />
<EmbeddedResource Include="SendPage.xaml" />
<EmbeddedResource Include="ReceivePage.xaml" />
<EmbeddedResource Include="BalancesPage.xaml" />
<EmbeddedResource Include="LoadingPage.xaml" />
<EmbeddedResource Include="WelcomePage.xaml" />
<EmbeddedResource Include="WelcomePage2.xaml" />
<Compile Include="..\GWallet.Frontend.XF\Controls\CircleChartView.fs" />
<Compile Include="..\GWallet.Frontend.XF\FrontendHelpers.fs" />
<Compile Include="..\GWallet.Frontend.XF\GlobalState.fs" />
<Compile Include="..\GWallet.Frontend.XF\PairingFromPage.xaml.fs">
<DependentUpon>PairingFromPage.xaml</DependentUpon>
</Compile>
<Compile Include="..\GWallet.Frontend.XF\PairingToPage.xaml.fs">
<DependentUpon>PairingToPage.xaml</DependentUpon>
</Compile>
<Compile Include="..\GWallet.Frontend.XF\SendPage.xaml.fs">
<DependentUpon>SendPage.xaml</DependentUpon>
</Compile>
<Compile Include="..\GWallet.Frontend.XF\ReceivePage.xaml.fs">
<DependentUpon>ReceivePage.xaml</DependentUpon>
</Compile>
<Compile Include="..\GWallet.Frontend.XF\BalancesPage.xaml.fs">
<DependentUpon>BalancesPage.xaml</DependentUpon>
</Compile>
Expand Down
25 changes: 10 additions & 15 deletions src/GWallet.Frontend.XF/BalancesPage.xaml.fs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ open GWallet.Backend
open GWallet.Backend.FSharpUtil.UwpHacks


type FiatAmountFrameTapHandler = unit -> unit

// this type allows us to represent the idea that if we have, for example, 3 LTC and an unknown number of ETC (might
// be because all ETC servers are unresponsive), then it means we have AT LEAST 3LTC; as opposed to when we know for
// sure all balances of all currencies because all servers are responsive
Expand Down Expand Up @@ -272,14 +274,12 @@ type BalancesPage(state: FrontendHelpers.IGlobalAppState,
balances |> Seq.iteri (fun balanceIndex balanceState ->
let balanceSet = balanceState.BalanceSet
let tapGestureRecognizer = TapGestureRecognizer()
#if XAMARIN
tapGestureRecognizer.Tapped.Subscribe(fun _ ->
let receivePage () =
ReceivePage(balanceSet.Account, readOnly, balanceState.UsdRate, self, balanceSet.Widgets)
:> Page
FrontendHelpers.SwitchToNewPage self receivePage true
) |> ignore
#endif
let frame = balanceSet.Widgets.Frame
frame.GestureRecognizers.Add tapGestureRecognizer
contentLayout.Children.Add frame
Expand Down Expand Up @@ -423,7 +423,7 @@ type BalancesPage(state: FrontendHelpers.IGlobalAppState,
cancelSource.Cancel()
cancelSource.Dispose()

member private self.ConfigureFiatAmountFrame (readOnly: bool): TapGestureRecognizer =
member private self.ConfigureFiatAmountFrame (readOnly: bool): FiatAmountFrameTapHandler =
let totalCurrentFiatAmountFrameName,totalOtherFiatAmountFrameName =
if readOnly then
"totalReadOnlyFiatAmountFrame","totalFiatAmountFrame"
Expand All @@ -447,9 +447,8 @@ type BalancesPage(state: FrontendHelpers.IGlobalAppState,
mainLayout.FindByName<CircleChartView> otherChartViewName

let tapGestureRecognizer = TapGestureRecognizer()
#if XAMARIN
tapGestureRecognizer.Tapped.Add(fun _ ->

let tapHandler () =
let shouldNotOpenNewPage =
if switchingToReadOnly then
readOnlyAccountsBalanceSets.Any()
Expand Down Expand Up @@ -495,26 +494,22 @@ type BalancesPage(state: FrontendHelpers.IGlobalAppState,
PairingFromPage(self, "Copy wallet info to clipboard", walletInfoJson, None)
:> Page
FrontendHelpers.SwitchToNewPage self page true

)
#endif
tapGestureRecognizer.Tapped.Add(fun _ -> tapHandler())
totalCurrentFiatAmountFrame.GestureRecognizers.Add tapGestureRecognizer
tapGestureRecognizer
tapHandler

member self.PopulateGridInitially () =

let tapper = self.ConfigureFiatAmountFrame false
let tapHandler = self.ConfigureFiatAmountFrame false
self.ConfigureFiatAmountFrame true |> ignore

self.PopulateBalances false normalBalanceStates
RedrawCircleView false normalBalanceStates

if startWithReadOnlyAccounts then
#if XAMARIN
tapper.SendTapped null
#else
() // No tapper.SendTapped in MAUI
#endif
tapHandler()

member private __.AssignColorLabels (readOnly: bool) =
let labels,color =
Expand Down
31 changes: 31 additions & 0 deletions src/GWallet.Frontend.XF/FrontendHelpers.fs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ open Xamarin.Forms
open Xamarin.Essentials
open ZXing
open ZXing.Mobile
open ZXing.Net.Mobile.Forms
#endif
open Fsdk
open GWallet.Backend
Expand Down Expand Up @@ -329,7 +330,11 @@ module FrontendHelpers =
let SwitchToNewPage (currentPage: Page) (createNewPage: unit -> Page) (navBar: bool): unit =
MainThread.BeginInvokeOnMainThread(fun _ ->
let newPage = createNewPage ()
#if !XAMARIN && GTK
NavigationPage.SetHasNavigationBar(newPage, navBar)
#else
NavigationPage.SetHasNavigationBar(newPage, false)
#endif
let navPage = NavigationPage newPage
NavigationPage.SetHasNavigationBar(navPage, navBar)

Expand Down Expand Up @@ -482,6 +487,32 @@ module FrontendHelpers =
#else
BarcodeReaderOptions(TryHarder = true, Formats = BarcodeFormat.QrCode)
#endif

let GetBarcodeScannerPage (onBarcodeDetected: string -> unit) =
#if XAMARIN
let scanPage = ZXingScannerPage BarCodeScanningOptions
scanPage.add_OnScanResult(fun result ->
scanPage.IsScanning <- false
onBarcodeDetected result.Text
)
scanPage
#else
let scanView = ZXing.Net.Maui.Controls.CameraBarcodeReaderView(Options = BarCodeScanningOptions)
scanView.BarcodesDetected.Add(fun result ->
let barCodeText = result.Results.[0].Value // assume our barcode is first result?
onBarcodeDetected barCodeText
)
ContentPage(Content = scanView)
#endif

/// Safer alternative to Navigation.PopModalAsync(): when ModalStack is empty, do nothing.
/// This is used in barcode scanner calbacks because sometimes those would be called more than one time.
let TryPopModalAsync (page: Page) : Task<Page> =
if page.Navigation.ModalStack.Count > 0 then
page.Navigation.PopModalAsync()
else
Task.FromResult page

let GetImageSource name =
let thisAssembly = typeof<BalanceState>.Assembly
let thisAssemblyName = thisAssembly.GetName().Name
Expand Down
32 changes: 29 additions & 3 deletions src/GWallet.Frontend.XF/PairingFromPage.xaml.fs
Original file line number Diff line number Diff line change
@@ -1,12 +1,26 @@
namespace GWallet.Frontend.XF
#if XAMARIN
namespace GWallet.Frontend.XF
#else
namespace GWallet.Frontend.Maui
#endif

open System

#if !XAMARIN
open Microsoft.Maui.Controls
open Microsoft.Maui.Controls.Xaml
open Microsoft.Maui.ApplicationModel
open Microsoft.Maui.ApplicationModel.DataTransfer

open ZXing.Net.Maui
open ZXing.Net.Maui.Controls
#else
open Xamarin.Forms
open Xamarin.Forms.Xaml
open Xamarin.Essentials

open ZXing.Net.Mobile.Forms
#endif

type PairingFromPage(previousPage: Page,
clipBoardButtonCaption: string,
Expand All @@ -28,13 +42,23 @@ type PairingFromPage(previousPage: Page,
let clipBoardButton = mainLayout.FindByName<Button> "copyToClipboardButton"
clipBoardButton.Text <- clipBoardButtonCaption

let qrCode = mainLayout.FindByName<ZXingBarcodeImageView> "qrCode"
let qrCode =
#if XAMARIN
mainLayout.FindByName<ZXingBarcodeImageView> "qrCode"
#else
mainLayout.FindByName<BarcodeGeneratorView> "qrCode"
#endif
if isNull qrCode then
failwith "Couldn't find QR code"
#if XAMARIN
qrCode.BarcodeValue <- qrCodeContents
qrCode.IsVisible <- true
qrCode.BarcodeFormat <- ZXing.BarcodeFormat.QR_CODE
qrCode.BarcodeOptions <- ZXing.Common.EncodingOptions(Width = 400, Height = 400)
#else
qrCode.Value <- qrCodeContents
qrCode.Format <- BarcodeFormat.QrCode
#endif
qrCode.IsVisible <- true

let nextStepButton = mainLayout.FindByName<Button> "nextStepButton"
match nextButtonCaptionAndSendPage with
Expand All @@ -45,6 +69,7 @@ type PairingFromPage(previousPage: Page,

// FIXME: remove this workaround below when https://github.com/xamarin/Xamarin.Forms/issues/8843 gets fixed
// TODO: file the UWP bug too
#if XAMARIN
if Device.RuntimePlatform <> Device.macOS && Device.RuntimePlatform <> Device.UWP then () else

let backButton = Button(Text = "< Go back")
Expand All @@ -55,6 +80,7 @@ type PairingFromPage(previousPage: Page,
) |> ignore
mainLayout.Children.Add(backButton)
//</workaround> (NOTE: this also exists in ReceivePage.xaml.fs)
#endif

member __.OnCopyToClipboardClicked(_sender: Object, _args: EventArgs) =
let copyToClipboardButton = base.FindByName<Button>("copyToClipboardButton")
Expand Down
35 changes: 23 additions & 12 deletions src/GWallet.Frontend.XF/PairingToPage.xaml.fs
Original file line number Diff line number Diff line change
@@ -1,12 +1,25 @@
namespace GWallet.Frontend.XF
#if XAMARIN
namespace GWallet.Frontend.XF
#else
namespace GWallet.Frontend.Maui
#endif

open System
open System.Linq

#if !XAMARIN
open Microsoft.Maui.Controls
open Microsoft.Maui.Controls.Xaml
open Microsoft.Maui.ApplicationModel
open Microsoft.Maui.Devices

open ZXing.Net.Maui.Controls
#else
open Xamarin.Forms
open Xamarin.Forms.Xaml
open Xamarin.Essentials
open ZXing.Net.Mobile.Forms
#endif
open Fsdk

open GWallet.Backend
Expand Down Expand Up @@ -41,18 +54,16 @@ type PairingToPage(balancesPage: Page,
Seq.empty,Map.empty,(fun (_,_) -> Page()))

member self.OnScanQrCodeButtonClicked(_sender: Object, _args: EventArgs): unit =
let scanPage = ZXingScannerPage FrontendHelpers.BarCodeScanningOptions
scanPage.add_OnScanResult(fun result ->
scanPage.IsScanning <- false
let scanPage =
FrontendHelpers.GetBarcodeScannerPage
(fun barcodeString ->
MainThread.BeginInvokeOnMainThread(fun _ ->
coldAddressesEntry.Text <- barcodeString
// NOTE: modal because otherwise we would see a 2nd topbar added below the 1st topbar when scanning
// (saw this behaviour on Android using Xamarin.Forms 3.0.x, re-test/file bug later?)
let task = FrontendHelpers.TryPopModalAsync self
task |> FrontendHelpers.DoubleCheckCompletionNonGeneric) )

MainThread.BeginInvokeOnMainThread(fun _ ->
// NOTE: modal because otherwise we would see a 2nd topbar added below the 1st topbar when scanning
// (saw this behaviour on Android using Xamarin.Forms 3.0.x, re-test/file bug later?)
let task = self.Navigation.PopModalAsync()
coldAddressesEntry.Text <- result.Text
task |> FrontendHelpers.DoubleCheckCompletionNonGeneric
)
)
MainThread.BeginInvokeOnMainThread(fun _ ->
// NOTE: modal because otherwise we would see a 2nd topbar added below the 1st topbar when scanning
// (saw this behaviour on Android using Xamarin.Forms 3.0.x, re-test/file bug later?)
Expand Down
2 changes: 1 addition & 1 deletion src/GWallet.Frontend.XF/ReceivePage.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
xmlns:zx="clr-namespace:ZXing.Net.Mobile.Forms;assembly=ZXing.Net.Mobile.Forms"
xmlns:zxcm="clr-namespace:ZXing.Common;assembly=zxing">
<Grid x:Name="mainLayout"
RowDefinitions="Auto,Auto,Auto,Auto,Auto,Auto"
RowDefinitions="Auto,Auto,Auto,Auto,Auto,Auto,Auto"
Padding="10,10,10,10"
VerticalOptions="Center"
>
Expand Down
Loading

0 comments on commit 919e40e

Please sign in to comment.