diff --git a/app/src/main/java/org/futo/circles/view/PostHeaderView.kt b/app/src/main/java/org/futo/circles/view/PostHeaderView.kt index 2c0d7e17c6c0f3902bf8e6cad099b375ab1147c5..741bfbca308c36f5eae7e5466fcc76047c5cda28 100644 --- a/app/src/main/java/org/futo/circles/view/PostHeaderView.kt +++ b/app/src/main/java/org/futo/circles/view/PostHeaderView.kt @@ -13,7 +13,7 @@ import org.futo.circles.core.extensions.setIsEncryptedIcon import org.futo.circles.core.extensions.setIsVisible import org.futo.circles.core.model.Post import org.futo.circles.core.provider.MatrixSessionProvider -import org.futo.circles.core.utils.UserUtils +import org.futo.circles.core.utils.UserIdUtils import org.futo.circles.databinding.ViewPostHeaderBinding import org.futo.circles.feature.timeline.list.PostOptionsListener import java.util.Date @@ -69,7 +69,7 @@ class PostHeaderView( } } tvUserName.text = name - tvUserId.text = UserUtils.removeDomainSuffix(userId) + tvUserId.text = UserIdUtils.removeDomainSuffix(userId) ivEncrypted.setIsEncryptedIcon(isEncrypted) tvMessageTime.text = DateFormat.format("MMM dd, h:mm a", Date(timestamp)) diff --git a/auth/src/main/java/org/futo/circles/auth/feature/log_in/LogInFragment.kt b/auth/src/main/java/org/futo/circles/auth/feature/log_in/LogInFragment.kt index 7d581a4ede16fab56f942e70b6c8f5431b5662c2..b40ab2aa535f3976b57c9921fa95b00ab12255ed 100644 --- a/auth/src/main/java/org/futo/circles/auth/feature/log_in/LogInFragment.kt +++ b/auth/src/main/java/org/futo/circles/auth/feature/log_in/LogInFragment.kt @@ -19,6 +19,7 @@ import org.futo.circles.auth.model.InvalidUserId import org.futo.circles.auth.model.RemoveUser import org.futo.circles.auth.model.SuggestedUserId import org.futo.circles.auth.model.ValidUserId +import org.futo.circles.auth.utils.UserIdUtils import org.futo.circles.core.base.fragment.BaseBindingFragment import org.futo.circles.core.base.fragment.HasLoadingState import org.futo.circles.core.base.list.BaseRvDecoration @@ -115,12 +116,12 @@ class LogInFragment : BaseBindingFragment<FragmentLogInBinding>(FragmentLogInBin private fun startLogin(isForgotPassword: Boolean) { val userId = binding.tilUserId.getText() - when (UserIdValidator.validateUserId(userId)) { + when (val status = UserIdUtils.validateUserId(userId)) { EmptyUserId -> showError(getString(R.string.user_id_can_not_be_empty)) InvalidUserId -> showError(getString(R.string.invalid_user_id)) is SuggestedUserId -> findNavController().navigateSafe( LogInFragmentDirections.toLoginSuggestionBottomSheet( - userId, isForgotPassword + status.suggestedUserId, isForgotPassword ) ) diff --git a/auth/src/main/java/org/futo/circles/auth/feature/log_in/LogInViewModel.kt b/auth/src/main/java/org/futo/circles/auth/feature/log_in/LogInViewModel.kt index 006376514579c6b6155eccb07c8b6d68bd1d57cb..99881700956db84216783ae8ec277c898dc1b972 100644 --- a/auth/src/main/java/org/futo/circles/auth/feature/log_in/LogInViewModel.kt +++ b/auth/src/main/java/org/futo/circles/auth/feature/log_in/LogInViewModel.kt @@ -17,14 +17,14 @@ class LogInViewModel @Inject constructor( private val refreshTokenManager: RefreshTokenManager ) : ViewModel() { - val loginResultLiveData = SingleEventLiveData<Response<Unit>>() + val loginResultLiveData = SingleEventLiveData<Response<Unit?>>() val switchUsersLiveData = MutableLiveData(switchUserDataSource.getSwitchUsersList()) val navigateToBottomMenuScreenLiveData = SingleEventLiveData<Unit>() - fun startLogInFlow(userName: String, domain: String, isForgotPassword: Boolean) { - switchUserDataSource.getSessionCredentialsIdByUserInfo(userName, domain) + fun startLogInFlow(userId: String, isForgotPassword: Boolean) { + switchUserDataSource.getSessionCredentialsIdByUserInfo(userId) ?.let { resumeSwitchUserSession(it) } - ?: login(userName, domain, isForgotPassword) + ?: login(userId, isForgotPassword) } fun removeSwitchUser(id: String) { @@ -43,9 +43,9 @@ class LogInViewModel @Inject constructor( } } - private fun login(userName: String, domain: String, isForgotPassword: Boolean) { + private fun login(userId: String, isForgotPassword: Boolean) { launchBg { - val loginResult = loginDataSource.startLogin(userName, domain, isForgotPassword) + val loginResult = loginDataSource.startLogin(userId, isForgotPassword) loginResultLiveData.postValue(loginResult) } } diff --git a/auth/src/main/java/org/futo/circles/auth/feature/log_in/LoginDataSource.kt b/auth/src/main/java/org/futo/circles/auth/feature/log_in/LoginDataSource.kt index 15f135767220d42edc4ac30736e26ca820a47228..726a4e4785b55847f956b1a0f51de7bb416b02f2 100644 --- a/auth/src/main/java/org/futo/circles/auth/feature/log_in/LoginDataSource.kt +++ b/auth/src/main/java/org/futo/circles/auth/feature/log_in/LoginDataSource.kt @@ -14,9 +14,10 @@ import org.futo.circles.auth.feature.uia.UIADataSource.Companion.TYPE_PARAM_KEY import org.futo.circles.auth.feature.uia.UIADataSource.Companion.USER_PARAM_KEY import org.futo.circles.auth.feature.uia.UIADataSourceProvider import org.futo.circles.auth.model.UIAFlowType +import org.futo.circles.auth.utils.UserIdUtils import org.futo.circles.core.extensions.createResult import org.futo.circles.core.provider.MatrixInstanceProvider -import org.futo.circles.core.utils.HomeServerUtils.buildHomeServerConfigFromDomain +import org.futo.circles.core.utils.HomeServerUtils.buildHomeServerConfigFromUserId import org.matrix.android.sdk.api.auth.registration.Stage import javax.inject.Inject @@ -29,30 +30,28 @@ class LoginDataSource @Inject constructor( private val authService by lazy { MatrixInstanceProvider.matrix.authenticationService() } suspend fun startLogin( - userName: String, - domain: String, + userId: String, isForgotPassword: Boolean ) = createResult { authService.cancelPendingLoginOrRegistration() - val stages = prepareLoginStages(userName, domain, isForgotPassword) + val stages = prepareLoginStages(userId, isForgotPassword) val uiaDataSource = UIADataSourceProvider.create( if (isForgotPassword) UIAFlowType.ForgotPassword else UIAFlowType.Login, uiaFactory ) + val (userName, domain) = UserIdUtils.getNameAndDomainFromId(userId) uiaDataSource.startUIAStages(stages, domain, userName) } private suspend fun prepareLoginStages( - userName: String, - domain: String, + userId: String, isForgotPassword: Boolean ): List<Stage> { - val homeServerConfig = buildHomeServerConfigFromDomain(domain) + val homeServerConfig = buildHomeServerConfigFromUserId(userId) val supportedLoginMethods = authService.getLoginFlow(homeServerConfig).supportedLoginTypes - val stages = - getCircleStages(userName, domain, isForgotPassword) - ?: getPasswordStagesIfAvailable(supportedLoginMethods, isForgotPassword) + val stages = getCircleStages(userId, isForgotPassword) + ?: getPasswordStagesIfAvailable(supportedLoginMethods, isForgotPassword) return stages ?: throw IllegalArgumentException(context.getString(R.string.unsupported_login_method)) @@ -68,12 +67,11 @@ class LoginDataSource @Inject constructor( } else null private suspend fun getCircleStages( - userName: String, - domain: String, + userId: String, isForgotPassword: Boolean ): List<Stage>? { val identifierParams = mapOf( - USER_PARAM_KEY to "@$userName:$domain", + USER_PARAM_KEY to userId, TYPE_PARAM_KEY to LOGIN_PASSWORD_USER_ID_TYPE ) val flows = authService.getLoginWizard() diff --git a/auth/src/main/java/org/futo/circles/auth/feature/log_in/switch_user/SwitchUserDataSource.kt b/auth/src/main/java/org/futo/circles/auth/feature/log_in/switch_user/SwitchUserDataSource.kt index 4cc7e3d4b8252f0378189a418e5f8c425e7eff27..381ca47e9ae330d62e05422ae2ab20a3a3e01109 100644 --- a/auth/src/main/java/org/futo/circles/auth/feature/log_in/switch_user/SwitchUserDataSource.kt +++ b/auth/src/main/java/org/futo/circles/auth/feature/log_in/switch_user/SwitchUserDataSource.kt @@ -36,8 +36,7 @@ class SwitchUserDataSource @Inject constructor() { private fun getSessionWithId(id: String): Session? = getSwitchUsersList().firstOrNull { it.id == id }?.session - fun getSessionCredentialsIdByUserInfo(userName: String, domain: String): String? { - val userId = "@$userName:$domain" + fun getSessionCredentialsIdByUserInfo(userId: String): String? { return getSwitchUsersList().firstOrNull { it.user.userId == userId }?.id } diff --git a/auth/src/main/java/org/futo/circles/auth/feature/log_in/UserIdValidator.kt b/auth/src/main/java/org/futo/circles/auth/utils/UserIdUtils.kt similarity index 73% rename from auth/src/main/java/org/futo/circles/auth/feature/log_in/UserIdValidator.kt rename to auth/src/main/java/org/futo/circles/auth/utils/UserIdUtils.kt index d01f36108c73cb101f6cb1f85763ba9c93776c8c..7d79964d0621037d2ec0488653de7c7374ba8290 100644 --- a/auth/src/main/java/org/futo/circles/auth/feature/log_in/UserIdValidator.kt +++ b/auth/src/main/java/org/futo/circles/auth/utils/UserIdUtils.kt @@ -1,4 +1,4 @@ -package org.futo.circles.auth.feature.log_in +package org.futo.circles.auth.utils import org.futo.circles.auth.model.EmptyUserId import org.futo.circles.auth.model.InvalidUserId @@ -8,10 +8,23 @@ import org.futo.circles.auth.model.ValidateUserIdStatus import org.futo.circles.core.base.CirclesAppConfig import org.matrix.android.sdk.api.MatrixPatterns -object UserIdValidator { + +object UserIdUtils { private val defaultDomain = CirclesAppConfig.usDomain + + fun getNameAndDomainFromId(userId: String): Pair<String, String> { + if (!MatrixPatterns.isUserId(userId)) throw IllegalArgumentException("Invalid userId $userId") + + return userId.split(":").takeIf { it.size == 2 }?.let { + val userName = it.first().replace("@", "") + val domain = it[1] + userName to domain + } ?: throw IllegalArgumentException("Invalid userId $userId") + } + + fun validateUserId(input: String): ValidateUserIdStatus { if (input.isEmpty()) return EmptyUserId if (MatrixPatterns.isUserId(input)) return ValidUserId(input) @@ -30,11 +43,13 @@ object UserIdValidator { private fun handleEmailToUserIdTransform(input: String): ValidateUserIdStatus { val parts = input.split("@") - .takeIf { it.size == 2 && !it.first().contains(":") } ?: return InvalidUserId + .takeIf { it.size == 2 && !it.first().contains(":") } + ?: return InvalidUserId return SuggestedUserId("@${parts.first()}:${parts[1]}") } private fun handleNoDomainInput(input: String): ValidateUserIdStatus { return SuggestedUserId("$input$defaultDomain") } + } \ No newline at end of file diff --git a/core/src/main/java/org/futo/circles/core/extensions/MatrixUserExtensions.kt b/core/src/main/java/org/futo/circles/core/extensions/MatrixUserExtensions.kt index 6884a51725d886f7a10b33b91a03b24f29c7029d..2ebc3145ab59ddc557c67ab9e8e2ff9c5a3de005 100644 --- a/core/src/main/java/org/futo/circles/core/extensions/MatrixUserExtensions.kt +++ b/core/src/main/java/org/futo/circles/core/extensions/MatrixUserExtensions.kt @@ -1,6 +1,6 @@ package org.futo.circles.core.extensions -import org.futo.circles.core.utils.UserUtils +import org.futo.circles.core.utils.UserIdUtils import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary import org.matrix.android.sdk.api.session.room.sender.SenderInfo import org.matrix.android.sdk.api.session.user.model.User @@ -15,5 +15,5 @@ fun SenderInfo.notEmptyDisplayName(): String = getName(userId, displayName) private fun getName(userId: String, displayName: String?): String { val name = displayName?.takeIf { it.isNotEmpty() } ?: userId.replace("@", "").substringBefore(":") - return UserUtils.removeDomainSuffix(name) + return UserIdUtils.removeDomainSuffix(name) } \ No newline at end of file diff --git a/core/src/main/java/org/futo/circles/core/feature/select_users/SelectUsersDataSource.kt b/core/src/main/java/org/futo/circles/core/feature/select_users/SelectUsersDataSource.kt index bc477494e1d4041d09d8d6f92599ca88594ed266..52b70036a2691b2b5b7c3b7ae2f64acd3d40f958 100644 --- a/core/src/main/java/org/futo/circles/core/feature/select_users/SelectUsersDataSource.kt +++ b/core/src/main/java/org/futo/circles/core/feature/select_users/SelectUsersDataSource.kt @@ -15,7 +15,7 @@ import org.futo.circles.core.model.InviteMemberListItem import org.futo.circles.core.model.NoResultsItem import org.futo.circles.core.model.UserListItem import org.futo.circles.core.provider.MatrixSessionProvider -import org.futo.circles.core.utils.UserUtils +import org.futo.circles.core.utils.UserIdUtils import org.matrix.android.sdk.api.MatrixPatterns import org.matrix.android.sdk.api.session.getRoom import org.matrix.android.sdk.api.session.room.members.roomMemberQueryParams @@ -95,7 +95,7 @@ class SelectUsersDataSource @Inject constructor( list.add(HeaderItem.suggestionHeader) list.add( UserListItem( - CirclesUserSummary(query, UserUtils.removeDomainSuffix(query), ""), + CirclesUserSummary(query, UserIdUtils.removeDomainSuffix(query), ""), selectedUsers.containsWithId(query) ) ) diff --git a/core/src/main/java/org/futo/circles/core/mapping/RoomSummaryMapping.kt b/core/src/main/java/org/futo/circles/core/mapping/RoomSummaryMapping.kt index ce2d5c1524a787dcb69d5579081c07d32f5029a9..388ba0ddd6ee9e3fcffc65aaafe9f0f83726b286 100644 --- a/core/src/main/java/org/futo/circles/core/mapping/RoomSummaryMapping.kt +++ b/core/src/main/java/org/futo/circles/core/mapping/RoomSummaryMapping.kt @@ -11,7 +11,7 @@ import org.futo.circles.core.model.SelectRoomTypeArg import org.futo.circles.core.model.SelectableRoomListItem import org.futo.circles.core.model.isCircle import org.futo.circles.core.provider.MatrixSessionProvider -import org.futo.circles.core.utils.UserUtils +import org.futo.circles.core.utils.UserIdUtils import org.futo.circles.core.utils.getKnocksCount import org.matrix.android.sdk.api.query.QueryStringValue import org.matrix.android.sdk.api.session.events.model.EventType @@ -52,7 +52,7 @@ fun RoomMemberSummary.toKnockRequestListItem(roomId: String, roomType: CircleRoo ?: "", roomType = roomType, requesterId = userId, - requesterName = displayName ?: UserUtils.removeDomainSuffix(userId), + requesterName = displayName ?: UserIdUtils.removeDomainSuffix(userId), requesterAvatarUrl = avatarUrl, message = getReasonMessage(roomId, userId) ) diff --git a/core/src/main/java/org/futo/circles/core/utils/HomeServerUtils.kt b/core/src/main/java/org/futo/circles/core/utils/HomeServerUtils.kt index 97125d5e8253b906712c00bf8ebc02a7a3a4acd5..d11f90ca9214b96b6647e177c189a1a3ea6f1df7 100644 --- a/core/src/main/java/org/futo/circles/core/utils/HomeServerUtils.kt +++ b/core/src/main/java/org/futo/circles/core/utils/HomeServerUtils.kt @@ -5,6 +5,12 @@ import org.matrix.android.sdk.api.auth.data.HomeServerConnectionConfig object HomeServerUtils { + fun buildHomeServerConfigFromUserId(userId: String): HomeServerConnectionConfig { + val domain = UserIdUtils.getServerDomain(userId) + return buildHomeServerConfigFromDomain(domain) + } + + fun buildHomeServerConfigFromDomain(domain: String) = HomeServerConnectionConfig .Builder() .withHomeServerUri(Uri.parse("https://$domain")) diff --git a/core/src/main/java/org/futo/circles/core/utils/UserUtils.kt b/core/src/main/java/org/futo/circles/core/utils/UserIdUtils.kt similarity index 96% rename from core/src/main/java/org/futo/circles/core/utils/UserUtils.kt rename to core/src/main/java/org/futo/circles/core/utils/UserIdUtils.kt index f364c610aeed3cc901c0e15276b4e04f36ac25f8..708293e3c51be2ab7cc07d04946e11a4bf4e31e9 100644 --- a/core/src/main/java/org/futo/circles/core/utils/UserUtils.kt +++ b/core/src/main/java/org/futo/circles/core/utils/UserIdUtils.kt @@ -3,7 +3,7 @@ package org.futo.circles.core.utils import org.futo.circles.core.provider.MatrixSessionProvider -object UserUtils { +object UserIdUtils { fun removeDomainSuffix(userId: String): String { val serverDomain = MatrixSessionProvider.currentSession?.sessionParams?.homeServerHost ?: "" @@ -17,4 +17,5 @@ object UserUtils { } fun getServerDomain(userId: String) = userId.substringAfter(":") + } \ No newline at end of file