diff --git a/app/src/main/java/eu/kanade/presentation/browse/ExtensionsScreen.kt b/app/src/main/java/eu/kanade/presentation/browse/ExtensionsScreen.kt index f064a4a1cb..b5a681446a 100644 --- a/app/src/main/java/eu/kanade/presentation/browse/ExtensionsScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/browse/ExtensionsScreen.kt @@ -40,6 +40,7 @@ import com.google.accompanist.swiperefresh.SwipeRefresh import com.google.accompanist.swiperefresh.rememberSwipeRefreshState import eu.kanade.presentation.browse.components.BaseBrowseItem import eu.kanade.presentation.browse.components.ExtensionIcon +import eu.kanade.presentation.components.SwipeRefreshIndicator import eu.kanade.presentation.theme.header import eu.kanade.presentation.util.horizontalPadding import eu.kanade.presentation.util.plus @@ -73,12 +74,12 @@ fun ExtensionScreen( SwipeRefresh( modifier = Modifier.nestedScroll(nestedScrollInterop), state = rememberSwipeRefreshState(isRefreshing), + indicator = { s, trigger -> SwipeRefreshIndicator(s, trigger) }, onRefresh = onRefresh, ) { when (state) { is ExtensionState.Initialized -> { ExtensionContent( - nestedScrollInterop = nestedScrollInterop, items = (state as ExtensionState.Initialized).list, onLongClickItem = onLongClickItem, onClickItemCancel = onClickItemCancel, @@ -98,7 +99,6 @@ fun ExtensionScreen( @Composable fun ExtensionContent( - nestedScrollInterop: NestedScrollConnection, items: List, onLongClickItem: (Extension) -> Unit, onClickItemCancel: (Extension) -> Unit, @@ -112,7 +112,6 @@ fun ExtensionContent( ) { val (trustState, setTrustState) = remember { mutableStateOf(null) } LazyColumn( - modifier = Modifier.nestedScroll(nestedScrollInterop), contentPadding = WindowInsets.navigationBars.asPaddingValues() + topPaddingValues, ) { items( diff --git a/app/src/main/java/eu/kanade/presentation/browse/SourceFilterScreen.kt b/app/src/main/java/eu/kanade/presentation/browse/SourcesFilterScreen.kt similarity index 92% rename from app/src/main/java/eu/kanade/presentation/browse/SourceFilterScreen.kt rename to app/src/main/java/eu/kanade/presentation/browse/SourcesFilterScreen.kt index b97ce3060a..3f29287a1e 100644 --- a/app/src/main/java/eu/kanade/presentation/browse/SourceFilterScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/browse/SourcesFilterScreen.kt @@ -22,14 +22,14 @@ import eu.kanade.presentation.components.LoadingScreen import eu.kanade.presentation.components.PreferenceRow import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.ui.browse.source.FilterUiModel -import eu.kanade.tachiyomi.ui.browse.source.SourceFilterPresenter import eu.kanade.tachiyomi.ui.browse.source.SourceFilterState +import eu.kanade.tachiyomi.ui.browse.source.SourcesFilterPresenter import eu.kanade.tachiyomi.util.system.LocaleHelper @Composable -fun SourceFilterScreen( +fun SourcesFilterScreen( nestedScrollInterop: NestedScrollConnection, - presenter: SourceFilterPresenter, + presenter: SourcesFilterPresenter, onClickLang: (String) -> Unit, onClickSource: (Source) -> Unit, ) { @@ -39,7 +39,7 @@ fun SourceFilterScreen( is SourceFilterState.Loading -> LoadingScreen() is SourceFilterState.Error -> Text(text = (state as SourceFilterState.Error).error.message!!) is SourceFilterState.Success -> - SourceFilterContent( + SourcesFilterContent( nestedScrollInterop = nestedScrollInterop, items = (state as SourceFilterState.Success).models, onClickLang = onClickLang, @@ -49,7 +49,7 @@ fun SourceFilterScreen( } @Composable -fun SourceFilterContent( +fun SourcesFilterContent( nestedScrollInterop: NestedScrollConnection, items: List, onClickLang: (String) -> Unit, @@ -81,14 +81,14 @@ fun SourceFilterContent( ) { model -> when (model) { is FilterUiModel.Header -> { - SourceFilterHeader( + SourcesFilterHeader( modifier = Modifier.animateItemPlacement(), language = model.language, isEnabled = model.isEnabled, onClickItem = onClickLang, ) } - is FilterUiModel.Item -> SourceFilterItem( + is FilterUiModel.Item -> SourcesFilterItem( modifier = Modifier.animateItemPlacement(), source = model.source, isEnabled = model.isEnabled, @@ -100,7 +100,7 @@ fun SourceFilterContent( } @Composable -fun SourceFilterHeader( +fun SourcesFilterHeader( modifier: Modifier, language: String, isEnabled: Boolean, @@ -117,7 +117,7 @@ fun SourceFilterHeader( } @Composable -fun SourceFilterItem( +fun SourcesFilterItem( modifier: Modifier, source: Source, isEnabled: Boolean, diff --git a/app/src/main/java/eu/kanade/presentation/browse/components/BrowseIcons.kt b/app/src/main/java/eu/kanade/presentation/browse/components/BrowseIcons.kt index 1b03232578..0cd3661e72 100644 --- a/app/src/main/java/eu/kanade/presentation/browse/components/BrowseIcons.kt +++ b/app/src/main/java/eu/kanade/presentation/browse/components/BrowseIcons.kt @@ -6,22 +6,26 @@ import androidx.compose.foundation.layout.aspectRatio import androidx.compose.foundation.layout.height import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.runtime.Composable +import androidx.compose.runtime.State import androidx.compose.runtime.getValue +import androidx.compose.runtime.produceState import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.ImageBitmap +import androidx.compose.ui.graphics.asImageBitmap import androidx.compose.ui.graphics.painter.ColorPainter +import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.imageResource import androidx.compose.ui.res.painterResource import androidx.compose.ui.unit.dp +import androidx.core.graphics.drawable.toBitmap import coil.compose.AsyncImage import eu.kanade.domain.source.model.Source import eu.kanade.presentation.util.bitmapPainterResource import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.extension.model.Extension -import eu.kanade.tachiyomi.ui.browse.extension.Result -import eu.kanade.tachiyomi.ui.browse.extension.getIcon +import eu.kanade.tachiyomi.util.lang.withIOContext private val defaultModifier = Modifier .height(40.dp) @@ -89,3 +93,27 @@ fun ExtensionIcon( ) } } + +@Composable +private fun Extension.getIcon(): State> { + val context = LocalContext.current + return produceState>(initialValue = Result.Loading, this) { + withIOContext { + value = try { + Result.Success( + context.packageManager.getApplicationIcon(pkgName) + .toBitmap() + .asImageBitmap(), + ) + } catch (e: Exception) { + Result.Error + } + } + } +} + +sealed class Result { + object Loading : Result() + object Error : Result() + data class Success(val value: T) : Result() +} diff --git a/app/src/main/java/eu/kanade/presentation/components/SwipeRefresh.kt b/app/src/main/java/eu/kanade/presentation/components/SwipeRefresh.kt new file mode 100644 index 0000000000..b9a1bc2a9a --- /dev/null +++ b/app/src/main/java/eu/kanade/presentation/components/SwipeRefresh.kt @@ -0,0 +1,17 @@ +package eu.kanade.presentation.components + +import androidx.compose.material3.MaterialTheme +import androidx.compose.runtime.Composable +import androidx.compose.ui.unit.Dp +import com.google.accompanist.swiperefresh.SwipeRefreshState +import com.google.accompanist.swiperefresh.SwipeRefreshIndicator as AccompanistSwipeRefreshIndicator + +@Composable +fun SwipeRefreshIndicator(state: SwipeRefreshState, refreshTrigger: Dp) { + AccompanistSwipeRefreshIndicator( + state = state, + refreshTriggerDistance = refreshTrigger, + backgroundColor = MaterialTheme.colorScheme.primary, + contentColor = MaterialTheme.colorScheme.onPrimary, + ) +} diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionViewUtils.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionViewUtils.kt deleted file mode 100644 index e9f4b263f6..0000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionViewUtils.kt +++ /dev/null @@ -1,46 +0,0 @@ -package eu.kanade.tachiyomi.ui.browse.extension - -import android.content.Context -import android.content.pm.PackageManager -import android.graphics.drawable.Drawable -import androidx.compose.runtime.Composable -import androidx.compose.runtime.State -import androidx.compose.runtime.produceState -import androidx.compose.ui.graphics.ImageBitmap -import androidx.compose.ui.graphics.asImageBitmap -import androidx.compose.ui.platform.LocalContext -import androidx.core.graphics.drawable.toBitmap -import eu.kanade.tachiyomi.extension.model.Extension -import eu.kanade.tachiyomi.util.lang.withIOContext - -fun Extension.getApplicationIcon(context: Context): Drawable? { - return try { - context.packageManager.getApplicationIcon(pkgName) - } catch (e: PackageManager.NameNotFoundException) { - null - } -} - -@Composable -fun Extension.getIcon(): State> { - val context = LocalContext.current - return produceState>(initialValue = Result.Loading, this) { - withIOContext { - value = try { - Result.Success( - context.packageManager.getApplicationIcon(pkgName) - .toBitmap() - .asImageBitmap(), - ) - } catch (e: Exception) { - Result.Error - } - } - } -} - -sealed class Result { - object Loading : Result() - object Error : Result() - data class Success(val value: T) : Result() -} diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourceFilterController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourcesFilterController.kt similarity index 79% rename from app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourceFilterController.kt rename to app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourcesFilterController.kt index df3a96bb76..327bf1adb8 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourceFilterController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourcesFilterController.kt @@ -3,19 +3,19 @@ package eu.kanade.tachiyomi.ui.browse.source import androidx.compose.runtime.Composable import androidx.compose.ui.input.nestedscroll.NestedScrollConnection import eu.kanade.domain.source.model.Source -import eu.kanade.presentation.browse.SourceFilterScreen +import eu.kanade.presentation.browse.SourcesFilterScreen import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.ui.base.controller.ComposeController -class SourceFilterController : ComposeController() { +class SourceFilterController : ComposeController() { override fun getTitle() = resources?.getString(R.string.label_sources) - override fun createPresenter(): SourceFilterPresenter = SourceFilterPresenter() + override fun createPresenter(): SourcesFilterPresenter = SourcesFilterPresenter() @Composable override fun ComposeContent(nestedScrollInterop: NestedScrollConnection) { - SourceFilterScreen( + SourcesFilterScreen( nestedScrollInterop = nestedScrollInterop, presenter = presenter, onClickLang = { language -> diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourceFilterPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourcesFilterPresenter.kt similarity index 98% rename from app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourceFilterPresenter.kt rename to app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourcesFilterPresenter.kt index 42301b488d..d8032d15eb 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourceFilterPresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourcesFilterPresenter.kt @@ -16,7 +16,7 @@ import kotlinx.coroutines.flow.collectLatest import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get -class SourceFilterPresenter( +class SourcesFilterPresenter( private val getLanguagesWithSources: GetLanguagesWithSources = Injekt.get(), private val toggleSource: ToggleSource = Injekt.get(), private val toggleLanguage: ToggleLanguage = Injekt.get(),