diff --git a/authentication/build.gradle.kts b/authentication/build.gradle.kts index 7a701b0e..3e912701 100644 --- a/authentication/build.gradle.kts +++ b/authentication/build.gradle.kts @@ -47,9 +47,17 @@ android { } buildTypes { release { isMinifyEnabled = false } } + + buildFeatures { compose = true } + composeOptions { kotlinCompilerExtensionVersion = "1.5.11" } } dependencies { + implementation(libs.androidx.ui.tooling.preview.android) + val composeBom = platform(libs.compose.bom) + implementation(composeBom) + implementation(libs.androidx.compose.foundation) + implementation(libs.material3) implementation(libs.appCompat) implementation(libs.chrometabs) implementation(libs.material) diff --git a/authentication/src/main/kotlin/com/uber/sdk2/auth/ui/LoginButton.kt b/authentication/src/main/kotlin/com/uber/sdk2/auth/ui/LoginButton.kt new file mode 100644 index 00000000..c33d167f --- /dev/null +++ b/authentication/src/main/kotlin/com/uber/sdk2/auth/ui/LoginButton.kt @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2016. Uber Technologies + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.uber.sdk2.auth.ui + +import android.content.Context +import android.util.AttributeSet +import androidx.annotation.StringRes +import androidx.annotation.StyleRes +import androidx.annotation.VisibleForTesting +import com.uber.sdk2.auth.R +import com.uber.sdk2.auth.UberAuthClientImpl +import com.uber.sdk2.auth.request.AuthContext +import com.uber.sdk2.core.ui.UberStyle +import com.uber.sdk2.core.ui.legacy.UberButton + +/** The [LoginButton] is used to initiate the Uber SDK Login flow. */ +class LoginButton : UberButton { + private var authContext: AuthContext? = null + + constructor(context: Context) : super(context) + + constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) + + constructor( + context: Context, + attrs: AttributeSet?, + defStyleAttr: Int, + ) : super(context, attrs, defStyleAttr) + + constructor( + context: Context, + attrs: AttributeSet?, + defStyleAttr: Int, + defStyleRes: Int, + ) : super(context, attrs, defStyleAttr, defStyleRes) + + override fun init( + context: Context, + @StringRes defaultText: Int, + attrs: AttributeSet?, + defStyleAttr: Int, + uberStyle: UberStyle, + ) { + isAllCaps = true + + val defStyleRes = STYLES[uberStyle.value] + + applyStyle(context, R.string.ub__sign_in, attrs, defStyleAttr, defStyleRes) + + setOnClickListener { login() } + } + + @VisibleForTesting + fun login() { + val activity = activity + UberAuthClientImpl().authenticate(activity, authContext!!) + } + + /** + * A [AuthContext] is required to identify the app being authenticated. + * + * @param authContext to be identified. + * @return this instance of [LoginButton] + */ + fun authContext(authContext: AuthContext): LoginButton { + this.authContext = authContext + return this + } + + companion object { + @StyleRes + private val STYLES = intArrayOf(R.style.UberButton_Login, R.style.UberButton_Login_White) + } +} diff --git a/authentication/src/main/kotlin/com/uber/sdk2/auth/ui/UberAuthButton.kt b/authentication/src/main/kotlin/com/uber/sdk2/auth/ui/UberAuthButton.kt new file mode 100644 index 00000000..072281ce --- /dev/null +++ b/authentication/src/main/kotlin/com/uber/sdk2/auth/ui/UberAuthButton.kt @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2024. Uber Technologies + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.uber.sdk2.auth.ui + +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.interaction.collectIsPressedAsState +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.wrapContentSize +import androidx.compose.foundation.layout.wrapContentWidth +import androidx.compose.material3.Button +import androidx.compose.material3.ButtonDefaults +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Shape +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import com.uber.sdk2.auth.ui.theme.UberDimens +import com.uber.sdk2.auth.ui.theme.UberTypography +import com.uber.sdk2.core.R + +@Composable +fun UberAuthButton( + isWhite: Boolean = false, + shape: Shape = MaterialTheme.shapes.large, + onClick: () -> Unit, +) { + val text = stringResource(id = com.uber.sdk2.auth.R.string.ub__sign_in) + val interactionSource = remember { MutableInteractionSource() } + val isPressed = interactionSource.collectIsPressedAsState().value + val backgroundColor = + if (isPressed) { + MaterialTheme.colorScheme.onSecondary + } else { + MaterialTheme.colorScheme.onPrimary + } + + val textColor = MaterialTheme.colorScheme.primary + + val iconResId = if (isWhite) R.drawable.uber_logotype_black else R.drawable.uber_logotype_white + + Button( + onClick = onClick, + modifier = Modifier.wrapContentSize(), + colors = + ButtonDefaults.buttonColors(containerColor = backgroundColor, contentColor = textColor), + shape = shape, + interactionSource = interactionSource, + ) { + Icon( + painter = painterResource(id = iconResId), + contentDescription = null, + modifier = Modifier.padding(end = UberDimens.signInMargin), + ) + Text( + text = text.uppercase(), + color = textColor, + style = UberTypography.bodyMedium, + modifier = Modifier.padding(UberDimens.standardPadding).wrapContentWidth(), + ) + } +} diff --git a/authentication/src/main/kotlin/com/uber/sdk2/auth/ui/theme/UberButtonAttributes.kt b/authentication/src/main/kotlin/com/uber/sdk2/auth/ui/theme/UberButtonAttributes.kt new file mode 100644 index 00000000..2413aae7 --- /dev/null +++ b/authentication/src/main/kotlin/com/uber/sdk2/auth/ui/theme/UberButtonAttributes.kt @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2024. Uber Technologies + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.uber.sdk2.auth.ui.theme + +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Shapes +import androidx.compose.ui.unit.dp + +val UberButtonShapes = + Shapes( + small = RoundedCornerShape(4.dp), + medium = RoundedCornerShape(8.dp), + large = RoundedCornerShape(16.dp), + ) + +object UberDimens { + val smallPadding = 8.dp + val standardPadding = 16.dp + val signInMargin = 48.dp +} diff --git a/authentication/src/main/kotlin/com/uber/sdk2/auth/ui/theme/UberColorPalette.kt b/authentication/src/main/kotlin/com/uber/sdk2/auth/ui/theme/UberColorPalette.kt new file mode 100644 index 00000000..c8789a40 --- /dev/null +++ b/authentication/src/main/kotlin/com/uber/sdk2/auth/ui/theme/UberColorPalette.kt @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2024. Uber Technologies + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.uber.sdk2.auth.ui.theme + +import androidx.compose.ui.graphics.Color + +val UberBlack = Color(0xFF000000) +val UberBlack90 = Color(0xFF282727) +val UberWhite = Color(0xFFFFFFFF) +val UberWhite40 = Color(0xFFE5E5E4) diff --git a/authentication/src/main/kotlin/com/uber/sdk2/auth/ui/theme/UberTheme.kt b/authentication/src/main/kotlin/com/uber/sdk2/auth/ui/theme/UberTheme.kt new file mode 100644 index 00000000..a269d8f4 --- /dev/null +++ b/authentication/src/main/kotlin/com/uber/sdk2/auth/ui/theme/UberTheme.kt @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2024. Uber Technologies + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.uber.sdk2.auth.ui.theme + +import androidx.compose.foundation.isSystemInDarkTheme +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.darkColorScheme +import androidx.compose.material3.lightColorScheme +import androidx.compose.runtime.Composable + +@Composable +fun UberTheme(darkTheme: Boolean = isSystemInDarkTheme(), content: @Composable () -> Unit) { + val colors = + if (darkTheme) { + darkColorScheme(primary = UberBlack, onPrimary = UberWhite, onSecondary = UberWhite40) + } else { + lightColorScheme(primary = UberWhite, onPrimary = UberBlack, onSecondary = UberBlack90) + } + + MaterialTheme( + colorScheme = colors, + typography = UberTypography, + shapes = UberButtonShapes, + content = content, + ) +} diff --git a/authentication/src/main/kotlin/com/uber/sdk2/auth/ui/theme/UberTypography.kt b/authentication/src/main/kotlin/com/uber/sdk2/auth/ui/theme/UberTypography.kt new file mode 100644 index 00000000..94ae9caa --- /dev/null +++ b/authentication/src/main/kotlin/com/uber/sdk2/auth/ui/theme/UberTypography.kt @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2024. Uber Technologies + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.uber.sdk2.auth.ui.theme + +import androidx.compose.material3.Typography +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.unit.sp + +val UberTypography = + Typography( + bodySmall = TextStyle(fontSize = 12.sp), + bodyMedium = TextStyle(fontSize = 14.sp), + bodyLarge = TextStyle(fontSize = 20.sp), + ) diff --git a/authentication/src/main/res/values-hi-rIN/strings_localized.xml b/authentication/src/main/res/values-hi-rIN/strings_localized.xml new file mode 100644 index 00000000..886d2422 --- /dev/null +++ b/authentication/src/main/res/values-hi-rIN/strings_localized.xml @@ -0,0 +1,20 @@ + + + + + साइन इन करें + diff --git a/authentication/src/main/res/values-zh-rCN/strings_localized.xml b/authentication/src/main/res/values-zh-rCN/strings_localized.xml new file mode 100644 index 00000000..26a8d8d5 --- /dev/null +++ b/authentication/src/main/res/values-zh-rCN/strings_localized.xml @@ -0,0 +1,20 @@ + + + + + 登录 + diff --git a/authentication/src/main/res/values-zh-rHK/strings_localized.xml b/authentication/src/main/res/values-zh-rHK/strings_localized.xml new file mode 100644 index 00000000..55912c52 --- /dev/null +++ b/authentication/src/main/res/values-zh-rHK/strings_localized.xml @@ -0,0 +1,20 @@ + + + + + Sign in + diff --git a/authentication/src/main/res/values-zh-rTW/strings_localized.xml b/authentication/src/main/res/values-zh-rTW/strings_localized.xml new file mode 100644 index 00000000..cd8bc4a7 --- /dev/null +++ b/authentication/src/main/res/values-zh-rTW/strings_localized.xml @@ -0,0 +1,20 @@ + + + + + 登入 + diff --git a/authentication/src/main/res/values/strings_localized.xml b/authentication/src/main/res/values/strings_localized.xml new file mode 100644 index 00000000..55912c52 --- /dev/null +++ b/authentication/src/main/res/values/strings_localized.xml @@ -0,0 +1,20 @@ + + + + + Sign in + diff --git a/authentication/src/main/res/values/styles.xml b/authentication/src/main/res/values/styles.xml new file mode 100644 index 00000000..93fcffe9 --- /dev/null +++ b/authentication/src/main/res/values/styles.xml @@ -0,0 +1,32 @@ + + + + + + + + \ No newline at end of file diff --git a/core/src/main/kotlin/com/uber/sdk2/core/utils/CustomTabsHelper.kt b/core/src/main/kotlin/com/uber/sdk2/core/utils/CustomTabsHelper.kt index cbe5fe28..57c2fccf 100644 --- a/core/src/main/kotlin/com/uber/sdk2/core/utils/CustomTabsHelper.kt +++ b/core/src/main/kotlin/com/uber/sdk2/core/utils/CustomTabsHelper.kt @@ -48,10 +48,10 @@ object CustomTabsHelper { ) { val packageName = getPackageNameToUse(context) if (packageName != null) { - connection = + val connection = object : CustomTabsServiceConnection() { override fun onCustomTabsServiceConnected( - componentName: ComponentName?, + componentName: ComponentName, client: CustomTabsClient, ) { client.warmup(0L) // This prevents backgrounding after redirection @@ -63,6 +63,7 @@ object CustomTabsHelper { override fun onServiceDisconnected(name: ComponentName?) {} } CustomTabsClient.bindCustomTabsService(context, packageName, connection) + this.connection = connection } else fallback?.openUri(context, uri) ?: Log.e( diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index e234dfa8..1c9000fc 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -2,7 +2,7 @@ [versions] agp = "8.2.2" -androidxVersion = "1.0.0" +androidxVersion = "1.7.0" uberJava = "0.8.5" mavenPublish = "0.27.0" kotlin = "1.9.23" diff --git a/samples/login-sample/src/main/java/com/uber/sdk/android/samples/LoginSampleActivity.java b/samples/login-sample/src/main/java/com/uber/sdk/android/samples/LoginSampleActivity.java index ac28664a..5ab10550 100644 --- a/samples/login-sample/src/main/java/com/uber/sdk/android/samples/LoginSampleActivity.java +++ b/samples/login-sample/src/main/java/com/uber/sdk/android/samples/LoginSampleActivity.java @@ -147,6 +147,7 @@ protected void onResume() { @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); Log.i(LOG_TAG, String.format("onActivityResult requestCode:[%s] resultCode [%s]", requestCode, resultCode)); diff --git a/samples/login-with-auth-code-demo/src/main/java/com/uber/sdk/android/samples/DemoActivity.java b/samples/login-with-auth-code-demo/src/main/java/com/uber/sdk/android/samples/DemoActivity.java index b9b2c2bd..d8d53d57 100644 --- a/samples/login-with-auth-code-demo/src/main/java/com/uber/sdk/android/samples/DemoActivity.java +++ b/samples/login-with-auth-code-demo/src/main/java/com/uber/sdk/android/samples/DemoActivity.java @@ -92,6 +92,7 @@ protected void onCreate(Bundle savedInstanceState) { @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); Log.i(LOG_TAG, String.format("onActivityResult requestCode:[%s] resultCode [%s]", requestCode, resultCode)); if (data != null) {