Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Unverified Commit 93a256ee authored by Arnau Mora's avatar Arnau Mora Committed by GitHub
Browse files

Icons next to CalDAV/CardDAV tab titles (#1599)



* Icons next to CalDAV/CardDAV tab titles

Signed-off-by: default avatarArnau Mora <arnyminerz@proton.me>

* Use shared element transitions

* Switch to `sharedBounds` to allow font size changes

* Update app/src/main/kotlin/at/bitfire/davdroid/ui/account/AccountScreen.kt

Co-authored-by: default avatarCopilot <175728472+Copilot@users.noreply.github.com>

* Minor changes

---------

Signed-off-by: default avatarArnau Mora <arnyminerz@proton.me>
Co-authored-by: default avatarCopilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: default avatarRicki Hirner <hirner@bitfire.at>
parent 61e9d60b
Loading
Loading
Loading
Loading
+125 −47
Original line number Diff line number Diff line
@@ -7,21 +7,31 @@ import android.Manifest
import android.accounts.Account
import android.content.Intent
import android.widget.Toast
import androidx.compose.animation.AnimatedContent
import androidx.compose.animation.AnimatedVisibilityScope
import androidx.compose.animation.ExperimentalSharedTransitionApi
import androidx.compose.animation.SharedTransitionLayout
import androidx.compose.animation.SharedTransitionScope
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.pager.HorizontalPager
import androidx.compose.foundation.pager.rememberPagerState
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.filled.CalendarToday
import androidx.compose.material.icons.filled.CreateNewFolder
import androidx.compose.material.icons.filled.Delete
import androidx.compose.material.icons.filled.DriveFileRenameOutline
import androidx.compose.material.icons.filled.MoreVert
import androidx.compose.material.icons.filled.Person
import androidx.compose.material.icons.filled.Settings
import androidx.compose.material.icons.filled.Sync
import androidx.compose.material.icons.filled.SyncProblem
import androidx.compose.material.icons.filled.Upcoming
import androidx.compose.material.icons.outlined.RuleFolder
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button
@@ -56,6 +66,7 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalInspectionMode
import androidx.compose.ui.res.stringResource
@@ -161,7 +172,7 @@ fun AccountScreen(
    )
}

@OptIn(ExperimentalFoundationApi::class, ExperimentalMaterial3Api::class)
@OptIn(ExperimentalFoundationApi::class, ExperimentalMaterial3Api::class, ExperimentalSharedTransitionApi::class)
@Composable
fun AccountScreen(
    accountName: String,
@@ -238,6 +249,10 @@ fun AccountScreen(
                    (if (idxWebcal != null) 1 else 0)
        val pagerState = rememberPagerState(pageCount = { nrPages })

        val calDavScrollState = rememberLazyListState()
        val cardDavScrollState = rememberLazyListState()
        val webcalScrollState = rememberLazyListState()

        Scaffold(
            topBar = {
                TopAppBar(
@@ -310,52 +325,61 @@ fun AccountScreen(
                modifier = Modifier.padding(padding)
            ) {
                if (nrPages > 0) {
                    TabRow(selectedTabIndex = pagerState.currentPage) {
                        if (idxCalDav != null) {
                            Tab(
                                selected = pagerState.currentPage == idxCalDav,
                                onClick = {
                    SharedTransitionLayout {
                        val idxCurrentPage = pagerState.currentPage

                        // The icon shall be shown when the scroll state is at the top (= we can't scroll backward)
                        val currentPageScrollState = when (idxCurrentPage) {
                            idxCalDav -> calDavScrollState
                            idxCardDav -> cardDavScrollState
                            idxWebcal -> webcalScrollState
                            else -> null
                        }
                        AnimatedContent(
                            targetState = currentPageScrollState?.canScrollBackward == false
                        ) { showIcon ->
                            TabRow(selectedTabIndex = idxCurrentPage) {
                                if (idxCalDav != null)
                                    AccountScreen_Tab(
                                        selected = idxCurrentPage == idxCalDav,
                                        showIcon = showIcon,
                                        icon = Icons.Default.CalendarToday,
                                        text = stringResource(R.string.account_caldav),
                                        animatedVisibilityScope = this@AnimatedContent,
                                        sharedTransitionScope = this@SharedTransitionLayout,
                                    ) {
                                        scope.launch {
                                            pagerState.scrollToPage(idxCalDav)
                                        }
                                    }
                            ) {
                                Text(
                                    stringResource(R.string.account_caldav),
                                    modifier = Modifier.padding(8.dp)
                                )
                            }
                        }

                        if (idxCardDav != null) {
                            Tab(
                                selected = pagerState.currentPage == idxCardDav,
                                onClick = {
                                if (idxCardDav != null)
                                    AccountScreen_Tab(
                                        selected = idxCurrentPage == idxCardDav,
                                        showIcon = showIcon,
                                        icon = Icons.Default.Person,
                                        text = stringResource(R.string.account_carddav),
                                        animatedVisibilityScope = this@AnimatedContent,
                                        sharedTransitionScope = this@SharedTransitionLayout,
                                    ) {
                                        scope.launch {
                                            pagerState.scrollToPage(idxCardDav)
                                        }
                                    }
                            ) {
                                Text(
                                    stringResource(R.string.account_carddav),
                                    modifier = Modifier.padding(8.dp)
                                )
                            }
                        }

                        if (idxWebcal != null) {
                            Tab(
                                selected = pagerState.currentPage == idxWebcal,
                                onClick = {
                                if (idxWebcal != null)
                                    AccountScreen_Tab(
                                        selected = idxCurrentPage == idxWebcal,
                                        showIcon = showIcon,
                                        icon = Icons.Default.Upcoming,
                                        text = stringResource(R.string.account_webcal),
                                        animatedVisibilityScope = this@AnimatedContent,
                                        sharedTransitionScope = this@SharedTransitionLayout,
                                    ) {
                                        scope.launch {
                                            pagerState.scrollToPage(idxWebcal)
                                        }
                                    }
                            ) {
                                Text(
                                    stringResource(R.string.account_webcal),
                                    modifier = Modifier.padding(8.dp)
                                )
                            }
                        }
                    }
@@ -378,7 +402,8 @@ fun AccountScreen(
                                        progress = cardDavProgress,
                                        collections = addressBooks,
                                        onUpdateCollectionSync = onUpdateCollectionSync,
                                        onCollectionDetails = onCollectionDetails
                                        onCollectionDetails = onCollectionDetails,
                                        state = cardDavScrollState
                                    )

                                idxCalDav -> {
@@ -390,7 +415,8 @@ fun AccountScreen(
                                        progress = calDavProgress,
                                        collections = calendars,
                                        onUpdateCollectionSync = onUpdateCollectionSync,
                                        onCollectionDetails = onCollectionDetails
                                        onCollectionDetails = onCollectionDetails,
                                        state = calDavScrollState
                                    )
                                }

@@ -425,7 +451,8 @@ fun AccountScreen(
                                            requiredPermissions = listOf(Manifest.permission.WRITE_CALENDAR),
                                            progress = calDavProgress,
                                            collections = subscriptions,
                                            onSubscribe = onSubscribe
                                            onSubscribe = onSubscribe,
                                            state = webcalScrollState
                                        )
                                    }
                                }
@@ -438,6 +465,55 @@ fun AccountScreen(
    }
}

@Composable
@OptIn(ExperimentalSharedTransitionApi::class)
fun AccountScreen_Tab(
    selected: Boolean,
    showIcon: Boolean,
    icon: ImageVector,
    text: String,
    sharedTransitionScope: SharedTransitionScope,
    animatedVisibilityScope: AnimatedVisibilityScope,
    onClick: () -> Unit,
) {
    with(sharedTransitionScope) {
        if (showIcon) {
            Tab(
                selected = selected,
                onClick = onClick,
                icon = { Icon(imageVector = icon, contentDescription = text) },
                text = {
                    Text(
                        text,
                        modifier = Modifier
                            .sharedBounds(
                                rememberSharedContentState(key = text),
                                animatedVisibilityScope = animatedVisibilityScope,
                            )
                            .padding(8.dp)
                    )
                }
            )
        } else {
            Tab(
                selected = selected,
                onClick = onClick,
                content = {
                    Text(
                        text,
                        modifier = Modifier
                            .sharedBounds(
                                rememberSharedContentState(key = text),
                                animatedVisibilityScope = animatedVisibilityScope,
                            )
                            .padding(8.dp)
                    )
                }
            )
        }
    }
}

@Composable
fun AccountScreen_Actions(
    accountName: String,
@@ -601,7 +677,8 @@ fun AccountScreen_ServiceTab(
    collections: LazyPagingItems<Collection>?,
    onUpdateCollectionSync: (collectionId: Long, sync: Boolean) -> Unit = { _, _ -> },
    onSubscribe: (Collection) -> Unit = {},
    onCollectionDetails: ((Collection) -> Unit)? = null
    onCollectionDetails: ((Collection) -> Unit)? = null,
    state: LazyListState = rememberLazyListState()
) {
    val context = LocalContext.current

@@ -646,7 +723,8 @@ fun AccountScreen_ServiceTab(
                    onChangeSync = onUpdateCollectionSync,
                    onSubscribe = onSubscribe,
                    onCollectionDetails = onCollectionDetails,
                    modifier = Modifier.weight(1f)
                    modifier = Modifier.weight(1f),
                    state = state
                )
        }
    }
+6 −2
Original line number Diff line number Diff line
@@ -22,6 +22,8 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.EventNote
@@ -61,12 +63,14 @@ fun CollectionsList(
    onChangeSync: (collectionId: Long, sync: Boolean) -> Unit,
    modifier: Modifier = Modifier,
    onSubscribe: (collection: Collection) -> Unit = {},
    onCollectionDetails: ((collection: Collection) -> Unit)? = null
    onCollectionDetails: ((collection: Collection) -> Unit)? = null,
    state: LazyListState = rememberLazyListState()
) {
    LazyColumn(
        contentPadding = PaddingValues(8.dp),
        verticalArrangement = Arrangement.spacedBy(12.dp, Alignment.Top),
        modifier = modifier
        modifier = modifier,
        state = state
    ) {
        items(
            count = collections.itemCount,