Skip to content

Commit

Permalink
Improve code readability
Browse files Browse the repository at this point in the history
  • Loading branch information
Iamlooker committed Dec 9, 2023
1 parent 23c1c98 commit 2efd20e
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 45 deletions.
1 change: 0 additions & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ trim_trailing_whitespace = true
[*.{kt,kts}]
ktlint_code_style = android_studio
indent_size = 4
ij_kotlin_packages_to_use_import_on_demand = **
ij_kotlin_name_count_to_use_star_import = 999
ij_kotlin_name_count_to_use_star_import_for_members = 999

Expand Down
74 changes: 37 additions & 37 deletions app/src/main/kotlin/com/looker/droidify/service/SyncService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,19 @@ import android.graphics.Color
import android.os.Build
import android.text.SpannableStringBuilder
import android.text.style.ForegroundColorSpan
import android.util.Log
import android.view.ContextThemeWrapper
import androidx.core.app.NotificationCompat
import androidx.fragment.app.Fragment
import com.looker.core.common.*
import com.looker.core.common.extension.*
import com.looker.core.common.Constants
import com.looker.core.common.DataSize
import com.looker.core.common.SdkCheck
import com.looker.core.common.extension.getColorFromAttr
import com.looker.core.common.extension.notificationManager
import com.looker.core.common.extension.percentBy
import com.looker.core.common.extension.startSelf
import com.looker.core.common.extension.stopForegroundCompat
import com.looker.core.common.result.Result
import com.looker.core.common.sdkAbove
import com.looker.core.datastore.SettingsRepository
import com.looker.core.domain.ProductItem
import com.looker.core.domain.Repository
Expand All @@ -30,10 +36,19 @@ import com.looker.droidify.database.Database
import com.looker.droidify.index.RepositoryUpdater
import com.looker.droidify.utility.extension.startUpdate
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.NonCancellable
import kotlinx.coroutines.cancel
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.sample
import kotlinx.coroutines.launch
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import kotlinx.coroutines.withContext
import java.lang.ref.WeakReference
import javax.inject.Inject
import com.looker.core.common.R as CommonR
Expand All @@ -45,32 +60,28 @@ import kotlinx.coroutines.Job as CoroutinesJob
class SyncService : ConnectionService<SyncService.Binder>() {

companion object {
private const val TAG = "SyncService"

private const val MAX_PROGRESS = 100

private const val NOTIFICATION_UPDATE_SAMPLING = 400L

private const val MAX_UPDATE_NOTIFICATION = 5
private const val ACTION_CANCEL = "${BuildConfig.APPLICATION_ID}.intent.action.CANCEL"

private val mutableStateSubject = MutableSharedFlow<State>()
private val mutableFinishState = MutableSharedFlow<Unit>()
private val syncState = MutableSharedFlow<State>()
private val onFinishState = MutableSharedFlow<Unit>()
}

@Inject
lateinit var settingsRepository: SettingsRepository

private sealed interface State {
data class Connecting(val name: String) : State
private sealed class State(val name: String) {
data class Connecting(val appName: String) : State(appName)
data class Syncing(
val name: String,
val appName: String,
val stage: RepositoryUpdater.Stage,
val read: DataSize,
val total: DataSize?
) : State

data object Finishing : State
) : State(appName)
}

private class Task(val repositoryId: Long, val manual: Boolean)
Expand All @@ -95,11 +106,11 @@ class SyncService : ConnectionService<SyncService.Binder>() {
enum class SyncRequest { AUTO, MANUAL, FORCE }

inner class Binder : android.os.Binder() {
val finish: SharedFlow<Unit>
get() = mutableFinishState.asSharedFlow()

val onFinish: SharedFlow<Unit>
get() = onFinishState.asSharedFlow()

private fun sync(ids: List<Long>, request: SyncRequest) {
Log.i(TAG, "Sync Started: ${request.name}")
val cancelledTask =
cancelCurrentTask { request == SyncRequest.FORCE && it.task?.repositoryId in ids }
cancelTasks { !it.manual && it.repositoryId in ids }
Expand Down Expand Up @@ -204,7 +215,7 @@ class SyncService : ConnectionService<SyncService.Binder>() {
}
downloadConnection.bind(this)
lifecycleScope.launch {
mutableStateSubject
syncState
.sample(NOTIFICATION_UPDATE_SAMPLING)
.collectLatest {
publishForegroundState(false, it)
Expand Down Expand Up @@ -301,15 +312,14 @@ class SyncService : ConnectionService<SyncService.Binder>() {
startForeground(
Constants.NOTIFICATION_ID_SYNCING,
stateNotificationBuilder.apply {
setContentTitle(getString(stringRes.syncing_FORMAT, state.name))
when (state) {
is State.Connecting -> {
setContentTitle(getString(stringRes.syncing_FORMAT, state.name))
setContentText(getString(stringRes.connecting))
setProgress(0, 0, true)
}

is State.Syncing -> {
setContentTitle(getString(stringRes.syncing_FORMAT, state.name))
when (state.stage) {
RepositoryUpdater.Stage.DOWNLOAD -> {
if (state.total != null) {
Expand All @@ -327,9 +337,7 @@ class SyncService : ConnectionService<SyncService.Binder>() {

RepositoryUpdater.Stage.PROCESS -> {
val progress = (state.read percentBy state.total)
.takeIf {
it != -1
}
.takeIf { it != -1 }
setContentText(
getString(
stringRes.processing_FORMAT,
Expand All @@ -356,12 +364,6 @@ class SyncService : ConnectionService<SyncService.Binder>() {
}
}
}

is State.Finishing -> {
setContentTitle(getString(stringRes.syncing))
setContentText(null)
setProgress(0, 0, true)
}
}::class
}.build()
)
Expand All @@ -388,7 +390,7 @@ class SyncService : ConnectionService<SyncService.Binder>() {
}
return
}
val task = tasks.removeFirstOrNull() ?: return
val task = tasks.removeFirst()
val repository = Database.RepositoryAdapter.get(task.repositoryId)
if (repository == null || !repository.enabled) handleNextTask(hasUpdates)
val lastStarted = started
Expand Down Expand Up @@ -431,9 +433,9 @@ class SyncService : ConnectionService<SyncService.Binder>() {
unstableUpdates
) { stage, progress, total ->
launch {
mutableStateSubject.emit(
syncState.emit(
State.Syncing(
name = repository.name,
appName = repository.name,
stage = stage,
read = DataSize(progress),
total = total?.let { DataSize(it) }
Expand Down Expand Up @@ -467,23 +469,21 @@ class SyncService : ConnectionService<SyncService.Binder>() {
) {
try {
if (!hasUpdates || !notifyUpdates) {
mutableFinishState.emit(Unit)
onFinishState.emit(Unit)
val needStop = started == Started.MANUAL
started = Started.NO
if (needStop) stopForegroundCompat()
return
}
val blocked = updateNotificationBlockerFragment?.get()?.isAdded == true
val updates = Database.ProductAdapter.getUpdates()
log("Updates: $currentTask", "SyncService")
if (!blocked && updates.isNotEmpty()) {
displayUpdatesNotification(updates)
if (autoUpdate) updateAllAppsInternal()
}
handleUpdates(hasUpdates = false, notifyUpdates = true, autoUpdate = autoUpdate)
} finally {
withContext(NonCancellable) {
log("Ending: $currentTask", "SyncService")
lock.withLock { currentTask = null }
handleNextTask(false)
}
Expand Down Expand Up @@ -574,7 +574,7 @@ class SyncService : ConnectionService<SyncService.Binder>() {
private val syncConnection =
Connection(SyncService::class.java, onBind = { connection, binder ->
jobScope.launch {
binder.finish.collect {
binder.onFinish.collect {
val params = syncParams
if (params != null) {
syncParams = null
Expand Down
5 changes: 5 additions & 0 deletions core/network/src/main/java/com/looker/network/Downloader.kt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ interface Downloader {
headers: HeadersBuilder.() -> Unit = {},
block: ProgressListener? = null
): NetworkResponse

companion object {
internal const val CONNECTION_TIMEOUT = 30_000L
internal const val SOCKET_TIMEOUT = 15_000L
}
}

typealias ProgressListener = suspend (bytesReceived: DataSize, contentLength: DataSize) -> Unit
20 changes: 13 additions & 7 deletions core/network/src/main/java/com/looker/network/KtorDownloader.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import com.looker.core.common.extension.exceptCancellation
import com.looker.core.common.extension.size
import com.looker.core.common.signature.FileValidator
import com.looker.core.common.signature.ValidationException
import com.looker.network.Downloader.Companion.CONNECTION_TIMEOUT
import com.looker.network.Downloader.Companion.SOCKET_TIMEOUT
import com.looker.network.header.HeadersBuilder
import com.looker.network.header.KtorHeadersBuilder
import io.ktor.client.HttpClient
Expand All @@ -23,19 +25,20 @@ import io.ktor.client.request.url
import io.ktor.client.statement.HttpResponse
import io.ktor.client.statement.bodyAsChannel
import io.ktor.http.HttpStatusCode
import io.ktor.http.URLParserException
import io.ktor.http.etag
import io.ktor.http.isSuccess
import io.ktor.http.lastModified
import io.ktor.utils.io.ByteReadChannel
import io.ktor.utils.io.core.ByteReadPacket
import io.ktor.utils.io.core.isEmpty
import io.ktor.utils.io.core.readBytes
import java.io.File
import java.io.IOException
import java.net.Proxy
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.isActive
import kotlinx.coroutines.withContext
import java.io.File
import java.io.IOException
import java.net.Proxy

internal class KtorDownloader : Downloader {

Expand Down Expand Up @@ -94,17 +97,20 @@ internal class KtorDownloader : Downloader {
} catch (e: ValidationException) {
target.delete()
NetworkResponse.Error.Validation(e)
} catch (e: Exception) {
e.exceptCancellation()
} catch (e: URLParserException) {
NetworkResponse.Error.Unknown(e)
} catch (e: IllegalStateException) {
NetworkResponse.Error.Unknown(e)
} catch (e: IllegalArgumentException) {
NetworkResponse.Error.Unknown(e)
}
}

companion object {

private fun HttpClientConfig<OkHttpConfig>.timeoutConfig() = install(HttpTimeout) {
connectTimeoutMillis = 30_000
socketTimeoutMillis = 15_000
connectTimeoutMillis = CONNECTION_TIMEOUT
socketTimeoutMillis = SOCKET_TIMEOUT
}

private fun createRequest(
Expand Down

0 comments on commit 2efd20e

Please sign in to comment.