diff --git a/README.md b/README.md
index 95576688e..caf124b56 100644
--- a/README.md
+++ b/README.md
@@ -52,9 +52,6 @@ A library which provides a way to use Android Drawables as Jetpack Compose Paint
### 📜 [Adaptive](./adaptive/)
A library providing a collection of utilities for adaptive layouts.
-### ⬇️ [Swipe to Refresh](./swiperefresh/) (Deprecated)
-See our [Migration Guide](https://google.github.io/accompanist/swiperefresh/) for migrating to PullRefresh in Compose Material.
-
### 🎨 [AppCompat Theme Adapter](./appcompat-theme/) (Deprecated)
See our [Migration Guide](https://google.github.io/accompanist/appcompat-theme/) for migrating to the new artifact in Accompanist.
@@ -85,9 +82,6 @@ A wrapper around WebView for basic WebView support in Jetpack Compose.
### 🗜 [Test Harness](./testharness/) (Deprecated)
Utilities for testing Compose layouts.
-### 📐 [Insets](./insets/) (Deprecated & Removed)
-See our [Migration Guide](https://google.github.io/accompanist/insets/) for migrating to Insets in Compose.
-
---
## Future?
diff --git a/docs/swiperefresh.md b/docs/swiperefresh.md
deleted file mode 100644
index 33a481003..000000000
--- a/docs/swiperefresh.md
+++ /dev/null
@@ -1,181 +0,0 @@
-# Swipe Refresh for Jetpack Compose
-
-[![Maven Central](https://img.shields.io/maven-central/v/com.google.accompanist/accompanist-swiperefresh)](https://search.maven.org/search?q=g:com.google.accompanist)
-
-!!! warning
- **This library is deprecated, with official pull refresh support in [androidx.compose.material.pullrefresh](https://developer.android.com/reference/kotlin/androidx/compose/material/pullrefresh/package-summary).** The migration guide and original documentation is below.
-
-## Migration
-
-Accompanist SwipeRefresh has been replaced by PullRefresh in [Compose Material 1.3.0](https://developer.android.com/jetpack/androidx/releases/compose-material#1.3.0). The implementation is similar but instead of being a Composable function, it is a Modifier that can be applied to a Composable function.
-
-A simple example is as follows:
-
-```kotlin
-val viewModel: MyViewModel = viewModel()
-val refreshing by viewModel.isRefreshing
-
-val pullRefreshState = rememberPullRefreshState(refreshing, { viewModel.refresh() })
-
-Box(Modifier.pullRefresh(pullRefreshState)) {
- LazyColumn(Modifier.fillMaxSize()) {
- ...
- }
-
- PullRefreshIndicator(refreshing, pullRefreshState, Modifier.align(Alignment.TopCenter))
-}
-```
-
-### Migration steps
-
-1. Replace SwipeRefresh with a Box or other layout of your choice, save your `onRefresh` lambda for the next step.
-2. Replace `rememberSwipeRefreshState()` with `rememberPullRefreshState(refreshing, onRefresh)`
-3. Add either the default `PullRefreshIndicator` or your own custom implementation to your layout.
-
-### Custom Indicator
-
-Instead of using the provided `PullRefreshIndicator` composable, you can create your own custom indicator.
-A full sample can be seen in the [Compose samples](https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:compose/material/material/samples/src/main/java/androidx/compose/material/samples/PullRefreshSamples.kt;l=91?q=pullrefresh).
-
-## Original Docs
-
-A library which provides a layout which provides the swipe-to-refresh UX pattern, similar to Android's [`SwipeRefreshLayout`](https://developer.android.com/training/swipe/add-swipe-interface).
-
-
-
-## Usage
-
-To implement this UX pattern there are two key APIs which are needed: [`SwipeRefresh`][api_swiperefresh], which is provides the layout, and [`rememberSwipeRefreshState()`][api_rememberstate] which provides some remembered state.
-
-The basic usage of a [`SwipeRefresh`][api_swiperefresh] using a ViewModel looks like so:
-
-``` kotlin
-val viewModel: MyViewModel = viewModel()
-val isRefreshing by viewModel.isRefreshing.collectAsState()
-
-SwipeRefresh(
- state = rememberSwipeRefreshState(isRefreshing),
- onRefresh = { viewModel.refresh() },
-) {
- LazyColumn {
- items(30) { index ->
- // TODO: list items
- }
- }
-}
-```
-
-The full example, including the view model implementation can be found [here](https://github.com/google/accompanist/blob/main/sample/src/main/java/com/google/accompanist/sample/swiperefresh/DocsSamples.kt).
-
-The content needs to be 'vertically scrollable' for `SwipeRefresh()` to be able to react to swipe gestures. Layouts such as [`LazyColumn`][lazycolumn] are automatically vertically scrollable, but others such as [`Column`][column] or [`LazyRow`][lazyrow] are not. In those instances, you can provide a [`Modifier.verticalScroll`][verticalscroll] modifier to that content like so:
-
-``` kotlin
-SwipeRefresh(
- // ...
-) {
- Column(Modifier.verticalScroll(rememberScrollState())) {
- // content
- }
-}
-```
-
-
-### Indicating a refresh without swiping
-
-As this library is built with a separate state object, it's easy to display a refreshing indicator without a swipe to triggering it.
-
-The unrealistic example below displays a forever refreshing indicator:
-
-``` kotlin
-val swipeRefreshState = rememberSwipeRefreshState(true)
-
-SwipeRefresh(
- state = swipeRefreshState,
- onRefresh = { /* todo */ },
-) {
- LazyColumn {
- items(30) { index ->
- // TODO: list items
- }
- }
-}
-```
-
-## Indicator
-
-The library provides a default indicator: [`SwipeRefreshIndicator()`][api_swiperefreshindicator], which `SwipeRefresh` uses automatically. You can customize the default indicator, and even provide your own indicator content using the `indicator` slot.
-
-### Customizing default indicator
-
-To customize the default indicator, we can provide our own `indicator` content block, to call [`SwipeRefreshIndicator()`][api_swiperefreshindicator] with customized parameters:
-
-=== "Sample"
-
- ``` kotlin
- SwipeRefresh(
- state = /* ... */,
- onRefresh = /* ... */,
- indicator = { state, trigger ->
- SwipeRefreshIndicator(
- // Pass the SwipeRefreshState + trigger through
- state = state,
- refreshTriggerDistance = trigger,
- // Enable the scale animation
- scale = true,
- // Change the color and shape
- backgroundColor = MaterialTheme.colors.primary,
- shape = MaterialTheme.shapes.small,
- )
- }
- )
- ```
-
-=== "Demo video"
-
-
-
-### Custom indicator
-
-As mentioned, you can also provide your own custom indicator content. A [`SwipeRefreshState`][api_swiperefreshstate] is provided to `indicator` content slot, which contains the information necessary to react to a swipe refresh gesture.
-
-An example of a custom indicator is provided [here][sample_customindicator].
-
-## Download
-
-[![Maven Central](https://img.shields.io/maven-central/v/com.google.accompanist/accompanist-swiperefresh)](https://search.maven.org/search?q=g:com.google.accompanist)
-
-```groovy
-repositories {
- mavenCentral()
-}
-
-dependencies {
- implementation "com.google.accompanist:accompanist-swiperefresh:"
-}
-```
-
-Snapshots of the development version are available in [Sonatype's `snapshots` repository][snap]. These are updated on every commit.
-
- [compose]: https://developer.android.com/jetpack/compose
- [snap]: https://oss.sonatype.org/content/repositories/snapshots/com/google/accompanist/accompanist-swiperefresh/
- [api_swiperefreshstate]: ../api/swiperefresh/com.google.accompanist.swiperefresh/-swipe-refresh-state/
- [api_swiperefreshindicator]: ../api/swiperefresh/com.google.accompanist.swiperefresh/-swipe-refresh-indicator.html
- [api_swiperefresh]: ../api/swiperefresh/com.google.accompanist.swiperefresh/-swipe-refresh.html
- [api_rememberstate]: ../api/swiperefresh/com.google.accompanist.swiperefresh/remember-swipe-refresh-state.html
- [sample_customindicator]: https://github.com/google/accompanist/blob/main/sample/src/main/java/com/google/accompanist/sample/swiperefresh/SwipeRefreshCustomIndicatorSample.kt
- [lazycolumn]: https://developer.android.com/reference/kotlin/androidx/compose/foundation/lazy/package-summary#LazyColumn(androidx.compose.ui.Modifier,androidx.compose.foundation.lazy.LazyListState,androidx.compose.foundation.layout.PaddingValues,kotlin.Boolean,androidx.compose.foundation.layout.Arrangement.Vertical,androidx.compose.ui.Alignment.Horizontal,androidx.compose.foundation.gestures.FlingBehavior,kotlin.Function1)
- [column]: https://developer.android.com/reference/kotlin/androidx/compose/foundation/layout/package-summary#Column(androidx.compose.ui.Modifier,androidx.compose.foundation.layout.Arrangement.Vertical,androidx.compose.ui.Alignment.Horizontal,kotlin.Function1)
- [lazyrow]: https://developer.android.com/reference/kotlin/androidx/compose/foundation/lazy/package-summary#LazyRow(androidx.compose.ui.Modifier,androidx.compose.foundation.lazy.LazyListState,androidx.compose.foundation.layout.PaddingValues,kotlin.Boolean,androidx.compose.foundation.layout.Arrangement.Horizontal,androidx.compose.ui.Alignment.Vertical,androidx.compose.foundation.gestures.FlingBehavior,kotlin.Function1)
- [verticalscroll]: https://developer.android.com/jetpack/compose/gestures#scroll-modifiers
diff --git a/mkdocs.yml b/mkdocs.yml
index 753aaddbb..a1a0620cd 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -36,9 +36,6 @@ nav:
- 'Core Theme Adapter':
- 'Guide': themeadapter-core.md
- 'API': api/themeadapter-core/
- - 'Swipe Refresh':
- - 'Guide': swiperefresh.md
- - 'API': api/swiperefresh/
- 'Placeholder':
- 'Guide': placeholder.md
- 'Foundation API': api/placeholder/
diff --git a/sample/build.gradle.kts b/sample/build.gradle.kts
index ba29efa89..c8a059093 100644
--- a/sample/build.gradle.kts
+++ b/sample/build.gradle.kts
@@ -66,7 +66,6 @@ dependencies {
implementation(project(":placeholder"))
implementation(project(":placeholder-material"))
implementation(project(":systemuicontroller"))
- implementation(project(":swiperefresh"))
implementation(project(":testharness")) // Don't use in production! Use the configurations below
testImplementation(project(":testharness"))
androidTestImplementation(project(":testharness"))
diff --git a/sample/src/main/AndroidManifest.xml b/sample/src/main/AndroidManifest.xml
index f7ae7a248..c861696b0 100644
--- a/sample/src/main/AndroidManifest.xml
+++ b/sample/src/main/AndroidManifest.xml
@@ -100,46 +100,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- get() = _isRefreshing.asStateFlow()
-
- fun refresh() {
- // This doesn't handle multiple 'refreshing' tasks, don't use this
- viewModelScope.launch {
- // A fake 2 second 'refresh'
- _isRefreshing.emit(true)
- delay(2000)
- _isRefreshing.emit(false)
- }
- }
-}
-
-@Composable
-fun SwipeRefreshSample() {
- val viewModel: MyViewModel = viewModel()
- val isRefreshing by viewModel.isRefreshing.collectAsState()
-
- SwipeRefresh(
- state = rememberSwipeRefreshState(isRefreshing),
- onRefresh = { viewModel.refresh() },
- ) {
- LazyColumn {
- items(30) { index ->
- // TODO: list items
- }
- }
- }
-}
diff --git a/sample/src/main/java/com/google/accompanist/sample/swiperefresh/SwipeRefreshBasicSample.kt b/sample/src/main/java/com/google/accompanist/sample/swiperefresh/SwipeRefreshBasicSample.kt
deleted file mode 100644
index d3b6c1557..000000000
--- a/sample/src/main/java/com/google/accompanist/sample/swiperefresh/SwipeRefreshBasicSample.kt
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.accompanist.sample.swiperefresh
-
-import android.os.Bundle
-import androidx.activity.ComponentActivity
-import androidx.activity.compose.setContent
-import androidx.compose.foundation.Image
-import androidx.compose.foundation.layout.Row
-import androidx.compose.foundation.layout.Spacer
-import androidx.compose.foundation.layout.fillMaxSize
-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.material.MaterialTheme
-import androidx.compose.material.Scaffold
-import androidx.compose.material.Text
-import androidx.compose.material.TopAppBar
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.LaunchedEffect
-import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.remember
-import androidx.compose.runtime.setValue
-import androidx.compose.ui.Alignment
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.res.stringResource
-import androidx.compose.ui.unit.dp
-import coil.annotation.ExperimentalCoilApi
-import coil.compose.rememberImagePainter
-import com.google.accompanist.sample.AccompanistSampleTheme
-import com.google.accompanist.sample.R
-import com.google.accompanist.sample.randomSampleImageUrl
-import com.google.accompanist.swiperefresh.SwipeRefresh
-import com.google.accompanist.swiperefresh.rememberSwipeRefreshState
-import kotlinx.coroutines.delay
-
-class SwipeRefreshBasicSample : ComponentActivity() {
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
-
- setContent {
- AccompanistSampleTheme {
- Sample()
- }
- }
- }
-}
-
-@Suppress("DEPRECATION")
-@OptIn(ExperimentalCoilApi::class)
-@Composable
-private fun Sample() {
- Scaffold(
- topBar = {
- TopAppBar(
- title = { Text(stringResource(R.string.swiperefresh_title_basics)) },
- backgroundColor = MaterialTheme.colors.surface,
- )
- },
- modifier = Modifier.fillMaxSize()
- ) { padding ->
- // Simulate a fake 2-second 'load'. Ideally this 'refreshing' value would
- // come from a ViewModel or similar
- var refreshing by remember { mutableStateOf(false) }
- LaunchedEffect(refreshing) {
- if (refreshing) {
- delay(2000)
- refreshing = false
- }
- }
-
- val state = rememberSwipeRefreshState(isRefreshing = true)
- SwipeRefresh(
- state = state,
- onRefresh = { refreshing = true },
- ) {
- LazyColumn(contentPadding = padding) {
- items(30) { index ->
- Row(Modifier.padding(16.dp)) {
- Image(
- painter = rememberImagePainter(randomSampleImageUrl(index)),
- contentDescription = null,
- modifier = Modifier.size(64.dp),
- )
-
- Spacer(Modifier.width(8.dp))
-
- Text(
- text = "Text",
- style = MaterialTheme.typography.subtitle2,
- modifier = Modifier
- .weight(1f)
- .align(Alignment.CenterVertically)
- )
- }
- }
- }
- }
- }
-}
diff --git a/sample/src/main/java/com/google/accompanist/sample/swiperefresh/SwipeRefreshContentPaddingSample.kt b/sample/src/main/java/com/google/accompanist/sample/swiperefresh/SwipeRefreshContentPaddingSample.kt
deleted file mode 100644
index 46cef1715..000000000
--- a/sample/src/main/java/com/google/accompanist/sample/swiperefresh/SwipeRefreshContentPaddingSample.kt
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.accompanist.sample.swiperefresh
-
-import android.os.Bundle
-import androidx.activity.ComponentActivity
-import androidx.activity.compose.setContent
-import androidx.compose.foundation.Image
-import androidx.compose.foundation.layout.Row
-import androidx.compose.foundation.layout.Spacer
-import androidx.compose.foundation.layout.WindowInsets
-import androidx.compose.foundation.layout.WindowInsetsSides
-import androidx.compose.foundation.layout.asPaddingValues
-import androidx.compose.foundation.layout.fillMaxWidth
-import androidx.compose.foundation.layout.only
-import androidx.compose.foundation.layout.padding
-import androidx.compose.foundation.layout.size
-import androidx.compose.foundation.layout.systemBars
-import androidx.compose.foundation.layout.width
-import androidx.compose.foundation.layout.windowInsetsPadding
-import androidx.compose.foundation.lazy.LazyColumn
-import androidx.compose.foundation.lazy.items
-import androidx.compose.foundation.shape.RoundedCornerShape
-import androidx.compose.material.MaterialTheme
-import androidx.compose.material.Text
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.LaunchedEffect
-import androidx.compose.runtime.SideEffect
-import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.remember
-import androidx.compose.runtime.setValue
-import androidx.compose.ui.Alignment
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.draw.clip
-import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.res.stringResource
-import androidx.compose.ui.unit.dp
-import androidx.core.view.WindowCompat
-import coil.annotation.ExperimentalCoilApi
-import coil.compose.rememberImagePainter
-import com.google.accompanist.insets.ui.Scaffold
-import com.google.accompanist.insets.ui.TopAppBarContent
-import com.google.accompanist.insets.ui.TopAppBarSurface
-import com.google.accompanist.sample.AccompanistSampleTheme
-import com.google.accompanist.sample.R
-import com.google.accompanist.sample.randomSampleImageUrl
-import com.google.accompanist.swiperefresh.SwipeRefresh
-import com.google.accompanist.swiperefresh.SwipeRefreshIndicator
-import com.google.accompanist.swiperefresh.rememberSwipeRefreshState
-import com.google.accompanist.systemuicontroller.rememberSystemUiController
-import kotlinx.coroutines.delay
-
-class SwipeRefreshContentPaddingSample : ComponentActivity() {
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
-
- // Turn off the decor fitting system windows, which means we need to through handling
- // insets
- WindowCompat.setDecorFitsSystemWindows(window, false)
-
- setContent {
- AccompanistSampleTheme {
- Sample()
- }
- }
- }
-}
-
-private val listItems = List(40) { randomSampleImageUrl(it) }
-
-@Suppress("DEPRECATION")
-@Composable
-private fun Sample() {
- val systemUiController = rememberSystemUiController()
- val useDarkIcons = MaterialTheme.colors.isLight
- SideEffect {
- systemUiController.setSystemBarsColor(Color.Transparent, darkIcons = useDarkIcons)
- }
-
- // Simulate a fake 2-second 'load'. Ideally this 'refreshing' value would
- // come from a ViewModel or similar
- var refreshing by remember { mutableStateOf(false) }
- LaunchedEffect(refreshing) {
- if (refreshing) {
- delay(2000)
- refreshing = false
- }
- }
-
- Scaffold(
- topBar = {
- TopAppBarSurface(
- backgroundColor = MaterialTheme.colors.surface.copy(alpha = 0.9f),
- modifier = Modifier.fillMaxWidth()
- ) {
- TopAppBarContent(
- title = {
- Text(stringResource(R.string.swiperefresh_title_content_padding))
- },
- modifier = Modifier.windowInsetsPadding(
- WindowInsets.systemBars.only(
- WindowInsetsSides.Horizontal + WindowInsetsSides.Top
- )
- )
- )
- }
- },
- contentPadding = WindowInsets.systemBars
- .only(WindowInsetsSides.Horizontal + WindowInsetsSides.Bottom)
- .asPaddingValues()
- ) { contentPadding ->
- SwipeRefresh(
- state = rememberSwipeRefreshState(refreshing),
- onRefresh = { refreshing = true },
- // Shift the indicator to match the list content padding
- indicatorPadding = contentPadding,
- // We want the indicator to draw within the padding
- clipIndicatorToPadding = false,
- // Tweak the indicator to scale up/down
- indicator = { state, refreshTriggerDistance ->
- SwipeRefreshIndicator(
- state = state,
- refreshTriggerDistance = refreshTriggerDistance,
- scale = true
- )
- }
- ) {
- LazyColumn(contentPadding = contentPadding) {
- items(items = listItems) { imageUrl ->
- ListItem(imageUrl, Modifier.fillMaxWidth())
- }
- }
- }
- }
-}
-
-@OptIn(ExperimentalCoilApi::class)
-@Composable
-fun ListItem(
- imageUrl: String,
- modifier: Modifier = Modifier
-) {
- Row(modifier.padding(horizontal = 16.dp, vertical = 8.dp)) {
- Image(
- painter = rememberImagePainter(imageUrl),
- contentDescription = null,
- modifier = Modifier
- .size(64.dp)
- .clip(RoundedCornerShape(4.dp)),
- )
-
- Spacer(Modifier.width(16.dp))
-
- Text(
- text = "Text",
- style = MaterialTheme.typography.subtitle2,
- modifier = Modifier.weight(1f)
- .align(Alignment.CenterVertically)
- )
- }
-}
diff --git a/sample/src/main/java/com/google/accompanist/sample/swiperefresh/SwipeRefreshCustomIndicatorSample.kt b/sample/src/main/java/com/google/accompanist/sample/swiperefresh/SwipeRefreshCustomIndicatorSample.kt
deleted file mode 100644
index e1022854d..000000000
--- a/sample/src/main/java/com/google/accompanist/sample/swiperefresh/SwipeRefreshCustomIndicatorSample.kt
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-@file:Suppress("DEPRECATION")
-
-package com.google.accompanist.sample.swiperefresh
-
-import android.os.Bundle
-import androidx.activity.ComponentActivity
-import androidx.activity.compose.setContent
-import androidx.compose.animation.core.FastOutSlowInEasing
-import androidx.compose.foundation.Image
-import androidx.compose.foundation.layout.Box
-import androidx.compose.foundation.layout.Row
-import androidx.compose.foundation.layout.Spacer
-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.foundation.layout.size
-import androidx.compose.foundation.layout.width
-import androidx.compose.foundation.lazy.LazyColumn
-import androidx.compose.material.LinearProgressIndicator
-import androidx.compose.material.MaterialTheme
-import androidx.compose.material.Scaffold
-import androidx.compose.material.Text
-import androidx.compose.material.TopAppBar
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.LaunchedEffect
-import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.remember
-import androidx.compose.runtime.setValue
-import androidx.compose.ui.Alignment
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.draw.drawWithCache
-import androidx.compose.ui.graphics.Brush
-import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.platform.LocalDensity
-import androidx.compose.ui.res.painterResource
-import androidx.compose.ui.res.stringResource
-import androidx.compose.ui.unit.Dp
-import androidx.compose.ui.unit.dp
-import com.google.accompanist.sample.AccompanistSampleTheme
-import com.google.accompanist.sample.R
-import com.google.accompanist.swiperefresh.SwipeRefresh
-import com.google.accompanist.swiperefresh.SwipeRefreshState
-import com.google.accompanist.swiperefresh.rememberSwipeRefreshState
-import kotlinx.coroutines.delay
-
-class SwipeRefreshCustomIndicatorSample : ComponentActivity() {
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
-
- setContent {
- AccompanistSampleTheme {
- Sample()
- }
- }
- }
-}
-
-@Suppress("DEPRECATION")
-@Composable
-private fun Sample() {
- Scaffold(
- topBar = {
- TopAppBar(
- title = { Text(stringResource(R.string.swiperefresh_title_custom)) },
- backgroundColor = MaterialTheme.colors.surface,
- )
- },
- modifier = Modifier.fillMaxSize()
- ) { padding ->
- // Simulate a fake 2-second 'load'. Ideally this 'refreshing' value would
- // come from a ViewModel or similar
- var refreshing by remember { mutableStateOf(false) }
- LaunchedEffect(refreshing) {
- if (refreshing) {
- delay(2000)
- refreshing = false
- }
- }
-
- SwipeRefresh(
- state = rememberSwipeRefreshState(isRefreshing = refreshing),
- onRefresh = { refreshing = true },
- indicator = { state, trigger ->
- GlowIndicator(
- swipeRefreshState = state,
- refreshTriggerDistance = trigger
- )
- },
- ) {
- LazyColumn(contentPadding = padding) {
- items(30) {
- Row(Modifier.padding(16.dp)) {
- Image(
- painter = painterResource(R.drawable.placeholder),
- contentDescription = null,
- modifier = Modifier.size(64.dp),
- )
-
- Spacer(Modifier.width(8.dp))
-
- Text(
- text = "Text",
- style = MaterialTheme.typography.subtitle2,
- modifier = Modifier
- .weight(1f)
- .align(Alignment.CenterVertically)
- )
- }
- }
- }
- }
- }
-}
-
-/**
- * A custom indicator which displays a glow and progress indicator
- */
-@Composable
-fun GlowIndicator(
- swipeRefreshState: SwipeRefreshState,
- refreshTriggerDistance: Dp,
- color: Color = MaterialTheme.colors.primary,
-) {
- Box(
- Modifier
- .drawWithCache {
- onDrawBehind {
- val distance = refreshTriggerDistance.toPx()
- val progress = (swipeRefreshState.indicatorOffset / distance).coerceIn(0f, 1f)
- // We draw a translucent glow
- val brush = Brush.verticalGradient(
- 0f to color.copy(alpha = 0.45f),
- 1f to color.copy(alpha = 0f)
- )
- // And fade the glow in/out based on the swipe progress
- drawRect(brush = brush, alpha = FastOutSlowInEasing.transform(progress))
- }
- }
- .fillMaxWidth()
- .height(72.dp)
- ) {
- if (swipeRefreshState.isRefreshing) {
- // If we're refreshing, show an indeterminate progress indicator
- LinearProgressIndicator(Modifier.fillMaxWidth())
- } else {
- // Otherwise we display a determinate progress indicator with the current swipe progress
- val trigger = with(LocalDensity.current) { refreshTriggerDistance.toPx() }
- val progress = (swipeRefreshState.indicatorOffset / trigger).coerceIn(0f, 1f)
- LinearProgressIndicator(
- progress = progress,
- modifier = Modifier.fillMaxWidth(),
- )
- }
- }
-}
diff --git a/sample/src/main/java/com/google/accompanist/sample/swiperefresh/SwipeRefreshTweakedIndicatorSample.kt b/sample/src/main/java/com/google/accompanist/sample/swiperefresh/SwipeRefreshTweakedIndicatorSample.kt
deleted file mode 100644
index 4228cf9b7..000000000
--- a/sample/src/main/java/com/google/accompanist/sample/swiperefresh/SwipeRefreshTweakedIndicatorSample.kt
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.accompanist.sample.swiperefresh
-
-import android.os.Bundle
-import androidx.activity.ComponentActivity
-import androidx.activity.compose.setContent
-import androidx.compose.foundation.Image
-import androidx.compose.foundation.layout.Row
-import androidx.compose.foundation.layout.Spacer
-import androidx.compose.foundation.layout.fillMaxSize
-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.material.MaterialTheme
-import androidx.compose.material.Scaffold
-import androidx.compose.material.Text
-import androidx.compose.material.TopAppBar
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.LaunchedEffect
-import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.remember
-import androidx.compose.runtime.setValue
-import androidx.compose.ui.Alignment
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.res.stringResource
-import androidx.compose.ui.unit.dp
-import coil.annotation.ExperimentalCoilApi
-import coil.compose.rememberImagePainter
-import com.google.accompanist.sample.AccompanistSampleTheme
-import com.google.accompanist.sample.R
-import com.google.accompanist.sample.randomSampleImageUrl
-import com.google.accompanist.swiperefresh.SwipeRefresh
-import com.google.accompanist.swiperefresh.SwipeRefreshIndicator
-import com.google.accompanist.swiperefresh.rememberSwipeRefreshState
-import kotlinx.coroutines.delay
-
-class SwipeRefreshTweakedIndicatorSample : ComponentActivity() {
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
-
- setContent {
- AccompanistSampleTheme {
- Sample()
- }
- }
- }
-}
-
-@Suppress("DEPRECATION")
-@OptIn(ExperimentalCoilApi::class)
-@Composable
-private fun Sample() {
- Scaffold(
- topBar = {
- TopAppBar(
- title = { Text(stringResource(R.string.swiperefresh_title_custom)) },
- backgroundColor = MaterialTheme.colors.surface,
- )
- },
- modifier = Modifier.fillMaxSize()
- ) { padding ->
- // Simulate a fake 2-second 'load'. Ideally this 'refreshing' value would
- // come from a ViewModel or similar
- var refreshing by remember { mutableStateOf(false) }
- LaunchedEffect(refreshing) {
- if (refreshing) {
- delay(2000)
- refreshing = false
- }
- }
-
- SwipeRefresh(
- state = rememberSwipeRefreshState(isRefreshing = refreshing),
- onRefresh = { refreshing = true },
- indicator = { state, trigger ->
- SwipeRefreshIndicator(
- state = state,
- refreshTriggerDistance = trigger,
- scale = true,
- arrowEnabled = false,
- backgroundColor = MaterialTheme.colors.primary,
- shape = MaterialTheme.shapes.small,
- largeIndication = true,
- elevation = 16.dp
- )
- },
- ) {
- LazyColumn(contentPadding = padding) {
- items(30) { index ->
- Row(Modifier.padding(16.dp)) {
- Image(
- painter = rememberImagePainter(randomSampleImageUrl(index)),
- contentDescription = null,
- modifier = Modifier.size(64.dp),
- )
-
- Spacer(Modifier.width(8.dp))
-
- Text(
- text = "Text",
- style = MaterialTheme.typography.subtitle2,
- modifier = Modifier
- .weight(1f)
- .align(Alignment.CenterVertically)
- )
- }
- }
- }
- }
- }
-}
diff --git a/settings.gradle.kts b/settings.gradle.kts
index 58a872399..d9a950207 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -38,7 +38,6 @@ include(":placeholder")
include(":placeholder-material")
include(":placeholder-material3")
include(":systemuicontroller")
-include(":swiperefresh")
include(":sample")
include(":testharness")
include(":themeadapter-core")
diff --git a/swiperefresh/README.md b/swiperefresh/README.md
deleted file mode 100644
index 62d727284..000000000
--- a/swiperefresh/README.md
+++ /dev/null
@@ -1,21 +0,0 @@
-# Swipe Refresh layout for Jetpack Compose
-
-[![Maven Central](https://img.shields.io/maven-central/v/com.google.accompanist/accompanist-swiperefresh)](https://search.maven.org/search?q=g:com.google.accompanist)
-
-> :warning: This library has been deprecated as official support is now available in Compose Material 1.3.0. Please see our [Migration Guide](https://google.github.io/accompanist/swiperefresh/) for how to migrate.
-
-## Download
-
-```groovy
-repositories {
- mavenCentral()
-}
-
-dependencies {
- implementation "com.google.accompanist:accompanist-swiperefresh:"
-}
-```
-
-Snapshots of the development version are available in [Sonatype's `snapshots` repository][snap]. These are updated on every commit.
-
- [snap]: https://oss.sonatype.org/content/repositories/snapshots/com/google/accompanist/accompanist-swiperefresh/
\ No newline at end of file
diff --git a/swiperefresh/api/current.api b/swiperefresh/api/current.api
deleted file mode 100644
index e604ee6b3..000000000
--- a/swiperefresh/api/current.api
+++ /dev/null
@@ -1,28 +0,0 @@
-// Signature format: 4.0
-package com.google.accompanist.swiperefresh {
-
- public final class SlingshotKt {
- }
-
- public final class SwipeRefreshIndicatorKt {
- method @Deprecated @androidx.compose.runtime.Composable public static void SwipeRefreshIndicator(com.google.accompanist.swiperefresh.SwipeRefreshState state, float refreshTriggerDistance, optional androidx.compose.ui.Modifier modifier, optional boolean fade, optional boolean scale, optional boolean arrowEnabled, optional long backgroundColor, optional long contentColor, optional androidx.compose.ui.graphics.Shape shape, optional float refreshingOffset, optional boolean largeIndication, optional float elevation);
- }
-
- public final class SwipeRefreshKt {
- method @Deprecated @androidx.compose.runtime.Composable public static void SwipeRefresh(com.google.accompanist.swiperefresh.SwipeRefreshState state, kotlin.jvm.functions.Function0 onRefresh, optional androidx.compose.ui.Modifier modifier, optional boolean swipeEnabled, optional float refreshTriggerDistance, optional androidx.compose.ui.Alignment indicatorAlignment, optional androidx.compose.foundation.layout.PaddingValues indicatorPadding, optional kotlin.jvm.functions.Function2 super com.google.accompanist.swiperefresh.SwipeRefreshState,? super androidx.compose.ui.unit.Dp,kotlin.Unit> indicator, optional boolean clipIndicatorToPadding, kotlin.jvm.functions.Function0 content);
- method @Deprecated @androidx.compose.runtime.Composable public static com.google.accompanist.swiperefresh.SwipeRefreshState rememberSwipeRefreshState(boolean isRefreshing);
- }
-
- @Deprecated @androidx.compose.runtime.Stable public final class SwipeRefreshState {
- ctor @Deprecated public SwipeRefreshState(boolean isRefreshing);
- method @Deprecated public float getIndicatorOffset();
- method @Deprecated public boolean isRefreshing();
- method @Deprecated public boolean isSwipeInProgress();
- method @Deprecated public void setRefreshing(boolean);
- property public final float indicatorOffset;
- property public final boolean isRefreshing;
- property public final boolean isSwipeInProgress;
- }
-
-}
-
diff --git a/swiperefresh/build.gradle.kts b/swiperefresh/build.gradle.kts
deleted file mode 100644
index dc997e547..000000000
--- a/swiperefresh/build.gradle.kts
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-@file:Suppress("UnstableApiUsage")
-
-plugins {
- id(libs.plugins.android.library.get().pluginId)
- id(libs.plugins.android.kotlin.get().pluginId)
- id(libs.plugins.jetbrains.dokka.get().pluginId)
- id(libs.plugins.gradle.metalava.get().pluginId)
- id(libs.plugins.vanniktech.maven.publish.get().pluginId)
-}
-
-kotlin {
- explicitApi()
-}
-
-android {
- namespace = "com.google.accompanist.swiperefresh"
-
- compileSdk = 34
-
- defaultConfig {
- minSdk = 21
- // targetSdkVersion has no effect for libraries. This is only used for the test APK
- targetSdk = 33
- testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
- }
-
- compileOptions {
- sourceCompatibility = JavaVersion.VERSION_1_8
- targetCompatibility = JavaVersion.VERSION_1_8
- }
-
- buildFeatures {
- buildConfig = false
- compose = true
- }
-
- composeOptions {
- kotlinCompilerExtensionVersion = libs.versions.composeCompiler.get()
- }
-
- lint {
- textReport = true
- textOutput = File("stdout")
- // We run a full lint analysis as build part in CI, so skip vital checks for assemble tasks
- checkReleaseBuilds = false
- disable += setOf("GradleOverrides")
- }
-
- packaging {
- // Some of the META-INF files conflict with coroutines-test. Exclude them to enable
- // our test APK to build (has no effect on our AARs)
- resources {
- excludes += listOf("/META-INF/AL2.0", "/META-INF/LGPL2.1")
- }
- }
-
- testOptions {
- unitTests {
- isIncludeAndroidResources = true
- }
- animationsDisabled = true
- }
-
- sourceSets {
- named("test") {
- java.srcDirs("src/sharedTest/kotlin")
- res.srcDirs("src/sharedTest/res")
- }
- named("androidTest") {
- java.srcDirs("src/sharedTest/kotlin")
- res.srcDirs("src/sharedTest/res")
- }
- }
-}
-
-metalava {
- sourcePaths.setFrom("src/main")
- filename.set("api/current.api")
- reportLintsAsErrors.set(true)
-}
-
-dependencies {
- implementation(libs.compose.material.material)
- implementation(libs.compose.ui.util)
- implementation(libs.kotlin.coroutines.android)
-
- // ======================
- // Test dependencies
- // ======================
- androidTestImplementation(project(":internal-testutils"))
- testImplementation(project(":internal-testutils"))
-
- androidTestImplementation(libs.junit)
- testImplementation(libs.junit)
-
- androidTestImplementation(libs.truth)
- testImplementation(libs.truth)
-
- androidTestImplementation(libs.compose.ui.test.junit4)
- testImplementation(libs.compose.ui.test.junit4)
-
- androidTestImplementation(libs.compose.ui.test.manifest)
- testImplementation(libs.compose.ui.test.manifest)
-
- androidTestImplementation(libs.androidx.test.runner)
- testImplementation(libs.androidx.test.runner)
-
- testImplementation(libs.robolectric)
-}
diff --git a/swiperefresh/gradle.properties b/swiperefresh/gradle.properties
deleted file mode 100644
index 6e06299b3..000000000
--- a/swiperefresh/gradle.properties
+++ /dev/null
@@ -1,3 +0,0 @@
-POM_ARTIFACT_ID=accompanist-swiperefresh
-POM_NAME=Accompanist SwipeRefresh library
-POM_PACKAGING=aar
\ No newline at end of file
diff --git a/swiperefresh/src/main/AndroidManifest.xml b/swiperefresh/src/main/AndroidManifest.xml
deleted file mode 100644
index 928e8bf1f..000000000
--- a/swiperefresh/src/main/AndroidManifest.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-
-
-
-
-
diff --git a/swiperefresh/src/main/java/com/google/accompanist/swiperefresh/CircularProgressPainter.kt b/swiperefresh/src/main/java/com/google/accompanist/swiperefresh/CircularProgressPainter.kt
deleted file mode 100644
index 9735dc7bd..000000000
--- a/swiperefresh/src/main/java/com/google/accompanist/swiperefresh/CircularProgressPainter.kt
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.accompanist.swiperefresh
-
-import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.setValue
-import androidx.compose.ui.geometry.Offset
-import androidx.compose.ui.geometry.Rect
-import androidx.compose.ui.geometry.Size
-import androidx.compose.ui.geometry.center
-import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.graphics.Path
-import androidx.compose.ui.graphics.PathFillType
-import androidx.compose.ui.graphics.StrokeCap
-import androidx.compose.ui.graphics.drawscope.DrawScope
-import androidx.compose.ui.graphics.drawscope.Stroke
-import androidx.compose.ui.graphics.drawscope.rotate
-import androidx.compose.ui.graphics.painter.Painter
-import androidx.compose.ui.unit.dp
-import kotlin.math.min
-
-/**
- * A private class to do all the drawing of SwipeRefreshIndicator, which includes progress spinner
- * and the arrow. This class is to separate drawing from animation.
- * Adapted from CircularProgressDrawable.
- */
-internal class CircularProgressPainter : Painter() {
- var color by mutableStateOf(Color.Unspecified)
- var alpha by mutableStateOf(1f)
- var arcRadius by mutableStateOf(0.dp)
- var strokeWidth by mutableStateOf(5.dp)
- var arrowEnabled by mutableStateOf(false)
- var arrowWidth by mutableStateOf(0.dp)
- var arrowHeight by mutableStateOf(0.dp)
- var arrowScale by mutableStateOf(1f)
-
- private val arrow: Path by lazy {
- Path().apply { fillType = PathFillType.EvenOdd }
- }
-
- var startTrim by mutableStateOf(0f)
- var endTrim by mutableStateOf(0f)
- var rotation by mutableStateOf(0f)
-
- override val intrinsicSize: Size
- get() = Size.Unspecified
-
- override fun applyAlpha(alpha: Float): Boolean {
- this.alpha = alpha
- return true
- }
-
- override fun DrawScope.onDraw() {
- rotate(degrees = rotation) {
- val arcRadius = arcRadius.toPx() + strokeWidth.toPx() / 2f
- val arcBounds = Rect(
- size.center.x - arcRadius,
- size.center.y - arcRadius,
- size.center.x + arcRadius,
- size.center.y + arcRadius
- )
- val startAngle = (startTrim + rotation) * 360
- val endAngle = (endTrim + rotation) * 360
- val sweepAngle = endAngle - startAngle
- drawArc(
- color = color,
- alpha = alpha,
- startAngle = startAngle,
- sweepAngle = sweepAngle,
- useCenter = false,
- topLeft = arcBounds.topLeft,
- size = arcBounds.size,
- style = Stroke(
- width = strokeWidth.toPx(),
- cap = StrokeCap.Square
- )
- )
- if (arrowEnabled) {
- drawArrow(startAngle, sweepAngle, arcBounds)
- }
- }
- }
-
- private fun DrawScope.drawArrow(startAngle: Float, sweepAngle: Float, bounds: Rect) {
- arrow.reset()
- arrow.moveTo(0f, 0f)
- arrow.lineTo(
- x = arrowWidth.toPx() * arrowScale,
- y = 0f
- )
- arrow.lineTo(
- x = arrowWidth.toPx() * arrowScale / 2,
- y = arrowHeight.toPx() * arrowScale
- )
- val radius = min(bounds.width, bounds.height) / 2f
- val inset = arrowWidth.toPx() * arrowScale / 2f
- arrow.translate(
- Offset(
- x = radius + bounds.center.x - inset,
- y = bounds.center.y + strokeWidth.toPx() / 2f
- )
- )
- arrow.close()
- rotate(degrees = startAngle + sweepAngle) {
- drawPath(
- path = arrow,
- color = color,
- alpha = alpha
- )
- }
- }
-}
diff --git a/swiperefresh/src/main/java/com/google/accompanist/swiperefresh/Slingshot.kt b/swiperefresh/src/main/java/com/google/accompanist/swiperefresh/Slingshot.kt
deleted file mode 100644
index 949907923..000000000
--- a/swiperefresh/src/main/java/com/google/accompanist/swiperefresh/Slingshot.kt
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.accompanist.swiperefresh
-
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.Stable
-import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.remember
-import androidx.compose.runtime.setValue
-import kotlin.math.abs
-import kotlin.math.max
-import kotlin.math.min
-import kotlin.math.pow
-
-/**
- * A utility function that calculates various aspects of 'slingshot' behavior.
- * Adapted from SwipeRefreshLayout#moveSpinner method.
- *
- * TODO: Investigate replacing this with a spring.
- *
- * @param offsetY The current y offset.
- * @param maxOffsetY The max y offset.
- * @param height The height of the item to slingshot.
- */
-@Composable
-internal fun rememberUpdatedSlingshot(
- offsetY: Float,
- maxOffsetY: Float,
- height: Int
-): Slingshot {
- val offsetPercent = min(1f, offsetY / maxOffsetY)
- val adjustedPercent = max(offsetPercent - 0.4f, 0f) * 5 / 3
- val extraOffset = abs(offsetY) - maxOffsetY
-
- // Can accommodate custom start and slingshot distance here
- val slingshotDistance = maxOffsetY
- val tensionSlingshotPercent = max(
- 0f, min(extraOffset, slingshotDistance * 2) / slingshotDistance
- )
- val tensionPercent = (
- (tensionSlingshotPercent / 4) -
- (tensionSlingshotPercent / 4).pow(2)
- ) * 2
- val extraMove = slingshotDistance * tensionPercent * 2
- val targetY = height + ((slingshotDistance * offsetPercent) + extraMove).toInt()
- val offset = targetY - height
- val strokeStart = adjustedPercent * 0.8f
-
- val startTrim = 0f
- val endTrim = strokeStart.coerceAtMost(MaxProgressArc)
-
- val rotation = (-0.25f + 0.4f * adjustedPercent + tensionPercent * 2) * 0.5f
- val arrowScale = min(1f, adjustedPercent)
-
- return remember { Slingshot() }.apply {
- this.offset = offset
- this.startTrim = startTrim
- this.endTrim = endTrim
- this.rotation = rotation
- this.arrowScale = arrowScale
- }
-}
-
-@Stable
-internal class Slingshot {
- var offset: Int by mutableStateOf(0)
- var startTrim: Float by mutableStateOf(0f)
- var endTrim: Float by mutableStateOf(0f)
- var rotation: Float by mutableStateOf(0f)
- var arrowScale: Float by mutableStateOf(0f)
-}
-
-internal const val MaxProgressArc = 0.8f
diff --git a/swiperefresh/src/main/java/com/google/accompanist/swiperefresh/SwipeRefresh.kt b/swiperefresh/src/main/java/com/google/accompanist/swiperefresh/SwipeRefresh.kt
deleted file mode 100644
index cebc30c71..000000000
--- a/swiperefresh/src/main/java/com/google/accompanist/swiperefresh/SwipeRefresh.kt
+++ /dev/null
@@ -1,317 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-@file:Suppress("DEPRECATION")
-
-package com.google.accompanist.swiperefresh
-
-import androidx.compose.animation.core.Animatable
-import androidx.compose.foundation.MutatePriority
-import androidx.compose.foundation.MutatorMutex
-import androidx.compose.foundation.layout.Box
-import androidx.compose.foundation.layout.PaddingValues
-import androidx.compose.foundation.layout.padding
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.LaunchedEffect
-import androidx.compose.runtime.Stable
-import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.remember
-import androidx.compose.runtime.rememberCoroutineScope
-import androidx.compose.runtime.rememberUpdatedState
-import androidx.compose.runtime.setValue
-import androidx.compose.ui.Alignment
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.draw.clipToBounds
-import androidx.compose.ui.geometry.Offset
-import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
-import androidx.compose.ui.input.nestedscroll.NestedScrollSource
-import androidx.compose.ui.input.nestedscroll.nestedScroll
-import androidx.compose.ui.platform.LocalDensity
-import androidx.compose.ui.unit.Dp
-import androidx.compose.ui.unit.Velocity
-import androidx.compose.ui.unit.dp
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.launch
-import kotlin.math.absoluteValue
-import kotlin.math.roundToInt
-
-private const val DragMultiplier = 0.5f
-
-/**
- * Creates a [SwipeRefreshState] that is remembered across compositions.
- *
- * Changes to [isRefreshing] will result in the [SwipeRefreshState] being updated.
- *
- * @param isRefreshing the value for [SwipeRefreshState.isRefreshing]
- */
-@Deprecated(
- """
- accompanist/swiperefresh is deprecated.
- The androidx.compose equivalent of rememberSwipeRefreshState() is rememberPullRefreshState().
- For more migration information, please visit https://google.github.io/accompanist/swiperefresh/#migration
- """,
- replaceWith = ReplaceWith(
- "rememberPullRefreshState(isRefreshing, onRefresh = )",
- "androidx.compose.material.pullrefresh.rememberPullRefreshState"
- )
-)
-@Composable
-public fun rememberSwipeRefreshState(
- isRefreshing: Boolean
-): SwipeRefreshState {
- return remember {
- SwipeRefreshState(
- isRefreshing = isRefreshing
- )
- }.apply {
- this.isRefreshing = isRefreshing
- }
-}
-
-/**
- * A state object that can be hoisted to control and observe changes for [SwipeRefresh].
- *
- * In most cases, this will be created via [rememberSwipeRefreshState].
- *
- * @param isRefreshing the initial value for [SwipeRefreshState.isRefreshing]
- */
-@Deprecated(
- """
- accompanist/swiperefresh is deprecated.
- The androidx.compose equivalent of SwipeRefreshState is PullRefreshState.
- For more migration information, please visit https://google.github.io/accompanist/swiperefresh/#migration
- """
-)
-@Stable
-public class SwipeRefreshState(
- isRefreshing: Boolean,
-) {
- private val _indicatorOffset = Animatable(0f)
- private val mutatorMutex = MutatorMutex()
-
- /**
- * Whether this [SwipeRefreshState] is currently refreshing or not.
- */
- public var isRefreshing: Boolean by mutableStateOf(isRefreshing)
-
- /**
- * Whether a swipe/drag is currently in progress.
- */
- public var isSwipeInProgress: Boolean by mutableStateOf(false)
- internal set
-
- /**
- * The current offset for the indicator, in pixels.
- */
- public val indicatorOffset: Float get() = _indicatorOffset.value
-
- internal suspend fun animateOffsetTo(offset: Float) {
- mutatorMutex.mutate {
- _indicatorOffset.animateTo(offset)
- }
- }
-
- /**
- * Dispatch scroll delta in pixels from touch events.
- */
- internal suspend fun dispatchScrollDelta(delta: Float) {
- mutatorMutex.mutate(MutatePriority.UserInput) {
- _indicatorOffset.snapTo(_indicatorOffset.value + delta)
- }
- }
-}
-
-private class SwipeRefreshNestedScrollConnection(
- private val state: SwipeRefreshState,
- private val coroutineScope: CoroutineScope,
- private val onRefresh: () -> Unit,
-) : NestedScrollConnection {
- var enabled: Boolean = false
- var refreshTrigger: Float = 0f
-
- override fun onPreScroll(
- available: Offset,
- source: NestedScrollSource
- ): Offset = when {
- // If swiping isn't enabled, return zero
- !enabled -> Offset.Zero
- // If we're refreshing, return zero
- state.isRefreshing -> Offset.Zero
- // If the user is swiping up, handle it
- source == NestedScrollSource.Drag && available.y < 0 -> onScroll(available)
- else -> Offset.Zero
- }
-
- override fun onPostScroll(
- consumed: Offset,
- available: Offset,
- source: NestedScrollSource
- ): Offset = when {
- // If swiping isn't enabled, return zero
- !enabled -> Offset.Zero
- // If we're refreshing, return zero
- state.isRefreshing -> Offset.Zero
- // If the user is swiping down and there's y remaining, handle it
- source == NestedScrollSource.Drag && available.y > 0 -> onScroll(available)
- else -> Offset.Zero
- }
-
- private fun onScroll(available: Offset): Offset {
- if (available.y > 0) {
- state.isSwipeInProgress = true
- } else if (state.indicatorOffset.roundToInt() == 0) {
- state.isSwipeInProgress = false
- }
-
- val newOffset = (available.y * DragMultiplier + state.indicatorOffset).coerceAtLeast(0f)
- val dragConsumed = newOffset - state.indicatorOffset
-
- return if (dragConsumed.absoluteValue >= 0.5f) {
- coroutineScope.launch {
- state.dispatchScrollDelta(dragConsumed)
- }
- // Return the consumed Y
- Offset(x = 0f, y = dragConsumed / DragMultiplier)
- } else {
- Offset.Zero
- }
- }
-
- override suspend fun onPreFling(available: Velocity): Velocity {
- // If we're dragging, not currently refreshing and scrolled
- // past the trigger point, refresh!
- if (!state.isRefreshing && state.indicatorOffset >= refreshTrigger) {
- onRefresh()
- }
-
- // Reset the drag in progress state
- state.isSwipeInProgress = false
-
- // Don't consume any velocity, to allow the scrolling layout to fling
- return Velocity.Zero
- }
-}
-
-/**
- * A layout which implements the swipe-to-refresh pattern, allowing the user to refresh content via
- * a vertical swipe gesture.
- *
- * This layout requires its content to be scrollable so that it receives vertical swipe events.
- * The scrollable content does not need to be a direct descendant though. Layouts such as
- * [androidx.compose.foundation.lazy.LazyColumn] are automatically scrollable, but others such as
- * [androidx.compose.foundation.layout.Column] require you to provide the
- * [androidx.compose.foundation.verticalScroll] modifier to that content.
- *
- * Apps should provide a [onRefresh] block to be notified each time a swipe to refresh gesture
- * is completed. That block is responsible for updating the [state] as appropriately,
- * typically by setting [SwipeRefreshState.isRefreshing] to `true` once a 'refresh' has been
- * started. Once a refresh has completed, the app should then set
- * [SwipeRefreshState.isRefreshing] to `false`.
- *
- * If an app wishes to show the progress animation outside of a swipe gesture, it can
- * set [SwipeRefreshState.isRefreshing] as required.
- *
- * This layout does not clip any of it's contents, including the indicator. If clipping
- * is required, apps can provide the [androidx.compose.ui.draw.clipToBounds] modifier.
- *
- * @sample com.google.accompanist.sample.swiperefresh.SwipeRefreshSample
- *
- * @param state the state object to be used to control or observe the [SwipeRefresh] state.
- * @param onRefresh Lambda which is invoked when a swipe to refresh gesture is completed.
- * @param modifier the modifier to apply to this layout.
- * @param swipeEnabled Whether the the layout should react to swipe gestures or not.
- * @param refreshTriggerDistance The minimum swipe distance which would trigger a refresh.
- * @param indicatorAlignment The alignment of the indicator. Defaults to [Alignment.TopCenter].
- * @param indicatorPadding Content padding for the indicator, to inset the indicator in if required.
- * @param indicator the indicator that represents the current state. By default this
- * will use a [SwipeRefreshIndicator].
- * @param clipIndicatorToPadding Whether to clip the indicator to [indicatorPadding]. If false is
- * provided the indicator will be clipped to the [content] bounds. Defaults to true.
- * @param content The content containing a scroll composable.
- */
-@Deprecated(
- """
- accompanist/swiperefresh is deprecated.
- The androidx.compose equivalent of SwipeRefresh is Modifier.pullRefresh().
- This is often migrated as:
- Box(modifier = Modifier.pullRefresh(refreshState)) {
- ...
- PullRefreshIndicator(...)
- }
-
- For more migration information, please visit https://google.github.io/accompanist/swiperefresh/#migration
-"""
-)
-@Composable
-public fun SwipeRefresh(
- state: SwipeRefreshState,
- onRefresh: () -> Unit,
- modifier: Modifier = Modifier,
- swipeEnabled: Boolean = true,
- refreshTriggerDistance: Dp = 80.dp,
- indicatorAlignment: Alignment = Alignment.TopCenter,
- indicatorPadding: PaddingValues = PaddingValues(0.dp),
- indicator: @Composable (state: SwipeRefreshState, refreshTrigger: Dp) -> Unit = { s, trigger ->
- SwipeRefreshIndicator(s, trigger)
- },
- clipIndicatorToPadding: Boolean = true,
- content: @Composable () -> Unit,
-) {
- val coroutineScope = rememberCoroutineScope()
- val updatedOnRefresh = rememberUpdatedState(onRefresh)
-
- // Our LaunchedEffect, which animates the indicator to its resting position
- LaunchedEffect(state.isSwipeInProgress) {
- if (!state.isSwipeInProgress) {
- // If there's not a swipe in progress, rest the indicator at 0f
- state.animateOffsetTo(0f)
- }
- }
-
- val refreshTriggerPx = with(LocalDensity.current) { refreshTriggerDistance.toPx() }
-
- // Our nested scroll connection, which updates our state.
- val nestedScrollConnection = remember(state, coroutineScope) {
- SwipeRefreshNestedScrollConnection(state, coroutineScope) {
- // On refresh, re-dispatch to the update onRefresh block
- updatedOnRefresh.value.invoke()
- }
- }.apply {
- this.enabled = swipeEnabled
- this.refreshTrigger = refreshTriggerPx
- }
-
- Box(modifier.nestedScroll(connection = nestedScrollConnection)) {
- content()
-
- Box(
- Modifier
- // If we're not clipping to the padding, we use clipToBounds() before the padding()
- // modifier.
- .let { if (!clipIndicatorToPadding) it.clipToBounds() else it }
- .padding(indicatorPadding)
- .matchParentSize()
- // Else, if we're are clipping to the padding, we use clipToBounds() after
- // the padding() modifier.
- .let { if (clipIndicatorToPadding) it.clipToBounds() else it }
- ) {
- Box(Modifier.align(indicatorAlignment)) {
- indicator(state, refreshTriggerDistance)
- }
- }
- }
-}
diff --git a/swiperefresh/src/main/java/com/google/accompanist/swiperefresh/SwipeRefreshIndicator.kt b/swiperefresh/src/main/java/com/google/accompanist/swiperefresh/SwipeRefreshIndicator.kt
deleted file mode 100644
index 4ae879aa8..000000000
--- a/swiperefresh/src/main/java/com/google/accompanist/swiperefresh/SwipeRefreshIndicator.kt
+++ /dev/null
@@ -1,236 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-@file:Suppress("DEPRECATION")
-
-package com.google.accompanist.swiperefresh
-
-import androidx.compose.animation.Crossfade
-import androidx.compose.animation.core.LinearOutSlowInEasing
-import androidx.compose.animation.core.animate
-import androidx.compose.animation.core.tween
-import androidx.compose.foundation.Image
-import androidx.compose.foundation.layout.Box
-import androidx.compose.foundation.layout.fillMaxSize
-import androidx.compose.foundation.layout.size
-import androidx.compose.foundation.shape.CircleShape
-import androidx.compose.foundation.shape.CornerSize
-import androidx.compose.material.CircularProgressIndicator
-import androidx.compose.material.MaterialTheme
-import androidx.compose.material.Surface
-import androidx.compose.material.contentColorFor
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.Immutable
-import androidx.compose.runtime.LaunchedEffect
-import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.remember
-import androidx.compose.runtime.setValue
-import androidx.compose.ui.Alignment
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.graphics.Shape
-import androidx.compose.ui.graphics.graphicsLayer
-import androidx.compose.ui.platform.LocalDensity
-import androidx.compose.ui.unit.Dp
-import androidx.compose.ui.unit.dp
-
-/**
- * A class to encapsulate details of different indicator sizes.
- *
- * @param size The overall size of the indicator.
- * @param arcRadius The radius of the arc.
- * @param strokeWidth The width of the arc stroke.
- * @param arrowWidth The width of the arrow.
- * @param arrowHeight The height of the arrow.
- */
-@Immutable
-private data class SwipeRefreshIndicatorSizes(
- val size: Dp,
- val arcRadius: Dp,
- val strokeWidth: Dp,
- val arrowWidth: Dp,
- val arrowHeight: Dp,
-)
-
-/**
- * The default/normal size values for [SwipeRefreshIndicator].
- */
-private val DefaultSizes = SwipeRefreshIndicatorSizes(
- size = 40.dp,
- arcRadius = 7.5.dp,
- strokeWidth = 2.5.dp,
- arrowWidth = 10.dp,
- arrowHeight = 5.dp,
-)
-
-/**
- * The 'large' size values for [SwipeRefreshIndicator].
- */
-private val LargeSizes = SwipeRefreshIndicatorSizes(
- size = 56.dp,
- arcRadius = 11.dp,
- strokeWidth = 3.dp,
- arrowWidth = 12.dp,
- arrowHeight = 6.dp,
-)
-
-/**
- * Indicator composable which is typically used in conjunction with [SwipeRefresh].
- *
- * @param state The [SwipeRefreshState] passed into the [SwipeRefresh] `indicator` block.
- * @param modifier The modifier to apply to this layout.
- * @param fade Whether the arrow should fade in/out as it is scrolled in. Defaults to true.
- * @param scale Whether the indicator should scale up/down as it is scrolled in. Defaults to false.
- * @param arrowEnabled Whether an arrow should be drawn on the indicator. Defaults to true.
- * @param backgroundColor The color of the indicator background surface.
- * @param contentColor The color for the indicator's contents.
- * @param shape The shape of the indicator background surface. Defaults to [CircleShape].
- * @param largeIndication Whether the indicator should be 'large' or not. Defaults to false.
- * @param elevation The size of the shadow below the indicator.
- */
-@Deprecated(
- """
- accompanist/swiperefresh is deprecated.
- The androidx.compose equivalent of SwipeRefreshIndicator() is PullRefreshIndicator().
- For more migration information, please visit https://google.github.io/accompanist/swiperefresh/#migration
- """
-)
-@Composable
-public fun SwipeRefreshIndicator(
- state: SwipeRefreshState,
- refreshTriggerDistance: Dp,
- modifier: Modifier = Modifier,
- fade: Boolean = true,
- scale: Boolean = false,
- arrowEnabled: Boolean = true,
- backgroundColor: Color = MaterialTheme.colors.surface,
- contentColor: Color = contentColorFor(backgroundColor),
- shape: Shape = MaterialTheme.shapes.small.copy(CornerSize(percent = 50)),
- refreshingOffset: Dp = 16.dp,
- largeIndication: Boolean = false,
- elevation: Dp = 6.dp,
-) {
- val sizes = if (largeIndication) LargeSizes else DefaultSizes
-
- val indicatorRefreshTrigger = with(LocalDensity.current) { refreshTriggerDistance.toPx() }
-
- val indicatorHeight = with(LocalDensity.current) { sizes.size.roundToPx() }
- val refreshingOffsetPx = with(LocalDensity.current) { refreshingOffset.toPx() }
-
- val slingshot = rememberUpdatedSlingshot(
- offsetY = state.indicatorOffset,
- maxOffsetY = indicatorRefreshTrigger,
- height = indicatorHeight,
- )
-
- var offset by remember { mutableStateOf(0f) }
-
- if (state.isSwipeInProgress) {
- // If the user is currently swiping, we use the 'slingshot' offset directly
- offset = slingshot.offset.toFloat()
- } else {
- // If there's no swipe currently in progress, animate to the correct resting position
- LaunchedEffect(state.isRefreshing) {
- animate(
- initialValue = offset,
- targetValue = when {
- state.isRefreshing -> indicatorHeight + refreshingOffsetPx
- else -> 0f
- }
- ) { value, _ ->
- offset = value
- }
- }
- }
-
- val adjustedElevation = when {
- state.isRefreshing -> elevation
- offset > 0.5f -> elevation
- else -> 0.dp
- }
-
- Surface(
- modifier = modifier
- .size(size = sizes.size)
- .graphicsLayer {
- // Translate the indicator according to the slingshot
- translationY = offset - indicatorHeight
-
- val scaleFraction = if (scale && !state.isRefreshing) {
- val progress = offset / indicatorRefreshTrigger.coerceAtLeast(1f)
-
- // We use LinearOutSlowInEasing to speed up the scale in
- LinearOutSlowInEasing
- .transform(progress)
- .coerceIn(0f, 1f)
- } else 1f
-
- scaleX = scaleFraction
- scaleY = scaleFraction
- },
- shape = shape,
- color = backgroundColor,
- elevation = adjustedElevation
- ) {
- val painter = remember { CircularProgressPainter() }
- painter.arcRadius = sizes.arcRadius
- painter.strokeWidth = sizes.strokeWidth
- painter.arrowWidth = sizes.arrowWidth
- painter.arrowHeight = sizes.arrowHeight
- painter.arrowEnabled = arrowEnabled && !state.isRefreshing
- painter.color = contentColor
- val alpha = if (fade) {
- (state.indicatorOffset / indicatorRefreshTrigger).coerceIn(0f, 1f)
- } else {
- 1f
- }
- painter.alpha = alpha
-
- painter.startTrim = slingshot.startTrim
- painter.endTrim = slingshot.endTrim
- painter.rotation = slingshot.rotation
- painter.arrowScale = slingshot.arrowScale
-
- // This shows either an Image with CircularProgressPainter or a CircularProgressIndicator,
- // depending on refresh state
- Crossfade(
- targetState = state.isRefreshing,
- animationSpec = tween(durationMillis = CrossfadeDurationMs)
- ) { refreshing ->
- Box(
- modifier = Modifier.fillMaxSize(),
- contentAlignment = Alignment.Center
- ) {
- if (refreshing) {
- val circleSize = (sizes.arcRadius + sizes.strokeWidth) * 2
- CircularProgressIndicator(
- color = contentColor,
- strokeWidth = sizes.strokeWidth,
- modifier = Modifier.size(circleSize),
- )
- } else {
- Image(
- painter = painter,
- contentDescription = "Refreshing"
- )
- }
- }
- }
- }
-}
-
-private const val CrossfadeDurationMs = 100
diff --git a/swiperefresh/src/sharedTest/kotlin/com/google/accompanist/swiperefresh/FakeTests.kt b/swiperefresh/src/sharedTest/kotlin/com/google/accompanist/swiperefresh/FakeTests.kt
deleted file mode 100644
index cc8524003..000000000
--- a/swiperefresh/src/sharedTest/kotlin/com/google/accompanist/swiperefresh/FakeTests.kt
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.accompanist.swiperefresh
-
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
-
-/**
- * Fake tests to help with sharding: https://github.com/android/android-test/issues/973
- */
-@RunWith(JUnit4::class)
-class FakeTests {
- @Test
- fun fake1() = Unit
-
- @Test
- fun fake2() = Unit
-
- @Test
- fun fake3() = Unit
-
- @Test
- fun fake4() = Unit
-
- @Test
- fun fake5() = Unit
-
- @Test
- fun fake6() = Unit
-
- @Test
- fun fake7() = Unit
-
- @Test
- fun fake8() = Unit
-
- @Test
- fun fake9() = Unit
-
- @Test
- fun fake10() = Unit
-}
diff --git a/swiperefresh/src/sharedTest/kotlin/com/google/accompanist/swiperefresh/SwipeRefreshTest.kt b/swiperefresh/src/sharedTest/kotlin/com/google/accompanist/swiperefresh/SwipeRefreshTest.kt
deleted file mode 100644
index 85884bd2f..000000000
--- a/swiperefresh/src/sharedTest/kotlin/com/google/accompanist/swiperefresh/SwipeRefreshTest.kt
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-@file:Suppress("DEPRECATION")
-
-package com.google.accompanist.swiperefresh
-
-import androidx.compose.foundation.layout.fillMaxSize
-import androidx.compose.foundation.layout.fillMaxWidth
-import androidx.compose.foundation.lazy.LazyColumn
-import androidx.compose.material.ExperimentalMaterialApi
-import androidx.compose.material.ListItem
-import androidx.compose.material.MaterialTheme
-import androidx.compose.material.Text
-import androidx.compose.runtime.Composable
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.platform.testTag
-import androidx.compose.ui.test.SemanticsNodeInteraction
-import androidx.compose.ui.test.assertIsDisplayed
-import androidx.compose.ui.test.assertIsNotDisplayed
-import androidx.compose.ui.test.getUnclippedBoundsInRoot
-import androidx.compose.ui.test.junit4.createComposeRule
-import androidx.compose.ui.test.onNodeWithTag
-import androidx.compose.ui.test.performTouchInput
-import androidx.compose.ui.test.swipeDown
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import com.google.common.truth.Truth.assertThat
-import org.junit.Ignore
-import org.junit.Rule
-import org.junit.Test
-import org.junit.runner.RunWith
-
-@RunWith(AndroidJUnit4::class)
-class SwipeRefreshTest {
- @get:Rule
- val rule = createComposeRule()
-
- @Test
- @Ignore("https://issuetracker.google.com/issues/185814751")
- fun swipeRefreshes() {
- val state = SwipeRefreshState(false)
- var refreshCallCount = 0
-
- rule.setContent {
- SwipeRefreshTestContent(state) {
- state.isRefreshing = true
- refreshCallCount++
- }
- }
-
- // Swipe down on the swipe refresh
- swipeRefreshNode.performTouchInput { swipeDown() }
-
- // Assert that the onRefresh lambda was called once, and that we're refreshing
- assertThat(refreshCallCount).isEqualTo(1)
- assertThat(state.isRefreshing).isTrue()
-
- // Assert that the indicator is displayed
- indicatorNode.assertIsDisplayed()
-
- // Now stop 'refreshing' and assert that the indicator is no longer displayed
- state.isRefreshing = false
- indicatorNode.assertIsNotDisplayed()
- }
-
- @Test
- @Ignore("https://issuetracker.google.com/issues/185814751")
- fun indicatorVisibility() {
- lateinit var state: SwipeRefreshState
-
- rule.setContent {
- state = rememberSwipeRefreshState(false)
- SwipeRefreshTestContent(state) {}
- }
-
- // Assert that the indicator is not displayed
- indicatorNode.assertIsNotDisplayed()
-
- // Set refreshing to true and assert that the indicator is displayed
- state.isRefreshing = true
-
- rule.waitForIdle()
- indicatorNode.assertIsDisplayed()
- }
-
- @Test
- fun refreshingInitially() {
- rule.setContent {
- SwipeRefreshTestContent(rememberSwipeRefreshState(true)) {}
- }
-
- // Assert that the indicator is displayed
- indicatorNode.assertIsDisplayed()
- }
-
- @Test
- fun refreshingIndicator_returnsToRest() {
- rule.setContent {
- SwipeRefreshTestContent(rememberSwipeRefreshState(true)) {}
- }
-
- // Assert that the indicator is displayed
- indicatorNode.assertIsDisplayed()
- // Store the 'resting' bounds
- val restingBounds = indicatorNode.getUnclippedBoundsInRoot()
-
- // Now swipe down. The indicator should react visually
- swipeRefreshNode.performTouchInput { swipeDown() }
-
- // Assert that the indicator returns back to it's 'resting' position
- assertThat(indicatorNode.getUnclippedBoundsInRoot()).isEqualTo(restingBounds)
- }
-
- private val swipeRefreshNode: SemanticsNodeInteraction
- get() = rule.onNodeWithTag(SwipeRefreshTag)
-
- private val indicatorNode: SemanticsNodeInteraction
- get() = rule.onNodeWithTag(SwipeRefreshIndicatorTag)
-}
-
-private const val SwipeRefreshTag = "swipe_refresh"
-private const val SwipeRefreshIndicatorTag = "swipe_refresh_indicator"
-
-@OptIn(ExperimentalMaterialApi::class)
-@Composable
-private fun SwipeRefreshTestContent(
- state: SwipeRefreshState,
- onRefresh: () -> Unit,
-) {
- MaterialTheme {
- SwipeRefresh(
- state = state,
- onRefresh = onRefresh,
- modifier = Modifier.testTag(SwipeRefreshTag),
- indicator = { state, trigger ->
- SwipeRefreshIndicator(state, trigger, Modifier.testTag(SwipeRefreshIndicatorTag))
- }
- ) {
- LazyColumn(Modifier.fillMaxSize()) {
- items(30) { index ->
- ListItem(Modifier.fillMaxWidth()) {
- Text(text = "Item $index")
- }
- }
- }
- }
- }
-}
diff --git a/swiperefresh/src/test/resources/robolectric.properties b/swiperefresh/src/test/resources/robolectric.properties
deleted file mode 100644
index 2806eaffa..000000000
--- a/swiperefresh/src/test/resources/robolectric.properties
+++ /dev/null
@@ -1,3 +0,0 @@
-# Pin SDK to 30 since Robolectric does not currently support API 31:
-# https://github.com/robolectric/robolectric/issues/6635
-sdk=30