Merge develop and selectable text

This commit is contained in:
J-Jamet
2022-02-13 13:49:41 +01:00
14 changed files with 176 additions and 46 deletions

View File

@@ -3,7 +3,8 @@ KeePassDX(3.3.0)
* Keep search context #1141 * Keep search context #1141
* Add searchable groups #905 #1006 * Add searchable groups #905 #1006
* Search with regular expression #175 * Search with regular expression #175
* Fix styles * Merge from file and save as copy #1221 #1204 #840
* New UI and fix styles
KeePassDX(3.2.0) KeePassDX(3.2.0)
* Manage data merge #840 #977 * Manage data merge #840 #977

View File

@@ -46,6 +46,7 @@ import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.core.view.GravityCompat import androidx.core.view.GravityCompat
import androidx.core.view.WindowInsetsCompat import androidx.core.view.WindowInsetsCompat
import androidx.core.view.WindowInsetsControllerCompat import androidx.core.view.WindowInsetsControllerCompat
import androidx.core.view.isVisible
import androidx.drawerlayout.widget.DrawerLayout import androidx.drawerlayout.widget.DrawerLayout
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.kunzisoft.keepass.R import com.kunzisoft.keepass.R
@@ -102,6 +103,7 @@ class GroupActivity : DatabaseLockActivity(),
private var lockView: View? = null private var lockView: View? = null
private var toolbar: Toolbar? = null private var toolbar: Toolbar? = null
private var databaseNameContainer: ViewGroup? = null private var databaseNameContainer: ViewGroup? = null
private var databaseModifiedView: ImageView? = null
private var databaseColorView: ImageView? = null private var databaseColorView: ImageView? = null
private var databaseNameView: TextView? = null private var databaseNameView: TextView? = null
private var searchView: SearchView? = null private var searchView: SearchView? = null
@@ -237,6 +239,7 @@ class GroupActivity : DatabaseLockActivity(),
addNodeButtonView = findViewById(R.id.add_node_button) addNodeButtonView = findViewById(R.id.add_node_button)
toolbar = findViewById(R.id.toolbar) toolbar = findViewById(R.id.toolbar)
databaseNameContainer = findViewById(R.id.database_name_container) databaseNameContainer = findViewById(R.id.database_name_container)
databaseModifiedView = findViewById(R.id.database_modified)
databaseColorView = findViewById(R.id.database_color) databaseColorView = findViewById(R.id.database_color)
databaseNameView = findViewById(R.id.database_name) databaseNameView = findViewById(R.id.database_name)
searchFiltersView = findViewById(R.id.search_filters) searchFiltersView = findViewById(R.id.search_filters)
@@ -575,13 +578,29 @@ class GroupActivity : DatabaseLockActivity(),
mRootGroup = database?.rootGroup mRootGroup = database?.rootGroup
loadGroup() loadGroup()
// Search suggestion // Update view
database?.let { database?.let {
mBreadcrumbAdapter?.iconDrawableFactory = it.iconDrawableFactory
}
databaseNavView?.apply {
if (!mMergeDataAllowed) {
menu.findItem(R.id.menu_merge_from)?.isVisible = false
}
}
refreshDatabaseViews()
invalidateOptionsMenu()
}
private fun refreshDatabaseViews() {
mDatabase?.let {
val databaseName = it.name.ifEmpty { getString(R.string.database) } val databaseName = it.name.ifEmpty { getString(R.string.database) }
databaseNavView?.setDatabaseName(databaseName) databaseNavView?.setDatabaseName(databaseName)
databaseNameView?.text = databaseName databaseNameView?.text = databaseName
databaseNavView?.setDatabasePath(it.fileUri?.toString()) databaseNavView?.setDatabasePath(it.fileUri?.toString())
databaseNavView?.setDatabaseVersion(it.version) databaseNavView?.setDatabaseVersion(it.version)
val modified = it.dataModifiedSinceLastLoading
databaseNavView?.setDatabaseModifiedSinceLastLoading(modified)
databaseModifiedView?.isVisible = modified
val customColor = it.customColor val customColor = it.customColor
databaseNavView?.setDatabaseColor(customColor) databaseNavView?.setDatabaseColor(customColor)
if (customColor != null) { if (customColor != null) {
@@ -593,16 +612,7 @@ class GroupActivity : DatabaseLockActivity(),
} else { } else {
databaseColorView?.visibility = View.GONE databaseColorView?.visibility = View.GONE
} }
mBreadcrumbAdapter?.iconDrawableFactory = it.iconDrawableFactory
} }
databaseNavView?.apply {
if (!mMergeDataAllowed) {
menu.findItem(R.id.menu_merge_from)?.isVisible = false
}
}
invalidateOptionsMenu()
} }
override fun onDatabaseActionFinished( override fun onDatabaseActionFinished(
@@ -750,6 +760,7 @@ class GroupActivity : DatabaseLockActivity(),
} else { } else {
// Add breadcrumb // Add breadcrumb
setBreadcrumbNode(group) setBreadcrumbNode(group)
refreshDatabaseViews()
invalidateOptionsMenu() invalidateOptionsMenu()
} }
initAddButton(group) initAddButton(group)

View File

@@ -358,13 +358,9 @@ class DatabaseTaskProvider {
fun startDatabaseMerge(fromDatabaseUri: Uri? = null, fun startDatabaseMerge(fromDatabaseUri: Uri? = null,
mainCredential: MainCredential? = null) { mainCredential: MainCredential? = null) {
start(Bundle().apply { start(Bundle().apply {
if (fromDatabaseUri != null) {
putParcelable(DatabaseTaskNotificationService.DATABASE_URI_KEY, fromDatabaseUri) putParcelable(DatabaseTaskNotificationService.DATABASE_URI_KEY, fromDatabaseUri)
}
if (mainCredential != null) {
putParcelable(DatabaseTaskNotificationService.MAIN_CREDENTIAL_KEY, mainCredential) putParcelable(DatabaseTaskNotificationService.MAIN_CREDENTIAL_KEY, mainCredential)
} }
}
, ACTION_DATABASE_MERGE_TASK) , ACTION_DATABASE_MERGE_TASK)
} }
@@ -701,9 +697,7 @@ class DatabaseTaskProvider {
fun startDatabaseSave(save: Boolean, saveToUri: Uri? = null) { fun startDatabaseSave(save: Boolean, saveToUri: Uri? = null) {
start(Bundle().apply { start(Bundle().apply {
putBoolean(DatabaseTaskNotificationService.SAVE_DATABASE_KEY, save) putBoolean(DatabaseTaskNotificationService.SAVE_DATABASE_KEY, save)
if (saveToUri != null) {
putParcelable(DatabaseTaskNotificationService.DATABASE_URI_KEY, saveToUri) putParcelable(DatabaseTaskNotificationService.DATABASE_URI_KEY, saveToUri)
}
} }
, ACTION_DATABASE_SAVE) , ACTION_DATABASE_SAVE)
} }

View File

@@ -748,9 +748,15 @@ class Database {
} }
databaseToMerge.mDatabaseKDB?.let { databaseKDBToMerge -> databaseToMerge.mDatabaseKDB?.let { databaseKDBToMerge ->
databaseMerger.merge(databaseKDBToMerge) databaseMerger.merge(databaseKDBToMerge)
if (databaseToMergeUri != null) {
this.dataModifiedSinceLastLoading = true
}
} }
databaseToMerge.mDatabaseKDBX?.let { databaseKDBXToMerge -> databaseToMerge.mDatabaseKDBX?.let { databaseKDBXToMerge ->
databaseMerger.merge(databaseKDBXToMerge) databaseMerger.merge(databaseKDBXToMerge)
if (databaseToMergeUri != null) {
this.dataModifiedSinceLastLoading = true
}
} }
} }
} else { } else {
@@ -903,9 +909,10 @@ class Database {
} }
@Throws(DatabaseOutputException::class) @Throws(DatabaseOutputException::class)
fun saveData(uri: Uri?, contentResolver: ContentResolver) { fun saveData(databaseCopyUri: Uri?, contentResolver: ContentResolver) {
try { try {
(uri ?: this.fileUri)?.let { saveUri -> val saveUri = databaseCopyUri ?: this.fileUri
if (saveUri != null) {
if (saveUri.scheme == "file") { if (saveUri.scheme == "file") {
saveUri.path?.let { filename -> saveUri.path?.let { filename ->
val tempFile = File("$filename.tmp") val tempFile = File("$filename.tmp")
@@ -954,8 +961,10 @@ class Database {
outputStream?.close() outputStream?.close()
} }
} }
if (databaseCopyUri == null) {
this.dataModifiedSinceLastLoading = false this.dataModifiedSinceLastLoading = false
} }
}
} catch (e: Exception) { } catch (e: Exception) {
Log.e(TAG, "Unable to save database", e) Log.e(TAG, "Unable to save database", e)
throw DatabaseOutputException(e) throw DatabaseOutputException(e)

View File

@@ -7,6 +7,7 @@ import android.widget.ImageView
import android.widget.TextView import android.widget.TextView
import androidx.core.graphics.BlendModeColorFilterCompat import androidx.core.graphics.BlendModeColorFilterCompat
import androidx.core.graphics.BlendModeCompat import androidx.core.graphics.BlendModeCompat
import androidx.core.view.isVisible
import com.google.android.material.navigation.NavigationView import com.google.android.material.navigation.NavigationView
import com.kunzisoft.keepass.R import com.kunzisoft.keepass.R
@@ -17,6 +18,7 @@ class NavigationDatabaseView @JvmOverloads constructor(context: Context,
private var databaseNavContainerView: View? = null private var databaseNavContainerView: View? = null
private var databaseNavIconView: ImageView? = null private var databaseNavIconView: ImageView? = null
private var databaseNavModifiedView: ImageView? = null
private var databaseNavColorView: ImageView? = null private var databaseNavColorView: ImageView? = null
private var databaseNavNameView: TextView? = null private var databaseNavNameView: TextView? = null
private var databaseNavPathView: TextView? = null private var databaseNavPathView: TextView? = null
@@ -25,6 +27,7 @@ class NavigationDatabaseView @JvmOverloads constructor(context: Context,
init { init {
inflateHeaderView(R.layout.nav_header_database) inflateHeaderView(R.layout.nav_header_database)
databaseNavIconView = databaseNavContainerView?.findViewById(R.id.nav_database_icon) databaseNavIconView = databaseNavContainerView?.findViewById(R.id.nav_database_icon)
databaseNavModifiedView = databaseNavContainerView?.findViewById(R.id.nav_database_modified)
databaseNavColorView = databaseNavContainerView?.findViewById(R.id.nav_database_color) databaseNavColorView = databaseNavContainerView?.findViewById(R.id.nav_database_color)
databaseNavNameView = databaseNavContainerView?.findViewById(R.id.nav_database_name) databaseNavNameView = databaseNavContainerView?.findViewById(R.id.nav_database_name)
databaseNavPathView = databaseNavContainerView?.findViewById(R.id.nav_database_path) databaseNavPathView = databaseNavContainerView?.findViewById(R.id.nav_database_path)
@@ -54,6 +57,10 @@ class NavigationDatabaseView @JvmOverloads constructor(context: Context,
databaseNavVersionView?.text = version databaseNavVersionView?.text = version
} }
fun setDatabaseModifiedSinceLastLoading(modified: Boolean) {
databaseNavModifiedView?.isVisible = modified
}
fun setDatabaseColor(color: Int?) { fun setDatabaseColor(color: Int?) {
if (color != null) { if (color != null) {
databaseNavColorView?.drawable?.colorFilter = BlendModeColorFilterCompat databaseNavColorView?.drawable?.colorFilter = BlendModeColorFilterCompat

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android" <vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="48dp" android:width="36dp"
android:height="48dp" android:height="36dp"
android:viewportWidth="48" android:viewportWidth="48"
android:viewportHeight="48"> android:viewportHeight="48">
<path <path

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="12dp"
android:height="12dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#ffffff"
android:strokeWidth="2.28571415"
android:strokeLineJoin="round"
android:strokeLineCap="round"
android:pathData="M 12 8 C 14.2091389993 8 16 9.79086100068 16 12 C 16 14.2091389993 14.2091389993 16 12 16 C 9.79086100068 16 8 14.2091389993 8 12 C 8 9.79086100068 9.79086100068 8 12 8 Z" />
</vector>

View File

@@ -60,16 +60,31 @@
</FrameLayout> </FrameLayout>
</androidx.appcompat.widget.Toolbar> </androidx.appcompat.widget.Toolbar>
<FrameLayout
android:layout_width="48dp"
android:layout_height="?attr/actionBarSize"
android:layout_below="@+id/special_mode_view"
android:layout_marginStart="50dp"
android:layout_marginLeft="50dp">
<ImageView <ImageView
android:id="@+id/database_color" android:id="@+id/database_color"
android:layout_width="12dp" android:layout_width="12dp"
android:layout_height="12dp" android:layout_height="12dp"
android:layout_marginTop="22dp" android:layout_gravity="center_vertical|start"
android:layout_marginStart="54dp"
android:layout_marginLeft="54dp"
android:layout_below="@+id/special_mode_view"
android:src="@drawable/background_rounded_square" android:src="@drawable/background_rounded_square"
android:contentDescription="@string/content_description_database_color"/> android:contentDescription="@string/content_description_database_color"/>
<ImageView
android:id="@+id/database_modified"
android:layout_width="12dp"
android:layout_height="12dp"
android:layout_marginStart="12dp"
android:layout_marginLeft="12dp"
android:layout_gravity="center_vertical|start"
android:visibility="gone"
android:src="@drawable/ic_modified_white_12dp"
android:tint="?attr/textColorInverse"
android:contentDescription="@string/save"/>
</FrameLayout>
<androidx.coordinatorlayout.widget.CoordinatorLayout <androidx.coordinatorlayout.widget.CoordinatorLayout
android:id="@+id/group_coordinator" android:id="@+id/group_coordinator"

View File

@@ -119,7 +119,8 @@
<com.kunzisoft.keepass.view.MainCredentialView <com.kunzisoft.keepass.view.MainCredentialView
android:id="@+id/activity_password_credentials" android:id="@+id/activity_password_credentials"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" /> android:layout_height="wrap_content"
android:background="?android:attr/windowBackground" />
</FrameLayout> </FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -27,10 +27,10 @@
android:paddingLeft="8dp" android:paddingLeft="8dp"
android:paddingEnd="8dp" android:paddingEnd="8dp"
android:paddingRight="8dp" android:paddingRight="8dp"
style="@style/KeepassDXStyle.TextAppearance.Info" style="@style/KeepassDXStyle.TextAppearance.Secondary.TextOnPrimary"
android:textSize="10sp" android:textSize="11sp"
tools:text="version" tools:text="version"
tools:ignore="SmallSp" /> android:textIsSelectable="true" />
<ImageView <ImageView
android:id="@+id/nav_database_icon" android:id="@+id/nav_database_icon"
@@ -40,19 +40,34 @@
app:layout_constraintTop_toBottomOf="@+id/nav_database_version" app:layout_constraintTop_toBottomOf="@+id/nav_database_version"
app:layout_constraintBottom_toTopOf="@+id/nav_database_name" app:layout_constraintBottom_toTopOf="@+id/nav_database_name"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
android:layout_marginStart="6dp"
android:layout_marginLeft="6dp"
android:layout_marginBottom="12dp" android:layout_marginBottom="12dp"
app:srcCompat="@drawable/ic_database_white_48dp" app:srcCompat="@drawable/ic_database_white_36dp"
app:tint="?attr/textColorInverse"/> style="@style/KeepassDXStyle.Icon"
app:tint="?attr/colorAccent" />
<ImageView
android:id="@+id/nav_database_modified"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/save"
android:src="@drawable/ic_modified_white_12dp"
android:tint="?attr/textColorInverse"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="@+id/nav_database_icon"
app:layout_constraintStart_toEndOf="@+id/nav_database_icon"
app:layout_constraintTop_toTopOf="@+id/nav_database_icon" />
<ImageView <ImageView
android:id="@+id/nav_database_color" android:id="@+id/nav_database_color"
android:layout_width="18dp" android:layout_width="18dp"
android:layout_height="18dp" android:layout_height="18dp"
android:layout_gravity="center"
android:contentDescription="@string/content_description_database_color" android:contentDescription="@string/content_description_database_color"
android:src="@drawable/background_icon" android:src="@drawable/background_icon"
app:layout_constraintBottom_toBottomOf="@+id/nav_database_name" app:layout_constraintBottom_toBottomOf="@+id/nav_database_name"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent" />
app:layout_constraintTop_toTopOf="@+id/nav_database_name" />
<TextView <TextView
android:id="@+id/nav_database_name" android:id="@+id/nav_database_name"
@@ -62,6 +77,7 @@
android:layout_marginBottom="6dp" android:layout_marginBottom="6dp"
android:maxLines="2" android:maxLines="2"
android:text="@string/database" android:text="@string/database"
android:textIsSelectable="true"
app:layout_constraintBottom_toTopOf="@+id/nav_database_path" app:layout_constraintBottom_toTopOf="@+id/nav_database_path"
app:layout_constraintEnd_toStartOf="@+id/nav_database_color" app:layout_constraintEnd_toStartOf="@+id/nav_database_color"
app:layout_constraintStart_toStartOf="parent" /> app:layout_constraintStart_toStartOf="parent" />
@@ -73,5 +89,6 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
android:textSize="11sp" android:textSize="11sp"
android:text="@string/path"/> android:text="@string/path"
android:textIsSelectable="true"/>
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -12,7 +12,6 @@
android:paddingRight="12dp" android:paddingRight="12dp"
android:paddingEnd="12dp" android:paddingEnd="12dp"
android:paddingBottom="12dp" android:paddingBottom="12dp"
android:background="?android:attr/windowBackground"
tools:targetApi="lollipop"> tools:targetApi="lollipop">
<!-- Password Input --> <!-- Password Input -->

61
art/ic_modified.svg Normal file
View File

@@ -0,0 +1,61 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="24"
height="24"
viewBox="0 0 24 24"
version="1.1"
id="svg4"
sodipodi:docname="ic_modified.svg"
inkscape:version="0.92.4 (5da689c313, 2019-01-14)">
<metadata
id="metadata10">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs8" />
<sodipodi:namedview
pagecolor="#c8c8c8"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0.28235294"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1016"
id="namedview6"
showgrid="true"
inkscape:zoom="32.000001"
inkscape:cx="-2.6793549"
inkscape:cy="13.621945"
inkscape:window-x="1920"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:current-layer="svg4">
<inkscape:grid
type="xygrid"
id="grid818" />
</sodipodi:namedview>
<circle
r="4"
cy="12"
cx="12"
id="circle816"
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2.28571415;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke fill markers" />
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@@ -2,4 +2,5 @@
* Keep search context #1141 * Keep search context #1141
* Add searchable groups #905 #1006 * Add searchable groups #905 #1006
* Search with regular expression #175 * Search with regular expression #175
* Fix styles * Merge from file and save as copy #1221 #1204 #840
* New UI and fix styles

View File

@@ -2,4 +2,5 @@
* Garde le contexte de recherche #1141 * Garde le contexte de recherche #1141
* Ajout des groupes cherchables #905 #1006 * Ajout des groupes cherchables #905 #1006
* Recherche avec expression régulière #175 * Recherche avec expression régulière #175
* Correction des styles * Fusion depuis un fichier et sauvegarde de copie #1221 #1204 #840
* Nouvelle interface utilisateur et correction des styles