Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

wear integration #6

Merged
merged 21 commits into from
Oct 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ androidApp/private_key.pepk
androidApp/google-services.json
androidApp/keystore.jks
desktop/build
wearApp/build
keys.properties
# iosApp
iosApp/Pods
Expand All @@ -38,6 +39,7 @@ modules/services/file_system/build
modules/services/xlsx/build
modules/services/xlsx/libs
modules/services/ads-yandex/build
modules/services/wear-messenger/build
# Features ----------------------------------
modules/features/dialog-confirm/build
modules/features/words-local/build
Expand Down
32 changes: 23 additions & 9 deletions androidApp/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ android {
applicationId = projectInfo.group
versionCode = gradleProperty("project.version.code").integer
versionName = projectInfo.versionString
setProperty("archivesBaseName", "${projectInfo.name}-${projectInfo.versionString}")
}
defaultConfig {
multiDexEnabled = true
Expand All @@ -32,9 +33,15 @@ android {
}

signingConfigs {
val secretKeyAlias = runCatching { secretProperty("KEY_ALIAS").string }.getOrNull() ?: ""
val secretKeyPassword = runCatching { secretProperty("KEY_PASSWORD").string }.getOrNull() ?: ""
val secretStorePassword = runCatching { secretProperty("STORE_PASSWORD").string }.getOrNull() ?: ""
val secretKeyAlias = runCatching {
secretProperty("KEY_ALIAS").string
}.getOrNull() ?: ""
val secretKeyPassword = runCatching {
secretProperty("KEY_PASSWORD").string
}.getOrNull() ?: ""
val secretStorePassword = runCatching {
secretProperty("STORE_PASSWORD").string
}.getOrNull() ?: ""
getByName("debug") {
if (file("keystore.jks").exists()) {
keyAlias = secretKeyAlias
Expand Down Expand Up @@ -79,16 +86,14 @@ android {
add("META-INF/LGPL2.1")
}
}
buildTypes {
// applicationVariants.all(
// com.makeevrserg.empireprojekt.mobile.ApplicationVariantAction(
// project
// )
// )
lint {
abortOnError = false
}
}

dependencies {
// Kotlin
implementation(libs.kotlin.serialization.json)
// Coroutines
implementation(libs.kotlin.coroutines.core)
implementation(libs.kotlin.coroutines.android)
Expand All @@ -114,13 +119,22 @@ dependencies {
implementation(libs.klibs.mikro.platform)
implementation(libs.klibs.kstorage)
implementation(libs.klibs.kdi)
// moko
implementation(libs.moko.resources.core)
// Decompose
implementation(libs.decompose.core)
implementation(libs.decompose.compose.jetpack)
implementation(libs.decompose.android)
implementation("com.google.android.gms:play-services-wearable:18.0.0")
// wear
implementation("com.google.android.horologist:horologist-datalayer:0.5.3")
// work
implementation("androidx.work:work-runtime:2.8.0")
implementation("androidx.work:work-runtime-ktx:2.8.0")
// Local
implementation(projects.modules.features.root)
implementation(projects.modules.features.ui)
implementation(projects.modules.services.coreUi)
implementation(projects.modules.services.resources)
implementation(projects.modules.services.wearMessenger)
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,36 +8,37 @@ import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.ModalBottomSheetLayout
import androidx.compose.runtime.getValue
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.core.view.WindowCompat
import com.arkivanov.decompose.defaultComponentContext
import com.makeevrserg.empireprojekt.mobile.application.App.Companion.asEmpireApp
import com.makeevrserg.empireprojekt.mobile.core.ui.rememberSlotModalBottomSheetState
import com.makeevrserg.empireprojekt.mobile.core.ui.theme.AppTheme
import com.makeevrserg.empireprojekt.mobile.features.root.DefaultRootBottomSheetComponent
import com.makeevrserg.empireprojekt.mobile.features.root.DefaultRootComponent
import com.makeevrserg.empireprojekt.mobile.features.root.di.RootModule
import com.makeevrserg.empireprojekt.mobile.features.root.modal.DefaultRootBottomSheetComponent
import com.makeevrserg.empireprojekt.mobile.features.ui.info.InfoScreen
import com.makeevrserg.empireprojekt.mobile.features.ui.root.ApplicationContent
import com.makeevrserg.empireprojekt.mobile.features.ui.root.ComposeApplication
import com.makeevrserg.empireprojekt.mobile.resources.R
import ru.astrainteractive.klibs.kdi.Provider
import ru.astrainteractive.klibs.kdi.getValue

@ExperimentalMaterialApi
@ExperimentalComposeUiApi
@ExperimentalAnimationApi
@ExperimentalFoundationApi
class MainActivity : ComponentActivity() {
private val rootModule by RootModule
private val servicesModule by rootModule.servicesModule
private val rootModule by Provider {
application.asEmpireApp().rootModule
}

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
WindowCompat.setDecorFitsSystemWindows(window, false)
setTheme(R.style.AppTheme)
val componentContext = defaultComponentContext()
val rootComponent = DefaultRootComponent(componentContext, rootModule, servicesModule)
val rootComponent = DefaultRootComponent(componentContext, rootModule)
val rootBottomSheetComponent = rootComponent.rootBottomSheetComponent

setContent {
Expand All @@ -51,7 +52,7 @@ class MainActivity : ComponentActivity() {
}
}
}
ComposeApplication(rootModule.themeSwitcher.value) {
ComposeApplication(rootModule.themeSwitcherComponent.value) {
ModalBottomSheetLayout(
sheetState = bottomSheetState.sheetState,
sheetContent = bottomSheetState.sheetContent.value,
Expand All @@ -60,7 +61,6 @@ class MainActivity : ComponentActivity() {
) {
ApplicationContent(
rootComponent = rootComponent,
rootBottomSheetComponent = rootBottomSheetComponent,
modifier = Modifier
)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,86 @@
package com.makeevrserg.empireprojekt.mobile.application

import android.app.Application
import android.content.Context
import androidx.work.ExistingPeriodicWorkPolicy
import androidx.work.PeriodicWorkRequest
import androidx.work.WorkManager
import com.google.android.horologist.annotations.ExperimentalHorologistApi
import com.google.android.horologist.data.WearDataLayerRegistry
import com.google.firebase.ktx.Firebase
import com.google.firebase.ktx.initialize
import com.makeevrserg.empireprojekt.mobile.features.root.di.RootModule
import com.makeevrserg.empireprojekt.mobile.features.root.di.impl.RootModuleImpl
import com.makeevrserg.empireprojekt.mobile.wear.messenger.di.WearMessengerModule
import com.makeevrserg.empireprojekt.mobile.work.CheckStatusWork
import kotlinx.coroutines.cancel
import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import ru.astrainteractive.klibs.kdi.getValue
import ru.astrainteractive.klibs.mikro.platform.DefaultAndroidPlatformConfiguration
import java.util.concurrent.TimeUnit
import kotlin.time.Duration.Companion.seconds

@OptIn(ExperimentalHorologistApi::class)
class App : Application() {
private val servicesModule by RootModule.servicesModule
val rootModule by lazy {
RootModuleImpl()
}
val wearMessengerModule by lazy {
WearMessengerModule.Default(
context = rootModule.servicesModule.platformConfiguration.value.applicationContext,
coroutineScope = rootModule.servicesModule.mainScope.value,
json = rootModule.servicesModule.jsonConfiguration.value
)
}
private val wearDataLayerRegistry by lazy {
WearDataLayerRegistry.fromContext(
application = applicationContext,
coroutineScope = rootModule.servicesModule.mainScope.value
)
}
private val messageClient by lazy {
wearDataLayerRegistry.messageClient
}

override fun onTerminate() {
super.onTerminate()
rootModule.servicesModule.mainScope.value.cancel()
}

override fun onCreate() {
super.onCreate()
Firebase.initialize(this)
servicesModule.platformConfiguration.initialize(
rootModule.servicesModule.platformConfiguration.initialize {
DefaultAndroidPlatformConfiguration(
applicationContext
)
)
}
scheduleWork()
}

private fun scheduleWork() {
val statusWork = PeriodicWorkRequest.Builder(
CheckStatusWork::class.java,
15,
TimeUnit.MINUTES
).build()
val instanceWorkManager = WorkManager.getInstance(applicationContext)

rootModule.servicesModule.mainScope.value.launch {
while (isActive) {
instanceWorkManager.enqueueUniquePeriodicWork(
CheckStatusWork::class.java.simpleName,
ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
statusWork
)
delay(30.seconds)
}
}
}

companion object {
fun Application.asEmpireApp(): App = (this as App)
fun Context.asEmpireApp(): App = (applicationContext as App)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package com.makeevrserg.empireprojekt.mobile.work

import android.content.Context
import android.util.Log
import androidx.work.CoroutineWorker
import androidx.work.WorkerParameters
import com.makeevrserg.empireprojekt.mobile.application.App.Companion.asEmpireApp
import com.makeevrserg.empireprojekt.mobile.features.status.StatusComponent
import com.makeevrserg.empireprojekt.mobile.wear.messenger.api.app.model.StatusModel
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.coroutineScope
import ru.astrainteractive.klibs.kdi.Provider
import ru.astrainteractive.klibs.kdi.getValue

class CheckStatusWork(
context: Context,
params: WorkerParameters
) : CoroutineWorker(context, params) {
private val wearMessengerModule by lazy {
applicationContext.asEmpireApp().wearMessengerModule
}
private val rootModule by lazy {
applicationContext.asEmpireApp().rootModule
}
private val rootStatusComponent by Provider {
rootModule.rootStatusComponent.value
}

override suspend fun doWork(): Result {
Log.d(TAG, "doWork: ")
sendStatus()
return Result.success()
}

private suspend fun sendStatus() = coroutineScope {
val messages = rootStatusComponent.statusComponents.map {
async {
it.checkStatus()
val model = it.model.value
StatusModel(
title = model.title.toString(applicationContext),
isLoading = model.isLoading,
status = when (model.status) {
StatusComponent.Model.LoadingStatus.LOADING -> StatusModel.LoadingStatus.LOADING
StatusComponent.Model.LoadingStatus.SUCCESS -> StatusModel.LoadingStatus.SUCCESS
StatusComponent.Model.LoadingStatus.ERROR -> StatusModel.LoadingStatus.ERROR
}
)
}
}.awaitAll()
wearMessengerModule.wearMessageProducer.produce(
message = wearMessengerModule.statusModelMessage,
value = messages
)
}

companion object {
private const val TAG = "CheckStatusWork"
}
}
4 changes: 2 additions & 2 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ makeevrserg.android.sdk.target=34
# Project
makeevrserg.project.name=EmpireProjektMobile
makeevrserg.project.group=com.makeevrserg.empireprojekt.mobile
makeevrserg.project.version.string=0.0.3
makeevrserg.project.version.code=5
makeevrserg.project.version.string=0.1.0
makeevrserg.project.version.code=6
makeevrserg.project.description=EmpireProjekt mobile application
makeevrserg.project.developers=makeevrserg|Makeev Roman|makeevrserg@gmail.com
makeevrserg.project.url=https://empireprojekt.ru
Expand Down
6 changes: 3 additions & 3 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
[versions]
# Kotlin
kotlin-version = "1.8.20"
kotlin-version = "1.9.0"
kotlin-dokka = "1.8.10"
kotlin-coroutines = "1.7.2"
kotlin-compilerExtensionVersion = "1.4.5"
kotlin-compilerExtensionVersion = "1.5.1"
kotlin-android-application = "8.0.1"
kotlin-serialization-json = "1.5.1"

Expand Down Expand Up @@ -55,7 +55,7 @@ klibs-kstorage = "1.0.0"
klibs-kdi = "1.1.0"

# Compose
kotlin-compose = "1.4.0"
kotlin-compose = "1.4.3"

# Moko
moko-mvvm = "0.16.1"
Expand Down
Binary file not shown.
6 changes: 3 additions & 3 deletions iosApp/iosApp/Presentation/Root/RootHolder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@ final class RootHolder {

init() {
lifecycle = LifecycleRegistryKt.LifecycleRegistry()
let platformConfiguration = DefaultIosPlatformConfiguration()
ServicesModuleCompanion.shared.platformConfiguration.initialize(value: platformConfiguration)
let platformConfiguration = DefaultNativePlatformConfiguration()
RootModuleCompanion.shared.servicesModule.platformConfiguration.initialize(value: platformConfiguration)
root = DefaultRootComponent(
componentContext: DefaultComponentContext(lifecycle: lifecycle),
rootModule: RootModuleCompanion.shared,
servicesModule: ServicesModuleCompanion.shared
servicesModule: RootModuleCompanion.shared.servicesModule
)
lifecycle.onCreate()
}
Expand Down
2 changes: 1 addition & 1 deletion iosApp/iosApp/Presentation/Root/RootView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ private struct ChildView: View {
case let child as DefaultRootComponentConfigurationSplash:
SplashView(root, child.splashComponent)
case let child as DefaultRootComponentConfigurationStatus:
StatusView(root, child.statusComponents)
StatusView(root, child.rootStatusComponent)
default:
EmptyView()
}
Expand Down
8 changes: 4 additions & 4 deletions iosApp/iosApp/Presentation/Status/StatusView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ import Root

struct StatusView: View {
let rootComponent: RootComponent
let statusComponents: [StatusComponent]
let statusComponent: RootStatusComponent

init(_ rootComponent: RootComponent, _ statusComponents: [StatusComponent]) {
self.statusComponents = statusComponents
init(_ rootComponent: RootComponent, _ statusComponent: RootStatusComponent) {
self.statusComponent = statusComponent
self.rootComponent = rootComponent
}
var body: some View {
Expand All @@ -27,7 +27,7 @@ struct StatusView: View {
Text(MR.strings.shared.status_subtitle.desc().localized())
.font(.body)

List(statusComponents,id: \.model.description) { statusComponent in
List(statusComponent.statusComponents,id: \.model.description) { statusComponent in
StatusWidget(statusComponent)
}.listStyle(.inset)
}
Expand Down
Loading
Loading