diff --git a/.idea/compiler.xml b/.idea/compiler.xml index b589d56e9f285d8cfdc6c270853a5d439021a278..e58d3e423fd6ba1f41f8b449410b7a5c9b2a5695 100644 --- a/.idea/compiler.xml +++ b/.idea/compiler.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <project version="4"> <component name="CompilerConfiguration"> - <bytecodeTargetLevel target="17" /> + <bytecodeTargetLevel target="19" /> </component> </project> \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml index 0897082f7512e48e89310db81b5455d997417505..8f1b960d1647c16b49204dafeda373864f7f7c7c 100644 --- a/.idea/gradle.xml +++ b/.idea/gradle.xml @@ -5,7 +5,7 @@ <option name="linkedExternalProjectsSettings"> <GradleProjectSettings> <option name="externalProjectPath" value="$PROJECT_DIR$" /> - <option name="gradleJvm" value="#GRADLE_LOCAL_JAVA_HOME" /> + <option name="gradleJvm" value="19" /> <option name="modules"> <set> <option value="$PROJECT_DIR$" /> diff --git a/.idea/kotlinc.xml b/.idea/kotlinc.xml index f8467b458e43862c587a34f34c06af8fbbf30d0f..fe63bb677dc7c018519fa0fb0fecb445e5256c67 100644 --- a/.idea/kotlinc.xml +++ b/.idea/kotlinc.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <project version="4"> <component name="KotlinJpsPluginSettings"> - <option name="version" value="1.9.10" /> + <option name="version" value="1.9.23" /> </component> </project> \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index 2188b52ba32001c9c693512cc725ce6c1d331efd..ddba1308a6b3133e32d83fa7b8e5174bc5e67922 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,3 +1,4 @@ +<?xml version="1.0" encoding="UTF-8"?> <project version="4"> <component name="EntryPointsManager"> <list size="1"> @@ -5,7 +6,7 @@ </list> </component> <component name="ExternalStorageConfigurationManager" enabled="true" /> - <component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="jbr-17" project-jdk-type="JavaSDK"> + <component name="ProjectRootManager" version="2" languageLevel="JDK_19" default="true" project-jdk-name="19" project-jdk-type="JavaSDK"> <output url="file://$PROJECT_DIR$/build/classes" /> </component> <component name="ProjectType"> diff --git a/app/build.gradle.kts b/app/build.gradle.kts index f4aa3feabbfbc17493a756142c97c07c516d545c..8d39981a7c3b1ffd92f89342c925a310b2e41e0a 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -1,6 +1,7 @@ import com.android.build.gradle.internal.cxx.configure.gradleLocalProperties plugins { + alias(libs.plugins.gradle.versions) alias(libs.plugins.android.application) alias(libs.plugins.kotlin.android) alias(libs.plugins.kotlinx.serialization) @@ -70,28 +71,27 @@ android { } } compileOptions { - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 + sourceCompatibility = JavaVersion.VERSION_19 + targetCompatibility = JavaVersion.VERSION_19 } kotlinOptions { - jvmTarget = "17" + jvmTarget = "19" freeCompilerArgs += "-Xcontext-receivers" // freeCompilerArgs += "-opt-in=kotlin.ExperimentalStdlibApi" // freeCompilerArgs += "-opt-in=kotlin.time.ExperimentalTime" - freeCompilerArgs += "-opt-in=kotlinx.coroutines.ExperimentalCoroutinesApi" +// freeCompilerArgs += "-opt-in=kotlinx.coroutines.ExperimentalCoroutinesApi" freeCompilerArgs += "-opt-in=androidx.compose.ui.ExperimentalComposeUiApi" freeCompilerArgs += "-opt-in=androidx.compose.foundation.ExperimentalFoundationApi" // freeCompilerArgs += "-opt-in=androidx.compose.foundation.layout.ExperimentalLayoutApi" // freeCompilerArgs += "-opt-in=androidx.compose.animation.ExperimentalAnimationApi" freeCompilerArgs += "-opt-in=androidx.compose.material3.ExperimentalMaterial3Api" - freeCompilerArgs += "-opt-in=com.google.accompanist.navigation.material.ExperimentalMaterialNavigationApi" } buildFeatures { compose = true buildConfig = true } composeOptions { - kotlinCompilerExtensionVersion = "1.5.3" + kotlinCompilerExtensionVersion = libs.versions.compose.compiler.get() } packaging { resources { diff --git a/app/src/main/java/net/novagamestudios/kaffeekasse/App.kt b/app/src/main/java/net/novagamestudios/kaffeekasse/App.kt index 3d7419aa763cb5392b99557b63a30c74e29c0d5e..996f2fa36017a60a000129d7cc4ee80a5a0db430 100644 --- a/app/src/main/java/net/novagamestudios/kaffeekasse/App.kt +++ b/app/src/main/java/net/novagamestudios/kaffeekasse/App.kt @@ -22,18 +22,18 @@ import net.novagamestudios.common_utils.compose.state.loadInitialBlocking import net.novagamestudios.common_utils.debug import net.novagamestudios.common_utils.info import net.novagamestudios.common_utils.toastShort -import net.novagamestudios.kaffeekasse.api.PortalClient +import net.novagamestudios.kaffeekasse.api.portal.PortalClient import net.novagamestudios.kaffeekasse.api.hiwi_tracker.HiwiTrackerAPI import net.novagamestudios.kaffeekasse.api.hiwi_tracker.HiwiTrackerScraper import net.novagamestudios.kaffeekasse.api.kaffeekasse.KaffeekasseAPI import net.novagamestudios.kaffeekasse.api.kaffeekasse.KaffeekasseScraper import net.novagamestudios.kaffeekasse.repositories.UpdateController import net.novagamestudios.kaffeekasse.gitlab.GitLab -import net.novagamestudios.kaffeekasse.repositories.GitLabReleases -import net.novagamestudios.kaffeekasse.repositories.HiwiTrackerRepository -import net.novagamestudios.kaffeekasse.repositories.KaffeekasseRepository +import net.novagamestudios.kaffeekasse.repositories.releases.GitLabReleases +import net.novagamestudios.kaffeekasse.repositories.i11.HiwiTrackerRepository +import net.novagamestudios.kaffeekasse.repositories.i11.KaffeekasseRepository import net.novagamestudios.kaffeekasse.repositories.Credentials -import net.novagamestudios.kaffeekasse.repositories.PortalRepository +import net.novagamestudios.kaffeekasse.repositories.i11.PortalRepository import net.novagamestudios.kaffeekasse.repositories.newSettingsStore diff --git a/app/src/main/java/net/novagamestudios/kaffeekasse/api/hiwi_tracker/HiwiTrackerAPI.kt b/app/src/main/java/net/novagamestudios/kaffeekasse/api/hiwi_tracker/HiwiTrackerAPI.kt index b53025551bd239b84691e730fd5fc393d56fe8d1..be4b62b1a3a49b38d72322f6dfd43c32c536eefc 100644 --- a/app/src/main/java/net/novagamestudios/kaffeekasse/api/hiwi_tracker/HiwiTrackerAPI.kt +++ b/app/src/main/java/net/novagamestudios/kaffeekasse/api/hiwi_tracker/HiwiTrackerAPI.kt @@ -3,7 +3,8 @@ package net.novagamestudios.kaffeekasse.api.hiwi_tracker import io.ktor.http.parameters import kotlinx.datetime.format import net.novagamestudios.common_utils.Logger -import net.novagamestudios.kaffeekasse.api.PortalClient +import net.novagamestudios.kaffeekasse.api.portal.PortalClient +import net.novagamestudios.kaffeekasse.api.hiwi_tracker.model.MonthDataResponse import net.novagamestudios.kaffeekasse.model.hiwi_tracker.MonthKey diff --git a/app/src/main/java/net/novagamestudios/kaffeekasse/api/hiwi_tracker/HiwiTrackerScraper.kt b/app/src/main/java/net/novagamestudios/kaffeekasse/api/hiwi_tracker/HiwiTrackerScraper.kt index e17ba275a0e2b9dfcb3ca12d6ae64e0caad13edf..8fb656fdc607e86b049f0ea5cbc2621f02528170 100644 --- a/app/src/main/java/net/novagamestudios/kaffeekasse/api/hiwi_tracker/HiwiTrackerScraper.kt +++ b/app/src/main/java/net/novagamestudios/kaffeekasse/api/hiwi_tracker/HiwiTrackerScraper.kt @@ -3,7 +3,7 @@ package net.novagamestudios.kaffeekasse.api.hiwi_tracker import io.ktor.http.URLBuilder import io.ktor.http.parameters import kotlinx.datetime.format -import net.novagamestudios.kaffeekasse.api.PortalClient +import net.novagamestudios.kaffeekasse.api.portal.PortalClient import net.novagamestudios.kaffeekasse.model.hiwi_tracker.WorkEntry class HiwiTrackerScraper( diff --git a/app/src/main/java/net/novagamestudios/kaffeekasse/api/hiwi_tracker/MonthDataResponse.kt b/app/src/main/java/net/novagamestudios/kaffeekasse/api/hiwi_tracker/model/MonthDataResponse.kt similarity index 95% rename from app/src/main/java/net/novagamestudios/kaffeekasse/api/hiwi_tracker/MonthDataResponse.kt rename to app/src/main/java/net/novagamestudios/kaffeekasse/api/hiwi_tracker/model/MonthDataResponse.kt index ecb791fb4247f6b1fa441adf7da384f7c6548b25..3b735e22345f0b4044e8c1a43fe601fc6293de0a 100644 --- a/app/src/main/java/net/novagamestudios/kaffeekasse/api/hiwi_tracker/MonthDataResponse.kt +++ b/app/src/main/java/net/novagamestudios/kaffeekasse/api/hiwi_tracker/model/MonthDataResponse.kt @@ -1,4 +1,4 @@ -package net.novagamestudios.kaffeekasse.api.hiwi_tracker +package net.novagamestudios.kaffeekasse.api.hiwi_tracker.model import kotlinx.serialization.KSerializer import kotlinx.serialization.SerialName @@ -8,9 +8,9 @@ import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor import kotlinx.serialization.descriptors.SerialDescriptor import kotlinx.serialization.encoding.Decoder import kotlinx.serialization.encoding.Encoder -import net.novagamestudios.kaffeekasse.api.PortalAPIResponse -import net.novagamestudios.kaffeekasse.model.ISODate -import net.novagamestudios.kaffeekasse.model.ISOTime +import net.novagamestudios.kaffeekasse.api.portal.model.PortalAPIResponse +import net.novagamestudios.kaffeekasse.model.date_time.ISODate +import net.novagamestudios.kaffeekasse.model.date_time.ISOTime import net.novagamestudios.kaffeekasse.model.hiwi_tracker.WorkEntry import kotlin.math.absoluteValue import kotlin.time.Duration diff --git a/app/src/main/java/net/novagamestudios/kaffeekasse/api/kaffeekasse/InfoResponse.kt b/app/src/main/java/net/novagamestudios/kaffeekasse/api/kaffeekasse/InfoResponse.kt deleted file mode 100644 index f9a69f582e9cd4cd24659b479c83606732457c5f..0000000000000000000000000000000000000000 --- a/app/src/main/java/net/novagamestudios/kaffeekasse/api/kaffeekasse/InfoResponse.kt +++ /dev/null @@ -1,94 +0,0 @@ -package net.novagamestudios.kaffeekasse.api.kaffeekasse - -import kotlinx.serialization.SerialName -import kotlinx.serialization.Serializable -import kotlinx.serialization.json.JsonArray -import kotlinx.serialization.json.JsonElement -import net.novagamestudios.kaffeekasse.model.kaffeekasse.PurchaseAccount -import net.novagamestudios.kaffeekasse.util.IntAsBooleanSerializer - -@Serializable -data class UserListResponse( - @SerialName("user_list") - val userList: List<BasicUserInfo> -) - -@Serializable -data class UserInfoResponse( - @SerialName("user_id") - override val id: Int, - @SerialName("name") - override val name: String, - @SerialName("balance") - override val balance: Double, - @SerialName("favorites") - override val favorites: JsonArray = JsonArray(emptyList()), - @SerialName("blacklist") - override val blacklist: List<BlackWhiteListUserInfo>? = null, - @SerialName("whitelist") - override val whitelist: List<BlackWhiteListUserInfo>? = null -) : ExtendedUserInfo - -sealed interface APIPurchaseAccount : PurchaseAccount - -sealed interface ExtendedUserInfo : APIPurchaseAccount { - override val id: Int - override val name: String - val balance: Double - val favorites: JsonArray - val blacklist: List<BlackWhiteListUserInfo>? - val whitelist: List<BlackWhiteListUserInfo>? -} - -@Serializable -data class BlackWhiteListUserInfo( - @SerialName("target_id") - override val id: Int, - @SerialName("name") - override val name: String -) : APIPurchaseAccount - -@Serializable -data class BasicUserInfo( - @SerialName("id") - override val id: Int, - @SerialName("name") - override val name: String, - @SerialName("empty_pin") - val noPinSet: @Serializable(with = IntAsBooleanSerializer::class) Boolean? = null -) : APIPurchaseAccount { - val firstName by lazy { name.split(", ")[1] } - val lastName by lazy { name.split(", ")[0] } -} - -@Serializable -data class ItemListResponse( - @SerialName("item_list") - val itemList: List<Item> -) { - @Serializable - data class Item( - @SerialName("item_id") - val id: Int, - @SerialName("name") - val originalName: String, - val gtin: String? = null, - val price: Double, - @SerialName("image_url") - val imageUrl: String? = null, - val sort: Int, - @SerialName("sort_p") - val sortP: Double, - @SerialName("itemtype_id") - val itemTypeId: ItemTypeId, - val enabled: @Serializable(with = IntAsBooleanSerializer::class) Boolean, - @SerialName("has_condition_reports") - val hasConditionReports: JsonElement - ) -} - -@Serializable -@JvmInline -value class ItemTypeId(val id: Int) - - diff --git a/app/src/main/java/net/novagamestudios/kaffeekasse/api/kaffeekasse/KaffeekasseAPI.kt b/app/src/main/java/net/novagamestudios/kaffeekasse/api/kaffeekasse/KaffeekasseAPI.kt index 0ebeeef0df74b0279fa263b0f4c0792a2cc490e5..8e8d1767ed7315d71e32616eef0c59a7b902aa4e 100644 --- a/app/src/main/java/net/novagamestudios/kaffeekasse/api/kaffeekasse/KaffeekasseAPI.kt +++ b/app/src/main/java/net/novagamestudios/kaffeekasse/api/kaffeekasse/KaffeekasseAPI.kt @@ -6,8 +6,17 @@ import io.ktor.util.sha1 import net.novagamestudios.common_utils.Logger import net.novagamestudios.common_utils.debug import net.novagamestudios.common_utils.error -import net.novagamestudios.kaffeekasse.api.PortalClient -import net.novagamestudios.kaffeekasse.api.kaffeekasse.KaffeekasseAPIResponse.Error.Code as ErrorCode +import net.novagamestudios.kaffeekasse.api.portal.PortalClient +import net.novagamestudios.kaffeekasse.api.kaffeekasse.model.ItemListResponse +import net.novagamestudios.kaffeekasse.api.kaffeekasse.model.KaffeekasseAPIResponse +import net.novagamestudios.kaffeekasse.api.kaffeekasse.model.LoggedInUserResponse +import net.novagamestudios.kaffeekasse.api.kaffeekasse.model.LoginDeviceResponse +import net.novagamestudios.kaffeekasse.api.kaffeekasse.model.LoginUserResponse +import net.novagamestudios.kaffeekasse.api.kaffeekasse.model.LogoutUserResponse +import net.novagamestudios.kaffeekasse.api.kaffeekasse.model.PurchaseResponse +import net.novagamestudios.kaffeekasse.api.kaffeekasse.model.UserInfoResponse +import net.novagamestudios.kaffeekasse.api.kaffeekasse.model.UserListResponse +import net.novagamestudios.kaffeekasse.api.kaffeekasse.model.KaffeekasseAPIResponse.Error.Code as ErrorCode class KaffeekasseAPI( client: PortalClient @@ -72,9 +81,9 @@ class KaffeekasseAPI( listOf("user_id" to "$userId") ) - suspend fun itemList(itemTypeId: ItemTypeId? = null) = invokeFunction<ItemListResponse>( + suspend fun itemList(itemTypeId: Int? = null) = invokeFunction<ItemListResponse>( name = "item_list", - listOfNotNull(itemTypeId?.let { "item_type_id" to "${it.id}" }) + listOfNotNull(itemTypeId?.let { "item_type_id" to "$it" }) ) diff --git a/app/src/main/java/net/novagamestudios/kaffeekasse/api/kaffeekasse/KaffeekasseScraper.kt b/app/src/main/java/net/novagamestudios/kaffeekasse/api/kaffeekasse/KaffeekasseScraper.kt index f277aded50c200900bdeb3f10ba0eec783f18f86..aa790757b56d0d8347f908aae51f7658565e5c4c 100644 --- a/app/src/main/java/net/novagamestudios/kaffeekasse/api/kaffeekasse/KaffeekasseScraper.kt +++ b/app/src/main/java/net/novagamestudios/kaffeekasse/api/kaffeekasse/KaffeekasseScraper.kt @@ -13,10 +13,9 @@ import it.skrape.selects.html5.table import it.skrape.selects.html5.td import it.skrape.selects.html5.tr import net.novagamestudios.common_utils.info -import net.novagamestudios.kaffeekasse.api.PortalClient +import net.novagamestudios.kaffeekasse.api.portal.PortalClient import net.novagamestudios.kaffeekasse.model.kaffeekasse.Cart import net.novagamestudios.kaffeekasse.model.kaffeekasse.KnownItem -import net.novagamestudios.kaffeekasse.model.kaffeekasse.KnownItemGroup import net.novagamestudios.kaffeekasse.model.kaffeekasse.ManualBillDetails import net.novagamestudios.kaffeekasse.model.kaffeekasse.Transaction import net.novagamestudios.kaffeekasse.model.kaffeekasse.isEmpty diff --git a/app/src/main/java/net/novagamestudios/kaffeekasse/api/kaffeekasse/model/APIPurchaseAccount.kt b/app/src/main/java/net/novagamestudios/kaffeekasse/api/kaffeekasse/model/APIPurchaseAccount.kt new file mode 100644 index 0000000000000000000000000000000000000000..d1a4905a827a08678b7de54575997f1235d8d3ec --- /dev/null +++ b/app/src/main/java/net/novagamestudios/kaffeekasse/api/kaffeekasse/model/APIPurchaseAccount.kt @@ -0,0 +1,5 @@ +package net.novagamestudios.kaffeekasse.api.kaffeekasse.model + +import net.novagamestudios.kaffeekasse.model.kaffeekasse.PurchaseAccount + +sealed interface APIPurchaseAccount : PurchaseAccount \ No newline at end of file diff --git a/app/src/main/java/net/novagamestudios/kaffeekasse/api/kaffeekasse/model/BasicUserInfo.kt b/app/src/main/java/net/novagamestudios/kaffeekasse/api/kaffeekasse/model/BasicUserInfo.kt new file mode 100644 index 0000000000000000000000000000000000000000..ce8efcd77dacc21c1a7ed1f9bd4dba36f0a7ae79 --- /dev/null +++ b/app/src/main/java/net/novagamestudios/kaffeekasse/api/kaffeekasse/model/BasicUserInfo.kt @@ -0,0 +1,18 @@ +package net.novagamestudios.kaffeekasse.api.kaffeekasse.model + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable +import net.novagamestudios.kaffeekasse.util.IntAsBooleanSerializer + +@Serializable +data class BasicUserInfo( + @SerialName("id") + override val id: Int, + @SerialName("name") + override val name: String, + @SerialName("empty_pin") + val noPinSet: @Serializable(with = IntAsBooleanSerializer::class) Boolean? = null +) : APIPurchaseAccount { + val firstName by lazy { name.split(", ")[1] } + val lastName by lazy { name.split(", ")[0] } +} \ No newline at end of file diff --git a/app/src/main/java/net/novagamestudios/kaffeekasse/api/kaffeekasse/model/BlackWhiteListUserInfo.kt b/app/src/main/java/net/novagamestudios/kaffeekasse/api/kaffeekasse/model/BlackWhiteListUserInfo.kt new file mode 100644 index 0000000000000000000000000000000000000000..cb98eaee42a6b1b559a12d149ca18f25d7d1cf07 --- /dev/null +++ b/app/src/main/java/net/novagamestudios/kaffeekasse/api/kaffeekasse/model/BlackWhiteListUserInfo.kt @@ -0,0 +1,12 @@ +package net.novagamestudios.kaffeekasse.api.kaffeekasse.model + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class BlackWhiteListUserInfo( + @SerialName("target_id") + override val id: Int, + @SerialName("name") + override val name: String +) : APIPurchaseAccount \ No newline at end of file diff --git a/app/src/main/java/net/novagamestudios/kaffeekasse/api/kaffeekasse/model/ItemListResponse.kt b/app/src/main/java/net/novagamestudios/kaffeekasse/api/kaffeekasse/model/ItemListResponse.kt new file mode 100644 index 0000000000000000000000000000000000000000..6960eb3b2a2b9624719b51d7ddf9c36e683a3891 --- /dev/null +++ b/app/src/main/java/net/novagamestudios/kaffeekasse/api/kaffeekasse/model/ItemListResponse.kt @@ -0,0 +1,32 @@ +package net.novagamestudios.kaffeekasse.api.kaffeekasse.model + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable +import kotlinx.serialization.json.JsonElement +import net.novagamestudios.kaffeekasse.util.IntAsBooleanSerializer + +@Serializable +data class ItemListResponse( + @SerialName("item_list") + val itemList: List<Item> +) { + @Serializable + data class Item( + @SerialName("item_id") + val id: Int, + @SerialName("name") + val originalName: String, + val gtin: String? = null, + val price: Double, + @SerialName("image_url") + val imageUrl: String? = null, + val sort: Int, + @SerialName("sort_p") + val sortP: Double, + @SerialName("itemtype_id") + val itemTypeId: Int, + val enabled: @Serializable(with = IntAsBooleanSerializer::class) Boolean, + @SerialName("has_condition_reports") + val hasConditionReports: JsonElement + ) +} \ No newline at end of file diff --git a/app/src/main/java/net/novagamestudios/kaffeekasse/api/kaffeekasse/KaffeekasseAPIResponse.kt b/app/src/main/java/net/novagamestudios/kaffeekasse/api/kaffeekasse/model/KaffeekasseAPIResponse.kt similarity index 89% rename from app/src/main/java/net/novagamestudios/kaffeekasse/api/kaffeekasse/KaffeekasseAPIResponse.kt rename to app/src/main/java/net/novagamestudios/kaffeekasse/api/kaffeekasse/model/KaffeekasseAPIResponse.kt index 7e291701335160ac6e3f02545c9c1174dd42803f..ec300f9d0f65a4f085c931623ccbf38bdca89eda 100644 --- a/app/src/main/java/net/novagamestudios/kaffeekasse/api/kaffeekasse/KaffeekasseAPIResponse.kt +++ b/app/src/main/java/net/novagamestudios/kaffeekasse/api/kaffeekasse/model/KaffeekasseAPIResponse.kt @@ -1,7 +1,7 @@ -package net.novagamestudios.kaffeekasse.api.kaffeekasse +package net.novagamestudios.kaffeekasse.api.kaffeekasse.model import kotlinx.serialization.Serializable -import net.novagamestudios.kaffeekasse.api.PortalAPIResponse +import net.novagamestudios.kaffeekasse.api.portal.model.PortalAPIResponse @Serializable diff --git a/app/src/main/java/net/novagamestudios/kaffeekasse/api/kaffeekasse/LoggedInUserResponse.kt b/app/src/main/java/net/novagamestudios/kaffeekasse/api/kaffeekasse/model/LoggedInUserResponse.kt similarity index 86% rename from app/src/main/java/net/novagamestudios/kaffeekasse/api/kaffeekasse/LoggedInUserResponse.kt rename to app/src/main/java/net/novagamestudios/kaffeekasse/api/kaffeekasse/model/LoggedInUserResponse.kt index b2e9b9f1d0a2ab8a5bfd066fa21981adf5fc062b..fd24ec875f6c7c375eab3bf442d0a8a8a62932a0 100644 --- a/app/src/main/java/net/novagamestudios/kaffeekasse/api/kaffeekasse/LoggedInUserResponse.kt +++ b/app/src/main/java/net/novagamestudios/kaffeekasse/api/kaffeekasse/model/LoggedInUserResponse.kt @@ -1,8 +1,8 @@ -package net.novagamestudios.kaffeekasse.api.kaffeekasse +package net.novagamestudios.kaffeekasse.api.kaffeekasse.model import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable -import net.novagamestudios.kaffeekasse.api.PortalAPIResponse +import net.novagamestudios.kaffeekasse.api.portal.model.PortalAPIResponse @Serializable diff --git a/app/src/main/java/net/novagamestudios/kaffeekasse/api/kaffeekasse/LoginDeviceResponse.kt b/app/src/main/java/net/novagamestudios/kaffeekasse/api/kaffeekasse/model/LoginDeviceResponse.kt similarity index 81% rename from app/src/main/java/net/novagamestudios/kaffeekasse/api/kaffeekasse/LoginDeviceResponse.kt rename to app/src/main/java/net/novagamestudios/kaffeekasse/api/kaffeekasse/model/LoginDeviceResponse.kt index 067bf6ad51dfdb2a74114f7a7b04c1b43f8f2f90..b1fc40956494a25a05226e4ce35adb78ac45de0c 100644 --- a/app/src/main/java/net/novagamestudios/kaffeekasse/api/kaffeekasse/LoginDeviceResponse.kt +++ b/app/src/main/java/net/novagamestudios/kaffeekasse/api/kaffeekasse/model/LoginDeviceResponse.kt @@ -1,4 +1,4 @@ -package net.novagamestudios.kaffeekasse.api.kaffeekasse +package net.novagamestudios.kaffeekasse.api.kaffeekasse.model import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable diff --git a/app/src/main/java/net/novagamestudios/kaffeekasse/api/kaffeekasse/LoginUserResponse.kt b/app/src/main/java/net/novagamestudios/kaffeekasse/api/kaffeekasse/model/LoginUserResponse.kt similarity index 74% rename from app/src/main/java/net/novagamestudios/kaffeekasse/api/kaffeekasse/LoginUserResponse.kt rename to app/src/main/java/net/novagamestudios/kaffeekasse/api/kaffeekasse/model/LoginUserResponse.kt index 554cb5c31c9988bc1394e88abe28cd2f4f0a2906..19e763274d09e122016c716a58d86d360595f38b 100644 --- a/app/src/main/java/net/novagamestudios/kaffeekasse/api/kaffeekasse/LoginUserResponse.kt +++ b/app/src/main/java/net/novagamestudios/kaffeekasse/api/kaffeekasse/model/LoginUserResponse.kt @@ -1,4 +1,4 @@ -package net.novagamestudios.kaffeekasse.api.kaffeekasse +package net.novagamestudios.kaffeekasse.api.kaffeekasse.model import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable diff --git a/app/src/main/java/net/novagamestudios/kaffeekasse/api/kaffeekasse/LogoutUserResponse.kt b/app/src/main/java/net/novagamestudios/kaffeekasse/api/kaffeekasse/model/LogoutUserResponse.kt similarity index 56% rename from app/src/main/java/net/novagamestudios/kaffeekasse/api/kaffeekasse/LogoutUserResponse.kt rename to app/src/main/java/net/novagamestudios/kaffeekasse/api/kaffeekasse/model/LogoutUserResponse.kt index 5c9929b258c666caeef6675d95c89e3cdd922e65..6dfc8e632bf98c69bd06ccf7ec6f5a5d7d605420 100644 --- a/app/src/main/java/net/novagamestudios/kaffeekasse/api/kaffeekasse/LogoutUserResponse.kt +++ b/app/src/main/java/net/novagamestudios/kaffeekasse/api/kaffeekasse/model/LogoutUserResponse.kt @@ -1,4 +1,4 @@ -package net.novagamestudios.kaffeekasse.api.kaffeekasse +package net.novagamestudios.kaffeekasse.api.kaffeekasse.model import kotlinx.serialization.Serializable diff --git a/app/src/main/java/net/novagamestudios/kaffeekasse/api/kaffeekasse/PurchaseResponse.kt b/app/src/main/java/net/novagamestudios/kaffeekasse/api/kaffeekasse/model/PurchaseResponse.kt similarity index 57% rename from app/src/main/java/net/novagamestudios/kaffeekasse/api/kaffeekasse/PurchaseResponse.kt rename to app/src/main/java/net/novagamestudios/kaffeekasse/api/kaffeekasse/model/PurchaseResponse.kt index 30d56bbd9d65718d21a57f421ee632b2a3d6a4ef..803abc8d9349456be1e70aad5b4dc4ca729d01aa 100644 --- a/app/src/main/java/net/novagamestudios/kaffeekasse/api/kaffeekasse/PurchaseResponse.kt +++ b/app/src/main/java/net/novagamestudios/kaffeekasse/api/kaffeekasse/model/PurchaseResponse.kt @@ -1,4 +1,4 @@ -package net.novagamestudios.kaffeekasse.api.kaffeekasse +package net.novagamestudios.kaffeekasse.api.kaffeekasse.model import kotlinx.serialization.Serializable diff --git a/app/src/main/java/net/novagamestudios/kaffeekasse/api/kaffeekasse/model/UserInfoResponse.kt b/app/src/main/java/net/novagamestudios/kaffeekasse/api/kaffeekasse/model/UserInfoResponse.kt new file mode 100644 index 0000000000000000000000000000000000000000..3ef3fbbe0e5ae2a9d83117045a47ebee1d6078ad --- /dev/null +++ b/app/src/main/java/net/novagamestudios/kaffeekasse/api/kaffeekasse/model/UserInfoResponse.kt @@ -0,0 +1,31 @@ +package net.novagamestudios.kaffeekasse.api.kaffeekasse.model + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable +import kotlinx.serialization.json.JsonArray + +@Serializable +data class UserInfoResponse( + @SerialName("user_id") + override val id: Int, + @SerialName("name") + override val name: String, + @SerialName("balance") + override val balance: Double, + @SerialName("favorites") + override val favorites: JsonArray = JsonArray(emptyList()), + @SerialName("blacklist") + override val blacklist: List<BlackWhiteListUserInfo>? = null, + @SerialName("whitelist") + override val whitelist: List<BlackWhiteListUserInfo>? = null +) : ExtendedUserInfo + +sealed interface ExtendedUserInfo : APIPurchaseAccount { + override val id: Int + override val name: String + val balance: Double + val favorites: JsonArray + val blacklist: List<BlackWhiteListUserInfo>? + val whitelist: List<BlackWhiteListUserInfo>? +} + diff --git a/app/src/main/java/net/novagamestudios/kaffeekasse/api/kaffeekasse/model/UserListResponse.kt b/app/src/main/java/net/novagamestudios/kaffeekasse/api/kaffeekasse/model/UserListResponse.kt new file mode 100644 index 0000000000000000000000000000000000000000..61a49462c5db46ea7f8b59135f951adb8109a642 --- /dev/null +++ b/app/src/main/java/net/novagamestudios/kaffeekasse/api/kaffeekasse/model/UserListResponse.kt @@ -0,0 +1,10 @@ +package net.novagamestudios.kaffeekasse.api.kaffeekasse.model + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class UserListResponse( + @SerialName("user_list") + val userList: List<BasicUserInfo> +) \ No newline at end of file diff --git a/app/src/main/java/net/novagamestudios/kaffeekasse/api/PortalClient.kt b/app/src/main/java/net/novagamestudios/kaffeekasse/api/portal/PortalClient.kt similarity index 94% rename from app/src/main/java/net/novagamestudios/kaffeekasse/api/PortalClient.kt rename to app/src/main/java/net/novagamestudios/kaffeekasse/api/portal/PortalClient.kt index 7eb335ec5ac1d33e52b949b20da4031e3a4959b9..4922e8c8c86e285552ce73f1c32e6ac867988b7c 100644 --- a/app/src/main/java/net/novagamestudios/kaffeekasse/api/PortalClient.kt +++ b/app/src/main/java/net/novagamestudios/kaffeekasse/api/portal/PortalClient.kt @@ -1,4 +1,4 @@ -package net.novagamestudios.kaffeekasse.api +package net.novagamestudios.kaffeekasse.api.portal import androidx.compose.runtime.mutableStateListOf import io.ktor.client.HttpClient @@ -22,6 +22,7 @@ import it.skrape.core.htmlDocument import it.skrape.selects.Doc import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.newCoroutineContext @@ -36,8 +37,9 @@ import net.novagamestudios.common_utils.error import net.novagamestudios.common_utils.info import net.novagamestudios.common_utils.verbose import net.novagamestudios.common_utils.warn -import net.novagamestudios.kaffeekasse.model.Login -import net.novagamestudios.kaffeekasse.model.isValid +import net.novagamestudios.kaffeekasse.api.portal.model.PortalAPIResponse +import net.novagamestudios.kaffeekasse.model.credentials.Login +import net.novagamestudios.kaffeekasse.model.credentials.isValid import net.novagamestudios.kaffeekasse.util.MutableCookiesStorage class PortalClient( @@ -45,6 +47,7 @@ class PortalClient( ) : Logger { private val baseUrl = Url("https://embedded.rwth-aachen.de") + @OptIn(ExperimentalCoroutinesApi::class) private val computationScope = coroutineScope.newCoroutineContext(Dispatchers.IO) private val jsonFormat by lazy { diff --git a/app/src/main/java/net/novagamestudios/kaffeekasse/api/PortalAPIResponse.kt b/app/src/main/java/net/novagamestudios/kaffeekasse/api/portal/model/PortalAPIResponse.kt similarity index 89% rename from app/src/main/java/net/novagamestudios/kaffeekasse/api/PortalAPIResponse.kt rename to app/src/main/java/net/novagamestudios/kaffeekasse/api/portal/model/PortalAPIResponse.kt index 8320ed75f1fd5304ebda957bb1a286db2beb7234..9bf63519a877f27e5109a47cef26f66c14164d28 100644 --- a/app/src/main/java/net/novagamestudios/kaffeekasse/api/PortalAPIResponse.kt +++ b/app/src/main/java/net/novagamestudios/kaffeekasse/api/portal/model/PortalAPIResponse.kt @@ -1,10 +1,10 @@ -package net.novagamestudios.kaffeekasse.api +package net.novagamestudios.kaffeekasse.api.portal.model import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import kotlinx.serialization.json.JsonElement import kotlinx.serialization.json.JsonNull -import net.novagamestudios.kaffeekasse.model.User +import net.novagamestudios.kaffeekasse.model.credentials.User @Serializable open class PortalAPIResponse { diff --git a/app/src/main/java/net/novagamestudios/kaffeekasse/gitlab/GitLabPackage.kt b/app/src/main/java/net/novagamestudios/kaffeekasse/gitlab/GitLabPackage.kt index 0c4163c11cc0b0ebadd1293220f9f360d5ca42ce..45c037a8b8ad6e10baea06482784391e29883139 100644 --- a/app/src/main/java/net/novagamestudios/kaffeekasse/gitlab/GitLabPackage.kt +++ b/app/src/main/java/net/novagamestudios/kaffeekasse/gitlab/GitLabPackage.kt @@ -2,8 +2,8 @@ package net.novagamestudios.kaffeekasse.gitlab import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable -import net.novagamestudios.kaffeekasse.model.AppVersion -import net.novagamestudios.kaffeekasse.model.ISODateTime +import net.novagamestudios.kaffeekasse.model.app.AppVersion +import net.novagamestudios.kaffeekasse.model.date_time.ISODateTime @Serializable data class GitLabPackage( diff --git a/app/src/main/java/net/novagamestudios/kaffeekasse/gitlab/GitLabPackageFile.kt b/app/src/main/java/net/novagamestudios/kaffeekasse/gitlab/GitLabPackageFile.kt index ae0f0106a6d663219c04c404e060ba78d3cec54c..0a61324dd15b4e7a76e81479beae3ed26fa9099d 100644 --- a/app/src/main/java/net/novagamestudios/kaffeekasse/gitlab/GitLabPackageFile.kt +++ b/app/src/main/java/net/novagamestudios/kaffeekasse/gitlab/GitLabPackageFile.kt @@ -2,7 +2,7 @@ package net.novagamestudios.kaffeekasse.gitlab import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable -import net.novagamestudios.kaffeekasse.model.ISODateTime +import net.novagamestudios.kaffeekasse.model.date_time.ISODateTime @Serializable data class GitLabPackageFile( diff --git a/app/src/main/java/net/novagamestudios/kaffeekasse/gitlab/GitLabRelease.kt b/app/src/main/java/net/novagamestudios/kaffeekasse/gitlab/GitLabRelease.kt index e411c6688472b839a49c9b9e8f96106a1a8f83f0..40aea1f5f07a7ae236f747e84ae11928656b4826 100644 --- a/app/src/main/java/net/novagamestudios/kaffeekasse/gitlab/GitLabRelease.kt +++ b/app/src/main/java/net/novagamestudios/kaffeekasse/gitlab/GitLabRelease.kt @@ -2,8 +2,8 @@ package net.novagamestudios.kaffeekasse.gitlab import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable -import net.novagamestudios.kaffeekasse.model.AppVersion -import net.novagamestudios.kaffeekasse.model.ISODateTime +import net.novagamestudios.kaffeekasse.model.app.AppVersion +import net.novagamestudios.kaffeekasse.model.date_time.ISODateTime @Serializable data class GitLabRelease( diff --git a/app/src/main/java/net/novagamestudios/kaffeekasse/model/ISODateTime.kt b/app/src/main/java/net/novagamestudios/kaffeekasse/model/ISODateTime.kt deleted file mode 100644 index 9453fb24a1a5d5253218ad969a6ece135d0691f6..0000000000000000000000000000000000000000 --- a/app/src/main/java/net/novagamestudios/kaffeekasse/model/ISODateTime.kt +++ /dev/null @@ -1,72 +0,0 @@ -package net.novagamestudios.kaffeekasse.model - -import kotlinx.datetime.LocalDate -import kotlinx.datetime.LocalDateTime -import kotlinx.datetime.LocalTime -import kotlinx.datetime.toJavaLocalDate -import kotlinx.datetime.toJavaLocalDateTime -import kotlinx.datetime.toJavaLocalTime -import kotlinx.datetime.toKotlinLocalDate -import kotlinx.datetime.toKotlinLocalDateTime -import kotlinx.datetime.toKotlinLocalTime -import kotlinx.serialization.KSerializer -import kotlinx.serialization.Serializable -import kotlinx.serialization.descriptors.PrimitiveKind -import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor -import kotlinx.serialization.descriptors.SerialDescriptor -import kotlinx.serialization.encoding.Decoder -import kotlinx.serialization.encoding.Encoder -import java.time.format.DateTimeFormatter -import java.time.LocalDate as JavaLocalDate -import java.time.LocalDateTime as JavaLocalDateTime -import java.time.LocalTime as JavaLocalTime - -typealias ISODateTime = @Serializable(with = ISODateTimeSerializer::class) LocalDateTime -class ISODateTimeSerializer : KSerializer<LocalDateTime> { - private val formatter = DateTimeFormatter.ISO_OFFSET_DATE_TIME!! - override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("ISODateTime", PrimitiveKind.STRING) - override fun serialize(encoder: Encoder, value: LocalDateTime) { - encoder.encodeString(value.format(formatter)) - } - override fun deserialize(decoder: Decoder): LocalDateTime { - return LocalDateTime.parse(decoder.decodeString(), formatter) - } -} - -typealias ISODate = @Serializable(with = ISODateSerializer::class) LocalDate -class ISODateSerializer : KSerializer<LocalDate> { - private val formatter = DateTimeFormatter.ISO_DATE!! - override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("ISODate", PrimitiveKind.STRING) - override fun serialize(encoder: Encoder, value: LocalDate) { - encoder.encodeString(value.format(formatter)) - } - override fun deserialize(decoder: Decoder): LocalDate { - return LocalDate.parse(decoder.decodeString(), formatter) - } -} - -typealias ISOTime = @Serializable(with = ISOTimeSerializer::class) LocalTime -class ISOTimeSerializer : KSerializer<LocalTime> { - private val formatter = DateTimeFormatter.ISO_TIME!! - override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("ISOTime", PrimitiveKind.STRING) - override fun serialize(encoder: Encoder, value: LocalTime) { - encoder.encodeString(value.format(formatter)) - } - override fun deserialize(decoder: Decoder): LocalTime { - val string = decoder.decodeString() - if (string.startsWith("24:")) return JavaLocalTime.MAX.toKotlinLocalTime() - return LocalTime.parse(string, formatter) - } -} - - -fun LocalDateTime.format(formatter: DateTimeFormatter) = formatter.format(toJavaLocalDateTime())!! -fun LocalDateTime.Companion.parse(input: CharSequence, formatter: DateTimeFormatter) = JavaLocalDateTime.parse(input, formatter).toKotlinLocalDateTime() - -fun LocalDate.format(formatter: DateTimeFormatter) = formatter.format(toJavaLocalDate())!! -fun LocalDate.Companion.parse(input: CharSequence, formatter: DateTimeFormatter) = JavaLocalDate.parse(input, formatter).toKotlinLocalDate() - -fun LocalTime.format(formatter: DateTimeFormatter) = formatter.format(toJavaLocalTime())!! -fun LocalTime.Companion.parse(input: CharSequence, formatter: DateTimeFormatter) = JavaLocalTime.parse(input, formatter).toKotlinLocalTime() - - diff --git a/app/src/main/java/net/novagamestudios/kaffeekasse/model/User.kt b/app/src/main/java/net/novagamestudios/kaffeekasse/model/User.kt deleted file mode 100644 index 380684f0a79bd47692e0bc457d6b8edeef3208cb..0000000000000000000000000000000000000000 --- a/app/src/main/java/net/novagamestudios/kaffeekasse/model/User.kt +++ /dev/null @@ -1,19 +0,0 @@ -package net.novagamestudios.kaffeekasse.model - -import net.novagamestudios.kaffeekasse.model.kaffeekasse.KnownItemGroup - -data class User( - val user: String? = null, - val displayName: String? = null -) - - -val User?.isKaffeekasse get() = this != null && user == "kaffeekasse" -val User?.isUser get() = this != null && !isKaffeekasse - -data class Device( - val name: String?, - val itemTypeId: Int? -) { - val knownItemGroup by lazy { itemTypeId?.let { KnownItemGroup.byId[it] } } -} diff --git a/app/src/main/java/net/novagamestudios/kaffeekasse/model/AppRelease.kt b/app/src/main/java/net/novagamestudios/kaffeekasse/model/app/AppRelease.kt similarity index 79% rename from app/src/main/java/net/novagamestudios/kaffeekasse/model/AppRelease.kt rename to app/src/main/java/net/novagamestudios/kaffeekasse/model/app/AppRelease.kt index 3cd0de2be8b683006afaf4e2d9159e6f33c2e68b..838384ee9bb33c99dec7b1eadecd79f0b5528cc3 100644 --- a/app/src/main/java/net/novagamestudios/kaffeekasse/model/AppRelease.kt +++ b/app/src/main/java/net/novagamestudios/kaffeekasse/model/app/AppRelease.kt @@ -1,4 +1,4 @@ -package net.novagamestudios.kaffeekasse.model +package net.novagamestudios.kaffeekasse.model.app import kotlinx.datetime.LocalDateTime diff --git a/app/src/main/java/net/novagamestudios/kaffeekasse/model/AppVersion.kt b/app/src/main/java/net/novagamestudios/kaffeekasse/model/app/AppVersion.kt similarity index 95% rename from app/src/main/java/net/novagamestudios/kaffeekasse/model/AppVersion.kt rename to app/src/main/java/net/novagamestudios/kaffeekasse/model/app/AppVersion.kt index f361c6d7f95052c07f8fd1d99554c7b12cb85966..dba08060809986bc560b5e0dac0593281ed49332 100644 --- a/app/src/main/java/net/novagamestudios/kaffeekasse/model/AppVersion.kt +++ b/app/src/main/java/net/novagamestudios/kaffeekasse/model/app/AppVersion.kt @@ -1,4 +1,4 @@ -package net.novagamestudios.kaffeekasse.model +package net.novagamestudios.kaffeekasse.model.app import kotlinx.serialization.Serializable import net.novagamestudios.kaffeekasse.BuildConfig diff --git a/app/src/main/java/net/novagamestudios/kaffeekasse/model/credentials/Device.kt b/app/src/main/java/net/novagamestudios/kaffeekasse/model/credentials/Device.kt new file mode 100644 index 0000000000000000000000000000000000000000..0954f5a832aab8963cfbaa262d1c99f70cdcae8d --- /dev/null +++ b/app/src/main/java/net/novagamestudios/kaffeekasse/model/credentials/Device.kt @@ -0,0 +1,10 @@ +package net.novagamestudios.kaffeekasse.model.credentials + +import net.novagamestudios.kaffeekasse.model.kaffeekasse.KnownItemGroup + +data class Device( + val name: String?, + val itemTypeId: Int? +) { + val knownItemGroup by lazy { itemTypeId?.let { KnownItemGroup.byId[it] } } +} \ No newline at end of file diff --git a/app/src/main/java/net/novagamestudios/kaffeekasse/model/DeviceCredentials.kt b/app/src/main/java/net/novagamestudios/kaffeekasse/model/credentials/DeviceCredentials.kt similarity index 62% rename from app/src/main/java/net/novagamestudios/kaffeekasse/model/DeviceCredentials.kt rename to app/src/main/java/net/novagamestudios/kaffeekasse/model/credentials/DeviceCredentials.kt index cb49dbaf5b9627eda8d3f86b6f5506354911adaa..9cda0b69708fb799c84733739ae926550553a579 100644 --- a/app/src/main/java/net/novagamestudios/kaffeekasse/model/DeviceCredentials.kt +++ b/app/src/main/java/net/novagamestudios/kaffeekasse/model/credentials/DeviceCredentials.kt @@ -1,4 +1,4 @@ -package net.novagamestudios.kaffeekasse.model +package net.novagamestudios.kaffeekasse.model.credentials import kotlinx.serialization.Serializable @@ -12,4 +12,3 @@ data class DeviceCredentials( } } -val DeviceCredentials.isValid get() = deviceId.isNotBlank() && apiKey.isNotBlank() diff --git a/app/src/main/java/net/novagamestudios/kaffeekasse/model/credentials/Extensions.kt b/app/src/main/java/net/novagamestudios/kaffeekasse/model/credentials/Extensions.kt new file mode 100644 index 0000000000000000000000000000000000000000..801695db8b2be55f071a2c870bba1711011ade38 --- /dev/null +++ b/app/src/main/java/net/novagamestudios/kaffeekasse/model/credentials/Extensions.kt @@ -0,0 +1,8 @@ +package net.novagamestudios.kaffeekasse.model.credentials + +val User?.isKaffeekasse get() = this != null && user == "kaffeekasse" +val User?.isUser get() = this != null && !isKaffeekasse + +val Login.isValid get() = username.isNotBlank() && password.isNotBlank() + +val DeviceCredentials.isValid get() = deviceId.isNotBlank() && apiKey.isNotBlank() diff --git a/app/src/main/java/net/novagamestudios/kaffeekasse/model/Login.kt b/app/src/main/java/net/novagamestudios/kaffeekasse/model/credentials/Login.kt similarity index 62% rename from app/src/main/java/net/novagamestudios/kaffeekasse/model/Login.kt rename to app/src/main/java/net/novagamestudios/kaffeekasse/model/credentials/Login.kt index 893b4fcd0609f5710e6dc553f6fa437b88426289..d80b1e088f01d968ab7b2993e0902698b0047b8f 100644 --- a/app/src/main/java/net/novagamestudios/kaffeekasse/model/Login.kt +++ b/app/src/main/java/net/novagamestudios/kaffeekasse/model/credentials/Login.kt @@ -1,4 +1,4 @@ -package net.novagamestudios.kaffeekasse.model +package net.novagamestudios.kaffeekasse.model.credentials import kotlinx.serialization.Serializable @@ -12,4 +12,3 @@ data class Login( } } -val Login.isValid get() = username.isNotBlank() && password.isNotBlank() diff --git a/app/src/main/java/net/novagamestudios/kaffeekasse/model/credentials/User.kt b/app/src/main/java/net/novagamestudios/kaffeekasse/model/credentials/User.kt new file mode 100644 index 0000000000000000000000000000000000000000..9c5b6006bad107994b7d9992fbe0c5dfb6a6010c --- /dev/null +++ b/app/src/main/java/net/novagamestudios/kaffeekasse/model/credentials/User.kt @@ -0,0 +1,7 @@ +package net.novagamestudios.kaffeekasse.model.credentials + +data class User( + val user: String? = null, + val displayName: String? = null +) + diff --git a/app/src/main/java/net/novagamestudios/kaffeekasse/model/date_time/Extensions.kt b/app/src/main/java/net/novagamestudios/kaffeekasse/model/date_time/Extensions.kt new file mode 100644 index 0000000000000000000000000000000000000000..ff09f5eaa799b8a7404d93b914c55684030088de --- /dev/null +++ b/app/src/main/java/net/novagamestudios/kaffeekasse/model/date_time/Extensions.kt @@ -0,0 +1,32 @@ +package net.novagamestudios.kaffeekasse.model.date_time + +import kotlinx.datetime.LocalDate +import kotlinx.datetime.LocalDateTime +import kotlinx.datetime.LocalTime +import kotlinx.datetime.toJavaLocalDate +import kotlinx.datetime.toJavaLocalDateTime +import kotlinx.datetime.toJavaLocalTime +import kotlinx.datetime.toKotlinLocalDate +import kotlinx.datetime.toKotlinLocalDateTime +import kotlinx.datetime.toKotlinLocalTime +import java.time.format.DateTimeFormatter +import java.time.LocalDate as JavaLocalDate +import java.time.LocalDateTime as JavaLocalDateTime +import java.time.LocalTime as JavaLocalTime + +fun LocalDateTime.format(formatter: DateTimeFormatter) = formatter.format(toJavaLocalDateTime())!! +fun LocalDateTime.Companion.parse(input: CharSequence, formatter: DateTimeFormatter) = JavaLocalDateTime.parse( + input, + formatter +).toKotlinLocalDateTime() +fun LocalDate.format(formatter: DateTimeFormatter) = formatter.format(toJavaLocalDate())!! +fun LocalDate.Companion.parse(input: CharSequence, formatter: DateTimeFormatter) = JavaLocalDate.parse( + input, + formatter +).toKotlinLocalDate() + +fun LocalTime.format(formatter: DateTimeFormatter) = formatter.format(toJavaLocalTime())!! +fun LocalTime.Companion.parse(input: CharSequence, formatter: DateTimeFormatter) = JavaLocalTime.parse( + input, + formatter +).toKotlinLocalTime() \ No newline at end of file diff --git a/app/src/main/java/net/novagamestudios/kaffeekasse/model/date_time/ISODate.kt b/app/src/main/java/net/novagamestudios/kaffeekasse/model/date_time/ISODate.kt new file mode 100644 index 0000000000000000000000000000000000000000..d1ac06f590f4731869586b7d2184cc8b8cfda63e --- /dev/null +++ b/app/src/main/java/net/novagamestudios/kaffeekasse/model/date_time/ISODate.kt @@ -0,0 +1,7 @@ +package net.novagamestudios.kaffeekasse.model.date_time + +import kotlinx.datetime.LocalDate +import kotlinx.serialization.Serializable +import net.novagamestudios.kaffeekasse.model.date_time.serializers.ISODateSerializer + +typealias ISODate = @Serializable(with = ISODateSerializer::class) LocalDate \ No newline at end of file diff --git a/app/src/main/java/net/novagamestudios/kaffeekasse/model/date_time/ISODateTime.kt b/app/src/main/java/net/novagamestudios/kaffeekasse/model/date_time/ISODateTime.kt new file mode 100644 index 0000000000000000000000000000000000000000..b1b601e751d74617deb9f2ccefe7e004644370ba --- /dev/null +++ b/app/src/main/java/net/novagamestudios/kaffeekasse/model/date_time/ISODateTime.kt @@ -0,0 +1,7 @@ +package net.novagamestudios.kaffeekasse.model.date_time + +import kotlinx.datetime.LocalDateTime +import kotlinx.serialization.Serializable +import net.novagamestudios.kaffeekasse.model.date_time.serializers.ISODateTimeSerializer + +typealias ISODateTime = @Serializable(with = ISODateTimeSerializer::class) LocalDateTime \ No newline at end of file diff --git a/app/src/main/java/net/novagamestudios/kaffeekasse/model/date_time/ISOTime.kt b/app/src/main/java/net/novagamestudios/kaffeekasse/model/date_time/ISOTime.kt new file mode 100644 index 0000000000000000000000000000000000000000..8973362d4cdbb77726f9031df708e364b49292cf --- /dev/null +++ b/app/src/main/java/net/novagamestudios/kaffeekasse/model/date_time/ISOTime.kt @@ -0,0 +1,7 @@ +package net.novagamestudios.kaffeekasse.model.date_time + +import kotlinx.datetime.LocalTime +import kotlinx.serialization.Serializable +import net.novagamestudios.kaffeekasse.model.date_time.serializers.ISOTimeSerializer + +typealias ISOTime = @Serializable(with = ISOTimeSerializer::class) LocalTime \ No newline at end of file diff --git a/app/src/main/java/net/novagamestudios/kaffeekasse/model/date_time/serializers/ISODateSerializer.kt b/app/src/main/java/net/novagamestudios/kaffeekasse/model/date_time/serializers/ISODateSerializer.kt new file mode 100644 index 0000000000000000000000000000000000000000..121066f973f8bfe307ad978e27af63284f53179b --- /dev/null +++ b/app/src/main/java/net/novagamestudios/kaffeekasse/model/date_time/serializers/ISODateSerializer.kt @@ -0,0 +1,24 @@ +package net.novagamestudios.kaffeekasse.model.date_time.serializers + +import kotlinx.datetime.LocalDate +import kotlinx.serialization.KSerializer +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.descriptors.SerialDescriptor +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import net.novagamestudios.kaffeekasse.model.date_time.format +import net.novagamestudios.kaffeekasse.model.date_time.parse +import java.time.format.DateTimeFormatter + +class ISODateSerializer : KSerializer<LocalDate> { + private val formatter = DateTimeFormatter.ISO_DATE!! + override val descriptor: SerialDescriptor = + PrimitiveSerialDescriptor("ISODate", PrimitiveKind.STRING) + override fun serialize(encoder: Encoder, value: LocalDate) { + encoder.encodeString(value.format(formatter)) + } + override fun deserialize(decoder: Decoder): LocalDate { + return LocalDate.parse(decoder.decodeString(), formatter) + } +} \ No newline at end of file diff --git a/app/src/main/java/net/novagamestudios/kaffeekasse/model/date_time/serializers/ISODateTimeSerializer.kt b/app/src/main/java/net/novagamestudios/kaffeekasse/model/date_time/serializers/ISODateTimeSerializer.kt new file mode 100644 index 0000000000000000000000000000000000000000..5e73613acbf18137149f11552d71afa8ce8c818b --- /dev/null +++ b/app/src/main/java/net/novagamestudios/kaffeekasse/model/date_time/serializers/ISODateTimeSerializer.kt @@ -0,0 +1,24 @@ +package net.novagamestudios.kaffeekasse.model.date_time.serializers + +import kotlinx.datetime.LocalDateTime +import kotlinx.serialization.KSerializer +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.descriptors.SerialDescriptor +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import net.novagamestudios.kaffeekasse.model.date_time.format +import net.novagamestudios.kaffeekasse.model.date_time.parse +import java.time.format.DateTimeFormatter + +class ISODateTimeSerializer : KSerializer<LocalDateTime> { + private val formatter = DateTimeFormatter.ISO_OFFSET_DATE_TIME!! + override val descriptor: SerialDescriptor = + PrimitiveSerialDescriptor("ISODateTime", PrimitiveKind.STRING) + override fun serialize(encoder: Encoder, value: LocalDateTime) { + encoder.encodeString(value.format(formatter)) + } + override fun deserialize(decoder: Decoder): LocalDateTime { + return LocalDateTime.parse(decoder.decodeString(), formatter) + } +} \ No newline at end of file diff --git a/app/src/main/java/net/novagamestudios/kaffeekasse/model/date_time/serializers/ISOTimeSerializer.kt b/app/src/main/java/net/novagamestudios/kaffeekasse/model/date_time/serializers/ISOTimeSerializer.kt new file mode 100644 index 0000000000000000000000000000000000000000..f48b7e374d1caffe403164a1cf1632f823d8d870 --- /dev/null +++ b/app/src/main/java/net/novagamestudios/kaffeekasse/model/date_time/serializers/ISOTimeSerializer.kt @@ -0,0 +1,28 @@ +package net.novagamestudios.kaffeekasse.model.date_time.serializers + +import kotlinx.datetime.LocalTime +import kotlinx.datetime.toKotlinLocalTime +import kotlinx.serialization.KSerializer +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.descriptors.SerialDescriptor +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import net.novagamestudios.kaffeekasse.model.date_time.format +import net.novagamestudios.kaffeekasse.model.date_time.parse +import java.time.format.DateTimeFormatter +import java.time.LocalTime as JavaLocalTime + +class ISOTimeSerializer : KSerializer<LocalTime> { + private val formatter = DateTimeFormatter.ISO_TIME!! + override val descriptor: SerialDescriptor = + PrimitiveSerialDescriptor("ISOTime", PrimitiveKind.STRING) + override fun serialize(encoder: Encoder, value: LocalTime) { + encoder.encodeString(value.format(formatter)) + } + override fun deserialize(decoder: Decoder): LocalTime { + val string = decoder.decodeString() + if (string.startsWith("24:")) return JavaLocalTime.MAX.toKotlinLocalTime() + return LocalTime.parse(string, formatter) + } +} \ No newline at end of file diff --git a/app/src/main/java/net/novagamestudios/kaffeekasse/model/kaffeekasse/Account.kt b/app/src/main/java/net/novagamestudios/kaffeekasse/model/kaffeekasse/Account.kt index e5643f4b084510cbf03fe974b75c81683abad424..4c350c095e0d61e941c3525c73a4717027fea3a1 100644 --- a/app/src/main/java/net/novagamestudios/kaffeekasse/model/kaffeekasse/Account.kt +++ b/app/src/main/java/net/novagamestudios/kaffeekasse/model/kaffeekasse/Account.kt @@ -9,9 +9,4 @@ data class Account( val deposited: Double ) -interface PurchaseAccount { - val id: Int - val name: String -} - diff --git a/app/src/main/java/net/novagamestudios/kaffeekasse/model/kaffeekasse/Items.kt b/app/src/main/java/net/novagamestudios/kaffeekasse/model/kaffeekasse/Item.kt similarity index 58% rename from app/src/main/java/net/novagamestudios/kaffeekasse/model/kaffeekasse/Items.kt rename to app/src/main/java/net/novagamestudios/kaffeekasse/model/kaffeekasse/Item.kt index 0a35f2c19e260c9ba2224f4de2af2153482999f7..1fe9f976eb048b7234c8038ba34448e1fcf03702 100644 --- a/app/src/main/java/net/novagamestudios/kaffeekasse/model/kaffeekasse/Items.kt +++ b/app/src/main/java/net/novagamestudios/kaffeekasse/model/kaffeekasse/Item.kt @@ -18,29 +18,3 @@ interface Item { val imageDrawable: Int? val imageUrl: String? } - - -enum class ItemCategory { - ColdBeverage, - HotBeverage, - Snack, - IceCream, - Food, - Fruit, - Other -} - - -interface ItemGroup { - val id: Int? - val originalName: String? - - val name: String - val items: List<Item> -} - - -interface Stock { - val itemGroups: List<ItemGroup> -} - diff --git a/app/src/main/java/net/novagamestudios/kaffeekasse/model/kaffeekasse/ItemCategory.kt b/app/src/main/java/net/novagamestudios/kaffeekasse/model/kaffeekasse/ItemCategory.kt new file mode 100644 index 0000000000000000000000000000000000000000..87c888c40759c86987b03fb4b20144d701651711 --- /dev/null +++ b/app/src/main/java/net/novagamestudios/kaffeekasse/model/kaffeekasse/ItemCategory.kt @@ -0,0 +1,11 @@ +package net.novagamestudios.kaffeekasse.model.kaffeekasse + +enum class ItemCategory { + ColdBeverage, + HotBeverage, + Snack, + IceCream, + Food, + Fruit, + Other +} \ No newline at end of file diff --git a/app/src/main/java/net/novagamestudios/kaffeekasse/model/kaffeekasse/ItemGroup.kt b/app/src/main/java/net/novagamestudios/kaffeekasse/model/kaffeekasse/ItemGroup.kt new file mode 100644 index 0000000000000000000000000000000000000000..06b72db8920a7e63586e54b1166ca9f6796b2a6d --- /dev/null +++ b/app/src/main/java/net/novagamestudios/kaffeekasse/model/kaffeekasse/ItemGroup.kt @@ -0,0 +1,9 @@ +package net.novagamestudios.kaffeekasse.model.kaffeekasse + +interface ItemGroup { + val id: Int? + val originalName: String? + + val name: String + val items: List<Item> +} \ No newline at end of file diff --git a/app/src/main/java/net/novagamestudios/kaffeekasse/model/kaffeekasse/KnownItem.kt b/app/src/main/java/net/novagamestudios/kaffeekasse/model/kaffeekasse/KnownItem.kt index 5209680dacd49da7dbeb8c293f6bd2618d9a1ea8..35f502543207f0ecd9b4c48b601e8be21e5ef990 100644 --- a/app/src/main/java/net/novagamestudios/kaffeekasse/model/kaffeekasse/KnownItem.kt +++ b/app/src/main/java/net/novagamestudios/kaffeekasse/model/kaffeekasse/KnownItem.kt @@ -3,86 +3,6 @@ package net.novagamestudios.kaffeekasse.model.kaffeekasse import kotlinx.serialization.Serializable -/* -KaffeekasseManualTransactionDetails( - accounts=[ - Account(name=Broeckmann, Jonas, id=339, isDefault=true) - ], - itemGroups=[ - ItemGroup( - name=Küche, - items=[ - Item(name=Almdudler, id=221), - Item(name=Bier (0,33L auch alk.frei–außer Leffe/Erdinger), id=110), - Item(name=Bier (0,5 L) auch alk.frei - kein Erdinger-, id=80), - Item(name=Café au lait, id=163), - Item(name=Cappuccino, id=159), - Item(name=Club-Mate, id=108), - Item(name=Coca Cola (hi-carb), id=77), - Item(name=Coke ZERO, id=78), - Item(name=Coke Zero koffeinfrei, id=246), - Item(name=Duplex Farbe, id=155), - Item(name=Chouffe Bier, id=262), - Item(name=Duplex S/W, id=91), - Item(name=Eifler Landbier, id=192), - Item(name=Eis: Cuja Mara Split, id=170), - Item(name=Eis: Magnum / NUII, id=124), - Item(name=Engelbert Apfel, id=127), - Item(name=Engelbert Naturell, id=240), - Item(name=Engelbert/Rheinfels Sprudel, id=79), - Item(name=Erdinger Alkoholfrei (0,5l), id=242), - Item(name=Erdnüsse, id=87), - Item(name=Espresso, id=160), - Item(name=Fanta, id=81), - Item(name=Fassbrause/Bionade, id=199), - Item(name=Gerolsteiner, id=83), - Item(name=Hanuta, id=209), - Item(name=Haribo-Beutel, id=149), - Item(name=Kaffee klein, id=84), - Item(name=Kaffee groß, id=165), - Item(name=Erdinger Alkoholfrei (0.33l), id=261), - Item(name=Knoppers Riegel, id=214), - Item(name=Latte Macchiato, id=161), - Item(name=Leffe, id=191), - Item(name=Milka, id=152), - Item(name=Moccachoc, id=162), - Item(name=Pizza, id=243), - Item(name=Rockstar/Monster (inkl. Pfand), id=187), - Item(name=Schoko-Creme (Kakao), id=164), - Item(name=Simplex Farbe, id=140), - Item(name=Simplex S/W, id=90), - Item(name=Taschentücher, id=158), - Item(name=Apfel, id=195), - Item(name=Balisto, id=105), - Item(name=Duplo, id=231), - Item(name=Eis: Cornetto, id=128), - Item(name=Eis: Nogger, id=101), - Item(name=Oreo Kekse, id=235), - Item(name=CocaCola 0,5l GLAS, id=265), - Item(name=Trolli, id=249), - Item(name=Twix, id=93), - Item(name=Yogurette, id=217), - Item(name=Kinder Schokolade, id=220), - Item(name=Nuts Royal Nüsse, id=227), - Item(name=Mandarine/Clementine, id=213), - Item(name=Milch (Maschine), id=263) - ] - ), - ItemGroup( - name=Getränkeraum, - items=[ - Item(name=MioMio Mate, id=259) - ] - ), ItemGroup( - name=Farbdrucker, - items=[ - Item(name=3D-Druck pro gramm, id=256), - Item(name=Euglüh, id=173) - ] - ) - ] -) -*/ @Serializable enum class KnownItem( val id: Int, @@ -164,18 +84,3 @@ enum class KnownItem( } } - -enum class KnownItemGroup( - val id: Int, - val originalName: String -) { - Kueche (5, "Küche"), - Getraenkeraum(6, "Getränkeraum"), - Farbdrucker (7, "Farbdrucker"), - ; - companion object { - val byId by lazy { entries.associateBy { it.id } } - val byOriginalName by lazy { entries.associateBy { it.originalName } } - } -} - diff --git a/app/src/main/java/net/novagamestudios/kaffeekasse/model/kaffeekasse/KnownItemGroup.kt b/app/src/main/java/net/novagamestudios/kaffeekasse/model/kaffeekasse/KnownItemGroup.kt new file mode 100644 index 0000000000000000000000000000000000000000..a82fa956552905808f638a490716b5274e63434e --- /dev/null +++ b/app/src/main/java/net/novagamestudios/kaffeekasse/model/kaffeekasse/KnownItemGroup.kt @@ -0,0 +1,15 @@ +package net.novagamestudios.kaffeekasse.model.kaffeekasse + +enum class KnownItemGroup( + val id: Int, + val originalName: String +) { + Kueche (5, "Küche"), + Getraenkeraum(6, "Getränkeraum"), + Farbdrucker (7, "Farbdrucker"), + ; + companion object { + val byId by lazy { entries.associateBy { it.id } } + val byOriginalName by lazy { entries.associateBy { it.originalName } } + } +} \ No newline at end of file diff --git a/app/src/main/java/net/novagamestudios/kaffeekasse/model/kaffeekasse/PurchaseAccount.kt b/app/src/main/java/net/novagamestudios/kaffeekasse/model/kaffeekasse/PurchaseAccount.kt new file mode 100644 index 0000000000000000000000000000000000000000..ffc199cc07122ffa66d126f21a5f4c9f1cd9c590 --- /dev/null +++ b/app/src/main/java/net/novagamestudios/kaffeekasse/model/kaffeekasse/PurchaseAccount.kt @@ -0,0 +1,6 @@ +package net.novagamestudios.kaffeekasse.model.kaffeekasse + +interface PurchaseAccount { + val id: Int + val name: String +} \ No newline at end of file diff --git a/app/src/main/java/net/novagamestudios/kaffeekasse/model/kaffeekasse/Stock.kt b/app/src/main/java/net/novagamestudios/kaffeekasse/model/kaffeekasse/Stock.kt new file mode 100644 index 0000000000000000000000000000000000000000..c27179bcf395bbc2071b671f19084bf93c3bfc9b --- /dev/null +++ b/app/src/main/java/net/novagamestudios/kaffeekasse/model/kaffeekasse/Stock.kt @@ -0,0 +1,5 @@ +package net.novagamestudios.kaffeekasse.model.kaffeekasse + +interface Stock { + val itemGroups: List<ItemGroup> +} \ No newline at end of file diff --git a/app/src/main/java/net/novagamestudios/kaffeekasse/repositories/Credentials.kt b/app/src/main/java/net/novagamestudios/kaffeekasse/repositories/Credentials.kt index 6168113e4c899a595f37a660cbb91e18f317b58d..4a35b181a8081411b5835aa085eeb66db3246a10 100644 --- a/app/src/main/java/net/novagamestudios/kaffeekasse/repositories/Credentials.kt +++ b/app/src/main/java/net/novagamestudios/kaffeekasse/repositories/Credentials.kt @@ -17,8 +17,8 @@ import net.novagamestudios.common_utils.error import net.novagamestudios.common_utils.info import net.novagamestudios.common_utils.toastShort import net.novagamestudios.kaffeekasse.BuildConfig -import net.novagamestudios.kaffeekasse.model.DeviceCredentials -import net.novagamestudios.kaffeekasse.model.Login +import net.novagamestudios.kaffeekasse.model.credentials.DeviceCredentials +import net.novagamestudios.kaffeekasse.model.credentials.Login class Credentials( private val credentialManager: CredentialManager, diff --git a/app/src/main/java/net/novagamestudios/kaffeekasse/repositories/I11Client.kt b/app/src/main/java/net/novagamestudios/kaffeekasse/repositories/I11Client.kt deleted file mode 100644 index f11fa5802ada84ef1d011a56977cee3d772779da..0000000000000000000000000000000000000000 --- a/app/src/main/java/net/novagamestudios/kaffeekasse/repositories/I11Client.kt +++ /dev/null @@ -1,464 +0,0 @@ -package net.novagamestudios.kaffeekasse.repositories - -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateListOf -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.setValue -import io.ktor.client.HttpClient -import io.ktor.client.call.body -import io.ktor.client.plugins.contentnegotiation.ContentNegotiation -import io.ktor.client.plugins.cookies.HttpCookies -import io.ktor.client.plugins.cookies.cookies -import io.ktor.client.request.HttpRequestBuilder -import io.ktor.client.request.forms.submitForm -import io.ktor.client.statement.HttpResponse -import io.ktor.http.ContentType -import io.ktor.http.Cookie -import io.ktor.http.Parameters -import io.ktor.http.URLBuilder -import io.ktor.http.Url -import io.ktor.http.parameters -import io.ktor.http.renderCookieHeader -import io.ktor.serialization.kotlinx.json.json -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.newCoroutineContext -import kotlinx.serialization.json.Json -import net.novagamestudios.common_utils.Logger -import net.novagamestudios.common_utils.debug -import net.novagamestudios.common_utils.info -import net.novagamestudios.kaffeekasse.api.PortalAPIResponse -import net.novagamestudios.kaffeekasse.model.Login -import net.novagamestudios.kaffeekasse.model.isValid -import net.novagamestudios.kaffeekasse.util.MutableCookiesStorage -import net.novagamestudios.kaffeekasse.util.isExpired - - -@Deprecated("Use PortalRepository instead") -class I11Client( - coroutineScope: CoroutineScope -) : Logger { - - private val computationScope = coroutineScope.newCoroutineContext(Dispatchers.IO) - - private val cookiesStorage by lazy { MutableCookiesStorage(mutableStateListOf()) } - private val client = HttpClient { - install(HttpCookies) { - storage = cookiesStorage - } - install(ContentNegotiation) { - json( - Json { - prettyPrint = true - isLenient = true - ignoreUnknownKeys = true - }, - contentType = ContentType.Text.Any // Uses "text/json" - ) - } - } - - - val portal = Portal() -// val kaffeekasse = Kaffeekasse() -// val hiwiTracker = HiwiTracker() - - private val modules: List<Module<*>> = listOf(portal) - - - private var lastTriedLogin: Login? = null - private var session by mutableStateOf<Session?>(null) - var loginErrors by mutableStateOf<List<String>?>(null) - private set - val isLoggedIn get() = session != null - - private suspend fun performLogin(login: Login): Session { - debug { "performing login" } - if (!login.isValid) throw IllegalArgumentException("Invalid login") - lastTriedLogin = login - session = null - loginErrors = null - modules.forEach { it.invalidateData() } - info { "logging in as ${login.username}" } - portal.fetchData(parameters { - append("username", login.username) - append("password", login.password) - append("login", "") - }) - val response = portal.jsonData.value - val sessionCookie = client.cookies(portal.baseUrl) - .firstOrNull { it.name == SessionCookieName && !it.isExpired } - if (response == null || !response.session.isLoggedIn || sessionCookie == null) { - debug { "login failed" } - modules.forEach { it.invalidateData() } - loginErrors = response?.errors ?: emptyList() - throw IllegalStateException("Login failed") - } - debug { "login successful" } - return Session(sessionCookie).also { session = it } - } - - suspend fun login(login: Login) { - debug { "login" } - if (!login.isValid) throw IllegalArgumentException("Invalid login") - if (login == lastTriedLogin && isLoggedIn) return - performLogin(login) - } - suspend fun logout() { - debug { "logout" } - lastTriedLogin = null - session = null - loginErrors = null - modules.forEach { it.invalidateData() } - } - private suspend fun requireSession(): Session = session?.takeIf { it.isValid } ?: performLogin( - lastTriedLogin ?: throw IllegalStateException("Not logged in and no login credentials provided") - ) - private data class Session( - private val sessionCookie: Cookie - ) { - val isValid get() = !sessionCookie.isExpired - context(HttpRequestBuilder) - fun apply() { - headers["Cookie"] = renderCookieHeader(sessionCookie) - } - } - - - companion object { - private const val SessionCookieName = "PORTALSESSID" - } - - - abstract inner class Module<T>( - val baseUrl: Url - ) { - val isLoggedIn get() = this@I11Client.isLoggedIn - - protected val jsonUrl = URLBuilder(baseUrl).apply { - parameters["json"] = "" - }.build() - - val jsonData = MutableStateFlow<T?>(null) - var jsonDataDirty by mutableStateOf(false) - protected set - - suspend fun fetchData(formParameters: Parameters = Parameters.Empty) { - val session = if ("login" in formParameters) null else requireSession() - val response = client.submitForm( - url = "$jsonUrl", - formParameters = formParameters - ) { - session?.apply() - } - jsonData.value = response.toData() - jsonDataDirty = false - } - protected abstract suspend fun HttpResponse.toData(): T - - open suspend fun invalidateData() { - cookiesStorage.clear(baseUrl) - jsonData.value = null - } - } - - inner class Portal : Module<PortalAPIResponse>(Url("https://portal.embedded.rwth-aachen.de")) { - override suspend fun HttpResponse.toData(): PortalAPIResponse { - return body<PortalAPIResponse>() - } - } -// @Serializable -// private data class I11PortalDataImpl( -// override val session: PortalAPIResponse.Session, -// override val infos: List<String>, -// override val warnings: List<String>, -// override val errors: List<String>, -// override val navigation: JsonElement, -// @SerialName("ajaxui") -// override val ajaxUI: PortalAPIResponse.AjaxUI? = null -// ) : PortalAPIResponse - - /*inner class Kaffeekasse : Module<KaffeekasseData>(Url("https://kaffeekasse.embedded.rwth-aachen.de")) { - val manuaBillUrl = URLBuilder(baseUrl).apply { - parameters["manualbill"] = "" - }.build() - val transactionsUrl = URLBuilder(baseUrl).apply { - parameters["balance"] = "" - }.build() - - val manualBillDetails = MutableStateFlow<ManualBillDetails?>(null) - val transactions = MutableStateFlow<List<Transaction>?>(null) - - var manualBillDetailsDirty by mutableStateOf(false) - private set - var transactionsDirty by mutableStateOf(false) - private set - - override suspend fun HttpResponse.toData(): KaffeekasseData { - return body<KaffeekasseData>() - } - - override suspend fun invalidateData() { - super.invalidateData() - manualBillDetails.value = null - transactions.value = null - } - - suspend fun fetchManualBillDetails() = withContext(computationScope) { - val session = requireSession() - val response = client.get(manuaBillUrl) { - session.apply() - } - manualBillDetails.value = htmlDocument(response.bodyAsText()) { - scrapeManualBillDetails() - } - manualBillDetailsDirty = false - } - - suspend fun fetchTransactions() { - val session = requireSession() - val response = client.get(transactionsUrl) { - session.apply() - } - transactions.value = htmlDocument(response.bodyAsText()) { - scrapeTransactions() - } - transactionsDirty = false - } - - suspend fun submitCart(account: Account, cart: Cart) { - if (cart.isEmpty()) return - val session = requireSession() - client.submitForm( - url = "$manuaBillUrl", - formParameters = parameters { - cart.forEach { (item, count) -> - info { "adding @ $account : $item x $count" } - append("tdata[account_id][]", account.id) - append("tdata[item_id][]", item.id) - append("tdata[item_count][]", "$count") - append("manualbill", "") - append("lockedfrom", "1") - } - } - ) { - session.apply() - } - jsonDataDirty = true - manualBillDetailsDirty = true - transactionsDirty = true - } - - private fun Doc.scrapeManualBillDetails(): ManualBillDetails = form { - table { - val accounts = select { - withId = "manual_account_id" - option { - findAll { - mapNotNull { option -> - if (option.hasAttribute("disabled")) null - else if (option.attribute("value").isBlank()) null - else Account( - name = option.text, - id = option.attribute("value"), - isDefault = option.attribute("selected") == "selected" - ) - } - } - } - } - val groups = select { - withId = "manual_item_id" - option { - findAll { - val groups = mutableListOf<ItemGroup>() - var currentGroup: String? = null - var currentItems = mutableListOf<Item>() - for (option in this) { - if (option.hasAttribute("disabled")) { - if (currentGroup != null) { - groups += ItemGroup( - currentGroup, - currentItems - ) - } - currentGroup = option.text - currentItems = mutableListOf() - } else if (option.attribute("value").isBlank()) continue - else { - val id = option.attribute("value") - val name = option.text - val knownItems = KnownItem.byId[id] - if (knownItems != null) knownItems.forEach { - currentItems += Item( - name = name, - id = id, - knownItem = it - ) - } else { - currentItems += Item( - name = option.text, - id = id - ) - } - } - } - if (currentGroup != null) { - groups += ItemGroup( - currentGroup, - currentItems - ) - } - groups - } - } - } - ManualBillDetails(accounts, groups) - } - } - - private fun Doc.scrapeTransactions(): List<Transaction> = table { - withClass = "transactions" - tr { - findAll { - mapNotNull { row -> - if (row.children.any { it.tagName == "th" }) return@mapNotNull null - row.scrapeTransactionRow() - } - } - } - } - private fun String.euros() = removeSuffix("€").toDouble() - private fun DocElement.scrapeTransactionRow(): Transaction? = td { - findAll { - if (size != 7) return@findAll null - // Example: 2024-02-26 13:05:21 - val dateTime = LocalDateTime.parse( - this[0].text.trim(), - DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss") - ) - val payer = this[1].text.trim().takeUnless { it == "-" } - val payee = this[2].text.trim() - val purpose = this[3].text.parseTransactionPurpose() - val total = this[4].text.trim().euros() - val newBalance = this[5].text.trim().euros() - val refundId = this[6].a { attribute("href") }.substringAfterLast("=") - Transaction( - date = dateTime, - payer = payer, - payee = payee, - purpose = purpose, - total = total, - newBalance = newBalance, - refundId = refundId - ) - } - } - private fun String.parseTransactionPurpose(): Transaction.Purpose { - val trimmed = trim() - return when (trimmed.lowercase()) { - "einzahlung" -> Transaction.Purpose.Deposit - else -> { - val match = "([0-9]+)x (.+) à (-?[0-9.]+€?)".toRegex().matchEntire(trimmed) - ?: return Transaction.Purpose.Other(trimmed) - val (count, itemName, unitPrice) = match.destructured - Transaction.Purpose.Purchase(itemName, count, unitPrice.euros()) - } - } - } - }*/ - - - /*inner class HiwiTracker : Module<MonthDataResponse>(Url("https://hiwi.embedded.rwth-aachen.de")) { - - val dataByMonth = mutableStateMapOf<MonthKey, RichDataState<MonthDataResponse, List<String>>>() - - private val apiDateFormat = LocalDate.Format { - year() - char('-') - monthNumber() - char('-') - dayOfMonth() - } - private val apiTimeFormat = LocalTime.Format { - hour() - char(':') - minute() - } - private fun Duration.apiFormat() = toComponents { hours, minutes, _, _ -> - "%02d:%02d".format(hours, minutes) - } - - suspend fun fetchDataForMonth(month: MonthKey) { - val richDataState = dataByMonth.getOrPut(month) { RichDataState() } - richDataState.tryCalculate( - onError = { - warn(it) { "Error fetching data for $month" } - RichData.Error(emptyList()) - } - ) { - val session = requireSession() - val response = client.get(jsonUrl) { - session.apply() - parameter("selectdate", month.toLocalDate().format(apiDateFormat)) - } - RichData.Data(response.toData()) - } - } - - override suspend fun HttpResponse.toData(): MonthDataResponse { - try { - return body<MonthDataResponse>() - } catch (e: Throwable) { - val text = bodyAsText() - debug { text } - throw e - } - } - override suspend fun invalidateData() { - super.invalidateData() - dataByMonth.clear() - } - - suspend fun submitWorkEntry(workEntry: WorkEntry) { - if (!workEntry.isValid) return - val monthKey = workEntry.date.toMonthKey() - val session = requireSession() - client.submitForm( - url = "$baseUrl", - formParameters = parameters { - append("hw_date", workEntry.date.format(apiDateFormat)) - append("hw_begin", workEntry.begin.format(apiTimeFormat)) - append("hw_end", workEntry.end.format(apiTimeFormat)) - append("hw_breaktime", workEntry.breakDurationOrNull?.apiFormat() ?: "") - append("hw_note", workEntry.note) - append("savetimes", "") - } - ) { - session.apply() - } - jsonDataDirty = true - dataByMonth[monthKey]?.markDirty() - } - - suspend fun deleteWorkEntry(workEntryId: Int) { - val session = requireSession() - client.submitForm( - url = "$baseUrl", - formParameters = parameters { - append("deleteentry", "$workEntryId") - }, - encodeInQuery = true - ) { - session.apply() - } - jsonDataDirty = true - dataByMonth.values.forEach { it.markDirty() } - } - }*/ -} - - - - diff --git a/app/src/main/java/net/novagamestudios/kaffeekasse/repositories/Settings.kt b/app/src/main/java/net/novagamestudios/kaffeekasse/repositories/Settings.kt index b0b1778f745acede17b78ee3e2dbee0ac63122c7..8611ae09f30bae6d02326488eaa8293359b8adec 100644 --- a/app/src/main/java/net/novagamestudios/kaffeekasse/repositories/Settings.kt +++ b/app/src/main/java/net/novagamestudios/kaffeekasse/repositories/Settings.kt @@ -16,14 +16,14 @@ import net.novagamestudios.common_utils.compose.state.DataStoreState import net.novagamestudios.common_utils.compose.state.MutableDataStoreState import net.novagamestudios.common_utils.compose.state.rememberMockedDataStoreState import net.novagamestudios.common_utils.compose.state.stateIn -import net.novagamestudios.kaffeekasse.model.DeviceCredentials +import net.novagamestudios.kaffeekasse.model.credentials.DeviceCredentials import java.io.File @Serializable data class Settings( val themeMode: ThemeMode = ThemeMode.Dark, val autoLogin: Boolean = false, - @Deprecated("Use favoriteItemIds instead") + @Deprecated("Use favoriteItemIds instead", ReplaceWith("favoriteItemIds")) val favoriteItems: List<String> = emptyList(), val favoriteItemIds: List<Int> = favoriteItems.mapNotNull { it.toIntOrNull() }, val lastSelectedModule: String? = null, diff --git a/app/src/main/java/net/novagamestudios/kaffeekasse/repositories/UpdateController.kt b/app/src/main/java/net/novagamestudios/kaffeekasse/repositories/UpdateController.kt index 3f550fc612a20359b277665341071329385a1d72..fabf2ec5343be44e7a1376b8631f8641383611b0 100644 --- a/app/src/main/java/net/novagamestudios/kaffeekasse/repositories/UpdateController.kt +++ b/app/src/main/java/net/novagamestudios/kaffeekasse/repositories/UpdateController.kt @@ -18,7 +18,7 @@ import net.novagamestudios.common_utils.info import net.novagamestudios.kaffeekasse.App import net.novagamestudios.kaffeekasse.MainActivity import net.novagamestudios.kaffeekasse.UpdateReceiver -import net.novagamestudios.kaffeekasse.model.AppRelease +import net.novagamestudios.kaffeekasse.model.app.AppRelease import java.io.File import java.io.FileInputStream diff --git a/app/src/main/java/net/novagamestudios/kaffeekasse/repositories/HiwiTrackerRepository.kt b/app/src/main/java/net/novagamestudios/kaffeekasse/repositories/i11/HiwiTrackerRepository.kt similarity index 93% rename from app/src/main/java/net/novagamestudios/kaffeekasse/repositories/HiwiTrackerRepository.kt rename to app/src/main/java/net/novagamestudios/kaffeekasse/repositories/i11/HiwiTrackerRepository.kt index e121aa501a6b3cc236dd2f354b97f4af679b4ae1..21f151c64aee0fce26238c5657b57da29d68dd9d 100644 --- a/app/src/main/java/net/novagamestudios/kaffeekasse/repositories/HiwiTrackerRepository.kt +++ b/app/src/main/java/net/novagamestudios/kaffeekasse/repositories/i11/HiwiTrackerRepository.kt @@ -1,11 +1,11 @@ -package net.novagamestudios.kaffeekasse.repositories +package net.novagamestudios.kaffeekasse.repositories.i11 import kotlinx.coroutines.CoroutineScope import net.novagamestudios.common_utils.Logger import net.novagamestudios.common_utils.debug import net.novagamestudios.kaffeekasse.api.hiwi_tracker.HiwiTrackerAPI import net.novagamestudios.kaffeekasse.api.hiwi_tracker.HiwiTrackerScraper -import net.novagamestudios.kaffeekasse.api.hiwi_tracker.MonthDataResponse +import net.novagamestudios.kaffeekasse.api.hiwi_tracker.model.MonthDataResponse import net.novagamestudios.kaffeekasse.model.hiwi_tracker.MonthKey import net.novagamestudios.kaffeekasse.model.hiwi_tracker.MonthKey.Companion.toMonthKey import net.novagamestudios.kaffeekasse.model.hiwi_tracker.WorkEntry diff --git a/app/src/main/java/net/novagamestudios/kaffeekasse/repositories/KaffeekasseRepository.kt b/app/src/main/java/net/novagamestudios/kaffeekasse/repositories/i11/KaffeekasseRepository.kt similarity index 92% rename from app/src/main/java/net/novagamestudios/kaffeekasse/repositories/KaffeekasseRepository.kt rename to app/src/main/java/net/novagamestudios/kaffeekasse/repositories/i11/KaffeekasseRepository.kt index 34aad0d666cde9805df3fa04f676fab2eedd7f74..ee38cc77f1bd64b83f2fd1db5f4f02b7f850523d 100644 --- a/app/src/main/java/net/novagamestudios/kaffeekasse/repositories/KaffeekasseRepository.kt +++ b/app/src/main/java/net/novagamestudios/kaffeekasse/repositories/i11/KaffeekasseRepository.kt @@ -1,20 +1,20 @@ -package net.novagamestudios.kaffeekasse.repositories +package net.novagamestudios.kaffeekasse.repositories.i11 import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow import net.novagamestudios.common_utils.Logger -import net.novagamestudios.kaffeekasse.api.kaffeekasse.APIPurchaseAccount +import net.novagamestudios.kaffeekasse.api.kaffeekasse.model.APIPurchaseAccount import net.novagamestudios.kaffeekasse.api.kaffeekasse.KaffeekasseAPI import net.novagamestudios.kaffeekasse.api.kaffeekasse.KaffeekasseScraper -import net.novagamestudios.kaffeekasse.api.kaffeekasse.ExtendedUserInfo +import net.novagamestudios.kaffeekasse.api.kaffeekasse.model.ExtendedUserInfo import net.novagamestudios.kaffeekasse.data.category import net.novagamestudios.kaffeekasse.data.cleanName import net.novagamestudios.kaffeekasse.data.cleanProductName import net.novagamestudios.kaffeekasse.data.cleanVariantName import net.novagamestudios.kaffeekasse.data.drawableResource -import net.novagamestudios.kaffeekasse.model.Device -import net.novagamestudios.kaffeekasse.model.DeviceCredentials +import net.novagamestudios.kaffeekasse.model.credentials.Device +import net.novagamestudios.kaffeekasse.model.credentials.DeviceCredentials import net.novagamestudios.kaffeekasse.model.kaffeekasse.Account import net.novagamestudios.kaffeekasse.model.kaffeekasse.Cart import net.novagamestudios.kaffeekasse.model.kaffeekasse.Item @@ -83,9 +83,11 @@ class KaffeekasseRepository( val baseItemGroups = scraper.manualBillDetails().itemGroups progress(1f / 3f) - if (!isDeviceLoggedIn) return@RichDataSource RichData.Data(StockImpl( + if (!isDeviceLoggedIn) return@RichDataSource RichData.Data( + StockImpl( itemGroups = baseItemGroups - )) + ) + ) val itemGroupsById: Map<Int?, MutableItemGroup> = baseItemGroups.map { MutableItemGroup( @@ -102,7 +104,8 @@ class KaffeekasseRepository( val knownItems = KnownItem.byId[item.id]?.takeUnless { it.isEmpty() } if (knownItems == null) { // Unknown item - itemGroupsById[item.itemTypeId.id]?.items?.add(ItemImpl( + itemGroupsById[item.itemTypeId]?.items?.add( + ItemImpl( id = item.id, originalName = item.originalName, category = ItemCategory.Other, @@ -112,10 +115,12 @@ class KaffeekasseRepository( estimatedPrice = item.price, imageDrawable = null, imageUrl = item.imageUrl - )) + ) + ) } else knownItems.forEach { known -> // Combine with known values - itemGroupsById[item.itemTypeId.id]?.items?.add(ItemImpl( + itemGroupsById[item.itemTypeId]?.items?.add( + ItemImpl( id = item.id, originalName = item.originalName, category = known.category, @@ -125,7 +130,8 @@ class KaffeekasseRepository( estimatedPrice = item.price, imageDrawable = known.drawableResource, imageUrl = item.imageUrl - )) + ) + ) } } progress(3f / 3f) diff --git a/app/src/main/java/net/novagamestudios/kaffeekasse/repositories/PortalRepository.kt b/app/src/main/java/net/novagamestudios/kaffeekasse/repositories/i11/PortalRepository.kt similarity index 90% rename from app/src/main/java/net/novagamestudios/kaffeekasse/repositories/PortalRepository.kt rename to app/src/main/java/net/novagamestudios/kaffeekasse/repositories/i11/PortalRepository.kt index 51cbe57dc629878e059ec7ca5a7c4ad71c48425f..963cfd23d89f8ec73487ab6ae20f3caadc74c469 100644 --- a/app/src/main/java/net/novagamestudios/kaffeekasse/repositories/PortalRepository.kt +++ b/app/src/main/java/net/novagamestudios/kaffeekasse/repositories/i11/PortalRepository.kt @@ -1,11 +1,11 @@ -package net.novagamestudios.kaffeekasse.repositories +package net.novagamestudios.kaffeekasse.repositories.i11 import net.novagamestudios.common_utils.Logger import net.novagamestudios.common_utils.info -import net.novagamestudios.kaffeekasse.api.PortalClient +import net.novagamestudios.kaffeekasse.api.portal.PortalClient import net.novagamestudios.kaffeekasse.api.kaffeekasse.KaffeekasseAPI -import net.novagamestudios.kaffeekasse.model.Login -import net.novagamestudios.kaffeekasse.model.isUser +import net.novagamestudios.kaffeekasse.model.credentials.Login +import net.novagamestudios.kaffeekasse.model.credentials.isUser import net.novagamestudios.kaffeekasse.util.mapState diff --git a/app/src/main/java/net/novagamestudios/kaffeekasse/repositories/GitLabPackageReleases.kt b/app/src/main/java/net/novagamestudios/kaffeekasse/repositories/releases/GitLabPackageReleases.kt similarity index 89% rename from app/src/main/java/net/novagamestudios/kaffeekasse/repositories/GitLabPackageReleases.kt rename to app/src/main/java/net/novagamestudios/kaffeekasse/repositories/releases/GitLabPackageReleases.kt index cdfc38418fb0089c57390ce949aa060c7d9555ee..0c4189ebc1d4599d823b2313b392efa5015d1591 100644 --- a/app/src/main/java/net/novagamestudios/kaffeekasse/repositories/GitLabPackageReleases.kt +++ b/app/src/main/java/net/novagamestudios/kaffeekasse/repositories/releases/GitLabPackageReleases.kt @@ -1,4 +1,4 @@ -package net.novagamestudios.kaffeekasse.repositories +package net.novagamestudios.kaffeekasse.repositories.releases import kotlinx.coroutines.flow.MutableStateFlow import net.novagamestudios.common_utils.Logger @@ -7,8 +7,8 @@ import net.novagamestudios.common_utils.info import net.novagamestudios.kaffeekasse.gitlab.GitLab import net.novagamestudios.kaffeekasse.gitlab.GitLabPackage import net.novagamestudios.kaffeekasse.gitlab.GitLabPackageFile -import net.novagamestudios.kaffeekasse.model.AppRelease -import net.novagamestudios.kaffeekasse.model.AppVersion +import net.novagamestudios.kaffeekasse.model.app.AppRelease +import net.novagamestudios.kaffeekasse.model.app.AppVersion class GitLabPackageReleases( diff --git a/app/src/main/java/net/novagamestudios/kaffeekasse/repositories/GitLabReleases.kt b/app/src/main/java/net/novagamestudios/kaffeekasse/repositories/releases/GitLabReleases.kt similarity index 96% rename from app/src/main/java/net/novagamestudios/kaffeekasse/repositories/GitLabReleases.kt rename to app/src/main/java/net/novagamestudios/kaffeekasse/repositories/releases/GitLabReleases.kt index ed18a6e68e4c4e291bf6998b3de09ad9215ffd0d..970b65fda7a276ab743f56c0cfe3741f1e46e5f5 100644 --- a/app/src/main/java/net/novagamestudios/kaffeekasse/repositories/GitLabReleases.kt +++ b/app/src/main/java/net/novagamestudios/kaffeekasse/repositories/releases/GitLabReleases.kt @@ -1,12 +1,12 @@ -package net.novagamestudios.kaffeekasse.repositories +package net.novagamestudios.kaffeekasse.repositories.releases import kotlinx.coroutines.flow.MutableStateFlow import net.novagamestudios.common_utils.Logger import net.novagamestudios.common_utils.debug import net.novagamestudios.common_utils.info import net.novagamestudios.kaffeekasse.gitlab.GitLab -import net.novagamestudios.kaffeekasse.model.AppRelease -import net.novagamestudios.kaffeekasse.model.AppVersion +import net.novagamestudios.kaffeekasse.model.app.AppRelease +import net.novagamestudios.kaffeekasse.model.app.AppVersion class GitLabReleases( private val gitLab: GitLab diff --git a/app/src/main/java/net/novagamestudios/kaffeekasse/repositories/Releases.kt b/app/src/main/java/net/novagamestudios/kaffeekasse/repositories/releases/Releases.kt similarity index 58% rename from app/src/main/java/net/novagamestudios/kaffeekasse/repositories/Releases.kt rename to app/src/main/java/net/novagamestudios/kaffeekasse/repositories/releases/Releases.kt index ca5ba59be71b0ad375af3e464d19dca9abf2c2ab..8698e298d367bf95e809d6398bf665f30aa8ef95 100644 --- a/app/src/main/java/net/novagamestudios/kaffeekasse/repositories/Releases.kt +++ b/app/src/main/java/net/novagamestudios/kaffeekasse/repositories/releases/Releases.kt @@ -1,7 +1,7 @@ -package net.novagamestudios.kaffeekasse.repositories +package net.novagamestudios.kaffeekasse.repositories.releases import kotlinx.coroutines.flow.MutableStateFlow -import net.novagamestudios.kaffeekasse.model.AppRelease +import net.novagamestudios.kaffeekasse.model.app.AppRelease interface Releases { val newerReleases: MutableStateFlow<List<AppRelease>?> diff --git a/app/src/main/java/net/novagamestudios/kaffeekasse/ui/App.kt b/app/src/main/java/net/novagamestudios/kaffeekasse/ui/App.kt index 30d09652bc662d9c4cc53a0bced525d713d10b8f..48a307d23cfce72aa14392b2aae8e85d8bd07b14 100644 --- a/app/src/main/java/net/novagamestudios/kaffeekasse/ui/App.kt +++ b/app/src/main/java/net/novagamestudios/kaffeekasse/ui/App.kt @@ -68,9 +68,9 @@ import net.novagamestudios.kaffeekasse.AppModule import net.novagamestudios.kaffeekasse.AppModules import net.novagamestudios.kaffeekasse.HiwiTrackerModule import net.novagamestudios.kaffeekasse.KaffeekasseModule -import net.novagamestudios.kaffeekasse.model.isUser +import net.novagamestudios.kaffeekasse.model.credentials.isUser import net.novagamestudios.kaffeekasse.repositories.MutableSettingsStore -import net.novagamestudios.kaffeekasse.repositories.PortalRepository +import net.novagamestudios.kaffeekasse.repositories.i11.PortalRepository import net.novagamestudios.kaffeekasse.ui.hiwi_tracker.HiwiTrackerTopBarActions import net.novagamestudios.kaffeekasse.ui.hiwi_tracker.HiwiTrackerTopBarTitle import net.novagamestudios.kaffeekasse.ui.kaffeekasse.KaffeekasseTopBarActions diff --git a/app/src/main/java/net/novagamestudios/kaffeekasse/ui/Login.kt b/app/src/main/java/net/novagamestudios/kaffeekasse/ui/Login.kt index 301e90a9514ff88641328ef9ea447bfa907bf02a..fa95cf1f92e2b7604913942c21e0e3969d7199cb 100644 --- a/app/src/main/java/net/novagamestudios/kaffeekasse/ui/Login.kt +++ b/app/src/main/java/net/novagamestudios/kaffeekasse/ui/Login.kt @@ -80,18 +80,18 @@ import net.novagamestudios.common_utils.debug import net.novagamestudios.common_utils.info import net.novagamestudios.common_utils.toastShort import net.novagamestudios.common_utils.warn -import net.novagamestudios.kaffeekasse.api.kaffeekasse.BasicUserInfo +import net.novagamestudios.kaffeekasse.api.kaffeekasse.model.BasicUserInfo import net.novagamestudios.kaffeekasse.api.kaffeekasse.KaffeekasseAPI import net.novagamestudios.kaffeekasse.data.cleanName -import net.novagamestudios.kaffeekasse.model.Device -import net.novagamestudios.kaffeekasse.model.DeviceCredentials -import net.novagamestudios.kaffeekasse.model.Login -import net.novagamestudios.kaffeekasse.model.isUser -import net.novagamestudios.kaffeekasse.model.isValid +import net.novagamestudios.kaffeekasse.model.credentials.Device +import net.novagamestudios.kaffeekasse.model.credentials.DeviceCredentials +import net.novagamestudios.kaffeekasse.model.credentials.Login +import net.novagamestudios.kaffeekasse.model.credentials.isUser +import net.novagamestudios.kaffeekasse.model.credentials.isValid import net.novagamestudios.kaffeekasse.repositories.Credentials -import net.novagamestudios.kaffeekasse.repositories.KaffeekasseRepository +import net.novagamestudios.kaffeekasse.repositories.i11.KaffeekasseRepository import net.novagamestudios.kaffeekasse.repositories.MutableSettingsStore -import net.novagamestudios.kaffeekasse.repositories.PortalRepository +import net.novagamestudios.kaffeekasse.repositories.i11.PortalRepository import net.novagamestudios.kaffeekasse.ui.kaffeekasse.components.FailureRetryScreen import net.novagamestudios.kaffeekasse.ui.util.rememberSerializableState import net.novagamestudios.kaffeekasse.ui.util.trueWhileWithMutex diff --git a/app/src/main/java/net/novagamestudios/kaffeekasse/ui/Updates.kt b/app/src/main/java/net/novagamestudios/kaffeekasse/ui/Updates.kt index c8bd0f33b0c0ac0cf5fdb63c3cdd7fdf77fa856d..118ee55746a08738bfbd5bbd01f219b2b19b8cf7 100644 --- a/app/src/main/java/net/novagamestudios/kaffeekasse/ui/Updates.kt +++ b/app/src/main/java/net/novagamestudios/kaffeekasse/ui/Updates.kt @@ -56,13 +56,12 @@ import net.novagamestudios.common_utils.compose.state.collectAsStateIn import net.novagamestudios.common_utils.toastLong import net.novagamestudios.kaffeekasse.App import net.novagamestudios.kaffeekasse.BuildConfig -import net.novagamestudios.kaffeekasse.model.AppRelease -import net.novagamestudios.kaffeekasse.model.AppVersion -import net.novagamestudios.kaffeekasse.model.format +import net.novagamestudios.kaffeekasse.model.app.AppRelease +import net.novagamestudios.kaffeekasse.model.app.AppVersion +import net.novagamestudios.kaffeekasse.model.date_time.format import net.novagamestudios.kaffeekasse.repositories.InstallStatus import net.novagamestudios.kaffeekasse.repositories.LocalSettingsStore -import net.novagamestudios.kaffeekasse.repositories.MutableSettingsStore -import net.novagamestudios.kaffeekasse.repositories.Releases +import net.novagamestudios.kaffeekasse.repositories.releases.Releases import net.novagamestudios.kaffeekasse.repositories.UpdateController import net.novagamestudios.kaffeekasse.util.openInBrowser import java.time.format.DateTimeFormatter diff --git a/app/src/main/java/net/novagamestudios/kaffeekasse/ui/UserSelection.kt b/app/src/main/java/net/novagamestudios/kaffeekasse/ui/UserSelection.kt index fd0e7c24501c906dad0c329c37b2b3f2f2cb23f2..817ea05f2beda9e03fcb831cae0ee3545d2ab2f5 100644 --- a/app/src/main/java/net/novagamestudios/kaffeekasse/ui/UserSelection.kt +++ b/app/src/main/java/net/novagamestudios/kaffeekasse/ui/UserSelection.kt @@ -36,8 +36,8 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.flowOn import net.novagamestudios.common_utils.compose.components.RowCenter -import net.novagamestudios.kaffeekasse.api.kaffeekasse.BasicUserInfo -import net.novagamestudios.kaffeekasse.repositories.KaffeekasseRepository +import net.novagamestudios.kaffeekasse.api.kaffeekasse.model.BasicUserInfo +import net.novagamestudios.kaffeekasse.repositories.i11.KaffeekasseRepository import net.novagamestudios.kaffeekasse.ui.kaffeekasse.components.FailureRetryScreen import net.novagamestudios.kaffeekasse.ui.util.PullToRefreshBox import net.novagamestudios.kaffeekasse.ui.util.RichDataContent @@ -95,6 +95,7 @@ fun UserSelection( horizontalAlignment = Alignment.CenterHorizontally ) { val focusRequester = remember { FocusRequester() } + // TODO DockedSearchBar( query = vm.searchQuery, onQueryChange = { vm.searchQuery = it }, diff --git a/app/src/main/java/net/novagamestudios/kaffeekasse/ui/hiwi_tracker/EnterWorkingHours.kt b/app/src/main/java/net/novagamestudios/kaffeekasse/ui/hiwi_tracker/EnterWorkingHours.kt index a2ccf5a6697bd576704a1d5c8142340ca83b0dae..75238324ea3df23d4e9ecac6ffa1fcd4e7baf32f 100644 --- a/app/src/main/java/net/novagamestudios/kaffeekasse/ui/hiwi_tracker/EnterWorkingHours.kt +++ b/app/src/main/java/net/novagamestudios/kaffeekasse/ui/hiwi_tracker/EnterWorkingHours.kt @@ -94,7 +94,7 @@ import net.novagamestudios.kaffeekasse.model.hiwi_tracker.WorkEntry.Companion.Mi import net.novagamestudios.kaffeekasse.model.hiwi_tracker.WorkEntry.Companion.invalidLargeBreak import net.novagamestudios.kaffeekasse.model.hiwi_tracker.WorkEntry.Companion.invalidSmallBreak import net.novagamestudios.kaffeekasse.model.hiwi_tracker.WorkEntry.Companion.isValid -import net.novagamestudios.kaffeekasse.repositories.HiwiTrackerRepository +import net.novagamestudios.kaffeekasse.repositories.i11.HiwiTrackerRepository import net.novagamestudios.kaffeekasse.ui.theme.disabled import net.novagamestudios.kaffeekasse.ui.util.ClockFace import net.novagamestudios.kaffeekasse.ui.util.TimePickerState @@ -548,7 +548,7 @@ private fun DurationInput( ) }, keyboardOptions = KeyboardOptions( - autoCorrect = false, + autoCorrectEnabled = false, keyboardType = KeyboardType.Number, imeAction = ImeAction.Done ), diff --git a/app/src/main/java/net/novagamestudios/kaffeekasse/ui/hiwi_tracker/HiwiTrackerModule.kt b/app/src/main/java/net/novagamestudios/kaffeekasse/ui/hiwi_tracker/HiwiTrackerModule.kt index 4e664e75a13636fd29d569e32f7981cbd041262a..11423cd4153ad4a1ea5c2836f192e080525f70c3 100644 --- a/app/src/main/java/net/novagamestudios/kaffeekasse/ui/hiwi_tracker/HiwiTrackerModule.kt +++ b/app/src/main/java/net/novagamestudios/kaffeekasse/ui/hiwi_tracker/HiwiTrackerModule.kt @@ -89,12 +89,12 @@ import net.novagamestudios.common_utils.compose.components.RowCenter import net.novagamestudios.common_utils.debug import net.novagamestudios.common_utils.verbose import net.novagamestudios.kaffeekasse.App -import net.novagamestudios.kaffeekasse.model.format +import net.novagamestudios.kaffeekasse.model.date_time.format import net.novagamestudios.kaffeekasse.model.hiwi_tracker.MonthKey import net.novagamestudios.kaffeekasse.model.hiwi_tracker.MonthKey.Companion.toMonthKey import net.novagamestudios.kaffeekasse.model.hiwi_tracker.WorkEntry -import net.novagamestudios.kaffeekasse.api.hiwi_tracker.MonthDataResponse -import net.novagamestudios.kaffeekasse.repositories.HiwiTrackerRepository +import net.novagamestudios.kaffeekasse.api.hiwi_tracker.model.MonthDataResponse +import net.novagamestudios.kaffeekasse.repositories.i11.HiwiTrackerRepository import net.novagamestudios.kaffeekasse.repositories.MutableSettingsStore import net.novagamestudios.kaffeekasse.ui.AppInfoTopBarAction import net.novagamestudios.kaffeekasse.ui.AppModuleSelection diff --git a/app/src/main/java/net/novagamestudios/kaffeekasse/ui/kaffeekasse/Account.kt b/app/src/main/java/net/novagamestudios/kaffeekasse/ui/kaffeekasse/Account.kt index 6a1086f8941807ec00323e06fa62a325b305336a..37fee4febb410d9015f1117705c63c76c8276bfb 100644 --- a/app/src/main/java/net/novagamestudios/kaffeekasse/ui/kaffeekasse/Account.kt +++ b/app/src/main/java/net/novagamestudios/kaffeekasse/ui/kaffeekasse/Account.kt @@ -34,7 +34,7 @@ import net.novagamestudios.common_utils.compose.components.ColumnCenter import net.novagamestudios.common_utils.format import net.novagamestudios.kaffeekasse.App import net.novagamestudios.kaffeekasse.model.kaffeekasse.Account -import net.novagamestudios.kaffeekasse.repositories.KaffeekasseRepository +import net.novagamestudios.kaffeekasse.repositories.i11.KaffeekasseRepository import net.novagamestudios.kaffeekasse.ui.kaffeekasse.components.FailureRetryScreen import net.novagamestudios.kaffeekasse.ui.util.PullToRefreshBox import net.novagamestudios.kaffeekasse.util.richdata.collectAsRichStateHere diff --git a/app/src/main/java/net/novagamestudios/kaffeekasse/ui/kaffeekasse/KaffeekasseModule.kt b/app/src/main/java/net/novagamestudios/kaffeekasse/ui/kaffeekasse/KaffeekasseModule.kt index 4cfeae1a561d607d77cab2fb2ec06c1e6be2382c..84250d1e8a81d5d0639d693499339f725f1ee958 100644 --- a/app/src/main/java/net/novagamestudios/kaffeekasse/ui/kaffeekasse/KaffeekasseModule.kt +++ b/app/src/main/java/net/novagamestudios/kaffeekasse/ui/kaffeekasse/KaffeekasseModule.kt @@ -20,7 +20,7 @@ import net.novagamestudios.kaffeekasse.App import net.novagamestudios.kaffeekasse.KaffeekasseModule import net.novagamestudios.kaffeekasse.model.kaffeekasse.MutableCart import net.novagamestudios.kaffeekasse.model.kaffeekasse.isNotEmpty -import net.novagamestudios.kaffeekasse.repositories.PortalRepository +import net.novagamestudios.kaffeekasse.repositories.i11.PortalRepository import net.novagamestudios.kaffeekasse.ui.AppBackNavigation import net.novagamestudios.kaffeekasse.ui.AppInfoTopBarAction import net.novagamestudios.kaffeekasse.ui.AppModuleSelection diff --git a/app/src/main/java/net/novagamestudios/kaffeekasse/ui/kaffeekasse/ManualBill.kt b/app/src/main/java/net/novagamestudios/kaffeekasse/ui/kaffeekasse/ManualBill.kt index 5c851c100ef4873db0a9aaaf228a16457dcb69f2..7bd1df06477b069d0cac435341f9c46d6ca4cf10 100644 --- a/app/src/main/java/net/novagamestudios/kaffeekasse/ui/kaffeekasse/ManualBill.kt +++ b/app/src/main/java/net/novagamestudios/kaffeekasse/ui/kaffeekasse/ManualBill.kt @@ -38,7 +38,7 @@ import net.novagamestudios.common_utils.compose.tabIndicatorOffset import net.novagamestudios.kaffeekasse.App import net.novagamestudios.kaffeekasse.KaffeekasseModule import net.novagamestudios.kaffeekasse.model.kaffeekasse.MutableCart -import net.novagamestudios.kaffeekasse.repositories.KaffeekasseRepository +import net.novagamestudios.kaffeekasse.repositories.i11.KaffeekasseRepository import net.novagamestudios.kaffeekasse.ui.kaffeekasse.components.APICheckoutViewModel import net.novagamestudios.kaffeekasse.ui.kaffeekasse.components.CategorizedItems import net.novagamestudios.kaffeekasse.ui.kaffeekasse.components.CategorizedItemsViewModel diff --git a/app/src/main/java/net/novagamestudios/kaffeekasse/ui/kaffeekasse/Transactions.kt b/app/src/main/java/net/novagamestudios/kaffeekasse/ui/kaffeekasse/Transactions.kt index 20f0f723266949571af24f0a092ee2013e50cfff..fdbb6c46fb777d9a775ad59be1eef13506f1f5c8 100644 --- a/app/src/main/java/net/novagamestudios/kaffeekasse/ui/kaffeekasse/Transactions.kt +++ b/app/src/main/java/net/novagamestudios/kaffeekasse/ui/kaffeekasse/Transactions.kt @@ -46,7 +46,7 @@ import net.novagamestudios.kaffeekasse.App import net.novagamestudios.kaffeekasse.data.category import net.novagamestudios.kaffeekasse.data.cleanFullName import net.novagamestudios.kaffeekasse.model.kaffeekasse.Transaction -import net.novagamestudios.kaffeekasse.repositories.KaffeekasseRepository +import net.novagamestudios.kaffeekasse.repositories.i11.KaffeekasseRepository import net.novagamestudios.kaffeekasse.repositories.LocalSettingsStore import net.novagamestudios.kaffeekasse.ui.kaffeekasse.components.FailureRetryScreen import net.novagamestudios.kaffeekasse.ui.kaffeekasse.components.cards.CategoryIcon diff --git a/app/src/main/java/net/novagamestudios/kaffeekasse/ui/kaffeekasse/components/AccountSelection.kt b/app/src/main/java/net/novagamestudios/kaffeekasse/ui/kaffeekasse/components/AccountSelection.kt index 03ad3955e9d789a64a5bb01e07346fd862cfaca1..d358d2d027ce01f482f4aa6db59c9607e016e72e 100644 --- a/app/src/main/java/net/novagamestudios/kaffeekasse/ui/kaffeekasse/components/AccountSelection.kt +++ b/app/src/main/java/net/novagamestudios/kaffeekasse/ui/kaffeekasse/components/AccountSelection.kt @@ -6,6 +6,7 @@ import androidx.compose.material3.DropdownMenuItem import androidx.compose.material3.ExposedDropdownMenuBox import androidx.compose.material3.ExposedDropdownMenuDefaults import androidx.compose.material3.Icon +import androidx.compose.material3.MenuAnchorType import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -40,7 +41,7 @@ fun AccountSelection( state.selectedAccount?.name ?: "", onValueChange = { }, Modifier - .menuAnchor(), + .menuAnchor(MenuAnchorType.PrimaryNotEditable), readOnly = true, label = { Text("Konto") }, leadingIcon = { Icon(Icons.Default.Person, "Konto") }, diff --git a/app/src/main/java/net/novagamestudios/kaffeekasse/ui/kaffeekasse/components/Checkout.kt b/app/src/main/java/net/novagamestudios/kaffeekasse/ui/kaffeekasse/components/Checkout.kt index 003a3c348384f1ed853b079b6f5232550f1e601d..d6f5033d1c153f92b350b3e7ca412f883d0bb341 100644 --- a/app/src/main/java/net/novagamestudios/kaffeekasse/ui/kaffeekasse/components/Checkout.kt +++ b/app/src/main/java/net/novagamestudios/kaffeekasse/ui/kaffeekasse/components/Checkout.kt @@ -54,14 +54,14 @@ import net.novagamestudios.common_utils.compose.maskedCircleIcon import net.novagamestudios.common_utils.compose.state.ReentrantActionState import net.novagamestudios.common_utils.toastLong import net.novagamestudios.common_utils.warn -import net.novagamestudios.kaffeekasse.api.kaffeekasse.APIPurchaseAccount +import net.novagamestudios.kaffeekasse.api.kaffeekasse.model.APIPurchaseAccount import net.novagamestudios.kaffeekasse.model.kaffeekasse.Cart import net.novagamestudios.kaffeekasse.model.kaffeekasse.ManualBillDetails import net.novagamestudios.kaffeekasse.model.kaffeekasse.MutableCart import net.novagamestudios.kaffeekasse.model.kaffeekasse.PurchaseAccount import net.novagamestudios.kaffeekasse.model.kaffeekasse.isEmpty import net.novagamestudios.kaffeekasse.model.kaffeekasse.isNotEmpty -import net.novagamestudios.kaffeekasse.repositories.KaffeekasseRepository +import net.novagamestudios.kaffeekasse.repositories.i11.KaffeekasseRepository import net.novagamestudios.kaffeekasse.ui.kaffeekasse.components.cards.CategoryIcon import net.novagamestudios.kaffeekasse.util.richdata.RichDataFlow import net.novagamestudios.kaffeekasse.util.richdata.RichDataState diff --git a/app/src/main/java/net/novagamestudios/kaffeekasse/ui/kaffeekasse/components/CustomItems.kt b/app/src/main/java/net/novagamestudios/kaffeekasse/ui/kaffeekasse/components/CustomItems.kt index 4a5b5387148f0d2f46eebf7684bb9bb0ee61379b..5048dcc67f6c0899b6ec09f9d286faa3ab3fdec1 100644 --- a/app/src/main/java/net/novagamestudios/kaffeekasse/ui/kaffeekasse/components/CustomItems.kt +++ b/app/src/main/java/net/novagamestudios/kaffeekasse/ui/kaffeekasse/components/CustomItems.kt @@ -38,7 +38,7 @@ import net.novagamestudios.kaffeekasse.App import net.novagamestudios.kaffeekasse.model.kaffeekasse.Item import net.novagamestudios.kaffeekasse.model.kaffeekasse.MutableCart import net.novagamestudios.kaffeekasse.model.kaffeekasse.Transaction -import net.novagamestudios.kaffeekasse.repositories.KaffeekasseRepository +import net.novagamestudios.kaffeekasse.repositories.i11.KaffeekasseRepository import net.novagamestudios.kaffeekasse.repositories.SettingsStore import net.novagamestudios.kaffeekasse.ui.theme.disabled import net.novagamestudios.kaffeekasse.util.richdata.asRichDataFlow diff --git a/app/src/main/java/net/novagamestudios/kaffeekasse/ui/util/PagerState.kt b/app/src/main/java/net/novagamestudios/kaffeekasse/ui/util/PagerState.kt index 8b3478ae0537dba5d731e6d4f93c57b5328b6c11..433f6469366f43d3392b69eba3e00d1f510b6ba0 100644 --- a/app/src/main/java/net/novagamestudios/kaffeekasse/ui/util/PagerState.kt +++ b/app/src/main/java/net/novagamestudios/kaffeekasse/ui/util/PagerState.kt @@ -3,6 +3,7 @@ package net.novagamestudios.kaffeekasse.ui.util import androidx.compose.animation.core.AnimationSpec import androidx.compose.animation.core.spring import androidx.compose.foundation.gestures.Orientation +import androidx.compose.foundation.gestures.TargetedFlingBehavior import androidx.compose.foundation.gestures.snapping.SnapFlingBehavior import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.pager.PageSize @@ -57,15 +58,16 @@ fun <K : Any> HorizontalKeyedPager( modifier: Modifier = Modifier, contentPadding: PaddingValues = PaddingValues(0.dp), pageSize: PageSize = PageSize.Fill, - beyondBoundsPageCount: Int = PagerDefaults.BeyondBoundsPageCount, + beyondViewportPageCount: Int = PagerDefaults.BeyondViewportPageCount, pageSpacing: Dp = 0.dp, verticalAlignment: Alignment.Vertical = Alignment.CenterVertically, - flingBehavior: SnapFlingBehavior = PagerDefaults.flingBehavior(state = state), + flingBehavior: TargetedFlingBehavior = PagerDefaults.flingBehavior(state = state), userScrollEnabled: Boolean = true, reverseLayout: Boolean = false, - pageNestedScrollConnection: NestedScrollConnection = remember(state) { - PagerDefaults.pageNestedScrollConnection(state, Orientation.Horizontal) - }, + pageNestedScrollConnection: NestedScrollConnection = PagerDefaults.pageNestedScrollConnection( + state, + Orientation.Horizontal + ), pageContent: @Composable PagerScope.(page: K) -> Unit ) { androidx.compose.foundation.pager.HorizontalPager( @@ -73,7 +75,7 @@ fun <K : Any> HorizontalKeyedPager( modifier = modifier, contentPadding = contentPadding, pageSize = pageSize, - beyondBoundsPageCount = beyondBoundsPageCount, + beyondViewportPageCount = beyondViewportPageCount, pageSpacing = pageSpacing, verticalAlignment = verticalAlignment, flingBehavior = flingBehavior, diff --git a/app/src/main/java/net/novagamestudios/kaffeekasse/ui/util/PullToRefreshBox.kt b/app/src/main/java/net/novagamestudios/kaffeekasse/ui/util/PullToRefreshBox.kt index 859fd8ec72c6fc3658aa3c976787bae89ee1356c..0f75704cd761fc501df3c7d3b5ed16294c3c5fc7 100644 --- a/app/src/main/java/net/novagamestudios/kaffeekasse/ui/util/PullToRefreshBox.kt +++ b/app/src/main/java/net/novagamestudios/kaffeekasse/ui/util/PullToRefreshBox.kt @@ -105,7 +105,7 @@ internal class PullToRefreshStateImpl( ): Offset = when { !enabled() -> Offset.Zero // Swiping up - source == NestedScrollSource.Drag && available.y < 0 -> { + source == NestedScrollSource.UserInput && available.y < 0 -> { consumeAvailableOffset(available) } else -> Offset.Zero @@ -118,7 +118,7 @@ internal class PullToRefreshStateImpl( ): Offset = when { !enabled() -> Offset.Zero // Swiping down - source == NestedScrollSource.Drag && available.y > 0 -> { + source == NestedScrollSource.UserInput && available.y > 0 -> { consumeAvailableOffset(available) } else -> Offset.Zero diff --git a/app/src/main/java/net/novagamestudios/kaffeekasse/util/richdata/RichDataFlow.kt b/app/src/main/java/net/novagamestudios/kaffeekasse/util/richdata/RichDataFlow.kt index 834bb47f14f278e5177bd62bbda21f9ddacd8728..71c1a3a27970700897ae367854a1c6cde4e1998f 100644 --- a/app/src/main/java/net/novagamestudios/kaffeekasse/util/richdata/RichDataFlow.kt +++ b/app/src/main/java/net/novagamestudios/kaffeekasse/util/richdata/RichDataFlow.kt @@ -1,6 +1,7 @@ package net.novagamestudios.kaffeekasse.util.richdata import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharingStarted @@ -52,6 +53,7 @@ fun <T : Any, R : Any> RichDataFlow<T>.mapRich( }) } +@OptIn(ExperimentalCoroutinesApi::class) @Suppress("UNCHECKED_CAST") fun <T : Any, R : Any> RichDataFlow<T>.mapLatestRich( loadDuringTransform: Boolean = false, diff --git a/build.gradle.kts b/build.gradle.kts index de030ed4a3fbfc299fa38a9a4696002c50584381..7c081188a34d9dee53a4541d911d2689c0b27156 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,5 +1,6 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. plugins { + alias(libs.plugins.gradle.versions) apply false alias(libs.plugins.android.application) apply false alias(libs.plugins.kotlin.android) apply false alias(libs.plugins.kotlinx.serialization) apply false diff --git a/gradle.properties b/gradle.properties index 3c5031eb7d63f785752b1914cc8692a453d1cc63..dc6773a6db44f3173d3c4e299a6cccf7c609f812 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,16 +1,6 @@ -# Project-wide Gradle settings. -# IDE (e.g. Android Studio) users: -# Gradle settings configured through the IDE *will override* -# any settings specified in this file. -# For more details on how to configure your build environment visit -# http://www.gradle.org/docs/current/userguide/build_environment.html # Specifies the JVM arguments used for the daemon process. # The setting is particularly useful for tweaking memory settings. org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 -# When configured, Gradle will run in incubating parallel mode. -# This option should only be used with decoupled projects. More details, visit -# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects -# org.gradle.parallel=true # AndroidX package structure to make it clearer which packages are bundled with the # Android operating system, and which are packaged with your app's APK # https://developer.android.com/topic/libraries/support-library/androidx-rn @@ -20,4 +10,12 @@ kotlin.code.style=official # Enables namespacing of each library's R class so that its R class includes only the # resources declared in the library itself and none from the library's dependencies, # thereby reducing the size of the R class for that library -android.nonTransitiveRClass=true \ No newline at end of file +android.nonTransitiveRClass=true + +#kotlin.experimental.tryK2=true + +# See https://github.com/ben-manes/gradle-versions-plugin/issues/859 +# Remove when version of AGP >= 8.3.1 +systemProp.javax.xml.parsers.SAXParserFactory=com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl +systemProp.javax.xml.transform.TransformerFactory=com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl +systemProp.javax.xml.parsers.DocumentBuilderFactory=com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 0a4f1e8d01dc7167c5487c99e52d4e6f6c5d0af0..f8bf34cc13f4117925a2b895b1626174cf95795c 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Mon Nov 27 19:34:08 CET 2023 +#Thu Apr 18 16:02:39 CEST 2024 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/settings.gradle.kts b/settings.gradle.kts index a59b93ec321a8d8a339cb2e43b52964047b404c5..84e0f446984555ebf00037472fd7f2714c3d07b4 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -15,41 +15,44 @@ dependencyResolutionManagement { } versionCatalogs { create("libs") { - version("kotlin", "1.9.10") - version("compose-bom", "2024.02.01") - version("androidx-lifecycle", "2.7.0") - version("ktor", "2.3.8") + version("kotlin", "1.9.23") + version("compose-compiler", "1.5.12") + version("compose-bom", "2024.04.01") + version("material3", "1.3.0-alpha05") + version("androidx-lifecycle", "2.8.0-beta01") + version("ktor", "3.0.0-beta-1") version("vico", "2.0.0-alpha.8") - version("voyager", "1.0.0") + version("voyager", "1.1.0-alpha04") version("coil", "2.6.0") + plugin("gradle-versions", "com.github.ben-manes.versions").version("0.51.0") plugin("android-application", "com.android.application").version("8.2.0") plugin("kotlin-android", "org.jetbrains.kotlin.android").versionRef("kotlin") plugin("kotlinx-serialization", "org.jetbrains.kotlin.plugin.serialization").versionRef("kotlin") - library("androidx-core", "androidx.core", "core-ktx").version("1.12.0") + library("androidx-core", "androidx.core", "core-ktx").version("1.13.0") library("androidx-lifecycle-runtime", "androidx.lifecycle", "lifecycle-runtime-ktx").versionRef("androidx-lifecycle") library("androidx-lifecycle-viewmodel-compose", "androidx.lifecycle", "lifecycle-viewmodel-compose").versionRef("androidx-lifecycle") library("androidx-navigation-compose", "androidx.navigation", "navigation-compose").version("2.7.7") - library("androidx-activity-compose", "androidx.activity", "activity-compose").version("1.8.2") + library("androidx-activity-compose", "androidx.activity", "activity-compose").version("1.9.0") library("compose-bom", "androidx.compose", "compose-bom").versionRef("compose-bom") library("compose-ui", "androidx.compose.ui", "ui").withoutVersion() library("compose-ui-graphics", "androidx.compose.ui", "ui-graphics").withoutVersion() library("compose-ui-tooling-preview", "androidx.compose.ui", "ui-tooling-preview").withoutVersion() - library("compose-ui-text-google-fonts", "androidx.compose.ui", "ui-text-google-fonts").version("1.6.2") - library("compose-material3", "androidx.compose.material3", "material3").version("1.2.0") - library("compose-material-icons-extended", "androidx.compose.material", "material-icons-extended").version("1.6.2") - library("compose-grid", "io.woong.compose.grid", "grid").version("1.2.1") + library("compose-ui-text-google-fonts", "androidx.compose.ui", "ui-text-google-fonts").withoutVersion() // .version("1.6.2") + library("compose-material-icons-extended", "androidx.compose.material", "material-icons-extended").withoutVersion() // .version("1.7.0-alpha07") + library("compose-material3", "androidx.compose.material3", "material3").versionRef("material3") + library("compose-grid", "io.woong.compose.grid", "grid").version("1.2.2") - library("androidx-credentials", "androidx.credentials", "credentials").version("1.3.0-alpha01") + library("androidx-credentials", "androidx.credentials", "credentials").version("1.3.0-alpha03") library("androidx-datastore", "androidx.datastore", "datastore-preferences-android").version("1.1.0-alpha07") library("kotlinx-datetime", "org.jetbrains.kotlinx", "kotlinx-datetime").version("0.6.0-RC.2") - library("kotlinx-serialization-json", "org.jetbrains.kotlinx", "kotlinx-serialization-json").version("1.6.0") + library("kotlinx-serialization-json", "org.jetbrains.kotlinx", "kotlinx-serialization-json").version("1.6.3") library("ktor-client-core", "io.ktor", "ktor-client-core").versionRef("ktor") library("ktor-client-okhttp", "io.ktor", "ktor-client-okhttp").versionRef("ktor") @@ -73,7 +76,7 @@ dependencyResolutionManagement { library("coil", "io.coil-kt", "coil").versionRef("coil") library("coil-compose", "io.coil-kt", "coil-compose").versionRef("coil") - library("commonutils", "com.gitlab.JojoIV", "common_utils").version("6e8e35fce9") + library("commonutils", "com.gitlab.JojoIV", "common_utils").version("2d5e5c9a17") } } }