Improved pulltorefresh look and implementation
This commit is contained in:
@@ -12,7 +12,6 @@ import androidx.compose.foundation.background
|
|||||||
import androidx.compose.foundation.gestures.detectTapGestures
|
import androidx.compose.foundation.gestures.detectTapGestures
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.BoxScope
|
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.RowScope
|
import androidx.compose.foundation.layout.RowScope
|
||||||
@@ -45,9 +44,6 @@ import androidx.compose.material3.OutlinedTextField
|
|||||||
import androidx.compose.material3.OutlinedTextFieldDefaults
|
import androidx.compose.material3.OutlinedTextFieldDefaults
|
||||||
import androidx.compose.material3.Surface
|
import androidx.compose.material3.Surface
|
||||||
import androidx.compose.material3.TextButton
|
import androidx.compose.material3.TextButton
|
||||||
import androidx.compose.material3.pulltorefresh.PullToRefreshDefaults.Indicator
|
|
||||||
import androidx.compose.material3.pulltorefresh.pullToRefresh
|
|
||||||
import androidx.compose.material3.pulltorefresh.rememberPullToRefreshState
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.MutableState
|
import androidx.compose.runtime.MutableState
|
||||||
@@ -161,36 +157,6 @@ object CustomElements {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
|
||||||
@Composable
|
|
||||||
fun PullToRefreshBox(
|
|
||||||
isRefreshing: Boolean,
|
|
||||||
onRefresh: () -> Unit,
|
|
||||||
modifier: Modifier = Modifier,
|
|
||||||
contentAlignment: Alignment = Alignment.TopStart,
|
|
||||||
enabled: Boolean = true,
|
|
||||||
content: @Composable BoxScope.() -> Unit,
|
|
||||||
) {
|
|
||||||
val refreshState = rememberPullToRefreshState()
|
|
||||||
|
|
||||||
Box(
|
|
||||||
modifier.pullToRefresh(
|
|
||||||
state = refreshState,
|
|
||||||
isRefreshing = isRefreshing,
|
|
||||||
onRefresh = onRefresh,
|
|
||||||
enabled = enabled,
|
|
||||||
),
|
|
||||||
contentAlignment = contentAlignment,
|
|
||||||
) {
|
|
||||||
content()
|
|
||||||
Indicator(
|
|
||||||
modifier = Modifier.align(Alignment.TopCenter),
|
|
||||||
isRefreshing = isRefreshing,
|
|
||||||
state = refreshState,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun DropdownMenu(
|
fun DropdownMenu(
|
||||||
expanded: Boolean,
|
expanded: Boolean,
|
||||||
|
|||||||
@@ -99,6 +99,9 @@ import androidx.compose.material3.TextButton
|
|||||||
import androidx.compose.material3.TextField
|
import androidx.compose.material3.TextField
|
||||||
import androidx.compose.material3.TopAppBar
|
import androidx.compose.material3.TopAppBar
|
||||||
import androidx.compose.material3.TopAppBarDefaults
|
import androidx.compose.material3.TopAppBarDefaults
|
||||||
|
import androidx.compose.material3.pulltorefresh.PullToRefreshDefaults.Indicator
|
||||||
|
import androidx.compose.material3.pulltorefresh.pullToRefresh
|
||||||
|
import androidx.compose.material3.pulltorefresh.rememberPullToRefreshState
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.collectAsState
|
import androidx.compose.runtime.collectAsState
|
||||||
@@ -140,7 +143,6 @@ import com.tutpro.baresip.CustomElements.Checkbox
|
|||||||
import com.tutpro.baresip.CustomElements.DropdownMenu
|
import com.tutpro.baresip.CustomElements.DropdownMenu
|
||||||
import com.tutpro.baresip.CustomElements.LabelText
|
import com.tutpro.baresip.CustomElements.LabelText
|
||||||
import com.tutpro.baresip.CustomElements.PasswordDialog
|
import com.tutpro.baresip.CustomElements.PasswordDialog
|
||||||
import com.tutpro.baresip.CustomElements.PullToRefreshBox
|
|
||||||
import com.tutpro.baresip.CustomElements.SelectableAlertDialog
|
import com.tutpro.baresip.CustomElements.SelectableAlertDialog
|
||||||
import com.tutpro.baresip.CustomElements.Text
|
import com.tutpro.baresip.CustomElements.Text
|
||||||
import com.tutpro.baresip.CustomElements.verticalScrollbar
|
import com.tutpro.baresip.CustomElements.verticalScrollbar
|
||||||
@@ -520,6 +522,10 @@ class MainActivity : ComponentActivity() {
|
|||||||
fun MainContent(ctx: Context, contentPadding: PaddingValues) {
|
fun MainContent(ctx: Context, contentPadding: PaddingValues) {
|
||||||
|
|
||||||
var isRefreshing by remember { mutableStateOf(false) }
|
var isRefreshing by remember { mutableStateOf(false) }
|
||||||
|
val refreshState = rememberPullToRefreshState()
|
||||||
|
var offset by remember { mutableFloatStateOf(0f) }
|
||||||
|
val swipeThreshold = 200
|
||||||
|
|
||||||
LaunchedEffect(isRefreshing) {
|
LaunchedEffect(isRefreshing) {
|
||||||
if (isRefreshing) {
|
if (isRefreshing) {
|
||||||
delay(1000)
|
delay(1000)
|
||||||
@@ -527,14 +533,13 @@ class MainActivity : ComponentActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (showAlert.value) {
|
if (showAlert.value)
|
||||||
AlertDialog(
|
AlertDialog(
|
||||||
showDialog = showAlert,
|
showDialog = showAlert,
|
||||||
title = alertTitle.value,
|
title = alertTitle.value,
|
||||||
message = alertMessage.value,
|
message = alertMessage.value,
|
||||||
positiveButtonText = stringResource(R.string.ok),
|
positiveButtonText = stringResource(R.string.ok),
|
||||||
)
|
)
|
||||||
}
|
|
||||||
|
|
||||||
if (showDialog.value)
|
if (showDialog.value)
|
||||||
AlertDialog(
|
AlertDialog(
|
||||||
@@ -547,87 +552,90 @@ class MainActivity : ComponentActivity() {
|
|||||||
onNegativeClicked = onNegativeClicked.value
|
onNegativeClicked = onNegativeClicked.value
|
||||||
)
|
)
|
||||||
|
|
||||||
PullToRefreshBox(
|
SelectableAlertDialog(
|
||||||
isRefreshing = isRefreshing,
|
openDialog = showSelectItemDialog,
|
||||||
modifier = Modifier.fillMaxSize(),
|
title = getString(R.string.choose_destination_uri),
|
||||||
enabled = pullToRefreshEnabled,
|
items = items.value,
|
||||||
onRefresh = {
|
onItemClicked = itemAction.value,
|
||||||
isRefreshing = true
|
neutralButtonText = getString(R.string.cancel),
|
||||||
if (uas.value.isNotEmpty()) {
|
onNeutralClicked = {}
|
||||||
if (viewModel.selectedAor.value == "")
|
)
|
||||||
spinToAor(uas.value.first().account.aor)
|
|
||||||
val ua = UserAgent.ofAor(viewModel.selectedAor.value)!!
|
Column(
|
||||||
if (ua.account.regint > 0)
|
modifier = Modifier
|
||||||
Api.ua_register(ua.uap)
|
.imePadding()
|
||||||
}
|
.fillMaxWidth()
|
||||||
}
|
.padding(contentPadding)
|
||||||
) {
|
.padding(top = 18.dp, bottom = 6.dp, start = 16.dp, end = 16.dp)
|
||||||
SelectableAlertDialog(
|
.fillMaxSize()
|
||||||
openDialog = showSelectItemDialog,
|
.pullToRefresh(
|
||||||
title = getString(R.string.choose_destination_uri),
|
state = refreshState,
|
||||||
items = items.value,
|
isRefreshing = isRefreshing,
|
||||||
onItemClicked = itemAction.value,
|
onRefresh = {
|
||||||
neutralButtonText = getString(R.string.cancel),
|
isRefreshing = true
|
||||||
onNeutralClicked = {}
|
if (uas.value.isNotEmpty()) {
|
||||||
)
|
if (viewModel.selectedAor.value == "")
|
||||||
var offset by remember { mutableFloatStateOf(0f) }
|
spinToAor(uas.value.first().account.aor)
|
||||||
val swipeThreshold = 200
|
val ua = UserAgent.ofAor(viewModel.selectedAor.value)!!
|
||||||
Column(
|
if (ua.account.regint > 0)
|
||||||
modifier = Modifier
|
Api.ua_register(ua.uap)
|
||||||
.imePadding()
|
}
|
||||||
.fillMaxWidth()
|
},
|
||||||
.padding(contentPadding)
|
enabled = pullToRefreshEnabled,
|
||||||
.padding(top = 18.dp, bottom = 6.dp, start = 16.dp, end = 16.dp)
|
)
|
||||||
.fillMaxSize()
|
.pointerInput(Unit) {
|
||||||
.pointerInput(Unit) {
|
detectHorizontalDragGestures(
|
||||||
detectHorizontalDragGestures(
|
onDragStart = { offset = 0f },
|
||||||
onDragStart = { offset = 0f },
|
onDragEnd = {
|
||||||
onDragEnd = {
|
if (offset < -swipeThreshold) {
|
||||||
if (offset < -swipeThreshold) {
|
if (uas.value.isNotEmpty()) {
|
||||||
if (uas.value.isNotEmpty()) {
|
val curPos = UserAgent.findAorIndex(viewModel.selectedAor.value)
|
||||||
val curPos = UserAgent.findAorIndex(viewModel.selectedAor.value)
|
val newPos = if (curPos == null)
|
||||||
val newPos = if (curPos == null)
|
0
|
||||||
0
|
else
|
||||||
else
|
(curPos + 1) % uas.value.size
|
||||||
(curPos + 1) % uas.value.size
|
if (curPos != newPos) {
|
||||||
if (curPos != newPos) {
|
val ua = uas.value[newPos]
|
||||||
val ua = uas.value[newPos]
|
spinToAor(ua.account.aor)
|
||||||
spinToAor(ua.account.aor)
|
showCall(ua)
|
||||||
showCall(ua)
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
else if (offset > swipeThreshold) {
|
||||||
else if (offset > swipeThreshold) {
|
if (uas.value.isNotEmpty()) {
|
||||||
if (uas.value.isNotEmpty()) {
|
val curPos = UserAgent.findAorIndex(viewModel.selectedAor.value)
|
||||||
val curPos = UserAgent.findAorIndex(viewModel.selectedAor.value)
|
val newPos = when (curPos) {
|
||||||
val newPos = when (curPos) {
|
null -> 0
|
||||||
null -> 0
|
0 -> uas.value.size - 1
|
||||||
0 -> uas.value.size - 1
|
else -> curPos - 1
|
||||||
else -> curPos - 1
|
}
|
||||||
}
|
if (curPos != newPos) {
|
||||||
if (curPos != newPos) {
|
val ua = uas.value[newPos]
|
||||||
val ua = uas.value[newPos]
|
spinToAor(ua.account.aor)
|
||||||
spinToAor(ua.account.aor)
|
showCall(ua)
|
||||||
showCall(ua)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
) { _, dragAmount ->
|
|
||||||
offset += dragAmount
|
|
||||||
}
|
}
|
||||||
|
) { _, dragAmount ->
|
||||||
|
offset += dragAmount
|
||||||
}
|
}
|
||||||
.verticalScroll(rememberScrollState()),
|
}
|
||||||
verticalArrangement = Arrangement.Top,
|
.verticalScroll(rememberScrollState()),
|
||||||
horizontalAlignment = Alignment.CenterHorizontally,
|
verticalArrangement = Arrangement.Top,
|
||||||
) {
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
AccountSpinner(ctx)
|
) {
|
||||||
CallUriRow()
|
AccountSpinner(ctx)
|
||||||
CallRow(ctx)
|
CallUriRow()
|
||||||
OnHoldNotice()
|
CallRow(ctx)
|
||||||
AskPasswords(ctx)
|
OnHoldNotice()
|
||||||
AskPassword(ctx)
|
AskPasswords(ctx)
|
||||||
}
|
AskPassword(ctx)
|
||||||
|
Indicator(
|
||||||
|
modifier = Modifier.align(Alignment.CenterHorizontally),
|
||||||
|
isRefreshing = isRefreshing,
|
||||||
|
state = refreshState,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user