package solutions.tretter.githugandroid import androidx.compose.runtime.saveable.listSaver val RepoStateSaver = listSaver( save = { state -> listOf( state.initialized, state.headBranch, state.files.flatMap { listOf( it.name, it.content, it.staged.toString(), it.tracked.toString(), it.deleted.toString(), it.stagedContent.orEmpty(), ) }, state.commits.flatMap { listOf( it.id, it.message, it.authorTimestampSeconds?.toString().orEmpty(), it.parentCount.toString(), ) }, state.branches.flatMap { listOf(it.key, it.value.toString()) }, state.currentDir, state.tags, state.remotes.flatMap { listOf(it.key, it.value) }, state.config.flatMap { listOf(it.key, it.value) }, state.stashes, state.fetchedBranches.toList(), state.pushedBranches.toList(), state.pushedTags.toList(), state.submodules.flatMap { listOf(it.key, it.value) }, state.maintenanceActions.toList(), state.fetchHeadCount, emptyList(), emptyList(), ) }, restore = { saved -> val initialized = saved[0] as Boolean val headBranch = saved[1] as String val fileParts = saved[2] as List<*> val commitParts = saved[3] as List<*> val branchParts = saved[4] as List<*> val tags = saved[6] as List<*> val remoteParts = saved[7] as List<*> val configParts = saved.getOrNull(8) as? List<*> ?: emptyList() val stashes = saved.getOrNull(9) as? List<*> ?: emptyList() val fetchedBranches = saved.getOrNull(10) as? List<*> ?: emptyList() val pushedBranches = saved.getOrNull(11) as? List<*> ?: emptyList() val pushedTags = saved.getOrNull(12) as? List<*> ?: emptyList() val submoduleParts = saved.getOrNull(13) as? List<*> ?: emptyList() val maintenanceActions = saved.getOrNull(14) as? List<*> ?: emptyList() val fetchHeadCount = saved.getOrNull(15) as? Int ?: 0 RepoState( initialized = initialized, headBranch = headBranch, files = fileParts.chunked( when { fileParts.size % 6 == 0 -> 6 fileParts.size % 5 == 0 -> 5 else -> 4 }, ).map { GitFile( name = it[0] as String, content = it[1] as String, staged = (it[2] as String).toBoolean(), tracked = (it[3] as String).toBoolean(), deleted = (it.getOrNull(4) as? String)?.toBoolean() ?: false, stagedContent = (it.getOrNull(5) as? String)?.takeIf { value -> value.isNotEmpty() }, ) }, commits = commitParts.restoreCommitNodes(), branches = branchParts.chunked(2).associate { (it[0] as String) to (it[1] as String).toInt() }, currentDir = saved[5] as String, tags = tags.filterIsInstance(), remotes = remoteParts.chunked(2).associate { (it[0] as String) to (it[1] as String) }, config = configParts.chunked(2).associate { (it[0] as String) to (it[1] as String) }, stashes = stashes.filterIsInstance(), fetchedBranches = fetchedBranches.filterIsInstance().toSet(), fetchHeadCount = fetchHeadCount, pushedBranches = pushedBranches.filterIsInstance().toSet(), pushedTags = pushedTags.filterIsInstance().toSet(), submodules = submoduleParts.chunked(2).associate { (it[0] as String) to (it[1] as String) }, maintenanceActions = maintenanceActions.filterIsInstance().toSet(), ) } ) private fun List<*>.restoreCommitNodes(): List { val hasTimestampAndParentColumns = size % 4 == 0 && chunked(4).all { chunk -> val timestamp = chunk.getOrNull(2) as? String val parentCount = chunk.getOrNull(3) as? String (timestamp.isNullOrEmpty() || timestamp.toLongOrNull()?.let { it >= 100_000_000L } == true) && parentCount?.toIntOrNull() != null } val hasTimestampColumn = !hasTimestampAndParentColumns && size % 3 == 0 && chunked(3).all { chunk -> val timestamp = chunk.getOrNull(2) as? String timestamp.isNullOrEmpty() || timestamp.toLongOrNull()?.let { it >= 100_000_000L } == true } val width = when { hasTimestampAndParentColumns -> 4 hasTimestampColumn -> 3 else -> 2 } return chunked(width).mapNotNull { chunk -> val id = chunk.getOrNull(0) as? String ?: return@mapNotNull null val message = chunk.getOrNull(1) as? String ?: "" CommitNode( id = id, message = message, authorTimestampSeconds = if (hasTimestampAndParentColumns || hasTimestampColumn) { (chunk.getOrNull(2) as? String)?.toLongOrNull() } else { null }, parentCount = if (hasTimestampAndParentColumns) (chunk.getOrNull(3) as? String)?.toIntOrNull() ?: 0 else 0, ) } }