Skip to content

Commit

Permalink
ErgoAuth iOS ErgoAuthenticationViewController introduced #112
Browse files Browse the repository at this point in the history
  • Loading branch information
MrStahlfelge committed Apr 20, 2022
1 parent ff755d7 commit 5558bbe
Show file tree
Hide file tree
Showing 5 changed files with 224 additions and 20 deletions.
9 changes: 7 additions & 2 deletions ios/src/main/java/org/ergoplatform/ios/BottomNavigationBar.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package org.ergoplatform.ios
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import org.ergoplatform.ios.ergoauth.ErgoAuthenticationViewController
import org.ergoplatform.ios.settings.SettingsViewController
import org.ergoplatform.ios.transactions.ChooseSpendingWalletViewController
import org.ergoplatform.ios.transactions.ErgoPaySigningViewController
Expand Down Expand Up @@ -107,8 +108,12 @@ class BottomNavigationBar : UITabBarController() {
}
}
}
}, navigateToAuthentication = {
// TODO ErgoAuth
}, navigateToAuthentication = { request ->
selectedViewController = viewControllers.first()
(selectedViewController as? UINavigationController)?.apply {
popToRootViewController(false)
pushViewController(ErgoAuthenticationViewController(request, null), true)
}
}, presentUserMessage = { message ->
presentViewController(buildSimpleAlertController("", message, texts), true) {}
})
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
package org.ergoplatform.ios.ergoauth

import kotlinx.coroutines.CoroutineScope
import org.ergoplatform.ios.transactions.ErgoPaySigningViewController
import org.ergoplatform.ios.ui.*
import org.ergoplatform.uilogic.*
import org.ergoplatform.uilogic.ergoauth.ErgoAuthUiLogic
import org.robovm.apple.coregraphics.CGRect
import org.robovm.apple.foundation.NSArray
import org.robovm.apple.uikit.*

class ErgoAuthenticationViewController(
private val request: String,
private val walletId: Int?,
) : CoroutineViewController() {

private val uiLogic = IosUiLogic()
private lateinit var authRequestContainer: AuthenticationRequestStack
private lateinit var fetchingContainer: ErgoPaySigningViewController.FetchDataContainer
private lateinit var texts: IosStringProvider
private val stateDoneContainer = CardView()

override fun viewDidLoad() {
super.viewDidLoad()

val appDelegate = getAppDelegate()
texts = IosStringProvider(appDelegate.texts)
fetchingContainer = ErgoPaySigningViewController.FetchDataContainer(texts)
authRequestContainer = AuthenticationRequestStack()

title = texts.getString(STRING_TITLE_ERGO_AUTH_REQUEST)
view.backgroundColor = UIColor.systemBackground()
navigationController.navigationBar?.tintColor = UIColor.label()

view.layoutMargins = UIEdgeInsets.Zero()

val scrollingContainer = UIView(CGRect.Zero())
val scrollView = scrollingContainer.wrapInVerticalScrollView()

view.addSubview(scrollView)
view.addSubview(fetchingContainer)
view.addSubview(stateDoneContainer)
scrollingContainer.addSubview(authRequestContainer)

fetchingContainer.widthMatchesSuperview(maxWidth = MAX_WIDTH).centerVertical()
authRequestContainer.edgesToSuperview(maxWidth = MAX_WIDTH)
stateDoneContainer.centerVertical().widthMatchesSuperview(maxWidth = MAX_WIDTH)
scrollView.edgesToSuperview()

uiLogic.init(
request,
walletId ?: -1,
texts,
appDelegate.database
)
}

private fun showDoneInfo() {
if (stateDoneContainer.contentView.subviews.isEmpty()) {
val image = uiLogic.getDoneSeverity().getImage()?.let {
UIImageView(getIosSystemImage(it, UIImageSymbolScale.Large)).apply {
contentMode = UIViewContentMode.ScaleAspectFit
tintColor = uiColorErgo
fixedHeight(100.0)
}
}

val descLabel = Body1Label()
descLabel.text = uiLogic.getDoneMessage(texts)
descLabel.textAlignment = NSTextAlignment.Center

val dismissButton = PrimaryButton(texts.getString(STRING_LABEL_DISMISS))
dismissButton.addOnTouchUpInsideListener { _, _ -> navigationController.popViewController(true) }
val doneButtonContainer = UIView()
doneButtonContainer.addSubview(dismissButton)
dismissButton.centerHorizontal().topToSuperview().bottomToSuperview().fixedWidth(150.0)

val txDoneStack = UIStackView().apply {
axis = UILayoutConstraintAxis.Vertical
spacing = DEFAULT_MARGIN * 3

image?.let { addArrangedSubview(image) }
addArrangedSubview(descLabel)
addArrangedSubview(doneButtonContainer)
}

stateDoneContainer.contentView.addSubview(txDoneStack)
txDoneStack.edgesToSuperview(inset = DEFAULT_MARGIN * 2)
}
}

inner class AuthenticationRequestStack : UIStackView(CGRect.Zero()) {
private val messageFromDApp = Body1Label()
private val messageIcon = UIImageView().apply {
tintColor = UIColor.secondaryLabel()
contentMode = UIViewContentMode.ScaleAspectFit
fixedWidth(40.0)
}
private val requestFromDappCard = CardView()
private val mainRequestContainer = ChooseAddressAndSignContainer()

init {
axis = UILayoutConstraintAxis.Vertical
spacing = DEFAULT_MARGIN

addArrangedSubview(requestFromDappCard)
addArrangedSubview(mainRequestContainer)

requestFromDappCard.contentView.addSubview(messageFromDApp)
requestFromDappCard.contentView.addSubview(messageIcon)

val messageStackView = UIStackView(NSArray(messageIcon, messageFromDApp)).apply {
axis = UILayoutConstraintAxis.Horizontal
spacing = DEFAULT_MARGIN * 2
}
requestFromDappCard.contentView.addSubview(messageStackView)
messageStackView.edgesToSuperview(inset = DEFAULT_MARGIN)
}

fun showRequestInfo() {
requestFromDappCard.isHidden = uiLogic.ergAuthRequest?.userMessage?.let {
messageFromDApp.text = texts.getString(STRING_LABEL_MESSAGE_FROM_DAPP, it)
messageIcon.isHidden = uiLogic.ergAuthRequest!!.messageSeverity.getImage()?.let {
messageIcon.image = getIosSystemImage(it, UIImageSymbolScale.Medium)
false
} ?: true
false
} ?: true
refreshAddressInfo()
}

fun refreshAddressInfo() {
mainRequestContainer.walletChooser.text = uiLogic.walletConfig?.displayName
}
}

inner class ChooseAddressAndSignContainer : UIView(CGRect.Zero()) {
private val descLabel = Body1Label().apply {
text = texts.getString(STRING_DESC_AUTHENTICATION_WALLET)
textAlignment = NSTextAlignment.Center
}
val walletChooser = Headline2Label().apply {
numberOfLines = 1
}
private val authButton = PrimaryButton(texts.getString(STRING_BUTTON_AUTHENTICATE)).apply {
addOnTouchUpInsideListener { _, _ ->
uiLogic.walletConfig?.let { walletConfig ->
startAuthFlow(walletConfig) { secrets ->
uiLogic.startResponse(secrets, texts)
}
}
}
}

init {
val walletChooseButton = walletChooser.wrapWithTrailingImage(
getIosSystemImage(IMAGE_OPEN_LIST, UIImageSymbolScale.Small, 20.0)!!,
keepWidth = true
).apply {
isUserInteractionEnabled = true
addGestureRecognizer(UITapGestureRecognizer {
presentViewController(
null, // TODO
true
) {}
})
}

addSubview(descLabel)
addSubview(walletChooseButton)
addSubview(authButton)

descLabel.topToSuperview().widthMatchesSuperview()
walletChooseButton.topToBottomOf(descLabel).centerHorizontal(true)
authButton.topToBottomOf(walletChooser, inset = DEFAULT_MARGIN * 2).bottomToSuperview().centerHorizontal()
}
}

inner class IosUiLogic : ErgoAuthUiLogic() {
override val coroutineScope: CoroutineScope
get() = viewControllerScope

override fun notifyStateChanged(newState: State) {
runOnMainThread {
stateDoneContainer.isHidden = newState != State.DONE
fetchingContainer.isHidden = newState != State.FETCHING_DATA

if (newState == State.DONE) {
showDoneInfo()
} else if (newState == State.WAIT_FOR_AUTH) {
authRequestContainer.showRequestInfo()
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package org.ergoplatform.ios.transactions

import kotlinx.coroutines.CoroutineScope
import org.ergoplatform.ios.tokens.TokenInformationViewController
import org.ergoplatform.transactions.MessageSeverity
import org.ergoplatform.ios.ui.*
import org.ergoplatform.ios.wallet.addresses.ChooseAddressListDialogViewController
import org.ergoplatform.transactions.TransactionResult
Expand Down Expand Up @@ -38,7 +37,7 @@ class ErgoPaySigningViewController(

val appDelegate = getAppDelegate()
texts = appDelegate.texts
fetchingContainer = FetchDataContainer()
fetchingContainer = FetchDataContainer(IosStringProvider(texts))
transactionContainer = TransactionWithHeaderContainer()

title = texts.get(STRING_TITLE_ERGO_PAY_REQUEST)
Expand Down Expand Up @@ -143,18 +142,9 @@ class ErgoPaySigningViewController(
}
}

private fun getImageFromSeverity(severity: MessageSeverity): String? {
return when (severity) {
MessageSeverity.NONE -> null
MessageSeverity.INFORMATION -> IMAGE_INFORMATION
MessageSeverity.WARNING -> IMAGE_WARNING
MessageSeverity.ERROR -> IMAGE_ERROR
}
}

private fun showDoneInfo() {
if (stateDoneContainer.contentView.subviews.isEmpty()) {
val image = getImageFromSeverity(uiLogic.getDoneSeverity())?.let {
val image = uiLogic.getDoneSeverity().getImage()?.let {
UIImageView(getIosSystemImage(it, UIImageSymbolScale.Large)).apply {
contentMode = UIViewContentMode.ScaleAspectFit
tintColor = uiColorErgo
Expand Down Expand Up @@ -219,7 +209,7 @@ class ErgoPaySigningViewController(
messageFromDApp.text = texts.format(STRING_LABEL_MESSAGE_FROM_DAPP, it)


messageIcon.isHidden = getImageFromSeverity(uiLogic.epsr!!.messageSeverity)?.let {
messageIcon.isHidden = uiLogic.epsr!!.messageSeverity.getImage()?.let {
messageIcon.image = getIosSystemImage(it, UIImageSymbolScale.Medium)
false
} ?: true
Expand All @@ -228,12 +218,12 @@ class ErgoPaySigningViewController(
}
}

inner class FetchDataContainer : UIView(CGRect.Zero()) {
class FetchDataContainer(private val texts: StringProvider) : UIView(CGRect.Zero()) {
private val progressIndicator = UIActivityIndicatorView().apply {
activityIndicatorViewStyle = UIActivityIndicatorViewStyle.Large
}
private val fetchDataLabel = Headline2Label().apply {
text = texts.get(STRING_LABEL_FETCHING_DATA)
text = texts.getString(STRING_LABEL_FETCHING_DATA)
textAlignment = NSTextAlignment.Center
}

Expand Down
12 changes: 11 additions & 1 deletion ios/src/main/java/org/ergoplatform/ios/ui/UIUtils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package org.ergoplatform.ios.ui
import com.badlogic.gdx.utils.I18NBundle
import org.ergoplatform.ios.Main
import org.ergoplatform.ios.wallet.addresses.ChooseAddressListDialogViewController
import org.ergoplatform.transactions.MessageSeverity
import org.ergoplatform.uilogic.*
import org.robovm.apple.coregraphics.CGAffineTransform
import org.robovm.apple.coregraphics.CGPoint
Expand Down Expand Up @@ -135,7 +136,7 @@ fun UIView.wrapWithTrailingImage(
image: UIImage,
fixedWith: Double = 0.0,
fixedHeight: Double = 0.0,
keepWidth: Boolean = false
keepWidth: Boolean = false // determines if the right boundary is fixed or flexible
): TrailingImageView<UIView> {
val imageView = UIImageView(image)
imageView.tintColor = (this as? UILabel)?.textColor ?: this.tintColor
Expand Down Expand Up @@ -355,4 +356,13 @@ fun UIImage.scaleToSize(scaleWidth: Double, scaleHeight: Double): UIImage? {
return renderer.toImage {
this.draw(CGRect(CGPoint.Zero(), scaledImageSize))
}
}

fun MessageSeverity.getImage(): String? {
return when (this) {
MessageSeverity.NONE -> null
MessageSeverity.INFORMATION -> IMAGE_INFORMATION
MessageSeverity.WARNING -> IMAGE_WARNING
MessageSeverity.ERROR -> IMAGE_ERROR
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import org.ergoplatform.ApiServiceManager
import org.ergoplatform.WalletStateSyncManager
import org.ergoplatform.ios.ergoauth.ErgoAuthenticationViewController
import org.ergoplatform.ios.tokens.TokenInformationViewController
import org.ergoplatform.ios.tokens.WalletDetailsTokenEntryView
import org.ergoplatform.ios.transactions.*
Expand Down Expand Up @@ -226,8 +227,10 @@ class WalletDetailsViewController(private val walletId: Int) : CoroutineViewCont
true
)
},
navigateToAuthentication = {
// TODO ErgoAuth
navigateToAuthentication = { request ->
navigationController.pushViewController(
ErgoAuthenticationViewController(request, walletId), true
)
},
showErrorMessage = { errorMessage ->
presentViewController(
Expand Down

0 comments on commit 5558bbe

Please sign in to comment.