diff options
author | Fabian Henneke <FabianHenneke@users.noreply.github.com> | 2020-08-26 10:06:36 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-08-26 13:36:36 +0530 |
commit | ad17fa7cc5003cf362c74019afa13e9d28d0f4e7 (patch) | |
tree | 38fb4bbc7bfa26fab0ab7833387df577a0bfa736 /app/src | |
parent | d0b15cec49a41ec1ea51890ac7b7c8cb8515f6a4 (diff) |
Rename ConnectionMode to AuthMode and remove clone_ prefix (#1053)
Diffstat (limited to 'app/src')
10 files changed, 77 insertions, 77 deletions
diff --git a/app/src/androidTest/java/com/zeapo/pwdstore/MigrationsTest.kt b/app/src/androidTest/java/com/zeapo/pwdstore/MigrationsTest.kt index c87bdae3..531ceebf 100644 --- a/app/src/androidTest/java/com/zeapo/pwdstore/MigrationsTest.kt +++ b/app/src/androidTest/java/com/zeapo/pwdstore/MigrationsTest.kt @@ -8,7 +8,7 @@ package com.zeapo.pwdstore import android.content.Context import androidx.core.content.edit -import com.zeapo.pwdstore.git.config.ConnectionMode +import com.zeapo.pwdstore.git.config.AuthMode import com.zeapo.pwdstore.git.config.Protocol import com.zeapo.pwdstore.utils.PreferenceKeys import com.zeapo.pwdstore.utils.getString @@ -36,7 +36,7 @@ class MigrationsTest { putString(PreferenceKeys.GIT_REMOTE_LOCATION, "/mnt/disk3/pass-repo") putString(PreferenceKeys.GIT_REMOTE_SERVER, "192.168.0.102") putString(PreferenceKeys.GIT_REMOTE_PROTOCOL, Protocol.Ssh.pref) - putString(PreferenceKeys.GIT_REMOTE_AUTH, ConnectionMode.Password.pref) + putString(PreferenceKeys.GIT_REMOTE_AUTH, AuthMode.Password.pref) } runMigrations(context) checkOldKeysAreRemoved(context) @@ -55,7 +55,7 @@ class MigrationsTest { putString(PreferenceKeys.GIT_REMOTE_LOCATION, "/mnt/disk3/pass-repo") putString(PreferenceKeys.GIT_REMOTE_SERVER, "192.168.0.102") putString(PreferenceKeys.GIT_REMOTE_PROTOCOL, Protocol.Ssh.pref) - putString(PreferenceKeys.GIT_REMOTE_AUTH, ConnectionMode.SshKey.pref) + putString(PreferenceKeys.GIT_REMOTE_AUTH, AuthMode.SshKey.pref) } runMigrations(context) checkOldKeysAreRemoved(context) @@ -74,7 +74,7 @@ class MigrationsTest { putString(PreferenceKeys.GIT_REMOTE_LOCATION, "Android-Password-Store/pass-test") putString(PreferenceKeys.GIT_REMOTE_SERVER, "github.com") putString(PreferenceKeys.GIT_REMOTE_PROTOCOL, Protocol.Https.pref) - putString(PreferenceKeys.GIT_REMOTE_AUTH, ConnectionMode.None.pref) + putString(PreferenceKeys.GIT_REMOTE_AUTH, AuthMode.None.pref) } runMigrations(context) checkOldKeysAreRemoved(context) diff --git a/app/src/main/java/com/zeapo/pwdstore/Migrations.kt b/app/src/main/java/com/zeapo/pwdstore/Migrations.kt index d0221d9e..cdf56bb3 100644 --- a/app/src/main/java/com/zeapo/pwdstore/Migrations.kt +++ b/app/src/main/java/com/zeapo/pwdstore/Migrations.kt @@ -78,7 +78,7 @@ private fun migrateToGitUrlBasedConfig(context: Context) { } if (url == null || GitSettings.updateConnectionSettingsIfValid( newProtocol = protocol, - newConnectionMode = GitSettings.connectionMode, + newAuthMode = GitSettings.authMode, newUrl = url, newBranch = GitSettings.branch) != GitSettings.UpdateConnectionSettingsResult.Valid) { e { "Failed to migrate to URL-based Git config, generated URL is invalid" } diff --git a/app/src/main/java/com/zeapo/pwdstore/PasswordFragment.kt b/app/src/main/java/com/zeapo/pwdstore/PasswordFragment.kt index 9e50ad2b..7e0ef418 100644 --- a/app/src/main/java/com/zeapo/pwdstore/PasswordFragment.kt +++ b/app/src/main/java/com/zeapo/pwdstore/PasswordFragment.kt @@ -26,7 +26,7 @@ import com.zeapo.pwdstore.databinding.PasswordRecyclerViewBinding import com.zeapo.pwdstore.git.BaseGitActivity import com.zeapo.pwdstore.git.GitOperationActivity import com.zeapo.pwdstore.git.GitServerConfigActivity -import com.zeapo.pwdstore.git.config.ConnectionMode +import com.zeapo.pwdstore.git.config.AuthMode import com.zeapo.pwdstore.git.config.GitSettings import com.zeapo.pwdstore.ui.OnOffItemAnimator import com.zeapo.pwdstore.ui.adapters.PasswordItemRecyclerAdapter @@ -93,10 +93,10 @@ class PasswordFragment : Fragment(R.layout.password_recycler_view) { .show() binding.swipeRefresher.isRefreshing = false } else { - // When authentication is set to ConnectionMode.None then the only git operation we - // can run is a pull, so automatically fallback to that. - val operationId = when (GitSettings.connectionMode) { - ConnectionMode.None -> BaseGitActivity.REQUEST_PULL + // When authentication is set to AuthMode.None then the only git operation we can + // run is a pull, so automatically fallback to that. + val operationId = when (GitSettings.authMode) { + AuthMode.None -> BaseGitActivity.REQUEST_PULL else -> BaseGitActivity.REQUEST_SYNC } val intent = Intent(context, GitOperationActivity::class.java) diff --git a/app/src/main/java/com/zeapo/pwdstore/PasswordStore.kt b/app/src/main/java/com/zeapo/pwdstore/PasswordStore.kt index d70417bc..d9afc7c9 100644 --- a/app/src/main/java/com/zeapo/pwdstore/PasswordStore.kt +++ b/app/src/main/java/com/zeapo/pwdstore/PasswordStore.kt @@ -50,7 +50,7 @@ import com.zeapo.pwdstore.crypto.PasswordCreationActivity import com.zeapo.pwdstore.git.BaseGitActivity import com.zeapo.pwdstore.git.GitOperationActivity import com.zeapo.pwdstore.git.GitServerConfigActivity -import com.zeapo.pwdstore.git.config.ConnectionMode +import com.zeapo.pwdstore.git.config.AuthMode import com.zeapo.pwdstore.git.config.GitSettings import com.zeapo.pwdstore.ui.dialogs.FolderCreationDialogFragment import com.zeapo.pwdstore.utils.PasswordItem @@ -249,7 +249,7 @@ class PasswordStore : AppCompatActivity(R.layout.activity_pwdstore) { override fun onCreateOptionsMenu(menu: Menu?): Boolean { val menuRes = when { - GitSettings.connectionMode == ConnectionMode.None -> R.menu.main_menu_no_auth + GitSettings.authMode == AuthMode.None -> R.menu.main_menu_no_auth PasswordRepository.isGitRepo() -> R.menu.main_menu_git else -> R.menu.main_menu_non_git } diff --git a/app/src/main/java/com/zeapo/pwdstore/git/BaseGitActivity.kt b/app/src/main/java/com/zeapo/pwdstore/git/BaseGitActivity.kt index 21795404..ed72c88d 100644 --- a/app/src/main/java/com/zeapo/pwdstore/git/BaseGitActivity.kt +++ b/app/src/main/java/com/zeapo/pwdstore/git/BaseGitActivity.kt @@ -61,7 +61,7 @@ abstract class BaseGitActivity : AppCompatActivity() { return } } - op.executeAfterAuthentication(GitSettings.connectionMode) + op.executeAfterAuthentication(GitSettings.authMode) } catch (e: Exception) { e.printStackTrace() MaterialAlertDialogBuilder(this).setMessage(e.message).show() diff --git a/app/src/main/java/com/zeapo/pwdstore/git/GitServerConfigActivity.kt b/app/src/main/java/com/zeapo/pwdstore/git/GitServerConfigActivity.kt index bb991449..cd6747f7 100644 --- a/app/src/main/java/com/zeapo/pwdstore/git/GitServerConfigActivity.kt +++ b/app/src/main/java/com/zeapo/pwdstore/git/GitServerConfigActivity.kt @@ -13,7 +13,7 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.snackbar.Snackbar import com.zeapo.pwdstore.R import com.zeapo.pwdstore.databinding.ActivityGitCloneBinding -import com.zeapo.pwdstore.git.config.ConnectionMode +import com.zeapo.pwdstore.git.config.AuthMode import com.zeapo.pwdstore.git.config.GitSettings import com.zeapo.pwdstore.git.config.Protocol import com.zeapo.pwdstore.utils.PasswordRepository @@ -33,7 +33,7 @@ class GitServerConfigActivity : BaseGitActivity() { private val binding by viewBinding(ActivityGitCloneBinding::inflate) private lateinit var newProtocol: Protocol - private lateinit var newConnectionMode: ConnectionMode + private lateinit var newAuthMode: AuthMode override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -45,40 +45,40 @@ class GitServerConfigActivity : BaseGitActivity() { supportActionBar?.setDisplayHomeAsUpEnabled(true) newProtocol = GitSettings.protocol - binding.cloneProtocolGroup.apply { + binding.protocolGroup.apply { when (newProtocol) { - Protocol.Ssh -> check(R.id.clone_protocol_ssh) - Protocol.Https -> check(R.id.clone_protocol_https) + Protocol.Ssh -> check(R.id.protocol_ssh) + Protocol.Https -> check(R.id.protocol_https) } addOnButtonCheckedListener { _, checkedId, checked -> if (checked) { when (checkedId) { - R.id.clone_protocol_https -> newProtocol = Protocol.Https - R.id.clone_protocol_ssh -> newProtocol = Protocol.Ssh + R.id.protocol_https -> newProtocol = Protocol.Https + R.id.protocol_ssh -> newProtocol = Protocol.Ssh } - updateConnectionModeToggleGroup() + updateAuthModeToggleGroup() } } } - newConnectionMode = GitSettings.connectionMode - binding.connectionModeGroup.apply { - when (newConnectionMode) { - ConnectionMode.SshKey -> check(R.id.connection_mode_ssh_key) - ConnectionMode.Password -> check(R.id.connection_mode_password) - ConnectionMode.OpenKeychain -> check(R.id.connection_mode_open_keychain) - ConnectionMode.None -> uncheck(checkedButtonId) + newAuthMode = GitSettings.authMode + binding.authModeGroup.apply { + when (newAuthMode) { + AuthMode.SshKey -> check(R.id.auth_mode_ssh_key) + AuthMode.Password -> check(R.id.auth_mode_password) + AuthMode.OpenKeychain -> check(R.id.auth_mode_open_keychain) + AuthMode.None -> uncheck(checkedButtonId) } addOnButtonCheckedListener { _, _, _ -> when (checkedButtonId) { - R.id.connection_mode_ssh_key -> newConnectionMode = ConnectionMode.SshKey - R.id.connection_mode_open_keychain -> newConnectionMode = ConnectionMode.OpenKeychain - R.id.connection_mode_password -> newConnectionMode = ConnectionMode.Password - View.NO_ID -> newConnectionMode = ConnectionMode.None + R.id.auth_mode_ssh_key -> newAuthMode = AuthMode.SshKey + R.id.auth_mode_open_keychain -> newAuthMode = AuthMode.OpenKeychain + R.id.auth_mode_password -> newAuthMode = AuthMode.Password + View.NO_ID -> newAuthMode = AuthMode.None } } } - updateConnectionModeToggleGroup() + updateAuthModeToggleGroup() binding.serverUrl.setText(GitSettings.url) binding.serverBranch.setText(GitSettings.branch) @@ -86,7 +86,7 @@ class GitServerConfigActivity : BaseGitActivity() { binding.saveButton.setOnClickListener { when (GitSettings.updateConnectionSettingsIfValid( newProtocol = newProtocol, - newConnectionMode = newConnectionMode, + newAuthMode = newAuthMode, newUrl = binding.serverUrl.text.toString().trim(), newBranch = binding.serverBranch.text.toString().trim())) { GitSettings.UpdateConnectionSettingsResult.FailedToParseUrl -> { @@ -112,25 +112,25 @@ class GitServerConfigActivity : BaseGitActivity() { } } - private fun updateConnectionModeToggleGroup() { + private fun updateAuthModeToggleGroup() { if (newProtocol == Protocol.Ssh) { - binding.connectionModeSshKey.isEnabled = true - binding.connectionModeOpenKeychain.isEnabled = true + binding.authModeSshKey.isEnabled = true + binding.authModeOpenKeychain.isEnabled = true // Reset connection mode to SSH key if the current value (none) is not valid for SSH. // Important note: This has to happen after enabling the other toggle buttons or they // won't check. - if (binding.connectionModeGroup.checkedButtonIds.isEmpty()) - binding.connectionModeGroup.check(R.id.connection_mode_ssh_key) - binding.connectionModeGroup.isSelectionRequired = true + if (binding.authModeGroup.checkedButtonIds.isEmpty()) + binding.authModeGroup.check(R.id.auth_mode_ssh_key) + binding.authModeGroup.isSelectionRequired = true } else { - binding.connectionModeGroup.isSelectionRequired = false + binding.authModeGroup.isSelectionRequired = false // Reset connection mode to password if the current value is not valid for HTTPS // Important note: This has to happen before disabling the other toggle buttons or they // won't uncheck. - if (newConnectionMode !in listOf(ConnectionMode.None, ConnectionMode.Password)) - binding.connectionModeGroup.check(R.id.connection_mode_password) - binding.connectionModeSshKey.isEnabled = false - binding.connectionModeOpenKeychain.isEnabled = false + if (newAuthMode !in listOf(AuthMode.None, AuthMode.Password)) + binding.authModeGroup.check(R.id.auth_mode_password) + binding.authModeSshKey.isEnabled = false + binding.authModeOpenKeychain.isEnabled = false } } diff --git a/app/src/main/java/com/zeapo/pwdstore/git/config/GitSettings.kt b/app/src/main/java/com/zeapo/pwdstore/git/config/GitSettings.kt index 2efae40c..b9c572fc 100644 --- a/app/src/main/java/com/zeapo/pwdstore/git/config/GitSettings.kt +++ b/app/src/main/java/com/zeapo/pwdstore/git/config/GitSettings.kt @@ -29,7 +29,7 @@ enum class Protocol(val pref: String) { } } -enum class ConnectionMode(val pref: String) { +enum class AuthMode(val pref: String) { SshKey("ssh-key"), Password("username/password"), OpenKeychain("OpenKeychain"), @@ -38,10 +38,10 @@ enum class ConnectionMode(val pref: String) { companion object { - private val map = values().associateBy(ConnectionMode::pref) - fun fromString(type: String?): ConnectionMode { + private val map = values().associateBy(AuthMode::pref) + fun fromString(type: String?): AuthMode { return map[type ?: return SshKey] - ?: throw IllegalArgumentException("$type is not a valid ConnectionMode") + ?: throw IllegalArgumentException("$type is not a valid AuthMode") } } } @@ -60,8 +60,8 @@ object GitSettings { putString(PreferenceKeys.GIT_REMOTE_PROTOCOL, value.pref) } } - var connectionMode - get() = ConnectionMode.fromString(settings.getString(PreferenceKeys.GIT_REMOTE_AUTH)) + var authMode + get() = AuthMode.fromString(settings.getString(PreferenceKeys.GIT_REMOTE_AUTH)) private set(value) { settings.edit { putString(PreferenceKeys.GIT_REMOTE_AUTH, value.pref) @@ -110,18 +110,18 @@ object GitSettings { MissingUsername, } - fun updateConnectionSettingsIfValid(newProtocol: Protocol, newConnectionMode: ConnectionMode, newUrl: String, newBranch: String): UpdateConnectionSettingsResult { + fun updateConnectionSettingsIfValid(newProtocol: Protocol, newAuthMode: AuthMode, newUrl: String, newBranch: String): UpdateConnectionSettingsResult { val parsedUrl = try { URIish(newUrl) } catch (_: Exception) { return UpdateConnectionSettingsResult.FailedToParseUrl } - if (newConnectionMode != ConnectionMode.None && parsedUrl.user.isNullOrBlank()) + if (newAuthMode != AuthMode.None && parsedUrl.user.isNullOrBlank()) return UpdateConnectionSettingsResult.MissingUsername url = newUrl protocol = newProtocol - connectionMode = newConnectionMode + authMode = newAuthMode branch = newBranch return UpdateConnectionSettingsResult.Valid } diff --git a/app/src/main/java/com/zeapo/pwdstore/git/operation/CredentialFinder.kt b/app/src/main/java/com/zeapo/pwdstore/git/operation/CredentialFinder.kt index 6b6b8ea8..b7b4f881 100644 --- a/app/src/main/java/com/zeapo/pwdstore/git/operation/CredentialFinder.kt +++ b/app/src/main/java/com/zeapo/pwdstore/git/operation/CredentialFinder.kt @@ -10,7 +10,7 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.textfield.TextInputEditText import com.google.android.material.textfield.TextInputLayout import com.zeapo.pwdstore.R -import com.zeapo.pwdstore.git.config.ConnectionMode +import com.zeapo.pwdstore.git.config.AuthMode import com.zeapo.pwdstore.git.sshj.InteractivePasswordFinder import com.zeapo.pwdstore.utils.PreferenceKeys import com.zeapo.pwdstore.utils.getEncryptedPrefs @@ -20,7 +20,7 @@ import kotlin.coroutines.resume class CredentialFinder( val callingActivity: FragmentActivity, - val connectionMode: ConnectionMode + val authMode: AuthMode ) : InteractivePasswordFinder() { override fun askForPassword(cont: Continuation<String?>, isRetry: Boolean) { @@ -30,15 +30,15 @@ class CredentialFinder( @StringRes val hintRes: Int @StringRes val rememberRes: Int @StringRes val errorRes: Int - when (connectionMode) { - ConnectionMode.SshKey -> { + when (authMode) { + AuthMode.SshKey -> { credentialPref = PreferenceKeys.SSH_KEY_LOCAL_PASSPHRASE messageRes = R.string.passphrase_dialog_text hintRes = R.string.ssh_keygen_passphrase rememberRes = R.string.git_operation_remember_passphrase errorRes = R.string.git_operation_wrong_passphrase } - ConnectionMode.Password -> { + AuthMode.Password -> { // Could be either an SSH or an HTTPS password credentialPref = PreferenceKeys.HTTPS_PASSWORD messageRes = R.string.password_dialog_text diff --git a/app/src/main/java/com/zeapo/pwdstore/git/operation/GitOperation.kt b/app/src/main/java/com/zeapo/pwdstore/git/operation/GitOperation.kt index 3efd3bd8..d537ba7f 100644 --- a/app/src/main/java/com/zeapo/pwdstore/git/operation/GitOperation.kt +++ b/app/src/main/java/com/zeapo/pwdstore/git/operation/GitOperation.kt @@ -13,7 +13,7 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.zeapo.pwdstore.R import com.zeapo.pwdstore.UserPreference import com.zeapo.pwdstore.git.ErrorMessages -import com.zeapo.pwdstore.git.config.ConnectionMode +import com.zeapo.pwdstore.git.config.AuthMode import com.zeapo.pwdstore.git.config.GitSettings import com.zeapo.pwdstore.git.sshj.InteractivePasswordFinder import com.zeapo.pwdstore.git.sshj.SshAuthData @@ -116,10 +116,10 @@ abstract class GitOperation(gitDir: File, internal val callingActivity: Fragment abstract suspend fun execute() suspend fun executeAfterAuthentication( - connectionMode: ConnectionMode, + authMode: AuthMode, ) { - when (connectionMode) { - ConnectionMode.SshKey -> if (!sshKeyFile.exists()) { + when (authMode) { + AuthMode.SshKey -> if (!sshKeyFile.exists()) { MaterialAlertDialogBuilder(callingActivity) .setMessage(callingActivity.resources.getString(R.string.ssh_preferences_dialog_text)) .setTitle(callingActivity.resources.getString(R.string.ssh_preferences_dialog_title)) @@ -135,12 +135,12 @@ abstract class GitOperation(gitDir: File, internal val callingActivity: Fragment }.show() } else { withPublicKeyAuthentication( - CredentialFinder(callingActivity, connectionMode)).execute() + CredentialFinder(callingActivity, authMode)).execute() } - ConnectionMode.OpenKeychain -> withOpenKeychainAuthentication(callingActivity).execute() - ConnectionMode.Password -> withPasswordAuthentication( - CredentialFinder(callingActivity, connectionMode)).execute() - ConnectionMode.None -> execute() + AuthMode.OpenKeychain -> withOpenKeychainAuthentication(callingActivity).execute() + AuthMode.Password -> withPasswordAuthentication( + CredentialFinder(callingActivity, authMode)).execute() + AuthMode.None -> execute() } } diff --git a/app/src/main/res/layout/activity_git_clone.xml b/app/src/main/res/layout/activity_git_clone.xml index 7c59572c..f16bda94 100644 --- a/app/src/main/res/layout/activity_git_clone.xml +++ b/app/src/main/res/layout/activity_git_clone.xml @@ -40,7 +40,7 @@ app:layout_constraintTop_toBottomOf="@id/server_label" /> <com.google.android.material.button.MaterialButtonToggleGroup - android:id="@+id/clone_protocol_group" + android:id="@+id/protocol_group" style="@style/TextAppearance.MaterialComponents.Headline1" android:layout_width="0dp" android:layout_height="wrap_content" @@ -51,14 +51,14 @@ app:singleSelection="true"> <com.google.android.material.button.MaterialButton - android:id="@+id/clone_protocol_ssh" + android:id="@+id/protocol_ssh" style="?attr/materialButtonOutlinedStyle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/clone_protocol_ssh" /> <com.google.android.material.button.MaterialButton - android:id="@+id/clone_protocol_https" + android:id="@+id/protocol_https" style="?attr/materialButtonOutlinedStyle" android:layout_width="wrap_content" android:layout_height="wrap_content" @@ -73,7 +73,7 @@ android:hint="@string/server_url" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toBottomOf="@id/clone_protocol_group"> + app:layout_constraintTop_toBottomOf="@id/protocol_group"> <com.google.android.material.textfield.TextInputEditText android:id="@+id/server_url" @@ -117,7 +117,7 @@ app:layout_constraintTop_toBottomOf="@id/label_server_branch" /> <com.google.android.material.button.MaterialButtonToggleGroup - android:id="@+id/connection_mode_group" + android:id="@+id/auth_mode_group" style="@style/TextAppearance.MaterialComponents.Headline1" android:layout_width="wrap_content" android:layout_height="wrap_content" @@ -127,21 +127,21 @@ app:singleSelection="true"> <com.google.android.material.button.MaterialButton - android:id="@+id/connection_mode_ssh_key" + android:id="@+id/auth_mode_ssh_key" style="?attr/materialButtonOutlinedStyle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/connection_mode_ssh_key" /> <com.google.android.material.button.MaterialButton - android:id="@+id/connection_mode_password" + android:id="@+id/auth_mode_password" style="?attr/materialButtonOutlinedStyle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/connection_mode_basic_authentication" /> <com.google.android.material.button.MaterialButton - android:id="@+id/connection_mode_open_keychain" + android:id="@+id/auth_mode_open_keychain" style="?attr/materialButtonOutlinedStyle" android:layout_width="wrap_content" android:layout_height="wrap_content" @@ -155,6 +155,6 @@ android:layout_marginTop="8dp" android:text="@string/crypto_save" app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintTop_toBottomOf="@id/connection_mode_group" /> + app:layout_constraintTop_toBottomOf="@id/auth_mode_group" /> </androidx.constraintlayout.widget.ConstraintLayout> </ScrollView> |