Compare commits

..

20 Commits

Author SHA1 Message Date
Quentin Hibon
e65c7de086 Don't accept null urls 2024-04-04 23:55:28 +02:00
06090e238a Merge branch 'feature/konfetti' into dev 2024-04-02 19:51:59 -05:00
e48452f724 Move showConfetti to ListHabitsScreen; use button location; other tweaks 2024-04-02 19:34:00 -05:00
dependabot[bot]
936986e110 Bump daggerVersion from 2.50 to 2.51.1
Bumps `daggerVersion` from 2.50 to 2.51.1.

Updates `com.google.dagger:dagger` from 2.50 to 2.51.1
- [Release notes](https://github.com/google/dagger/releases)
- [Changelog](https://github.com/google/dagger/blob/master/CHANGELOG.md)
- [Commits](https://github.com/google/dagger/compare/dagger-2.50...dagger-2.51.1)

Updates `com.google.dagger:dagger-compiler` from 2.50 to 2.51.1
- [Release notes](https://github.com/google/dagger/releases)
- [Changelog](https://github.com/google/dagger/blob/master/CHANGELOG.md)
- [Commits](https://github.com/google/dagger/compare/dagger-2.50...dagger-2.51.1)

---
updated-dependencies:
- dependency-name: com.google.dagger:dagger
  dependency-type: direct:production
  update-type: version-update:semver-minor
- dependency-name: com.google.dagger:dagger-compiler
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-02 22:04:24 +02:00
dependabot[bot]
4b3910aea8 Bump com.google.guava:guava from 33.0.0-android to 33.1.0-android
Bumps [com.google.guava:guava](https://github.com/google/guava) from 33.0.0-android to 33.1.0-android.
- [Release notes](https://github.com/google/guava/releases)
- [Commits](https://github.com/google/guava/commits)

---
updated-dependencies:
- dependency-name: com.google.guava:guava
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-01 18:11:48 +02:00
Gokul K
1280e798d2 rendering only if layout and konfetti view exists - to avoid null reference errors 2024-02-03 23:14:58 -06:00
Gokul K
b09306e793 fixing another lint error 2024-02-03 23:14:58 -06:00
Gokul K
e30636a447 fixed ktlint erorrs and is building successfully now 2024-02-03 23:14:58 -06:00
Gokul K
ad8738180c fixing some comments from @hiqua 2024-02-03 23:14:58 -06:00
Gokul K
08410c59d0 introducing confetti animation using konfetti library 2024-02-03 23:14:58 -06:00
Manish Kumar Verma
ab86cee70b Fix: No notification when goal type is set to "maximum" (#1931) 2024-02-02 19:21:40 -06:00
dependabot[bot]
3a0603605b Bump androidx.annotation:annotation from 1.7.0 to 1.7.1
Bumps androidx.annotation:annotation from 1.7.0 to 1.7.1.

---
updated-dependencies:
- dependency-name: androidx.annotation:annotation
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-01 04:43:18 -06:00
dependabot[bot]
6a78b4d853 Bump daggerVersion from 2.48.1 to 2.50 (#1907)
Bumps `daggerVersion` from 2.48.1 to 2.50.

Updates `com.google.dagger:dagger` from 2.48.1 to 2.50
- [Release notes](https://github.com/google/dagger/releases)
- [Changelog](https://github.com/google/dagger/blob/master/CHANGELOG.md)
- [Commits](https://github.com/google/dagger/compare/dagger-2.48.1...dagger-2.50)

Updates `com.google.dagger:dagger-compiler` from 2.48.1 to 2.50
- [Release notes](https://github.com/google/dagger/releases)
- [Changelog](https://github.com/google/dagger/blob/master/CHANGELOG.md)
- [Commits](https://github.com/google/dagger/compare/dagger-2.48.1...dagger-2.50)

---
updated-dependencies:
- dependency-name: com.google.dagger:dagger
  dependency-type: direct:production
  update-type: version-update:semver-minor
- dependency-name: com.google.dagger:dagger-compiler
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-01 04:34:40 -06:00
dependabot[bot]
fe43b1435d Bump ch.qos.logback:logback-classic from 1.4.13 to 1.4.14 (#1905)
Bumps [ch.qos.logback:logback-classic](https://github.com/qos-ch/logback) from 1.4.13 to 1.4.14.
- [Commits](https://github.com/qos-ch/logback/compare/v_1.4.13...v_1.4.14)

---
updated-dependencies:
- dependency-name: ch.qos.logback:logback-classic
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-01 04:33:18 -06:00
dependabot[bot]
12503b8a6d Bump com.google.guava:guava from 32.1.3-android to 33.0.0-android (#1902)
Bumps [com.google.guava:guava](https://github.com/google/guava) from 32.1.3-android to 33.0.0-android.
- [Release notes](https://github.com/google/guava/releases)
- [Commits](https://github.com/google/guava/commits)

---
updated-dependencies:
- dependency-name: com.google.guava:guava
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-01 04:33:03 -06:00
dependabot[bot]
ef7f78bff0 Bump org.xerial:sqlite-jdbc from 3.42.0.0 to 3.45.1.0 (#1929)
Bumps [org.xerial:sqlite-jdbc](https://github.com/xerial/sqlite-jdbc) from 3.42.0.0 to 3.45.1.0.
- [Release notes](https://github.com/xerial/sqlite-jdbc/releases)
- [Changelog](https://github.com/xerial/sqlite-jdbc/blob/master/CHANGELOG)
- [Commits](https://github.com/xerial/sqlite-jdbc/compare/3.42.0.0...3.45.1.0)

---
updated-dependencies:
- dependency-name: org.xerial:sqlite-jdbc
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-01 04:32:43 -06:00
dependabot[bot]
53c208ded5 Bump com.google.android.material:material from 1.10.0 to 1.11.0 (#1908)
Bumps [com.google.android.material:material](https://github.com/material-components/material-components-android) from 1.10.0 to 1.11.0.
- [Release notes](https://github.com/material-components/material-components-android/releases)
- [Commits](https://github.com/material-components/material-components-android/compare/1.10.0...1.11.0)

---
updated-dependencies:
- dependency-name: com.google.android.material:material
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-01 04:32:23 -06:00
dependabot[bot]
1bdc83e92f Bump org.mockito.kotlin:mockito-kotlin from 5.1.0 to 5.2.1 (#1906)
Bumps [org.mockito.kotlin:mockito-kotlin](https://github.com/mockito/mockito-kotlin) from 5.1.0 to 5.2.1.
- [Release notes](https://github.com/mockito/mockito-kotlin/releases)
- [Commits](https://github.com/mockito/mockito-kotlin/compare/5.1.0...5.2.1)

---
updated-dependencies:
- dependency-name: org.mockito.kotlin:mockito-kotlin
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-01 04:32:08 -06:00
dependabot[bot]
680c1cdc76 Bump kotlinVersion from 1.9.21 to 1.9.22 (#1904)
Bumps `kotlinVersion` from 1.9.21 to 1.9.22.

Updates `org.jetbrains.kotlin.android` from 1.9.21 to 1.9.22

Updates `org.jetbrains.kotlin.kapt` from 1.9.21 to 1.9.22

Updates `org.jetbrains.kotlin.multiplatform` from 1.9.21 to 1.9.22

Updates `org.jetbrains.kotlin:kotlin-stdlib-jdk8` from 1.9.21 to 1.9.22
- [Release notes](https://github.com/JetBrains/kotlin/releases)
- [Changelog](https://github.com/JetBrains/kotlin/blob/master/ChangeLog.md)
- [Commits](https://github.com/JetBrains/kotlin/compare/v1.9.21...v1.9.22)

---
updated-dependencies:
- dependency-name: org.jetbrains.kotlin.android
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: org.jetbrains.kotlin.kapt
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: org.jetbrains.kotlin.multiplatform
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: org.jetbrains.kotlin:kotlin-stdlib-jdk8
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-01 04:31:50 -06:00
dependabot[bot]
80916bac50 Bump actions/upload-artifact from 3 to 4 (#1901)
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 3 to 4.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-01 04:31:37 -06:00
18 changed files with 150 additions and 40 deletions

View File

@@ -22,7 +22,7 @@ jobs:
- name: Upload artifacts
if: always()
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: build
path: |

View File

@@ -1,5 +1,5 @@
plugins {
val kotlinVersion = "1.9.21"
val kotlinVersion = "1.9.22"
id("com.android.application") version "8.1.4" apply (false)
id("org.jetbrains.kotlin.android") version kotlinVersion apply (false)
id("org.jetbrains.kotlin.kapt") version kotlinVersion apply (false)

View File

@@ -94,8 +94,8 @@ android {
}
dependencies {
val daggerVersion = "2.48.1"
val kotlinVersion = "1.9.21"
val daggerVersion = "2.51.1"
val kotlinVersion = "1.9.22"
val kxCoroutinesVersion = "1.7.3"
val ktorVersion = "1.6.8"
val espressoVersion = "3.5.1"
@@ -106,17 +106,17 @@ dependencies {
androidTestImplementation("com.linkedin.dexmaker:dexmaker-mockito:2.28.3")
androidTestImplementation("io.ktor:ktor-client-mock:$ktorVersion")
androidTestImplementation("io.ktor:ktor-jackson:$ktorVersion")
androidTestImplementation("androidx.annotation:annotation:1.7.0")
androidTestImplementation("androidx.annotation:annotation:1.7.1")
androidTestImplementation("androidx.test.ext:junit:1.1.5")
androidTestImplementation("androidx.test.uiautomator:uiautomator:2.2.0")
androidTestImplementation("androidx.test:rules:1.5.0")
androidTestImplementation("org.mockito.kotlin:mockito-kotlin:5.1.0")
androidTestImplementation("org.mockito.kotlin:mockito-kotlin:5.2.1")
compileOnly("javax.annotation:jsr250-api:1.0")
coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.0.4")
implementation("com.github.AppIntro:AppIntro:6.3.1")
implementation("com.google.code.findbugs:jsr305:3.0.2")
implementation("com.google.dagger:dagger:$daggerVersion")
implementation("com.google.guava:guava:32.1.3-android")
implementation("com.google.guava:guava:33.1.0-android")
implementation("io.ktor:ktor-client-android:$ktorVersion")
implementation("io.ktor:ktor-client-core:$ktorVersion")
implementation("io.ktor:ktor-client-jackson:$ktorVersion")
@@ -127,14 +127,15 @@ dependencies {
implementation("androidx.appcompat:appcompat:1.6.1")
implementation("androidx.legacy:legacy-preference-v14:1.0.0")
implementation("androidx.legacy:legacy-support-v4:1.0.0")
implementation("com.google.android.material:material:1.10.0")
implementation("com.google.android.material:material:1.11.0")
implementation("com.opencsv:opencsv:5.9")
implementation("nl.dionsegijn:konfetti-xml:2.0.2")
implementation(project(":uhabits-core"))
kapt("com.google.dagger:dagger-compiler:$daggerVersion")
kaptAndroidTest("com.google.dagger:dagger-compiler:$daggerVersion")
testImplementation("com.google.dagger:dagger:$daggerVersion")
testImplementation("junit:junit:4.13.2")
testImplementation("org.mockito.kotlin:mockito-kotlin:5.1.0")
testImplementation("org.mockito.kotlin:mockito-kotlin:5.2.1")
}
kapt {

View File

@@ -132,7 +132,7 @@ object CommonSteps : BaseUserInterfaceTest() {
}
@Throws(Exception::class)
fun verifyOpensWebsite(url: String?) {
fun verifyOpensWebsite(url: String) {
var browserPkg = "org.chromium.webview_shell"
if (SDK_INT <= Build.VERSION_CODES.M) {
browserPkg = "com.android.browser"

View File

@@ -33,17 +33,19 @@ import org.isoron.uhabits.core.models.Entry.Companion.UNKNOWN
import org.isoron.uhabits.core.models.Entry.Companion.YES_MANUAL
import org.isoron.uhabits.databinding.CheckmarkPopupBinding
import org.isoron.uhabits.utils.InterfaceUtils.getFontAwesome
import org.isoron.uhabits.utils.getCenter
import org.isoron.uhabits.utils.sres
class CheckmarkDialog : AppCompatDialogFragment() {
var onToggle: (Int, String) -> Unit = { _, _ -> }
var onToggle: (Int, String, Float, Float) -> Unit = { _, _, _, _ -> }
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val appComponent = (requireActivity().application as HabitsApplication).component
val prefs = appComponent.preferences
val view = CheckmarkPopupBinding.inflate(LayoutInflater.from(context))
val color = requireArguments().getInt("color")
arrayOf(view.yesBtn, view.skipBtn).forEach {
it.setTextColor(requireArguments().getInt("color"))
it.setTextColor(color)
}
arrayOf(view.noBtn, view.unknownBtn).forEach {
it.setTextColor(view.root.sres.getColor(R.attr.contrast60))
@@ -62,7 +64,8 @@ class CheckmarkDialog : AppCompatDialogFragment() {
}
fun onClick(v: Int) {
val notes = view.notes.text.toString().trim()
onToggle(v, notes)
val location = view.yesBtn.getCenter()
onToggle(v, notes, location.x, location.y)
requireDialog().dismiss()
}
view.yesBtn.setOnClickListener { onClick(YES_MANUAL) }

View File

@@ -15,6 +15,7 @@ import org.isoron.uhabits.R
import org.isoron.uhabits.core.models.Entry
import org.isoron.uhabits.databinding.CheckmarkPopupBinding
import org.isoron.uhabits.utils.InterfaceUtils
import org.isoron.uhabits.utils.getCenter
import org.isoron.uhabits.utils.requestFocusWithKeyboard
import org.isoron.uhabits.utils.sres
import java.text.DecimalFormat
@@ -24,7 +25,7 @@ import java.text.ParseException
class NumberDialog : AppCompatDialogFragment() {
var onToggle: (Double, String) -> Unit = { _, _ -> }
var onToggle: (Double, String, Float, Float) -> Unit = { _, _, _, _ -> }
var onDismiss: () -> Unit = {}
private var originalNotes: String = ""
@@ -113,7 +114,8 @@ class NumberDialog : AppCompatDialogFragment() {
// NOP
}
val notes = view.notes.text.toString()
onToggle(value, notes)
val location = view.saveBtn.getCenter()
onToggle(value, notes, location.x, location.y)
requireDialog().dismiss()
}
}

View File

@@ -23,6 +23,7 @@ import android.content.Context
import android.view.ViewGroup.LayoutParams.MATCH_PARENT
import android.widget.FrameLayout
import android.widget.RelativeLayout
import nl.dionsegijn.konfetti.xml.KonfettiView
import org.isoron.uhabits.R
import org.isoron.uhabits.activities.common.views.ScrollableChart
import org.isoron.uhabits.activities.common.views.TaskProgressBar
@@ -69,6 +70,9 @@ class ListHabitsRootView @Inject constructor(
val listView: HabitCardListView = habitCardListViewFactory.create()
val llEmpty = EmptyListView(context)
val tbar = buildToolbar()
val konfettiView = KonfettiView(context).apply {
translationZ = 10f
}
val progressBar = TaskProgressBar(context, runner)
val hintView: HintView
val header = HeaderView(context, preferences, midnightTimer)
@@ -80,6 +84,7 @@ class ListHabitsRootView @Inject constructor(
val rootView = RelativeLayout(context).apply {
background = sres.getDrawable(R.attr.windowBackgroundColor)
addAtTop(konfettiView)
addAtTop(tbar)
addBelow(header, tbar)
addBelow(listView, header, height = MATCH_PARENT)

View File

@@ -25,6 +25,9 @@ import android.content.Intent
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import dagger.Lazy
import nl.dionsegijn.konfetti.core.Party
import nl.dionsegijn.konfetti.core.Position
import nl.dionsegijn.konfetti.core.emitter.Emitter
import org.isoron.platform.gui.toInt
import org.isoron.uhabits.R
import org.isoron.uhabits.activities.common.dialogs.CheckmarkDialog
@@ -63,6 +66,7 @@ import org.isoron.uhabits.intents.IntentFactory
import org.isoron.uhabits.tasks.ExportDBTaskFactory
import org.isoron.uhabits.tasks.ImportDataTask
import org.isoron.uhabits.tasks.ImportDataTaskFactory
import org.isoron.uhabits.utils.ColorUtils
import org.isoron.uhabits.utils.copyTo
import org.isoron.uhabits.utils.currentTheme
import org.isoron.uhabits.utils.dismissCurrentAndShow
@@ -72,6 +76,7 @@ import org.isoron.uhabits.utils.showSendEmailScreen
import org.isoron.uhabits.utils.showSendFileScreen
import java.io.File
import java.io.IOException
import java.util.concurrent.TimeUnit
import javax.inject.Inject
const val RESULT_IMPORT_DATA = 101
@@ -218,6 +223,28 @@ class ListHabitsScreen
activity.showSendFileScreen(filename)
}
override fun showConfetti(color: PaletteColor, x: Float, y: Float) {
val baseColor = themeSwitcher.currentTheme!!.color(color).toInt()
rootView.get().konfettiView.start(
Party(
speed = 0f,
maxSpeed = 16f,
damping = 0.9f,
spread = 360,
angle = 0,
colors = listOf(
ColorUtils.changeHue(baseColor, 180f),
ColorUtils.changeHue(baseColor, 20f),
ColorUtils.changeHue(baseColor, -20f),
baseColor
),
position = Position.Absolute(x, y),
emitter = Emitter(duration = 25, TimeUnit.MILLISECONDS).max(25),
timeToLive = 0
)
)
}
override fun showSettingsScreen() {
val intent = intentFactory.startSettingsActivity(activity)
activity.startActivityForResult(intent, REQUEST_SETTINGS)
@@ -240,7 +267,7 @@ class ListHabitsScreen
putDouble("value", value)
putString("notes", notes)
}
dialog.onToggle = { v, n -> callback.onNumberPicked(v, n) }
dialog.onToggle = { v, n, x, y -> callback.onNumberPicked(v, n, x, y) }
dialog.dismissCurrentAndShow(fm, "numberDialog")
}
@@ -258,7 +285,7 @@ class ListHabitsScreen
putInt("value", selectedValue)
putString("notes", notes)
}
dialog.onToggle = { v, n -> callback.onNotesSaved(v, n) }
dialog.onToggle = { v, n, x, y -> callback.onNotesSaved(v, n, x, y) }
dialog.dismissCurrentAndShow(fm, "checkmarkDialog")
}

View File

@@ -20,6 +20,7 @@
package org.isoron.uhabits.activities.habits.list.views
import android.content.Context
import android.graphics.PointF
import android.graphics.text.LineBreaker.BREAK_STRATEGY_BALANCED
import android.os.Build
import android.os.Build.VERSION.SDK_INT
@@ -154,7 +155,17 @@ class HabitCardView(
checkmarkPanel = checkmarkPanelFactory.create().apply {
onToggle = { timestamp, value, notes ->
triggerRipple(timestamp)
habit?.let { behavior.onToggle(it, timestamp, value, notes) }
val location = getAbsoluteButtonLocation(timestamp)
habit?.let {
behavior.onToggle(
it,
timestamp,
value,
notes,
location.x,
location.y
)
}
}
onEdit = { timestamp ->
triggerRipple(timestamp)
@@ -206,12 +217,27 @@ class HabitCardView(
}
fun triggerRipple(timestamp: Timestamp) {
val location = getRelativeButtonLocation(timestamp)
triggerRipple(location.x, location.y)
}
private fun getRelativeButtonLocation(timestamp: Timestamp): PointF {
val today = DateUtils.getTodayWithOffset()
val offset = timestamp.daysUntil(today) - dataOffset
val button = checkmarkPanel.buttons[offset]
val y = button.height / 2.0f
val x = checkmarkPanel.x + button.x + (button.width / 2).toFloat()
triggerRipple(x, y)
return PointF(x, y)
}
private fun getAbsoluteButtonLocation(timestamp: Timestamp): PointF {
val containerLocation = IntArray(2)
this.getLocationOnScreen(containerLocation)
val relButtonLocation = getRelativeButtonLocation(timestamp)
return PointF(
containerLocation[0].toFloat() + relButtonLocation.x,
containerLocation[1].toFloat() - relButtonLocation.y
)
}
override fun onAttachedToWindow() {

View File

@@ -179,7 +179,7 @@ class ShowHabitActivity : AppCompatActivity(), CommandRunner.Listener {
putDouble("value", value)
putString("notes", notes)
}
dialog.onToggle = { v, n -> callback.onNumberPicked(v, n) }
dialog.onToggle = { v, n, x, y -> callback.onNumberPicked(v, n, x, y) }
dialog.dismissCurrentAndShow(supportFragmentManager, "numberDialog")
}
@@ -196,7 +196,7 @@ class ShowHabitActivity : AppCompatActivity(), CommandRunner.Listener {
putInt("value", selectedValue)
putString("notes", notes)
}
dialog.onToggle = { v, n -> callback.onNotesSaved(v, n) }
dialog.onToggle = { v, n, x, y -> callback.onNotesSaved(v, n, x, y) }
dialog.dismissCurrentAndShow(supportFragmentManager, "checkmarkDialog")
}

View File

@@ -36,6 +36,13 @@ object ColorUtils {
return a or r or g or b
}
fun changeHue(color: Int, delta: Float): Int {
val hsv = FloatArray(3)
Color.colorToHSV(color, hsv)
hsv[0] = (hsv[0] + delta).mod(360f)
return Color.HSVToColor(hsv)
}
@JvmStatic
fun setAlpha(color: Int, newAlpha: Float): Int {
val intAlpha = (newAlpha * 255).toInt()

View File

@@ -26,6 +26,7 @@ import android.content.Intent
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.PointF
import android.graphics.drawable.ColorDrawable
import android.os.Handler
import android.os.SystemClock
@@ -135,7 +136,11 @@ fun Activity.startActivitySafely(intent: Intent) {
}
}
fun Activity.showSendEmailScreen(@StringRes toId: Int, @StringRes subjectId: Int, content: String?) {
fun Activity.showSendEmailScreen(
@StringRes toId: Int,
@StringRes subjectId: Int,
content: String?
) {
val to = this.getString(toId)
val subject = this.getString(subjectId)
this.startActivity(
@@ -232,3 +237,11 @@ fun View.requestFocusWithKeyboard() {
dispatchTouchEvent(MotionEvent.obtain(time, time, MotionEvent.ACTION_UP, 0f, 0f, 0))
}, 250)
}
fun View.getCenter(): PointF {
val viewLocation = IntArray(2)
this.getLocationOnScreen(viewLocation)
viewLocation[0] += this.width / 2
viewLocation[1] -= this.height / 2
return PointF(viewLocation[0].toFloat(), viewLocation[1].toFloat())
}

View File

@@ -44,10 +44,10 @@ kotlin {
val jvmMain by getting {
dependencies {
implementation(kotlin("stdlib-jdk8"))
compileOnly("com.google.dagger:dagger:2.48.1")
implementation("com.google.guava:guava:32.1.3-android")
compileOnly("com.google.dagger:dagger:2.51.1")
implementation("com.google.guava:guava:33.1.0-android")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.7.3")
implementation("androidx.annotation:annotation:1.7.0")
implementation("androidx.annotation:annotation:1.7.1")
implementation("com.google.code.findbugs:jsr305:3.0.2")
implementation("com.opencsv:opencsv:5.9")
implementation("commons-codec:commons-codec:1.16.0")
@@ -59,10 +59,10 @@ kotlin {
dependencies {
implementation(kotlin("test"))
implementation(kotlin("test-junit"))
implementation("org.xerial:sqlite-jdbc:3.42.0.0")
implementation("org.xerial:sqlite-jdbc:3.45.1.0")
implementation("org.hamcrest:hamcrest:2.2")
implementation("org.apache.commons:commons-io:1.3.2")
implementation("org.mockito.kotlin:mockito-kotlin:5.1.0")
implementation("org.mockito.kotlin:mockito-kotlin:5.2.1")
implementation("org.junit.jupiter:junit-jupiter:5.10.1")
}
}

View File

@@ -61,7 +61,7 @@ data class Habit(
return if (isNumerical) {
when (targetType) {
NumericalHabitType.AT_LEAST -> value / 1000.0 >= targetValue
NumericalHabitType.AT_MOST -> value / 1000.0 <= targetValue
NumericalHabitType.AT_MOST -> value != Entry.UNKNOWN && value / 1000.0 <= targetValue
}
} else {
value != Entry.NO && value != Entry.UNKNOWN

View File

@@ -20,9 +20,12 @@ package org.isoron.uhabits.core.ui.screens.habits.list
import org.isoron.uhabits.core.commands.CommandRunner
import org.isoron.uhabits.core.commands.CreateRepetitionCommand
import org.isoron.uhabits.core.models.Entry.Companion.YES_MANUAL
import org.isoron.uhabits.core.models.Habit
import org.isoron.uhabits.core.models.HabitList
import org.isoron.uhabits.core.models.HabitType
import org.isoron.uhabits.core.models.NumericalHabitType.AT_LEAST
import org.isoron.uhabits.core.models.NumericalHabitType.AT_MOST
import org.isoron.uhabits.core.models.PaletteColor
import org.isoron.uhabits.core.models.Timestamp
import org.isoron.uhabits.core.preferences.Preferences
@@ -52,8 +55,16 @@ open class ListHabitsBehavior @Inject constructor(
val entry = habit.computedEntries.get(timestamp!!)
if (habit.type == HabitType.NUMERICAL) {
val oldValue = entry.value.toDouble() / 1000
screen.showNumberPopup(oldValue, entry.notes) { newValue: Double, newNotes: String ->
screen.showNumberPopup(oldValue, entry.notes) { newValue: Double, newNotes: String, x: Float, y: Float ->
val value = (newValue * 1000).roundToInt()
if (newValue != oldValue) {
if (
(habit.targetType == AT_LEAST && newValue >= habit.targetValue) ||
(habit.targetType == AT_MOST && newValue <= habit.targetValue)
) {
screen.showConfetti(habit.color, x, y)
}
}
commandRunner.run(CreateRepetitionCommand(habitList, habit, timestamp, value, newNotes))
}
} else {
@@ -61,7 +72,8 @@ open class ListHabitsBehavior @Inject constructor(
entry.value,
entry.notes,
habit.color
) { newValue, newNotes ->
) { newValue: Int, newNotes: String, x: Float, y: Float ->
if (newValue != entry.value && newValue == YES_MANUAL) screen.showConfetti(habit.color, x, y)
commandRunner.run(CreateRepetitionCommand(habitList, habit, timestamp, newValue, newNotes))
}
}
@@ -117,10 +129,11 @@ open class ListHabitsBehavior @Inject constructor(
if (prefs.isFirstRun) onFirstRun()
}
fun onToggle(habit: Habit, timestamp: Timestamp, value: Int, notes: String) {
fun onToggle(habit: Habit, timestamp: Timestamp, value: Int, notes: String, x: Float, y: Float) {
commandRunner.run(
CreateRepetitionCommand(habitList, habit, timestamp, value, notes)
)
if (value == YES_MANUAL) screen.showConfetti(habit.color, x, y)
}
enum class Message {
@@ -144,12 +157,22 @@ open class ListHabitsBehavior @Inject constructor(
}
fun interface NumberPickerCallback {
fun onNumberPicked(newValue: Double, notes: String)
fun onNumberPicked(
newValue: Double,
notes: String,
x: Float,
y: Float
)
fun onNumberPickerDismissed() {}
}
fun interface CheckMarkDialogCallback {
fun onNotesSaved(value: Int, notes: String)
fun onNotesSaved(
value: Int,
notes: String,
x: Float,
y: Float
)
fun onNotesDismissed() {}
}
@@ -170,5 +193,6 @@ open class ListHabitsBehavior @Inject constructor(
)
fun showSendBugReportToDeveloperScreen(log: String)
fun showSendFileScreen(filename: String)
fun showConfetti(color: PaletteColor, x: Float, y: Float)
}
}

View File

@@ -98,7 +98,7 @@ class HistoryCardPresenter(
entry.value,
entry.notes,
habit.color
) { newValue, newNotes ->
) { newValue, newNotes, _: Float, _: Float ->
commandRunner.run(
CreateRepetitionCommand(
habitList,
@@ -135,7 +135,7 @@ class HistoryCardPresenter(
screen.showNumberPopup(
value = oldValue / 1000.0,
notes = entry.notes
) { newValue: Double, newNotes: String ->
) { newValue: Double, newNotes: String, _: Float, _: Float ->
val thousands = (newValue * 1000).roundToInt()
commandRunner.run(
CreateRepetitionCommand(

View File

@@ -84,7 +84,7 @@ class ListHabitsBehaviorTest : BaseUnitTest() {
eq(""),
picker.capture()
)
picker.lastValue.onNumberPicked(100.0, "")
picker.lastValue.onNumberPicked(100.0, "", 0f, 0f)
val today = getTodayWithOffset()
assertThat(habit2.computedEntries.get(today).value, equalTo(100000))
}
@@ -168,7 +168,9 @@ class ListHabitsBehaviorTest : BaseUnitTest() {
habit = habit1,
timestamp = getToday(),
value = Entry.NO,
notes = ""
notes = "",
x = 0f,
y = 0f
)
assertFalse(habit1.isCompletedToday())
}

View File

@@ -38,9 +38,9 @@ application {
dependencies {
val ktorVersion = "1.6.8"
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.9.21")
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.9.22")
implementation("io.ktor:ktor-server-netty:$ktorVersion")
implementation("ch.qos.logback:logback-classic:1.4.13")
implementation("ch.qos.logback:logback-classic:1.4.14")
implementation("io.ktor:ktor-server-core:$ktorVersion")
implementation("io.ktor:ktor-html-builder:$ktorVersion")
implementation("io.ktor:ktor-jackson:$ktorVersion")
@@ -49,7 +49,7 @@ dependencies {
implementation("io.prometheus:simpleclient_httpserver:0.16.0")
implementation("io.prometheus:simpleclient_hotspot:0.16.0")
testImplementation("io.ktor:ktor-server-tests:$ktorVersion")
testImplementation("org.mockito.kotlin:mockito-kotlin:5.1.0")
testImplementation("org.mockito.kotlin:mockito-kotlin:5.2.1")
testImplementation(kotlin("test"))
testImplementation(kotlin("test-junit"))
}