mirror of
https://github.com/openflocon/Flocon.git
synced 2026-05-06 04:06:10 +00:00
feat: [NETWORK] persist settings (#348)
Co-authored-by: Florent Champigny <florent@bere.al>
This commit is contained in:
parent
dd4b3dd6b9
commit
15eae36341
23 changed files with 490 additions and 77 deletions
|
|
@ -2,7 +2,7 @@
|
|||
"formatVersion": 1,
|
||||
"database": {
|
||||
"version": 67,
|
||||
"identityHash": "2038d2adaa065952692bba0a38a7de5f",
|
||||
"identityHash": "94a1a4f3eb4cf29757584bdaa3c2a455",
|
||||
"entities": [
|
||||
{
|
||||
"tableName": "FloconNetworkCallEntity",
|
||||
|
|
@ -1216,6 +1216,52 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"tableName": "NetworkSettingsEntity",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`deviceId` TEXT NOT NULL, `packageName` TEXT NOT NULL, `valueAsJson` TEXT NOT NULL, PRIMARY KEY(`deviceId`, `packageName`), FOREIGN KEY(`deviceId`, `packageName`) REFERENCES `DeviceAppEntity`(`deviceId`, `packageName`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "deviceId",
|
||||
"columnName": "deviceId",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "packageName",
|
||||
"columnName": "packageName",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "valueAsJson",
|
||||
"columnName": "valueAsJson",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"deviceId",
|
||||
"packageName"
|
||||
]
|
||||
},
|
||||
"foreignKeys": [
|
||||
{
|
||||
"table": "DeviceAppEntity",
|
||||
"onDelete": "CASCADE",
|
||||
"onUpdate": "NO ACTION",
|
||||
"columns": [
|
||||
"deviceId",
|
||||
"packageName"
|
||||
],
|
||||
"referencedColumns": [
|
||||
"deviceId",
|
||||
"packageName"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"tableName": "MockNetworkEntity",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`mockId` TEXT NOT NULL, `deviceId` TEXT, `packageName` TEXT, `isEnabled` INTEGER NOT NULL, `response` TEXT NOT NULL, `expectation_urlPattern` TEXT NOT NULL, `expectation_method` TEXT NOT NULL, PRIMARY KEY(`mockId`), FOREIGN KEY(`deviceId`, `packageName`) REFERENCES `DeviceAppEntity`(`deviceId`, `packageName`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
||||
|
|
@ -1590,7 +1636,7 @@
|
|||
],
|
||||
"setupQueries": [
|
||||
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
|
||||
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '2038d2adaa065952692bba0a38a7de5f')"
|
||||
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '94a1a4f3eb4cf29757584bdaa3c2a455')"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
@ -30,8 +30,10 @@ import io.github.openflocon.data.local.network.dao.FloconNetworkDao
|
|||
import io.github.openflocon.data.local.network.dao.NetworkBadQualityConfigDao
|
||||
import io.github.openflocon.data.local.network.dao.NetworkFilterDao
|
||||
import io.github.openflocon.data.local.network.dao.NetworkMocksDao
|
||||
import io.github.openflocon.data.local.network.dao.NetworkSettingsDao
|
||||
import io.github.openflocon.data.local.network.models.FloconNetworkCallEntity
|
||||
import io.github.openflocon.data.local.network.models.NetworkFilterEntity
|
||||
import io.github.openflocon.data.local.network.models.NetworkSettingsEntity
|
||||
import io.github.openflocon.data.local.network.models.badquality.BadQualityConfigEntity
|
||||
import io.github.openflocon.data.local.network.models.mock.MockNetworkEntity
|
||||
import io.github.openflocon.data.local.table.dao.FloconTableDao
|
||||
|
|
@ -43,7 +45,7 @@ import io.github.openflocon.flocondesktop.common.db.converters.MapStringsConvert
|
|||
import kotlinx.coroutines.Dispatchers
|
||||
|
||||
@Database(
|
||||
version = 67,
|
||||
version = 68,
|
||||
entities = [
|
||||
FloconNetworkCallEntity::class,
|
||||
FileEntity::class,
|
||||
|
|
@ -58,6 +60,7 @@ import kotlinx.coroutines.Dispatchers
|
|||
DeeplinkEntity::class,
|
||||
AnalyticsItemEntity::class,
|
||||
NetworkFilterEntity::class,
|
||||
NetworkSettingsEntity::class,
|
||||
MockNetworkEntity::class,
|
||||
DeviceWithSerialEntity::class,
|
||||
BadQualityConfigEntity::class,
|
||||
|
|
@ -73,6 +76,7 @@ import kotlinx.coroutines.Dispatchers
|
|||
)
|
||||
abstract class AppDatabase : RoomDatabase() {
|
||||
abstract val networkDao: FloconNetworkDao
|
||||
abstract val networkSettingsDao: NetworkSettingsDao
|
||||
abstract val fileDao: FloconFileDao
|
||||
abstract val dashboardDao: FloconDashboardDao
|
||||
abstract val tableDao: FloconTableDao
|
||||
|
|
|
|||
|
|
@ -10,6 +10,9 @@ val roomModule =
|
|||
single {
|
||||
get<AppDatabase>().networkDao
|
||||
}
|
||||
single {
|
||||
get<AppDatabase>().networkSettingsDao
|
||||
}
|
||||
single {
|
||||
get<AppDatabase>().fileDao
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,8 +10,6 @@ data class ContentUiState(
|
|||
val detailJsons: Set<NetworkBodyDetailUi>,
|
||||
val mocksDisplayed: MockDisplayed?,
|
||||
val badNetworkQualityDisplayed: Boolean,
|
||||
val invertList: Boolean,
|
||||
val autoScroll: Boolean
|
||||
)
|
||||
|
||||
@Immutable
|
||||
|
|
@ -25,6 +23,4 @@ fun previewContentUiState() = ContentUiState(
|
|||
detailJsons = emptySet(),
|
||||
mocksDisplayed = null,
|
||||
badNetworkQualityDisplayed = false,
|
||||
invertList = false,
|
||||
autoScroll = false
|
||||
)
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ import io.github.openflocon.domain.network.models.BadQualityConfigDomainModel
|
|||
import io.github.openflocon.domain.network.models.MockNetworkDomainModel
|
||||
import io.github.openflocon.domain.network.models.NetworkFilterDomainModel
|
||||
import io.github.openflocon.domain.network.models.NetworkFilterDomainModel.Filters
|
||||
import io.github.openflocon.domain.network.models.NetworkSettingsDomainModel
|
||||
import io.github.openflocon.domain.network.models.NetworkTextFilterColumns
|
||||
import io.github.openflocon.domain.network.usecase.DecodeJwtTokenUseCase
|
||||
import io.github.openflocon.domain.network.usecase.ExportNetworkCallsToCsvUseCase
|
||||
|
|
@ -29,6 +30,8 @@ import io.github.openflocon.domain.network.usecase.RemoveOldSessionsNetworkReque
|
|||
import io.github.openflocon.domain.network.usecase.ResetCurrentDeviceHttpRequestsUseCase
|
||||
import io.github.openflocon.domain.network.usecase.badquality.ObserveAllNetworkBadQualitiesUseCase
|
||||
import io.github.openflocon.domain.network.usecase.mocks.ObserveNetworkMocksUseCase
|
||||
import io.github.openflocon.domain.network.usecase.settings.ObserveNetworkSettingsUseCase
|
||||
import io.github.openflocon.domain.network.usecase.settings.UpdateNetworkSettingsUseCase
|
||||
import io.github.openflocon.flocondesktop.features.network.body.model.ContentUiState
|
||||
import io.github.openflocon.flocondesktop.features.network.body.model.MockDisplayed
|
||||
import io.github.openflocon.flocondesktop.features.network.detail.mapper.toDetailUi
|
||||
|
|
@ -55,7 +58,6 @@ import kotlinx.coroutines.flow.flatMapLatest
|
|||
import kotlinx.coroutines.flow.flowOf
|
||||
import kotlinx.coroutines.flow.flowOn
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.mapLatest
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.launch
|
||||
|
|
@ -77,6 +79,8 @@ class NetworkViewModel(
|
|||
private val exportNetworkCallsToCsv: ExportNetworkCallsToCsvUseCase,
|
||||
private val decodeJwtTokenUseCase: DecodeJwtTokenUseCase,
|
||||
private val removeOldSessionsNetworkRequestUseCase: RemoveOldSessionsNetworkRequestUseCase,
|
||||
private val observeNetworkSettingsUseCase: ObserveNetworkSettingsUseCase,
|
||||
private val updateNetworkSettingsUseCase: UpdateNetworkSettingsUseCase,
|
||||
) : ViewModel(headerDelegate) {
|
||||
|
||||
private val contentState = MutableStateFlow(
|
||||
|
|
@ -85,26 +89,37 @@ class NetworkViewModel(
|
|||
detailJsons = emptySet(),
|
||||
mocksDisplayed = null,
|
||||
badNetworkQualityDisplayed = false,
|
||||
invertList = false,
|
||||
autoScroll = false
|
||||
),
|
||||
)
|
||||
|
||||
private val _filterText = mutableStateOf("")
|
||||
val filterText: State<String> = _filterText
|
||||
|
||||
private val displayOldSessions = MutableStateFlow(true)
|
||||
private val defaultNetworkSettings = NetworkSettingsDomainModel(
|
||||
displayOldSessions = true,
|
||||
autoScroll = false,
|
||||
invertList = false,
|
||||
)
|
||||
|
||||
private val settings: StateFlow<NetworkSettingsDomainModel> = observeNetworkSettingsUseCase()
|
||||
.flowOn(dispatcherProvider.viewModel)
|
||||
.map { it ?: defaultNetworkSettings }
|
||||
.stateIn(
|
||||
viewModelScope,
|
||||
SharingStarted.WhileSubscribed(5_000),
|
||||
initialValue = defaultNetworkSettings
|
||||
)
|
||||
|
||||
private val filterUiState = combine(
|
||||
mocksUseCase().map { it.any(MockNetworkDomainModel::isEnabled) }.distinctUntilChanged(),
|
||||
badNetworkUseCase().map { it.any(BadQualityConfigDomainModel::isEnabled) }
|
||||
.distinctUntilChanged(),
|
||||
displayOldSessions,
|
||||
) { mockEnabled, badNetworkEnabled, displayOldSessions ->
|
||||
settings,
|
||||
) { mockEnabled, badNetworkEnabled, settings ->
|
||||
TopBarUiState(
|
||||
hasBadNetwork = badNetworkEnabled,
|
||||
hasMocks = mockEnabled,
|
||||
displayOldSessions = displayOldSessions,
|
||||
displayOldSessions = settings.displayOldSessions,
|
||||
)
|
||||
}.stateIn(
|
||||
viewModelScope, SharingStarted.WhileSubscribed(5_000),
|
||||
|
|
@ -135,13 +150,13 @@ class NetworkViewModel(
|
|||
headerDelegate.textFiltersState.map { it.toDomain() }.distinctUntilChanged(),
|
||||
headerDelegate.allowedMethods().map { items -> methodsToDomain(items) }
|
||||
.distinctUntilChanged(),
|
||||
displayOldSessions,
|
||||
).map { (textFilters, filterOnAllColumns, methods, displayOldSessions) ->
|
||||
settings,
|
||||
).map { (textFilters, filterOnAllColumns, methods, settings) ->
|
||||
NetworkFilterDomainModel(
|
||||
filterOnAllColumns = textFilters,
|
||||
textsFilters = filterOnAllColumns,
|
||||
methodFilter = methods,
|
||||
displayOldSessions = displayOldSessions,
|
||||
displayOldSessions = settings.displayOldSessions,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -150,36 +165,39 @@ class NetworkViewModel(
|
|||
filter,
|
||||
).distinctUntilChanged()
|
||||
|
||||
val items: Flow<PagingData<NetworkItemViewState>> = observeCurrentDeviceIdAndPackageNameUseCase()
|
||||
.flatMapLatest { deviceIdAndPackageName ->
|
||||
sortAndFilter.flatMapLatest { (sorted, filter) ->
|
||||
observeNetworkRequestsUseCase(
|
||||
sortedBy = sorted,
|
||||
filter = filter,
|
||||
deviceIdAndPackageName = deviceIdAndPackageName,
|
||||
).map { networkCallPagingData ->
|
||||
networkCallPagingData.map {
|
||||
it.toUi(
|
||||
deviceIdAndPackageName = deviceIdAndPackageName
|
||||
)
|
||||
val items: Flow<PagingData<NetworkItemViewState>> =
|
||||
observeCurrentDeviceIdAndPackageNameUseCase()
|
||||
.flatMapLatest { deviceIdAndPackageName ->
|
||||
sortAndFilter.flatMapLatest { (sorted, filter) ->
|
||||
observeNetworkRequestsUseCase(
|
||||
sortedBy = sorted,
|
||||
filter = filter,
|
||||
deviceIdAndPackageName = deviceIdAndPackageName,
|
||||
).map { networkCallPagingData ->
|
||||
networkCallPagingData.map {
|
||||
it.toUi(
|
||||
deviceIdAndPackageName = deviceIdAndPackageName
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.flowOn(dispatcherProvider.viewModel)
|
||||
.cachedIn(viewModelScope)
|
||||
.flowOn(dispatcherProvider.viewModel)
|
||||
.cachedIn(viewModelScope)
|
||||
|
||||
val uiState = combine(
|
||||
contentState,
|
||||
detailState,
|
||||
filterUiState,
|
||||
headerDelegate.headerUiState,
|
||||
) { content, detail, filter, header ->
|
||||
settings.map { it.toUi() },
|
||||
) { content, detail, filter, header, settings ->
|
||||
NetworkUiState(
|
||||
contentState = content,
|
||||
detailState = detail,
|
||||
filterState = filter,
|
||||
headerState = header,
|
||||
settings = settings,
|
||||
)
|
||||
}
|
||||
.flowOn(dispatcherProvider.viewModel)
|
||||
|
|
@ -191,6 +209,7 @@ class NetworkViewModel(
|
|||
contentState = contentState.value,
|
||||
filterState = filterUiState.value,
|
||||
headerState = headerDelegate.headerUiState.value,
|
||||
settings = settings.value.toUi(),
|
||||
),
|
||||
)
|
||||
|
||||
|
|
@ -226,12 +245,12 @@ class NetworkViewModel(
|
|||
action = action.action,
|
||||
)
|
||||
|
||||
is NetworkAction.InvertList -> onInvertList(action)
|
||||
NetworkAction.ToggleAutoScroll -> onAutoScroll()
|
||||
is NetworkAction.InvertList -> toggleInvertList(action)
|
||||
is NetworkAction.ToggleAutoScroll -> toggleAutoScroll(action)
|
||||
NetworkAction.ClearOldSession -> onClearSession()
|
||||
is NetworkAction.Down -> contentState.update { it.copy(selectedRequestId = action.itemIdToSelect) }
|
||||
is NetworkAction.Up -> contentState.update { it.copy(selectedRequestId = action.itemIdToSelect) }
|
||||
is NetworkAction.UpdateDisplayOldSessions -> displayOldSessions.update { action.value }
|
||||
is NetworkAction.UpdateDisplayOldSessions -> toggleDisplayOldSessions(action)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -241,12 +260,34 @@ class NetworkViewModel(
|
|||
}
|
||||
}
|
||||
|
||||
private fun onAutoScroll() {
|
||||
contentState.update { it.copy(autoScroll = !it.autoScroll) }
|
||||
private fun toggleAutoScroll(action: NetworkAction.ToggleAutoScroll) {
|
||||
viewModelScope.launch(dispatcherProvider.viewModel) {
|
||||
updateNetworkSettingsUseCase(
|
||||
settings.value.copy(
|
||||
autoScroll = action.value
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun onInvertList(action: NetworkAction.InvertList) {
|
||||
contentState.update { it.copy(invertList = action.value) }
|
||||
private fun toggleDisplayOldSessions(action: NetworkAction.UpdateDisplayOldSessions) {
|
||||
viewModelScope.launch(dispatcherProvider.viewModel) {
|
||||
updateNetworkSettingsUseCase(
|
||||
settings.value.copy(
|
||||
displayOldSessions = action.value
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun toggleInvertList(action: NetworkAction.InvertList) {
|
||||
viewModelScope.launch(dispatcherProvider.viewModel) {
|
||||
updateNetworkSettingsUseCase(
|
||||
settings.value.copy(
|
||||
invertList = action.value
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun displayBearerJwt(token: String) {
|
||||
|
|
@ -418,7 +459,7 @@ private fun Map<NetworkTextFilterColumns, TextFilterStateUiModel>.toDomain(): Li
|
|||
}
|
||||
}
|
||||
|
||||
private fun TextFilterStateUiModel.FilterItem.toDomain(): NetworkFilterDomainModel.Filters.FilterItem? {
|
||||
private fun TextFilterStateUiModel.FilterItem.toDomain(): Filters.FilterItem? {
|
||||
return if (isActive) {
|
||||
Filters.FilterItem(
|
||||
text = text,
|
||||
|
|
@ -427,5 +468,6 @@ private fun TextFilterStateUiModel.FilterItem.toDomain(): NetworkFilterDomainMod
|
|||
}
|
||||
|
||||
private fun methodsToDomain(items: List<NetworkMethodUi>): List<String>? {
|
||||
return items.map { it.text }.takeIf { it.isNotEmpty() }?.takeIf { it.size != NetworkMethodUi.all().size } // returns null if we accept all
|
||||
return items.map { it.text }.takeIf { it.isNotEmpty() }
|
||||
?.takeIf { it.size != NetworkMethodUi.all().size } // returns null if we accept all
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,10 @@
|
|||
package io.github.openflocon.flocondesktop.features.network.list.mapper
|
||||
|
||||
import io.github.openflocon.domain.network.models.NetworkSettingsDomainModel
|
||||
import io.github.openflocon.flocondesktop.features.network.list.model.NetworkSettingsUiModel
|
||||
|
||||
fun NetworkSettingsDomainModel.toUi() = NetworkSettingsUiModel(
|
||||
displayOldSessions = displayOldSessions,
|
||||
autoScroll = autoScroll,
|
||||
invertList = invertList,
|
||||
)
|
||||
|
|
@ -42,7 +42,7 @@ sealed interface NetworkAction {
|
|||
|
||||
data class InvertList(val value: Boolean) : NetworkAction
|
||||
|
||||
data object ToggleAutoScroll : NetworkAction
|
||||
data class ToggleAutoScroll(val value: Boolean) : NetworkAction
|
||||
|
||||
data object ClearOldSession : NetworkAction
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,16 @@
|
|||
package io.github.openflocon.flocondesktop.features.network.list.model
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
|
||||
@Immutable
|
||||
data class NetworkSettingsUiModel(
|
||||
val displayOldSessions: Boolean,
|
||||
val autoScroll: Boolean,
|
||||
val invertList: Boolean
|
||||
)
|
||||
|
||||
fun previewNetworkSettingsUiModel() = NetworkSettingsUiModel(
|
||||
displayOldSessions = true,
|
||||
autoScroll = false,
|
||||
invertList = false,
|
||||
)
|
||||
|
|
@ -10,6 +10,7 @@ import io.github.openflocon.flocondesktop.features.network.body.model.previewCon
|
|||
@Immutable
|
||||
data class NetworkUiState(
|
||||
val contentState: ContentUiState,
|
||||
val settings: NetworkSettingsUiModel,
|
||||
val detailState: NetworkDetailViewState?,
|
||||
val filterState: TopBarUiState,
|
||||
val headerState: NetworkHeaderUiState,
|
||||
|
|
@ -20,4 +21,5 @@ fun previewNetworkUiState() = NetworkUiState(
|
|||
contentState = previewContentUiState(),
|
||||
filterState = previewTopBarUiState(),
|
||||
headerState = previewNetworkHeaderUiState(),
|
||||
settings = previewNetworkSettingsUiModel(),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ package io.github.openflocon.flocondesktop.features.network.list.view
|
|||
import androidx.compose.desktop.ui.tooling.preview.Preview
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
|
|
@ -28,7 +27,6 @@ import androidx.compose.runtime.getValue
|
|||
import androidx.compose.runtime.mutableStateMapOf
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.input.key.Key
|
||||
|
|
@ -36,13 +34,11 @@ import androidx.compose.ui.input.key.KeyEventType
|
|||
import androidx.compose.ui.input.key.key
|
||||
import androidx.compose.ui.input.key.onPreviewKeyEvent
|
||||
import androidx.compose.ui.input.key.type
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import androidx.paging.PagingData
|
||||
import androidx.paging.compose.LazyPagingItems
|
||||
import androidx.paging.compose.collectAsLazyPagingItems
|
||||
import androidx.paging.compose.itemKey
|
||||
import com.composeunstyled.Text
|
||||
import io.github.openflocon.flocondesktop.common.ui.window.FloconWindowState
|
||||
import io.github.openflocon.flocondesktop.common.ui.window.createFloconWindowState
|
||||
import io.github.openflocon.flocondesktop.features.network.badquality.list.view.BadNetworkQualityWindow
|
||||
|
|
@ -61,7 +57,6 @@ import io.github.openflocon.flocondesktop.features.network.mock.list.view.Networ
|
|||
import io.github.openflocon.flocondesktop.features.network.model.NetworkBodyDetailUi
|
||||
import io.github.openflocon.flocondesktop.features.network.view.NetworkBodyWindow
|
||||
import io.github.openflocon.library.designsystem.FloconTheme
|
||||
import io.github.openflocon.library.designsystem.components.FloconCheckbox
|
||||
import io.github.openflocon.library.designsystem.components.FloconDropdownMenuItem
|
||||
import io.github.openflocon.library.designsystem.components.FloconDropdownSeparator
|
||||
import io.github.openflocon.library.designsystem.components.FloconFeature
|
||||
|
|
@ -109,8 +104,8 @@ fun NetworkScreen(
|
|||
val columnWidths: NetworkItemColumnWidths =
|
||||
remember { NetworkItemColumnWidths() } // Default widths provided
|
||||
|
||||
LaunchedEffect(uiState.contentState.autoScroll, rows.itemCount) {
|
||||
if (uiState.contentState.autoScroll && rows.itemCount != -1) {
|
||||
LaunchedEffect(uiState.settings.autoScroll, rows.itemCount) {
|
||||
if (uiState.settings.autoScroll && rows.itemCount != -1) {
|
||||
lazyListState.animateScrollToItem(rows.itemCount)
|
||||
}
|
||||
}
|
||||
|
|
@ -242,13 +237,13 @@ fun NetworkScreen(
|
|||
onClick = { onAction(NetworkAction.ExportCsv) }
|
||||
)
|
||||
FloconDropdownMenuItem(
|
||||
checked = uiState.contentState.autoScroll,
|
||||
checked = uiState.settings.autoScroll,
|
||||
text = "Auto scroll",
|
||||
leadingIcon = Icons.Outlined.PlayCircle,
|
||||
onCheckedChange = { onAction(NetworkAction.ToggleAutoScroll) }
|
||||
onCheckedChange = { onAction(NetworkAction.ToggleAutoScroll(it)) }
|
||||
)
|
||||
FloconDropdownMenuItem(
|
||||
checked = uiState.contentState.invertList,
|
||||
checked = uiState.settings.invertList,
|
||||
text = "Invert list",
|
||||
leadingIcon = Icons.AutoMirrored.Outlined.List,
|
||||
onCheckedChange = { onAction(NetworkAction.InvertList(it)) }
|
||||
|
|
@ -287,7 +282,7 @@ fun NetworkScreen(
|
|||
) {
|
||||
LazyColumn(
|
||||
state = lazyListState,
|
||||
reverseLayout = uiState.contentState.invertList,
|
||||
reverseLayout = uiState.settings.invertList,
|
||||
modifier = Modifier
|
||||
.fillMaxHeight()
|
||||
.weight(1f)
|
||||
|
|
@ -388,7 +383,7 @@ private fun selectPreviousRow(
|
|||
rows.itemSnapshotList.indexOfFirst { it?.uuid == uiState.contentState.selectedRequestId }
|
||||
.takeIf { it != -1 }
|
||||
?.let { selectedIndex ->
|
||||
val newIndex = if (uiState.contentState.invertList)
|
||||
val newIndex = if (uiState.settings.invertList)
|
||||
selectedIndex + 1
|
||||
else
|
||||
selectedIndex - 1
|
||||
|
|
@ -404,7 +399,7 @@ private fun selectNextRow(
|
|||
rows.itemSnapshotList.indexOfFirst { it?.uuid == uiState.contentState.selectedRequestId }
|
||||
.takeIf { it != -1 }
|
||||
?.let { selectedIndex ->
|
||||
val newIndex = if (uiState.contentState.invertList)
|
||||
val newIndex = if (uiState.settings.invertList)
|
||||
selectedIndex - 1
|
||||
else
|
||||
selectedIndex + 1
|
||||
|
|
@ -441,24 +436,3 @@ private fun NetworkScreenPreview() {
|
|||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun TopBarCheckbox(
|
||||
checked: Boolean,
|
||||
label: String,
|
||||
onCheckedChange: (Boolean) -> Unit,
|
||||
) {
|
||||
Row(verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(2.dp)) {
|
||||
val color = FloconTheme.colorPalette.surface
|
||||
FloconCheckbox(
|
||||
checked = checked,
|
||||
onCheckedChange = {},
|
||||
uncheckedColor = color
|
||||
)
|
||||
Text(
|
||||
label,
|
||||
style = FloconTheme.typography.bodySmall,
|
||||
color = color,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue