diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 000000000..5adef55c9
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1 @@
+public/** linguist-vendored
\ No newline at end of file
diff --git a/.idea/kotlinc.xml b/.idea/kotlinc.xml
index e805548aa..8d81632f8 100644
--- a/.idea/kotlinc.xml
+++ b/.idea/kotlinc.xml
@@ -1,6 +1,6 @@
-
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
index a33bb3181..49d13d9e4 100644
--- a/.idea/vcs.xml
+++ b/.idea/vcs.xml
@@ -2,7 +2,6 @@
-
\ No newline at end of file
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index cd1991864..7cf318518 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -1,4 +1,4 @@
-import com.android.build.gradle.internal.cxx.configure.gradleLocalProperties
+import org.jetbrains.kotlin.konan.properties.Properties
plugins {
alias(libs.plugins.android.application)
@@ -13,19 +13,26 @@ plugins {
}
android {
+ buildFeatures.buildConfig = true
+
defaultConfig {
applicationId = "com.kafka.user"
- versionCode = 52
+ versionCode = 53
versionName = libs.versions.versionname.toString()
- val root = gradleLocalProperties(rootDir)
- val googleServerClientId: String = (root.getProperty("GOOGLE_SERVER_CLIENT_ID")
- ?: System.getenv("GOOGLE_SERVER_CLIENT_ID")) as String
- val pipelessAuthToken: String = (root.getProperty("PIPELESS_AUTH_TOKEN")
- ?: System.getenv("PIPELESS_AUTH_TOKEN")) as String
+ val properties = Properties()
+ properties.load(project.rootProject.file("local.properties").inputStream())
- buildConfigField("String", "GOOGLE_SERVER_CLIENT_ID", googleServerClientId)
- buildConfigField("String", "PIPELESS_AUTH_TOKEN", pipelessAuthToken)
+ buildConfigField(
+ "String",
+ "GOOGLE_SERVER_CLIENT_ID",
+ properties["PIPELESS_AUTH_TOKEN"]?.toString() ?: System.getenv("PIPELESS_AUTH_TOKEN")
+ )
+ buildConfigField(
+ "String",
+ "PIPELESS_AUTH_TOKEN",
+ properties["PIPELESS_AUTH_TOKEN"]?.toString() ?: System.getenv("PIPELESS_AUTH_TOKEN")
+ )
}
compileOptions {
@@ -107,8 +114,6 @@ android {
warning += "AutoboxingStateCreation"
}
- buildFeatures.buildConfig = true
-
}
dependencies {
diff --git a/app/src/main/java/com/kafka/user/MainActivity.kt b/app/src/main/java/com/kafka/user/MainActivity.kt
index 197a29d50..98d434c5c 100644
--- a/app/src/main/java/com/kafka/user/MainActivity.kt
+++ b/app/src/main/java/com/kafka/user/MainActivity.kt
@@ -45,10 +45,10 @@ class MainActivity : ComponentActivity() {
override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
- if (::navController.isInitialized) {
+ if (::navController.isInitialized && intent != null) {
navController.handleDeepLink(intent)
} else {
- Timber.e(Error("navController is not initialized. isFinishing $isFinishing"))
+ Timber.e(Error("navController is not initialized or intent is null. isFinishing = $isFinishing, intent = $intent"))
}
}
}
diff --git a/app/src/main/java/com/kafka/user/fcm/FirebaseMessageService.kt b/app/src/main/java/com/kafka/user/fcm/FirebaseMessageService.kt
index 788ef116a..3db944412 100644
--- a/app/src/main/java/com/kafka/user/fcm/FirebaseMessageService.kt
+++ b/app/src/main/java/com/kafka/user/fcm/FirebaseMessageService.kt
@@ -42,14 +42,20 @@ class FirebaseMessageService : FirebaseMessagingService() {
debug { "Received FCM message: $message" }
- when {
- message.data.isNotEmpty() -> notificationManager.buildNotification(
- push = pushMapper.map(message),
- pendingIntent = mainActivityIntent()
- )
+ if (message.data.isNotEmpty()) {
+ val contentId = message.data["itemId"]
- else -> super.onMessageReceived(message)
+ debug { "FCM contentId $contentId" }
}
+
+// when {
+// message.data.isNotEmpty() -> notificationManager.buildNotification(
+// push = pushMapper.map(message),
+// pendingIntent = mainActivityIntent()
+// )
+//
+// else -> super.onMessageReceived(message)
+// }
}
override fun onNewToken(token: String) {
diff --git a/app/src/main/java/com/kafka/user/injection/PlayerModule.kt b/app/src/main/java/com/kafka/user/injection/PlayerModule.kt
index 9272dc60e..c30bb513c 100644
--- a/app/src/main/java/com/kafka/user/injection/PlayerModule.kt
+++ b/app/src/main/java/com/kafka/user/injection/PlayerModule.kt
@@ -1,13 +1,17 @@
package com.kafka.user.injection
+import com.kafka.remote.config.RemoteConfig
+import com.kafka.remote.config.isExactAlarmEnabled
import com.kafka.user.playback.KafkaPlayerEventLogger
import com.kafka.user.playback.PlayerAudioDataSource
+import com.sarahang.playback.core.PlayerRemoteConfig
import com.sarahang.playback.core.apis.AudioDataSource
import com.sarahang.playback.core.apis.PlayerEventLogger
import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
+import javax.inject.Inject
@InstallIn(SingletonComponent::class)
@Module
@@ -18,4 +22,15 @@ abstract class PlayerModule {
@Binds
abstract fun playerEventLogger(kafkaPlayerEventLogger: KafkaPlayerEventLogger): PlayerEventLogger
+
+ @Binds
+ abstract fun PlayerRemoteConfig(playerRemoteConfig: PlayerRemoteConfigImpl): PlayerRemoteConfig
+}
+
+class PlayerRemoteConfigImpl @Inject constructor(
+ private val remoteConfig: RemoteConfig
+) : PlayerRemoteConfig {
+ override fun isExactAlarmEnabled(): Boolean {
+ return remoteConfig.isExactAlarmEnabled()
+ }
}
diff --git a/core/remote-config/src/main/java/com/kafka/remote/config/RemoteConfigExtensions.kt b/core/remote-config/src/main/java/com/kafka/remote/config/RemoteConfigExtensions.kt
index e5060d7b5..195eef202 100644
--- a/core/remote-config/src/main/java/com/kafka/remote/config/RemoteConfigExtensions.kt
+++ b/core/remote-config/src/main/java/com/kafka/remote/config/RemoteConfigExtensions.kt
@@ -6,6 +6,7 @@ const val DOWNLOADER_TYPE = "downloader_type"
const val GOOGLE_LOGIN_ENABLED = "google_login_enabled"
const val RECOMMENDATION_ENABLED = "recommendation_data_enabled"
const val ONLINE_READER_ENABLED = "online_reader_enabled"
+const val EXACT_ALARM_ENABLED = "exact_alarm_enabled"
fun RemoteConfig.getPlayerTheme() = get(REMOTE_CONFIG_PLAYER_THEME_KEY)
@@ -18,3 +19,5 @@ fun RemoteConfig.isGoogleLoginEnabled() = getBoolean(GOOGLE_LOGIN_ENABLED)
fun RemoteConfig.isRecommendationEnabled() = getBoolean(RECOMMENDATION_ENABLED)
fun RemoteConfig.isOnlineReaderEnabled() = getBoolean(ONLINE_READER_ENABLED)
+
+fun RemoteConfig.isExactAlarmEnabled() = getBoolean(EXACT_ALARM_ENABLED)
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 76417fc2c..32160df46 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -1,20 +1,20 @@
[versions]
accompanist = "0.34.0"
-agp = "8.2.2"
-androidxhilt = "1.1.0"
+agp = "8.3.0"
+androidxhilt = "1.2.0"
androidxlifecycle = "2.7.0"
-navigation = "2.7.6"
-coil = "2.5.0"
+navigation = "2.7.7"
+coil = "2.6.0"
compose-alpha = "2024.01.00-alpha01"
-compose-bom = "2024.01.00"
+compose-bom = "2024.02.02"
constraintlayout = "1.1.0-alpha13"
-composecompiler = "1.5.4"
-coroutines = "1.7.3"
-dagger = "2.50"
+composecompiler = "1.5.10"
+coroutines = "1.8.0"
+dagger = "2.51"
icons = "1.0.0"
-kotlin = "1.9.20"
+kotlin = "1.9.22"
kotlin-immutable = "0.3.7"
-material3 = "1.2.0-rc01"
+material3 = "1.2.1"
mixpanel = "7.0.0"
okhttp = "4.12.0"
paging = "3.2.1"
@@ -30,25 +30,25 @@ targetSdk = "33"
core-ktx = "1.12.0"
androidx-test-ext-junit = "1.1.5"
espresso-core = "3.5.1"
-uiautomator = "2.2.0"
+uiautomator = "2.3.0"
benchmark-macro-junit4 = "1.2.3"
androidx-baselineprofile = "1.2.3"
profileinstaller = "1.3.1"
review = "2.0.1"
-versionname = "0.12.0"
+versionname = "0.13.0"
[plugins]
android-application = { id = "com.android.application", version.ref = "agp" }
android-library = { id = "com.android.library", version.ref = "agp" }
android-lint = { id = "com.android.lint", version.ref = "agp" }
-cacheFixPlugin = { id = "org.gradle.android.cache-fix", version = "3.0" }
+cacheFixPlugin = { id = "org.gradle.android.cache-fix", version = "3.0.1" }
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
kotlin-kapt = { id = "org.jetbrains.kotlin.kapt", version.ref = "kotlin" }
-ksp = "com.google.devtools.ksp:1.9.22-1.0.16"
-gms-googleServices = "com.google.gms.google-services:4.4.0"
+ksp = "com.google.devtools.ksp:1.9.23-1.0.19"
+gms-googleServices = "com.google.gms.google-services:4.4.1"
firebase-crashlytics = "com.google.firebase.crashlytics:2.9.9"
-spotless = "com.diffplug.spotless:6.24.0"
+spotless = "com.diffplug.spotless:6.25.0"
kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }
hilt = { id = "com.google.dagger.hilt.android", version.ref = "dagger" }
androidTest = { id = "com.android.test", version.ref = "agp" }
@@ -76,7 +76,7 @@ androidx-collection = "androidx.collection:collection-ktx:1.4.0"
androidx-core = "androidx.core:core-ktx:1.12.0"
androidx-hilt-compiler = { module = "androidx.hilt:hilt-compiler", version.ref = "androidxhilt" }
-androidx-hilt-compose = "androidx.hilt:hilt-navigation-compose:1.1.0"
+androidx-hilt-compose = "androidx.hilt:hilt-navigation-compose:1.2.0"
androidx-hilt-navigation = { module = "androidx.hilt:hilt-navigation", version.ref = "androidxhilt" }
hilt-compiler = { module = "com.google.dagger:hilt-android-compiler", version.ref = "dagger" }
@@ -129,16 +129,16 @@ fetch-okhttp = "androidx.tonyodev.fetch2okhttp:xfetch2okhttp:3.1.6"
dagger-dagger = { module = "com.google.dagger:dagger", version.ref = "dagger" }
-google-bom = "com.google.firebase:firebase-bom:32.7.1"
+google-bom = "com.google.firebase:firebase-bom:32.7.4"
google-analytics = { module = "com.google.firebase:firebase-analytics" }
google-crashlytics = { module = "com.google.firebase:firebase-crashlytics" }
google-dynamic_links = { module = "com.google.firebase:firebase-dynamic-links" }
google-auth = { module = "com.google.firebase:firebase-auth" }
-google-coroutines = "org.jetbrains.kotlinx:kotlinx-coroutines-play-services:1.7.3"
+google-coroutines = "org.jetbrains.kotlinx:kotlinx-coroutines-play-services:1.8.0"
google-firestore = { module = "com.google.firebase:firebase-firestore" }
google-messaging = { module = "com.google.firebase:firebase-messaging" }
google-performance = { module = "com.google.firebase:firebase-perf" }
-google-playservices-auth = "com.google.android.gms:play-services-auth:20.7.0"
+google-playservices-auth = "com.google.android.gms:play-services-auth:21.0.0"
google-remoteConfig = { module = "com.google.firebase:firebase-config" }
google-storage = { module = "com.google.firebase:firebase-storage-ktx" }
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index e57a6b765..92c1ac1bd 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,7 @@
-#Wed Sep 15 09:55:12 CEST 2021
distributionBase=GRADLE_USER_HOME
-distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip
distributionPath=wrapper/dists
-zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip
+networkTimeout=10000
+validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
\ No newline at end of file
diff --git a/ui/common/src/main/java/org/kafka/common/LazyList.kt b/ui/common/src/main/java/org/kafka/common/LazyList.kt
new file mode 100644
index 000000000..f5d091e4b
--- /dev/null
+++ b/ui/common/src/main/java/org/kafka/common/LazyList.kt
@@ -0,0 +1,15 @@
+package org.kafka.common
+
+import androidx.compose.foundation.lazy.LazyListState
+import androidx.compose.ui.unit.Dp
+import androidx.compose.ui.unit.dp
+
+val LazyListState.elevation: Dp
+ get() = if (firstVisibleItemIndex == 0) {
+ // For the first element, use the minimum of scroll offset and default elevation
+ // i.e. a value between 0 and 4.dp
+ minOf(firstVisibleItemScrollOffset.toFloat().dp, 24.dp)
+ } else {
+ // If not the first element, always set elevation and show the shadow
+ 24.dp
+ }
diff --git a/ui/common/src/main/java/org/kafka/common/extensions/Elevation.kt b/ui/common/src/main/java/org/kafka/common/extensions/Elevation.kt
deleted file mode 100644
index 53085b167..000000000
--- a/ui/common/src/main/java/org/kafka/common/extensions/Elevation.kt
+++ /dev/null
@@ -1,41 +0,0 @@
-package org.kafka.common.extensions
-
-import androidx.compose.foundation.ScrollState
-import androidx.compose.foundation.lazy.LazyListState
-import androidx.compose.foundation.lazy.grid.LazyGridState
-import androidx.compose.runtime.derivedStateOf
-import androidx.compose.ui.unit.Dp
-import androidx.compose.ui.unit.dp
-import ui.common.theme.theme.Dimens
-
-val ScrollState.elevation
- get() = derivedStateOf {
- this.run { ((value / 100) * 2).coerceAtMost(MaxElevation).dp } ?: 0.dp
- }
-
-val LazyListState.elevation: Dp
- get() = if (firstVisibleItemIndex == 0) {
- // For the first element, use the minimum of scroll offset and default elevation
- // i.e. a value between 0 and 4.dp
- minOf(firstVisibleItemScrollOffset.toFloat().dp, 24.dp)
- } else {
- // If not the first element, always set elevation and show the shadow
- 24.dp
- }
-
-
-val LazyListState?.elevation
- get() = derivedStateOf {
- if (this?.firstVisibleItemIndex == 0) {
- minOf(firstVisibleItemScrollOffset.toFloat().dp, MaxElevation.dp)
- } else {
- Dimens.Spacing20
- }
- }
-
-
-fun LazyGridState.elevation(maxElevation: Int = 40) = derivedStateOf {
- this.run { firstVisibleItemScrollOffset.coerceAtMost(maxElevation) }.dp
-}
-
-private const val MaxElevation = 20
diff --git a/ui/common/src/main/java/org/kafka/common/extensions/elevation.kt b/ui/common/src/main/java/org/kafka/common/extensions/elevation.kt
deleted file mode 100644
index 53085b167..000000000
--- a/ui/common/src/main/java/org/kafka/common/extensions/elevation.kt
+++ /dev/null
@@ -1,41 +0,0 @@
-package org.kafka.common.extensions
-
-import androidx.compose.foundation.ScrollState
-import androidx.compose.foundation.lazy.LazyListState
-import androidx.compose.foundation.lazy.grid.LazyGridState
-import androidx.compose.runtime.derivedStateOf
-import androidx.compose.ui.unit.Dp
-import androidx.compose.ui.unit.dp
-import ui.common.theme.theme.Dimens
-
-val ScrollState.elevation
- get() = derivedStateOf {
- this.run { ((value / 100) * 2).coerceAtMost(MaxElevation).dp } ?: 0.dp
- }
-
-val LazyListState.elevation: Dp
- get() = if (firstVisibleItemIndex == 0) {
- // For the first element, use the minimum of scroll offset and default elevation
- // i.e. a value between 0 and 4.dp
- minOf(firstVisibleItemScrollOffset.toFloat().dp, 24.dp)
- } else {
- // If not the first element, always set elevation and show the shadow
- 24.dp
- }
-
-
-val LazyListState?.elevation
- get() = derivedStateOf {
- if (this?.firstVisibleItemIndex == 0) {
- minOf(firstVisibleItemScrollOffset.toFloat().dp, MaxElevation.dp)
- } else {
- Dimens.Spacing20
- }
- }
-
-
-fun LazyGridState.elevation(maxElevation: Int = 40) = derivedStateOf {
- this.run { firstVisibleItemScrollOffset.coerceAtMost(maxElevation) }.dp
-}
-
-private const val MaxElevation = 20
diff --git a/ui/homepage/src/main/java/org/kafka/homepage/recent/RecentScreen.kt b/ui/homepage/src/main/java/org/kafka/homepage/recent/RecentScreen.kt
index db45f7edc..908be05ae 100644
--- a/ui/homepage/src/main/java/org/kafka/homepage/recent/RecentScreen.kt
+++ b/ui/homepage/src/main/java/org/kafka/homepage/recent/RecentScreen.kt
@@ -16,7 +16,7 @@ import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.kafka.data.entities.RecentItem
import kotlinx.collections.immutable.ImmutableList
-import org.kafka.common.extensions.elevation
+import org.kafka.common.elevation
import org.kafka.common.widgets.shadowMaterial
import org.kafka.homepage.R
import org.kafka.navigation.LocalNavigator
diff --git a/ui/item/src/main/java/org/kafka/item/files/Files.kt b/ui/item/src/main/java/org/kafka/item/files/Files.kt
index 820deec33..d59d0b0e2 100644
--- a/ui/item/src/main/java/org/kafka/item/files/Files.kt
+++ b/ui/item/src/main/java/org/kafka/item/files/Files.kt
@@ -16,7 +16,7 @@ import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.kafka.data.entities.File
import kotlinx.coroutines.CoroutineScope
-import org.kafka.common.extensions.elevation
+import org.kafka.common.elevation
import org.kafka.common.test.testTagUi
import org.kafka.common.widgets.shadowMaterial
import org.kafka.navigation.LocalNavigator