diff --git a/.gitignore b/.gitignore index 428073f23..ec3b87f2e 100644 --- a/.gitignore +++ b/.gitignore @@ -73,3 +73,4 @@ output-metadata.json /Habitica/jacoco.exec *.dm /fastlane/upload_slack.py +.kotlin diff --git a/Habitica/build.gradle b/Habitica/build.gradle index 5b640b68c..3b85ac5f5 100644 --- a/Habitica/build.gradle +++ b/Habitica/build.gradle @@ -10,6 +10,8 @@ plugins { id 'com.google.firebase.firebase-perf' id 'jacoco-report-aggregation' + id 'org.jetbrains.kotlin.plugin.compose' + id("kotlin-parcelize") } apply plugin: 'kotlin-android' @@ -171,10 +173,6 @@ android { aidl true } - composeOptions { - kotlinCompilerExtensionVersion = rootProject.compose_compiler - } - signingConfigs { release } diff --git a/Habitica/res/layout/subscription_benefits.xml b/Habitica/res/layout/subscription_benefits.xml index 27d7d53a6..201081719 100644 --- a/Habitica/res/layout/subscription_benefits.xml +++ b/Habitica/res/layout/subscription_benefits.xml @@ -23,6 +23,7 @@ android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:layout_marginStart="12dp" + android:layout_marginVertical="6dp" android:orientation="vertical"> Become a subscriber to receive these exclusive benefits! Free Monthly Gems Monthly Mystic Hourglass - Never miss an item with 1 Mystic Hourglass a month to use in the Time Travelers Shop! + Monthly Mystery Items Special Subscriber Pet Hang on with 1 HP! Special Pet & More Drops diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/models/tasks/ChecklistItem.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/models/tasks/ChecklistItem.kt index 030ffd563..7d78867e1 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/models/tasks/ChecklistItem.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/models/tasks/ChecklistItem.kt @@ -55,7 +55,6 @@ open class ChecklistItem : RealmObject, BaseMainObject, Parcelable { companion object CREATOR : Parcelable.Creator, RealmModel { override fun createFromParcel(source: Parcel): ChecklistItem = ChecklistItem(source) - override fun newArray(size: Int): Array = arrayOfNulls(size) } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/social/InboxAdapter.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/social/InboxAdapter.kt index 5695ef629..1e7d4ecc5 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/social/InboxAdapter.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/social/InboxAdapter.kt @@ -24,13 +24,17 @@ class InboxAdapter(private var user: User?) : var onCopyMessage: ((ChatMessage) -> Unit)? = null private fun isPositionIntroMessage(position: Int): Boolean { - return (position == super.getItemCount() - 1) + return (position == super.getItemCount()) } override fun getItemViewType(position: Int): Int { return if (isPositionIntroMessage(position)) FIRST_MESSAGE else NORMAL_MESSAGE } + override fun getItemCount(): Int { + return super.getItemCount() + 1 + } + override fun onCreateViewHolder( parent: ViewGroup, viewType: Int, diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/purchases/GiftBalanceGemsFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/purchases/GiftBalanceGemsFragment.kt index f48156e40..6cd2b9676 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/purchases/GiftBalanceGemsFragment.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/purchases/GiftBalanceGemsFragment.kt @@ -73,7 +73,7 @@ class GiftBalanceGemsFragment : BaseFragment() { if (isGifting) return isGifting = true try { - val amount = binding?.giftEditText?.text.toString().strip().toInt() + val amount = binding?.giftEditText?.text.toString().trim().toInt() giftedMember?.id?.let { activity?.lifecycleScope?.launchCatching({ isGifting = false diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/BottomSheetUtils.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/BottomSheetUtils.kt index 769a2b3b5..df75bfe46 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/BottomSheetUtils.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/BottomSheetUtils.kt @@ -4,6 +4,7 @@ import android.app.Activity import android.view.ViewGroup import androidx.activity.compose.BackHandler import androidx.compose.foundation.background +import androidx.compose.foundation.gestures.scrollable import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.ExperimentalLayoutApi @@ -13,7 +14,9 @@ import androidx.compose.foundation.layout.navigationBarsIgnoringVisibility import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.windowInsetsBottomHeight +import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.verticalScroll import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ModalBottomSheet import androidx.compose.material3.SheetValue @@ -86,6 +89,7 @@ private fun BottomSheetWrapper( val systemUiController = rememberSystemUiController() val statusBarColor = colorResource(R.color.content_background) val navigationbarColor = colorResource(R.color.brand_50) + DisposableEffect(systemUiController) { systemUiController.setStatusBarColor(statusBarColor.copy(alpha = 0.3f), darkIcons = true) systemUiController.setNavigationBarColor(navigationbarColor, darkIcons = true) @@ -108,6 +112,7 @@ private fun BottomSheetWrapper( horizontalAlignment = Alignment.CenterHorizontally, modifier = Modifier + .verticalScroll(rememberScrollState()) .padding(horizontal = 4.dp) .background( HabiticaTheme.colors.windowBackground, diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/ValidatingEditText.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/ValidatingEditText.kt index a763a9a2f..232b80389 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/ValidatingEditText.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/ValidatingEditText.kt @@ -28,9 +28,8 @@ class ValidatingEditText binding.errorText.text = value } var hint: CharSequence? - get() = binding.editText.hint + get() = binding.inputLayout.hint set(value) { - binding.editText.hint = value binding.inputLayout.hint = value } var validator: ((String?) -> Boolean)? = null diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/subscriptions/SubscriptionDetailsView.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/subscriptions/SubscriptionDetailsView.kt index 83efc13e9..b435f4376 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/subscriptions/SubscriptionDetailsView.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/subscriptions/SubscriptionDetailsView.kt @@ -10,6 +10,7 @@ import android.widget.LinearLayout import androidx.core.view.isVisible import com.habitrpg.android.habitica.R import com.habitrpg.android.habitica.databinding.SubscriptionDetailsBinding +import com.habitrpg.android.habitica.extensions.toZonedDateTime import com.habitrpg.android.habitica.models.user.SubscriptionPlan import com.habitrpg.android.habitica.ui.views.HabiticaIconsHelper import com.habitrpg.common.habitica.extensions.layoutInflater @@ -144,11 +145,12 @@ class SubscriptionDetailsView : LinearLayout { binding.gemCapTextView.text = plan.totalNumberOfGems.toString() - if (plan.isActive && plan.dateTerminated == null) { - val now = LocalDate.now() - val nextHourglassDate = - LocalDate.now().plusMonths(plan.monthsUntilNextHourglass.toLong()) - .withDayOfMonth(1) + val now = LocalDate.now() + val nextHourglassDate = + now.plusMonths(plan.monthsUntilNextHourglass.toLong()) + .withDayOfMonth(1) + val terminatedLocalDate = plan.dateTerminated?.toZonedDateTime()?.toLocalDate() + if (plan.isActive && (terminatedLocalDate == null || nextHourglassDate.isBefore(terminatedLocalDate))) { val format = if (now.year != nextHourglassDate.year) { "dd MMM yyyy" diff --git a/build.gradle b/build.gradle index 5ebdc1495..7c9ef00e3 100644 --- a/build.gradle +++ b/build.gradle @@ -21,7 +21,7 @@ buildscript { daggerhilt_version = '2.51.1' firebase_bom = '31.3.0' kotest_version = '5.6.2' - kotlin_version = '1.9.24' + kotlin_version = '2.0.20' ktlint_version = '1.2.1' lifecycle_version = '2.8.4' markwon_version = '4.6.2' @@ -44,7 +44,7 @@ buildscript { mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:8.4.2' + classpath 'com.android.tools.build:gradle:8.5.2' classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8' classpath 'com.google.gms:google-services:4.4.2' classpath 'com.google.firebase:firebase-crashlytics-gradle:3.0.2' @@ -56,6 +56,7 @@ buildscript { classpath 'com.google.firebase:perf-plugin:1.4.2' classpath "com.google.dagger:hilt-android-gradle-plugin:$daggerhilt_version" classpath "org.jlleitschuh.gradle:ktlint-gradle:11.3.1" + classpath "org.jetbrains.kotlin:compose-compiler-gradle-plugin:$kotlin_version" } } diff --git a/common/build.gradle.kts b/common/build.gradle.kts index 45b19f50f..7fc6589ab 100644 --- a/common/build.gradle.kts +++ b/common/build.gradle.kts @@ -6,6 +6,7 @@ import java.util.Properties plugins { id("com.android.library") id("org.jetbrains.kotlin.android") + id("org.jetbrains.kotlin.plugin.compose") } val rootExtra = rootProject.extra @@ -130,11 +131,11 @@ dependencies { testImplementation("io.kotest:kotest-framework-datatest:$kotest_version") testImplementation("org.jetbrains.kotlin:kotlin-reflect:$kotlin_version") - androidTestImplementation("androidx.test.ext:junit:1.1.5") - androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1") + androidTestImplementation("androidx.test.ext:junit:1.2.1") + androidTestImplementation("androidx.test.espresso:espresso-core:3.6.1") androidTestImplementation("org.jetbrains.kotlin:kotlin-reflect:$kotlin_version") - implementation("androidx.activity:activity-compose:1.9.0") + implementation("androidx.activity:activity-compose:1.9.1") implementation("androidx.compose.runtime:runtime-livedata:$compose_version") implementation("androidx.compose.animation:animation:$compose_version") implementation("androidx.compose.ui:ui-text-google-fonts:$compose_version") diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 5735e5275..aa8686625 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ #Mon Jun 10 15:25:21 CEST 2024 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/shared/build.gradle.kts b/shared/build.gradle.kts index 2e5bb6bc2..b3435c1c5 100644 --- a/shared/build.gradle.kts +++ b/shared/build.gradle.kts @@ -22,7 +22,6 @@ kotlin { js(IR) { browser() nodejs() - binaries.library() } sourceSets { diff --git a/shared/src/androidMain/kotlin/com/habitrpg/shared/habitica/Platform.android.kt b/shared/src/androidMain/kotlin/com/habitrpg/shared/habitica/Platform.android.kt new file mode 100644 index 000000000..ee26c8b00 --- /dev/null +++ b/shared/src/androidMain/kotlin/com/habitrpg/shared/habitica/Platform.android.kt @@ -0,0 +1,5 @@ +package com.habitrpg.shared.habitica + +import android.os.Parcel + +actual typealias HParcel = Parcel diff --git a/shared/src/androidMain/kotlin/com/habitrpg/shared/habitica/Platform.kt b/shared/src/androidMain/kotlin/com/habitrpg/shared/habitica/Platform.kt index a0fa0a379..3c50a8e43 100644 --- a/shared/src/androidMain/kotlin/com/habitrpg/shared/habitica/Platform.kt +++ b/shared/src/androidMain/kotlin/com/habitrpg/shared/habitica/Platform.kt @@ -1,3 +1,5 @@ +@file:Suppress("EXPECT_ACTUAL_CLASSIFIERS_ARE_IN_BETA_WARNING") + package com.habitrpg.shared.habitica import android.os.Parcelable diff --git a/shared/src/commonMain/kotlin/com/habitrpg/shared/habitica/Platform.kt b/shared/src/commonMain/kotlin/com/habitrpg/shared/habitica/Platform.kt index b6e26bc78..353ba8012 100644 --- a/shared/src/commonMain/kotlin/com/habitrpg/shared/habitica/Platform.kt +++ b/shared/src/commonMain/kotlin/com/habitrpg/shared/habitica/Platform.kt @@ -1,13 +1,29 @@ package com.habitrpg.shared.habitica +import com.habitrpg.shared.habitica.models.responses.TaskDirectionDataDrop + expect class Platform() { val platform: String } -expect interface HParcelable +@Suppress("EXPECT_ACTUAL_CLASSIFIERS_ARE_IN_BETA_WARNING") +expect interface HParcelable { + fun writeToParcel(dest: HParcel, flags: Int) + fun describeContents(): Int +} +@Suppress("EXPECT_ACTUAL_CLASSIFIERS_ARE_IN_BETA_WARNING") @OptIn(ExperimentalMultiplatform::class) @OptionalExpectation @Target(AnnotationTarget.CLASS) @Retention(AnnotationRetention.BINARY) expect annotation class HParcelize() + +expect class HParcel { + fun writeByte(byte: Byte) + fun writeParcelable(drop: HParcelable?, flags: Int) + fun writeDouble(experienceDelta: Double) + fun writeInt(level: Int) + fun writeValue(questDamage: Any?) + fun writeString(it: String?) +} diff --git a/shared/src/commonMain/kotlin/com/habitrpg/shared/habitica/models/responses/TaskDirectionDataTemp.kt b/shared/src/commonMain/kotlin/com/habitrpg/shared/habitica/models/responses/TaskDirectionDataTemp.kt index 5a118e24b..9b1a44ef7 100644 --- a/shared/src/commonMain/kotlin/com/habitrpg/shared/habitica/models/responses/TaskDirectionDataTemp.kt +++ b/shared/src/commonMain/kotlin/com/habitrpg/shared/habitica/models/responses/TaskDirectionDataTemp.kt @@ -1,5 +1,6 @@ package com.habitrpg.shared.habitica.models.responses +import com.habitrpg.shared.habitica.HParcel import com.habitrpg.shared.habitica.HParcelable import com.habitrpg.shared.habitica.HParcelize @@ -14,10 +15,20 @@ class TaskDirectionDataQuest { var collection: Int = 0 } -@HParcelize data class TaskDirectionDataDrop( var value: Int, var key: String?, var type: String?, var dialog: String?, -) : HParcelable +) : HParcelable { + override fun writeToParcel(dest: HParcel, flags: Int) { + dest.writeInt(value) + dest.writeString(key) + dest.writeString(type) + dest.writeString(dialog) + } + + override fun describeContents(): Int { + return 0 + } +} diff --git a/shared/src/commonMain/kotlin/com/habitrpg/shared/habitica/models/responses/TaskScoringResult.kt b/shared/src/commonMain/kotlin/com/habitrpg/shared/habitica/models/responses/TaskScoringResult.kt index 746af57a8..2c4a9e070 100644 --- a/shared/src/commonMain/kotlin/com/habitrpg/shared/habitica/models/responses/TaskScoringResult.kt +++ b/shared/src/commonMain/kotlin/com/habitrpg/shared/habitica/models/responses/TaskScoringResult.kt @@ -1,10 +1,10 @@ package com.habitrpg.shared.habitica.models.responses +import com.habitrpg.shared.habitica.HParcel import com.habitrpg.shared.habitica.HParcelable import com.habitrpg.shared.habitica.HParcelize import com.habitrpg.shared.habitica.models.AvatarStats -@HParcelize data class TaskScoringResult( var hasDied: Boolean = false, var drop: TaskDirectionDataDrop? = null, @@ -33,4 +33,21 @@ data class TaskScoringResult( data._tmp?.quest?.progressDelta, data._tmp?.quest?.collection, ) + + override fun writeToParcel(dest: HParcel, flags: Int) { + dest.writeByte(if (hasDied) 1.toByte() else 0.toByte()) + dest.writeParcelable(drop, flags) + dest.writeDouble(experienceDelta) + dest.writeDouble(healthDelta) + dest.writeDouble(goldDelta) + dest.writeDouble(manaDelta) + dest.writeByte(if (hasLeveledUp) 1.toByte() else 0.toByte()) + dest.writeInt(level) + dest.writeValue(questDamage) + dest.writeValue(questItemsFound) + } + + override fun describeContents(): Int { + return 0 + } } diff --git a/shared/src/iosMain/kotlin/com/habitrpg/shared/habitica/Platform.ios.kt b/shared/src/iosMain/kotlin/com/habitrpg/shared/habitica/Platform.ios.kt new file mode 100644 index 000000000..4dbe70171 --- /dev/null +++ b/shared/src/iosMain/kotlin/com/habitrpg/shared/habitica/Platform.ios.kt @@ -0,0 +1,3 @@ +package com.habitrpg.shared.habitica + +actual class HParcel diff --git a/shared/src/jsMain/kotlin/com/habitrpg/shared/habitica/Platform.js.kt b/shared/src/jsMain/kotlin/com/habitrpg/shared/habitica/Platform.js.kt index 6c981fbf8..963527e78 100644 --- a/shared/src/jsMain/kotlin/com/habitrpg/shared/habitica/Platform.js.kt +++ b/shared/src/jsMain/kotlin/com/habitrpg/shared/habitica/Platform.js.kt @@ -6,3 +6,4 @@ actual class Platform actual constructor() { } actual interface HParcelable +actual class HParcel diff --git a/version.properties b/version.properties index e811a3107..f4b1e53df 100644 --- a/version.properties +++ b/version.properties @@ -1,2 +1,2 @@ NAME=4.5.0 -CODE=8051 \ No newline at end of file +CODE=8061 \ No newline at end of file