mirror of
				https://github.com/mihonapp/mihon.git
				synced 2025-10-29 21:37:56 +01:00 
			
		
		
		
	Require Android 8+
Given that the next stable version of Chrome (120) will require Android 8+, it's inevitable that the WebView functionality will gradually break. As always, newer OS versions are recommended for better support with evolving Internet technologies. According to https://apilevels.com/, Android 8+ still covers 93.7% of Android users.
This commit is contained in:
		| @@ -1,6 +1,5 @@ | ||||
| package eu.kanade.domain.ui | ||||
|  | ||||
| import android.os.Build | ||||
| import eu.kanade.domain.ui.model.AppTheme | ||||
| import eu.kanade.domain.ui.model.TabletUiMode | ||||
| import eu.kanade.domain.ui.model.ThemeMode | ||||
| @@ -16,10 +15,7 @@ class UiPreferences( | ||||
|     private val preferenceStore: PreferenceStore, | ||||
| ) { | ||||
|  | ||||
|     fun themeMode() = preferenceStore.getEnum( | ||||
|         "pref_theme_mode_key", | ||||
|         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { ThemeMode.SYSTEM } else { ThemeMode.LIGHT }, | ||||
|     ) | ||||
|     fun themeMode() = preferenceStore.getEnum("pref_theme_mode_key", ThemeMode.SYSTEM) | ||||
|  | ||||
|     fun appTheme() = preferenceStore.getEnum( | ||||
|         "pref_app_theme", | ||||
|   | ||||
| @@ -2,7 +2,6 @@ package eu.kanade.presentation.manga.components | ||||
|  | ||||
| import android.graphics.Bitmap | ||||
| import android.graphics.drawable.BitmapDrawable | ||||
| import android.os.Build | ||||
| import androidx.compose.foundation.background | ||||
| import androidx.compose.foundation.layout.Box | ||||
| import androidx.compose.foundation.layout.Row | ||||
| @@ -176,14 +175,9 @@ fun MangaCoverDialog( | ||||
|                                 // Copy bitmap in case it came from memory cache | ||||
|                                 // Because SSIV needs to thoroughly read the image | ||||
|                                 val copy = (drawable as? BitmapDrawable)?.let { | ||||
|                                     val config = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { | ||||
|                                         Bitmap.Config.HARDWARE | ||||
|                                     } else { | ||||
|                                         Bitmap.Config.ARGB_8888 | ||||
|                                     } | ||||
|                                     BitmapDrawable( | ||||
|                                         view.context.resources, | ||||
|                                         it.bitmap.copy(config, false), | ||||
|                                         it.bitmap.copy(Bitmap.Config.HARDWARE, false), | ||||
|                                     ) | ||||
|                                 } ?: drawable | ||||
|                                 view.setImage(copy, ReaderPageImageView.Config(zoomDuration = 500)) | ||||
|   | ||||
| @@ -3,7 +3,6 @@ package eu.kanade.presentation.more.settings.screen | ||||
| import android.annotation.SuppressLint | ||||
| import android.content.ActivityNotFoundException | ||||
| import android.content.Intent | ||||
| import android.os.Build | ||||
| import android.provider.Settings | ||||
| import android.webkit.WebStorage | ||||
| import android.webkit.WebView | ||||
| @@ -81,62 +80,50 @@ object SettingsAdvancedScreen : SearchableSettings { | ||||
|         val basePreferences = remember { Injekt.get<BasePreferences>() } | ||||
|         val networkPreferences = remember { Injekt.get<NetworkPreferences>() } | ||||
|  | ||||
|         return buildList { | ||||
|             addAll( | ||||
|                 listOf( | ||||
|                     Preference.PreferenceItem.SwitchPreference( | ||||
|                         pref = basePreferences.acraEnabled(), | ||||
|                         title = stringResource(R.string.pref_enable_acra), | ||||
|                         subtitle = stringResource(R.string.pref_acra_summary), | ||||
|                         enabled = isPreviewBuildType || isReleaseBuildType, | ||||
|                     ), | ||||
|                     Preference.PreferenceItem.TextPreference( | ||||
|                         title = stringResource(R.string.pref_dump_crash_logs), | ||||
|                         subtitle = stringResource(R.string.pref_dump_crash_logs_summary), | ||||
|                         onClick = { | ||||
|                             scope.launch { | ||||
|                                 CrashLogUtil(context).dumpLogs() | ||||
|                             } | ||||
|                         }, | ||||
|                     ), | ||||
|                     Preference.PreferenceItem.SwitchPreference( | ||||
|                         pref = networkPreferences.verboseLogging(), | ||||
|                         title = stringResource(R.string.pref_verbose_logging), | ||||
|                         subtitle = stringResource(R.string.pref_verbose_logging_summary), | ||||
|                         onValueChanged = { | ||||
|                             context.toast(R.string.requires_app_restart) | ||||
|                             true | ||||
|                         }, | ||||
|                     ), | ||||
|                     Preference.PreferenceItem.TextPreference( | ||||
|                         title = stringResource(R.string.pref_debug_info), | ||||
|                         onClick = { navigator.push(DebugInfoScreen()) }, | ||||
|                     ), | ||||
|                 ), | ||||
|             ) | ||||
|             if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { | ||||
|                 add( | ||||
|                     Preference.PreferenceItem.TextPreference( | ||||
|                         title = stringResource(R.string.pref_manage_notifications), | ||||
|                         onClick = { | ||||
|                             val intent = Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS).apply { | ||||
|                                 putExtra(Settings.EXTRA_APP_PACKAGE, context.packageName) | ||||
|                             } | ||||
|                             context.startActivity(intent) | ||||
|                         }, | ||||
|                     ), | ||||
|                 ) | ||||
|             } | ||||
|             addAll( | ||||
|                 listOf( | ||||
|                     getBackgroundActivityGroup(), | ||||
|                     getDataGroup(), | ||||
|                     getNetworkGroup(networkPreferences = networkPreferences), | ||||
|                     getLibraryGroup(), | ||||
|                     getExtensionsGroup(basePreferences = basePreferences), | ||||
|                 ), | ||||
|             ) | ||||
|         } | ||||
|         return listOf( | ||||
|             Preference.PreferenceItem.SwitchPreference( | ||||
|                 pref = basePreferences.acraEnabled(), | ||||
|                 title = stringResource(R.string.pref_enable_acra), | ||||
|                 subtitle = stringResource(R.string.pref_acra_summary), | ||||
|                 enabled = isPreviewBuildType || isReleaseBuildType, | ||||
|             ), | ||||
|             Preference.PreferenceItem.TextPreference( | ||||
|                 title = stringResource(R.string.pref_dump_crash_logs), | ||||
|                 subtitle = stringResource(R.string.pref_dump_crash_logs_summary), | ||||
|                 onClick = { | ||||
|                     scope.launch { | ||||
|                         CrashLogUtil(context).dumpLogs() | ||||
|                     } | ||||
|                 }, | ||||
|             ), | ||||
|             Preference.PreferenceItem.SwitchPreference( | ||||
|                 pref = networkPreferences.verboseLogging(), | ||||
|                 title = stringResource(R.string.pref_verbose_logging), | ||||
|                 subtitle = stringResource(R.string.pref_verbose_logging_summary), | ||||
|                 onValueChanged = { | ||||
|                     context.toast(R.string.requires_app_restart) | ||||
|                     true | ||||
|                 }, | ||||
|             ), | ||||
|             Preference.PreferenceItem.TextPreference( | ||||
|                 title = stringResource(R.string.pref_debug_info), | ||||
|                 onClick = { navigator.push(DebugInfoScreen()) }, | ||||
|             ), | ||||
|             Preference.PreferenceItem.TextPreference( | ||||
|                 title = stringResource(R.string.pref_manage_notifications), | ||||
|                 onClick = { | ||||
|                     val intent = Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS).apply { | ||||
|                         putExtra(Settings.EXTRA_APP_PACKAGE, context.packageName) | ||||
|                     } | ||||
|                     context.startActivity(intent) | ||||
|                 }, | ||||
|             ), | ||||
|             getBackgroundActivityGroup(), | ||||
|             getDataGroup(), | ||||
|             getNetworkGroup(networkPreferences = networkPreferences), | ||||
|             getLibraryGroup(), | ||||
|             getExtensionsGroup(basePreferences = basePreferences), | ||||
|         ) | ||||
|     } | ||||
|  | ||||
|     @Composable | ||||
|   | ||||
| @@ -2,7 +2,6 @@ package eu.kanade.presentation.more.settings.screen | ||||
|  | ||||
| import android.app.Activity | ||||
| import android.content.Context | ||||
| import android.os.Build | ||||
| import androidx.annotation.StringRes | ||||
| import androidx.appcompat.app.AppCompatDelegate | ||||
| import androidx.compose.runtime.Composable | ||||
| @@ -81,18 +80,11 @@ object SettingsAppearanceScreen : SearchableSettings { | ||||
|                 Preference.PreferenceItem.ListPreference( | ||||
|                     pref = themeModePref, | ||||
|                     title = stringResource(R.string.pref_theme_mode), | ||||
|                     entries = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { | ||||
|                         mapOf( | ||||
|                             ThemeMode.SYSTEM to stringResource(R.string.theme_system), | ||||
|                             ThemeMode.LIGHT to stringResource(R.string.theme_light), | ||||
|                             ThemeMode.DARK to stringResource(R.string.theme_dark), | ||||
|                         ) | ||||
|                     } else { | ||||
|                         mapOf( | ||||
|                             ThemeMode.LIGHT to stringResource(R.string.theme_light), | ||||
|                             ThemeMode.DARK to stringResource(R.string.theme_dark), | ||||
|                         ) | ||||
|                     }, | ||||
|                     entries = mapOf( | ||||
|                         ThemeMode.SYSTEM to stringResource(R.string.theme_system), | ||||
|                         ThemeMode.LIGHT to stringResource(R.string.theme_light), | ||||
|                         ThemeMode.DARK to stringResource(R.string.theme_dark), | ||||
|                     ), | ||||
|                 ), | ||||
|                 Preference.PreferenceItem.CustomPreference( | ||||
|                     title = stringResource(R.string.pref_app_theme), | ||||
|   | ||||
| @@ -58,7 +58,6 @@ object SettingsReaderScreen : SearchableSettings { | ||||
|                 pref = readerPref.trueColor(), | ||||
|                 title = stringResource(R.string.pref_true_color), | ||||
|                 subtitle = stringResource(R.string.pref_true_color_summary), | ||||
|                 enabled = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O, | ||||
|             ), | ||||
|             Preference.PreferenceItem.SwitchPreference( | ||||
|                 pref = readerPref.pageTransitions(), | ||||
|   | ||||
| @@ -79,6 +79,7 @@ fun ScreenTransition( | ||||
|         targetState = navigator.lastItem, | ||||
|         transitionSpec = transition, | ||||
|         modifier = modifier, | ||||
|         label = "ScreenTransition", | ||||
|     ) { screen -> | ||||
|         navigator.saveableState("transition", screen) { | ||||
|             content(screen) | ||||
|   | ||||
| @@ -171,22 +171,19 @@ class App : Application(), DefaultLifecycleObserver, ImageLoaderFactory { | ||||
|     } | ||||
|  | ||||
|     override fun getPackageName(): String { | ||||
|         // This causes freezes in Android 6/7 for some reason | ||||
|         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { | ||||
|             try { | ||||
|                 // Override the value passed as X-Requested-With in WebView requests | ||||
|                 val stackTrace = Looper.getMainLooper().thread.stackTrace | ||||
|                 val chromiumElement = stackTrace.find { | ||||
|                     it.className.equals( | ||||
|                         "org.chromium.base.BuildInfo", | ||||
|                         ignoreCase = true, | ||||
|                     ) | ||||
|                 } | ||||
|                 if (chromiumElement?.methodName.equals("getAll", ignoreCase = true)) { | ||||
|                     return WebViewUtil.SPOOF_PACKAGE_NAME | ||||
|                 } | ||||
|             } catch (e: Exception) { | ||||
|         try { | ||||
|             // Override the value passed as X-Requested-With in WebView requests | ||||
|             val stackTrace = Looper.getMainLooper().thread.stackTrace | ||||
|             val chromiumElement = stackTrace.find { | ||||
|                 it.className.equals( | ||||
|                     "org.chromium.base.BuildInfo", | ||||
|                     ignoreCase = true, | ||||
|                 ) | ||||
|             } | ||||
|             if (chromiumElement?.methodName.equals("getAll", ignoreCase = true)) { | ||||
|                 return WebViewUtil.SPOOF_PACKAGE_NAME | ||||
|             } | ||||
|         } catch (e: Exception) { | ||||
|         } | ||||
|         return super.getPackageName() | ||||
|     } | ||||
|   | ||||
| @@ -1,6 +1,5 @@ | ||||
| package eu.kanade.tachiyomi.data.coil | ||||
|  | ||||
| import android.os.Build | ||||
| import androidx.core.graphics.drawable.toDrawable | ||||
| import coil.ImageLoader | ||||
| import coil.decode.DecodeResult | ||||
| @@ -48,8 +47,7 @@ class TachiyomiImageDecoder(private val resources: ImageSource, private val opti | ||||
|                 ImageUtil.findImageType(it) | ||||
|             } | ||||
|             return when (type) { | ||||
|                 ImageUtil.ImageType.AVIF, ImageUtil.ImageType.JXL -> true | ||||
|                 ImageUtil.ImageType.HEIF -> Build.VERSION.SDK_INT < Build.VERSION_CODES.O | ||||
|                 ImageUtil.ImageType.AVIF, ImageUtil.ImageType.JXL, ImageUtil.ImageType.HEIF -> true | ||||
|                 else -> false | ||||
|             } | ||||
|         } | ||||
|   | ||||
| @@ -5,7 +5,6 @@ import android.content.BroadcastReceiver | ||||
| import android.content.Context | ||||
| import android.content.Intent | ||||
| import android.net.Uri | ||||
| import android.os.Build | ||||
| import androidx.core.net.toUri | ||||
| import eu.kanade.tachiyomi.R | ||||
| import eu.kanade.tachiyomi.data.backup.BackupRestoreJob | ||||
| @@ -368,20 +367,18 @@ class NotificationReceiver : BroadcastReceiver() { | ||||
|  | ||||
|             When programmatically dismissing this notification, the group notification is not automatically dismissed. | ||||
|              */ | ||||
|             if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { | ||||
|                 val groupKey = context.notificationManager.activeNotifications.find { | ||||
|                     it.id == notificationId | ||||
|                 }?.groupKey | ||||
|             val groupKey = context.notificationManager.activeNotifications.find { | ||||
|                 it.id == notificationId | ||||
|             }?.groupKey | ||||
|  | ||||
|                 if (groupId != null && groupId != 0 && groupKey != null && groupKey.isNotEmpty()) { | ||||
|                     val notifications = context.notificationManager.activeNotifications.filter { | ||||
|                         it.groupKey == groupKey | ||||
|                     } | ||||
|             if (groupId != null && groupId != 0 && !groupKey.isNullOrEmpty()) { | ||||
|                 val notifications = context.notificationManager.activeNotifications.filter { | ||||
|                     it.groupKey == groupKey | ||||
|                 } | ||||
|  | ||||
|                     if (notifications.size == 2) { | ||||
|                         context.cancelNotification(groupId) | ||||
|                         return | ||||
|                     } | ||||
|                 if (notifications.size == 2) { | ||||
|                     context.cancelNotification(groupId) | ||||
|                     return | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|   | ||||
| @@ -2,7 +2,6 @@ package eu.kanade.tachiyomi.extension.installer | ||||
|  | ||||
| import android.app.Service | ||||
| import android.content.pm.PackageManager | ||||
| import android.os.Build | ||||
| import eu.kanade.tachiyomi.R | ||||
| import eu.kanade.tachiyomi.extension.model.InstallStep | ||||
| import eu.kanade.tachiyomi.util.system.getUriSize | ||||
| @@ -50,11 +49,7 @@ class ShizukuInstaller(private val service: Service) : Installer(service) { | ||||
|             try { | ||||
|                 val size = service.getUriSize(entry.uri) ?: throw IllegalStateException() | ||||
|                 service.contentResolver.openInputStream(entry.uri)!!.use { | ||||
|                     val createCommand = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { | ||||
|                         "pm install-create --user current -r -i ${service.packageName} -S $size" | ||||
|                     } else { | ||||
|                         "pm install-create -r -i ${service.packageName} -S $size" | ||||
|                     } | ||||
|                     val createCommand = "pm install-create --user current -r -i ${service.packageName} -S $size" | ||||
|                     val createResult = exec(createCommand) | ||||
|                     sessionId = SESSION_ID_REGEX.find(createResult.out)?.value | ||||
|                         ?: throw RuntimeException("Failed to create install session") | ||||
|   | ||||
| @@ -2,9 +2,7 @@ package eu.kanade.tachiyomi.util.storage | ||||
|  | ||||
| import android.content.Context | ||||
| import android.net.Uri | ||||
| import android.os.Build | ||||
| import androidx.core.content.FileProvider | ||||
| import androidx.core.net.toUri | ||||
| import eu.kanade.tachiyomi.BuildConfig | ||||
| import java.io.File | ||||
|  | ||||
| @@ -17,11 +15,7 @@ val Context.cacheImageDir: File | ||||
|  * @param context context of application | ||||
|  */ | ||||
| fun File.getUriCompat(context: Context): Uri { | ||||
|     return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { | ||||
|         FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID + ".provider", this) | ||||
|     } else { | ||||
|         this.toUri() | ||||
|     } | ||||
|     return FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID + ".provider", this) | ||||
| } | ||||
|  | ||||
| /** | ||||
|   | ||||
| @@ -18,8 +18,7 @@ fun Context.isOnline(): Boolean { | ||||
|     val networkCapabilities = connectivityManager.getNetworkCapabilities(activeNetwork) ?: return false | ||||
|     val maxTransport = when { | ||||
|         Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1 -> NetworkCapabilities.TRANSPORT_LOWPAN | ||||
|         Build.VERSION.SDK_INT >= Build.VERSION_CODES.O -> NetworkCapabilities.TRANSPORT_WIFI_AWARE | ||||
|         else -> NetworkCapabilities.TRANSPORT_VPN | ||||
|         else -> NetworkCapabilities.TRANSPORT_WIFI_AWARE | ||||
|     } | ||||
|     return (NetworkCapabilities.TRANSPORT_CELLULAR..maxTransport).any(networkCapabilities::hasTransport) | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user