diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/base/controller/ComposeController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/base/controller/ComposeController.kt index ac7ce1080e..f767020f69 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/base/controller/ComposeController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/base/controller/ComposeController.kt @@ -3,17 +3,12 @@ package eu.kanade.tachiyomi.ui.base.controller import android.os.Bundle import android.view.LayoutInflater import android.view.View -import androidx.compose.foundation.layout.consumeWindowInsets -import androidx.compose.material3.LocalContentColor -import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable -import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.ui.input.nestedscroll.NestedScrollConnection -import androidx.compose.ui.platform.ViewCompositionStrategy import androidx.compose.ui.platform.rememberNestedScrollInteropConnection -import eu.kanade.presentation.theme.TachiyomiTheme import eu.kanade.tachiyomi.databinding.ComposeControllerBinding import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter +import eu.kanade.tachiyomi.util.view.setComposeContent import nucleus.presenter.Presenter abstract class FullComposeController

>(bundle: Bundle? = null) : @@ -27,14 +22,8 @@ abstract class FullComposeController

>(bundle: Bundle? = null) : super.onViewCreated(view) binding.root.apply { - consumeWindowInsets = false - setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed) - setContent { - TachiyomiTheme { - CompositionLocalProvider(LocalContentColor provides MaterialTheme.colorScheme.onBackground) { - ComposeContent() - } - } + setComposeContent { + ComposeContent() } } } @@ -54,15 +43,9 @@ abstract class ComposeController

>(bundle: Bundle? = null) : super.onViewCreated(view) binding.root.apply { - consumeWindowInsets = false - setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed) - setContent { + setComposeContent { val nestedScrollInterop = rememberNestedScrollInteropConnection() - TachiyomiTheme { - CompositionLocalProvider(LocalContentColor provides MaterialTheme.colorScheme.onBackground) { - ComposeContent(nestedScrollInterop) - } - } + ComposeContent(nestedScrollInterop) } } } @@ -82,15 +65,9 @@ abstract class BasicComposeController : super.onViewCreated(view) binding.root.apply { - consumeWindowInsets = false - setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed) - setContent { + setComposeContent { val nestedScrollInterop = rememberNestedScrollInteropConnection() - TachiyomiTheme { - CompositionLocalProvider(LocalContentColor provides MaterialTheme.colorScheme.onBackground) { - ComposeContent(nestedScrollInterop) - } - } + ComposeContent(nestedScrollInterop) } } } @@ -107,15 +84,9 @@ abstract class SearchableComposeController

>(bundle: Bundle? super.onViewCreated(view) binding.root.apply { - consumeWindowInsets = false - setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed) - setContent { + setComposeContent { val nestedScrollInterop = rememberNestedScrollInteropConnection() - TachiyomiTheme { - CompositionLocalProvider(LocalContentColor provides MaterialTheme.colorScheme.onBackground) { - ComposeContent(nestedScrollInterop) - } - } + ComposeContent(nestedScrollInterop) } } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryAdapter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryAdapter.kt index 82617e3e31..cb50142c39 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryAdapter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryAdapter.kt @@ -3,17 +3,11 @@ package eu.kanade.tachiyomi.ui.library import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import androidx.compose.foundation.layout.consumeWindowInsets -import androidx.compose.material3.LocalContentColor -import androidx.compose.material3.LocalTextStyle -import androidx.compose.material3.MaterialTheme -import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateListOf import androidx.compose.ui.Modifier import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.platform.ComposeView -import androidx.compose.ui.platform.ViewCompositionStrategy import androidx.compose.ui.platform.rememberNestedScrollInteropConnection import com.google.accompanist.swiperefresh.SwipeRefresh import com.google.accompanist.swiperefresh.rememberSwipeRefreshState @@ -23,7 +17,6 @@ import eu.kanade.presentation.library.components.LibraryComfortableGrid import eu.kanade.presentation.library.components.LibraryCompactGrid import eu.kanade.presentation.library.components.LibraryCoverOnlyGrid import eu.kanade.presentation.library.components.LibraryList -import eu.kanade.presentation.theme.TachiyomiTheme import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.database.models.LibraryManga import eu.kanade.tachiyomi.data.library.LibraryUpdateService @@ -31,6 +24,7 @@ import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.databinding.ComposeControllerBinding import eu.kanade.tachiyomi.ui.library.setting.DisplayModeSetting import eu.kanade.tachiyomi.util.system.toast +import eu.kanade.tachiyomi.util.view.setComposeContent import eu.kanade.tachiyomi.widget.RecyclerViewPagerAdapter import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get @@ -101,80 +95,74 @@ class LibraryAdapter( */ override fun bindView(view: View, position: Int) { (view as ComposeView).apply { - consumeWindowInsets = false - setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed) - setContent { - TachiyomiTheme { - CompositionLocalProvider(LocalTextStyle provides MaterialTheme.typography.bodySmall, LocalContentColor provides MaterialTheme.colorScheme.onBackground) { - val nestedScrollInterop = rememberNestedScrollInteropConnection() + setComposeContent { + val nestedScrollInterop = rememberNestedScrollInteropConnection() - val category = presenter.categories[position] - val displayMode = presenter.getDisplayMode(index = position) - val mangaList by presenter.getMangaForCategory(categoryId = category.id) + val category = presenter.categories[position] + val displayMode = presenter.getDisplayMode(index = position) + val mangaList by presenter.getMangaForCategory(categoryId = category.id) - val onClickManga = { manga: LibraryManga -> - if (presenter.hasSelection().not()) { - onClickManga(manga) - } else { - presenter.toggleSelection(manga) - } + val onClickManga = { manga: LibraryManga -> + if (presenter.hasSelection().not()) { + onClickManga(manga) + } else { + presenter.toggleSelection(manga) + } + } + val onLongClickManga = { manga: LibraryManga -> + presenter.toggleSelection(manga) + } + + SwipeRefresh( + modifier = Modifier.nestedScroll(nestedScrollInterop), + state = rememberSwipeRefreshState(isRefreshing = false), + onRefresh = { + if (LibraryUpdateService.start(context, category)) { + context.toast(R.string.updating_category) } - val onLongClickManga = { manga: LibraryManga -> - presenter.toggleSelection(manga) + }, + indicator = { s, trigger -> + SwipeRefreshIndicator( + state = s, + refreshTriggerDistance = trigger, + ) + }, + ) { + when (displayMode) { + DisplayModeSetting.LIST -> { + LibraryList( + items = mangaList, + selection = presenter.selection, + onClick = onClickManga, + onLongClick = onLongClickManga, + ) } - - SwipeRefresh( - modifier = Modifier.nestedScroll(nestedScrollInterop), - state = rememberSwipeRefreshState(isRefreshing = false), - onRefresh = { - if (LibraryUpdateService.start(context, category)) { - context.toast(R.string.updating_category) - } - }, - indicator = { s, trigger -> - SwipeRefreshIndicator( - state = s, - refreshTriggerDistance = trigger, - ) - }, - ) { - when (displayMode) { - DisplayModeSetting.LIST -> { - LibraryList( - items = mangaList, - selection = presenter.selection, - onClick = onClickManga, - onLongClick = onLongClickManga, - ) - } - DisplayModeSetting.COMPACT_GRID -> { - LibraryCompactGrid( - items = mangaList, - columns = presenter.columns, - selection = presenter.selection, - onClick = onClickManga, - onLongClick = onLongClickManga, - ) - } - DisplayModeSetting.COMFORTABLE_GRID -> { - LibraryComfortableGrid( - items = mangaList, - columns = presenter.columns, - selection = presenter.selection, - onClick = onClickManga, - onLongClick = onLongClickManga, - ) - } - DisplayModeSetting.COVER_ONLY_GRID -> { - LibraryCoverOnlyGrid( - items = mangaList, - columns = presenter.columns, - selection = presenter.selection, - onClick = onClickManga, - onLongClick = onLongClickManga, - ) - } - } + DisplayModeSetting.COMPACT_GRID -> { + LibraryCompactGrid( + items = mangaList, + columns = presenter.columns, + selection = presenter.selection, + onClick = onClickManga, + onLongClick = onLongClickManga, + ) + } + DisplayModeSetting.COMFORTABLE_GRID -> { + LibraryComfortableGrid( + items = mangaList, + columns = presenter.columns, + selection = presenter.selection, + onClick = onClickManga, + onLongClick = onLongClickManga, + ) + } + DisplayModeSetting.COVER_ONLY_GRID -> { + LibraryCoverOnlyGrid( + items = mangaList, + columns = presenter.columns, + selection = presenter.selection, + onClick = onClickManga, + onLongClick = onLongClickManga, + ) } } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/track/BaseOAuthLoginActivity.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/track/BaseOAuthLoginActivity.kt index 6f85bb498b..ada06753d9 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/track/BaseOAuthLoginActivity.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/track/BaseOAuthLoginActivity.kt @@ -3,12 +3,11 @@ package eu.kanade.tachiyomi.ui.setting.track import android.content.Intent import android.net.Uri import android.os.Bundle -import androidx.activity.compose.setContent import eu.kanade.presentation.components.LoadingScreen -import eu.kanade.presentation.theme.TachiyomiTheme import eu.kanade.tachiyomi.data.track.TrackManager import eu.kanade.tachiyomi.ui.base.activity.BaseActivity import eu.kanade.tachiyomi.ui.main.MainActivity +import eu.kanade.tachiyomi.util.view.setComposeContent import uy.kohesive.injekt.injectLazy abstract class BaseOAuthLoginActivity : BaseActivity() { @@ -20,10 +19,8 @@ abstract class BaseOAuthLoginActivity : BaseActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - setContent { - TachiyomiTheme { - LoadingScreen() - } + setComposeContent { + LoadingScreen() } handleResult(intent.data) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/webview/WebViewActivity.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/webview/WebViewActivity.kt index cc0db61d22..571587e03e 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/webview/WebViewActivity.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/webview/WebViewActivity.kt @@ -4,8 +4,6 @@ import android.content.Context import android.content.Intent import android.os.Bundle import android.widget.Toast -import androidx.activity.compose.setContent -import eu.kanade.presentation.theme.TachiyomiTheme import eu.kanade.presentation.webview.WebViewScreen import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.network.NetworkHelper @@ -16,6 +14,7 @@ import eu.kanade.tachiyomi.util.system.WebViewUtil import eu.kanade.tachiyomi.util.system.logcat import eu.kanade.tachiyomi.util.system.openInBrowser import eu.kanade.tachiyomi.util.system.toast +import eu.kanade.tachiyomi.util.view.setComposeContent import okhttp3.HttpUrl.Companion.toHttpUrl import uy.kohesive.injekt.injectLazy @@ -44,18 +43,16 @@ class WebViewActivity : BaseActivity() { headers = source.headers.toMultimap().mapValues { it.value.getOrNull(0) ?: "" }.toMutableMap() } - setContent { - TachiyomiTheme { - WebViewScreen( - onUp = { finish() }, - initialTitle = intent.extras?.getString(TITLE_KEY), - url = url, - headers = headers, - onShare = this::shareWebpage, - onOpenInBrowser = this::openInBrowser, - onClearCookies = this::clearCookies, - ) - } + setComposeContent { + WebViewScreen( + onUp = { finish() }, + initialTitle = intent.extras?.getString(TITLE_KEY), + url = url, + headers = headers, + onShare = this::shareWebpage, + onOpenInBrowser = this::openInBrowser, + onClearCookies = this::clearCookies, + ) } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/util/view/ViewExtensions.kt b/app/src/main/java/eu/kanade/tachiyomi/util/view/ViewExtensions.kt index f22faf8b7c..27e123a28e 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/util/view/ViewExtensions.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/util/view/ViewExtensions.kt @@ -5,42 +5,71 @@ package eu.kanade.tachiyomi.util.view import android.annotation.SuppressLint import android.content.Context import android.content.res.Resources -import android.graphics.Point import android.graphics.Rect import android.graphics.drawable.Drawable -import android.text.TextUtils import android.view.Gravity import android.view.Menu import android.view.MenuItem import android.view.View import android.view.ViewGroup -import android.widget.TextView +import androidx.activity.ComponentActivity +import androidx.activity.compose.setContent import androidx.annotation.MenuRes import androidx.annotation.StringRes import androidx.appcompat.content.res.AppCompatResources import androidx.appcompat.view.menu.MenuBuilder import androidx.appcompat.widget.PopupMenu import androidx.appcompat.widget.TooltipCompat +import androidx.compose.foundation.layout.consumeWindowInsets +import androidx.compose.material3.LocalContentColor +import androidx.compose.material3.LocalTextStyle +import androidx.compose.material3.MaterialTheme +import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionContext +import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.ui.platform.ComposeView +import androidx.compose.ui.platform.ViewCompositionStrategy import androidx.core.view.children import androidx.core.view.descendants import androidx.core.view.forEach import androidx.recyclerview.widget.RecyclerView -import androidx.viewpager.widget.ViewPager -import com.google.android.material.chip.Chip -import com.google.android.material.chip.ChipGroup import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton import com.google.android.material.shape.MaterialShapeDrawable import com.google.android.material.snackbar.Snackbar +import eu.kanade.presentation.theme.TachiyomiTheme import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.util.system.getResourceColor -/** - * Returns coordinates of view. - * Used for animation - * - * @return coordinates of view - */ -fun View.getCoordinates() = Point((left + right) / 2, (top + bottom) / 2) +inline fun ComposeView.setComposeContent(crossinline content: @Composable () -> Unit) { + consumeWindowInsets = false + setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed) + setContent { + TachiyomiTheme { + CompositionLocalProvider( + LocalTextStyle provides MaterialTheme.typography.bodySmall, + LocalContentColor provides MaterialTheme.colorScheme.onBackground, + ) { + content() + } + } + } +} + +inline fun ComponentActivity.setComposeContent( + parent: CompositionContext? = null, + crossinline content: @Composable () -> Unit, +) { + setContent(parent) { + TachiyomiTheme { + CompositionLocalProvider( + LocalTextStyle provides MaterialTheme.typography.bodySmall, + LocalContentColor provides MaterialTheme.colorScheme.onBackground, + ) { + content() + } + } + } +} /** * Shows a snackbar in this view. @@ -164,39 +193,6 @@ inline fun ExtendedFloatingActionButton.shrinkOnScroll(recycler: RecyclerView): return listener } -/** - * Replaces chips in a ChipGroup. - * - * @param items List of strings that are shown as individual chips. - * @param onClick Optional on click listener for each chip. - * @param onLongClick Optional on long click listener for each chip. - */ -inline fun ChipGroup.setChips( - items: List?, - noinline onClick: ((item: String) -> Unit)? = null, - noinline onLongClick: ((item: String) -> Unit)? = null, -) { - removeAllViews() - - items?.forEach { item -> - val chip = Chip(context).apply { - text = item - if (onClick != null) { setOnClickListener { onClick(item) } } - if (onLongClick != null) { setOnLongClickListener { onLongClick(item); true } } - } - - addView(chip) - } -} - -/** - * Sets TextView max lines dynamically. Can only be called when the view is already laid out. - */ -inline fun TextView.setMaxLinesAndEllipsize(_ellipsize: TextUtils.TruncateAt = TextUtils.TruncateAt.END) = post { - maxLines = (measuredHeight - paddingTop - paddingBottom) / lineHeight - ellipsize = _ellipsize -} - /** * Callback will be run immediately when no animation running */ @@ -228,29 +224,6 @@ inline fun ViewGroup.findDescendant(): T? { return descendants.find { it is T } as? T } -/** - * Returns the active child view of a ViewPager according to the LayoutParams - */ -fun ViewPager.getActivePageView(): View? { - if (null == adapter || adapter?.count == 0 || childCount == 0) { - return null - } - - val positionField = ViewPager.LayoutParams::class.java.getDeclaredField("position") - positionField.isAccessible = true - return children.find { child -> - val layoutParams = child.layoutParams as ViewPager.LayoutParams - try { - if (!layoutParams.isDecor && positionField.getInt(layoutParams) == currentItem) { - return@find true - } - } catch (e: NoSuchFieldException) { - } catch (e: IllegalAccessException) { - } - false - } -} - /** * Returns a deep copy of the provided [Drawable] */ diff --git a/app/src/main/res/layout/chapters_item.xml b/app/src/main/res/layout/chapters_item.xml deleted file mode 100644 index cad01eb1e9..0000000000 --- a/app/src/main/res/layout/chapters_item.xml +++ /dev/null @@ -1,66 +0,0 @@ - - - - - - - - - - - - diff --git a/app/src/main/res/layout/library_controller.xml b/app/src/main/res/layout/library_controller.xml index 7b60d7af75..b1038fbb09 100644 --- a/app/src/main/res/layout/library_controller.xml +++ b/app/src/main/res/layout/library_controller.xml @@ -1,6 +1,5 @@