Skip to content

Commit c4d5f5d

Browse files
sentinelwebsentinelweb
authored andcommitted
#496 - completed queue, save MemoryTransfersService.kt state onStop for android (destroy and terminate dint get called during dev reinstall)
1 parent ab987dd commit c4d5f5d

File tree

11 files changed

+80
-81
lines changed

11 files changed

+80
-81
lines changed

app/src/main/java/uk/co/sentinelweb/cuer/app/CuerApp.kt

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ import uk.co.sentinelweb.cuer.app.util.permission.NotificationChannelCreator
2020
import uk.co.sentinelweb.cuer.app.util.share.SharingShortcutsManager
2121
import uk.co.sentinelweb.cuer.app.util.wrapper.ServiceWrapper
2222
import uk.co.sentinelweb.cuer.app.util.wrapper.ServiceWrapper.Companion.SERVICE_NOT_FOUND
23-
import uk.co.sentinelweb.cuer.app.util.wrapper.StethoWrapper
2423
import uk.co.sentinelweb.cuer.app.work.WorkManagerInteractor
2524
import uk.co.sentinelweb.cuer.core.wrapper.LogWrapper
2625
import uk.co.sentinelweb.cuer.core.wrapper.WifiStateProvider
@@ -29,7 +28,6 @@ import kotlin.time.ExperimentalTime
2928
@ExperimentalTime
3029
class CuerApp : Application() {
3130

32-
private val stethoWrapper: StethoWrapper by inject()
3331
private val sharingShortcutsManager: SharingShortcutsManager by inject()
3432
private val databaseInit: DatabaseInitializer by inject()
3533
private val firebaseWrapper: FirebaseWrapper by inject()
@@ -59,8 +57,8 @@ class CuerApp : Application() {
5957
modules(Modules.allModules)
6058
}
6159
sharedApp.onCreate()
60+
6261
castSessionListener.listen()
63-
stethoWrapper.init()
6462
sharingShortcutsManager.apply {
6563
removeAllDirectShareTargets(this@CuerApp)
6664
pushDirectShareTargets(this@CuerApp)
@@ -82,6 +80,7 @@ class CuerApp : Application() {
8280

8381
override fun onTerminate() {
8482
super.onTerminate()
83+
// note TransfersService.saveState also called in MainActivity onStop - since this deosnt run when the process is killed
8584
sharedApp.onDestroy()
8685
castSessionListener.destroy()
8786
if (castServiceManager.isRunning()) {

app/src/main/java/uk/co/sentinelweb/cuer/app/di/Modules.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,6 @@ object Modules {
280280

281281
private val wrapperModule = module {
282282
factory { ToastWrapper(androidApplication()) }
283-
factory { StethoWrapper(androidApplication()) }
284283
factory { NotificationWrapper(androidApplication()) }
285284
factory { ResourceWrapper(androidApplication()) }
286285
factory<StringDecoder> { get<ResourceWrapper>() }

app/src/main/java/uk/co/sentinelweb/cuer/app/ui/main/MainContract.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ interface MainContract {
8585
linkScanner = get(),
8686
mediaOrchestrator = get(),
8787
playlistOrchestrator = get(),
88+
transfersService = get(),
8889
)
8990
}
9091
scoped {

app/src/main/java/uk/co/sentinelweb/cuer/app/ui/main/MainPresenter.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import uk.co.sentinelweb.cuer.app.orchestrator.OrchestratorContract.Source.LOCAL
77
import uk.co.sentinelweb.cuer.app.orchestrator.PlaylistOrchestrator
88
import uk.co.sentinelweb.cuer.app.orchestrator.flatOptions
99
import uk.co.sentinelweb.cuer.app.ui.cast.CastController
10+
import uk.co.sentinelweb.cuer.app.ui.filebrowser.transfers.TransfersContract
1011
import uk.co.sentinelweb.cuer.app.ui.ytplayer.floating.FloatingPlayerContract
1112
import uk.co.sentinelweb.cuer.app.util.chromecast.listener.ChromecastContract
1213
import uk.co.sentinelweb.cuer.app.util.permission.NotificationPermissionCheckDialog
@@ -31,6 +32,7 @@ class MainPresenter(
3132
private val linkScanner: LinkScanner,
3233
private val mediaOrchestrator: MediaOrchestrator,
3334
private val playlistOrchestrator: PlaylistOrchestrator,
35+
private val transfersService: TransfersContract.Service,
3436
) : MainContract.Presenter {
3537

3638
init {
@@ -82,6 +84,7 @@ class MainPresenter(
8284
ytContextHolder.mainPlayerControls = null
8385
if (!view.isRecreating()) {
8486
castController.switchToService()
87+
transfersService.saveState()
8588
}
8689
}
8790

app/src/main/java/uk/co/sentinelweb/cuer/app/util/wrapper/StethoWrapper.kt

Lines changed: 0 additions & 11 deletions
This file was deleted.

app/src/main/res/xml/network_security_config.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<!-- This file is generated from the build.gradle.kts-->
33
<network-security-config>
44

5-
<domain-config cleartextTrafficPermitted="true">
5+
<domain-config cleartextTrafficPermitted="true">
66
<domain includeSubdomains="false">192.168.0.1</domain>
77
<domain includeSubdomains="false">192.168.0.2</domain>
88
<domain includeSubdomains="false">192.168.0.3</domain>

shared/src/commonMain/kotlin/uk/co/sentinelweb/cuer/app/service/transfers/MemoryTransfersService.kt

Lines changed: 55 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,17 @@ class MemoryTransfersService(
3838

3939
private val _stateObservable = MutableStateFlow(initialState)
4040

41-
override val queueFlow: Flow<List<TransferDomain>>
41+
override val transfersFlow: Flow<List<TransferDomain>>
4242
get() = _stateObservable
43-
.map { it.queue }
43+
.map { it.queue + it.completed }
44+
.distinctUntilChanged()
45+
4446
override val queue: List<TransferDomain>
4547
get() = _stateObservable.value.queue
4648

49+
override val completed: List<TransferDomain>
50+
get() = _stateObservable.value.completed
51+
4752
init {
4853
log.tag(this)
4954
executeTransferUseCase.progressFlow
@@ -70,57 +75,55 @@ class MemoryTransfersService(
7075

7176
override fun addReplaceTransfer(domain: TransferDomain): TransferDomain {
7277
val cleaned = cleanTransfer(domain)
73-
val updated = _stateObservable.value.queue.let { queue ->
74-
if (cleaned.id == null) {
75-
createId(cleaned)
76-
.let { it to (queue + it) }
77-
} else {
78-
queue.indexOfFirst { it.id == cleaned.id }
79-
.takeIf { it >= 0 }
80-
?.let { cleaned to queue.toMutableList().apply { set(it, cleaned) } }
81-
?: let {
82-
cleaned
83-
.let { it to (queue + it) }
84-
}
78+
return if (cleaned.status == Complete) {
79+
val updatedQueue = queue.toMutableList().apply { removeAll { it.id == cleaned.id } }
80+
val updateCompleted = completed.indexOfFirst { it.id == cleaned.id }
81+
.takeIf { it >= 0 }
82+
?.let { completed.toMutableList().apply { set(it, cleaned) } }
83+
?: let { completed + cleaned }
84+
85+
_stateObservable.update {
86+
it.copy(
87+
queue = updatedQueue,
88+
completed = updateCompleted
89+
)
90+
}
91+
cleaned
92+
} else {
93+
val updated = queue.let { queue ->
94+
if (cleaned.id == null) {
95+
createId(cleaned)
96+
.let { it to (queue + it) }
97+
} else {
98+
queue.indexOfFirst { it.id == cleaned.id }
99+
.takeIf { it >= 0 }
100+
?.let { cleaned to queue.toMutableList().apply { set(it, cleaned) } }
101+
?: let {
102+
cleaned
103+
.let { it to (queue + it) }
104+
}
105+
}
85106
}
107+
_stateObservable.update { it.copy(queue = updated.second) }
108+
updated.first
86109
}
87-
_stateObservable.update { it.copy(queue = updated.second) }
88-
return updated.first
89110
}
90111

91-
private fun cleanTransfer(domain: TransferDomain): TransferDomain = domain.copy(
92-
target = domain.target?.copy(
93-
path = ((domain.target?.path as? PlaylistDomain) ?: error("target path is not a playlist"))
94-
.copy(items = listOf()),
95-
)
96-
)
97-
98112
override fun removeTransfer(domain: TransferDomain): Boolean {
99113
return removeTransfer(domain.id ?: return false)
100114
}
101115

102-
override fun removeTransfer(id: Identifier<GUID>): Boolean {
103-
val queue1 = _stateObservable.value.queue
104-
val result =
105-
queue1
106-
.find { it.id == id }
107-
?.also { _stateObservable.update { it.copy(queue = queue1.filterNot { it.id == id }) } }
108-
?.let { true }
109-
?: let { false }
110-
return result
111-
}
112-
113-
override fun replaceTransfer(transfer: TransferDomain): Boolean {
114-
return queue.indexOfFirst { it.id == transfer.id }
115-
.takeIf { it >= 0 }
116-
?.let { index ->
117-
_stateObservable.update { last ->
118-
last.copy(queue = last.queue.toMutableList().apply { set(index, transfer) })
119-
}
120-
true
121-
} ?: false
122-
123-
}
116+
override fun removeTransfer(id: Identifier<GUID>): Boolean =
117+
queue
118+
.find { it.id == id }
119+
?.also { _stateObservable.update { it.copy(queue = queue.filterNot { it.id == id }) } }
120+
?.let { true }
121+
?: let {
122+
completed.find { it.id == id }
123+
?.also { _stateObservable.update { it.copy(completed = completed.filterNot { it.id == id }) } }
124+
?.let { true }
125+
}
126+
?: let { false }
124127

125128
override fun hasId(id: Identifier<GUID>?): Boolean =
126129
queue.any { it.id == id }
@@ -129,6 +132,13 @@ class MemoryTransfersService(
129132
dataStore.save(_stateObservable.value)
130133
}
131134

135+
private fun cleanTransfer(domain: TransferDomain): TransferDomain = domain.copy(
136+
target = domain.target?.copy(
137+
path = ((domain.target?.path as? PlaylistDomain) ?: error("target path is not a playlist"))
138+
.copy(items = listOf()),
139+
)
140+
)
141+
132142
private fun createId(domain: TransferDomain): TransferDomain =
133143
domain.copy(
134144
id = Identifier(

shared/src/commonMain/kotlin/uk/co/sentinelweb/cuer/app/service/transfers/TransfersDataStore.kt

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import io.ktor.utils.io.charsets.*
22
import io.ktor.utils.io.core.*
33
import kotlinx.serialization.encodeToString
4-
import kotlinx.serialization.json.Json
54
import uk.co.sentinelweb.cuer.app.db.repository.file.AFile
65
import uk.co.sentinelweb.cuer.app.db.repository.file.PlatformFileOperation
76
import uk.co.sentinelweb.cuer.app.ui.filebrowser.transfers.TransfersContract
87
import uk.co.sentinelweb.cuer.core.wrapper.LogWrapper
8+
import uk.co.sentinelweb.cuer.domain.ext.domainJsonSerializer
99

1010
class SimpleTransfersDataStore(
1111
private val file: AFile,
@@ -20,26 +20,22 @@ class SimpleTransfersDataStore(
2020
var state: TransfersContract.Service.State = TransfersContract.Service.State.Initial
2121
private set
2222

23-
private val json = Json {
24-
ignoreUnknownKeys = true
25-
prettyPrint = true
26-
}
27-
2823
override fun load(): TransfersContract.Service.State {
2924
return try {
3025
fileOperations.readBytes(file)
3126
.decodeToString()
32-
.let { jsonString -> json.decodeFromString<TransfersContract.Service.State>(jsonString) }
27+
.let { jsonString -> domainJsonSerializer.decodeFromString<TransfersContract.Service.State>(jsonString) }
3328
.also { state = it }
3429
} catch (e: Exception) {
35-
log.e("Couldn't load state", e)
30+
log.e("Couldn't load state: ${e.message}")
3631
TransfersContract.Service.State.Initial
3732
}
3833
}
3934

4035
override fun save(state: TransfersContract.Service.State) {
4136
if (this.state != state) {
42-
val jsonString = json.encodeToString(state)
37+
log.d("save transfers state")
38+
val jsonString = domainJsonSerializer.encodeToString(state)
4339
fileOperations.writeBytes(file, jsonString.toByteArray(Charset.forName("UTF-8")))
4440
this.state = state
4541
}

shared/src/commonMain/kotlin/uk/co/sentinelweb/cuer/app/ui/filebrowser/transfers/TransfersContract.kt

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,23 +15,25 @@ interface TransfersContract {
1515

1616
interface Service {
1717
val queue: List<TransferDomain>
18-
val queueFlow: Flow<List<TransferDomain>>
18+
val completed: List<TransferDomain>
19+
val transfersFlow: Flow<List<TransferDomain>>
1920

2021
fun addReplaceTransfer(domain: TransferDomain): TransferDomain
2122
fun removeTransfer(domain: TransferDomain): Boolean
2223
fun removeTransfer(id: Identifier<GUID>): Boolean
23-
fun replaceTransfer(transfer: TransferDomain): Boolean
2424
fun hasId(id: Identifier<GUID>?): Boolean
2525
fun saveState()
2626

2727
@Serializable
2828
data class State(
29-
val queue: List<TransferDomain>
29+
val queue: List<TransferDomain>,
30+
val completed: List<TransferDomain> = listOf(),
3031
) {
3132
companion object {
3233
val Initial = State(listOf())
3334
}
3435
}
36+
3537
}
3638

3739
interface DataStore {

shared/src/commonMain/kotlin/uk/co/sentinelweb/cuer/app/ui/filebrowser/transfers/TransfersViewModel.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ class TransfersViewModel(
4444
init {
4545
log.tag(this)
4646
viewModelScope.launch {
47-
service.queueFlow.collectLatest {
47+
service.transfersFlow.collectLatest {
4848
_stateObservable.value = _stateObservable.value.copy(
4949
localNode = localRepository.localNode,
5050
queue = it
@@ -85,7 +85,7 @@ class TransfersViewModel(
8585
val fileNodeSelected: (NodeDomain, Domain?) -> Unit = { fbNode, fbPath ->
8686
val updated = _stateObservable.value.selectedTransfer
8787
?.let { copy(it, TransferDomain.AddressDomain(fbNode, fbPath)) }
88-
?.also { service.replaceTransfer(it) }
88+
?.also { service.addReplaceTransfer(it) }
8989

9090
_stateObservable.update { last ->
9191
last.copy(selectedTransfer = updated)
@@ -133,7 +133,7 @@ class TransfersViewModel(
133133
source = it.target,
134134
target = it.source
135135
)
136-
}?.also { service.replaceTransfer(it) }
136+
}?.also { service.addReplaceTransfer(it) }
137137
_stateObservable.update { last ->
138138
last.copy(selectedTransfer = newValue)
139139
}
@@ -160,7 +160,7 @@ class TransfersViewModel(
160160
transfer
161161
.takeIf { transfer.status == Initial }
162162
?.copy(status = Confirmed)
163-
?.also { service.replaceTransfer(it) }
163+
?.also { service.addReplaceTransfer(it) }
164164
_stateObservable.update { last ->
165165
last.copy(selectedTransfer = null) // go back after confirm
166166
}

0 commit comments

Comments
 (0)