Skip to content

Commit 5ced838

Browse files
Merge pull request #10 from torusresearch/FD-594
Fd 594 login dropdown and choosing browser
2 parents 95073e9 + f43ce76 commit 5ced838

27 files changed

+477
-169
lines changed

.idea/deploymentTargetDropDown.xml

Lines changed: 17 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/gradle.xml

Lines changed: 1 addition & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/jarRepositories.xml

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/misc.xml

Lines changed: 10 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

README.md

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -83,12 +83,10 @@ class MainActivity : AppCompatActivity() {
8383
super.onCreate(savedInstanceState)
8484
setContentView(R.layout.activity_main)
8585

86-
openlogin = OpenLogin(
87-
this,
86+
openlogin = OpenLogin(OpenLoginOptions(context = this,
8887
clientId = getString(R.string.openlogin_client_id),
8988
network = OpenLogin.Network.MAINNET,
90-
redirectUrl = Uri.parse("{YOUR_APP_PACKAGE_NAME}://auth"),
91-
)
89+
redirectUrl = Uri.parse("{YOUR_APP_PACKAGE_NAME}://auth")))
9290

9391
// Handle user signing in when app is not alive
9492
openlogin.setResultUrl(intent?.data)
@@ -106,7 +104,17 @@ class MainActivity : AppCompatActivity() {
106104
}
107105

108106
private fun onClickLogin() {
109-
openlogin.login()
107+
val selectedLoginProvider = OpenLogin.Provider.GOOGLE // Can be Google, Facebook, Twitch etc
108+
val loginCompletableFuture: CompletableFuture<State> = openlogin.login(LoginParams(selectedLoginProvider))
109+
110+
loginCompletableFuture.whenComplete { state, error ->
111+
if (error == null) {
112+
// render logged in UI
113+
} else {
114+
// render login error UI
115+
}
116+
117+
}
110118
}
111119

112120
//...
@@ -127,18 +135,32 @@ Make sure your sign-in activity `launchMode` is set to `singleTop` in your `Andr
127135

128136
```kotlin
129137
class OpenLogin(
130-
context: Context, // Android context to launch Web-based authentication, usually is the current activity
131-
clientId: String, // Your OpenLogin project ID
132-
network: Network, // Network to run OpenLogin, either MAINNET or TESTNET
133-
redirectUrl: Uri? = null, // URL that OpenLogin will redirect API responses
134-
)
138+
var openLoginOptions : OpenLoginOptions
139+
) {
135140
// Trigger login flow that shows a modal for user to select one of supported providers to login,
136141
// e.g. Google, Facebook, Twitter, Passwordless, etc
137142
fun login() {}
138143

139-
// Trigger login flow using a specific provider
144+
// Trigger login flow using login params. Specific Login Provider can be set through Login Params
140145
fun login(
141-
loginProvider: Provider,
146+
loginParams: LoginParams,
142147
) {}
143148
}
149+
150+
data class OpenLoginOptions(
151+
context: Context, // Android context to launch Web-based authentication, usually is the current activity
152+
clientId: String, // Your OpenLogin project ID
153+
network: Network, // Network to run OpenLogin, either MAINNET or TESTNET
154+
redirectUrl: Uri? = null, // URL that OpenLogin will redirect API responses
155+
)
156+
157+
data class LoginParams(
158+
val loginProvider: OpenLogin.Provider,
159+
val reLogin: Boolean? = null,
160+
val skipTKey: Boolean? = null,
161+
val extraLoginOptions: ExtraLoginOptions? = null,
162+
val redirectUrl: Uri? = null,
163+
val appState: String? = null
164+
)
165+
144166
```

app/build.gradle

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,23 +4,36 @@ plugins {
44
}
55

66
android {
7+
signingConfigs {
8+
release {
9+
storeFile file('/Users/tanuj/Desktop/Torus/open login/open_login')
10+
storePassword 'torus123'
11+
keyAlias 'key0'
12+
keyPassword 'torus123'
13+
}
14+
}
715
compileSdkVersion 31
8-
buildToolsVersion "30.0.3"
916

1017
defaultConfig {
1118
applicationId "com.openlogin.app"
1219
minSdkVersion 21
1320
targetSdkVersion 31
1421
versionCode 1
1522
versionName "1.0"
23+
manifestPlaceholders = [
24+
'torusRedirectScheme' : 'torusapp',
25+
'torusRedirectHost' : 'org.torusresearch.openloginexample',
26+
'torusRedirectPathPrefix': '/redirect'
27+
]
1628

1729
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
1830
}
1931

2032
buildTypes {
2133
release {
22-
minifyEnabled false
34+
minifyEnabled true
2335
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
36+
signingConfig signingConfigs.release
2437
}
2538
}
2639
compileOptions {
@@ -40,6 +53,9 @@ dependencies {
4053
implementation 'com.google.android.material:material:1.4.0'
4154
implementation 'androidx.constraintlayout:constraintlayout:2.1.2'
4255

56+
// Completable Futures support
57+
implementation 'net.sourceforge.streamsupport:streamsupport-cfuture:1.7.4'
58+
4359
// Encoding
4460
implementation 'com.google.code.gson:gson:2.8.9'
4561

app/proguard-rules.pro

Lines changed: 6 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,6 @@
1-
# Add project specific ProGuard rules here.
2-
# You can control the set of applied configuration files using the
3-
# proguardFiles setting in build.gradle.
4-
#
5-
# For more details, see
6-
# http://developer.android.com/guide/developing/tools/proguard.html
7-
8-
# If your project uses WebView with JS, uncomment the following
9-
# and specify the fully qualified class name to the JavaScript interface
10-
# class:
11-
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12-
# public *;
13-
#}
14-
15-
# Uncomment this to preserve the line number information for
16-
# debugging stack traces.
17-
#-keepattributes SourceFile,LineNumberTable
18-
19-
# If you keep the line number information, uncomment this to
20-
# hide the original source file name.
21-
#-renamesourcefileattribute SourceFile
1+
#### GSON
2+
# Prevent proguard from stripping interface information from TypeAdapterFactory,
3+
# JsonSerializer, JsonDeserializer instances (so they can be used in @JsonAdapter)
4+
-keep class * implements com.google.gson.TypeAdapterFactory
5+
-keep class * implements com.google.gson.JsonSerializer
6+
-keep class * implements com.google.gson.JsonDeserializer

app/src/main/AndroidManifest.xml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,11 @@
2727
<category android:name="android.intent.category.DEFAULT" />
2828
<category android:name="android.intent.category.BROWSABLE" />
2929

30-
<!-- Accept URIs: http://localhost[:*]/redirect/* -->
3130
<data
32-
android:host="org.torusresearch.openloginexample"
33-
android:pathPrefix="/redirect"
34-
android:scheme="torusapp" />
31+
android:host="${torusRedirectHost}"
32+
android:pathPattern="/*"
33+
android:pathPrefix="${torusRedirectPathPrefix}"
34+
android:scheme="${torusRedirectScheme}" />
3535
</intent-filter>
3636
<intent-filter>
3737
<action android:name="android.intent.action.VIEW" />
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package com.openlogin.app
2+
3+
import com.openlogin.core.OpenLogin
4+
5+
data class LoginVerifier (
6+
val name : String,
7+
val loginProvider : OpenLogin.Provider
8+
)

app/src/main/java/com/openlogin/app/MainActivity.kt

Lines changed: 86 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,44 +3,97 @@ package com.openlogin.app
33
import android.content.Intent
44
import android.net.Uri
55
import android.os.Bundle
6+
import android.util.Log
67
import android.view.View
7-
import android.widget.Button
8-
import android.widget.TextView
8+
import android.widget.*
99
import androidx.appcompat.app.AppCompatActivity
10+
import com.google.android.material.textfield.TextInputLayout
1011
import com.google.gson.Gson
11-
import com.openlogin.core.AuthStateChangeListener
1212
import com.openlogin.core.OpenLogin
13+
import com.openlogin.core.isEmailValid
14+
import com.openlogin.core.types.ExtraLoginOptions
15+
import com.openlogin.core.types.LoginParams
16+
import com.openlogin.core.types.OpenLoginOptions
17+
import com.openlogin.core.types.OpenLoginResponse
18+
import java8.util.concurrent.CompletableFuture
1319

14-
class MainActivity : AppCompatActivity() {
20+
class MainActivity : AppCompatActivity(), AdapterView.OnItemClickListener {
1521
private lateinit var openlogin: OpenLogin
1622

23+
private val verifierList : List<LoginVerifier> = listOf(
24+
LoginVerifier("Google", OpenLogin.Provider.GOOGLE),
25+
LoginVerifier("Facebook", OpenLogin.Provider.FACEBOOK),
26+
LoginVerifier("Twitch", OpenLogin.Provider.TWITCH),
27+
LoginVerifier("Discord", OpenLogin.Provider.DISCORD),
28+
LoginVerifier("Reddit", OpenLogin.Provider.REDDIT),
29+
LoginVerifier("Apple", OpenLogin.Provider.APPLE),
30+
LoginVerifier("Github", OpenLogin.Provider.GITHUB),
31+
LoginVerifier("LinkedIn", OpenLogin.Provider.LINKEDIN),
32+
LoginVerifier("Twitter", OpenLogin.Provider.TWITTER),
33+
LoginVerifier("Line", OpenLogin.Provider.LINE),
34+
LoginVerifier("Hosted Email Passwordless", OpenLogin.Provider.EMAIL_PASSWORDLESS)
35+
)
36+
37+
private var selectedLoginProvider: OpenLogin.Provider = OpenLogin.Provider.GOOGLE
38+
1739
private val gson = Gson()
1840

1941
private fun signIn() {
20-
openlogin.login(OpenLogin.Provider.GOOGLE)
42+
val hintEmailEditText = findViewById<EditText>(R.id.etEmailHint)
43+
var extraLoginOptions : ExtraLoginOptions? = null
44+
if (selectedLoginProvider == OpenLogin.Provider.EMAIL_PASSWORDLESS) {
45+
val hintEmail = hintEmailEditText.text.toString()
46+
if (hintEmail.isBlank() || !hintEmail.isEmailValid()) {
47+
Toast.makeText(this, "Please enter a valid Email.", Toast.LENGTH_LONG).show()
48+
return
49+
}
50+
extraLoginOptions = ExtraLoginOptions(login_hint = hintEmail)
51+
}
52+
53+
val loginCompletableFuture: CompletableFuture<OpenLoginResponse> = openlogin.login(LoginParams(selectedLoginProvider, extraLoginOptions = extraLoginOptions))
54+
loginCompletableFuture.whenComplete { loginResponse, error ->
55+
if (error == null) {
56+
reRender(loginResponse)
57+
} else {
58+
Log.d("MainActivity_OpenLogin", error.message ?: "Something went wrong" )
59+
}
60+
61+
}
2162
}
2263

2364
private fun signOut() {
24-
openlogin.logout()
65+
val logoutCompletableFuture = openlogin.logout()
66+
logoutCompletableFuture.whenComplete { _, error ->
67+
if (error == null) {
68+
reRender(OpenLoginResponse())
69+
} else {
70+
Log.d("MainActivity_OpenLogin", error.message ?: "Something went wrong" )
71+
}
72+
}
2573
}
2674

27-
private fun reRender() {
75+
private fun reRender(openLoginResponse: OpenLoginResponse) {
2876
val contentTextView = findViewById<TextView>(R.id.contentTextView)
2977
val signInButton = findViewById<Button>(R.id.signInButton)
3078
val signOutButton = findViewById<Button>(R.id.signOutButton)
79+
val spinner = findViewById<TextInputLayout>(R.id.verifierList)
80+
val hintEmailEditText = findViewById<EditText>(R.id.etEmailHint)
3181

32-
val key = openlogin.state.privKey
33-
val userInfo = openlogin.state.userInfo
82+
val key = openLoginResponse.privKey
83+
val userInfo = openLoginResponse.userInfo
3484
if (key is String && key.isNotEmpty()) {
35-
contentTextView.text = gson.toJson(openlogin.state)
85+
contentTextView.text = gson.toJson(openLoginResponse)
3686
contentTextView.visibility = View.VISIBLE
3787
signInButton.visibility = View.GONE
3888
signOutButton.visibility = View.VISIBLE
89+
spinner.visibility = View.GONE
90+
hintEmailEditText.visibility = View.GONE
3991
} else {
4092
contentTextView.text = getString(R.string.not_logged_in)
4193
contentTextView.visibility = View.GONE
4294
signInButton.visibility = View.VISIBLE
4395
signOutButton.visibility = View.GONE
96+
spinner.visibility = View.VISIBLE
4497
}
4598
}
4699

@@ -49,27 +102,43 @@ class MainActivity : AppCompatActivity() {
49102
setContentView(R.layout.activity_main)
50103

51104
// Configure OpenLogin
52-
openlogin = OpenLogin(
53-
this,
105+
openlogin = OpenLogin(OpenLoginOptions(context = this,
54106
clientId = getString(R.string.openlogin_project_id),
55107
network = OpenLogin.Network.MAINNET,
56-
redirectUrl = Uri.parse("torusapp://org.torusresearch.openloginexample/redirect"),
57-
)
108+
redirectUrl = Uri.parse("torusapp://org.torusresearch.openloginexample/redirect")))
109+
58110
openlogin.setResultUrl(intent.data)
59-
openlogin.addAuthStateChangeListener(AuthStateChangeListener {
60-
reRender()
61-
})
62111

63112
// Setup UI and event handlers
64113
val signInButton = findViewById<Button>(R.id.signInButton)
65114
signInButton.setOnClickListener { signIn() }
66115

67116
val signOutButton = findViewById<Button>(R.id.signOutButton)
68117
signOutButton.setOnClickListener { signOut() }
118+
119+
val spinner = findViewById<AutoCompleteTextView>(R.id.spinnerTextView)
120+
val loginVerifierList: List<String> = verifierList.map {
121+
item -> item.name
122+
}
123+
val adapter: ArrayAdapter<String> =
124+
ArrayAdapter(this, R.layout.item_dropdown, loginVerifierList)
125+
spinner.setAdapter(adapter)
126+
spinner.onItemClickListener = this
69127
}
70128

71129
override fun onNewIntent(intent: Intent?) {
72130
super.onNewIntent(intent)
73131
openlogin.setResultUrl(intent?.data)
74132
}
133+
134+
override fun onItemClick(p0: AdapterView<*>?, p1: View?, p2: Int, p3: Long) {
135+
selectedLoginProvider = verifierList[p2].loginProvider
136+
137+
val hintEmailEditText = findViewById<EditText>(R.id.etEmailHint)
138+
if (selectedLoginProvider == OpenLogin.Provider.EMAIL_PASSWORDLESS) {
139+
hintEmailEditText.visibility = View.VISIBLE
140+
} else {
141+
hintEmailEditText.visibility = View.GONE
142+
}
143+
}
75144
}

0 commit comments

Comments
 (0)