mirror of
https://github.com/Kunzisoft/KeePassDX.git
synced 2025-12-04 15:49:33 +01:00
Change list to recyclerview
This commit is contained in:
@@ -242,7 +242,7 @@ class EntryActivity : LockingActivity() {
|
|||||||
val entryInfo = entry.getEntryInfo(mDatabase)
|
val entryInfo = entry.getEntryInfo(mDatabase)
|
||||||
|
|
||||||
// Assign title icon
|
// Assign title icon
|
||||||
titleIconView?.assignDatabaseIcon(mDatabase!!.drawFactory, entryInfo.icon, iconColor)
|
titleIconView?.assignDatabaseIcon(mDatabase!!.iconDrawableFactory, entryInfo.icon, iconColor)
|
||||||
|
|
||||||
// Assign title text
|
// Assign title text
|
||||||
val entryTitle = entryInfo.title
|
val entryTitle = entryInfo.title
|
||||||
|
|||||||
@@ -208,7 +208,7 @@ class EntryEditActivity : LockingActivity(),
|
|||||||
.replace(R.id.entry_edit_contents, entryEditFragment!!, ENTRY_EDIT_FRAGMENT_TAG)
|
.replace(R.id.entry_edit_contents, entryEditFragment!!, ENTRY_EDIT_FRAGMENT_TAG)
|
||||||
.commit()
|
.commit()
|
||||||
entryEditFragment?.apply {
|
entryEditFragment?.apply {
|
||||||
drawFactory = mDatabase?.drawFactory
|
drawFactory = mDatabase?.iconDrawableFactory
|
||||||
setOnDateClickListener = {
|
setOnDateClickListener = {
|
||||||
expiryTime.date.let { expiresDate ->
|
expiryTime.date.let { expiresDate ->
|
||||||
val dateTime = DateTime(expiresDate)
|
val dateTime = DateTime(expiresDate)
|
||||||
|
|||||||
@@ -535,8 +535,8 @@ class GroupActivity : LockingActivity(),
|
|||||||
// Assign the group icon depending of IconPack or custom icon
|
// Assign the group icon depending of IconPack or custom icon
|
||||||
iconView?.visibility = View.VISIBLE
|
iconView?.visibility = View.VISIBLE
|
||||||
mCurrentGroup?.let {
|
mCurrentGroup?.let {
|
||||||
if (mDatabase?.drawFactory != null)
|
if (mDatabase?.iconDrawableFactory != null)
|
||||||
iconView?.assignDatabaseIcon(mDatabase?.drawFactory!!, it.icon, mIconColor)
|
iconView?.assignDatabaseIcon(mDatabase?.iconDrawableFactory!!, it.icon, mIconColor)
|
||||||
|
|
||||||
if (toolbar != null) {
|
if (toolbar != null) {
|
||||||
if (mCurrentGroup?.containsParent() == true)
|
if (mCurrentGroup?.containsParent() == true)
|
||||||
|
|||||||
@@ -205,8 +205,8 @@ class GroupEditDialogFragment : DialogFragment(), IconPickerDialogFragment.IconP
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun assignIconView() {
|
private fun assignIconView() {
|
||||||
if (mDatabase?.drawFactory != null) {
|
if (mDatabase?.iconDrawableFactory != null) {
|
||||||
iconButtonView.assignDatabaseIcon(mDatabase?.drawFactory!!, mGroupInfo.icon, iconColor)
|
iconButtonView.assignDatabaseIcon(mDatabase?.iconDrawableFactory!!, mGroupInfo.icon, iconColor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,15 +24,13 @@ import android.os.Bundle
|
|||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.fragment.app.*
|
import androidx.fragment.app.DialogFragment
|
||||||
|
import androidx.fragment.app.FragmentActivity
|
||||||
import androidx.viewpager.widget.ViewPager
|
import androidx.viewpager.widget.ViewPager
|
||||||
import com.google.android.material.tabs.TabLayout
|
import com.google.android.material.tabs.TabLayout
|
||||||
import com.kunzisoft.keepass.R
|
import com.kunzisoft.keepass.R
|
||||||
import com.kunzisoft.keepass.activities.fragments.IconCustomFragment
|
import com.kunzisoft.keepass.adapters.IconPickerPagerAdapter
|
||||||
import com.kunzisoft.keepass.activities.fragments.IconStandardFragment
|
|
||||||
import com.kunzisoft.keepass.database.element.icon.IconImage
|
import com.kunzisoft.keepass.database.element.icon.IconImage
|
||||||
import com.kunzisoft.keepass.database.element.icon.IconImageCustom
|
|
||||||
import com.kunzisoft.keepass.database.element.icon.IconImageStandard
|
|
||||||
|
|
||||||
|
|
||||||
class IconPickerDialogFragment : DialogFragment() {
|
class IconPickerDialogFragment : DialogFragment() {
|
||||||
@@ -45,7 +43,12 @@ class IconPickerDialogFragment : DialogFragment() {
|
|||||||
override fun onAttach(context: Context) {
|
override fun onAttach(context: Context) {
|
||||||
super.onAttach(context)
|
super.onAttach(context)
|
||||||
try {
|
try {
|
||||||
iconPickerListener = context as IconPickerListener
|
iconPickerListener = object : IconPickerListener {
|
||||||
|
override fun iconPicked(icon: IconImage) {
|
||||||
|
(context as IconPickerListener).iconPicked(icon)
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
}
|
||||||
} catch (e: ClassCastException) {
|
} catch (e: ClassCastException) {
|
||||||
// The activity doesn't implement the interface, throw exception
|
// The activity doesn't implement the interface, throw exception
|
||||||
throw ClassCastException(context.toString()
|
throw ClassCastException(context.toString()
|
||||||
@@ -82,50 +85,14 @@ class IconPickerDialogFragment : DialogFragment() {
|
|||||||
val root = layoutInflater.inflate(R.layout.fragment_icon_picker, container)
|
val root = layoutInflater.inflate(R.layout.fragment_icon_picker, container)
|
||||||
viewPager = root.findViewById(R.id.icon_picker_pager)
|
viewPager = root.findViewById(R.id.icon_picker_pager)
|
||||||
tabLayout = root.findViewById(R.id.icon_picker_tabs)
|
tabLayout = root.findViewById(R.id.icon_picker_tabs)
|
||||||
iconPickerPagerAdapter = IconPickerPagerAdapter(childFragmentManager, { icon ->
|
iconPickerPagerAdapter = IconPickerPagerAdapter(childFragmentManager)
|
||||||
iconPickerListener?.iconPicked(IconImage(icon))
|
iconPickerPagerAdapter.iconSelected = iconPickerListener
|
||||||
dismiss()
|
|
||||||
}, { icon ->
|
|
||||||
iconPickerListener?.iconPicked(IconImage(icon))
|
|
||||||
dismiss()
|
|
||||||
}
|
|
||||||
)
|
|
||||||
viewPager.adapter = iconPickerPagerAdapter
|
viewPager.adapter = iconPickerPagerAdapter
|
||||||
tabLayout.setupWithViewPager(viewPager)
|
tabLayout.setupWithViewPager(viewPager)
|
||||||
|
|
||||||
return root
|
return root
|
||||||
}
|
}
|
||||||
|
|
||||||
class IconPickerPagerAdapter(fragmentManager: FragmentManager,
|
|
||||||
iconStandardSelected: (icon: IconImageStandard) -> Unit,
|
|
||||||
iconCustomSelected: (icon: IconImageCustom) -> Unit)
|
|
||||||
: FragmentStatePagerAdapter(fragmentManager, BEHAVIOR_SET_USER_VISIBLE_HINT) {
|
|
||||||
|
|
||||||
private val iconStandardFragment = IconStandardFragment()
|
|
||||||
private val iconCustomFragment = IconCustomFragment()
|
|
||||||
|
|
||||||
init {
|
|
||||||
iconStandardFragment.iconStandardPickerListener = iconStandardSelected
|
|
||||||
iconCustomFragment.iconCustomPickerListener = iconCustomSelected
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getCount(): Int = 2
|
|
||||||
|
|
||||||
override fun getItem(i: Int): Fragment {
|
|
||||||
return when (i) {
|
|
||||||
1 -> iconCustomFragment
|
|
||||||
else -> iconStandardFragment
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getPageTitle(position: Int): CharSequence {
|
|
||||||
return when (position) {
|
|
||||||
1 -> "Custom" //context.getString(R.string.iconStandard)
|
|
||||||
else -> "Standard" //context.getString(R.string.iconStandard)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
interface IconPickerListener {
|
interface IconPickerListener {
|
||||||
fun iconPicked(icon: IconImage)
|
fun iconPicked(icon: IconImage)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,98 +1,20 @@
|
|||||||
package com.kunzisoft.keepass.activities.fragments
|
package com.kunzisoft.keepass.activities.fragments
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.view.LayoutInflater
|
|
||||||
import android.view.View
|
|
||||||
import android.view.ViewGroup
|
|
||||||
import android.widget.BaseAdapter
|
|
||||||
import android.widget.GridView
|
|
||||||
import android.widget.ImageView
|
|
||||||
import androidx.fragment.app.Fragment
|
|
||||||
import com.kunzisoft.keepass.R
|
import com.kunzisoft.keepass.R
|
||||||
import com.kunzisoft.keepass.database.element.Database
|
import com.kunzisoft.keepass.database.element.Database
|
||||||
import com.kunzisoft.keepass.database.element.icon.IconImage
|
import com.kunzisoft.keepass.database.element.icon.IconImage
|
||||||
import com.kunzisoft.keepass.database.element.icon.IconImageCustom
|
|
||||||
import com.kunzisoft.keepass.database.element.icon.IconPool
|
|
||||||
import com.kunzisoft.keepass.icons.IconDrawableFactory
|
|
||||||
import com.kunzisoft.keepass.icons.assignDatabaseIcon
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Content fragments
|
* Content fragments
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class IconCustomFragment : Fragment() {
|
class IconCustomFragment : IconFragment() {
|
||||||
|
|
||||||
private lateinit var currIconGridView: GridView
|
override fun retrieveMainLayoutId(): Int {
|
||||||
private var iconPool: IconPool? = null
|
return R.layout.fragment_icon_custom_picker
|
||||||
private var iconDrawableFactory: IconDrawableFactory? = null
|
|
||||||
var iconCustomPickerListener: ((icon: IconImageCustom) -> Unit)? = null
|
|
||||||
|
|
||||||
override fun onDetach() {
|
|
||||||
iconCustomPickerListener = null
|
|
||||||
super.onDetach()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateView(inflater: LayoutInflater,
|
override fun defineIconList(database: Database): List<IconImage> {
|
||||||
container: ViewGroup?,
|
return database.iconPool.getCustomIconList()
|
||||||
savedInstanceState: Bundle?): View {
|
|
||||||
val root = inflater.inflate(R.layout.fragment_icon_standard_picker, container, false)
|
|
||||||
currIconGridView = root.findViewById(R.id.IconGridView)
|
|
||||||
return root
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
|
||||||
super.onActivityCreated(savedInstanceState)
|
|
||||||
|
|
||||||
|
|
||||||
val database = Database.getInstance()
|
|
||||||
iconPool = database.iconPool
|
|
||||||
iconDrawableFactory = database.drawFactory
|
|
||||||
|
|
||||||
currIconGridView.adapter = IconCustomAdapter(requireActivity()).apply {
|
|
||||||
iconPool?.doForEachCustomIcon {
|
|
||||||
putIcon(it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inner class IconCustomAdapter(private val context: Context) : BaseAdapter() {
|
|
||||||
|
|
||||||
private val customIconList = ArrayList<IconImageCustom>()
|
|
||||||
|
|
||||||
fun putIcon(icon: IconImageCustom) {
|
|
||||||
customIconList.add(icon)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getCount(): Int {
|
|
||||||
return customIconList.size
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getItem(position: Int): Any {
|
|
||||||
return customIconList[position]
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getItemId(position: Int): Long {
|
|
||||||
return customIconList[position].uuid.leastSignificantBits
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
|
|
||||||
val currentView: View = convertView
|
|
||||||
?: (context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater)
|
|
||||||
.inflate(R.layout.item_icon, parent, false)
|
|
||||||
|
|
||||||
val iconImage = IconImage(customIconList[position])
|
|
||||||
|
|
||||||
iconDrawableFactory?.let {
|
|
||||||
val iconImageView = currentView.findViewById<ImageView>(R.id.icon_image)
|
|
||||||
iconImageView.assignDatabaseIcon(it, iconImage)
|
|
||||||
}
|
|
||||||
|
|
||||||
currentView.setOnClickListener {
|
|
||||||
iconCustomPickerListener?.invoke(iconImage.custom)
|
|
||||||
}
|
|
||||||
|
|
||||||
return currentView
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
package com.kunzisoft.keepass.activities.fragments
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.graphics.Color
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import com.kunzisoft.keepass.R
|
||||||
|
import com.kunzisoft.keepass.activities.dialogs.IconPickerDialogFragment
|
||||||
|
import com.kunzisoft.keepass.adapters.IconAdapter
|
||||||
|
import com.kunzisoft.keepass.database.element.Database
|
||||||
|
import com.kunzisoft.keepass.database.element.icon.IconImage
|
||||||
|
|
||||||
|
abstract class IconFragment : Fragment() {
|
||||||
|
|
||||||
|
private lateinit var iconsGridView: RecyclerView
|
||||||
|
private lateinit var iconAdapter: IconAdapter
|
||||||
|
var iconListener: IconPickerDialogFragment.IconPickerListener? = null
|
||||||
|
|
||||||
|
abstract fun retrieveMainLayoutId(): Int
|
||||||
|
|
||||||
|
abstract fun defineIconList(database: Database): List<IconImage>
|
||||||
|
|
||||||
|
override fun onAttach(context: Context) {
|
||||||
|
super.onAttach(context)
|
||||||
|
|
||||||
|
val database = Database.getInstance()
|
||||||
|
|
||||||
|
iconAdapter = IconAdapter(requireActivity()).apply {
|
||||||
|
iconDrawableFactory = database.iconDrawableFactory
|
||||||
|
setList(defineIconList(database))
|
||||||
|
}
|
||||||
|
iconAdapter.iconPickerListener = iconListener
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDetach() {
|
||||||
|
iconAdapter.iconPickerListener = null
|
||||||
|
super.onDetach()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateView(inflater: LayoutInflater,
|
||||||
|
container: ViewGroup?,
|
||||||
|
savedInstanceState: Bundle?): View {
|
||||||
|
val root = inflater.inflate(retrieveMainLayoutId(), container, false)
|
||||||
|
iconsGridView = root.findViewById(R.id.icons_grid_view)
|
||||||
|
iconsGridView.adapter = iconAdapter
|
||||||
|
return root
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,89 +1,20 @@
|
|||||||
package com.kunzisoft.keepass.activities.fragments
|
package com.kunzisoft.keepass.activities.fragments
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.content.res.ColorStateList
|
|
||||||
import android.graphics.Color
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.view.LayoutInflater
|
|
||||||
import android.view.View
|
|
||||||
import android.view.ViewGroup
|
|
||||||
import android.widget.BaseAdapter
|
|
||||||
import android.widget.GridView
|
|
||||||
import android.widget.ImageView
|
|
||||||
import androidx.core.widget.ImageViewCompat
|
|
||||||
import androidx.fragment.app.Fragment
|
|
||||||
import com.kunzisoft.keepass.R
|
import com.kunzisoft.keepass.R
|
||||||
import com.kunzisoft.keepass.database.element.icon.IconImageStandard
|
import com.kunzisoft.keepass.database.element.Database
|
||||||
import com.kunzisoft.keepass.icons.IconPack
|
import com.kunzisoft.keepass.database.element.icon.IconImage
|
||||||
import com.kunzisoft.keepass.icons.IconPackChooser
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Content fragments
|
* Content fragments
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class IconStandardFragment : Fragment() {
|
class IconStandardFragment : IconFragment() {
|
||||||
|
|
||||||
private lateinit var currIconGridView: GridView
|
override fun retrieveMainLayoutId(): Int {
|
||||||
private var iconPack: IconPack? = null
|
return R.layout.fragment_icon_standard_picker
|
||||||
var iconStandardPickerListener: ((icon: IconImageStandard) -> Unit)? = null
|
|
||||||
|
|
||||||
override fun onDetach() {
|
|
||||||
iconStandardPickerListener = null
|
|
||||||
super.onDetach()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateView(inflater: LayoutInflater,
|
override fun defineIconList(database: Database): List<IconImage> {
|
||||||
container: ViewGroup?,
|
return database.iconPool.getStandardIconList()
|
||||||
savedInstanceState: Bundle?): View {
|
|
||||||
val root = inflater.inflate(R.layout.fragment_icon_standard_picker, container, false)
|
|
||||||
currIconGridView = root.findViewById(R.id.IconGridView)
|
|
||||||
return root
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
|
||||||
super.onActivityCreated(savedInstanceState)
|
|
||||||
|
|
||||||
iconPack = IconPackChooser.getSelectedIconPack(requireContext())
|
|
||||||
currIconGridView.adapter = IconStandardAdapter(requireActivity())
|
|
||||||
}
|
|
||||||
|
|
||||||
inner class IconStandardAdapter(private val context: Context) : BaseAdapter() {
|
|
||||||
|
|
||||||
override fun getCount(): Int {
|
|
||||||
return iconPack?.numberOfIcons() ?: 0
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getItem(position: Int): Any? {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getItemId(position: Int): Long {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
|
|
||||||
val currentView: View = convertView
|
|
||||||
?: (context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater)
|
|
||||||
.inflate(R.layout.item_icon, parent, false)
|
|
||||||
|
|
||||||
iconPack?.let { iconPack ->
|
|
||||||
val iconImageView = currentView.findViewById<ImageView>(R.id.icon_image)
|
|
||||||
iconImageView.setImageResource(iconPack.iconToResId(position))
|
|
||||||
|
|
||||||
// Assign color if icons are tintable
|
|
||||||
if (iconPack.tintable()) {
|
|
||||||
// Retrieve the textColor to tint the icon
|
|
||||||
val ta = context.theme.obtainStyledAttributes(intArrayOf(android.R.attr.textColor))
|
|
||||||
ImageViewCompat.setImageTintList(iconImageView, ColorStateList.valueOf(ta.getColor(0, Color.BLACK)))
|
|
||||||
ta.recycle()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
currentView.setOnClickListener {
|
|
||||||
iconStandardPickerListener?.invoke(IconImageStandard(position))
|
|
||||||
}
|
|
||||||
|
|
||||||
return currentView
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
package com.kunzisoft.keepass.adapters
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.graphics.Color
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.ImageView
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import com.kunzisoft.keepass.R
|
||||||
|
import com.kunzisoft.keepass.activities.dialogs.IconPickerDialogFragment
|
||||||
|
import com.kunzisoft.keepass.database.element.icon.IconImage
|
||||||
|
import com.kunzisoft.keepass.icons.IconDrawableFactory
|
||||||
|
import com.kunzisoft.keepass.icons.assignDatabaseIcon
|
||||||
|
|
||||||
|
class IconAdapter(context: Context) : RecyclerView.Adapter<IconAdapter.CustomIconViewHolder>() {
|
||||||
|
|
||||||
|
private val inflater: LayoutInflater = LayoutInflater.from(context)
|
||||||
|
|
||||||
|
private val iconList = ArrayList<IconImage>()
|
||||||
|
|
||||||
|
var iconDrawableFactory: IconDrawableFactory? = null
|
||||||
|
var iconPickerListener: IconPickerDialogFragment.IconPickerListener? = null
|
||||||
|
|
||||||
|
var tintColor : Int = Color.BLACK
|
||||||
|
|
||||||
|
init {
|
||||||
|
// Retrieve the textColor to tint the icon
|
||||||
|
val ta = context.theme.obtainStyledAttributes(intArrayOf(android.R.attr.textColor))
|
||||||
|
tintColor = ta.getColor(0, Color.BLACK)
|
||||||
|
ta.recycle()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setList(icon: List<IconImage>) {
|
||||||
|
iconList.clear()
|
||||||
|
iconList.addAll(icon)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CustomIconViewHolder {
|
||||||
|
val view = inflater.inflate(R.layout.item_icon, parent, false)
|
||||||
|
return CustomIconViewHolder(view)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBindViewHolder(holder: CustomIconViewHolder, position: Int) {
|
||||||
|
val icon = iconList[position]
|
||||||
|
iconDrawableFactory?.let {
|
||||||
|
holder.iconImageView.assignDatabaseIcon(it, icon, tintColor)
|
||||||
|
}
|
||||||
|
holder.itemView.setOnClickListener { iconPickerListener?.iconPicked(icon) }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getItemCount(): Int {
|
||||||
|
return iconList.size
|
||||||
|
}
|
||||||
|
|
||||||
|
inner class CustomIconViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
|
||||||
|
var iconImageView: ImageView = itemView.findViewById(R.id.icon_image)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package com.kunzisoft.keepass.adapters
|
||||||
|
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import androidx.fragment.app.FragmentManager
|
||||||
|
import androidx.fragment.app.FragmentStatePagerAdapter
|
||||||
|
import com.kunzisoft.keepass.activities.dialogs.IconPickerDialogFragment
|
||||||
|
import com.kunzisoft.keepass.activities.fragments.IconCustomFragment
|
||||||
|
import com.kunzisoft.keepass.activities.fragments.IconStandardFragment
|
||||||
|
|
||||||
|
class IconPickerPagerAdapter(fragmentManager: FragmentManager)
|
||||||
|
: FragmentStatePagerAdapter(fragmentManager, BEHAVIOR_SET_USER_VISIBLE_HINT) {
|
||||||
|
|
||||||
|
var iconSelected: IconPickerDialogFragment.IconPickerListener? = null
|
||||||
|
private val iconStandardFragment = IconStandardFragment()
|
||||||
|
private val iconCustomFragment = IconCustomFragment()
|
||||||
|
|
||||||
|
override fun getCount(): Int = 2
|
||||||
|
|
||||||
|
override fun getItem(i: Int): Fragment {
|
||||||
|
return when (i) {
|
||||||
|
1 -> iconCustomFragment
|
||||||
|
else -> iconStandardFragment
|
||||||
|
}.apply {
|
||||||
|
iconListener = iconSelected
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getPageTitle(position: Int): CharSequence {
|
||||||
|
return when (position) {
|
||||||
|
1 -> "Custom" //context.getString(R.string.iconStandard)
|
||||||
|
else -> "Standard" //context.getString(R.string.iconStandard)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -304,7 +304,7 @@ class NodeAdapter (private val context: Context)
|
|||||||
}
|
}
|
||||||
holder.imageIdentifier?.setColorFilter(iconColor)
|
holder.imageIdentifier?.setColorFilter(iconColor)
|
||||||
holder.icon.apply {
|
holder.icon.apply {
|
||||||
assignDatabaseIcon(mDatabase.drawFactory, subNode.icon, iconColor)
|
assignDatabaseIcon(mDatabase.iconDrawableFactory, subNode.icon, iconColor)
|
||||||
// Relative size of the icon
|
// Relative size of the icon
|
||||||
layoutParams?.apply {
|
layoutParams?.apply {
|
||||||
height = (mIconDefaultDimension * mPrefSizeMultiplier).toInt()
|
height = (mIconDefaultDimension * mPrefSizeMultiplier).toInt()
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ class SearchEntryCursorAdapter(private val context: Context,
|
|||||||
|
|
||||||
// Assign image
|
// Assign image
|
||||||
viewHolder.imageViewIcon?.assignDatabaseIcon(
|
viewHolder.imageViewIcon?.assignDatabaseIcon(
|
||||||
database.drawFactory,
|
database.iconDrawableFactory,
|
||||||
currentEntry.icon,
|
currentEntry.icon,
|
||||||
iconColor)
|
iconColor)
|
||||||
|
|
||||||
|
|||||||
@@ -276,7 +276,7 @@ object AutofillHelper {
|
|||||||
if (remoteViewsIcon != null) {
|
if (remoteViewsIcon != null) {
|
||||||
presentation.assignDatabaseIcon(context,
|
presentation.assignDatabaseIcon(context,
|
||||||
R.id.autofill_entry_icon,
|
R.id.autofill_entry_icon,
|
||||||
Database.getInstance().drawFactory,
|
Database.getInstance().iconDrawableFactory,
|
||||||
remoteViewsIcon,
|
remoteViewsIcon,
|
||||||
ContextCompat.getColor(context, R.color.green))
|
ContextCompat.getColor(context, R.color.green))
|
||||||
}
|
}
|
||||||
@@ -285,7 +285,7 @@ object AutofillHelper {
|
|||||||
|
|
||||||
private fun buildIconFromEntry(context: Context, entryInfo: EntryInfo): Icon? {
|
private fun buildIconFromEntry(context: Context, entryInfo: EntryInfo): Icon? {
|
||||||
return createIconFromDatabaseIcon(context,
|
return createIconFromDatabaseIcon(context,
|
||||||
Database.getInstance().drawFactory,
|
Database.getInstance().iconDrawableFactory,
|
||||||
entryInfo.icon,
|
entryInfo.icon,
|
||||||
ContextCompat.getColor(context, R.color.green))
|
ContextCompat.getColor(context, R.color.green))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ class Database {
|
|||||||
|
|
||||||
var isReadOnly = false
|
var isReadOnly = false
|
||||||
|
|
||||||
val drawFactory = IconDrawableFactory()
|
val iconDrawableFactory = IconDrawableFactory()
|
||||||
|
|
||||||
var loaded = false
|
var loaded = false
|
||||||
set(value) {
|
set(value) {
|
||||||
@@ -625,7 +625,7 @@ class Database {
|
|||||||
|
|
||||||
fun clear(filesDirectory: File? = null) {
|
fun clear(filesDirectory: File? = null) {
|
||||||
iconPool.clearCache()
|
iconPool.clearCache()
|
||||||
drawFactory.clearCache()
|
iconDrawableFactory.clearCache()
|
||||||
// Delete the cache of the database if present
|
// Delete the cache of the database if present
|
||||||
mDatabaseKDB?.clearCache()
|
mDatabaseKDB?.clearCache()
|
||||||
mDatabaseKDBX?.clearCache()
|
mDatabaseKDBX?.clearCache()
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ package com.kunzisoft.keepass.database.element.icon
|
|||||||
|
|
||||||
import android.os.Parcel
|
import android.os.Parcel
|
||||||
import android.os.Parcelable
|
import android.os.Parcelable
|
||||||
|
import com.kunzisoft.keepass.icons.IconPack.Companion.NB_ICONS
|
||||||
|
|
||||||
class IconImageStandard : Parcelable {
|
class IconImageStandard : Parcelable {
|
||||||
|
|
||||||
@@ -31,7 +32,7 @@ class IconImageStandard : Parcelable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
constructor(iconId: Int) {
|
constructor(iconId: Int) {
|
||||||
if (iconId < MIN_ID || iconId > MAX_ID)
|
if (iconId < 0 || iconId > NB_ICONS)
|
||||||
this.id = KEY_ID
|
this.id = KEY_ID
|
||||||
else
|
else
|
||||||
this.id = iconId
|
this.id = iconId
|
||||||
@@ -72,8 +73,6 @@ class IconImageStandard : Parcelable {
|
|||||||
const val KEY_ID = 0
|
const val KEY_ID = 0
|
||||||
const val TRASH_ID = 43
|
const val TRASH_ID = 43
|
||||||
const val FOLDER_ID = 48
|
const val FOLDER_ID = 48
|
||||||
const val MIN_ID = 0
|
|
||||||
const val MAX_ID = 48
|
|
||||||
|
|
||||||
@JvmField
|
@JvmField
|
||||||
val CREATOR: Parcelable.Creator<IconImageStandard> = object : Parcelable.Creator<IconImageStandard> {
|
val CREATOR: Parcelable.Creator<IconImageStandard> = object : Parcelable.Creator<IconImageStandard> {
|
||||||
|
|||||||
@@ -19,22 +19,31 @@
|
|||||||
*/
|
*/
|
||||||
package com.kunzisoft.keepass.database.element.icon
|
package com.kunzisoft.keepass.database.element.icon
|
||||||
|
|
||||||
|
import com.kunzisoft.keepass.icons.IconPack.Companion.NB_ICONS
|
||||||
|
import java.util.ArrayList
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
|
|
||||||
class IconPool {
|
class IconPool {
|
||||||
|
|
||||||
private val standardCache = HashMap<Int, IconImageStandard?>()
|
private val standardCache = List(NB_ICONS) {
|
||||||
|
IconImageStandard(it)
|
||||||
|
}
|
||||||
private val customCache = HashMap<UUID, IconImageCustom?>()
|
private val customCache = HashMap<UUID, IconImageCustom?>()
|
||||||
|
|
||||||
fun getIcon(iconId: Int): IconImageStandard {
|
fun getIcon(iconId: Int): IconImageStandard {
|
||||||
var icon: IconImageStandard? = standardCache[iconId]
|
return standardCache[iconId]
|
||||||
|
}
|
||||||
|
|
||||||
if (icon == null) {
|
fun getStandardIconList(): List<IconImage> {
|
||||||
icon = IconImageStandard(iconId)
|
return standardCache.mapIndexed { _, iconImageStandard -> IconImage(iconImageStandard) }
|
||||||
standardCache[iconId] = icon
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return icon
|
/*
|
||||||
|
* Custom
|
||||||
|
*/
|
||||||
|
|
||||||
|
fun putIcon(icon: IconImageCustom) {
|
||||||
|
customCache[icon.uuid] = icon
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getIcon(iconUuid: UUID): IconImageCustom {
|
fun getIcon(iconUuid: UUID): IconImageCustom {
|
||||||
@@ -48,25 +57,22 @@ class IconPool {
|
|||||||
return icon
|
return icon
|
||||||
}
|
}
|
||||||
|
|
||||||
fun putIcon(icon: IconImageCustom) {
|
|
||||||
customCache[icon.uuid] = icon
|
|
||||||
}
|
|
||||||
|
|
||||||
fun containsCustomIcons(): Boolean {
|
fun containsCustomIcons(): Boolean {
|
||||||
return customCache.isNotEmpty()
|
return customCache.isNotEmpty()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun doForEachCustomIcon(action: (customIcon: IconImageCustom) -> Unit) {
|
fun getCustomIconList(): List<IconImage> {
|
||||||
|
val list = ArrayList<IconImage>(customCache.size)
|
||||||
for ((_, customIcon) in customCache) {
|
for ((_, customIcon) in customCache) {
|
||||||
action.invoke(customIcon!!)
|
list.add(IconImage(customIcon!!))
|
||||||
}
|
}
|
||||||
|
return list
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clear the cache of icons
|
* Clear the cache of icons
|
||||||
*/
|
*/
|
||||||
fun clearCache() {
|
fun clearCache() {
|
||||||
standardCache.clear()
|
|
||||||
customCache.clear()
|
customCache.clear()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -701,11 +701,11 @@ class DatabaseOutputKDBX(private val mDatabaseKDBX: DatabaseKDBX,
|
|||||||
|
|
||||||
xml.startTag(null, DatabaseKDBXXML.ElemCustomIcons)
|
xml.startTag(null, DatabaseKDBXXML.ElemCustomIcons)
|
||||||
|
|
||||||
mDatabaseKDBX.iconPool.doForEachCustomIcon { customIcon ->
|
mDatabaseKDBX.iconPool.getCustomIconList().forEach { icon ->
|
||||||
xml.startTag(null, DatabaseKDBXXML.ElemCustomIconItem)
|
xml.startTag(null, DatabaseKDBXXML.ElemCustomIconItem)
|
||||||
|
|
||||||
writeUuid(DatabaseKDBXXML.ElemCustomIconItemID, customIcon.uuid)
|
writeUuid(DatabaseKDBXXML.ElemCustomIconItemID, icon.custom.uuid)
|
||||||
writeObject(DatabaseKDBXXML.ElemCustomIconItemData, String(Base64.encode(customIcon.imageData, BASE_64_FLAG)))
|
writeObject(DatabaseKDBXXML.ElemCustomIconItemData, String(Base64.encode(icon.custom.imageData, BASE_64_FLAG)))
|
||||||
|
|
||||||
xml.endTag(null, DatabaseKDBXXML.ElemCustomIconItem)
|
xml.endTag(null, DatabaseKDBXXML.ElemCustomIconItem)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -111,21 +111,16 @@ class IconDrawableFactory {
|
|||||||
fun getIconSuperDrawable(context: Context, icon: IconImage, width: Int, tint: Boolean = false, tintColor: Int = Color.WHITE): SuperDrawable {
|
fun getIconSuperDrawable(context: Context, icon: IconImage, width: Int, tint: Boolean = false, tintColor: Int = Color.WHITE): SuperDrawable {
|
||||||
return if (!icon.custom.isUnknown) {
|
return if (!icon.custom.isUnknown) {
|
||||||
SuperDrawable(getIconDrawable(context.resources, icon.custom))
|
SuperDrawable(getIconDrawable(context.resources, icon.custom))
|
||||||
} else IconPackChooser.getSelectedIconPack(context)?.iconToResId(icon.standard.id)?.let { resId ->
|
} else {
|
||||||
getIconSuperDrawable(context, resId, width, tint, tintColor)
|
val iconPack = IconPackChooser.getSelectedIconPack(context)
|
||||||
} ?: run {
|
iconPack?.iconToResId(icon.standard.id)?.let { iconId ->
|
||||||
SuperDrawable(PatternIcon(context.resources).blankDrawable)
|
SuperDrawable(getIconDrawable(context.resources, iconId, width, tint, tintColor), iconPack.tintable())
|
||||||
|
} ?: run {
|
||||||
|
SuperDrawable(PatternIcon(context.resources).blankDrawable)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the [SuperDrawable] IconImageStandard from [iconId] (cache, or build it and add it to the cache if not exists yet)
|
|
||||||
* , then [tint] it with [tintColor] if needed
|
|
||||||
*/
|
|
||||||
fun getIconSuperDrawable(context: Context, iconId: Int, width: Int, tint: Boolean, tintColor: Int): SuperDrawable {
|
|
||||||
return SuperDrawable(getIconDrawable(context.resources, iconId, width, tint, tintColor), true)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Key class to retrieve a Drawable in the cache if it's tinted or not
|
* Key class to retrieve a Drawable in the cache if it's tinted or not
|
||||||
*/
|
*/
|
||||||
@@ -258,28 +253,6 @@ class IconDrawableFactory {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Assign a default database icon to an ImageView and tint it with [tintColor] if needed
|
|
||||||
*/
|
|
||||||
fun ImageView.assignDefaultDatabaseIcon(iconFactory: IconDrawableFactory,
|
|
||||||
tintColor: Int = Color.WHITE) {
|
|
||||||
try {
|
|
||||||
IconPackChooser.getSelectedIconPack(context)?.let { selectedIconPack ->
|
|
||||||
iconFactory.assignDrawableToImageView(
|
|
||||||
iconFactory.getIconSuperDrawable(context,
|
|
||||||
selectedIconPack.defaultIconId,
|
|
||||||
width,
|
|
||||||
selectedIconPack.tintable(),
|
|
||||||
tintColor),
|
|
||||||
this,
|
|
||||||
selectedIconPack.tintable(),
|
|
||||||
tintColor)
|
|
||||||
}
|
|
||||||
} catch (e: Exception) {
|
|
||||||
Log.e(ImageView::class.java.name, "Unable to assign icon in image view", e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Assign a database [icon] to an ImageView and tint it with [tintColor] if needed
|
* Assign a database [icon] to an ImageView and tint it with [tintColor] if needed
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -134,7 +134,6 @@ class IconPack(packageName: String, resources: Resources, resourceId: Int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
const val NB_ICONS = 68
|
||||||
private const val NB_ICONS = 68
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ object IconPackChooser {
|
|||||||
fun setSelectedIconPack(iconPackIdString: String?) {
|
fun setSelectedIconPack(iconPackIdString: String?) {
|
||||||
for (iconPack in iconPackList) {
|
for (iconPack in iconPackList) {
|
||||||
if (iconPack.id == iconPackIdString) {
|
if (iconPack.id == iconPackIdString) {
|
||||||
Database.getInstance().drawFactory.clearCache()
|
Database.getInstance().iconDrawableFactory.clearCache()
|
||||||
iconPackSelected = iconPack
|
iconPackSelected = iconPack
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|||||||
35
app/src/main/res/layout/fragment_icon_custom_picker.xml
Normal file
35
app/src/main/res/layout/fragment_icon_custom_picker.xml
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
Copyright 2021 Jeremy Jamet / Kunzisoft.
|
||||||
|
|
||||||
|
This file is part of KeePassDX.
|
||||||
|
|
||||||
|
KeePassDX is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
KeePassDX is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with KeePassDX. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
-->
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:id="@+id/icons_grid_view"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
|
||||||
|
app:spanCount="2"
|
||||||
|
android:verticalSpacing="32dp"
|
||||||
|
android:paddingTop="20dp"
|
||||||
|
android:gravity="center"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:columnWidth="64dp"
|
||||||
|
android:numColumns="auto_fit"
|
||||||
|
android:stretchMode="spacingWidthUniform">
|
||||||
|
</androidx.recyclerview.widget.RecyclerView>
|
||||||
@@ -17,10 +17,14 @@
|
|||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with KeePassDX. If not, see <http://www.gnu.org/licenses/>.
|
along with KeePassDX. If not, see <http://www.gnu.org/licenses/>.
|
||||||
-->
|
-->
|
||||||
<GridView xmlns:android="http://schemas.android.com/apk/res/android"
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:id="@+id/IconGridView"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:layout_width="wrap_content"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:id="@+id/icons_grid_view"
|
||||||
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
|
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
|
||||||
|
app:spanCount="2"
|
||||||
android:verticalSpacing="32dp"
|
android:verticalSpacing="32dp"
|
||||||
android:paddingTop="20dp"
|
android:paddingTop="20dp"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
@@ -28,4 +32,4 @@
|
|||||||
android:columnWidth="64dp"
|
android:columnWidth="64dp"
|
||||||
android:numColumns="auto_fit"
|
android:numColumns="auto_fit"
|
||||||
android:stretchMode="spacingWidthUniform">
|
android:stretchMode="spacingWidthUniform">
|
||||||
</GridView>
|
</androidx.recyclerview.widget.RecyclerView>
|
||||||
|
|||||||
Reference in New Issue
Block a user