Skip to content

Commit

Permalink
Merge pull request #41 from unbiaseduser/under-the-hood-improvements
Browse files Browse the repository at this point in the history
Merge I'm Definitely Sober features back into Sobriety
  • Loading branch information
KiARC authored Oct 20, 2022
2 parents 4797409 + bff29c5 commit ecdd454
Show file tree
Hide file tree
Showing 22 changed files with 628 additions and 394 deletions.
30 changes: 19 additions & 11 deletions app/build.gradle
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
id 'kotlin-android'
}

android {
compileSdk 30
compileSdk 33

defaultConfig {
applicationId "com.katiearose.sobriety"
minSdk 26
targetSdk 30
minSdk 21
targetSdk 33
versionCode 14
versionName "v5.9.9"
setProperty("archivesBaseName", "Sobriety $versionName")
Expand All @@ -35,23 +36,30 @@ android {
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_11
targetCompatibility JavaVersion.VERSION_11
coreLibraryDesugaringEnabled true
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '11'
jvmTarget = '1.8'
}
buildFeatures {
viewBinding true
}
compileSdkVersion 30
compileSdkVersion 33
namespace 'com.katiearose.sobriety'
}

dependencies {
implementation 'androidx.core:core-ktx:1.6.0'
implementation 'androidx.appcompat:appcompat:1.3.1'
implementation 'com.google.android.material:material:1.4.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
implementation 'androidx.core:core-ktx:1.9.0'
implementation 'androidx.appcompat:appcompat:1.5.1'
implementation 'com.google.android.material:material:1.6.1'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
coreLibraryDesugaring ('com.android.tools:desugar_jdk_libs') {
version {
strictly ("1.2.0") //2.0.0 requires gradle 7.4.0-alpha10
}
}
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
Expand Down
26 changes: 18 additions & 8 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.katiearose.sobriety">
<manifest xmlns:android="http://schemas.android.com/apk/res/android">

<application
android:allowBackup="true"
Expand All @@ -11,14 +10,25 @@
android:supportsRtl="true"
android:theme="@style/Theme.Sobriety">
<activity
android:name=".Create"
android:name=".activities.Timeline"
android:exported="false"
android:label="Add new addiction"
android:windowSoftInputMode="adjustResize" />
android:label="@string/timeline">
<meta-data
android:name="android.app.lib_name"
android:value="" />
</activity>
<activity
android:name=".activities.Create"
android:exported="false"
android:label="@string/add_new_addiction"
android:windowSoftInputMode="adjustResize" >
<meta-data
android:name="android.app.lib_name"
android:value="" />
</activity>
<activity
android:name=".Main"
android:exported="true"
android:label="@string/app_name">
android:name=".activities.Main"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

Expand Down
39 changes: 34 additions & 5 deletions app/src/main/java/com/katiearose/sobriety/Addiction.kt
Original file line number Diff line number Diff line change
@@ -1,18 +1,37 @@
package com.katiearose.sobriety

import com.katiearose.sobriety.internal.CircularBuffer
import com.katiearose.sobriety.utils.putLast
import com.katiearose.sobriety.utils.secondsFromNow
import java.io.Serializable
import java.time.Instant

class Addiction(
val name: String,
var lastRelapse: Instant,
var relapses: CircularBuffer<Long> = CircularBuffer(3) //Default is a new one, but you can provide your own (from a cache)
var isStopped: Boolean,
var timeStopped: Long, //in milliseconds
val history: LinkedHashMap<Long, Long> = LinkedHashMap(), //in milliseconds
private val relapses: CircularBuffer<Long> = CircularBuffer(3) //Default is a new one, but you can provide your own (from a cache)
) : Serializable {
var averageRelapseDuration = Main.timeSinceInstant(lastRelapse)
var averageRelapseDuration = if (relapses.get(0) == null) -1 else calculateAverageRelapseDuration()
private set

fun stopAbstaining() {
isStopped = true
timeStopped = System.currentTimeMillis()
relapses.update(Instant.ofEpochMilli(timeStopped).epochSecond - lastRelapse.epochSecond)
averageRelapseDuration = calculateAverageRelapseDuration()
history.putLast(System.currentTimeMillis())
}

fun relapse() {
relapses.update(Main.timeSinceInstant(lastRelapse))
if (!isStopped) {
relapses.update(lastRelapse.secondsFromNow())
history.putLast(System.currentTimeMillis())
}
history[System.currentTimeMillis()] = 0
isStopped = false
averageRelapseDuration = calculateAverageRelapseDuration()
lastRelapse = Instant.now()
}
Expand All @@ -25,13 +44,23 @@ class Addiction(
val map = HashMap<Int, Any>()
map[0] = name
map[1] = lastRelapse
map[2] = relapses
map[2] = isStopped
map[3] = timeStopped
map[4] = history
map[5] = relapses
return map
}

companion object {
fun fromCacheable(map: HashMap<Int, Any>): Addiction {
return Addiction(map[0] as String, map[1] as Instant, map[2] as CircularBuffer<Long>)
return Addiction(
map[0] as String,
map[1] as Instant,
map[2] as Boolean,
map[3] as Long,
map[4] as LinkedHashMap<Long, Long>,
map[5] as CircularBuffer<Long>
)
}
}
}
89 changes: 61 additions & 28 deletions app/src/main/java/com/katiearose/sobriety/AddictionCardAdapter.kt
Original file line number Diff line number Diff line change
@@ -1,21 +1,51 @@
package com.katiearose.sobriety

import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.katiearose.sobriety.activities.Main
import com.katiearose.sobriety.utils.convertSecondsToString
import com.katiearose.sobriety.utils.secondsFromNow
import java.text.DateFormat
import java.util.*

class AddictionCardAdapter(private val activity: Main, private val cacheHandler: CacheHandler) :
class AddictionCardAdapter(private val context: Context) :
RecyclerView.Adapter<AddictionCardAdapter.AddictionCardViewHolder>() {

private lateinit var onButtonDeleteClickListener: View.OnClickListener
private lateinit var onButtonRelapseClickListener: View.OnClickListener
private lateinit var onButtonStopClickListener: View.OnClickListener
private lateinit var onTimelineButtonClickListener: View.OnClickListener
private val dateFormat = DateFormat.getDateTimeInstance()

fun setOnButtonDeleteClickListener(onButtonDeleteClickListener: View.OnClickListener) {
this.onButtonDeleteClickListener = onButtonDeleteClickListener
}

fun setOnButtonRelapseClickListener(onButtonRelapseClickListener: View.OnClickListener) {
this.onButtonRelapseClickListener = onButtonRelapseClickListener
}

fun setOnButtonStopClickListener(onButtonStopClickListener: View.OnClickListener) {
this.onButtonStopClickListener = onButtonStopClickListener
}

fun setOnTimelineButtonClickListener(onTimelineButtonClickListener: View.OnClickListener) {
this.onTimelineButtonClickListener = onTimelineButtonClickListener
}

override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
): AddictionCardViewHolder {
val itemView =
LayoutInflater.from(parent.context).inflate(R.layout.card_addiction, parent, false)
return AddictionCardViewHolder(itemView)
return AddictionCardViewHolder(itemView, onButtonDeleteClickListener, onButtonRelapseClickListener,
onButtonStopClickListener, onTimelineButtonClickListener)
}

override fun onBindViewHolder(
Expand All @@ -25,39 +55,42 @@ class AddictionCardAdapter(private val activity: Main, private val cacheHandler:
val addiction = Main.addictions[position]

holder.textViewName.text = addiction.name
holder.textViewTime.text =
Main.secondsToString(Main.timeSinceInstant(addiction.lastRelapse))
holder.textViewTime.text = if (!addiction.isStopped) context.convertSecondsToString(addiction.lastRelapse.secondsFromNow())
else context.getString(R.string.stop_notice,
dateFormat.format(Date(addiction.timeStopped)),
context.convertSecondsToString((addiction.timeStopped - addiction.lastRelapse.toEpochMilli()) / 1000))
holder.textViewAverage.visibility = if (addiction.averageRelapseDuration == -1L) View.GONE else View.VISIBLE
holder.textViewAverage.text =
"Recent Average: ${Main.secondsToString(addiction.averageRelapseDuration)}"

holder.buttonDelete.setOnClickListener {
val action: () -> Unit = {
Main.addictions.remove(addiction)
activity.updatePromptVisibility()
notifyItemRemoved(position)
Main.deleting = true
cacheHandler.writeCache()
}
activity.dialogConfirm("Delete entry \"${addiction.name}\" ?", action)
}

holder.buttonReset.setOnClickListener {
val action: () -> Unit = {
addiction.relapse()
notifyItemChanged(position)
cacheHandler.writeCache()
}
activity.dialogConfirm("Log relapse of \"${addiction.name}\" ?", action)
}
context.getString(R.string.recent_avg, context.convertSecondsToString(addiction.averageRelapseDuration))
}

override fun getItemCount() = Main.addictions.size

class AddictionCardViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
class AddictionCardViewHolder(itemView: View, onButtonDeleteClickListener: View.OnClickListener,
onButtonRelapseClickListener: View.OnClickListener,
onButtonStopClickListener: View.OnClickListener,
onTimelineButtonClickListener: View.OnClickListener
) : RecyclerView.ViewHolder(itemView) {
val textViewName: TextView = itemView.findViewById(R.id.textViewAddictionName)
val textViewTime: TextView = itemView.findViewById(R.id.textViewTime)
val textViewAverage: TextView = itemView.findViewById(R.id.textViewAverage)
val buttonDelete: ImageView = itemView.findViewById(R.id.imageDelete)
val buttonReset: ImageView = itemView.findViewById(R.id.imageReset)
init {
itemView.findViewById<ImageView>(R.id.imageDelete).apply {
tag = this@AddictionCardViewHolder
setOnClickListener(onButtonDeleteClickListener)
}
itemView.findViewById<ImageView>(R.id.imageReset).apply {
tag = this@AddictionCardViewHolder
setOnClickListener(onButtonRelapseClickListener)
}
itemView.findViewById<ImageView>(R.id.imageStop).apply {
tag = this@AddictionCardViewHolder
setOnClickListener(onButtonStopClickListener)
}
itemView.findViewById<ImageView>(R.id.imageTimeline).apply {
tag = this@AddictionCardViewHolder
setOnClickListener(onTimelineButtonClickListener)
}
}
}
}
Loading

0 comments on commit ecdd454

Please sign in to comment.