diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/UserProfileView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/UserProfileView.kt index 60b99c620f..967ec73f2f 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/UserProfileView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/UserProfileView.kt @@ -10,8 +10,7 @@ import androidx.compose.foundation.text.BasicTextField import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.material.* import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.outlined.Close -import androidx.compose.material.icons.outlined.PhotoCamera +import androidx.compose.material.icons.outlined.* import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -25,8 +24,10 @@ import androidx.compose.ui.unit.sp import chat.simplex.app.R import chat.simplex.app.model.ChatModel import chat.simplex.app.model.Profile +import chat.simplex.app.ui.theme.HighOrLowlight import chat.simplex.app.ui.theme.SimpleXTheme import chat.simplex.app.views.helpers.* +import chat.simplex.app.views.isValidDisplayName import com.google.accompanist.insets.ProvideWindowInsets import com.google.accompanist.insets.navigationBarsWithImePadding import kotlinx.coroutines.launch @@ -128,7 +129,12 @@ fun UserProfileLayout( } } } - ProfileNameTextField(displayName) + Box { + if (!isValidDisplayName(displayName.value)) { + Icon(Icons.Outlined.Info, tint = Color.Red, contentDescription = stringResource(R.string.display_name_cannot_contain_whitespace)) + } + ProfileNameTextField(displayName) + } ProfileNameTextField(fullName) Row { TextButton(stringResource(R.string.cancel_verb)) { @@ -138,9 +144,22 @@ fun UserProfileLayout( editProfile.value = false } Spacer(Modifier.padding(horizontal = 8.dp)) - TextButton(stringResource(R.string.save_and_notify_contacts)) { - saveProfile(displayName.value, fullName.value, profileImage.value) + val enabled = displayName.value.isNotEmpty() && isValidDisplayName(displayName.value) + val saveModifier: Modifier + val saveColor: Color + if (enabled) { + saveModifier = Modifier + .clickable { saveProfile(displayName.value, fullName.value, profileImage.value) } + saveColor = MaterialTheme.colors.primary + } else { + saveModifier = Modifier + saveColor = HighOrLowlight } + Text( + stringResource(R.string.save_and_notify_contacts), + modifier = saveModifier, + color = saveColor + ) } } } else { @@ -187,6 +206,7 @@ private fun ProfileNameTextField(name: MutableState) { onValueChange = { name.value = it }, modifier = Modifier .padding(bottom = 24.dp) + .padding(start = 28.dp) .fillMaxWidth(), textStyle = MaterialTheme.typography.body1.copy(color = MaterialTheme.colors.onBackground), keyboardOptions = KeyboardOptions( diff --git a/apps/ios/Shared/Views/Onboarding/CreateProfile.swift b/apps/ios/Shared/Views/Onboarding/CreateProfile.swift index cae263e938..639a161adf 100644 --- a/apps/ios/Shared/Views/Onboarding/CreateProfile.swift +++ b/apps/ios/Shared/Views/Onboarding/CreateProfile.swift @@ -106,15 +106,15 @@ struct CreateProfile: View { UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil) } - func validDisplayName(_ name: String) -> Bool { - name.firstIndex(of: " ") == nil - } - func canCreateProfile() -> Bool { displayName != "" && validDisplayName(displayName) } } +func validDisplayName(_ name: String) -> Bool { + name.firstIndex(of: " ") == nil +} + struct CreateProfile_Previews: PreviewProvider { static var previews: some View { CreateProfile() diff --git a/apps/ios/Shared/Views/UserSettings/UserProfile.swift b/apps/ios/Shared/Views/UserSettings/UserProfile.swift index 4de7695136..3ac68f75dc 100644 --- a/apps/ios/Shared/Views/UserSettings/UserProfile.swift +++ b/apps/ios/Shared/Views/UserSettings/UserProfile.swift @@ -45,11 +45,19 @@ struct UserProfile: View { .frame(maxWidth: .infinity, alignment: .center) VStack(alignment: .leading) { - profileNameTextEdit("Display name", $profile.displayName) + ZStack(alignment: .leading) { + if !validDisplayName(profile.displayName) { + Image(systemName: "exclamationmark.circle") + .foregroundColor(.red) + .padding(.bottom, 10) + } + profileNameTextEdit("Display name", $profile.displayName) + } profileNameTextEdit("Full name (optional)", $profile.fullName) HStack(spacing: 20) { Button("Cancel") { editProfile = false } Button("Save (and notify contacts)") { saveProfile() } + .disabled(profile.displayName == "" || !validDisplayName(profile.displayName)) } } .frame(maxWidth: .infinity, minHeight: 120, alignment: .leading) @@ -111,6 +119,7 @@ struct UserProfile: View { .textInputAutocapitalization(.never) .disableAutocorrection(true) .padding(.bottom) + .padding(.leading, 28) } func profileNameView(_ label: String, _ name: String) -> some View {