mirror of
				https://github.com/mihonapp/mihon.git
				synced 2025-10-31 22:37:56 +01:00 
			
		
		
		
	Basic initial port of About screen to Compose
This commit is contained in:
		| @@ -0,0 +1,39 @@ | ||||
| package eu.kanade.presentation.components | ||||
|  | ||||
| import androidx.compose.foundation.clickable | ||||
| import androidx.compose.foundation.layout.padding | ||||
| import androidx.compose.material3.Icon | ||||
| import androidx.compose.material3.MaterialTheme | ||||
| import androidx.compose.runtime.Composable | ||||
| import androidx.compose.ui.Modifier | ||||
| import androidx.compose.ui.graphics.painter.Painter | ||||
| import androidx.compose.ui.platform.LocalUriHandler | ||||
| import androidx.compose.ui.unit.dp | ||||
|  | ||||
| @Composable | ||||
| fun LinkIcon( | ||||
|     modifier: Modifier = Modifier, | ||||
|     label: String, | ||||
|     painter: Painter, | ||||
|     url: String, | ||||
| ) { | ||||
|     val uriHandler = LocalUriHandler.current | ||||
|     LinkIcon(modifier, label, painter) { uriHandler.openUri(url) } | ||||
| } | ||||
|  | ||||
| @Composable | ||||
| fun LinkIcon( | ||||
|     modifier: Modifier = Modifier, | ||||
|     label: String, | ||||
|     painter: Painter, | ||||
|     onClick: () -> Unit, | ||||
| ) { | ||||
|     Icon( | ||||
|         modifier = modifier | ||||
|             .clickable(onClick = onClick) | ||||
|             .padding(16.dp), | ||||
|         painter = painter, | ||||
|         tint = MaterialTheme.colorScheme.primary, | ||||
|         contentDescription = label, | ||||
|     ) | ||||
| } | ||||
| @@ -0,0 +1,89 @@ | ||||
| package eu.kanade.presentation.components | ||||
|  | ||||
| import androidx.compose.foundation.combinedClickable | ||||
| import androidx.compose.foundation.layout.Box | ||||
| import androidx.compose.foundation.layout.Column | ||||
| import androidx.compose.foundation.layout.Row | ||||
| import androidx.compose.foundation.layout.fillMaxWidth | ||||
| import androidx.compose.foundation.layout.padding | ||||
| import androidx.compose.foundation.layout.requiredHeight | ||||
| import androidx.compose.foundation.layout.size | ||||
| import androidx.compose.foundation.layout.widthIn | ||||
| import androidx.compose.material3.Icon | ||||
| import androidx.compose.material3.MaterialTheme | ||||
| import androidx.compose.material3.Text | ||||
| import androidx.compose.material3.contentColorFor | ||||
| import androidx.compose.runtime.Composable | ||||
| import androidx.compose.ui.Alignment | ||||
| import androidx.compose.ui.Modifier | ||||
| import androidx.compose.ui.graphics.vector.ImageVector | ||||
| import androidx.compose.ui.text.font.FontWeight | ||||
| import androidx.compose.ui.text.style.TextOverflow | ||||
| import androidx.compose.ui.unit.dp | ||||
| import eu.kanade.presentation.util.horizontalPadding | ||||
|  | ||||
| @Composable | ||||
| fun PreferenceRow( | ||||
|     title: String, | ||||
|     icon: ImageVector? = null, | ||||
|     onClick: () -> Unit = {}, | ||||
|     onLongClick: () -> Unit = {}, | ||||
|     subtitle: String? = null, | ||||
|     action: @Composable (() -> Unit)? = null, | ||||
| ) { | ||||
|     val height = if (subtitle != null) 72.dp else 56.dp | ||||
|  | ||||
|     // TODO: adjust text styles, especially subtitles | ||||
|     val textStyle = MaterialTheme.typography.titleMedium.copy( | ||||
|         color = contentColorFor(MaterialTheme.colorScheme.background), | ||||
|     ) | ||||
|  | ||||
|     Row( | ||||
|         modifier = Modifier | ||||
|             .fillMaxWidth() | ||||
|             .requiredHeight(height) | ||||
|             .combinedClickable( | ||||
|                 onLongClick = onLongClick, | ||||
|                 onClick = onClick | ||||
|             ), | ||||
|         verticalAlignment = Alignment.CenterVertically | ||||
|     ) { | ||||
|         if (icon != null) { | ||||
|             Icon( | ||||
|                 imageVector = icon, | ||||
|                 modifier = Modifier | ||||
|                     .padding(horizontal = horizontalPadding) | ||||
|                     .size(24.dp), | ||||
|                 tint = MaterialTheme.colorScheme.primary, | ||||
|                 contentDescription = null | ||||
|             ) | ||||
|         } | ||||
|         Column( | ||||
|             Modifier | ||||
|                 .padding(horizontal = horizontalPadding) | ||||
|                 .weight(1f) | ||||
|         ) { | ||||
|             Text( | ||||
|                 text = title, | ||||
|                 overflow = TextOverflow.Ellipsis, | ||||
|                 maxLines = 1, | ||||
|                 style = textStyle, | ||||
|             ) | ||||
|             if (subtitle != null) { | ||||
|                 Text( | ||||
|                     text = subtitle, | ||||
|                     overflow = TextOverflow.Ellipsis, | ||||
|                     maxLines = 1, | ||||
|                     style = textStyle.copy( | ||||
|                         fontWeight = FontWeight.Normal, | ||||
|                     ), | ||||
|                 ) | ||||
|             } | ||||
|         } | ||||
|         if (action != null) { | ||||
|             Box(Modifier.widthIn(min = 56.dp)) { | ||||
|                 action() | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										144
									
								
								app/src/main/java/eu/kanade/presentation/more/AboutScreen.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										144
									
								
								app/src/main/java/eu/kanade/presentation/more/AboutScreen.kt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,144 @@ | ||||
| package eu.kanade.presentation.more | ||||
|  | ||||
| import androidx.compose.foundation.layout.Arrangement | ||||
| import androidx.compose.foundation.layout.Row | ||||
| import androidx.compose.foundation.layout.fillMaxWidth | ||||
| import androidx.compose.foundation.lazy.LazyColumn | ||||
| import androidx.compose.material.icons.Icons | ||||
| import androidx.compose.material.icons.outlined.Public | ||||
| import androidx.compose.runtime.Composable | ||||
| import androidx.compose.ui.Modifier | ||||
| import androidx.compose.ui.graphics.vector.rememberVectorPainter | ||||
| import androidx.compose.ui.input.nestedscroll.NestedScrollConnection | ||||
| import androidx.compose.ui.input.nestedscroll.nestedScroll | ||||
| import androidx.compose.ui.platform.LocalContext | ||||
| import androidx.compose.ui.platform.LocalUriHandler | ||||
| import androidx.compose.ui.res.painterResource | ||||
| import androidx.compose.ui.res.stringResource | ||||
| import eu.kanade.presentation.components.LinkIcon | ||||
| import eu.kanade.presentation.components.PreferenceRow | ||||
| import eu.kanade.tachiyomi.BuildConfig | ||||
| import eu.kanade.tachiyomi.R | ||||
| import eu.kanade.tachiyomi.data.updater.RELEASE_URL | ||||
| import eu.kanade.tachiyomi.util.CrashLogUtil | ||||
| import eu.kanade.tachiyomi.util.system.copyToClipboard | ||||
|  | ||||
| @Composable | ||||
| fun AboutScreen( | ||||
|     nestedScrollInterop: NestedScrollConnection, | ||||
|     checkVersion: () -> Unit, | ||||
|     getFormattedBuildTime: () -> String, | ||||
|     onClickLicenses: () -> Unit, | ||||
| ) { | ||||
|     val context = LocalContext.current | ||||
|     val uriHandler = LocalUriHandler.current | ||||
|  | ||||
|     LazyColumn( | ||||
|         modifier = Modifier.nestedScroll(nestedScrollInterop), | ||||
|     ) { | ||||
|         item { | ||||
|             LogoHeader() | ||||
|         } | ||||
|  | ||||
|         item { | ||||
|             PreferenceRow( | ||||
|                 title = stringResource(R.string.version), | ||||
|                 subtitle = when { | ||||
|                     BuildConfig.DEBUG -> { | ||||
|                         "Debug ${BuildConfig.COMMIT_SHA} (${getFormattedBuildTime()})" | ||||
|                     } | ||||
|                     BuildConfig.PREVIEW -> { | ||||
|                         "Preview r${BuildConfig.COMMIT_COUNT} (${BuildConfig.COMMIT_SHA}, ${getFormattedBuildTime()})" | ||||
|                     } | ||||
|                     else -> { | ||||
|                         "Stable ${BuildConfig.VERSION_NAME} (${getFormattedBuildTime()})" | ||||
|                     } | ||||
|                 }, | ||||
|                 onClick = { | ||||
|                     val deviceInfo = CrashLogUtil(context).getDebugInfo() | ||||
|                     context.copyToClipboard("Debug information", deviceInfo) | ||||
|                 }, | ||||
|             ) | ||||
|         } | ||||
|  | ||||
|         if (BuildConfig.INCLUDE_UPDATER) { | ||||
|             item { | ||||
|                 PreferenceRow( | ||||
|                     title = stringResource(R.string.check_for_updates), | ||||
|                     onClick = { | ||||
|                         checkVersion() | ||||
|                     }, | ||||
|                 ) | ||||
|             } | ||||
|         } | ||||
|         if (!BuildConfig.DEBUG) { | ||||
|             item { | ||||
|                 PreferenceRow( | ||||
|                     title = stringResource(R.string.whats_new), | ||||
|                     onClick = { | ||||
|                         uriHandler.openUri(RELEASE_URL) | ||||
|                     }, | ||||
|                 ) | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         item { | ||||
|             PreferenceRow( | ||||
|                 title = stringResource(R.string.help_translate), | ||||
|                 onClick = { uriHandler.openUri("https://tachiyomi.org/help/contribution/#translation") }, | ||||
|             ) | ||||
|         } | ||||
|  | ||||
|         item { | ||||
|             PreferenceRow( | ||||
|                 title = stringResource(R.string.licenses), | ||||
|                 onClick = onClickLicenses, | ||||
|             ) | ||||
|         } | ||||
|  | ||||
|         item { | ||||
|             PreferenceRow( | ||||
|                 title = stringResource(R.string.privacy_policy), | ||||
|                 onClick = { uriHandler.openUri("https://tachiyomi.org/privacy") }, | ||||
|             ) | ||||
|         } | ||||
|  | ||||
|         item { | ||||
|             Row( | ||||
|                 modifier = Modifier.fillMaxWidth(), | ||||
|                 horizontalArrangement = Arrangement.Center, | ||||
|             ) { | ||||
|                 LinkIcon( | ||||
|                     label = stringResource(R.string.website), | ||||
|                     painter = rememberVectorPainter(Icons.Outlined.Public), | ||||
|                     url = "https://tachiyomi.org", | ||||
|                 ) | ||||
|                 LinkIcon( | ||||
|                     label = "Discord", | ||||
|                     painter = painterResource(R.drawable.ic_discord_24dp), | ||||
|                     url = "https://discord.gg/tachiyomi", | ||||
|                 ) | ||||
|                 LinkIcon( | ||||
|                     label = "Twitter", | ||||
|                     painter = painterResource(R.drawable.ic_twitter_24dp), | ||||
|                     url = "https://twitter.com/tachiyomiorg", | ||||
|                 ) | ||||
|                 LinkIcon( | ||||
|                     label = "Facebook", | ||||
|                     painter = painterResource(R.drawable.ic_facebook_24dp), | ||||
|                     url = "https://facebook.com/tachiyomiorg", | ||||
|                 ) | ||||
|                 LinkIcon( | ||||
|                     label = "Reddit", | ||||
|                     painter = painterResource(R.drawable.ic_reddit_24dp), | ||||
|                     url = "https://www.reddit.com/r/Tachiyomi", | ||||
|                 ) | ||||
|                 LinkIcon( | ||||
|                     label = "GitHub", | ||||
|                     painter = painterResource(R.drawable.ic_github_24dp), | ||||
|                     url = "https://github.com/tachiyomiorg", | ||||
|                 ) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,28 @@ | ||||
| package eu.kanade.presentation.more | ||||
|  | ||||
| import androidx.compose.foundation.layout.fillMaxSize | ||||
| import androidx.compose.material3.MaterialTheme | ||||
| import androidx.compose.material3.contentColorFor | ||||
| import androidx.compose.runtime.Composable | ||||
| import androidx.compose.ui.Modifier | ||||
| import androidx.compose.ui.input.nestedscroll.NestedScrollConnection | ||||
| import androidx.compose.ui.input.nestedscroll.nestedScroll | ||||
| import com.mikepenz.aboutlibraries.ui.compose.LibrariesContainer | ||||
| import com.mikepenz.aboutlibraries.ui.compose.LibraryDefaults | ||||
|  | ||||
| @Composable | ||||
| fun LicensesScreen( | ||||
|     nestedScrollInterop: NestedScrollConnection, | ||||
| ) { | ||||
|     LibrariesContainer( | ||||
|         modifier = Modifier | ||||
|             .fillMaxSize() | ||||
|             .nestedScroll(nestedScrollInterop), | ||||
|         colors = LibraryDefaults.libraryColors( | ||||
|             backgroundColor = MaterialTheme.colorScheme.background, | ||||
|             contentColor = contentColorFor(MaterialTheme.colorScheme.background), | ||||
|             badgeBackgroundColor = MaterialTheme.colorScheme.primary, | ||||
|             badgeContentColor = contentColorFor(MaterialTheme.colorScheme.primary), | ||||
|         ), | ||||
|     ) | ||||
| } | ||||
							
								
								
									
										36
									
								
								app/src/main/java/eu/kanade/presentation/more/LogoHeader.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								app/src/main/java/eu/kanade/presentation/more/LogoHeader.kt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,36 @@ | ||||
| package eu.kanade.presentation.more | ||||
|  | ||||
| import androidx.compose.foundation.layout.Column | ||||
| import androidx.compose.foundation.layout.fillMaxWidth | ||||
| import androidx.compose.foundation.layout.padding | ||||
| import androidx.compose.foundation.layout.size | ||||
| import androidx.compose.material3.Divider | ||||
| import androidx.compose.material3.Icon | ||||
| import androidx.compose.material3.MaterialTheme | ||||
| import androidx.compose.material3.Surface | ||||
| import androidx.compose.runtime.Composable | ||||
| import androidx.compose.ui.Modifier | ||||
| import androidx.compose.ui.res.painterResource | ||||
| import androidx.compose.ui.unit.dp | ||||
| import eu.kanade.tachiyomi.R | ||||
|  | ||||
| @Composable | ||||
| fun LogoHeader() { | ||||
|     Column { | ||||
|         Surface( | ||||
|             modifier = Modifier.fillMaxWidth() | ||||
|         ) { | ||||
|             Icon( | ||||
|                 painter = painterResource(R.drawable.ic_tachi), | ||||
|                 contentDescription = null, | ||||
|                 tint = MaterialTheme.colorScheme.onSurface, | ||||
|                 modifier = Modifier | ||||
|                     .padding(32.dp) | ||||
|                     .size(56.dp), | ||||
|             ) | ||||
|         } | ||||
|  | ||||
|         // TODO: proper color | ||||
|         Divider() | ||||
|     } | ||||
| } | ||||
| @@ -1,106 +1,44 @@ | ||||
| package eu.kanade.tachiyomi.ui.more | ||||
|  | ||||
| import androidx.preference.PreferenceScreen | ||||
| import androidx.compose.runtime.Composable | ||||
| import androidx.compose.ui.input.nestedscroll.NestedScrollConnection | ||||
| import eu.kanade.presentation.more.AboutScreen | ||||
| import eu.kanade.tachiyomi.BuildConfig | ||||
| import eu.kanade.tachiyomi.R | ||||
| import eu.kanade.tachiyomi.data.preference.PreferencesHelper | ||||
| import eu.kanade.tachiyomi.data.updater.AppUpdateChecker | ||||
| import eu.kanade.tachiyomi.data.updater.AppUpdateResult | ||||
| import eu.kanade.tachiyomi.data.updater.RELEASE_URL | ||||
| import eu.kanade.tachiyomi.ui.base.controller.BasicComposeController | ||||
| import eu.kanade.tachiyomi.ui.base.controller.NoAppBarElevationController | ||||
| import eu.kanade.tachiyomi.ui.base.controller.openInBrowser | ||||
| import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction | ||||
| import eu.kanade.tachiyomi.ui.setting.SettingsController | ||||
| import eu.kanade.tachiyomi.util.CrashLogUtil | ||||
| import eu.kanade.tachiyomi.util.lang.launchNow | ||||
| import eu.kanade.tachiyomi.util.lang.toDateTimestampString | ||||
| import eu.kanade.tachiyomi.util.preference.add | ||||
| import eu.kanade.tachiyomi.util.preference.onClick | ||||
| import eu.kanade.tachiyomi.util.preference.preference | ||||
| import eu.kanade.tachiyomi.util.preference.titleRes | ||||
| import eu.kanade.tachiyomi.util.system.copyToClipboard | ||||
| import eu.kanade.tachiyomi.util.system.logcat | ||||
| import eu.kanade.tachiyomi.util.system.toast | ||||
| import logcat.LogPriority | ||||
| import uy.kohesive.injekt.injectLazy | ||||
| import java.text.DateFormat | ||||
| import java.text.SimpleDateFormat | ||||
| import java.util.Locale | ||||
| import java.util.TimeZone | ||||
|  | ||||
| class AboutController : SettingsController(), NoAppBarElevationController { | ||||
| class AboutController : BasicComposeController(), NoAppBarElevationController { | ||||
|  | ||||
|     private val preferences: PreferencesHelper by injectLazy() | ||||
|     private val updateChecker by lazy { AppUpdateChecker() } | ||||
|  | ||||
|     private val dateFormat: DateFormat = preferences.dateFormat() | ||||
|     override fun getTitle() = resources?.getString(R.string.pref_category_about) | ||||
|  | ||||
|     override fun setupPreferenceScreen(screen: PreferenceScreen) = screen.apply { | ||||
|         titleRes = R.string.pref_category_about | ||||
|  | ||||
|         add(MoreHeaderPreference(context)) | ||||
|  | ||||
|         preference { | ||||
|             key = "pref_about_version" | ||||
|             titleRes = R.string.version | ||||
|             summary = when { | ||||
|                 BuildConfig.DEBUG -> { | ||||
|                     "Debug ${BuildConfig.COMMIT_SHA} (${getFormattedBuildTime()})" | ||||
|                 } | ||||
|                 BuildConfig.PREVIEW -> { | ||||
|                     "Preview r${BuildConfig.COMMIT_COUNT} (${BuildConfig.COMMIT_SHA}, ${getFormattedBuildTime()})" | ||||
|                 } | ||||
|                 else -> { | ||||
|                     "Stable ${BuildConfig.VERSION_NAME} (${getFormattedBuildTime()})" | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             onClick { | ||||
|                 activity?.let { | ||||
|                     val deviceInfo = CrashLogUtil(it).getDebugInfo() | ||||
|                     it.copyToClipboard("Debug information", deviceInfo) | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         if (BuildConfig.INCLUDE_UPDATER) { | ||||
|             preference { | ||||
|                 key = "pref_about_check_for_updates" | ||||
|                 titleRes = R.string.check_for_updates | ||||
|  | ||||
|                 onClick { checkVersion() } | ||||
|             } | ||||
|         } | ||||
|         if (!BuildConfig.DEBUG) { | ||||
|             preference { | ||||
|                 key = "pref_about_whats_new" | ||||
|                 titleRes = R.string.whats_new | ||||
|  | ||||
|                 onClick { | ||||
|                     openInBrowser(RELEASE_URL) | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         preference { | ||||
|             key = "pref_about_help_translate" | ||||
|             titleRes = R.string.help_translate | ||||
|  | ||||
|             onClick { | ||||
|                 openInBrowser("https://tachiyomi.org/help/contribution/#translation") | ||||
|             } | ||||
|         } | ||||
|         preference { | ||||
|             key = "pref_about_licenses" | ||||
|             titleRes = R.string.licenses | ||||
|             onClick { | ||||
|     @Composable | ||||
|     override fun ComposeContent(nestedScrollInterop: NestedScrollConnection) { | ||||
|         AboutScreen( | ||||
|             nestedScrollInterop = nestedScrollInterop, | ||||
|             checkVersion = this::checkVersion, | ||||
|             getFormattedBuildTime = this::getFormattedBuildTime, | ||||
|             onClickLicenses = { | ||||
|                 router.pushController(LicensesController().withFadeTransaction()) | ||||
|             } | ||||
|         } | ||||
|         preference { | ||||
|             key = "pref_about_privacy_policy" | ||||
|             titleRes = R.string.privacy_policy | ||||
|             onClick { | ||||
|                 openInBrowser("https://tachiyomi.org/privacy") | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         add(AboutLinksPreference(context)) | ||||
|             }, | ||||
|         ) | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -142,7 +80,7 @@ class AboutController : SettingsController(), NoAppBarElevationController { | ||||
|             ) | ||||
|             outputDf.timeZone = TimeZone.getDefault() | ||||
|  | ||||
|             buildTime!!.toDateTimestampString(dateFormat) | ||||
|             buildTime!!.toDateTimestampString(preferences.dateFormat()) | ||||
|         } catch (e: Exception) { | ||||
|             BuildConfig.BUILD_TIME | ||||
|         } | ||||
|   | ||||
| @@ -1,14 +1,8 @@ | ||||
| package eu.kanade.tachiyomi.ui.more | ||||
|  | ||||
| import androidx.compose.foundation.layout.fillMaxSize | ||||
| import androidx.compose.material3.MaterialTheme | ||||
| import androidx.compose.material3.contentColorFor | ||||
| import androidx.compose.runtime.Composable | ||||
| import androidx.compose.ui.Modifier | ||||
| import androidx.compose.ui.input.nestedscroll.NestedScrollConnection | ||||
| import androidx.compose.ui.input.nestedscroll.nestedScroll | ||||
| import com.mikepenz.aboutlibraries.ui.compose.LibrariesContainer | ||||
| import com.mikepenz.aboutlibraries.ui.compose.LibraryDefaults.libraryColors | ||||
| import eu.kanade.presentation.more.LicensesScreen | ||||
| import eu.kanade.tachiyomi.R | ||||
| import eu.kanade.tachiyomi.ui.base.controller.BasicComposeController | ||||
|  | ||||
| @@ -18,16 +12,6 @@ class LicensesController : BasicComposeController() { | ||||
|  | ||||
|     @Composable | ||||
|     override fun ComposeContent(nestedScrollInterop: NestedScrollConnection) { | ||||
|         LibrariesContainer( | ||||
|             modifier = Modifier | ||||
|                 .fillMaxSize() | ||||
|                 .nestedScroll(nestedScrollInterop), | ||||
|             colors = libraryColors( | ||||
|                 backgroundColor = MaterialTheme.colorScheme.background, | ||||
|                 contentColor = contentColorFor(MaterialTheme.colorScheme.background), | ||||
|                 badgeBackgroundColor = MaterialTheme.colorScheme.primary, | ||||
|                 badgeContentColor = contentColorFor(MaterialTheme.colorScheme.primary), | ||||
|             ), | ||||
|         ) | ||||
|         LicensesScreen(nestedScrollInterop = nestedScrollInterop) | ||||
|     } | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user