mirror of
https://github.com/JustinZeus/Wholphin.git
synced 2026-07-09 08:01:20 +02:00
Focus improvements
This commit is contained in:
parent
43fde88695
commit
7e53f95054
4 changed files with 84 additions and 36 deletions
|
|
@ -11,7 +11,6 @@ import androidx.compose.foundation.lazy.LazyColumn
|
|||
import androidx.compose.foundation.lazy.itemsIndexed
|
||||
import androidx.compose.material3.HorizontalDivider
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.focus.FocusRequester
|
||||
|
|
@ -24,7 +23,6 @@ import androidx.tv.material3.MaterialTheme
|
|||
import androidx.tv.material3.Text
|
||||
import com.github.damontecres.wholphin.R
|
||||
import com.github.damontecres.wholphin.ui.ifElse
|
||||
import com.github.damontecres.wholphin.ui.tryRequestFocus
|
||||
|
||||
@Composable
|
||||
fun HomeSettingsAddRow(
|
||||
|
|
@ -35,7 +33,7 @@ fun HomeSettingsAddRow(
|
|||
modifier: Modifier,
|
||||
firstFocus: FocusRequester = remember { FocusRequester() },
|
||||
) {
|
||||
LaunchedEffect(Unit) { firstFocus.tryRequestFocus() }
|
||||
// LaunchedEffect(Unit) { firstFocus.tryRequestFocus() }
|
||||
Column(modifier = modifier) {
|
||||
Text(
|
||||
text = "Add row for...",
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import androidx.compose.runtime.LaunchedEffect
|
|||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.focus.FocusRequester
|
||||
import androidx.compose.ui.focus.focusRequester
|
||||
import androidx.compose.ui.focus.focusRestorer
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
|
|
@ -65,7 +66,7 @@ fun HomeSettingsGlobal(
|
|||
)
|
||||
},
|
||||
onClick = { onClickResize.invoke(1) },
|
||||
modifier = Modifier,
|
||||
modifier = Modifier.focusRequester(firstFocus),
|
||||
)
|
||||
}
|
||||
item {
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import androidx.compose.foundation.layout.heightIn
|
|||
import androidx.compose.foundation.layout.wrapContentWidth
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.itemsIndexed
|
||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Add
|
||||
import androidx.compose.material.icons.filled.Delete
|
||||
|
|
@ -17,7 +18,10 @@ import androidx.compose.material.icons.filled.Settings
|
|||
import androidx.compose.material3.HorizontalDivider
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.focus.FocusDirection
|
||||
|
|
@ -36,7 +40,9 @@ import com.github.damontecres.wholphin.R
|
|||
import com.github.damontecres.wholphin.services.HomeRowConfigDisplay
|
||||
import com.github.damontecres.wholphin.ui.FontAwesome
|
||||
import com.github.damontecres.wholphin.ui.components.Button
|
||||
import com.github.damontecres.wholphin.ui.rememberInt
|
||||
import com.github.damontecres.wholphin.ui.tryRequestFocus
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
enum class MoveDirection {
|
||||
UP,
|
||||
|
|
@ -55,7 +61,16 @@ fun HomeSettingsRowList(
|
|||
firstFocus: FocusRequester = remember { FocusRequester() },
|
||||
) {
|
||||
val focusManager = LocalFocusManager.current
|
||||
LaunchedEffect(Unit) { firstFocus.tryRequestFocus() }
|
||||
val scope = rememberCoroutineScope()
|
||||
val listState = rememberLazyListState()
|
||||
|
||||
val itemsBeforeRows = 3
|
||||
val focusRequesters =
|
||||
remember(state.rows.size) { List(itemsBeforeRows + state.rows.size) { FocusRequester() } }
|
||||
|
||||
var position by rememberInt(0)
|
||||
|
||||
LaunchedEffect(Unit) { focusRequesters.getOrNull(position)?.tryRequestFocus() }
|
||||
Column(modifier = modifier) {
|
||||
Text(
|
||||
text = stringResource(R.string.customize_home),
|
||||
|
|
@ -64,6 +79,7 @@ fun HomeSettingsRowList(
|
|||
modifier = Modifier.fillMaxWidth(),
|
||||
)
|
||||
LazyColumn(
|
||||
state = listState,
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||
modifier =
|
||||
modifier
|
||||
|
|
@ -84,8 +100,11 @@ fun HomeSettingsRowList(
|
|||
contentDescription = null,
|
||||
)
|
||||
},
|
||||
onClick = onClickAdd,
|
||||
modifier = Modifier.focusRequester(firstFocus),
|
||||
onClick = {
|
||||
position = 0
|
||||
onClickAdd.invoke()
|
||||
},
|
||||
modifier = Modifier.focusRequester(focusRequesters[0]),
|
||||
)
|
||||
}
|
||||
item {
|
||||
|
|
@ -102,8 +121,11 @@ fun HomeSettingsRowList(
|
|||
contentDescription = null,
|
||||
)
|
||||
},
|
||||
onClick = onClickSettings,
|
||||
modifier = Modifier,
|
||||
onClick = {
|
||||
position = 1
|
||||
onClickSettings.invoke()
|
||||
},
|
||||
modifier = Modifier.focusRequester(focusRequesters[1]),
|
||||
)
|
||||
}
|
||||
item {
|
||||
|
|
@ -121,7 +143,18 @@ fun HomeSettingsRowList(
|
|||
moveUpAllowed = index > 0,
|
||||
moveDownAllowed = index != state.rows.lastIndex,
|
||||
deleteAllowed = state.rows.size > 1,
|
||||
onClickMove = { onClickMove.invoke(it, index) },
|
||||
onClickMove = {
|
||||
onClickMove.invoke(it, index)
|
||||
scope.launch {
|
||||
val scrollIndex =
|
||||
itemsBeforeRows + if (it == MoveDirection.UP) index - 1 else index + 1
|
||||
if (scrollIndex < listState.firstVisibleItemIndex ||
|
||||
scrollIndex > listState.layoutInfo.visibleItemsInfo.lastIndex
|
||||
) {
|
||||
listState.animateScrollToItem(scrollIndex)
|
||||
}
|
||||
}
|
||||
},
|
||||
onClickDelete = {
|
||||
if (index != state.rows.lastIndex) {
|
||||
focusManager.moveFocus(FocusDirection.Down)
|
||||
|
|
@ -130,10 +163,15 @@ fun HomeSettingsRowList(
|
|||
}
|
||||
onClickDelete.invoke(index)
|
||||
},
|
||||
onClick = { onClick.invoke(index, row) },
|
||||
onClick = {
|
||||
position = itemsBeforeRows + index
|
||||
onClick.invoke(index, row)
|
||||
},
|
||||
modifier =
|
||||
Modifier
|
||||
.fillMaxWidth(),
|
||||
.fillMaxWidth()
|
||||
.animateItem()
|
||||
.focusRequester(focusRequesters[itemsBeforeRows + index]),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,11 +30,16 @@ import com.github.damontecres.wholphin.util.LoadingState
|
|||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.awaitAll
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.sync.Semaphore
|
||||
import kotlinx.coroutines.sync.withPermit
|
||||
import kotlinx.serialization.Serializable
|
||||
import org.jellyfin.sdk.model.api.BaseItemKind
|
||||
import org.jellyfin.sdk.model.api.CollectionType
|
||||
|
|
@ -95,14 +100,17 @@ class HomeSettingsViewModel
|
|||
|
||||
private suspend fun fetchRowData() {
|
||||
val limit = 6
|
||||
val semaphore = Semaphore(4)
|
||||
val rows =
|
||||
serverRepository.currentUserDto.value?.let { userDto ->
|
||||
val prefs = userPreferencesService.getCurrent().appPreferences.homePagePreferences
|
||||
state.value.let { state ->
|
||||
state.value
|
||||
.let { state ->
|
||||
state.rows
|
||||
.map { it.config }
|
||||
.map { row ->
|
||||
// TODO parallelize
|
||||
viewModelScope.async(Dispatchers.IO) {
|
||||
semaphore.withPermit {
|
||||
homeSettingsService.fetchDataForRow(
|
||||
row = row,
|
||||
scope = viewModelScope,
|
||||
|
|
@ -114,6 +122,8 @@ class HomeSettingsViewModel
|
|||
}
|
||||
}
|
||||
}
|
||||
}.awaitAll()
|
||||
}
|
||||
rows?.let { rows ->
|
||||
rows
|
||||
.firstOrNull { it is HomeRowLoadingState.Success && it.items.isNotEmpty() }
|
||||
|
|
@ -152,16 +162,17 @@ class HomeSettingsViewModel
|
|||
direction: MoveDirection,
|
||||
index: Int,
|
||||
) {
|
||||
viewModelScope.launchIO {
|
||||
updateState {
|
||||
val rows = it.rows.move(direction, index)
|
||||
// TODO would be more efficient to move rowData, but uncombined continue watching is two rows
|
||||
// val rowData = it.rowData.move(direction, index)
|
||||
val rowData = it.rowData.move(direction, index)
|
||||
it.copy(
|
||||
loading = LoadingState.Loading,
|
||||
rows = rows,
|
||||
rowData = rowData,
|
||||
)
|
||||
}
|
||||
viewModelScope.launchIO { fetchRowData() }
|
||||
}
|
||||
// viewModelScope.launchIO { fetchRowData() }
|
||||
}
|
||||
|
||||
fun deleteRow(index: Int) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue