Add settings store/repo etc. to save user settings.
This commit is contained in:
		
							parent
							
								
									992c79a100
								
							
						
					
					
						commit
						2058a6a789
					
				
					 12 changed files with 238 additions and 19 deletions
				
			
		| 
						 | 
				
			
			@ -2,6 +2,7 @@ package com.pixelized.desktop.lwa
 | 
			
		|||
 | 
			
		||||
import com.pixelized.desktop.lwa.business.CharacterSheetUseCase
 | 
			
		||||
import com.pixelized.desktop.lwa.business.RollUseCase
 | 
			
		||||
import com.pixelized.desktop.lwa.business.SettingsUseCase
 | 
			
		||||
import com.pixelized.desktop.lwa.business.SkillStepUseCase
 | 
			
		||||
import com.pixelized.desktop.lwa.business.SkillValueComputationUseCase
 | 
			
		||||
import com.pixelized.desktop.lwa.parser.arithmetic.ArithmeticParser
 | 
			
		||||
| 
						 | 
				
			
			@ -11,6 +12,9 @@ import com.pixelized.desktop.lwa.repository.characterSheet.CharacterSheetStore
 | 
			
		|||
import com.pixelized.desktop.lwa.repository.characterSheet.SkillDescriptionFactory
 | 
			
		||||
import com.pixelized.desktop.lwa.repository.network.NetworkRepository
 | 
			
		||||
import com.pixelized.desktop.lwa.repository.roll_history.RollHistoryRepository
 | 
			
		||||
import com.pixelized.desktop.lwa.repository.settings.SettingsFactory
 | 
			
		||||
import com.pixelized.desktop.lwa.repository.settings.SettingsRepository
 | 
			
		||||
import com.pixelized.desktop.lwa.repository.settings.SettingsStore
 | 
			
		||||
import com.pixelized.desktop.lwa.screen.characterSheet.detail.CharacterSheetFactory
 | 
			
		||||
import com.pixelized.desktop.lwa.screen.characterSheet.detail.CharacterSheetViewModel
 | 
			
		||||
import com.pixelized.desktop.lwa.screen.characterSheet.edit.CharacterSheetEditFactory
 | 
			
		||||
| 
						 | 
				
			
			@ -21,6 +25,7 @@ import com.pixelized.desktop.lwa.screen.network.NetworkFactory
 | 
			
		|||
import com.pixelized.desktop.lwa.screen.network.NetworkViewModel
 | 
			
		||||
import com.pixelized.desktop.lwa.screen.roll.RollViewModel
 | 
			
		||||
import com.pixelized.desktop.lwa.screen.rollhistory.RollHistoryViewModel
 | 
			
		||||
import kotlinx.serialization.json.Json
 | 
			
		||||
import org.koin.core.module.dsl.factoryOf
 | 
			
		||||
import org.koin.core.module.dsl.singleOf
 | 
			
		||||
import org.koin.core.module.dsl.viewModelOf
 | 
			
		||||
| 
						 | 
				
			
			@ -28,19 +33,32 @@ import org.koin.dsl.module
 | 
			
		|||
 | 
			
		||||
val moduleDependencies
 | 
			
		||||
    get() = listOf(
 | 
			
		||||
        toolsDependencies,
 | 
			
		||||
        parserDependencies,
 | 
			
		||||
        factoryDependencies,
 | 
			
		||||
        useCaseDependencies,
 | 
			
		||||
        storeDependencies,
 | 
			
		||||
        repositoryDependencies,
 | 
			
		||||
        viewModelDependencies,
 | 
			
		||||
        useCaseDependencies,
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
val toolsDependencies
 | 
			
		||||
    get() = module {
 | 
			
		||||
        factory { Json { explicitNulls = false } }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
val storeDependencies
 | 
			
		||||
    get() = module {
 | 
			
		||||
        singleOf(::CharacterSheetStore)
 | 
			
		||||
        singleOf(::SettingsStore)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
val repositoryDependencies
 | 
			
		||||
    get() = module {
 | 
			
		||||
        singleOf(::CharacterSheetStore)
 | 
			
		||||
        singleOf(::NetworkRepository)
 | 
			
		||||
        singleOf(::CharacterSheetRepository)
 | 
			
		||||
        singleOf(::RollHistoryRepository)
 | 
			
		||||
        singleOf(::SettingsRepository)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
val factoryDependencies
 | 
			
		||||
| 
						 | 
				
			
			@ -51,6 +69,7 @@ val factoryDependencies
 | 
			
		|||
        factoryOf(::NetworkFactory)
 | 
			
		||||
        factoryOf(::SkillFieldFactory)
 | 
			
		||||
        factoryOf(::SkillDescriptionFactory)
 | 
			
		||||
        factoryOf(::SettingsFactory)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
val viewModelDependencies
 | 
			
		||||
| 
						 | 
				
			
			@ -74,4 +93,5 @@ val useCaseDependencies
 | 
			
		|||
        factoryOf(::RollUseCase)
 | 
			
		||||
        factoryOf(::SkillValueComputationUseCase)
 | 
			
		||||
        factoryOf(::CharacterSheetUseCase)
 | 
			
		||||
        factoryOf(::SettingsUseCase)
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,10 @@
 | 
			
		|||
package com.pixelized.desktop.lwa.business
 | 
			
		||||
 | 
			
		||||
import com.pixelized.desktop.lwa.repository.settings.model.Settings
 | 
			
		||||
 | 
			
		||||
class SettingsUseCase {
 | 
			
		||||
 | 
			
		||||
    fun defaultSettings(): Settings = Settings(
 | 
			
		||||
        playerName = "",
 | 
			
		||||
    )
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -3,6 +3,7 @@ package com.pixelized.desktop.lwa.repository.characterSheet
 | 
			
		|||
import com.pixelized.desktop.lwa.repository.characterSheet.model.CharacterSheet
 | 
			
		||||
import kotlinx.coroutines.CoroutineScope
 | 
			
		||||
import kotlinx.coroutines.Dispatchers
 | 
			
		||||
import kotlinx.coroutines.Job
 | 
			
		||||
import kotlinx.coroutines.flow.MutableStateFlow
 | 
			
		||||
import kotlinx.coroutines.flow.SharingStarted
 | 
			
		||||
import kotlinx.coroutines.flow.StateFlow
 | 
			
		||||
| 
						 | 
				
			
			@ -12,7 +13,7 @@ import kotlinx.coroutines.flow.stateIn
 | 
			
		|||
class CharacterSheetRepository(
 | 
			
		||||
    private val store: CharacterSheetStore,
 | 
			
		||||
) {
 | 
			
		||||
    private val scope = CoroutineScope(Dispatchers.IO)
 | 
			
		||||
    private val scope = CoroutineScope(Dispatchers.IO + Job())
 | 
			
		||||
 | 
			
		||||
    private val sheets = store.characterSheetFlow()
 | 
			
		||||
        .stateIn(
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -15,9 +15,9 @@ import java.io.File
 | 
			
		|||
 | 
			
		||||
class CharacterSheetStore(
 | 
			
		||||
    private val factory: CharacterSheetJsonFactory,
 | 
			
		||||
    private val jsonFormatter: Json,
 | 
			
		||||
) {
 | 
			
		||||
    private val characterDirectory = File(characterStorePath()).also { it.mkdirs() }
 | 
			
		||||
    private val jsonFormatter: Json = Json { explicitNulls = false }
 | 
			
		||||
    private val flow = MutableStateFlow<List<CharacterSheet>>(value = emptyList())
 | 
			
		||||
 | 
			
		||||
    init {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,6 +5,7 @@ package com.pixelized.desktop.lwa.repository.network
 | 
			
		|||
//import io.ktor.server.netty.NettyApplicationEngine
 | 
			
		||||
import com.pixelized.desktop.lwa.repository.network.helper.client
 | 
			
		||||
import com.pixelized.desktop.lwa.repository.network.helper.connectWebSocket
 | 
			
		||||
import com.pixelized.desktop.lwa.repository.settings.SettingsRepository
 | 
			
		||||
import com.pixelized.desktop.lwa.utils.extention.decodeFromFrame
 | 
			
		||||
import com.pixelized.desktop.lwa.utils.extention.encodeToFrame
 | 
			
		||||
import com.pixelized.server.lwa.SERVER_PORT
 | 
			
		||||
| 
						 | 
				
			
			@ -26,7 +27,9 @@ import kotlinx.serialization.json.Json
 | 
			
		|||
 | 
			
		||||
typealias Client = HttpClient
 | 
			
		||||
 | 
			
		||||
class NetworkRepository {
 | 
			
		||||
class NetworkRepository(
 | 
			
		||||
    private val settingsRepository: SettingsRepository,
 | 
			
		||||
) {
 | 
			
		||||
    companion object {
 | 
			
		||||
        const val DEFAULT_PORT = SERVER_PORT
 | 
			
		||||
        const val DEFAULT_HOST = "pixelized.freeboxos.fr"
 | 
			
		||||
| 
						 | 
				
			
			@ -40,15 +43,9 @@ class NetworkRepository {
 | 
			
		|||
    private val incomingMessageBuffer = MutableSharedFlow<Message>()
 | 
			
		||||
    val data: SharedFlow<Message> get() = incomingMessageBuffer
 | 
			
		||||
 | 
			
		||||
    private val _player = MutableStateFlow("")
 | 
			
		||||
    val player: StateFlow<String> get() = _player
 | 
			
		||||
 | 
			
		||||
    private val _status = MutableStateFlow(Status.DISCONNECTED)
 | 
			
		||||
    val status: StateFlow<Status> get() = _status
 | 
			
		||||
 | 
			
		||||
    fun onPlayerNameChange(player: String) {
 | 
			
		||||
        _player.value = player
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun connect(
 | 
			
		||||
        host: String,
 | 
			
		||||
| 
						 | 
				
			
			@ -101,11 +98,12 @@ class NetworkRepository {
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    suspend fun share(
 | 
			
		||||
        playerName: String = settingsRepository.settings().playerName,
 | 
			
		||||
        content: MessageContent,
 | 
			
		||||
    ) {
 | 
			
		||||
        if (status.value == Status.CONNECTED) {
 | 
			
		||||
            val message = Message(
 | 
			
		||||
                from = player.value,
 | 
			
		||||
                from = playerName,
 | 
			
		||||
                value = content,
 | 
			
		||||
            )
 | 
			
		||||
            // emit the message into the outgoing buffer
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,38 @@
 | 
			
		|||
package com.pixelized.desktop.lwa.repository.settings
 | 
			
		||||
 | 
			
		||||
import com.pixelized.desktop.lwa.business.SettingsUseCase
 | 
			
		||||
import com.pixelized.desktop.lwa.repository.settings.model.Settings
 | 
			
		||||
import com.pixelized.desktop.lwa.repository.settings.model.SettingsJson
 | 
			
		||||
import com.pixelized.desktop.lwa.repository.settings.model.SettingsJsonV1
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class SettingsFactory(
 | 
			
		||||
    private val useCase: SettingsUseCase,
 | 
			
		||||
) {
 | 
			
		||||
 | 
			
		||||
    fun convertToJson(
 | 
			
		||||
        settings: Settings,
 | 
			
		||||
    ): SettingsJson {
 | 
			
		||||
        return SettingsJsonV1(
 | 
			
		||||
            playerName = settings.playerName,
 | 
			
		||||
        )
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun convertFromJson(
 | 
			
		||||
        json: SettingsJson,
 | 
			
		||||
    ): Settings {
 | 
			
		||||
        return when (json) {
 | 
			
		||||
            is SettingsJsonV1 -> convertFromJsonV1(json)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun convertFromJsonV1(
 | 
			
		||||
        json: SettingsJsonV1,
 | 
			
		||||
    ): Settings {
 | 
			
		||||
        return with(useCase.defaultSettings()) {
 | 
			
		||||
            Settings(
 | 
			
		||||
                playerName = json.playerName ?: playerName
 | 
			
		||||
            )
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,36 @@
 | 
			
		|||
package com.pixelized.desktop.lwa.repository.settings
 | 
			
		||||
 | 
			
		||||
import com.pixelized.desktop.lwa.business.SettingsUseCase
 | 
			
		||||
import com.pixelized.desktop.lwa.repository.settings.model.Settings
 | 
			
		||||
import kotlinx.coroutines.CoroutineScope
 | 
			
		||||
import kotlinx.coroutines.Dispatchers
 | 
			
		||||
import kotlinx.coroutines.Job
 | 
			
		||||
import kotlinx.coroutines.flow.SharingStarted
 | 
			
		||||
import kotlinx.coroutines.flow.StateFlow
 | 
			
		||||
import kotlinx.coroutines.flow.stateIn
 | 
			
		||||
 | 
			
		||||
class SettingsRepository(
 | 
			
		||||
    private val store: SettingsStore,
 | 
			
		||||
    private val useCase: SettingsUseCase,
 | 
			
		||||
) {
 | 
			
		||||
    private val scope = CoroutineScope(Dispatchers.IO + Job())
 | 
			
		||||
 | 
			
		||||
    private val settings = store.settingsFlow()
 | 
			
		||||
        .stateIn(
 | 
			
		||||
            scope = scope,
 | 
			
		||||
            started = SharingStarted.Eagerly,
 | 
			
		||||
            initialValue = useCase.defaultSettings()
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    fun settingsFlow(): StateFlow<Settings> = settings
 | 
			
		||||
 | 
			
		||||
    fun settings(): Settings = settings.value
 | 
			
		||||
 | 
			
		||||
    fun update(settings: Settings) {
 | 
			
		||||
        store.save(settings = settings)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun reset() {
 | 
			
		||||
        store.save(settings = useCase.defaultSettings())
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,90 @@
 | 
			
		|||
package com.pixelized.desktop.lwa.repository.settings
 | 
			
		||||
 | 
			
		||||
import com.pixelized.desktop.lwa.business.SettingsUseCase
 | 
			
		||||
import com.pixelized.desktop.lwa.repository.settings.model.Settings
 | 
			
		||||
import com.pixelized.desktop.lwa.repository.settings.model.SettingsJson
 | 
			
		||||
import com.pixelized.desktop.lwa.repository.storePath
 | 
			
		||||
import kotlinx.coroutines.CoroutineScope
 | 
			
		||||
import kotlinx.coroutines.Dispatchers
 | 
			
		||||
import kotlinx.coroutines.Job
 | 
			
		||||
import kotlinx.coroutines.flow.MutableStateFlow
 | 
			
		||||
import kotlinx.coroutines.flow.StateFlow
 | 
			
		||||
import kotlinx.coroutines.launch
 | 
			
		||||
import kotlinx.serialization.encodeToString
 | 
			
		||||
import kotlinx.serialization.json.Json
 | 
			
		||||
import java.io.File
 | 
			
		||||
 | 
			
		||||
class SettingsStore(
 | 
			
		||||
    private val factory: SettingsFactory,
 | 
			
		||||
    private val useCase: SettingsUseCase,
 | 
			
		||||
    private val jsonFormatter: Json,
 | 
			
		||||
) {
 | 
			
		||||
    private val settingsDirectory = File(storePath()).also { it.mkdirs() }
 | 
			
		||||
    private val flow = MutableStateFlow(value = useCase.defaultSettings())
 | 
			
		||||
 | 
			
		||||
    fun settingsFlow(): StateFlow<Settings> = flow
 | 
			
		||||
 | 
			
		||||
    init {
 | 
			
		||||
        val scope = CoroutineScope(Dispatchers.IO + Job())
 | 
			
		||||
        scope.launch {
 | 
			
		||||
            flow.value = load()
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Throws(
 | 
			
		||||
        SettingsStoreException::class,
 | 
			
		||||
        FileWriteException::class,
 | 
			
		||||
        JsonConversionException::class,
 | 
			
		||||
    )
 | 
			
		||||
    fun save(settings: Settings) {
 | 
			
		||||
        val json = try {
 | 
			
		||||
            factory.convertToJson(settings = settings).let(jsonFormatter::encodeToString)
 | 
			
		||||
        } catch (exception: Exception) {
 | 
			
		||||
            throw JsonConversionException(root = exception)
 | 
			
		||||
        }
 | 
			
		||||
        try {
 | 
			
		||||
            val file = settingsFile()
 | 
			
		||||
            file.writeText(
 | 
			
		||||
                text = json,
 | 
			
		||||
                charset = Charsets.UTF_8,
 | 
			
		||||
            )
 | 
			
		||||
        } catch (exception: Exception) {
 | 
			
		||||
            throw FileWriteException(
 | 
			
		||||
                root = exception
 | 
			
		||||
            )
 | 
			
		||||
        }
 | 
			
		||||
        flow.value = settings
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun load(): Settings {
 | 
			
		||||
        return settingsFile().let { file ->
 | 
			
		||||
            val json = try {
 | 
			
		||||
                file.readText(charset = Charsets.UTF_8)
 | 
			
		||||
            } catch (exception: Exception) {
 | 
			
		||||
                throw FileReadException(
 | 
			
		||||
                    root = exception
 | 
			
		||||
                )
 | 
			
		||||
            }
 | 
			
		||||
            if (json.isBlank()) {
 | 
			
		||||
                return useCase.defaultSettings()
 | 
			
		||||
            }
 | 
			
		||||
            try {
 | 
			
		||||
                factory.convertFromJson(
 | 
			
		||||
                    json = jsonFormatter.decodeFromString<SettingsJson>(json)
 | 
			
		||||
                )
 | 
			
		||||
            } catch (exception: Exception) {
 | 
			
		||||
                throw JsonConversionException(root = exception)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun settingsFile(): File {
 | 
			
		||||
        return File("${storePath()}settings.json")
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    sealed class SettingsStoreException(root: Exception) : Exception(root)
 | 
			
		||||
    class JsonConversionException(root: Exception) : SettingsStoreException(root)
 | 
			
		||||
    class FileWriteException(root: Exception) : SettingsStoreException(root)
 | 
			
		||||
    class FileReadException(root: Exception) : SettingsStoreException(root)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,5 @@
 | 
			
		|||
package com.pixelized.desktop.lwa.repository.settings.model
 | 
			
		||||
 | 
			
		||||
data class Settings(
 | 
			
		||||
    val playerName: String,
 | 
			
		||||
)
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,6 @@
 | 
			
		|||
package com.pixelized.desktop.lwa.repository.settings.model
 | 
			
		||||
 | 
			
		||||
import kotlinx.serialization.Serializable
 | 
			
		||||
 | 
			
		||||
@Serializable
 | 
			
		||||
sealed interface SettingsJson
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,8 @@
 | 
			
		|||
package com.pixelized.desktop.lwa.repository.settings.model
 | 
			
		||||
 | 
			
		||||
import kotlinx.serialization.Serializable
 | 
			
		||||
 | 
			
		||||
@Serializable
 | 
			
		||||
data class SettingsJsonV1(
 | 
			
		||||
    val playerName: String?,
 | 
			
		||||
) : SettingsJson
 | 
			
		||||
| 
						 | 
				
			
			@ -12,13 +12,16 @@ import androidx.lifecycle.viewModelScope
 | 
			
		|||
import com.pixelized.desktop.lwa.composable.blur.BlurContentController
 | 
			
		||||
import com.pixelized.desktop.lwa.composable.error.snack.ErrorSnackUio
 | 
			
		||||
import com.pixelized.desktop.lwa.repository.network.NetworkRepository
 | 
			
		||||
import com.pixelized.desktop.lwa.repository.settings.SettingsRepository
 | 
			
		||||
import com.pixelized.desktop.lwa.utils.extention.collectAsState
 | 
			
		||||
import kotlinx.coroutines.flow.MutableSharedFlow
 | 
			
		||||
import kotlinx.coroutines.flow.SharedFlow
 | 
			
		||||
import kotlinx.coroutines.launch
 | 
			
		||||
 | 
			
		||||
class NetworkViewModel(
 | 
			
		||||
    private val repository: NetworkRepository,
 | 
			
		||||
    private val factory: NetworkFactory
 | 
			
		||||
    private val settingsRepository: SettingsRepository,
 | 
			
		||||
    private val networkRepository: NetworkRepository,
 | 
			
		||||
    private val factory: NetworkFactory,
 | 
			
		||||
) : ViewModel() {
 | 
			
		||||
    private val host = mutableStateOf(NetworkRepository.DEFAULT_HOST)
 | 
			
		||||
    private val port = mutableStateOf(NetworkRepository.DEFAULT_PORT)
 | 
			
		||||
| 
						 | 
				
			
			@ -38,8 +41,8 @@ class NetworkViewModel(
 | 
			
		|||
        @Composable
 | 
			
		||||
        @Stable
 | 
			
		||||
        get() {
 | 
			
		||||
            val player = repository.player.collectAsState()
 | 
			
		||||
            val status = repository.status.collectAsState()
 | 
			
		||||
            val player = settingsRepository.settingsFlow().collectAsState { it.playerName }
 | 
			
		||||
            val status = networkRepository.status.collectAsState()
 | 
			
		||||
            return remember {
 | 
			
		||||
                derivedStateOf {
 | 
			
		||||
                    factory.convertToUio(
 | 
			
		||||
| 
						 | 
				
			
			@ -53,7 +56,11 @@ class NetworkViewModel(
 | 
			
		|||
        }
 | 
			
		||||
 | 
			
		||||
    fun onPlayerNameChange(player: String) {
 | 
			
		||||
        repository.onPlayerNameChange(player = player)
 | 
			
		||||
        settingsRepository.update(
 | 
			
		||||
            settings = settingsRepository.settings().copy(
 | 
			
		||||
                playerName = player,
 | 
			
		||||
            )
 | 
			
		||||
        )
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun onPortChange(port: String) {
 | 
			
		||||
| 
						 | 
				
			
			@ -68,7 +75,7 @@ class NetworkViewModel(
 | 
			
		|||
        controller.show()
 | 
			
		||||
        _isLoading.value = true
 | 
			
		||||
 | 
			
		||||
        repository.connect(
 | 
			
		||||
        networkRepository.connect(
 | 
			
		||||
            host = host.value,
 | 
			
		||||
            port = port.value,
 | 
			
		||||
            onConnect = {
 | 
			
		||||
| 
						 | 
				
			
			@ -86,6 +93,6 @@ class NetworkViewModel(
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    fun disconnect() {
 | 
			
		||||
        repository.disconnect()
 | 
			
		||||
        networkRepository.disconnect()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue