Skip to content

Commit

Permalink
Merge pull request #78 from PhenoApps/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
trife authored Sep 27, 2021
2 parents d49027b + 355307b commit 0d7fc81
Show file tree
Hide file tree
Showing 54 changed files with 1,349 additions and 327 deletions.
17 changes: 9 additions & 8 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,13 @@ android {
signingConfigs {
playStoreConfig {
Properties keystoreProps = new Properties()
keystoreProps.load(new FileInputStream(file('keystore.config')))

keyAlias keystoreProps['keyAlias']
keyPassword keystoreProps['keyPassword']
storePassword keystoreProps['storePassword']
storeFile file('prospector.keystore.jks')
if (file('keystore.config').exists()) {
keystoreProps.load(new FileInputStream(file('keystore.config')))
keyAlias keystoreProps['keyAlias']
keyPassword keystoreProps['keyPassword']
storePassword keystoreProps['storePassword']
storeFile file('prospector.keystore.jks')
}
}
}

Expand All @@ -27,8 +28,8 @@ android {
//link square api has minimum requirement of 21
minSdkVersion 21
targetSdkVersion 30
versionCode 4
versionName "1.0.1"
versionCode 5
versionName "1.1"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
multiDexEnabled true

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope by MainScope() {
mSnackbar.push(
SnackbarQueue
.SnackJob(
mBinding.root,
mBinding.actMainCoordinatorLayout,
if (mConnected) getString(R.string.connected)
else getString(R.string.disconnect)
)
Expand All @@ -142,6 +142,20 @@ class MainActivity : AppCompatActivity(), CoroutineScope by MainScope() {
Timer().scheduleAtFixedRate(check, 0, 1500)
}

/**
* Displays a snack bar message.
*/
fun notify(message: String) {

mSnackbar.push(
SnackbarQueue
.SnackJob(
mBinding.actMainCoordinatorLayout,
message
)
)
}

private fun startLoadSampleData() {

lifecycleScope.launch {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import org.phenoapps.prospector.R
import org.phenoapps.prospector.callbacks.DiffCallbacks
import org.phenoapps.prospector.databinding.ListItemExperimentBinding
import org.phenoapps.prospector.fragments.ExperimentListFragmentDirections
import org.phenoapps.prospector.utils.DateUtil

/**
* The adapter class used in the experiment list fragment recycler view.
Expand Down Expand Up @@ -64,6 +65,8 @@ class ExperimentAdapter(

this.experiment = experiment

this.date = DateUtil().displayTime(experiment.date)

//count query uses a left join, so a single sample is still counted even if no samples exist for that experiment.
this.sampleCount = if (experiment.count == 1 && experiment.sampleName?.isBlank() != false) {
context.resources
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,15 @@ import org.phenoapps.prospector.R
import org.phenoapps.prospector.callbacks.DiffCallbacks
import org.phenoapps.prospector.data.models.SampleScanCount
import org.phenoapps.prospector.databinding.ListItemSampleBinding
import org.phenoapps.prospector.fragments.SampleListFragment
import org.phenoapps.prospector.fragments.SampleListFragmentDirections
import org.phenoapps.prospector.interfaces.SampleListClickListener
import org.phenoapps.prospector.utils.DateUtil

class SampleAdapter(
private val context: Context
) : ListAdapter<SampleScanCount, SampleAdapter.ViewHolder>(DiffCallbacks.Companion.SampleScanCountDiffCallback()) {
private val context: Context,
private val listener: SampleListClickListener
) : ListAdapter<SampleListFragment.IndexedSampleScanCount, SampleAdapter.ViewHolder>(DiffCallbacks.Companion.SampleScanCountDiffCallback()) {

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return ViewHolder(
Expand All @@ -35,28 +39,39 @@ class SampleAdapter(

itemView.tag = sample.name

if (sample.count == -1) itemView.visibility = View.INVISIBLE
else itemView.visibility = View.VISIBLE

itemView.setOnLongClickListener {
listener.onListItemLongClicked(sample)
true
}

bind(sample, position)
}
}
}

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

fun bind(sample: SampleScanCount, listPosition: Int) {
fun bind(sample: SampleListFragment.IndexedSampleScanCount, listPosition: Int) {

with(binding) {

position = listPosition + 1
position = sample.index + 1

clickListener = View.OnClickListener {

Navigation.findNavController(binding.root).navigate(
if (sample.count >= 0) Navigation.findNavController(binding.root).navigate(
SampleListFragmentDirections.actionToScanList(sample.eid, sample.name))

}

this.scanCount = context.resources
.getQuantityString(R.plurals.numberOfScans, sample.count, sample.count)
this.scanCount = if (sample.count >= 0)
context.resources.getQuantityString(R.plurals.numberOfScans, sample.count, sample.count)
else ""

this.date = DateUtil().displayTime(sample.date)

this.sample = sample

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import org.phenoapps.prospector.callbacks.DiffCallbacks
import org.phenoapps.prospector.data.models.Scan
import org.phenoapps.prospector.databinding.ListItemScanBinding
import org.phenoapps.prospector.interfaces.GraphItemClickListener
import org.phenoapps.prospector.utils.DateUtil
import org.phenoapps.prospector.utils.Dialogs

class ScansAdapter(val context: Context, private val listener: GraphItemClickListener) : ListAdapter<Scan,
Expand Down Expand Up @@ -85,6 +86,7 @@ class ScansAdapter(val context: Context, private val listener: GraphItemClickLis

this.scan = scan
//
this.date = DateUtil().displayScanTime(scan.date)
// this.deviceType = when(scan.deviceType) {
// "0" -> "LinkSquare 1"
// else -> "Unknown"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import androidx.recyclerview.widget.DiffUtil
import org.phenoapps.prospector.adapter.ExperimentAdapter
import org.phenoapps.prospector.data.models.SampleScanCount
import org.phenoapps.prospector.data.models.Scan
import org.phenoapps.prospector.fragments.SampleListFragment

/**
* DiffCallbacks are used in each adapter implementation.
Expand All @@ -25,13 +26,13 @@ class DiffCallbacks {
}
}

class SampleScanCountDiffCallback : DiffUtil.ItemCallback<SampleScanCount>() {
class SampleScanCountDiffCallback : DiffUtil.ItemCallback<SampleListFragment.IndexedSampleScanCount>() {

override fun areItemsTheSame(oldItem: SampleScanCount, newItem: SampleScanCount): Boolean {
return oldItem.name == newItem.name
override fun areItemsTheSame(oldItem: SampleListFragment.IndexedSampleScanCount, newItem: SampleListFragment.IndexedSampleScanCount): Boolean {
return oldItem.index == newItem.index
}

override fun areContentsTheSame(oldItem: SampleScanCount, newItem: SampleScanCount): Boolean {
override fun areContentsTheSame(oldItem: SampleListFragment.IndexedSampleScanCount, newItem: SampleListFragment.IndexedSampleScanCount): Boolean {
return oldItem.name == newItem.name
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,16 @@ package org.phenoapps.prospector.data

import android.content.Context
import android.database.sqlite.SQLiteDatabase
import androidx.room.Database
import androidx.room.DatabaseConfiguration
import androidx.room.Room
import androidx.room.RoomDatabase
import androidx.room.*
import org.phenoapps.prospector.data.dao.ExperimentDao
import org.phenoapps.prospector.data.dao.SampleDao
import org.phenoapps.prospector.data.dao.ScanDao
import org.phenoapps.prospector.data.migrations.MigrationV2
import org.phenoapps.prospector.data.models.*
import java.io.File

@Database(entities = [Experiment::class, Scan::class, SpectralFrame::class, Sample::class],
views = [SampleScanCount::class, DeviceTypeExport::class], version = 1, exportSchema = false)
views = [SampleScanCount::class, DeviceTypeExport::class], version = 2, exportSchema = true)
abstract class ProspectorDatabase : RoomDatabase() {


Expand Down Expand Up @@ -86,7 +84,8 @@ abstract class ProspectorDatabase : RoomDatabase() {
private fun buildDatabase(ctx: Context): ProspectorDatabase {

return Room.databaseBuilder(ctx, ProspectorDatabase::class.java, "PROSPECTOR")
.build()
.addMigrations(MigrationV2())
.build()

}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ package org.phenoapps.prospector.data.dao

import androidx.lifecycle.LiveData
import androidx.room.Dao
import androidx.room.OnConflictStrategy
import androidx.room.Query
import androidx.room.Update
import org.phenoapps.prospector.data.models.DeviceTypeExport
import org.phenoapps.prospector.data.models.Sample
import org.phenoapps.prospector.data.models.SampleScanCount
Expand Down Expand Up @@ -39,4 +41,7 @@ interface SampleDao {
@Query("DELETE FROM samples WHERE eid = :eid and name = :name")
suspend fun deleteSample(eid: Long, name: String)

@Query("UPDATE samples SET name = :name, note = :note WHERE eid = :eid AND name = :oldName")
suspend fun update(eid: Long, oldName: String, name: String, note: String)

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package org.phenoapps.prospector.data.migrations

import android.database.sqlite.SQLiteException
import androidx.room.migration.Migration
import androidx.sqlite.db.SupportSQLiteDatabase

class MigrationV2: Migration(1, 2) {

override fun migrate(database: SupportSQLiteDatabase) {

with (database) {

createNewScansTable()

}
}

//backup technique for deleting columns in SQLite https://www.sqlite.org/faq.html#q11
private fun SupportSQLiteDatabase.createNewScansTable() {

execSQL("CREATE TEMP TABLE scans_backup(eid INT NOT NULL, name TEXT NOT NULL, date TEXT NOT NULL, deviceType TEXT NOT NULL, color TEXT, deviceId TEXT, alias TEXT, operator TEXT, lightSource INT, sid INTEGER PRIMARY KEY AUTOINCREMENT)")

execSQL("INSERT INTO scans_backup SELECT eid, name, date, deviceType, color, deviceId, alias, operator, lightSource, sid FROM scans")

execSQL("DROP TABLE scans")

execSQL("CREATE TABLE scans(eid INT NOT NULL, name TEXT NOT NULL, date TEXT NOT NULL, deviceType TEXT NOT NULL, color TEXT, deviceId TEXT, alias TEXT, operator TEXT, lightSource INT, sid INTEGER PRIMARY KEY AUTOINCREMENT, FOREIGN KEY (eid, name) REFERENCES samples(eid, name) ON UPDATE CASCADE ON DELETE CASCADE)")

execSQL("INSERT INTO scans SELECT eid, name, date, deviceType, color, deviceId, alias, operator, lightSource, sid FROM scans_backup")

execSQL("DROP TABLE scans_backup")

execSQL("CREATE INDEX index_scans_eid ON scans (eid)")

execSQL("CREATE INDEX index_scans_name ON scans (name)")

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ import org.phenoapps.prospector.utils.DateUtil
ForeignKey(
entity = Sample::class,
parentColumns = ["eid", "name"],
childColumns = ["eid", "name"], onDelete = ForeignKey.CASCADE)
childColumns = ["eid", "name"],
onUpdate = ForeignKey.CASCADE,
onDelete = ForeignKey.CASCADE)
])
data class Scan(

Expand All @@ -26,7 +28,7 @@ data class Scan(
var name: String,

@ColumnInfo(name = "date")
var date: String = DateUtil().getScanTime(),
var date: String = DateUtil().getTime(),

@ColumnInfo(name = "deviceType")
var deviceType: String = DEVICE_TYPE_NIR,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.phenoapps.prospector.data.viewmodels

import androidx.lifecycle.LiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
Expand All @@ -15,13 +16,6 @@ class SampleViewModel @Inject constructor(
experimentRepo: ExperimentRepository,
private val repo: SampleRepository): ViewModel() {

//non-live
suspend fun getSamples(eid: Long): List<Sample> = viewModelScope.async {

return@async repo.getSamples(eid)

}.await()

//live data
fun getSamplesLive(eid: Long) = repo.getSamplesLive(eid)
fun getSampleScanCounts(eid: Long) = repo.getSampleScanCounts(eid)
Expand All @@ -30,6 +24,10 @@ class SampleViewModel @Inject constructor(

suspend fun deleteSample(eid: Long, name: String) = repo.deleteSample(eid, name)

suspend fun update(eid: Long, oldName: String, name: String, note: String) = viewModelScope.launch {
repo.update(eid, oldName, name, note)
}

fun insertSampleAsync(sample: Sample) = viewModelScope.async { return@async repo.insertSample(sample) }


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,5 @@ class SampleRepository @Inject constructor(

suspend fun insertSample(sample: Sample) = dao.insertSample(sample.eid, sample.name, sample.date, sample.note)

suspend fun update(eid: Long, oldName: String, name: String, note: String) = dao.update(eid, oldName, name, note)
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.phenoapps.prospector.fragments

import android.Manifest
import android.media.MediaPlayer
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
Expand All @@ -12,13 +13,15 @@ import androidx.databinding.DataBindingUtil
import androidx.fragment.app.Fragment
import androidx.fragment.app.setFragmentResult
import androidx.navigation.fragment.findNavController
import androidx.preference.PreferenceManager
import com.google.zxing.ResultPoint
import com.journeyapps.barcodescanner.BarcodeCallback
import com.journeyapps.barcodescanner.BarcodeResult
import dagger.hilt.android.AndroidEntryPoint
import dagger.hilt.android.WithFragmentBindings
import org.phenoapps.prospector.R
import org.phenoapps.prospector.databinding.FragmentBarcodeScanBinding
import org.phenoapps.prospector.utils.KeyUtil

/**
* A barcode fragment that uses Zebra SDK. Specifically, this fragment returns the first scanned
Expand All @@ -42,6 +45,14 @@ class BarcodeScanFragment : Fragment() {
}
}

private val mPrefs by lazy {
PreferenceManager.getDefaultSharedPreferences(context)
}

private val mKeyUtil by lazy {
KeyUtil(context)
}

private fun setupBarcodeScanner() {

mBinding?.barcodeScanner.apply {
Expand All @@ -67,6 +78,10 @@ class BarcodeScanFragment : Fragment() {

if (result.text == null) return // || result.text == lastText) return

if (mPrefs.getBoolean(mKeyUtil.audioEnabled, true)) {
MediaPlayer.create(context, R.raw.notification_simple).start()
}

setFragmentResult("BarcodeResult",
bundleOf("barcode_result" to result.text.toString()))

Expand Down
Loading

0 comments on commit 0d7fc81

Please sign in to comment.