Drop deprecated Accompanist libraries (#500)

* Migrate XML themes to Compose

* Vendor Accompanist WebView
This commit is contained in:
FooIbar authored and GitHub committed 2023-12-14 18:04:51 +08:00
1 parent b02fb2d1d7
commit b51120e914
13 files changed
+721 -58

No files matched your search

-2
View File
@@ -233,8 +233,6 @@ dependencies {
implementation(libs.androidx.work.runtime)
implementation(libs.photoview) // Dead Dependency
implementation(libs.directionalviewpager) // Dead Dependency
// https://github.com/google/accompanist/releases
implementation(libs.bundles.accompanist)
implementation(libs.material)
implementation(libs.bundles.splitties)
@@ -0,0 +1,653 @@
/*
* 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.web
import android.content.Context
import android.graphics.Bitmap
import android.os.Bundle
import android.view.ViewGroup.LayoutParams
import android.webkit.WebChromeClient
import android.webkit.WebResourceError
import android.webkit.WebResourceRequest
import android.webkit.WebView
import android.webkit.WebViewClient
import android.widget.FrameLayout
import androidx.activity.compose.BackHandler
import androidx.compose.foundation.layout.BoxWithConstraints
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Immutable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.Stable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.runtime.snapshotFlow
import androidx.compose.runtime.snapshots.SnapshotStateList
import androidx.compose.ui.Modifier
import androidx.compose.ui.viewinterop.AndroidView
import com.google.accompanist.web.LoadingState.Finished
import com.google.accompanist.web.LoadingState.Loading
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
/**
* A wrapper around the Android View WebView to provide a basic WebView composable.
*
* If you require more customisation you are most likely better rolling your own and using this
* wrapper as an example.
*
* The WebView attempts to set the layoutParams based on the Compose modifier passed in. If it
* is incorrectly sizing, use the layoutParams composable function instead.
*
* @param state The webview state holder where the Uri to load is defined.
* @param modifier A compose modifier
* @param captureBackPresses Set to true to have this Composable capture back presses and navigate
* the WebView back.
* @param navigator An optional navigator object that can be used to control the WebView's
* navigation from outside the composable.
* @param onCreated Called when the WebView is first created, this can be used to set additional
* settings on the WebView. WebChromeClient and WebViewClient should not be set here as they will be
* subsequently overwritten after this lambda is called.
* @param onDispose Called when the WebView is destroyed. Provides a bundle which can be saved
* if you need to save and restore state in this WebView.
* @param client Provides access to WebViewClient via subclassing
* @param chromeClient Provides access to WebChromeClient via subclassing
* @param factory An optional WebView factory for using a custom subclass of WebView
*/
@Composable
fun WebView(
state: WebViewState,
modifier: Modifier = Modifier,
captureBackPresses: Boolean = true,
navigator: WebViewNavigator = rememberWebViewNavigator(),
onCreated: (WebView) -> Unit = {},
onDispose: (WebView) -> Unit = {},
client: AccompanistWebViewClient = remember { AccompanistWebViewClient() },
chromeClient: AccompanistWebChromeClient = remember { AccompanistWebChromeClient() },
factory: ((Context) -> WebView)? = null,
) {
BoxWithConstraints(modifier) {
// WebView changes it's layout strategy based on
// it's layoutParams. We convert from Compose Modifier to
// layout params here.
val width =
if (constraints.hasFixedWidth) {
LayoutParams.MATCH_PARENT
} else {
LayoutParams.WRAP_CONTENT
}
val height =
if (constraints.hasFixedHeight) {
LayoutParams.MATCH_PARENT
} else {
LayoutParams.WRAP_CONTENT
}
val layoutParams = FrameLayout.LayoutParams(
width,
height,
)
WebView(
state,
layoutParams,
Modifier,
captureBackPresses,
navigator,
onCreated,
onDispose,
client,
chromeClient,
factory,
)
}
}
/**
* A wrapper around the Android View WebView to provide a basic WebView composable.
*
* If you require more customisation you are most likely better rolling your own and using this
* wrapper as an example.
*
* The WebView attempts to set the layoutParams based on the Compose modifier passed in. If it
* is incorrectly sizing, use the layoutParams composable function instead.
*
* @param state The webview state holder where the Uri to load is defined.
* @param layoutParams A FrameLayout.LayoutParams object to custom size the underlying WebView.
* @param modifier A compose modifier
* @param captureBackPresses Set to true to have this Composable capture back presses and navigate
* the WebView back.
* @param navigator An optional navigator object that can be used to control the WebView's
* navigation from outside the composable.
* @param onCreated Called when the WebView is first created, this can be used to set additional
* settings on the WebView. WebChromeClient and WebViewClient should not be set here as they will be
* subsequently overwritten after this lambda is called.
* @param onDispose Called when the WebView is destroyed. Provides a bundle which can be saved
* if you need to save and restore state in this WebView.
* @param client Provides access to WebViewClient via subclassing
* @param chromeClient Provides access to WebChromeClient via subclassing
* @param factory An optional WebView factory for using a custom subclass of WebView
*/
@Composable
fun WebView(
state: WebViewState,
layoutParams: FrameLayout.LayoutParams,
modifier: Modifier = Modifier,
captureBackPresses: Boolean = true,
navigator: WebViewNavigator = rememberWebViewNavigator(),
onCreated: (WebView) -> Unit = {},
onDispose: (WebView) -> Unit = {},
client: AccompanistWebViewClient = remember { AccompanistWebViewClient() },
chromeClient: AccompanistWebChromeClient = remember { AccompanistWebChromeClient() },
factory: ((Context) -> WebView)? = null,
) {
val webView = state.webView
BackHandler(captureBackPresses && navigator.canGoBack) {
webView?.goBack()
}
webView?.let { wv ->
LaunchedEffect(wv, navigator) {
with(navigator) {
wv.handleNavigationEvents()
}
}
LaunchedEffect(wv, state) {
snapshotFlow { state.content }.collect { content ->
when (content) {
is WebContent.Url -> {
wv.loadUrl(content.url, content.additionalHttpHeaders)
}
is WebContent.Data -> {
wv.loadDataWithBaseURL(
content.baseUrl,
content.data,
content.mimeType,
content.encoding,
content.historyUrl,
)
}
is WebContent.Post -> {
wv.postUrl(
content.url,
content.postData,
)
}
is WebContent.NavigatorOnly -> {
// NO-OP
}
}
}
}
}
// Set the state of the client and chrome client
// This is done internally to ensure they always are the same instance as the
// parent Web composable
client.state = state
client.navigator = navigator
chromeClient.state = state
AndroidView(
factory = { context ->
(factory?.invoke(context) ?: WebView(context)).apply {
onCreated(this)
this.layoutParams = layoutParams
state.viewState?.let {
this.restoreState(it)
}
webChromeClient = chromeClient
webViewClient = client
}.also { state.webView = it }
},
modifier = modifier,
onRelease = {
onDispose(it)
},
)
}
/**
* AccompanistWebViewClient
*
* A parent class implementation of WebViewClient that can be subclassed to add custom behaviour.
*
* As Accompanist Web needs to set its own web client to function, it provides this intermediary
* class that can be overriden if further custom behaviour is required.
*/
open class AccompanistWebViewClient : WebViewClient() {
open lateinit var state: WebViewState
internal set
open lateinit var navigator: WebViewNavigator
internal set
override fun onPageStarted(view: WebView, url: String?, favicon: Bitmap?) {
super.onPageStarted(view, url, favicon)
state.loadingState = Loading(0.0f)
state.errorsForCurrentRequest.clear()
state.pageTitle = null
state.pageIcon = null
state.lastLoadedUrl = url
}
override fun onPageFinished(view: WebView, url: String?) {
super.onPageFinished(view, url)
state.loadingState = Finished
}
override fun doUpdateVisitedHistory(view: WebView, url: String?, isReload: Boolean) {
super.doUpdateVisitedHistory(view, url, isReload)
navigator.canGoBack = view.canGoBack()
navigator.canGoForward = view.canGoForward()
}
override fun onReceivedError(
view: WebView,
request: WebResourceRequest?,
error: WebResourceError?,
) {
super.onReceivedError(view, request, error)
if (error != null) {
state.errorsForCurrentRequest.add(WebViewError(request, error))
}
}
}
/**
* AccompanistWebChromeClient
*
* A parent class implementation of WebChromeClient that can be subclassed to add custom behaviour.
*
* As Accompanist Web needs to set its own web client to function, it provides this intermediary
* class that can be overriden if further custom behaviour is required.
*/
open class AccompanistWebChromeClient : WebChromeClient() {
open lateinit var state: WebViewState
internal set
override fun onReceivedTitle(view: WebView, title: String?) {
super.onReceivedTitle(view, title)
state.pageTitle = title
}
override fun onReceivedIcon(view: WebView, icon: Bitmap?) {
super.onReceivedIcon(view, icon)
state.pageIcon = icon
}
override fun onProgressChanged(view: WebView, newProgress: Int) {
super.onProgressChanged(view, newProgress)
if (state.loadingState is Finished) return
state.loadingState = Loading(newProgress / 100.0f)
}
}
sealed class WebContent {
data class Url(
val url: String,
val additionalHttpHeaders: Map<String, String> = emptyMap(),
) : WebContent()
data class Data(
val data: String,
val baseUrl: String? = null,
val encoding: String = "utf-8",
val mimeType: String? = null,
val historyUrl: String? = null,
) : WebContent()
data class Post(
val url: String,
val postData: ByteArray,
) : WebContent() {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as Post
if (url != other.url) return false
if (!postData.contentEquals(other.postData)) return false
return true
}
override fun hashCode(): Int {
var result = url.hashCode()
result = 31 * result + postData.contentHashCode()
return result
}
}
data object NavigatorOnly : WebContent()
}
/**
* Sealed class for constraining possible loading states.
* See [Loading] and [Finished].
*/
sealed class LoadingState {
/**
* Describes a WebView that has not yet loaded for the first time.
*/
data object Initializing : LoadingState()
/**
* Describes a webview between `onPageStarted` and `onPageFinished` events, contains a
* [progress] property which is updated by the webview.
*/
data class Loading(val progress: Float) : LoadingState()
/**
* Describes a webview that has finished loading content.
*/
data object Finished : LoadingState()
}
/**
* A state holder to hold the state for the WebView. In most cases this will be remembered
* using the rememberWebViewState(uri) function.
*/
@Stable
class WebViewState(webContent: WebContent) {
var lastLoadedUrl: String? by mutableStateOf(null)
internal set
/**
* The content being loaded by the WebView
*/
var content: WebContent by mutableStateOf(webContent)
/**
* Whether the WebView is currently [LoadingState.Loading] data in its main frame (along with
* progress) or the data loading has [LoadingState.Finished]. See [LoadingState]
*/
var loadingState: LoadingState by mutableStateOf(LoadingState.Initializing)
internal set
/**
* Whether the webview is currently loading data in its main frame
*/
val isLoading: Boolean
get() = loadingState !is Finished
/**
* The title received from the loaded content of the current page
*/
var pageTitle: String? by mutableStateOf(null)
internal set
/**
* the favicon received from the loaded content of the current page
*/
var pageIcon: Bitmap? by mutableStateOf(null)
internal set
/**
* A list for errors captured in the last load. Reset when a new page is loaded.
* Errors could be from any resource (iframe, image, etc.), not just for the main page.
* For more fine grained control use the OnError callback of the WebView.
*/
val errorsForCurrentRequest: SnapshotStateList<WebViewError> = mutableStateListOf()
/**
* The saved view state from when the view was destroyed last. To restore state,
* use the navigator and only call loadUrl if the bundle is null.
* See WebViewSaveStateSample.
*/
var viewState: Bundle? = null
internal set
// We need access to this in the state saver. An internal DisposableEffect or AndroidView
// onDestroy is called after the state saver and so can't be used.
internal var webView by mutableStateOf<WebView?>(null)
}
/**
* Allows control over the navigation of a WebView from outside the composable. E.g. for performing
* a back navigation in response to the user clicking the "up" button in a TopAppBar.
*
* @see [rememberWebViewNavigator]
*/
@Stable
class WebViewNavigator(private val coroutineScope: CoroutineScope) {
private sealed interface NavigationEvent {
data object Back : NavigationEvent
data object Forward : NavigationEvent
data object Reload : NavigationEvent
data object StopLoading : NavigationEvent
data class LoadUrl(
val url: String,
val additionalHttpHeaders: Map<String, String> = emptyMap(),
) : NavigationEvent
data class LoadHtml(
val html: String,
val baseUrl: String? = null,
val mimeType: String? = null,
val encoding: String? = "utf-8",
val historyUrl: String? = null,
) : NavigationEvent
data class PostUrl(
val url: String,
val postData: ByteArray,
) : NavigationEvent {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as PostUrl
if (url != other.url) return false
if (!postData.contentEquals(other.postData)) return false
return true
}
override fun hashCode(): Int {
var result = url.hashCode()
result = 31 * result + postData.contentHashCode()
return result
}
}
}
private val navigationEvents: MutableSharedFlow<NavigationEvent> = MutableSharedFlow(replay = 1)
// Use Dispatchers.Main to ensure that the webview methods are called on UI thread
internal suspend fun WebView.handleNavigationEvents(): Nothing = withContext(Dispatchers.Main) {
navigationEvents.collect { event ->
when (event) {
is NavigationEvent.Back -> goBack()
is NavigationEvent.Forward -> goForward()
is NavigationEvent.Reload -> reload()
is NavigationEvent.StopLoading -> stopLoading()
is NavigationEvent.LoadHtml -> loadDataWithBaseURL(
event.baseUrl,
event.html,
event.mimeType,
event.encoding,
event.historyUrl,
)
is NavigationEvent.LoadUrl -> {
loadUrl(event.url, event.additionalHttpHeaders)
}
is NavigationEvent.PostUrl -> {
postUrl(event.url, event.postData)
}
}
}
}
/**
* True when the web view is able to navigate backwards, false otherwise.
*/
var canGoBack: Boolean by mutableStateOf(false)
internal set
/**
* True when the web view is able to navigate forwards, false otherwise.
*/
var canGoForward: Boolean by mutableStateOf(false)
internal set
fun loadUrl(url: String, additionalHttpHeaders: Map<String, String> = emptyMap()) {
coroutineScope.launch {
navigationEvents.emit(
NavigationEvent.LoadUrl(
url,
additionalHttpHeaders,
),
)
}
}
fun loadHtml(
html: String,
baseUrl: String? = null,
mimeType: String? = null,
encoding: String? = "utf-8",
historyUrl: String? = null,
) {
coroutineScope.launch {
navigationEvents.emit(
NavigationEvent.LoadHtml(
html,
baseUrl,
mimeType,
encoding,
historyUrl,
),
)
}
}
fun postUrl(
url: String,
postData: ByteArray,
) {
coroutineScope.launch {
navigationEvents.emit(
NavigationEvent.PostUrl(
url,
postData,
),
)
}
}
/**
* Navigates the webview back to the previous page.
*/
fun navigateBack() {
coroutineScope.launch { navigationEvents.emit(NavigationEvent.Back) }
}
/**
* Navigates the webview forward after going back from a page.
*/
fun navigateForward() {
coroutineScope.launch { navigationEvents.emit(NavigationEvent.Forward) }
}
/**
* Reloads the current page in the webview.
*/
fun reload() {
coroutineScope.launch { navigationEvents.emit(NavigationEvent.Reload) }
}
/**
* Stops the current page load (if one is loading).
*/
fun stopLoading() {
coroutineScope.launch { navigationEvents.emit(NavigationEvent.StopLoading) }
}
}
/**
* Creates and remembers a [WebViewNavigator] using the default [CoroutineScope] or a provided
* override.
*/
@Composable
fun rememberWebViewNavigator(
coroutineScope: CoroutineScope = rememberCoroutineScope(),
): WebViewNavigator = remember(coroutineScope) { WebViewNavigator(coroutineScope) }
/**
* A wrapper class to hold errors from the WebView.
*/
@Immutable
data class WebViewError(
/**
* The request the error came from.
*/
val request: WebResourceRequest?,
/**
* The error that was reported.
*/
val error: WebResourceError,
)
/**
* Creates a WebView state that is remembered across Compositions.
*
* @param url The url to load in the WebView
* @param additionalHttpHeaders Optional, additional HTTP headers that are passed to [WebView.loadUrl].
* Note that these headers are used for all subsequent requests of the WebView.
*/
@Composable
fun rememberWebViewState(
url: String,
additionalHttpHeaders: Map<String, String> = emptyMap(),
): WebViewState =
// Rather than using .apply {} here we will recreate the state, this prevents
// a recomposition loop when the webview updates the url itself.
remember {
WebViewState(
WebContent.Url(
url = url,
additionalHttpHeaders = additionalHttpHeaders,
),
)
}.apply {
this.content = WebContent.Url(
url = url,
additionalHttpHeaders = additionalHttpHeaders,
)
}
@@ -110,6 +110,7 @@ object Settings : DataStorePreferences(null) {
val languageFilter = intPref("language_filter", -1)
val meteredNetworkWarning = boolPref("cellular_network_warning", false)
val predictiveNavAnim = boolPref("predictive_nav_anim", true)
val blackDarkTheme = boolPref("black_dark_theme", false)
val needSignInFlow: Flow<Boolean>
var downloadScheme by stringOrNullPref("image_scheme", null)
@@ -146,7 +147,6 @@ object Settings : DataStorePreferences(null) {
var security by boolPref("require_unlock", false)
var removeImageFiles by boolPref("include_pic", true)
var needSignIn by boolPref("need_sign_in", true).also { needSignInFlow = it.valueFlow() }
var blackDarkTheme by boolPref("black_dark_theme", false).observed { updateWhenAmoledModeChanges() }
var harmonizeCategoryColor by boolPref("harmonize_category_color", true)
var preloadThumbAggressively by boolPref("preload_thumb_aggressively", false)
var downloadOriginImage by boolPref("download_origin_image", false)
@@ -2,7 +2,6 @@ package com.hippo.ehviewer
import android.app.UiModeManager
import androidx.appcompat.app.AppCompatDelegate
import androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY
import androidx.core.os.LocaleListCompat
import com.hippo.ehviewer.client.EhCookieStore
import com.hippo.ehviewer.client.EhEngine
@@ -59,14 +58,6 @@ fun updateWhenThemeChanges() {
}
}
fun updateWhenAmoledModeChanges() {
collectScope.launch {
delay(100) // Avoid recompose being cancelled
AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_AUTO_BATTERY) // Trigger onNightModeChanged
AppCompatDelegate.setDefaultNightMode(Settings.theme)
}
}
fun updateWhenRequestNewsChanges() {
updateDailyCheckWork(appCtx)
}
@@ -15,32 +15,14 @@
*/
package com.hippo.ehviewer.ui
import android.content.res.Resources.Theme
import android.os.Bundle
import androidx.activity.enableEdgeToEdge
import androidx.annotation.StyleRes
import androidx.appcompat.app.AppCompatActivity
import androidx.navigation.ActivityNavigator
import com.hippo.ehviewer.R
import com.hippo.ehviewer.Settings
import eu.kanade.tachiyomi.util.system.isNightMode
import eu.kanade.tachiyomi.util.view.setSecureScreen
abstract class EhActivity : AppCompatActivity() {
@StyleRes
fun getThemeStyleRes(): Int {
return if (Settings.blackDarkTheme && isNightMode()) R.style.ThemeOverlay_Black else R.style.ThemeOverlay
}
override fun onApplyThemeResource(theme: Theme, resid: Int, first: Boolean) {
super.onApplyThemeResource(theme, resid, first)
theme.applyStyle(getThemeStyleRes(), true)
}
override fun onNightModeChanged(mode: Int) {
theme.applyStyle(getThemeStyleRes(), true)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
@@ -5,34 +5,40 @@ import androidx.activity.compose.setContent
import androidx.compose.animation.core.tween
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.material3.LocalContentColor
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.remember
import androidx.compose.ui.platform.ComposeView
import com.google.accompanist.themeadapter.material3.Mdc3Theme
import com.hippo.ehviewer.ui.theme.EhTheme
import com.hippo.ehviewer.ui.tools.DialogState
import com.hippo.ehviewer.ui.tools.LocalDialogState
import com.hippo.ehviewer.ui.tools.ProvideVectorPainterCache
import com.ramcosta.composedestinations.animations.defaults.RootNavGraphDefaultAnimations
// To make sure compose theme and legacy view theme are in sync, we only use Mdc3Theme
inline fun ComposeView.setMD3Content(crossinline content: @Composable () -> Unit) = setContent {
Mdc3Theme {
EhTheme {
val dialogState = remember { DialogState() }
dialogState.Intercept()
CompositionLocalProvider(LocalDialogState provides dialogState) {
CompositionLocalProvider(
LocalDialogState provides dialogState,
LocalContentColor provides MaterialTheme.colorScheme.onBackground,
) {
content()
}
}
}
inline fun ComponentActivity.setMD3Content(crossinline content: @Composable () -> Unit) = setContent {
Mdc3Theme {
EhTheme {
ProvideVectorPainterCache {
val dialogState = remember { DialogState() }
dialogState.Intercept()
CompositionLocalProvider(LocalDialogState provides dialogState) {
CompositionLocalProvider(
LocalDialogState provides dialogState,
LocalContentColor provides MaterialTheme.colorScheme.onBackground,
) {
content()
}
}
@@ -218,7 +218,7 @@ fun EhScreen(navigator: DestinationsNavigator) {
)
SwitchPreference(
title = stringResource(id = R.string.black_dark_theme),
value = Settings::blackDarkTheme,
value = Settings.blackDarkTheme::value,
)
SwitchPreference(
title = stringResource(id = R.string.harmonize_category_color),
@@ -0,0 +1,51 @@
package com.hippo.ehviewer.ui.theme
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.darkColorScheme
import androidx.compose.material3.dynamicDarkColorScheme
import androidx.compose.material3.dynamicLightColorScheme
import androidx.compose.material3.lightColorScheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import com.hippo.ehviewer.Settings
import com.hippo.ehviewer.collectAsState
import com.hippo.ehviewer.util.isAtLeastS
@Composable
fun EhTheme(content: @Composable () -> Unit) {
val useDarkTheme = isSystemInDarkTheme()
val amoled by Settings.blackDarkTheme.collectAsState()
val context = LocalContext.current
val colors = if (useDarkTheme) {
if (isAtLeastS) {
dynamicDarkColorScheme(context)
} else {
darkColorScheme()
}.let {
if (amoled) {
it.copy(
surface = Color.Black,
onSurface = Color.White,
background = Color.Black,
onBackground = Color.White,
)
} else {
it
}
}
} else {
if (isAtLeastS) {
dynamicLightColorScheme(context)
} else {
lightColorScheme()
}
}
MaterialTheme(
colorScheme = colors,
content = content,
)
}
@@ -43,7 +43,6 @@ import androidx.activity.result.contract.ActivityResultContracts.CreateDocument
import androidx.activity.viewModels
import androidx.annotation.ChecksSdkIntAtLeast
import androidx.annotation.RequiresApi
import androidx.compose.material3.LocalContentColor
import androidx.compose.material3.LocalTextStyle
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.ModalBottomSheetFix
@@ -666,7 +665,6 @@ class ReaderActivity : EhActivity() {
binding.pageNumber.setMD3Content {
CompositionLocalProvider(
LocalTextStyle provides MaterialTheme.typography.bodySmall,
LocalContentColor provides MaterialTheme.colorScheme.onBackground,
) {
PageIndicatorText(
currentPage = currentPage,
@@ -14,7 +14,7 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.platform.AbstractComposeView
import androidx.compose.ui.platform.ViewCompositionStrategy
import androidx.core.view.isVisible
import com.google.accompanist.themeadapter.material3.Mdc3Theme
import com.hippo.ehviewer.ui.theme.EhTheme
class ReaderProgressIndicator @JvmOverloads constructor(
context: Context,
@@ -32,7 +32,7 @@ class ReaderProgressIndicator @JvmOverloads constructor(
@Composable
override fun Content() {
Mdc3Theme {
EhTheme {
if (visible) CombinedCircularProgressIndicator(progress = progress)
}
}
@@ -17,7 +17,6 @@ import androidx.core.graphics.blue
import androidx.core.graphics.green
import androidx.core.graphics.red
import com.hippo.ehviewer.R
import com.hippo.ehviewer.Settings as AppSettings
import eu.kanade.tachiyomi.ui.reader.setting.ReaderPreferences
import kotlin.math.roundToInt
import splitties.systemservices.windowManager
@@ -122,8 +121,6 @@ fun Context.createReaderThemeContext(): Context {
val wrappedContext = ContextThemeWrapper(this, R.style.AppTheme)
wrappedContext.applyOverrideConfiguration(overrideConf)
val resId = if (AppSettings.blackDarkTheme && isDarkBackground) R.style.ThemeOverlay_Black else R.style.ThemeOverlay
wrappedContext.theme.applyStyle(resId, true)
return wrappedContext
}
return this
-8
View File
@@ -25,14 +25,6 @@
<item name="materialAlertDialogTheme">@style/MaterialAlertDialogTheme</item>
</style>
<style name="ThemeOverlay" />
<style name="ThemeOverlay.Black">
<item name="colorSurface">@android:color/black</item>
<item name="colorPrimaryDark">@android:color/black</item>
<item name="android:colorBackground">@android:color/black</item>
</style>
<style name="RatingBarTheme" parent="ThemeOverlay.Material3">
<item name="colorControlNormal">@color/yellow_800</item>
<item name="colorControlActivated">@color/yellow_800</item>
-5
View File
@@ -20,7 +20,6 @@ coil = "3.0.0-SNAPSHOT"
compose-bom = "2023.12.00-alpha03"
compose-compiler = "1.5.5-dev-k2.0.0-Beta1-06b8ae672a4"
compose-destinations = "1.9.55"
google-accompanist = "0.32.0"
google-android-material = "1.12.0-alpha02"
kotlin = "2.0.0-Beta1"
kotlinx-coroutines = "1.7.3"
@@ -35,9 +34,6 @@ splitties = "3.0.0"
[libraries]
aboutlibraries-core = { module = "com.mikepenz:aboutlibraries-core", version.ref = "aboutlibraries" }
accompanist-themeadapter-material3 = { module = "com.google.accompanist:accompanist-themeadapter-material3", version.ref = "google-accompanist" }
accompanist-webview = { module = "com.google.accompanist:accompanist-webview", version.ref = "google-accompanist" }
androidx-activity-compose = { module = "androidx.activity:activity-compose", version.ref = "androidx-activity" }
androidx-appcompat = { module = "androidx.appcompat:appcompat", version.ref = "androidx-appcompat" }
androidx-biometric = { module = "androidx.biometric:biometric-ktx", version.ref = "androidx-biometric" }
@@ -117,7 +113,6 @@ splitties-preferences = { module = "com.louiscad.splitties:splitties-preferences
splitties-systemservices = { module = "com.louiscad.splitties:splitties-systemservices", version.ref = "splitties" }
[bundles]
accompanist = ["accompanist-themeadapter-material3", "accompanist-webview"]
androidx-navigation = ["androidx-navigation-compose", "androidx-navigation-ui"]
coil = ["coil-compose", "coil-gif"]
compose = ["compose-foundation", "compose-material-icons-extended", "compose-material3", "compose-material3-windowsizeclass", "compose-ui-util"]