Skip to content
438 changes: 438 additions & 0 deletions app/schemas/org.phenoapps.intercross.data.IntercrossDatabase/3.json

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -680,7 +680,8 @@ class MainActivity : AppCompatActivity(), SearchPreferenceResultListener {
}

doubleBackToExitPressedOnce = true
Toast.makeText(this@MainActivity, "Press back again to exit", Toast.LENGTH_SHORT).show()
Toast.makeText(this@MainActivity,
getString(R.string.press_back_again_to_exit), Toast.LENGTH_SHORT).show()

Handler(Looper.getMainLooper()).postDelayed(
{ doubleBackToExitPressedOnce = false },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,14 @@ fun bindCrossTypeImage(view: ImageView, event: Event?) {

@BindingAdapter("setQRCode")
fun bindQRCodeImage(view: ImageView, code: String?) {

code?.let {

view.tag = code

AsyncLoadBarcode(view, code).execute(code)
if (code.isNullOrBlank()) {
view.tag = null
view.setImageDrawable(null)
return
}

view.tag = code
AsyncLoadBarcode(view, code).execute(code)
}

@BindingAdapter("layoutMarginStart")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.phenoapps.intercross.adapters

import android.content.Context
import android.view.GestureDetector
import android.view.LayoutInflater
import android.view.MotionEvent
import android.view.View
Expand Down Expand Up @@ -45,22 +46,34 @@ class CrossTrackerAdapter(

init {
val crossCardView: CardView = view.findViewById(R.id.cross_card)
var isLongPress = false

val gestureDetector = GestureDetector(view.context, object : GestureDetector.SimpleOnGestureListener() {
override fun onSingleTapConfirmed(e: MotionEvent): Boolean {
view.performClick()
handleClick(layoutPosition)
return true
}

override fun onLongPress(e: MotionEvent) {
handleLongClick(layoutPosition)
}
})

// intercept touch events to prevent person, date and wishlist progress chip ripple
crossCardView.setOnTouchListener{ _, event ->
if (event.action == MotionEvent.ACTION_UP) {
if (!isLongPress) {
view.performClick()
handleClick(layoutPosition)
}
isLongPress = false
}
gestureDetector.onTouchEvent(event)
true
}
}
}

private fun handleLongClick(position: Int) {
if (position != RecyclerView.NO_POSITION) {
val item = currentList[position]
crossController.onCrossLongClicked(item.male, item.female, item.maleId, item.femaleId)
}
}

private fun handleClick(position: Int) {
if (position != RecyclerView.NO_POSITION) {
when (val item = currentList[position]) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
package org.phenoapps.intercross.adapters

import android.graphics.Color
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.content.res.AppCompatResources
import androidx.databinding.DataBindingUtil
import androidx.core.view.isVisible
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import androidx.sqlite.throwSQLiteException
import org.phenoapps.intercross.R
import org.phenoapps.intercross.data.models.BaseParent
import org.phenoapps.intercross.data.models.Parent
Expand All @@ -15,7 +18,8 @@ import org.phenoapps.intercross.data.viewmodels.PollenGroupListViewModel
import org.phenoapps.intercross.databinding.ListItemSelectableParentRowBinding

class ParentsAdapter(private val listModel: ParentsListViewModel,
private val groupModel: PollenGroupListViewModel)
private val groupModel: PollenGroupListViewModel,
private val crossCountProvider: (BaseParent) -> Int = { 0 })
: ListAdapter<BaseParent, ParentsAdapter.ViewHolder>(BaseParent.Companion.DiffCallback()) {

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
Expand Down Expand Up @@ -46,25 +50,43 @@ class ParentsAdapter(private val listModel: ParentsListViewModel,
fun bind(p: BaseParent) {

with(binding) {
val context = root.context
val isPollenGroup = p is PollenGroup
val crossCount = crossCountProvider(p)
val isSelected = when (p) {
is Parent -> p.selected
is PollenGroup -> p.selected
else -> false
}

if (p is Parent) {

name = p.name
name = when (p) {
is Parent -> p.name
is PollenGroup -> p.name
else -> ""
}

checked = p.selected
code = when (p) {
is Parent -> p.codeId
is PollenGroup -> p.codeId
else -> null
}

} else if (p is PollenGroup) {
checked = isSelected

this.textField.setBackgroundColor(Color.parseColor("#42FF5722"))
doneCheckBox.isChecked = isSelected
pollenGroupChip.isVisible = isPollenGroup
pollenGroupChip.text = context.getString(R.string.parent_pollen_group_chip)
crossCountChip.text = crossCount.toString()

name = p.name
crossCountChip.visibility = if (crossCount > 0) View.VISIBLE else View.GONE

checked = p.selected
parentTypeChip.chipIcon = when((p as? Parent)?.sex) {
0 -> AppCompatResources.getDrawable(context, R.drawable.ic_female_black_24dp)
else -> AppCompatResources.getDrawable(context, R.drawable.ic_male_black_24dp)
}

linearLayout.setOnClickListener {

doneCheckBox.isChecked=!doneCheckBox.isChecked
parentCard.setOnClickListener {
doneCheckBox.isChecked = !doneCheckBox.isChecked

if (p is Parent) {

Expand All @@ -82,6 +104,8 @@ class ParentsAdapter(private val listModel: ParentsListViewModel,
})
}
}

executePendingBindings()
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
package org.phenoapps.intercross.adapters

import android.graphics.Color
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.databinding.DataBindingUtil
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.card.MaterialCardView
import org.phenoapps.intercross.R
import org.phenoapps.intercross.databinding.SimpleListItemBinding
import org.phenoapps.intercross.interfaces.OnSimpleItemClicked
Expand Down Expand Up @@ -46,9 +46,6 @@ class SimpleListAdapter(private val listener: OnSimpleItemClicked)

with(holder) {

if (mSelectedPosition == position) itemView.setBackgroundColor(Color.parseColor("#6000ee00"))
else itemView.setBackgroundResource(R.drawable.text_cell)

holder.itemView.setOnLongClickListener {

listener.onItemLongClicked(item)
Expand All @@ -68,17 +65,18 @@ class SimpleListAdapter(private val listener: OnSimpleItemClicked)
this@SimpleListAdapter.listener.onItemClicked(item)
}

bind(item)
bind(item, mSelectedPosition == position)
}
}
}

inner class ViewHolder(private val binding: SimpleListItemBinding)
: RecyclerView.ViewHolder(binding.root) {

fun bind(pair: Pair<String, String>) {
fun bind(pair: Pair<String, String>, isSelected: Boolean) {

binding.name = pair.second
(binding.root as? MaterialCardView)?.isChecked = isSelected
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package org.phenoapps.intercross.adapters

import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.core.widget.doAfterTextChanged
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import org.phenoapps.intercross.R
import org.phenoapps.intercross.databinding.ListItemWishValueBinding

data class WishValueItem(
val type: String,
var min: Int? = null,
var max: Int? = null
)

class WishValueAdapter : ListAdapter<WishValueItem, WishValueAdapter.ViewHolder>(
object : DiffUtil.ItemCallback<WishValueItem>() {
override fun areItemsTheSame(old: WishValueItem, new: WishValueItem) = old.type == new.type
override fun areContentsTheSame(old: WishValueItem, new: WishValueItem) = old == new
}
) {

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return ViewHolder(
ListItemWishValueBinding.inflate(
LayoutInflater.from(parent.context),
parent,
false
)
)
}

override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.bind(getItem(position))
}

inner class ViewHolder(private val binding: ListItemWishValueBinding) :
RecyclerView.ViewHolder(binding.root) {

private var currentItem: WishValueItem? = null
private var isBinding = false

init {
binding.wishValueMinEt.doAfterTextChanged {
if (!isBinding) {
currentItem?.min = it?.toString()?.toIntOrNull()
validate(currentItem)
}
}
binding.wishValueMaxEt.doAfterTextChanged {
if (!isBinding) {
currentItem?.max = it?.toString()?.toIntOrNull()
validate(currentItem)
}
}
}

fun bind(item: WishValueItem) {
isBinding = true
currentItem = item
binding.name = item.type
binding.wishValueMinEt.setText(item.min?.toString() ?: "")
binding.wishValueMaxEt.setText(item.max?.toString() ?: "")
validate(item)
isBinding = false
}

private fun validate(item: WishValueItem?) {
item ?: return
val min = item.min
val max = item.max

if (min != null && min <= 0) {
binding.wishValueMinTil.error = binding.root.context.getString(R.string.frag_wf_values_min_must_not_be_null)
} else {
binding.wishValueMinTil.error = null
}

if (max != null && min != null && max < min) {
binding.wishValueMaxTil.error = binding.root.context.getString(R.string.frag_wf_values_max_must_not_be_null)
} else {
binding.wishValueMaxTil.error = null
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
import androidx.room.TypeConverters
import androidx.room.migration.Migration
import androidx.sqlite.db.SupportSQLiteDatabase
import org.phenoapps.intercross.data.dao.*
import org.phenoapps.intercross.data.migrations.MigrationV2MetaData
import org.phenoapps.intercross.data.migrations.MigrationV3WishlistView
import org.phenoapps.intercross.data.migrations.MigrationV4UniqueWishType
import org.phenoapps.intercross.data.models.*
import kotlin.jvm.java

@Database(entities = [Event::class, Parent::class,
Wishlist::class, Settings::class, PollenGroup::class,
Expand Down Expand Up @@ -46,6 +46,7 @@ abstract class IntercrossDatabase : RoomDatabase() {
return Room.databaseBuilder(ctx, IntercrossDatabase::class.java, DATABASE_NAME)
.addMigrations(MigrationV2MetaData()) //v1 -> v2 migration added JSON based metadata
.addMigrations(MigrationV3WishlistView()) // v2 -> v3 migration for WishlistView
.addMigrations(MigrationV4UniqueWishType()) // v3 -> v4 migration for unique wishlist type
.setJournalMode(JournalMode.TRUNCATE) //truncate mode makes it easier to export/import database w/o having to manage WAL files.
.build()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ class WishlistRepository private constructor(

fun getAll() = wishlistDao.getAll()

fun getByParents(femaleId: String, maleId: String) = wishlistDao.getByParents(femaleId, maleId)

fun getWishes() = wishlistDao.getWishes()

fun getAllCounts() = wishlistDao.getAllCounts()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package org.phenoapps.intercross.data.dao

import androidx.lifecycle.LiveData
import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import androidx.room.Transaction
import org.phenoapps.intercross.data.models.Wishlist
Expand All @@ -13,6 +15,9 @@ interface WishlistDao : BaseDao<Wishlist> {
@Query("SELECT * FROM wishlist ORDER BY wishlist.wishMin DESC")
fun getAll(): LiveData<List<Wishlist>>

@Query("SELECT * FROM wishlist WHERE femaleDbId = :femaleId AND maleDbId = :maleId")
fun getByParents(femaleId: String, maleId: String): LiveData<List<Wishlist>>

@Query("SELECT * FROM wishlistView ORDER BY wishlistView.wishProgress DESC")
fun getAllCounts(): LiveData<List<WishlistView>>

Expand Down Expand Up @@ -52,4 +57,7 @@ interface WishlistDao : BaseDao<Wishlist> {
@Transaction
@Query("DELETE FROM wishlist")
fun drop()

@Insert(onConflict = OnConflictStrategy.REPLACE)
override fun insert(vararg items: Wishlist)
}
Loading