diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index b488028..e021703 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -9,7 +9,7 @@ androidx-lifecycle-runtime-ktx = "2.8.4" # Compose androidx-activity-compose = "1.9.1" androidx-paging-compose = "3.3.2" -compose-multiplatform = "1.6.11" +compose-multiplatform = "1.7.0-alpha03" # KotlinX kotlinx-coroutines-core = "1.8.1" diff --git a/ui/build.gradle.kts b/ui/build.gradle.kts index 56b116e..ad1fb54 100644 --- a/ui/build.gradle.kts +++ b/ui/build.gradle.kts @@ -46,7 +46,6 @@ kotlin { api(libs.bundles.voyager) api(compose.material3) - api(compose.material) api(compose.materialIconsExtended) api(compose.runtime) diff --git a/ui/src/commonMain/kotlin/com/materiiapps/gloom/ui/component/RefreshIndicator.kt b/ui/src/commonMain/kotlin/com/materiiapps/gloom/ui/component/RefreshIndicator.kt deleted file mode 100644 index 771bba8..0000000 --- a/ui/src/commonMain/kotlin/com/materiiapps/gloom/ui/component/RefreshIndicator.kt +++ /dev/null @@ -1,23 +0,0 @@ -package com.materiiapps.gloom.ui.component - -import androidx.compose.foundation.layout.BoxScope -import androidx.compose.material.ExperimentalMaterialApi -import androidx.compose.material.pullrefresh.PullRefreshIndicator -import androidx.compose.material.pullrefresh.PullRefreshState -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.surfaceColorAtElevation -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.dp - -@OptIn(ExperimentalMaterialApi::class) -@Composable -fun BoxScope.RefreshIndicator(state: PullRefreshState, isRefreshing: Boolean) = - PullRefreshIndicator( - state = state, - contentColor = MaterialTheme.colorScheme.primary, - backgroundColor = MaterialTheme.colorScheme.surfaceColorAtElevation(2.dp), - refreshing = isRefreshing, - modifier = Modifier.align(Alignment.TopCenter) - ) \ No newline at end of file diff --git a/ui/src/commonMain/kotlin/com/materiiapps/gloom/ui/component/bottomsheet/BottomSheet.kt b/ui/src/commonMain/kotlin/com/materiiapps/gloom/ui/component/bottomsheet/BottomSheet.kt index d4606c8..d3ef095 100644 --- a/ui/src/commonMain/kotlin/com/materiiapps/gloom/ui/component/bottomsheet/BottomSheet.kt +++ b/ui/src/commonMain/kotlin/com/materiiapps/gloom/ui/component/bottomsheet/BottomSheet.kt @@ -41,7 +41,7 @@ fun BottomSheet( tonalElevation = tonalElevation, scrimColor = scrimColor, dragHandle = dragHandle, - windowInsets = WindowInsets(0, 0, 0, 0), + contentWindowInsets = { WindowInsets(0, 0, 0, 0) }, content = { val coroutineScope = rememberCoroutineScope() val animateToDismiss: () -> Unit = { diff --git a/ui/src/commonMain/kotlin/com/materiiapps/gloom/ui/screen/explorer/FileViewerScreen.kt b/ui/src/commonMain/kotlin/com/materiiapps/gloom/ui/screen/explorer/FileViewerScreen.kt index 32ca1b4..13eb954 100644 --- a/ui/src/commonMain/kotlin/com/materiiapps/gloom/ui/screen/explorer/FileViewerScreen.kt +++ b/ui/src/commonMain/kotlin/com/materiiapps/gloom/ui/screen/explorer/FileViewerScreen.kt @@ -11,15 +11,12 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding -import androidx.compose.material.ExperimentalMaterialApi import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Close import androidx.compose.material.icons.filled.Share import androidx.compose.material.icons.outlined.ContentCopy import androidx.compose.material.icons.outlined.Description import androidx.compose.material.icons.outlined.FormatColorText -import androidx.compose.material.pullrefresh.pullRefresh -import androidx.compose.material.pullrefresh.rememberPullRefreshState import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon import androidx.compose.material3.IconButton @@ -29,6 +26,7 @@ import androidx.compose.material3.Text import androidx.compose.material3.TopAppBar import androidx.compose.material3.TopAppBarDefaults import androidx.compose.material3.TopAppBarScrollBehavior +import androidx.compose.material3.pulltorefresh.PullToRefreshBox import androidx.compose.material3.surfaceColorAtElevation import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue @@ -50,7 +48,6 @@ import com.materiiapps.gloom.gql.fragment.RepoFile import com.materiiapps.gloom.ui.component.BackButton import com.materiiapps.gloom.ui.component.DownloadButton import com.materiiapps.gloom.ui.component.ErrorMessage -import com.materiiapps.gloom.ui.component.RefreshIndicator import com.materiiapps.gloom.ui.screen.explorer.viewers.ImageFileViewer import com.materiiapps.gloom.ui.screen.explorer.viewers.MarkdownFileViewer import com.materiiapps.gloom.ui.screen.explorer.viewers.PdfFileViewer @@ -69,13 +66,11 @@ class FileViewerScreen( ) : Screen { @Composable - @OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterialApi::class) + @OptIn(ExperimentalMaterial3Api::class) override fun Content() { val viewModel: FileViewerViewModel = getScreenModel { parametersOf(FileViewerViewModel.Input(owner, name, branch, path)) } val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior() - val pullRefreshState = - rememberPullRefreshState(viewModel.isLoading, onRefresh = viewModel::refresh) val file = viewModel.file?.gitObject?.onCommit?.file var topBarHidden by remember { @@ -87,11 +82,12 @@ class FileViewerScreen( modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection), contentWindowInsets = WindowInsets(0, 0, 0, 0) ) { pv -> - Box( + PullToRefreshBox( + isRefreshing = viewModel.isLoading, + onRefresh = { viewModel.refresh() }, modifier = Modifier .padding(pv) .fillMaxSize() - .pullRefresh(pullRefreshState) ) { when (viewModel.fileHasError) { true -> ErrorMessage( @@ -110,8 +106,6 @@ class FileViewerScreen( } ) } - - RefreshIndicator(pullRefreshState, viewModel.isLoading) } } } diff --git a/ui/src/commonMain/kotlin/com/materiiapps/gloom/ui/screen/home/HomeScreen.kt b/ui/src/commonMain/kotlin/com/materiiapps/gloom/ui/screen/home/HomeScreen.kt index 3bc804c..0acd7ed 100644 --- a/ui/src/commonMain/kotlin/com/materiiapps/gloom/ui/screen/home/HomeScreen.kt +++ b/ui/src/commonMain/kotlin/com/materiiapps/gloom/ui/screen/home/HomeScreen.kt @@ -9,19 +9,17 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.rememberLazyListState -import androidx.compose.material.ExperimentalMaterialApi import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Home import androidx.compose.material.icons.filled.KeyboardArrowUp import androidx.compose.material.icons.outlined.Home -import androidx.compose.material.pullrefresh.pullRefresh -import androidx.compose.material.pullrefresh.rememberPullRefreshState import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon import androidx.compose.material3.Scaffold import androidx.compose.material3.SmallFloatingActionButton import androidx.compose.material3.TopAppBarDefaults import androidx.compose.material3.TopAppBarScrollBehavior +import androidx.compose.material3.pulltorefresh.PullToRefreshBox import androidx.compose.runtime.Composable import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue @@ -39,7 +37,6 @@ import cafe.adriel.voyager.navigator.tab.LocalTabNavigator import cafe.adriel.voyager.navigator.tab.Tab import cafe.adriel.voyager.navigator.tab.TabOptions import com.materiiapps.gloom.Res -import com.materiiapps.gloom.ui.component.RefreshIndicator import com.materiiapps.gloom.ui.component.toolbar.LargeToolbar import com.materiiapps.gloom.ui.screen.home.viewmodel.HomeViewModel import com.materiiapps.gloom.ui.screen.home.component.CreatedRepoItem @@ -68,16 +65,13 @@ class HomeScreen : Tab { override fun Content() = Screen() @Composable - @OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterialApi::class) + @OptIn(ExperimentalMaterial3Api::class) private fun Screen( viewModel: HomeViewModel = getScreenModel() ) { val items = viewModel.items.collectAsLazyPagingItems() val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior() val isLoading = items.loadState.refresh == LoadState.Loading - val refreshState = rememberPullRefreshState(isLoading, onRefresh = { - viewModel.refresh(items) - }) val lazyListState = rememberLazyListState() val coroutineScope = rememberCoroutineScope() val canScrollBackToTop by remember { derivedStateOf { lazyListState.canScrollBackward } } @@ -100,11 +94,12 @@ class HomeScreen : Tab { } } ) { pv -> - Box( + PullToRefreshBox( + isRefreshing = isLoading, + onRefresh = { viewModel.refresh(items) }, modifier = Modifier .fillMaxSize() .padding(pv) - .pullRefresh(refreshState) .nestedScroll(scrollBehavior.nestedScrollConnection) ) { LazyColumn( @@ -193,8 +188,6 @@ class HomeScreen : Tab { } } } - - RefreshIndicator(refreshState, isRefreshing = isLoading) } } } diff --git a/ui/src/commonMain/kotlin/com/materiiapps/gloom/ui/screen/list/base/BaseListScreen.kt b/ui/src/commonMain/kotlin/com/materiiapps/gloom/ui/screen/list/base/BaseListScreen.kt index 2a16282..72badf8 100644 --- a/ui/src/commonMain/kotlin/com/materiiapps/gloom/ui/screen/list/base/BaseListScreen.kt +++ b/ui/src/commonMain/kotlin/com/materiiapps/gloom/ui/screen/list/base/BaseListScreen.kt @@ -4,13 +4,11 @@ import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.material.ExperimentalMaterialApi -import androidx.compose.material.pullrefresh.pullRefresh -import androidx.compose.material.pullrefresh.rememberPullRefreshState import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Scaffold import androidx.compose.material3.TopAppBarDefaults import androidx.compose.material3.TopAppBarScrollBehavior +import androidx.compose.material3.pulltorefresh.PullToRefreshBox import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.input.nestedscroll.nestedScroll @@ -20,7 +18,6 @@ import androidx.paging.compose.itemContentType import androidx.paging.compose.itemKey import cafe.adriel.voyager.core.screen.Screen import com.apollographql.apollo.api.Query -import com.materiiapps.gloom.ui.component.RefreshIndicator import com.materiiapps.gloom.ui.component.ThinDivider import com.materiiapps.gloom.ui.component.toolbar.LargeToolbar import com.materiiapps.gloom.ui.screen.list.viewmodel.BaseListViewModel @@ -41,23 +38,21 @@ abstract class BaseListScreen - Box( + PullToRefreshBox( + isRefreshing = isLoading, + onRefresh = { items.refresh() }, modifier = Modifier .fillMaxSize() .padding(pv) - .pullRefresh(refreshState) ) { LazyColumn( modifier = Modifier @@ -76,8 +71,6 @@ abstract class BaseListScreen - Box( + PullToRefreshBox( + isRefreshing = viewModel.isLoading, + onRefresh = { viewModel.loadData() }, modifier = Modifier .fillMaxSize() .padding(pv) - .pullRefresh(refreshState) ) { Column( Modifier @@ -179,8 +175,6 @@ open class ProfileScreen( Spacer(modifier = Modifier.height(16.dp)) } } - - RefreshIndicator(refreshState, isRefreshing = viewModel.isLoading) } } } diff --git a/ui/src/commonMain/kotlin/com/materiiapps/gloom/ui/screen/release/ReleaseScreen.kt b/ui/src/commonMain/kotlin/com/materiiapps/gloom/ui/screen/release/ReleaseScreen.kt index 26b7806..56a15c1 100644 --- a/ui/src/commonMain/kotlin/com/materiiapps/gloom/ui/screen/release/ReleaseScreen.kt +++ b/ui/src/commonMain/kotlin/com/materiiapps/gloom/ui/screen/release/ReleaseScreen.kt @@ -8,13 +8,10 @@ import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.material.ExperimentalMaterialApi import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Download import androidx.compose.material.icons.filled.Share import androidx.compose.material.icons.outlined.CheckCircleOutline -import androidx.compose.material.pullrefresh.pullRefresh -import androidx.compose.material.pullrefresh.rememberPullRefreshState import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon import androidx.compose.material3.IconButton @@ -24,6 +21,7 @@ import androidx.compose.material3.Text import androidx.compose.material3.TopAppBar import androidx.compose.material3.TopAppBarDefaults import androidx.compose.material3.TopAppBarScrollBehavior +import androidx.compose.material3.pulltorefresh.PullToRefreshBox import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clipToBounds @@ -46,7 +44,6 @@ import com.materiiapps.gloom.domain.manager.DialogState import com.materiiapps.gloom.domain.manager.ShareManager import com.materiiapps.gloom.gql.fragment.ReleaseDetails import com.materiiapps.gloom.ui.component.BackButton -import com.materiiapps.gloom.ui.component.RefreshIndicator import com.materiiapps.gloom.ui.component.ThinDivider import com.materiiapps.gloom.ui.theme.colors import com.materiiapps.gloom.ui.screen.release.viewmodel.ReleaseViewModel @@ -74,7 +71,7 @@ class ReleaseScreen( override val key = "$owner/$name-$tag-${uuid4()}" @Composable - @OptIn(ExperimentalMaterialApi::class, ExperimentalMaterial3Api::class) + @OptIn(ExperimentalMaterial3Api::class) override fun Content() { val viewModel: ReleaseViewModel = getScreenModel { parametersOf(Triple(owner, name, tag)) } val alertController = LocalAlertController.current @@ -83,10 +80,6 @@ class ReleaseScreen( val items = viewModel.items.collectAsLazyPagingItems() val details = viewModel.details val isLoading = items.loadState.refresh == LoadState.Loading - val pullRefreshState = rememberPullRefreshState( - refreshing = isLoading, - onRefresh = { items.refresh() } - ) Scaffold( topBar = { @@ -97,10 +90,11 @@ class ReleaseScreen( ) } ) { pv -> - Box( + PullToRefreshBox( + isRefreshing = isLoading, + onRefresh = { items.refresh() }, modifier = Modifier .padding(pv) - .pullRefresh(pullRefreshState) .fillMaxSize() .clipToBounds() .nestedScroll(scrollBehavior.nestedScrollConnection) @@ -231,13 +225,12 @@ class ReleaseScreen( } } } - RefreshIndicator(state = pullRefreshState, isRefreshing = isLoading) } } } @Composable - @OptIn(ExperimentalFoundationApi::class, ExperimentalMaterial3Api::class) + @OptIn(ExperimentalMaterial3Api::class) fun TitleBar( details: ReleaseDetails?, isLoading: Boolean, diff --git a/ui/src/commonMain/kotlin/com/materiiapps/gloom/ui/screen/repo/RepoScreen.kt b/ui/src/commonMain/kotlin/com/materiiapps/gloom/ui/screen/repo/RepoScreen.kt index eceb2cb..6624faa 100644 --- a/ui/src/commonMain/kotlin/com/materiiapps/gloom/ui/screen/repo/RepoScreen.kt +++ b/ui/src/commonMain/kotlin/com/materiiapps/gloom/ui/screen/repo/RepoScreen.kt @@ -17,7 +17,6 @@ import androidx.compose.foundation.layout.widthIn import androidx.compose.foundation.pager.HorizontalPager import androidx.compose.foundation.pager.rememberPagerState import androidx.compose.foundation.shape.CircleShape -import androidx.compose.material.IconButton import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Share import androidx.compose.material.icons.outlined.Inventory2 @@ -25,6 +24,7 @@ import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton import androidx.compose.material3.LargeTopAppBar import androidx.compose.material3.LocalContentColor import androidx.compose.material3.MaterialTheme @@ -81,7 +81,7 @@ class RepoScreen( override fun Content() = Screen() @Composable - @OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class) + @OptIn(ExperimentalMaterial3Api::class) private fun Screen( viewModel: RepoViewModel = getScreenModel { parametersOf(owner to name) } ) { @@ -207,7 +207,7 @@ class RepoScreen( } @Composable - @OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class) + @OptIn(ExperimentalMaterial3Api::class) private fun Toolbar( scrollBehavior: TopAppBarScrollBehavior, viewModel: RepoViewModel diff --git a/ui/src/commonMain/kotlin/com/materiiapps/gloom/ui/screen/repo/tab/CodeTab.kt b/ui/src/commonMain/kotlin/com/materiiapps/gloom/ui/screen/repo/tab/CodeTab.kt index c8f9cd6..c35af37 100644 --- a/ui/src/commonMain/kotlin/com/materiiapps/gloom/ui/screen/repo/tab/CodeTab.kt +++ b/ui/src/commonMain/kotlin/com/materiiapps/gloom/ui/screen/repo/tab/CodeTab.kt @@ -1,6 +1,5 @@ package com.materiiapps.gloom.ui.screen.repo.tab -import androidx.compose.animation.ExperimentalAnimationApi import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row @@ -9,11 +8,11 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll -import androidx.compose.material.ExperimentalMaterialApi -import androidx.compose.material.pullrefresh.pullRefresh -import androidx.compose.material.pullrefresh.rememberPullRefreshState import androidx.compose.material3.ElevatedCard +import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Text +import androidx.compose.material3.pulltorefresh.PullToRefreshBox +import androidx.compose.material3.pulltorefresh.rememberPullToRefreshState import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clipToBounds @@ -24,7 +23,6 @@ import cafe.adriel.voyager.navigator.tab.Tab import cafe.adriel.voyager.navigator.tab.TabOptions import com.benasher44.uuid.uuid4 import com.materiiapps.gloom.Res -import com.materiiapps.gloom.ui.component.RefreshIndicator import com.materiiapps.gloom.ui.screen.explorer.DirectoryListingScreen import com.materiiapps.gloom.ui.transition.SlideTransition import com.materiiapps.gloom.ui.screen.repo.viewmodel.RepoCodeViewModel @@ -43,20 +41,16 @@ class CodeTab( @Composable override fun Content() = Screen() - @OptIn(ExperimentalMaterialApi::class, ExperimentalAnimationApi::class) @Composable + @OptIn(ExperimentalMaterial3Api::class) fun Screen( viewModel: RepoCodeViewModel = getScreenModel { parametersOf(owner to name) } ) { - val pullRefreshState = rememberPullRefreshState( - refreshing = viewModel.isLoading, - onRefresh = { viewModel.loadDefaultBranch() } - ) - - Box( + PullToRefreshBox( + isRefreshing = viewModel.isLoading, + onRefresh = { viewModel.loadDefaultBranch() }, modifier = Modifier .fillMaxSize() - .pullRefresh(pullRefreshState) .clipToBounds() ) { Column( @@ -96,7 +90,6 @@ class CodeTab( } } } - RefreshIndicator(state = pullRefreshState, isRefreshing = viewModel.isLoading) } } diff --git a/ui/src/commonMain/kotlin/com/materiiapps/gloom/ui/screen/repo/tab/DetailsTab.kt b/ui/src/commonMain/kotlin/com/materiiapps/gloom/ui/screen/repo/tab/DetailsTab.kt index b9829ab..dfa508f 100644 --- a/ui/src/commonMain/kotlin/com/materiiapps/gloom/ui/screen/repo/tab/DetailsTab.kt +++ b/ui/src/commonMain/kotlin/com/materiiapps/gloom/ui/screen/repo/tab/DetailsTab.kt @@ -11,16 +11,15 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll -import androidx.compose.material.ExperimentalMaterialApi import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Star import androidx.compose.material.icons.outlined.StarBorder -import androidx.compose.material.pullrefresh.pullRefresh -import androidx.compose.material.pullrefresh.rememberPullRefreshState +import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon import androidx.compose.material3.LocalContentColor import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text +import androidx.compose.material3.pulltorefresh.PullToRefreshBox import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.ui.Alignment @@ -40,7 +39,6 @@ import com.benasher44.uuid.uuid4 import com.materiiapps.gloom.Res import com.materiiapps.gloom.ui.component.LargeSegmentedButton import com.materiiapps.gloom.ui.component.LargeSegmentedButtonRow -import com.materiiapps.gloom.ui.component.RefreshIndicator import com.materiiapps.gloom.ui.component.ThinDivider import com.materiiapps.gloom.ui.icon.custom.Balance import com.materiiapps.gloom.ui.icon.Custom @@ -68,22 +66,19 @@ class DetailsTab( @Composable override fun Content() = Screen() - @OptIn(ExperimentalMaterialApi::class) @Composable + @OptIn(ExperimentalMaterial3Api::class) fun Screen( viewModel: RepoDetailsViewModel = getScreenModel { parametersOf(owner to name) } ) { val nav = LocalNavigator.currentOrThrow - val refreshState = rememberPullRefreshState( - refreshing = viewModel.detailsLoading, - onRefresh = { viewModel.loadDetails() } - ) val repoDetails = viewModel.details - Box( + PullToRefreshBox( + isRefreshing = viewModel.detailsLoading, + onRefresh = { viewModel.loadDetails() }, modifier = Modifier .fillMaxSize() - .pullRefresh(refreshState) .clipToBounds() ) { Column( @@ -109,13 +104,13 @@ class DetailsTab( ) } - details.parent?.let { parent -> + details.parent?.let { (nameWithOwner) -> Row( verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(10.dp), modifier = Modifier .clickable { - val (owner, name) = parent.nameWithOwner.split("/") + val (owner, name) = nameWithOwner.split("/") nav.navigate(RepoScreen(owner, name)) } .fillMaxWidth() @@ -137,7 +132,7 @@ class DetailsTab( Text( text = stringResource( Res.strings.forked_from, - parent.nameWithOwner + nameWithOwner ), style = MaterialTheme.typography.bodySmall ) @@ -219,7 +214,6 @@ class DetailsTab( } } } - RefreshIndicator(state = refreshState, isRefreshing = viewModel.detailsLoading) } } diff --git a/ui/src/commonMain/kotlin/com/materiiapps/gloom/ui/screen/repo/tab/IssuesTab.kt b/ui/src/commonMain/kotlin/com/materiiapps/gloom/ui/screen/repo/tab/IssuesTab.kt index b33e8b7..e0e2b25 100644 --- a/ui/src/commonMain/kotlin/com/materiiapps/gloom/ui/screen/repo/tab/IssuesTab.kt +++ b/ui/src/commonMain/kotlin/com/materiiapps/gloom/ui/screen/repo/tab/IssuesTab.kt @@ -4,9 +4,8 @@ import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.material.ExperimentalMaterialApi -import androidx.compose.material.pullrefresh.pullRefresh -import androidx.compose.material.pullrefresh.rememberPullRefreshState +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.pulltorefresh.PullToRefreshBox import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clipToBounds @@ -19,7 +18,6 @@ import cafe.adriel.voyager.navigator.tab.Tab import cafe.adriel.voyager.navigator.tab.TabOptions import com.benasher44.uuid.uuid4 import com.materiiapps.gloom.Res -import com.materiiapps.gloom.ui.component.RefreshIndicator import com.materiiapps.gloom.ui.component.ThinDivider import com.materiiapps.gloom.ui.screen.repo.viewmodel.RepoIssuesViewModel import com.materiiapps.gloom.ui.screen.repo.component.IssueItem @@ -39,20 +37,17 @@ class IssuesTab( override fun Content() = Screen() @Composable - @OptIn(ExperimentalMaterialApi::class) + @OptIn(ExperimentalMaterial3Api::class) fun Screen() { val viewModel: RepoIssuesViewModel = getScreenModel { parametersOf(owner to name) } val items = viewModel.items.collectAsLazyPagingItems() val isLoading = items.loadState.refresh == LoadState.Loading - val pullRefreshState = rememberPullRefreshState( - refreshing = isLoading, - onRefresh = { items.refresh() } - ) - Box( + PullToRefreshBox( + isRefreshing = isLoading, + onRefresh = { items.refresh() }, modifier = Modifier .fillMaxSize() - .pullRefresh(pullRefreshState) .clipToBounds() ) { LazyColumn { @@ -69,7 +64,6 @@ class IssuesTab( } } } - RefreshIndicator(state = pullRefreshState, isRefreshing = isLoading) } } diff --git a/ui/src/commonMain/kotlin/com/materiiapps/gloom/ui/screen/repo/tab/PullRequestTab.kt b/ui/src/commonMain/kotlin/com/materiiapps/gloom/ui/screen/repo/tab/PullRequestTab.kt index d9c4243..0474d52 100644 --- a/ui/src/commonMain/kotlin/com/materiiapps/gloom/ui/screen/repo/tab/PullRequestTab.kt +++ b/ui/src/commonMain/kotlin/com/materiiapps/gloom/ui/screen/repo/tab/PullRequestTab.kt @@ -4,9 +4,8 @@ import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.material.ExperimentalMaterialApi -import androidx.compose.material.pullrefresh.pullRefresh -import androidx.compose.material.pullrefresh.rememberPullRefreshState +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.pulltorefresh.PullToRefreshBox import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clipToBounds @@ -19,7 +18,6 @@ import cafe.adriel.voyager.navigator.tab.Tab import cafe.adriel.voyager.navigator.tab.TabOptions import com.benasher44.uuid.uuid4 import com.materiiapps.gloom.Res -import com.materiiapps.gloom.ui.component.RefreshIndicator import com.materiiapps.gloom.ui.component.ThinDivider import com.materiiapps.gloom.ui.screen.repo.viewmodel.RepoPullRequestsViewModel import com.materiiapps.gloom.ui.screen.repo.component.PullRequestItem @@ -39,20 +37,17 @@ class PullRequestTab( override fun Content() = Screen() @Composable - @OptIn(ExperimentalMaterialApi::class) + @OptIn(ExperimentalMaterial3Api::class) fun Screen() { val viewModel: RepoPullRequestsViewModel = getScreenModel { parametersOf(owner to name) } val items = viewModel.items.collectAsLazyPagingItems() val isLoading = items.loadState.refresh == LoadState.Loading - val pullRefreshState = rememberPullRefreshState( - refreshing = isLoading, - onRefresh = { items.refresh() } - ) - Box( + PullToRefreshBox( + isRefreshing = isLoading, + onRefresh = { items.refresh() }, modifier = Modifier .fillMaxSize() - .pullRefresh(pullRefreshState) .clipToBounds() ) { LazyColumn { @@ -69,7 +64,6 @@ class PullRequestTab( } } } - RefreshIndicator(state = pullRefreshState, isRefreshing = isLoading) } } diff --git a/ui/src/commonMain/kotlin/com/materiiapps/gloom/ui/screen/repo/tab/ReleasesTab.kt b/ui/src/commonMain/kotlin/com/materiiapps/gloom/ui/screen/repo/tab/ReleasesTab.kt index e79a5ba..9f56642 100644 --- a/ui/src/commonMain/kotlin/com/materiiapps/gloom/ui/screen/repo/tab/ReleasesTab.kt +++ b/ui/src/commonMain/kotlin/com/materiiapps/gloom/ui/screen/repo/tab/ReleasesTab.kt @@ -5,11 +5,10 @@ import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.material.ExperimentalMaterialApi -import androidx.compose.material.pullrefresh.pullRefresh -import androidx.compose.material.pullrefresh.rememberPullRefreshState +import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text +import androidx.compose.material3.pulltorefresh.PullToRefreshBox import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clipToBounds @@ -23,7 +22,6 @@ import cafe.adriel.voyager.navigator.tab.Tab import cafe.adriel.voyager.navigator.tab.TabOptions import com.benasher44.uuid.uuid4 import com.materiiapps.gloom.Res -import com.materiiapps.gloom.ui.component.RefreshIndicator import com.materiiapps.gloom.ui.component.ThinDivider import com.materiiapps.gloom.ui.screen.repo.viewmodel.RepoReleasesViewModel import com.materiiapps.gloom.ui.screen.repo.component.LatestReleaseItem @@ -43,21 +41,18 @@ class ReleasesTab( @Composable override fun Content() = Screen() - @OptIn(ExperimentalMaterialApi::class) @Composable + @OptIn(ExperimentalMaterial3Api::class) fun Screen() { val viewModel: RepoReleasesViewModel = getScreenModel { parametersOf(owner to name) } val items = viewModel.items.collectAsLazyPagingItems() val isLoading = items.loadState.refresh == LoadState.Loading - val pullRefreshState = rememberPullRefreshState( - refreshing = isLoading, - onRefresh = { items.refresh() } - ) - Box( + PullToRefreshBox( + isRefreshing = isLoading, + onRefresh = { items.refresh() }, modifier = Modifier .fillMaxSize() - .pullRefresh(pullRefreshState) .clipToBounds() ) { LazyColumn { @@ -102,7 +97,6 @@ class ReleasesTab( } } } - RefreshIndicator(state = pullRefreshState, isRefreshing = isLoading) } } diff --git a/ui/src/commonMain/kotlin/com/materiiapps/gloom/ui/screen/settings/AccountSettingsScreen.kt b/ui/src/commonMain/kotlin/com/materiiapps/gloom/ui/screen/settings/AccountSettingsScreen.kt index 3b3ff28..d0befee 100644 --- a/ui/src/commonMain/kotlin/com/materiiapps/gloom/ui/screen/settings/AccountSettingsScreen.kt +++ b/ui/src/commonMain/kotlin/com/materiiapps/gloom/ui/screen/settings/AccountSettingsScreen.kt @@ -7,12 +7,9 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items -import androidx.compose.material.ExperimentalMaterialApi import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Edit import androidx.compose.material.icons.outlined.Edit -import androidx.compose.material.pullrefresh.pullRefresh -import androidx.compose.material.pullrefresh.rememberPullRefreshState import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon import androidx.compose.material3.IconButtonDefaults @@ -21,6 +18,7 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold import androidx.compose.material3.TopAppBarDefaults import androidx.compose.material3.TopAppBarScrollBehavior +import androidx.compose.material3.pulltorefresh.PullToRefreshBox import androidx.compose.runtime.Composable import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue @@ -32,7 +30,6 @@ import cafe.adriel.voyager.koin.getScreenModel import cafe.adriel.voyager.navigator.LocalNavigator import cafe.adriel.voyager.navigator.currentOrThrow import com.materiiapps.gloom.Res -import com.materiiapps.gloom.ui.component.RefreshIndicator import com.materiiapps.gloom.ui.screen.settings.component.SettingsButton import com.materiiapps.gloom.ui.component.toolbar.LargeToolbar import com.materiiapps.gloom.ui.screen.auth.LandingScreen @@ -48,20 +45,12 @@ import dev.icerock.moko.resources.compose.stringResource class AccountSettingsScreen : Screen { @Composable - @OptIn( - ExperimentalMaterial3Api::class, ExperimentalMaterialApi::class, - ExperimentalFoundationApi::class - ) + @OptIn(ExperimentalMaterial3Api::class) override fun Content() { val viewModel: AccountSettingsViewModel = getScreenModel() val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior() val nav = LocalNavigator.currentOrThrow - val pullRefreshState = rememberPullRefreshState( - refreshing = viewModel.isLoading, - onRefresh = { viewModel.loadAccounts() } - ) - val accounts by remember(viewModel.authManager.accounts) { derivedStateOf { viewModel.authManager.accounts.values @@ -99,11 +88,12 @@ class AccountSettingsScreen : Screen { }, modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection) ) { pv -> - Box( + PullToRefreshBox( + isRefreshing = viewModel.isLoading, + onRefresh = { viewModel.loadAccounts() }, modifier = Modifier .padding(pv) .fillMaxSize() - .pullRefresh(state = pullRefreshState) ) { LazyColumn( modifier = Modifier @@ -135,8 +125,7 @@ class AccountSettingsScreen : Screen { onClick = { viewModel.openSignOutDialog(account.id) } ) }, - modifier = Modifier - .animateItemPlacement(tween(200)) + modifier = Modifier.animateItem(tween(200)) ) } item( @@ -155,7 +144,6 @@ class AccountSettingsScreen : Screen { ) } } - RefreshIndicator(state = pullRefreshState, isRefreshing = viewModel.isLoading) } } } diff --git a/ui/src/commonMain/kotlin/com/materiiapps/gloom/ui/screen/settings/component/AvatarShapeSetting.kt b/ui/src/commonMain/kotlin/com/materiiapps/gloom/ui/screen/settings/component/AvatarShapeSetting.kt index d05248d..0f52dd6 100644 --- a/ui/src/commonMain/kotlin/com/materiiapps/gloom/ui/screen/settings/component/AvatarShapeSetting.kt +++ b/ui/src/commonMain/kotlin/com/materiiapps/gloom/ui/screen/settings/component/AvatarShapeSetting.kt @@ -4,6 +4,7 @@ import androidx.compose.animation.AnimatedVisibility import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.background import androidx.compose.foundation.border +import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -17,9 +18,13 @@ import androidx.compose.foundation.selection.selectable import androidx.compose.foundation.selection.selectableGroup import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.CheckCircle +import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon +import androidx.compose.material3.Label import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.PlainTooltip import androidx.compose.material3.Slider +import androidx.compose.material3.SliderDefaults import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.remember @@ -27,6 +32,8 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.semantics.Role +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.DpSize import androidx.compose.ui.unit.dp import com.materiiapps.gloom.Res import com.materiiapps.gloom.domain.manager.AvatarShape @@ -45,6 +52,7 @@ import kotlin.math.roundToInt * @param onCornerRadiusUpdate Callback for when the user changes the radius * @param modifier The [Modifier] for this component */ +@OptIn(ExperimentalMaterial3Api::class) @Composable fun AvatarShapeSetting( currentShape: AvatarShape, @@ -100,27 +108,52 @@ fun AvatarShapeSetting( } AnimatedVisibility(currentShape == AvatarShape.RoundedCorner) { - Row( - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(16.dp), + Column( + verticalArrangement = Arrangement.spacedBy(0.dp), modifier = Modifier.padding(top = 16.dp) ) { - Text( - text = stringResource(Res.strings.appearance_av_radius), - style = MaterialTheme.typography.labelMedium - ) + val sliderInteractionSource = remember { MutableInteractionSource() } + + Row( + verticalAlignment = Alignment.CenterVertically + ) { + Text( + text = stringResource(Res.strings.appearance_av_radius), + style = MaterialTheme.typography.labelMedium, + fontWeight = FontWeight.Bold, + color = MaterialTheme.colorScheme.primary, + modifier = Modifier.weight(1f) + ) + + Text( + text = DecimalFormat("#%").format(cornerRadius/100f), + color = MaterialTheme.colorScheme.primary, + style = MaterialTheme.typography.labelMedium + ) + } Slider( value = cornerRadius.toFloat(), onValueChange = { onCornerRadiusUpdate(it.roundToInt()) }, valueRange = 0f..50f, - modifier = Modifier - .weight(1f) - ) - - Text( - text = DecimalFormat("#%").format(cornerRadius/100f), - style = MaterialTheme.typography.labelSmall + interactionSource = sliderInteractionSource, + thumb = { + Label( + label = { + PlainTooltip { + Text( + text = DecimalFormat("#%").format(cornerRadius/100f) + ) + } + }, + interactionSource = sliderInteractionSource + ) { + SliderDefaults.Thumb( + interactionSource = sliderInteractionSource, + thumbSize = DpSize(width = 4.dp, height = 32.dp) + ) + } + } ) } } diff --git a/ui/src/commonMain/kotlin/com/materiiapps/gloom/ui/screen/settings/component/account/AccountSwitcherSheet.kt b/ui/src/commonMain/kotlin/com/materiiapps/gloom/ui/screen/settings/component/account/AccountSwitcherSheet.kt index 329e327..f4c18c6 100644 --- a/ui/src/commonMain/kotlin/com/materiiapps/gloom/ui/screen/settings/component/account/AccountSwitcherSheet.kt +++ b/ui/src/commonMain/kotlin/com/materiiapps/gloom/ui/screen/settings/component/account/AccountSwitcherSheet.kt @@ -29,7 +29,7 @@ import dev.icerock.moko.resources.compose.stringResource import org.koin.compose.koinInject @Composable -@OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class) +@OptIn(ExperimentalMaterial3Api::class) fun AccountSwitcherSheet( onDismiss: () -> Unit, ) { @@ -72,7 +72,7 @@ fun AccountSwitcherSheet( nav.replaceAll(RootScreen()) } }, - modifier = Modifier.animateItemPlacement(tween(200)) + modifier = Modifier.animateItem(tween(200)) ) } item( diff --git a/ui/src/commonMain/kotlin/com/materiiapps/gloom/ui/theme/GloomColorScheme.kt b/ui/src/commonMain/kotlin/com/materiiapps/gloom/ui/theme/GloomColorScheme.kt index 03caee6..d72a1a7 100644 --- a/ui/src/commonMain/kotlin/com/materiiapps/gloom/ui/theme/GloomColorScheme.kt +++ b/ui/src/commonMain/kotlin/com/materiiapps/gloom/ui/theme/GloomColorScheme.kt @@ -43,6 +43,13 @@ class GloomColorScheme( outline: Color, outlineVariant: Color, scrim: Color, + surfaceBright: Color, + surfaceDim: Color, + surfaceContainer: Color, + surfaceContainerHigh: Color, + surfaceContainerHighest: Color, + surfaceContainerLow: Color, + surfaceContainerLowest: Color, //Custom colors statusGreen: Color, @@ -97,6 +104,13 @@ class GloomColorScheme( colorScheme.outline, colorScheme.outlineVariant, colorScheme.scrim, + colorScheme.surfaceBright, + colorScheme.surfaceDim, + colorScheme.surfaceContainer, + colorScheme.surfaceContainerHigh, + colorScheme.surfaceContainerHighest, + colorScheme.surfaceContainerLow, + colorScheme.surfaceContainerLowest, statusGreen, statusPurple, statusRed, @@ -166,6 +180,20 @@ class GloomColorScheme( internal set var scrim by mutableStateOf(scrim, structuralEqualityPolicy()) internal set + var surfaceBright by mutableStateOf(surfaceBright, structuralEqualityPolicy()) + internal set + var surfaceDim by mutableStateOf(surfaceDim, structuralEqualityPolicy()) + internal set + var surfaceContainer by mutableStateOf(surfaceContainer, structuralEqualityPolicy()) + internal set + var surfaceContainerHigh by mutableStateOf(surfaceContainerHigh, structuralEqualityPolicy()) + internal set + var surfaceContainerHighest by mutableStateOf(surfaceContainerHighest, structuralEqualityPolicy()) + internal set + var surfaceContainerLow by mutableStateOf(surfaceContainerLow, structuralEqualityPolicy()) + internal set + var surfaceContainerLowest by mutableStateOf(surfaceContainerLowest, structuralEqualityPolicy()) + internal set var statusGreen by mutableStateOf(statusGreen, structuralEqualityPolicy()) internal set @@ -224,7 +252,14 @@ class GloomColorScheme( onErrorContainer, outline, outlineVariant, - scrim + scrim, + surfaceBright, + surfaceDim, + surfaceContainer, + surfaceContainerHigh, + surfaceContainerHighest, + surfaceContainerLow, + surfaceContainerLowest ) } } diff --git a/ui/src/commonMain/kotlin/com/materiiapps/gloom/ui/widget/code/CodeViewer.kt b/ui/src/commonMain/kotlin/com/materiiapps/gloom/ui/widget/code/CodeViewer.kt index d420ea3..788d603 100644 --- a/ui/src/commonMain/kotlin/com/materiiapps/gloom/ui/widget/code/CodeViewer.kt +++ b/ui/src/commonMain/kotlin/com/materiiapps/gloom/ui/widget/code/CodeViewer.kt @@ -22,7 +22,7 @@ import androidx.compose.foundation.lazy.LazyListState import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.foundation.rememberScrollState -import androidx.compose.material.Text +import androidx.compose.material3.Text import androidx.compose.material.ripple.rememberRipple import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue