Add Activity to view the Git commit log (#1056)
This commit is contained in:
parent
88b1de2b50
commit
0f0d1994e5
18 changed files with 342 additions and 52 deletions
|
@ -8,6 +8,7 @@ All notable changes to this project will be documented in this file.
|
|||
|
||||
- Allow sorting by recently used
|
||||
- Add [Bromite](https://www.bromite.org/) and [Ungoogled Chromium](https://git.droidware.info/wchen342/ungoogled-chromium-android) to supported browsers list for Autofill
|
||||
- Add ability to view the Git commit log
|
||||
|
||||
### Changed
|
||||
|
||||
|
@ -17,7 +18,6 @@ All notable changes to this project will be documented in this file.
|
|||
|
||||
### Fixed
|
||||
|
||||
- Password creation UI will scroll if it does not fit on the screen
|
||||
- Git server protocol and authentication mode are only updated when explicitly saved
|
||||
- Remember HTTPS password during a sync operation
|
||||
|
||||
|
|
|
@ -65,6 +65,10 @@
|
|||
android:label="@string/title_activity_git_config"
|
||||
android:windowSoftInputMode="adjustResize" />
|
||||
|
||||
<activity
|
||||
android:name=".git.log.GitLogActivity"
|
||||
android:label="@string/title_activity_git_log" />
|
||||
|
||||
<activity
|
||||
android:name=".UserPreference"
|
||||
android:label="@string/action_settings"
|
||||
|
|
|
@ -48,6 +48,7 @@ import com.zeapo.pwdstore.crypto.BasePgpActivity.Companion.getLongName
|
|||
import com.zeapo.pwdstore.crypto.DecryptActivity
|
||||
import com.zeapo.pwdstore.crypto.PasswordCreationActivity
|
||||
import com.zeapo.pwdstore.git.BaseGitActivity
|
||||
import com.zeapo.pwdstore.git.log.GitLogActivity
|
||||
import com.zeapo.pwdstore.git.GitOperationActivity
|
||||
import com.zeapo.pwdstore.git.GitServerConfigActivity
|
||||
import com.zeapo.pwdstore.git.config.AuthMode
|
||||
|
|
|
@ -4,20 +4,24 @@
|
|||
*/
|
||||
package com.zeapo.pwdstore.git
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.util.Patterns
|
||||
import androidx.core.os.postDelayed
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.github.ajalt.timberkt.e
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import com.zeapo.pwdstore.R
|
||||
import com.zeapo.pwdstore.databinding.ActivityGitConfigBinding
|
||||
import com.zeapo.pwdstore.git.config.GitSettings
|
||||
import com.zeapo.pwdstore.git.log.GitLogActivity
|
||||
import com.zeapo.pwdstore.utils.PasswordRepository
|
||||
import com.zeapo.pwdstore.utils.viewBinding
|
||||
import kotlinx.coroutines.launch
|
||||
import org.eclipse.jgit.lib.Constants
|
||||
import org.eclipse.jgit.lib.Repository
|
||||
|
||||
class GitConfigActivity : BaseGitActivity() {
|
||||
|
||||
|
@ -33,23 +37,7 @@ class GitConfigActivity : BaseGitActivity() {
|
|||
else
|
||||
binding.gitUserName.setText(GitSettings.authorName)
|
||||
binding.gitUserEmail.setText(GitSettings.authorEmail)
|
||||
val repo = PasswordRepository.getRepository(PasswordRepository.getRepositoryDirectory())
|
||||
if (repo != null) {
|
||||
try {
|
||||
val objectId = repo.resolve(Constants.HEAD)
|
||||
val ref = repo.getRef("refs/heads/${GitSettings.branch}")
|
||||
val head = if (ref.objectId.equals(objectId)) ref.name else "DETACHED"
|
||||
binding.gitCommitHash.text = String.format("%s (%s)", objectId.abbreviate(8).name(), head)
|
||||
|
||||
// enable the abort button only if we're rebasing
|
||||
val isRebasing = repo.repositoryState.isRebasing
|
||||
binding.gitAbortRebase.isEnabled = isRebasing
|
||||
binding.gitAbortRebase.alpha = if (isRebasing) 1.0f else 0.5f
|
||||
} catch (ignored: Exception) {
|
||||
}
|
||||
}
|
||||
binding.gitAbortRebase.setOnClickListener { lifecycleScope.launch { launchGitOperation(BREAK_OUT_OF_DETACHED) } }
|
||||
binding.gitResetToRemote.setOnClickListener { lifecycleScope.launch { launchGitOperation(REQUEST_RESET) } }
|
||||
setupTools()
|
||||
binding.saveButton.setOnClickListener {
|
||||
val email = binding.gitUserEmail.text.toString().trim()
|
||||
val name = binding.gitUserName.text.toString().trim()
|
||||
|
@ -66,4 +54,50 @@ class GitConfigActivity : BaseGitActivity() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up the UI components of the tools section.
|
||||
*/
|
||||
private fun setupTools() {
|
||||
val repo = PasswordRepository.getRepository(null)
|
||||
if (repo != null) {
|
||||
binding.gitHeadStatus.text = headStatusMsg(repo)
|
||||
// enable the abort button only if we're rebasing
|
||||
val isRebasing = repo.repositoryState.isRebasing
|
||||
binding.gitAbortRebase.isEnabled = isRebasing
|
||||
binding.gitAbortRebase.alpha = if (isRebasing) 1.0f else 0.5f
|
||||
}
|
||||
binding.gitLog.setOnClickListener {
|
||||
try {
|
||||
intent = Intent(this, GitLogActivity::class.java)
|
||||
startActivity(intent)
|
||||
} catch (ex: Exception) {
|
||||
e(ex) { "Failed to start GitLogActivity" }
|
||||
}
|
||||
}
|
||||
binding.gitAbortRebase.setOnClickListener { lifecycleScope.launch { launchGitOperation(BREAK_OUT_OF_DETACHED) } }
|
||||
binding.gitResetToRemote.setOnClickListener { lifecycleScope.launch { launchGitOperation(REQUEST_RESET) } }
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a user-friendly message about the current state of HEAD.
|
||||
*
|
||||
* The state is recognized to be either pointing to a branch or detached.
|
||||
*/
|
||||
private fun headStatusMsg(repo: Repository): String {
|
||||
return try {
|
||||
val headRef = repo.getRef(Constants.HEAD)
|
||||
if (headRef.isSymbolic) {
|
||||
val branchName = headRef.target.name
|
||||
val shortBranchName = Repository.shortenRefName(branchName)
|
||||
getString(R.string.git_head_on_branch, shortBranchName)
|
||||
} else {
|
||||
val commitHash = headRef.objectId.abbreviate(8).name()
|
||||
getString(R.string.git_head_detached, commitHash)
|
||||
}
|
||||
} catch (ex: Exception) {
|
||||
e(ex) { "Error getting HEAD reference" }
|
||||
getString(R.string.git_head_missing)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
18
app/src/main/java/com/zeapo/pwdstore/git/log/GitCommit.kt
Normal file
18
app/src/main/java/com/zeapo/pwdstore/git/log/GitCommit.kt
Normal file
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
* Copyright © 2014-2020 The Android Password Store Authors. All Rights Reserved.
|
||||
* SPDX-License-Identifier: GPL-3.0-only
|
||||
*/
|
||||
|
||||
package com.zeapo.pwdstore.git.log
|
||||
|
||||
import java.util.Date
|
||||
|
||||
/**
|
||||
* Basic information about a git commit.
|
||||
*
|
||||
* @property hash full-length hash of the commit object.
|
||||
* @property shortMessage the commit's short message (i.e. title line).
|
||||
* @property authorName name of the commit's author without email address.
|
||||
* @property time time when the commit was created.
|
||||
*/
|
||||
data class GitCommit(val hash: String, val shortMessage: String, val authorName: String, val time: Date)
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright © 2014-2020 The Android Password Store Authors. All Rights Reserved.
|
||||
* SPDX-License-Identifier: GPL-3.0-only
|
||||
*/
|
||||
|
||||
package com.zeapo.pwdstore.git.log
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.recyclerview.widget.DividerItemDecoration
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.zeapo.pwdstore.databinding.ActivityGitLogBinding
|
||||
import com.zeapo.pwdstore.git.BaseGitActivity
|
||||
import com.zeapo.pwdstore.utils.viewBinding
|
||||
|
||||
/**
|
||||
* Displays the repository's git commits in git-log fashion.
|
||||
*
|
||||
* It provides basic information about each commit by way of a non-interactive RecyclerView.
|
||||
*/
|
||||
class GitLogActivity : BaseGitActivity() {
|
||||
|
||||
private val binding by viewBinding(ActivityGitLogBinding::inflate)
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(binding.root)
|
||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||
createRecyclerView()
|
||||
}
|
||||
|
||||
private fun createRecyclerView() {
|
||||
binding.gitLogRecyclerView.apply {
|
||||
setHasFixedSize(true)
|
||||
addItemDecoration(DividerItemDecoration(context, LinearLayoutManager.VERTICAL))
|
||||
adapter = GitLogAdapter()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Copyright © 2014-2020 The Android Password Store Authors. All Rights Reserved.
|
||||
* SPDX-License-Identifier: GPL-3.0-only
|
||||
*/
|
||||
|
||||
package com.zeapo.pwdstore.git.log
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.github.ajalt.timberkt.e
|
||||
import com.zeapo.pwdstore.databinding.GitLogRowLayoutBinding
|
||||
import java.text.DateFormat
|
||||
import java.util.Date
|
||||
|
||||
private fun shortHash(hash: String): String {
|
||||
return hash.substring(0 until 8)
|
||||
}
|
||||
|
||||
private fun stringFrom(date: Date): String {
|
||||
return DateFormat.getDateTimeInstance().format(date)
|
||||
}
|
||||
|
||||
/**
|
||||
* @see GitLogActivity
|
||||
*/
|
||||
class GitLogAdapter : RecyclerView.Adapter<GitLogAdapter.ViewHolder>() {
|
||||
|
||||
private val model = GitLogModel()
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||
val inflater = LayoutInflater.from(parent.context)
|
||||
val binding = GitLogRowLayoutBinding.inflate(inflater, parent, false)
|
||||
return ViewHolder(binding)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(viewHolder: ViewHolder, position: Int) {
|
||||
val commit = model.get(position)
|
||||
if (commit == null) {
|
||||
e { "There is no git commit for view holder at position $position." }
|
||||
return
|
||||
}
|
||||
viewHolder.bind(commit)
|
||||
}
|
||||
|
||||
override fun getItemCount() = model.size
|
||||
|
||||
class ViewHolder(private val binding: GitLogRowLayoutBinding) : RecyclerView.ViewHolder(binding.root) {
|
||||
|
||||
fun bind(commit: GitCommit) = with(binding) {
|
||||
gitLogRowMessage.text = commit.shortMessage
|
||||
gitLogRowHash.text = shortHash(commit.hash)
|
||||
gitLogRowTime.text = stringFrom(commit.time)
|
||||
}
|
||||
}
|
||||
}
|
53
app/src/main/java/com/zeapo/pwdstore/git/log/GitLogModel.kt
Normal file
53
app/src/main/java/com/zeapo/pwdstore/git/log/GitLogModel.kt
Normal file
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* Copyright © 2014-2020 The Android Password Store Authors. All Rights Reserved.
|
||||
* SPDX-License-Identifier: GPL-3.0-only
|
||||
*/
|
||||
|
||||
package com.zeapo.pwdstore.git.log
|
||||
|
||||
import com.github.ajalt.timberkt.e
|
||||
import com.zeapo.pwdstore.utils.PasswordRepository
|
||||
import com.zeapo.pwdstore.utils.hash
|
||||
import com.zeapo.pwdstore.utils.time
|
||||
import org.eclipse.jgit.api.Git
|
||||
import org.eclipse.jgit.revwalk.RevCommit
|
||||
|
||||
private fun commits(): Iterable<RevCommit> {
|
||||
val repo = PasswordRepository.getRepository(null)
|
||||
if (repo == null) {
|
||||
e { "Could not access git repository" }
|
||||
return listOf()
|
||||
}
|
||||
return try {
|
||||
Git(repo).log().call()
|
||||
} catch (exc: Exception) {
|
||||
e(exc) { "Failed to obtain git commits" }
|
||||
listOf()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides [GitCommit]s from a git-log of the password git repository.
|
||||
*
|
||||
* All commits are acquired on the first request to this object.
|
||||
*/
|
||||
class GitLogModel {
|
||||
|
||||
// All commits are acquired here at once. Acquiring the commits in batches would not have been
|
||||
// entirely sensible because the amount of computation required to obtain commit number n from
|
||||
// the log includes the amount of computation required to obtain commit number n-1 from the log.
|
||||
// This is because the commit graph is walked from HEAD to the last commit to obtain.
|
||||
// Additionally, tests with 1000 commits in the log have not produced a significant delay in the
|
||||
// user experience.
|
||||
private val cache: MutableList<GitCommit> by lazy {
|
||||
commits().map {
|
||||
GitCommit(it.hash, it.shortMessage, it.authorIdent.name, it.time)
|
||||
}.toMutableList()
|
||||
}
|
||||
val size = cache.size
|
||||
|
||||
fun get(index: Int): GitCommit? {
|
||||
if (index >= size) e { "Cannot get git commit with index $index. There are only $size." }
|
||||
return cache.getOrNull(index)
|
||||
}
|
||||
}
|
|
@ -28,6 +28,9 @@ import com.zeapo.pwdstore.git.GitCommandExecutor
|
|||
import com.zeapo.pwdstore.git.operation.GitOperation
|
||||
import com.zeapo.pwdstore.utils.PasswordRepository.Companion.getRepositoryDirectory
|
||||
import java.io.File
|
||||
import java.util.Date
|
||||
import org.eclipse.jgit.lib.ObjectId
|
||||
import org.eclipse.jgit.revwalk.RevCommit
|
||||
|
||||
const val OPENPGP_PROVIDER = "org.sufficientlysecure.keychain"
|
||||
|
||||
|
@ -162,3 +165,23 @@ val Context.autofillManager: AutofillManager?
|
|||
fun File.isInsideRepository(): Boolean {
|
||||
return canonicalPath.contains(getRepositoryDirectory().canonicalPath)
|
||||
}
|
||||
|
||||
/**
|
||||
* Unique SHA-1 hash of this commit as hexadecimal string.
|
||||
*
|
||||
* @see RevCommit.id
|
||||
*/
|
||||
val RevCommit.hash: String
|
||||
get() = ObjectId.toString(id)
|
||||
|
||||
/**
|
||||
* Time this commit was made with second precision.
|
||||
*
|
||||
* @see RevCommit.commitTime
|
||||
*/
|
||||
val RevCommit.time: Date
|
||||
get() {
|
||||
val epochSeconds = commitTime.toLong()
|
||||
val epochMilliseconds = epochSeconds * 1000
|
||||
return Date(epochMilliseconds)
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
android:id="@+id/username_input_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="8dp"
|
||||
android:layout_margin="@dimen/normal_margin"
|
||||
android:hint="@string/git_user_name_hint"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
|
@ -35,7 +35,7 @@
|
|||
android:id="@+id/email_input_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="8dp"
|
||||
android:layout_margin="@dimen/normal_margin"
|
||||
android:hint="@string/git_user_email"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/username_input_layout">
|
||||
|
@ -52,7 +52,7 @@
|
|||
android:id="@+id/save_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="8dp"
|
||||
android:layout_margin="@dimen/normal_margin"
|
||||
android:text="@string/crypto_save"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/email_input_layout" />
|
||||
|
@ -62,45 +62,43 @@
|
|||
style="@style/TextAppearance.MaterialComponents.Headline5"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="8dp"
|
||||
android:text="@string/hackish_tools"
|
||||
android:layout_margin="@dimen/normal_margin"
|
||||
android:text="@string/git_tools"
|
||||
android:textSize="24sp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/save_button" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/commit_hash_label"
|
||||
android:id="@+id/git_head_status"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="8dp"
|
||||
android:text="@string/commit_hash"
|
||||
android:layout_margin="@dimen/normal_margin"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/git_tools_title" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/git_commit_hash"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="8dp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintStart_toEndOf="@id/commit_hash_label"
|
||||
app:layout_constraintTop_toBottomOf="@id/git_tools_title"
|
||||
tools:text="HASH" />
|
||||
tools:text="HEAD status" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/git_log"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="@dimen/normal_margin"
|
||||
android:text="@string/git_log"
|
||||
app:layout_constraintTop_toBottomOf="@+id/git_head_status" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/git_abort_rebase"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="8dp"
|
||||
android:layout_margin="@dimen/normal_margin"
|
||||
android:text="@string/abort_rebase"
|
||||
app:layout_constraintTop_toBottomOf="@id/commit_hash_label" />
|
||||
app:layout_constraintTop_toBottomOf="@+id/git_log" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/git_reset_to_remote"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="8dp"
|
||||
android:layout_margin="@dimen/normal_margin"
|
||||
android:text="@string/reset_to_remote"
|
||||
app:layout_constraintTop_toBottomOf="@id/git_abort_rebase" />
|
||||
|
||||
|
|
22
app/src/main/res/layout/activity_git_log.xml
Normal file
22
app/src/main/res/layout/activity_git_log.xml
Normal file
|
@ -0,0 +1,22 @@
|
|||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ Copyright © 2014-2020 The Android Password Store Authors. All Rights Reserved.
|
||||
~ SPDX-License-Identifier: GPL-3.0-only
|
||||
-->
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/git_log_recycler_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:scrollbars="vertical"
|
||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
||||
tools:context="com.zeapo.pwdstore.git.log.GitLogActivity"
|
||||
tools:listitem="@layout/git_log_row_layout" />
|
||||
|
||||
</LinearLayout>
|
45
app/src/main/res/layout/git_log_row_layout.xml
Normal file
45
app/src/main/res/layout/git_log_row_layout.xml
Normal file
|
@ -0,0 +1,45 @@
|
|||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ Copyright © 2014-2020 The Android Password Store Authors. All Rights Reserved.
|
||||
~ SPDX-License-Identifier: GPL-3.0-only
|
||||
-->
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingHorizontal="@dimen/activity_vertical_margin"
|
||||
android:paddingVertical="@dimen/activity_horizontal_margin">
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/git_log_row_message"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/normal_margin"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="2"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/git_log_row_hash"
|
||||
tools:text="Commit message" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/git_log_row_hash"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="?attr/colorSecondary"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="Hash" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/git_log_row_time"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:alpha="0.5"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="Time" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -11,6 +11,7 @@
|
|||
<string name="dialog_delete">Ordner löschen</string>
|
||||
<string name="dialog_do_not_delete">Abbruch</string>
|
||||
<string name="title_activity_git_clone">Repository Informationen</string>
|
||||
<string name="title_activity_git_log">Commit-Log</string>
|
||||
<!-- Password Store -->
|
||||
<string name="creation_dialog_text">Bitte klone oder erstelle ein neues Repository, bevor du versuchst ein Passwort hinzuzufügen oder jegliche Synchronisation-Operation durchführst.</string>
|
||||
<string name="move">Verschieben</string>
|
||||
|
@ -121,6 +122,7 @@
|
|||
<string name="git_sync">Synchronisiere Repository</string>
|
||||
<string name="git_pull">Git Pull</string>
|
||||
<string name="git_push">Git Push</string>
|
||||
<string name="git_log">Commit-Log anzeigen</string>
|
||||
<string name="show_password_pref_title">Zeige das Password</string>
|
||||
<string name="show_password_pref_summary">Soll das entschlüsselte Passwort sichtbar sein? Dies deaktiviert nicht das Kopieren.</string>
|
||||
<string name="show_extra_content_pref_title">Zeige weiteren Inhalt</string>
|
||||
|
|
|
@ -178,7 +178,5 @@
|
|||
<string name="git_push_generic_error">El envío fue rechazado por el servidor, la razón:</string>
|
||||
<string name="jgit_error_push_dialog_text">Ocurrió un error durante el envío:</string>
|
||||
<string name="git_operation_remember_passphrase">Recordar contraseñagit (inseguro)</string>
|
||||
<string name="hackish_tools">Hackish tools</string>
|
||||
<string name="abort_rebase">Abortar rebase</string>
|
||||
<string name="commit_hash">Hash del commit</string>
|
||||
</resources>
|
||||
|
|
|
@ -178,6 +178,4 @@
|
|||
<string name="git_push_other_error">Pousser au dépôt distant sans avance rapide rejetée. Vérifiez la variable receive.denyNonFastForwards dans le fichier de configuration du répertoire de destination.</string>
|
||||
<string name="jgit_error_push_dialog_text">Une erreur s\'est produite lors de l\'opération de poussée:</string>
|
||||
<string name="git_operation_remember_passphrase">Se rappeler de la phrase secrète dans la configuration de l\'application (peu sûr)</string>
|
||||
<string name="hackish_tools">Outils de hack</string>
|
||||
<string name="commit_hash">Commettre la clé</string>
|
||||
</resources>
|
||||
|
|
|
@ -248,10 +248,8 @@
|
|||
<string name="clear_saved_passphrase_ssh">Limpar a frase secreta salva para chave SSH local</string>
|
||||
<string name="clear_saved_passphrase_https">Limpar senha HTTPS salva</string>
|
||||
<string name="git_operation_remember_passphrase">Lembrar senha da chave</string>
|
||||
<string name="hackish_tools">Ferramentas de hackers</string>
|
||||
<string name="abort_rebase">Abortar rebase e realizar push do novo branch</string>
|
||||
<string name="reset_to_remote">Hard reset no branch remoto</string>
|
||||
<string name="commit_hash">Commit hash</string>
|
||||
<string name="openkeychain_ssh_api_connect_fail">Falha ao conectar ao serviço de API SSH do OpenKeychain.</string>
|
||||
<string name="no_ssh_api_provider">Nenhum provedor de API SSH encontrado. O OpenKeychain está instalado?</string>
|
||||
<string name="ssh_api_pending_intent_failed">SSH API pendente falhou</string>
|
||||
|
|
|
@ -233,10 +233,8 @@
|
|||
<string name="git_push_other_error">Удаленный репозиторий отклонил запись изменений без быстрой перемотки вперед. Проверьте переменную receive.denyNonFastForwards в файле конфигурации репозитория назначения.</string>
|
||||
<string name="jgit_error_push_dialog_text">В хоте операции записи изменений возникла ошибка:</string>
|
||||
<string name="git_operation_remember_passphrase">Заполнить парольную фразу в конфигурации приложнеия (небезопасно)</string>
|
||||
<string name="hackish_tools">Костыльные инструменты</string>
|
||||
<string name="abort_rebase">Прервать перебазирование и записать изменения в новую ветку</string>
|
||||
<string name="reset_to_remote">Полный сброс до состояния удаленной ветки</string>
|
||||
<string name="commit_hash">Хэш-сумма изменений</string>
|
||||
<string name="openkeychain_ssh_api_connect_fail">Ошибка при подключении к сервису OpenKeychain SSH API</string>
|
||||
<string name="no_ssh_api_provider">Не найдено SSH API провайдеров. OpenKeychain установлен?</string>
|
||||
<string name="ssh_api_pending_intent_failed">Ожидаемое намерение SSH API не удалось</string>
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
<string name="dialog_do_not_delete">Cancel</string>
|
||||
<string name="title_activity_git_clone">Repository information</string>
|
||||
<string name="title_activity_git_config" translatable="false">Git configuration</string>
|
||||
<string name="title_activity_git_log">Commit log</string>
|
||||
|
||||
<!-- Password Store -->
|
||||
<string name="creation_dialog_text">Please clone or create a new repository below before trying to add a password or running any synchronization operation.</string>
|
||||
|
@ -117,8 +118,8 @@
|
|||
|
||||
<!-- Preferences -->
|
||||
<string name="pref_repository_title">Repository</string>
|
||||
<string name="pref_edit_server_info">Edit git server settings</string>
|
||||
<string name="pref_edit_git_config">Git utils</string>
|
||||
<string name="pref_edit_server_info">Edit Git server settings</string>
|
||||
<string name="pref_edit_git_config">Local Git config & utilities</string>
|
||||
<string name="pref_ssh_title">Import SSH key</string>
|
||||
<string name="pref_ssh_keygen_title">Generate SSH key pair</string>
|
||||
<string name="pref_ssh_see_key_title">View generated public SSH key</string>
|
||||
|
@ -217,6 +218,7 @@
|
|||
<string name="git_pull">Pull from remote</string>
|
||||
<string name="git_push">Push to remote</string>
|
||||
<string name="git_push_up_to_date">Everything up-to-date</string>
|
||||
<string name="git_log">Show commit log</string>
|
||||
<string name="show_password_pref_title">Show the password</string>
|
||||
<string name="show_password_pref_summary">Control the visibility of the passwords once decrypted. This does not disable copying to clipboard.</string>
|
||||
<string name="show_extra_content_pref_title">Show extra content</string>
|
||||
|
@ -281,10 +283,12 @@
|
|||
<string name="clear_saved_passphrase_ssh">Clear saved passphrase for local SSH key</string>
|
||||
<string name="clear_saved_passphrase_https">Clear saved HTTPS password</string>
|
||||
<string name="git_operation_remember_passphrase">Remember key passphrase</string>
|
||||
<string name="hackish_tools">Hackish tools</string>
|
||||
<string name="git_tools">Utilities</string>
|
||||
<string name="abort_rebase">Abort rebase and push new branch</string>
|
||||
<string name="reset_to_remote">Hard reset to remote branch</string>
|
||||
<string name="commit_hash">Commit hash</string>
|
||||
<string name="git_head_on_branch">On branch %1$s</string>
|
||||
<string name="git_head_detached">HEAD detached at %1$s</string>
|
||||
<string name="git_head_missing">Unable to locate HEAD</string>
|
||||
<string name="openkeychain_ssh_api_connect_fail">Failed to connect to OpenKeychain SSH API service.</string>
|
||||
<string name="no_ssh_api_provider">No SSH API provider found. Is OpenKeychain installed?</string>
|
||||
<string name="ssh_api_pending_intent_failed">SSH API pending intent failed</string>
|
||||
|
@ -393,6 +397,6 @@
|
|||
<!-- GPG key selection in folder creation -->
|
||||
<string name="folder_creation_err_file_exists">A file by that name already exists</string>
|
||||
<string name="folder_creation_err_folder_exists">A folder by that name already exists</string>
|
||||
<string name="xkpwgen_extrachars_label" >Digits/Symbols (d/s)</string>
|
||||
<string name="xkpwgen_extrachars_label">Digits/Symbols (d/s)</string>
|
||||
<string name="xk_numbers_symbols_append_default">ds</string>
|
||||
</resources>
|
||||
|
|
Loading…
Reference in a new issue