Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

introducing confetti animation using konfetti library #1743

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions uhabits-android/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ dependencies {
implementation("androidx.legacy:legacy-support-v4:1.0.0")
implementation("com.google.android.material:material:1.8.0")
implementation("com.opencsv:opencsv:5.7.1")
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")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View.GONE
import android.view.View.VISIBLE
import android.widget.LinearLayout
import androidx.appcompat.app.AppCompatDialogFragment
import org.isoron.uhabits.HabitsApplication
import org.isoron.uhabits.R
Expand All @@ -33,6 +34,7 @@ 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.showConfetti
import org.isoron.uhabits.utils.sres

class CheckmarkDialog : AppCompatDialogFragment() {
Expand Down Expand Up @@ -64,6 +66,10 @@ class CheckmarkDialog : AppCompatDialogFragment() {
val notes = view.notes.text.toString().trim()
onToggle(v, notes)
requireDialog().dismiss()
val konfettiView = requireActivity().findViewById<LinearLayout>(R.id.konfettiLayout)
when (v) {
YES_MANUAL -> showConfetti(konfettiView)
}
}
view.yesBtn.setOnClickListener { onClick(YES_MANUAL) }
view.noBtn.setOnClickListener { onClick(NO) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@ import android.view.KeyEvent
import android.view.LayoutInflater
import android.view.MotionEvent
import android.view.View
import android.widget.LinearLayout
import androidx.appcompat.app.AppCompatDialogFragment
import org.isoron.uhabits.HabitsApplication
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.requestFocusWithKeyboard
import org.isoron.uhabits.utils.showConfetti
import org.isoron.uhabits.utils.sres
import java.text.DecimalFormat
import java.text.DecimalFormatSymbols
Expand Down Expand Up @@ -100,5 +102,11 @@ class NumberDialog : AppCompatDialogFragment() {
val notes = view.notes.text.toString()
onToggle(value, notes)
requireDialog().dismiss()
val konfettiView = requireActivity().findViewById<LinearLayout>(R.id.konfettiLayout)

if (value > 0.0) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe it should be on completion rather than for any value? Not sure.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added a code comment.

Reason: I thought it would be motivating for users to at least add some value rather than not doing the habit. 😸

// To motivate, show confetti even if some value is present
showConfetti(konfettiView)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import org.isoron.uhabits.inject.ActivityScope
import org.isoron.uhabits.utils.addAtBottom
import org.isoron.uhabits.utils.addAtTop
import org.isoron.uhabits.utils.addBelow
import org.isoron.uhabits.utils.buildKonfettiView
import org.isoron.uhabits.utils.buildToolbar
import org.isoron.uhabits.utils.currentTheme
import org.isoron.uhabits.utils.dim
Expand All @@ -69,6 +70,7 @@ class ListHabitsRootView @Inject constructor(
val listView: HabitCardListView = habitCardListViewFactory.create()
val llEmpty = EmptyListView(context)
val tbar = buildToolbar()
val konfettiView = buildKonfettiView()
val progressBar = TaskProgressBar(context, runner)
val hintView: HintView
val header = HeaderView(context, preferences, midnightTimer)
Expand All @@ -80,6 +82,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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import org.isoron.uhabits.core.preferences.Preferences
import org.isoron.uhabits.inject.ActivityContext
import org.isoron.uhabits.utils.drawNotesIndicator
import org.isoron.uhabits.utils.getFontAwesome
import org.isoron.uhabits.utils.showConfetti
import org.isoron.uhabits.utils.sp
import org.isoron.uhabits.utils.sres
import org.isoron.uhabits.utils.toMeasureSpec
Expand Down Expand Up @@ -88,20 +89,23 @@ class CheckmarkButtonView(
setOnLongClickListener(this)
}

fun performToggle() {
fun performToggle(view: View) {
value = Entry.nextToggleValue(
value = value,
isSkipEnabled = preferences.isSkipEnabled,
areQuestionMarksEnabled = preferences.areQuestionMarksEnabled
)
onToggle(value, notes)
performHapticFeedback(HapticFeedbackConstants.LONG_PRESS)
when (value) {
YES_MANUAL -> showConfetti(view.rootView)
}
invalidate()
}

override fun onClick(v: View) {
if (preferences.isShortToggleEnabled) {
performToggle()
performToggle(v)
} else {
onEdit()
}
Expand All @@ -111,7 +115,7 @@ class CheckmarkButtonView(
if (preferences.isShortToggleEnabled) {
onEdit()
} else {
performToggle()
performToggle(v)
}
return true
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import android.view.ViewGroup
import android.view.ViewGroup.LayoutParams.MATCH_PARENT
import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
import android.view.WindowManager
import android.widget.LinearLayout
import android.widget.RelativeLayout
import android.widget.RelativeLayout.ALIGN_PARENT_BOTTOM
import android.widget.RelativeLayout.ALIGN_PARENT_TOP
Expand All @@ -46,13 +47,18 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.Toolbar
import androidx.core.content.FileProvider
import com.google.android.material.snackbar.Snackbar
import nl.dionsegijn.konfetti.core.Party
import nl.dionsegijn.konfetti.core.Position
import nl.dionsegijn.konfetti.core.emitter.Emitter
import nl.dionsegijn.konfetti.xml.KonfettiView
import org.isoron.platform.gui.toInt
import org.isoron.uhabits.HabitsApplication
import org.isoron.uhabits.R
import org.isoron.uhabits.activities.AndroidThemeSwitcher
import org.isoron.uhabits.core.models.PaletteColor
import org.isoron.uhabits.core.ui.views.Theme
import java.io.File
import java.util.concurrent.TimeUnit

fun RelativeLayout.addBelow(
view: View,
Expand All @@ -77,7 +83,9 @@ fun RelativeLayout.addAtBottom(
view.layoutParams = RelativeLayout.LayoutParams(width, height).apply {
addRule(ALIGN_PARENT_BOTTOM)
}
view.id = View.generateViewId()
if (view.id == null) {
view.id = View.generateViewId()
}
this.addView(view)
}

Expand All @@ -89,7 +97,10 @@ fun RelativeLayout.addAtTop(
view.layoutParams = RelativeLayout.LayoutParams(width, height).apply {
addRule(ALIGN_PARENT_TOP)
}
view.id = View.generateViewId()

if (view.id == null) {
view.id = View.generateViewId()
}
this.addView(view)
}

Expand All @@ -98,6 +109,32 @@ fun ViewGroup.buildToolbar(): Toolbar {
return inflater.inflate(R.layout.toolbar, null) as Toolbar
}

fun ViewGroup.buildKonfettiView(): View {
val inflater = LayoutInflater.from(context)
return inflater.inflate(R.layout.konfetti, null) as View
}

fun showConfetti(view: View) {
val viewId = R.id.konfetttiView
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
val viewId = R.id.konfetttiView
val viewId = R.id.konfettiView

Is this a typo or is there a reason to have 3 t?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not typo, i was just using 3 t to differentiate the variables in kt files and in XML. Just a minor naming convention

val linearLayout = view.findViewById<LinearLayout>(R.id.konfettiLayout)
val kv = view.findViewById<KonfettiView>(viewId)
if (linearLayout != null) {
linearLayout.bringToFront()
}
val party = Party(
speed = 0f,
maxSpeed = 32f,
damping = 0.9f,
spread = 360,
colors = listOf(0xfce18a, 0xff726d, 0xf4306d, 0xb48def, 0x818181, 0x81a48c),
position = Position.Relative(0.5, 0.3),
emitter = Emitter(duration = 300, TimeUnit.MILLISECONDS).max(300)
)
if (kv != null) {
kv.start(party)
}
}

fun View.showMessage(msg: String) {
try {
val snackbar = Snackbar.make(this, msg, Snackbar.LENGTH_SHORT)
Expand Down
29 changes: 29 additions & 0 deletions uhabits-android/src/main/res/layout/konfetti.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (C) 2013 The Android Open Source Project
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/konfettiLayout"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:focusable="false"
android:orientation="vertical" >

<nl.dionsegijn.konfetti.xml.KonfettiView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/konfetttiView"/>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
android:id="@+id/konfetttiView"/>
android:id="@+id/konfettiView"/>


</LinearLayout>
Loading