- Expand the missing-native-Git message with the selected ABI, 32/64-bit ABI lists, Android version, device model/platform details, expected binary path, and a request to report the information so device support can be added. - Use application-scoped DataStore delegates for game progress and pane layout preferences to avoid duplicate DataStore instances during activity recreation, such as screen orientation changes. - Center manpage search matches in the visible scroll viewport when possible and apply IME padding so keyboard-covered space is accounted for. - Support mobile-friendly handling for interactive add/stage commands (`git add -i`, `git stage -i`, and `git add --interactive`) by routing them through GitHug's staging semantics instead of rejecting them or launching Git's terminal UI. - Apply IME padding to editor dialogs so controls remain reachable while the keyboard is displayed.
71 lines
2.8 KiB
Kotlin
71 lines
2.8 KiB
Kotlin
package solutions.tretter.githugandroid
|
|
|
|
import android.content.Context
|
|
import androidx.datastore.preferences.core.edit
|
|
import androidx.datastore.preferences.core.emptyPreferences
|
|
import androidx.datastore.preferences.core.stringPreferencesKey
|
|
import androidx.datastore.preferences.preferencesDataStore
|
|
import kotlinx.coroutines.flow.catch
|
|
import kotlinx.coroutines.flow.map
|
|
import java.io.IOException
|
|
|
|
private val Context.paneLayoutDataStore by preferencesDataStore(name = "pane_layout_preferences")
|
|
|
|
class PaneLayoutStore(private val context: Context) {
|
|
private val dataStore = context.applicationContext.paneLayoutDataStore
|
|
|
|
private val orderKey = stringPreferencesKey("pane_order")
|
|
private val collapsedKey = stringPreferencesKey("pane_collapsed")
|
|
private val weightsKey = stringPreferencesKey("pane_weights")
|
|
|
|
val layoutFlow = dataStore.data
|
|
.catch { error ->
|
|
if (error is IOException) emit(emptyPreferences()) else throw error
|
|
}
|
|
.map { preferences ->
|
|
val defaults = defaultPaneLayout()
|
|
val order = preferences[orderKey]
|
|
?.split(',')
|
|
?.mapNotNull { value -> PaneId.entries.firstOrNull { it.name == value } }
|
|
?.let { parsed ->
|
|
val missing = PaneId.entries.filterNot { it in parsed }
|
|
parsed + missing
|
|
}
|
|
?.takeIf { it.isNotEmpty() }
|
|
?: defaults.order
|
|
|
|
val collapsed = preferences[collapsedKey]
|
|
?.split(',')
|
|
?.mapNotNull { value -> PaneId.entries.firstOrNull { it.name == value } }
|
|
?.toSet()
|
|
?: emptySet()
|
|
|
|
val parsedWeights = preferences[weightsKey]
|
|
?.split(';')
|
|
?.mapNotNull { item ->
|
|
val parts = item.split(':', limit = 2)
|
|
val paneId = PaneId.entries.firstOrNull { it.name == parts.getOrNull(0) }
|
|
val weight = parts.getOrNull(1)?.toFloatOrNull()
|
|
if (paneId != null && weight != null) paneId to weight.coerceAtLeast(0.6f) else null
|
|
}
|
|
?.toMap()
|
|
.orEmpty()
|
|
|
|
PaneLayout(
|
|
order = order,
|
|
collapsed = collapsed,
|
|
weights = PaneId.entries.associateWith { pane -> parsedWeights[pane] ?: defaults.weights.getValue(pane) },
|
|
)
|
|
}
|
|
|
|
suspend fun save(layout: PaneLayout) {
|
|
dataStore.edit { preferences ->
|
|
preferences[orderKey] = layout.order.joinToString(",") { it.name }
|
|
preferences[collapsedKey] = layout.collapsed.joinToString(",") { it.name }
|
|
preferences[weightsKey] = layout.order.joinToString(";") { pane ->
|
|
"${pane.name}:${layout.weights[pane] ?: 1f}"
|
|
}
|
|
}
|
|
}
|
|
}
|