mirror of
https://codeberg.org/timelimit/timelimit-android.git
synced 2025-10-06 03:50:23 +02:00
Use a more reliable fragment id generation
This commit is contained in:
parent
dac0ce74fe
commit
c0d723ee00
3 changed files with 28 additions and 15 deletions
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* TimeLimit Copyright <C> 2019 - 2021 Jonas Lochmann
|
||||
* TimeLimit Copyright <C> 2019 - 2023 Jonas Lochmann
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -16,9 +16,19 @@
|
|||
package io.timelimit.android
|
||||
|
||||
import android.app.Application
|
||||
import android.view.View
|
||||
import com.jakewharton.threetenabp.AndroidThreeTen
|
||||
|
||||
class Application : Application() {
|
||||
// two legacy screens use small id numbers as they want; by running generateViewId() often enough,
|
||||
// all ids that are harcoded this way are not returned from generateViewId
|
||||
init { (0..1024).forEach { _ -> View.generateViewId() } }
|
||||
|
||||
// allocate some view ids for Fragments that are not used for anything else
|
||||
// by running this in the Application class, there is a high chance that these
|
||||
// are always the same ids so that there is no trouble when restoring state
|
||||
val viewIdPool = (0..4).map { View.generateViewId() }
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
|
||||
|
|
|
@ -79,7 +79,6 @@ class MainActivity : AppCompatActivity(), ActivityViewModelHolder, U2fManager.De
|
|||
private const val EXTRA_AUTH_HANDOVER = "authHandover"
|
||||
private const val MAIN_MODEL_STATE = "mainModelState"
|
||||
private const val FRAGMENT_IDS_STATE = "fragmentIds"
|
||||
private const val NEXT_FRAGMENT_ID = "nextFragmentId"
|
||||
|
||||
private var authHandover: Triple<Long, Long, AuthenticatedUser>? = null
|
||||
|
||||
|
@ -114,7 +113,6 @@ class MainActivity : AppCompatActivity(), ActivityViewModelHolder, U2fManager.De
|
|||
}
|
||||
|
||||
private val mainModel by viewModels<MainModel>()
|
||||
private var fragmentIds = mutableSetOf<Int>()
|
||||
private val syncModel: SyncStatusModel by lazy {
|
||||
ViewModelProviders.of(this).get(SyncStatusModel::class.java)
|
||||
}
|
||||
|
@ -134,8 +132,7 @@ class MainActivity : AppCompatActivity(), ActivityViewModelHolder, U2fManager.De
|
|||
|
||||
if (savedInstanceState != null) {
|
||||
mainModel.state.value = savedInstanceState.getSerializable(MAIN_MODEL_STATE) as State
|
||||
fragmentIds.addAll(savedInstanceState.getIntegerArrayList(FRAGMENT_IDS_STATE) ?: emptyList())
|
||||
mainModel.nextFragmentId = savedInstanceState.getInt(NEXT_FRAGMENT_ID)
|
||||
mainModel.fragmentIds.addAll(savedInstanceState.getIntegerArrayList(FRAGMENT_IDS_STATE) ?: emptyList())
|
||||
}
|
||||
|
||||
lifecycleScope.launch {
|
||||
|
@ -279,7 +276,7 @@ class MainActivity : AppCompatActivity(), ActivityViewModelHolder, U2fManager.De
|
|||
screen = screen,
|
||||
executeCommand = ::execute,
|
||||
fragmentManager = supportFragmentManager,
|
||||
fragmentIds = fragmentIds,
|
||||
fragmentIds = mainModel.fragmentIds,
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(paddingValues)
|
||||
|
@ -300,8 +297,7 @@ class MainActivity : AppCompatActivity(), ActivityViewModelHolder, U2fManager.De
|
|||
super.onSaveInstanceState(outState)
|
||||
|
||||
outState.putSerializable(MAIN_MODEL_STATE, mainModel.state.value)
|
||||
outState.putIntegerArrayList(FRAGMENT_IDS_STATE, ArrayList(fragmentIds))
|
||||
outState.putInt(NEXT_FRAGMENT_ID, mainModel.nextFragmentId)
|
||||
outState.putIntegerArrayList(FRAGMENT_IDS_STATE, ArrayList(mainModel.fragmentIds))
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
|
@ -373,7 +369,7 @@ class MainActivity : AppCompatActivity(), ActivityViewModelHolder, U2fManager.De
|
|||
}
|
||||
|
||||
private fun cleanupFragments() {
|
||||
fragmentIds
|
||||
mainModel.fragmentIds
|
||||
.filter { fragmentId ->
|
||||
var v = mainModel.state.value as State?
|
||||
|
||||
|
@ -385,8 +381,7 @@ class MainActivity : AppCompatActivity(), ActivityViewModelHolder, U2fManager.De
|
|||
|
||||
true
|
||||
}
|
||||
.map { supportFragmentManager.findFragmentById(it) }
|
||||
.filterNotNull()
|
||||
.mapNotNull { supportFragmentManager.findFragmentById(it) }
|
||||
.filter { it.isDetached }
|
||||
.forEach {
|
||||
if (BuildConfig.DEBUG) {
|
||||
|
@ -399,7 +394,7 @@ class MainActivity : AppCompatActivity(), ActivityViewModelHolder, U2fManager.De
|
|||
.remove(it)
|
||||
.commitAllowingStateLoss()
|
||||
|
||||
fragmentIds.remove(id)
|
||||
mainModel.fragmentIds.remove(id)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -81,7 +81,7 @@ class MainModel(application: Application): AndroidViewModel(application) {
|
|||
|
||||
val activityCommand: ReceiveChannel<ActivityCommand> = activityCommandInternal
|
||||
val state = MutableStateFlow(State.LaunchState as State)
|
||||
var nextFragmentId = 1
|
||||
var fragmentIds = mutableSetOf<Int>()
|
||||
|
||||
val screen: Flow<Screen> = flow {
|
||||
while (true) {
|
||||
|
@ -93,9 +93,17 @@ class MainModel(application: Application): AndroidViewModel(application) {
|
|||
is State.DiagnoseScreen.DeviceOwner -> emitAll(DeviceOwnerHandling.processState(logic, scope, authenticationModelApi, state))
|
||||
is FragmentState -> emitAll(state.transformWhile {
|
||||
if (it is FragmentState && it !is State.Overview) {
|
||||
if (it.containerId == null) it.containerId = nextFragmentId++
|
||||
val containerId = it.containerId ?: run {
|
||||
((application as io.timelimit.android.Application).viewIdPool - fragmentIds).firstOrNull()?.also { id ->
|
||||
it.containerId = id
|
||||
}
|
||||
}
|
||||
|
||||
emit(Screen.FragmentScreen(it, it.toolbarIcons, it.toolbarOptions, it, it.containerId!!))
|
||||
if (containerId != null) {
|
||||
fragmentIds.add(containerId)
|
||||
|
||||
emit(Screen.FragmentScreen(it, it.toolbarIcons, it.toolbarOptions, it, containerId))
|
||||
}
|
||||
|
||||
true
|
||||
} else false
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue