Skip to content

Commit

Permalink
refactor&feat&fix: migration to flowmvi, new validation model, stabil…
Browse files Browse the repository at this point in the history
…ity config for Compose and other fixes (#124)

* refactor: from MVI with ViewModels to MVI with the Decompose

* refactor: from MVI with ViewModels to MVI with the Decompose

* feat: compose reports & compose stability config

* feat&refactor: better validation with built-in support from SDK

* feat: timers repository now handles updates locally

* feat: hook to use libs generation in the build conventions

* refactor: from self-written MVI model to the flowmvi

* refactor: sdk-related objects creation is fixed

* fix: missing LocalTimeProvider

* refactor: removed run configuration in favor to IDE configuration

* fix: target jvm

* chore: removed modules that're no longer in use

* fix&feat: fix of mistakes & new strings

* refactor: clean up

* chore: Singletons instead of Factories

* fix: fixes according to new versions of libs

* feat: Android Run Configuration

* fix: previews

* small fixes
  • Loading branch information
y9vad9 authored Mar 24, 2024
1 parent af5f604 commit 9ceac1f
Show file tree
Hide file tree
Showing 265 changed files with 2,624 additions and 3,227 deletions.
24 changes: 0 additions & 24 deletions .run/Android Install Debug.run.xml

This file was deleted.

69 changes: 69 additions & 0 deletions .run/Run Android Application.run.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Run Android Application" type="AndroidRunConfigurationType" factoryName="Android App">
<module name="timemates-app.platform.android.main" />
<option name="DEPLOY" value="true" />
<option name="DEPLOY_APK_FROM_BUNDLE" value="false" />
<option name="DEPLOY_AS_INSTANT" value="false" />
<option name="ARTIFACT_NAME" value="" />
<option name="PM_INSTALL_OPTIONS" value="" />
<option name="ALL_USERS" value="false" />
<option name="ALWAYS_INSTALL_WITH_PM" value="false" />
<option name="CLEAR_APP_STORAGE" value="false" />
<option name="DYNAMIC_FEATURES_DISABLED_LIST" value="" />
<option name="ACTIVITY_EXTRA_FLAGS" value="" />
<option name="MODE" value="default_activity" />
<option name="CLEAR_LOGCAT" value="false" />
<option name="SHOW_LOGCAT_AUTOMATICALLY" value="true" />
<option name="INSPECTION_WITHOUT_ACTIVITY_RESTART" value="false" />
<option name="TARGET_SELECTION_MODE" value="DEVICE_AND_SNAPSHOT_COMBO_BOX" />
<option name="SELECTED_CLOUD_MATRIX_CONFIGURATION_ID" value="-1" />
<option name="SELECTED_CLOUD_MATRIX_PROJECT_ID" value="" />
<option name="DEBUGGER_TYPE" value="Auto" />
<Auto>
<option name="USE_JAVA_AWARE_DEBUGGER" value="false" />
<option name="SHOW_STATIC_VARS" value="true" />
<option name="WORKING_DIR" value="" />
<option name="TARGET_LOGGING_CHANNELS" value="lldb process:gdb-remote packets" />
<option name="SHOW_OPTIMIZED_WARNING" value="true" />
<option name="ATTACH_ON_WAIT_FOR_DEBUGGER" value="false" />
<option name="DEBUG_SANDBOX_SDK" value="false" />
</Auto>
<Hybrid>
<option name="USE_JAVA_AWARE_DEBUGGER" value="false" />
<option name="SHOW_STATIC_VARS" value="true" />
<option name="WORKING_DIR" value="" />
<option name="TARGET_LOGGING_CHANNELS" value="lldb process:gdb-remote packets" />
<option name="SHOW_OPTIMIZED_WARNING" value="true" />
<option name="ATTACH_ON_WAIT_FOR_DEBUGGER" value="false" />
<option name="DEBUG_SANDBOX_SDK" value="false" />
</Hybrid>
<Java>
<option name="ATTACH_ON_WAIT_FOR_DEBUGGER" value="false" />
<option name="DEBUG_SANDBOX_SDK" value="false" />
</Java>
<Native>
<option name="USE_JAVA_AWARE_DEBUGGER" value="false" />
<option name="SHOW_STATIC_VARS" value="true" />
<option name="WORKING_DIR" value="" />
<option name="TARGET_LOGGING_CHANNELS" value="lldb process:gdb-remote packets" />
<option name="SHOW_OPTIMIZED_WARNING" value="true" />
<option name="ATTACH_ON_WAIT_FOR_DEBUGGER" value="false" />
<option name="DEBUG_SANDBOX_SDK" value="false" />
</Native>
<Profilers>
<option name="ADVANCED_PROFILING_ENABLED" value="false" />
<option name="STARTUP_PROFILING_ENABLED" value="false" />
<option name="STARTUP_CPU_PROFILING_ENABLED" value="false" />
<option name="STARTUP_CPU_PROFILING_CONFIGURATION_NAME" value="Java/Kotlin Method Sample (legacy)" />
<option name="STARTUP_NATIVE_MEMORY_PROFILING_ENABLED" value="false" />
<option name="NATIVE_MEMORY_SAMPLE_RATE_BYTES" value="2048" />
</Profilers>
<option name="DEEP_LINK" value="" />
<option name="ACTIVITY_CLASS" value="" />
<option name="SEARCH_ACTIVITY_IN_GLOBAL_SCOPE" value="false" />
<option name="SKIP_ACTIVITY_VALIDATION" value="false" />
<method v="2">
<option name="Android.Gradle.BeforeRunTask" enabled="true" />
</method>
</configuration>
</component>
2 changes: 1 addition & 1 deletion .run/Run Desktop App.run.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Run Desktop App" type="JetRunConfigurationType">
<option name="MAIN_CLASS_NAME" value="org.timemates.app.MainKt" />
<module name="timemates-app.platforms.desktop.main" />
<module name="timemates-app.platform.desktop.main" />
<shortenClasspath name="NONE" />
<method v="2">
<option name="Make" enabled="true" />
Expand Down
1 change: 1 addition & 0 deletions build-conventions/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ kotlin {
}

dependencies {
api(files(libs.javaClass.superclass.protectionDomain.codeSource.location))
api(libs.kotlin.plugin)
api(libs.android.gradle.plugin)
api(libs.compose.multiplatform.plugin)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,16 @@
import org.gradle.accessors.dm.LibrariesForLibs

plugins {
id("multiplatform-library-convention")
id("com.google.devtools.ksp")
}

version = "SNAPSHOT"

val koinVersion = "3.5.3"
val koinAnnotationsVersion = "1.3.0"
val libs = the<LibrariesForLibs>()

dependencies {
commonMainImplementation("io.insert-koin:koin-core:$koinVersion")
commonMainImplementation("io.insert-koin:koin-annotations:$koinAnnotationsVersion")

val kspCompiler = "io.insert-koin:koin-ksp-compiler:$koinAnnotationsVersion"

add("kspCommonMainMetadata", kspCompiler)
add("kspJvm", kspCompiler)
add("kspAndroid", kspCompiler)
commonMainImplementation(libs.koin.core)
commonMainImplementation(libs.koin.annotations)
ksp(libs.koin.ksp.compiler)
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
kotlin("multiplatform")
id("com.android.library")
Expand Down Expand Up @@ -25,3 +27,8 @@ android {
}
}

tasks.withType<KotlinCompile> {
kotlinOptions {
jvmTarget = "19"
}
}
18 changes: 17 additions & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ plugins {
alias(libs.plugins.kotlin.multiplatform) apply false
alias(libs.plugins.kotlin.jvm) apply false
alias(libs.plugins.android.library) apply false
alias(libs.plugins.android.application) apply false
alias(libs.plugins.kotlin.android) apply false
alias(libs.plugins.kotlin.parcelize) apply false
alias(libs.plugins.ksp) apply false
Expand All @@ -16,7 +17,22 @@ group = "org.timemates.app"
allprojects {
tasks.withType<KotlinCompile> {
kotlinOptions {
jvmTarget = "19"
freeCompilerArgs += listOf("-Xskip-prerelease-check")

val composeReportsDir = "compose_reports"

freeCompilerArgs += listOf(
"-P",
"plugin:androidx.compose.compiler.plugins.kotlin:stabilityConfigurationPath=$rootDir/stability-config.txt"
)
freeCompilerArgs += listOf(
"-P",
"plugin:androidx.compose.compiler.plugins.kotlin:reportsDestination=" +
project.layout.buildDirectory.get().dir(composeReportsDir).asFile.absolutePath,
"-P",
"plugin:androidx.compose.compiler.plugins.kotlin:metricsDestination=" +
project.layout.buildDirectory.get().dir(composeReportsDir).asFile.absolutePath,
)
}
}
}
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ plugins {
}

dependencies {
commonMainImplementation(projects.localization)
commonMainImplementation(projects.core.localization)
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,5 @@
package org.timemates.app.localization

import io.timemates.sdk.authorization.sessions.types.value.ConfirmationCode
import io.timemates.sdk.timers.types.value.TimerDescription
import io.timemates.sdk.timers.types.value.TimerName
import io.timemates.sdk.users.profile.types.value.UserDescription
import io.timemates.sdk.users.profile.types.value.UserName

object EnglishStrings : Strings {
override val appName: String = "TimeMates"
override val start: String = "Start"
Expand All @@ -23,7 +17,7 @@ object EnglishStrings : Strings {
override val changeEmail: String = "Change email"
override val emailSizeIsInvalid: String = "Email address size should be in range of 5 and 200 symbols"
override val emailIsInvalid: String = "Email address is invalid."
override val codeSizeIsInvalid: String = "Code size should be ${ConfirmationCode.SIZE} symbols length"
override val codeSizeIsInvalid: String = "Code size should be 0 symbols length"
override val codeIsInvalid: String = "Confirmation code should consist only from [a-Z] and [0-9]"
override val unknownFailure: String = "Unknown failure happened"
override val confirmationAttemptFailed: String = "Confirmation code is invalid. Recheck and try again."
Expand All @@ -34,9 +28,9 @@ object EnglishStrings : Strings {
override val configureNewAccountDescription: String = "Welcome to TimeMates! Let’s start our journey by configuring your profile details."
override val aboutYou: String = "About you"
override val yourName: String = "Your name"
override val nameSizeIsInvalid: String = "Name size should be in range of ${UserName.SIZE_RANGE.first} to ${UserName.SIZE_RANGE.last} symbols."
override val nameSizeIsInvalid: String = "Name size should be in range of 0 to 0 symbols."
override val nameIsInvalid: String = "Name consists from illegal characters."
override val aboutYouSizeIsInvalid: String = "User description should be in range of ${UserDescription.SIZE_RANGE.first} and ${UserDescription.SIZE_RANGE.last} symbols."
override val aboutYouSizeIsInvalid: String = "User description should be in range of 0 and 0 symbols."
override val timerSettings: String = "Edit timer"
override val description: String = "Description"
override val name: String = "Name"
Expand All @@ -47,8 +41,8 @@ object EnglishStrings : Strings {
override val advancedRestSettingsDescription: String = "Enable big rest time (extended rest every X rounds)."
override val publicManageTimerStateDescription: String = "Everyone can manage timer state"
override val confirmationRequiredDescription: String = "Always require confirmation before round start"
override val timerNameSizeIsInvalid: String = "Name size should be in range of ${TimerName.SIZE_RANGE.first} to ${TimerName.SIZE_RANGE.last} symbols."
override val timerDescriptionSizeIsInvalid: String = "Timer description should be in range of ${TimerDescription.SIZE_RANGE.first} and ${TimerDescription.SIZE_RANGE.last} symbols."
override val timerNameSizeIsInvalid: String = "Name size should be in range of 0 to 0 symbols."
override val timerDescriptionSizeIsInvalid: String = "Timer description should be in range of 0 and 0 symbols."
override val save: String = "Save"
override val welcome: String = "Welcome to TimeMates"
override val welcomeDescription: String = "Unlock Your Productivity: Seamlessly Organize Tasks, Collaborate Effortlessly, and Achieve your Goals."
Expand All @@ -59,9 +53,28 @@ object EnglishStrings : Strings {
override val alreadyExists: String = "It already exists or functionality isn't supposed to be used twice."
override val invalidArgument: String = "Invalid input information."
override val notFound: String = "Entity is not found."
override val unauthorized: String = "Your authorized was whether terminated or expired, please relogin."
override val unauthorized: String = "Your authorization is whether terminated or expired, please relogin."
override val unavailable: String = "Service is not available at the moment, please try again later."
override val unsupported: String = "This functionality is not yet supported."
override val fieldCannotBeEmpty: String = "This field cannot be empty."

override fun minValueFailure(min: Number): String {
return "Minimal value is the $min."
}

override fun lengthExactFailure(size: Int): String {
return "Length should be exactly $size."
}

override fun lengthRangeFailure(range: IntRange): String {
return "Length should be in a range of ${range.first} to ${range.last}."
}

override fun valueRangeFailure(first: Number, last: Number): String {
return "Value range should be in frame from $first to $last."
}

override val patternFailure: String = "The value does not follow the correct format."

override fun internalError(message: String): String {
return "Internal server failure has happened, details: $message"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package org.timemates.app.localization

import androidx.compose.runtime.Immutable
import androidx.compose.runtime.Stable

@Immutable
interface Strings {
val appName: String

Expand Down Expand Up @@ -105,6 +107,22 @@ interface Strings {

val unsupported: String

val fieldCannotBeEmpty: String

@Stable
fun minValueFailure(min: Number): String

@Stable
fun lengthExactFailure(size: Int): String

@Stable
fun lengthRangeFailure(range: IntRange): String

@Stable
fun valueRangeFailure(first: Number, last: Number): String

val patternFailure: String

@Stable
fun internalError(message: String): String

Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,5 @@
package org.timemates.app.localization

import io.timemates.sdk.authorization.sessions.types.value.ConfirmationCode
import io.timemates.sdk.timers.types.value.TimerDescription
import io.timemates.sdk.timers.types.value.TimerName
import io.timemates.sdk.users.profile.types.value.UserDescription
import io.timemates.sdk.users.profile.types.value.UserName

object UkrainianStrings : Strings {
override val appName: String = "TimeMates"
override val start: String = "Почати"
Expand All @@ -23,7 +17,7 @@ object UkrainianStrings : Strings {
override val changeEmail: String = "Змінити пошту"
override val emailSizeIsInvalid: String = "Розмір електронної пошти має бути від 5 до 200 символів"
override val emailIsInvalid: String = "Ваша електронна пошта неправильна."
override val codeSizeIsInvalid: String = "Розмір має бути ${ConfirmationCode.SIZE} символів."
override val codeSizeIsInvalid: String = "Розмір має бути 0 символів."
override val codeIsInvalid: String = "Код має містити лише [a-Z] символи та цифри."
override val unknownFailure: String = "Сталась невідома помилка"
override val confirmationAttemptFailed: String = "Код неправильний, перевірьте будь-ласка код та спробуйте знову."
Expand All @@ -34,9 +28,9 @@ object UkrainianStrings : Strings {
override val configureNewAccountDescription: String = "Ласкаво просимо до TimeMates! Давайте почнемо нашу подорож із налаштування даних вашого профілю."
override val aboutYou: String = "Про тебе"
override val yourName: String = "Твоє ім'я"
override val nameSizeIsInvalid: String = "Ім'я має бути в межах ${UserName.SIZE_RANGE.first} й ${UserName.SIZE_RANGE.last} символів."
override val nameSizeIsInvalid: String = "Ім'я має бути в межах 0 й 0 символів."
override val nameIsInvalid: String = "Ім'я містить заборонені символи."
override val aboutYouSizeIsInvalid: String = "Опис має бути в межах ${UserDescription.SIZE_RANGE.first} й ${UserDescription.SIZE_RANGE.last} символів."
override val aboutYouSizeIsInvalid: String = "Опис має бути в межах 0 й 0 символів."
override val timerSettings: String = "Редагувати таймер"
override val description: String = "Описання"
override val name: String = "Найменування"
Expand All @@ -47,8 +41,8 @@ object UkrainianStrings : Strings {
override val advancedRestSettingsDescription: String = "Увімкнути подовжений відпочинок (кожні X раундів)."
override val publicManageTimerStateDescription: String = "Кожен може керувати станом таймера"
override val confirmationRequiredDescription: String = "Завжди вимагати підтвердження перед початком раунду"
override val timerNameSizeIsInvalid: String = "Ім'я має бути в межах ${TimerName.SIZE_RANGE.first} й ${TimerName.SIZE_RANGE.last} символів."
override val timerDescriptionSizeIsInvalid: String = "Опис має бути в межах ${TimerDescription.SIZE_RANGE.first} й ${TimerDescription.SIZE_RANGE.last} символів."
override val timerNameSizeIsInvalid: String = "Ім'я має бути в межах 0 й 0 символів."
override val timerDescriptionSizeIsInvalid: String = "Опис має бути в межах 0 й 0 символів."
override val save: String = "Зберегти"
override val welcome: String = "Ласкаво просимо до TimeMates"
override val welcomeDescription: String = "Розкрийте Свою Продуктивність: Легко Організовуйте Завдання, Співпрацюйте Без Зусиль і Досягніть своїх Цілей."
Expand All @@ -62,6 +56,25 @@ object UkrainianStrings : Strings {
override val unauthorized: String = "Ваша авторизація була видалена або закінчився строк її дії."
override val unavailable: String = "Сервіс недоступний, спробуйте будь-ласка пізніше."
override val unsupported: String = "Дана функціональність ще не підтримується на сервері або клієнті, зв'яжіться з розробником."
override val fieldCannotBeEmpty: String = "Це поле не може бути пустим."

override fun minValueFailure(min: Number): String {
return "Мінімальне значення має відповідати $min."
}

override fun lengthExactFailure(size: Int): String {
return "Довжина тексту має бути мінімум $size."
}

override fun lengthRangeFailure(range: IntRange): String {
return "Довжина тексту має бути в межах від ${range.first} до ${range.last} символів."
}

override fun valueRangeFailure(first: Number, last: Number): String {
return "Діапазон значень має бути в рамках від $first до $last."
}

override val patternFailure: String = "Неправильний формат даних."

override fun internalError(message: String): String {
return "Внутрішня помилка серверу, деталі: $message."
Expand Down
Loading

0 comments on commit 9ceac1f

Please sign in to comment.