From 34b88c3ad8d603693908960d28b5c2c6bd1e3453 Mon Sep 17 00:00:00 2001 From: Ricki Hirner Date: Fri, 19 Apr 2024 11:05:39 +0200 Subject: [PATCH] Add M3 theme and apply to AboutActivity (#731) * Rename AppTheme to M2Theme, add M3 theme * Rewrite AboutActivity to M3 * Apply M3 theme; minor optimizations * Use M3 version of AboutLibraries * Use material3 instead of material3-android dependency * Use reversed theme --- app/build.gradle.kts | 1 + .../at/bitfire/davdroid/ui/AboutActivity.kt | 39 ++--- .../bitfire/davdroid/ui/AccountsActivity.kt | 2 +- .../davdroid/ui/AppSettingsActivity.kt | 2 +- .../kotlin/at/bitfire/davdroid/ui/AppTheme.kt | 26 +++- .../bitfire/davdroid/ui/DebugInfoActivity.kt | 2 +- .../davdroid/ui/PermissionsActivity.kt | 4 +- .../at/bitfire/davdroid/ui/TasksActivity.kt | 4 +- .../davdroid/ui/account/AccountActivity.kt | 4 +- .../ui/account/AccountSettingsActivity.kt | 4 +- .../ui/account/CreateAddressBookActivity.kt | 4 +- .../ui/account/CreateCalendarActivity.kt | 4 +- .../ui/account/WifiPermissionsActivity.kt | 4 +- .../ui/intro/BatteryOptimizationsPage.kt | 4 +- .../davdroid/ui/intro/IntroActivity.kt | 8 +- .../bitfire/davdroid/ui/intro/WelcomePage.kt | 2 +- .../davdroid/ui/setup/LoginActivity.kt | 4 +- .../ui/webdav/AddWebdavMountActivity.kt | 6 +- .../ui/webdav/WebdavMountsActivity.kt | 8 +- .../davdroid/ui/widget/SyncButtonWidget.kt | 4 +- .../ui/OpenSourceLicenseInfoProvider.kt | 18 ++- .../at/bitfire/davdroid/ui/ThemeColors.kt | 136 +++++++++++++++++- gradle/libs.versions.toml | 3 +- 23 files changed, 222 insertions(+), 71 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 1388f094..5ec34ab9 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -165,6 +165,7 @@ dependencies { implementation(libs.compose.accompanist.permissions) implementation(platform(libs.compose.bom)) implementation(libs.compose.material) + implementation(libs.compose.material3) implementation(libs.compose.materialIconsExtended) implementation(libs.compose.runtime.livedata) debugImplementation(libs.compose.ui.tooling) diff --git a/app/src/main/kotlin/at/bitfire/davdroid/ui/AboutActivity.kt b/app/src/main/kotlin/at/bitfire/davdroid/ui/AboutActivity.kt index 02c0cf2a..11682b14 100644 --- a/app/src/main/kotlin/at/bitfire/davdroid/ui/AboutActivity.kt +++ b/app/src/main/kotlin/at/bitfire/davdroid/ui/AboutActivity.kt @@ -23,17 +23,18 @@ import androidx.compose.foundation.pager.HorizontalPager import androidx.compose.foundation.pager.rememberPagerState import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll -import androidx.compose.material.Icon -import androidx.compose.material.IconButton -import androidx.compose.material.MaterialTheme -import androidx.compose.material.Scaffold -import androidx.compose.material.Tab -import androidx.compose.material.TabRow -import androidx.compose.material.Text -import androidx.compose.material.TopAppBar import androidx.compose.material.icons.Icons import androidx.compose.material.icons.automirrored.filled.ArrowBack import androidx.compose.material.icons.filled.Home +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Tab +import androidx.compose.material3.TabRow +import androidx.compose.material3.Text +import androidx.compose.material3.TopAppBar import androidx.compose.runtime.Composable import androidx.compose.runtime.livedata.observeAsState import androidx.compose.runtime.rememberCoroutineScope @@ -55,7 +56,7 @@ import at.bitfire.davdroid.R import at.bitfire.davdroid.log.Logger import at.bitfire.davdroid.ui.composable.PixelBoxes import com.mikepenz.aboutlibraries.Libs -import com.mikepenz.aboutlibraries.ui.compose.LibrariesContainer +import com.mikepenz.aboutlibraries.ui.compose.m3.LibrariesContainer import com.mikepenz.aboutlibraries.util.withJson import dagger.BindsOptionalOf import dagger.Module @@ -87,7 +88,7 @@ class AboutActivity: AppCompatActivity() { lateinit var licenseInfoProvider: Optional - @OptIn(ExperimentalFoundationApi::class) + @OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -266,7 +267,7 @@ fun AboutApp(licenseInfoProvider: AboutActivity.AppLicenseInfoProvider? = null) ) Text( stringResource(R.string.app_name), - style = MaterialTheme.typography.h5, + style = MaterialTheme.typography.headlineMedium, textAlign = TextAlign.Center, modifier = Modifier .fillMaxWidth() @@ -275,7 +276,7 @@ fun AboutApp(licenseInfoProvider: AboutActivity.AppLicenseInfoProvider? = null) Text( stringResource(R.string.about_version, BuildConfig.VERSION_NAME, BuildConfig.VERSION_CODE), - style = MaterialTheme.typography.body1, + style = MaterialTheme.typography.bodyLarge, textAlign = TextAlign.Center, modifier = Modifier.fillMaxWidth() ) @@ -283,14 +284,14 @@ fun AboutApp(licenseInfoProvider: AboutActivity.AppLicenseInfoProvider? = null) val dateFormatter = DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT) Text( stringResource(R.string.about_build_date, dateFormatter.format(buildTime)), - style = MaterialTheme.typography.body1, + style = MaterialTheme.typography.bodyLarge, textAlign = TextAlign.Center, modifier = Modifier.fillMaxWidth() ) Text( stringResource(R.string.about_copyright), - style = MaterialTheme.typography.body1, + style = MaterialTheme.typography.bodyLarge, textAlign = TextAlign.Center, modifier = Modifier .fillMaxWidth() @@ -299,17 +300,17 @@ fun AboutApp(licenseInfoProvider: AboutActivity.AppLicenseInfoProvider? = null) Text( stringResource(R.string.about_license_info_no_warranty), - style = MaterialTheme.typography.body1, + style = MaterialTheme.typography.bodyLarge, modifier = Modifier .fillMaxWidth() - .padding(vertical = 8.dp) + .padding(top = 8.dp) ) PixelBoxes( arrayOf(Color(0xFFFCF434), Color.White, Color(0xFF9C59D1), Color.Black), modifier = Modifier .align(Alignment.CenterHorizontally) - .padding(8.dp) + .padding(16.dp) ) licenseInfoProvider?.LicenseInfo() @@ -337,14 +338,14 @@ fun TranslatorsGallery( items(translations) { translation -> Text( translation.language, - style = MaterialTheme.typography.h6, + style = MaterialTheme.typography.headlineMedium, modifier = Modifier.padding(vertical = 4.dp) ) Text( translation.translators .sortedWith { a, b -> collator.compare(a, b) } .joinToString(" ยท "), - style = MaterialTheme.typography.body1, + style = MaterialTheme.typography.bodyLarge, modifier = Modifier.padding(bottom = 16.dp) ) } diff --git a/app/src/main/kotlin/at/bitfire/davdroid/ui/AccountsActivity.kt b/app/src/main/kotlin/at/bitfire/davdroid/ui/AccountsActivity.kt index 1a418edc..7b168b10 100644 --- a/app/src/main/kotlin/at/bitfire/davdroid/ui/AccountsActivity.kt +++ b/app/src/main/kotlin/at/bitfire/davdroid/ui/AccountsActivity.kt @@ -141,7 +141,7 @@ class AccountsActivity: AppCompatActivity() { val accounts by model.accountInfos.observeAsState() - AppTheme { + M2Theme { Scaffold( scaffoldState = scaffoldState, drawerContent = { diff --git a/app/src/main/kotlin/at/bitfire/davdroid/ui/AppSettingsActivity.kt b/app/src/main/kotlin/at/bitfire/davdroid/ui/AppSettingsActivity.kt index 94609644..426f2f5f 100644 --- a/app/src/main/kotlin/at/bitfire/davdroid/ui/AppSettingsActivity.kt +++ b/app/src/main/kotlin/at/bitfire/davdroid/ui/AppSettingsActivity.kt @@ -96,7 +96,7 @@ class AppSettingsActivity: AppCompatActivity() { super.onCreate(savedInstanceState) setContent { - AppTheme { + M2Theme { AppSettings() } } diff --git a/app/src/main/kotlin/at/bitfire/davdroid/ui/AppTheme.kt b/app/src/main/kotlin/at/bitfire/davdroid/ui/AppTheme.kt index a34d0350..123a1a57 100644 --- a/app/src/main/kotlin/at/bitfire/davdroid/ui/AppTheme.kt +++ b/app/src/main/kotlin/at/bitfire/davdroid/ui/AppTheme.kt @@ -5,7 +5,7 @@ package at.bitfire.davdroid.ui import androidx.compose.foundation.isSystemInDarkTheme -import androidx.compose.material.MaterialTheme +import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.ui.platform.LocalContext @@ -13,15 +13,31 @@ import androidx.compose.ui.platform.LocalUriHandler import at.bitfire.davdroid.ui.composable.SafeAndroidUriHandler @Composable -fun AppTheme(content: @Composable () -> Unit) { +fun M2Theme(content: @Composable () -> Unit) { val colors = if (isSystemInDarkTheme()) - ThemeColors.dark + M2Colors.dark else - ThemeColors.light + M2Colors.light CompositionLocalProvider(LocalUriHandler provides SafeAndroidUriHandler(LocalContext.current)) { - MaterialTheme(colors = colors) { + androidx.compose.material.MaterialTheme(colors = colors) { content() } } +} + +@Composable +fun AppTheme( + useDarkTheme: Boolean = isSystemInDarkTheme(), + content: @Composable () -> Unit +) { + val colors = if (!useDarkTheme) + M3ColorScheme.LightColors + else + M3ColorScheme.DarkColors + + MaterialTheme( + colorScheme = colors, + content = content + ) } \ No newline at end of file diff --git a/app/src/main/kotlin/at/bitfire/davdroid/ui/DebugInfoActivity.kt b/app/src/main/kotlin/at/bitfire/davdroid/ui/DebugInfoActivity.kt index b834276e..57ee55c4 100644 --- a/app/src/main/kotlin/at/bitfire/davdroid/ui/DebugInfoActivity.kt +++ b/app/src/main/kotlin/at/bitfire/davdroid/ui/DebugInfoActivity.kt @@ -179,7 +179,7 @@ class DebugInfoActivity : AppCompatActivity() { } setContent { - AppTheme { + M2Theme { val debugInfo by model.debugInfo.observeAsState() val zipProgress by model.zipProgress.observeAsState(false) diff --git a/app/src/main/kotlin/at/bitfire/davdroid/ui/PermissionsActivity.kt b/app/src/main/kotlin/at/bitfire/davdroid/ui/PermissionsActivity.kt index b283840c..df9b63c9 100644 --- a/app/src/main/kotlin/at/bitfire/davdroid/ui/PermissionsActivity.kt +++ b/app/src/main/kotlin/at/bitfire/davdroid/ui/PermissionsActivity.kt @@ -57,7 +57,7 @@ class PermissionsActivity: AppCompatActivity() { super.onCreate(savedInstanceState) setContent { - AppTheme { + M2Theme { Scaffold( topBar = { BasicTopAppBar( @@ -143,7 +143,7 @@ fun PermissionsContent( @Preview(showBackground = true, showSystemUi = true) @Composable fun PermissionsCard_Preview() { - AppTheme { + M2Theme { PermissionsCardContent( keepPermissions = true, onKeepPermissionsRequested = {}, diff --git a/app/src/main/kotlin/at/bitfire/davdroid/ui/TasksActivity.kt b/app/src/main/kotlin/at/bitfire/davdroid/ui/TasksActivity.kt index 9c850048..b00bb459 100644 --- a/app/src/main/kotlin/at/bitfire/davdroid/ui/TasksActivity.kt +++ b/app/src/main/kotlin/at/bitfire/davdroid/ui/TasksActivity.kt @@ -70,7 +70,7 @@ class TasksActivity: AppCompatActivity() { super.onCreate(savedInstanceState) setContent { - AppTheme { + M2Theme { Scaffold( topBar = { BasicTopAppBar( @@ -202,7 +202,7 @@ fun TasksCard( @Preview(showBackground = true, showSystemUi = true) @Composable fun TasksCardContent_Preview() { - AppTheme { + M2Theme { TasksCardContent( jtxSelected = true, jtxInstalled = true, diff --git a/app/src/main/kotlin/at/bitfire/davdroid/ui/account/AccountActivity.kt b/app/src/main/kotlin/at/bitfire/davdroid/ui/account/AccountActivity.kt index 5773693e..41426d89 100644 --- a/app/src/main/kotlin/at/bitfire/davdroid/ui/account/AccountActivity.kt +++ b/app/src/main/kotlin/at/bitfire/davdroid/ui/account/AccountActivity.kt @@ -80,7 +80,7 @@ import at.bitfire.davdroid.db.Collection import at.bitfire.davdroid.servicedetection.RefreshCollectionsWorker import at.bitfire.davdroid.settings.AccountSettings import at.bitfire.davdroid.syncadapter.OneTimeSyncWorker -import at.bitfire.davdroid.ui.AppTheme +import at.bitfire.davdroid.ui.M2Theme import at.bitfire.davdroid.ui.PermissionsActivity import at.bitfire.davdroid.ui.composable.ActionCard import at.bitfire.davdroid.util.TaskUtils @@ -133,7 +133,7 @@ class AccountActivity : AppCompatActivity() { } setContent { - AppTheme { + M2Theme { val cardDavSvc by model.cardDavSvc.observeAsState() val canCreateAddressBook by model.canCreateAddressBook.observeAsState(false) val cardDavRefreshing by model.cardDavRefreshing.observeAsState(false) diff --git a/app/src/main/kotlin/at/bitfire/davdroid/ui/account/AccountSettingsActivity.kt b/app/src/main/kotlin/at/bitfire/davdroid/ui/account/AccountSettingsActivity.kt index 921529f9..95307269 100644 --- a/app/src/main/kotlin/at/bitfire/davdroid/ui/account/AccountSettingsActivity.kt +++ b/app/src/main/kotlin/at/bitfire/davdroid/ui/account/AccountSettingsActivity.kt @@ -67,7 +67,7 @@ import at.bitfire.davdroid.settings.AccountSettings import at.bitfire.davdroid.settings.SettingsManager import at.bitfire.davdroid.syncadapter.OneTimeSyncWorker import at.bitfire.davdroid.syncadapter.Syncer -import at.bitfire.davdroid.ui.AppTheme +import at.bitfire.davdroid.ui.M2Theme import at.bitfire.davdroid.ui.composable.ActionCard import at.bitfire.davdroid.ui.composable.EditTextInputDialog import at.bitfire.davdroid.ui.composable.MultipleChoiceInputDialog @@ -117,7 +117,7 @@ class AccountSettingsActivity: AppCompatActivity() { title = account.name setContent { - AppTheme { + M2Theme { val uriHandler = LocalUriHandler.current val snackbarHostState = remember { SnackbarHostState() } diff --git a/app/src/main/kotlin/at/bitfire/davdroid/ui/account/CreateAddressBookActivity.kt b/app/src/main/kotlin/at/bitfire/davdroid/ui/account/CreateAddressBookActivity.kt index a3f533fb..e0e8ddc8 100644 --- a/app/src/main/kotlin/at/bitfire/davdroid/ui/account/CreateAddressBookActivity.kt +++ b/app/src/main/kotlin/at/bitfire/davdroid/ui/account/CreateAddressBookActivity.kt @@ -46,7 +46,7 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider import at.bitfire.davdroid.R import at.bitfire.davdroid.db.HomeSet -import at.bitfire.davdroid.ui.AppTheme +import at.bitfire.davdroid.ui.M2Theme import at.bitfire.davdroid.ui.widget.ExceptionInfoDialog import dagger.hilt.android.AndroidEntryPoint import okhttp3.HttpUrl.Companion.toHttpUrl @@ -78,7 +78,7 @@ class CreateAddressBookActivity: AppCompatActivity() { super.onCreate(savedInstanceState) setContent { - AppTheme { + M2Theme { var displayName by remember { mutableStateOf("") } var description by remember { mutableStateOf("") } var homeSet by remember { mutableStateOf(null) } diff --git a/app/src/main/kotlin/at/bitfire/davdroid/ui/account/CreateCalendarActivity.kt b/app/src/main/kotlin/at/bitfire/davdroid/ui/account/CreateCalendarActivity.kt index 831bc40b..9a63d42b 100644 --- a/app/src/main/kotlin/at/bitfire/davdroid/ui/account/CreateCalendarActivity.kt +++ b/app/src/main/kotlin/at/bitfire/davdroid/ui/account/CreateCalendarActivity.kt @@ -62,7 +62,7 @@ import androidx.lifecycle.viewModelScope import at.bitfire.davdroid.Constants import at.bitfire.davdroid.R import at.bitfire.davdroid.db.HomeSet -import at.bitfire.davdroid.ui.AppTheme +import at.bitfire.davdroid.ui.M2Theme import at.bitfire.davdroid.ui.composable.MultipleChoiceInputDialog import at.bitfire.davdroid.ui.widget.CalendarColorPickerDialog import at.bitfire.davdroid.ui.widget.ExceptionInfoDialog @@ -104,7 +104,7 @@ class CreateCalendarActivity: AppCompatActivity() { super.onCreate(savedInstanceState) setContent { - AppTheme { + M2Theme { var displayName by remember { mutableStateOf("") } var color by remember { mutableIntStateOf(Constants.DAVDROID_GREEN_RGBA) } var description by remember { mutableStateOf("") } diff --git a/app/src/main/kotlin/at/bitfire/davdroid/ui/account/WifiPermissionsActivity.kt b/app/src/main/kotlin/at/bitfire/davdroid/ui/account/WifiPermissionsActivity.kt index 1fce8457..41731e61 100644 --- a/app/src/main/kotlin/at/bitfire/davdroid/ui/account/WifiPermissionsActivity.kt +++ b/app/src/main/kotlin/at/bitfire/davdroid/ui/account/WifiPermissionsActivity.kt @@ -52,7 +52,7 @@ import androidx.lifecycle.viewModelScope import at.bitfire.davdroid.Constants import at.bitfire.davdroid.Constants.withStatParams import at.bitfire.davdroid.R -import at.bitfire.davdroid.ui.AppTheme +import at.bitfire.davdroid.ui.M2Theme import at.bitfire.davdroid.ui.composable.PermissionSwitchRow import at.bitfire.davdroid.util.PermissionUtils import at.bitfire.davdroid.util.broadcastReceiverFlow @@ -78,7 +78,7 @@ class WifiPermissionsActivity: AppCompatActivity() { super.onCreate(savedInstanceState) setContent { - AppTheme { + M2Theme { Scaffold( topBar = { TopAppBar( diff --git a/app/src/main/kotlin/at/bitfire/davdroid/ui/intro/BatteryOptimizationsPage.kt b/app/src/main/kotlin/at/bitfire/davdroid/ui/intro/BatteryOptimizationsPage.kt index 5772ab43..4041454f 100644 --- a/app/src/main/kotlin/at/bitfire/davdroid/ui/intro/BatteryOptimizationsPage.kt +++ b/app/src/main/kotlin/at/bitfire/davdroid/ui/intro/BatteryOptimizationsPage.kt @@ -52,7 +52,7 @@ import at.bitfire.davdroid.Constants import at.bitfire.davdroid.Constants.withStatParams import at.bitfire.davdroid.R import at.bitfire.davdroid.settings.SettingsManager -import at.bitfire.davdroid.ui.AppTheme +import at.bitfire.davdroid.ui.M2Theme import at.bitfire.davdroid.ui.intro.BatteryOptimizationsPage.Model.Companion.HINT_AUTOSTART_PERMISSION import at.bitfire.davdroid.ui.intro.BatteryOptimizationsPage.Model.Companion.HINT_BATTERY_OPTIMIZATIONS import at.bitfire.davdroid.util.PermissionUtils @@ -224,7 +224,7 @@ class BatteryOptimizationsPage: IntroPage { @Preview(showBackground = true, showSystemUi = true) @Composable private fun BatteryOptimizationsContent_Preview() { - AppTheme { + M2Theme { BatteryOptimizationsContent( dontShowBattery = true, onChangeDontShowBattery = {}, diff --git a/app/src/main/kotlin/at/bitfire/davdroid/ui/intro/IntroActivity.kt b/app/src/main/kotlin/at/bitfire/davdroid/ui/intro/IntroActivity.kt index 280f88f3..f187c8d3 100644 --- a/app/src/main/kotlin/at/bitfire/davdroid/ui/intro/IntroActivity.kt +++ b/app/src/main/kotlin/at/bitfire/davdroid/ui/intro/IntroActivity.kt @@ -26,8 +26,8 @@ import androidx.fragment.app.Fragment import androidx.fragment.app.activityViewModels import androidx.lifecycle.AndroidViewModel import at.bitfire.davdroid.log.Logger -import at.bitfire.davdroid.ui.AppTheme -import at.bitfire.davdroid.ui.ThemeColors +import at.bitfire.davdroid.ui.M2Theme +import at.bitfire.davdroid.ui.M2Colors import com.github.appintro.AppIntro2 import dagger.hilt.EntryPoint import dagger.hilt.InstallIn @@ -73,7 +73,7 @@ class IntroActivity : AppIntro2() { }) } - setBarColor(ThemeColors.primaryDark.toArgb()) + setBarColor(M2Colors.primaryDark.toArgb()) isSkipButtonEnabled = false onBackPressedDispatcher.addCallback(this) { @@ -112,7 +112,7 @@ class IntroActivity : AppIntro2() { ComposeView(requireActivity()).apply { setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed) setContent { - AppTheme { + M2Theme { Box(Modifier.padding(bottom = dimensionResource(com.github.appintro.R.dimen.appintro2_bottombar_height))) { page.ComposePage() } diff --git a/app/src/main/kotlin/at/bitfire/davdroid/ui/intro/WelcomePage.kt b/app/src/main/kotlin/at/bitfire/davdroid/ui/intro/WelcomePage.kt index 6770cbf2..20ecb6c7 100644 --- a/app/src/main/kotlin/at/bitfire/davdroid/ui/intro/WelcomePage.kt +++ b/app/src/main/kotlin/at/bitfire/davdroid/ui/intro/WelcomePage.kt @@ -31,7 +31,7 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import at.bitfire.davdroid.R -import at.bitfire.davdroid.ui.ThemeColors.primaryDark +import at.bitfire.davdroid.ui.M2Colors.primaryDark class WelcomePage: IntroPage { diff --git a/app/src/main/kotlin/at/bitfire/davdroid/ui/setup/LoginActivity.kt b/app/src/main/kotlin/at/bitfire/davdroid/ui/setup/LoginActivity.kt index 58506627..17da55a6 100644 --- a/app/src/main/kotlin/at/bitfire/davdroid/ui/setup/LoginActivity.kt +++ b/app/src/main/kotlin/at/bitfire/davdroid/ui/setup/LoginActivity.kt @@ -10,7 +10,7 @@ import android.os.Bundle import androidx.activity.compose.setContent import androidx.appcompat.app.AppCompatActivity import at.bitfire.davdroid.db.Credentials -import at.bitfire.davdroid.ui.AppTheme +import at.bitfire.davdroid.ui.M2Theme import dagger.hilt.android.AndroidEntryPoint import java.net.URI import javax.inject.Inject @@ -118,7 +118,7 @@ class LoginActivity @Inject constructor(): AppCompatActivity() { super.onCreate(savedInstanceState) setContent { - AppTheme { + M2Theme { LoginScreen( loginTypesProvider = loginTypesProvider, initialLoginInfo = loginInfoFromIntent(intent), diff --git a/app/src/main/kotlin/at/bitfire/davdroid/ui/webdav/AddWebdavMountActivity.kt b/app/src/main/kotlin/at/bitfire/davdroid/ui/webdav/AddWebdavMountActivity.kt index 7cf67915..c9493a8c 100644 --- a/app/src/main/kotlin/at/bitfire/davdroid/ui/webdav/AddWebdavMountActivity.kt +++ b/app/src/main/kotlin/at/bitfire/davdroid/ui/webdav/AddWebdavMountActivity.kt @@ -59,7 +59,7 @@ import at.bitfire.davdroid.db.Credentials import at.bitfire.davdroid.db.WebDavMount import at.bitfire.davdroid.log.Logger import at.bitfire.davdroid.network.HttpClient -import at.bitfire.davdroid.ui.AppTheme +import at.bitfire.davdroid.ui.M2Theme import at.bitfire.davdroid.ui.composable.PasswordTextField import at.bitfire.davdroid.webdav.CredentialsStore import at.bitfire.davdroid.webdav.DavDocumentsProvider @@ -93,7 +93,7 @@ class AddWebdavMountActivity : AppCompatActivity() { val username by model.userName.observeAsState(initial = "") val password by model.password.observeAsState(initial = "") - AppTheme { + M2Theme { Layout( isLoading = isLoading, error = error, @@ -303,7 +303,7 @@ class AddWebdavMountActivity : AppCompatActivity() { @Preview @Composable fun Layout_Preview() { - AppTheme { + M2Theme { Layout() } } diff --git a/app/src/main/kotlin/at/bitfire/davdroid/ui/webdav/WebdavMountsActivity.kt b/app/src/main/kotlin/at/bitfire/davdroid/ui/webdav/WebdavMountsActivity.kt index 609351b8..90b156fe 100644 --- a/app/src/main/kotlin/at/bitfire/davdroid/ui/webdav/WebdavMountsActivity.kt +++ b/app/src/main/kotlin/at/bitfire/davdroid/ui/webdav/WebdavMountsActivity.kt @@ -65,7 +65,7 @@ import at.bitfire.davdroid.db.AppDatabase import at.bitfire.davdroid.db.WebDavDocument import at.bitfire.davdroid.db.WebDavMount import at.bitfire.davdroid.log.Logger -import at.bitfire.davdroid.ui.AppTheme +import at.bitfire.davdroid.ui.M2Theme import at.bitfire.davdroid.ui.UiUtils.toAnnotatedString import at.bitfire.davdroid.ui.widget.ClickableTextWithLink import at.bitfire.davdroid.util.DavUtils @@ -104,7 +104,7 @@ class WebdavMountsActivity: AppCompatActivity() { super.onCreate(savedInstanceState) setContent { - AppTheme { + M2Theme { val mountInfos by model.mountInfos.observeAsState(emptyList()) WebdavMountsContent(mountInfos) } @@ -328,7 +328,7 @@ class WebdavMountsActivity: AppCompatActivity() { @Preview(showBackground = true, showSystemUi = true) @Composable fun WebdavMountsContent_Preview() { - AppTheme { + M2Theme { WebdavMountsContent(emptyList()) } } @@ -336,7 +336,7 @@ class WebdavMountsActivity: AppCompatActivity() { @Preview(showBackground = true) @Composable fun WebdavMountsItem_Preview() { - AppTheme { + M2Theme { WebdavMountsItem( info = MountInfo( mount = WebDavMount( diff --git a/app/src/main/kotlin/at/bitfire/davdroid/ui/widget/SyncButtonWidget.kt b/app/src/main/kotlin/at/bitfire/davdroid/ui/widget/SyncButtonWidget.kt index 1ba5e921..861690f5 100644 --- a/app/src/main/kotlin/at/bitfire/davdroid/ui/widget/SyncButtonWidget.kt +++ b/app/src/main/kotlin/at/bitfire/davdroid/ui/widget/SyncButtonWidget.kt @@ -31,8 +31,8 @@ import androidx.glance.text.TextDefaults import androidx.glance.unit.ColorProvider import at.bitfire.davdroid.R import at.bitfire.davdroid.syncadapter.OneTimeSyncWorker -import at.bitfire.davdroid.ui.ThemeColors.onPrimary -import at.bitfire.davdroid.ui.ThemeColors.primary +import at.bitfire.davdroid.ui.M2Colors.onPrimary +import at.bitfire.davdroid.ui.M2Colors.primary import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch diff --git a/app/src/ose/kotlin/at/bitfire/davdroid/ui/OpenSourceLicenseInfoProvider.kt b/app/src/ose/kotlin/at/bitfire/davdroid/ui/OpenSourceLicenseInfoProvider.kt index aff93489..5a31a2ac 100644 --- a/app/src/ose/kotlin/at/bitfire/davdroid/ui/OpenSourceLicenseInfoProvider.kt +++ b/app/src/ose/kotlin/at/bitfire/davdroid/ui/OpenSourceLicenseInfoProvider.kt @@ -6,17 +6,18 @@ package at.bitfire.davdroid.ui import android.app.Application import android.text.Spanned -import androidx.compose.material.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.livedata.observeAsState +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.setValue import androidx.compose.ui.text.AnnotatedString import androidx.compose.ui.tooling.preview.Preview import androidx.core.text.HtmlCompat import androidx.lifecycle.AndroidViewModel -import androidx.lifecycle.MutableLiveData import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewmodel.compose.viewModel import at.bitfire.davdroid.ui.UiUtils.toAnnotatedString +import at.bitfire.davdroid.ui.widget.ClickableTextWithLink import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -34,23 +35,20 @@ class OpenSourceLicenseInfoProvider @Inject constructor(): AboutActivity.AppLice fun LicenseInfoGpl( model: Model = viewModel() ) { - model.gpl.observeAsState().value?.let { gpl -> - OpenSourceLicenseInfo(gpl.toAnnotatedString()) - } + model.gpl?.let { OpenSourceLicenseInfo(it.toAnnotatedString()) } } @HiltViewModel class Model @Inject constructor(app: Application): AndroidViewModel(app) { - val gpl = MutableLiveData() + var gpl by mutableStateOf(null) init { viewModelScope.launch(Dispatchers.IO) { app.resources.assets.open("gplv3.html").use { inputStream -> val raw = IOUtils.toString(inputStream, Charsets.UTF_8) - val html = HtmlCompat.fromHtml(raw, HtmlCompat.FROM_HTML_MODE_LEGACY) - gpl.postValue(html) + gpl = HtmlCompat.fromHtml(raw, HtmlCompat.FROM_HTML_MODE_LEGACY) } } } @@ -62,7 +60,7 @@ class OpenSourceLicenseInfoProvider @Inject constructor(): AboutActivity.AppLice @Composable fun OpenSourceLicenseInfo(license: AnnotatedString) { - Text(license) + ClickableTextWithLink(license) } @Composable diff --git a/app/src/ose/kotlin/at/bitfire/davdroid/ui/ThemeColors.kt b/app/src/ose/kotlin/at/bitfire/davdroid/ui/ThemeColors.kt index dcd4f908..4b30e72b 100644 --- a/app/src/ose/kotlin/at/bitfire/davdroid/ui/ThemeColors.kt +++ b/app/src/ose/kotlin/at/bitfire/davdroid/ui/ThemeColors.kt @@ -5,9 +5,11 @@ package at.bitfire.davdroid.ui import androidx.compose.material.Colors +import androidx.compose.material3.darkColorScheme +import androidx.compose.material3.lightColorScheme import androidx.compose.ui.graphics.Color -object ThemeColors { +object M2Colors { private val grey100 = Color(0xfff5f5f5) private val grey200 = Color(0xffeeeeee) @@ -54,4 +56,136 @@ object ThemeColors { isLight = false ) +} + +object M3ColorScheme { + + val md_theme_light_primary = Color(0xFF3C6A00) + val md_theme_light_onPrimary = Color(0xFFFFFFFF) + val md_theme_light_primaryContainer = Color(0xFFB8F47A) + val md_theme_light_onPrimaryContainer = Color(0xFF0E2000) + val md_theme_light_secondary = Color(0xFF3C6A00) + val md_theme_light_onSecondary = Color(0xFFFFFFFF) + val md_theme_light_secondaryContainer = Color(0xFFB8F47A) + val md_theme_light_onSecondaryContainer = Color(0xFF0E2000) + val md_theme_light_tertiary = Color(0xFF964900) + val md_theme_light_onTertiary = Color(0xFFFFFFFF) + val md_theme_light_tertiaryContainer = Color(0xFFFFDCC7) + val md_theme_light_onTertiaryContainer = Color(0xFF311300) + val md_theme_light_error = Color(0xFFBA1A1A) + val md_theme_light_errorContainer = Color(0xFFFFDAD6) + val md_theme_light_onError = Color(0xFFFFFFFF) + val md_theme_light_onErrorContainer = Color(0xFF410002) + val md_theme_light_background = Color(0xFFF8FDFF) + val md_theme_light_onBackground = Color(0xFF001F25) + val md_theme_light_surface = Color(0xFFF8FDFF) + val md_theme_light_onSurface = Color(0xFF001F25) + val md_theme_light_surfaceVariant = Color(0xFFE1E4D5) + val md_theme_light_onSurfaceVariant = Color(0xFF44483D) + val md_theme_light_outline = Color(0xFF75796C) + val md_theme_light_inverseOnSurface = Color(0xFFD6F6FF) + val md_theme_light_inverseSurface = Color(0xFF00363F) + val md_theme_light_inversePrimary = Color(0xFF9DD761) + val md_theme_light_shadow = Color(0xFF000000) + val md_theme_light_surfaceTint = Color(0xFF3C6A00) + val md_theme_light_outlineVariant = Color(0xFFC4C8BA) + val md_theme_light_scrim = Color(0xFF000000) + + val md_theme_dark_primary = Color(0xFF9DD761) + val md_theme_dark_onPrimary = Color(0xFF1D3700) + val md_theme_dark_primaryContainer = Color(0xFF2C5000) + val md_theme_dark_onPrimaryContainer = Color(0xFFB8F47A) + val md_theme_dark_secondary = Color(0xFF9DD761) + val md_theme_dark_onSecondary = Color(0xFF1D3700) + val md_theme_dark_secondaryContainer = Color(0xFF2C5000) + val md_theme_dark_onSecondaryContainer = Color(0xFFB8F47A) + val md_theme_dark_tertiary = Color(0xFFFFB787) + val md_theme_dark_onTertiary = Color(0xFF502400) + val md_theme_dark_tertiaryContainer = Color(0xFF723600) + val md_theme_dark_onTertiaryContainer = Color(0xFFFFDCC7) + val md_theme_dark_error = Color(0xFFFFB4AB) + val md_theme_dark_errorContainer = Color(0xFF93000A) + val md_theme_dark_onError = Color(0xFF690005) + val md_theme_dark_onErrorContainer = Color(0xFFFFDAD6) + val md_theme_dark_background = Color(0xFF001F25) + val md_theme_dark_onBackground = Color(0xFFA6EEFF) + val md_theme_dark_surface = Color(0xFF001F25) + val md_theme_dark_onSurface = Color(0xFFA6EEFF) + val md_theme_dark_surfaceVariant = Color(0xFF44483D) + val md_theme_dark_onSurfaceVariant = Color(0xFFC4C8BA) + val md_theme_dark_outline = Color(0xFF8E9285) + val md_theme_dark_inverseOnSurface = Color(0xFF001F25) + val md_theme_dark_inverseSurface = Color(0xFFA6EEFF) + val md_theme_dark_inversePrimary = Color(0xFF3C6A00) + val md_theme_dark_shadow = Color(0xFF000000) + val md_theme_dark_surfaceTint = Color(0xFF9DD761) + val md_theme_dark_outlineVariant = Color(0xFF44483D) + val md_theme_dark_scrim = Color(0xFF000000) + + val seed = Color(0xFF7CB342) + + val LightColors = lightColorScheme( + primary = md_theme_light_primary, + onPrimary = md_theme_light_onPrimary, + primaryContainer = md_theme_light_primaryContainer, + onPrimaryContainer = md_theme_light_onPrimaryContainer, + secondary = md_theme_light_secondary, + onSecondary = md_theme_light_onSecondary, + secondaryContainer = md_theme_light_secondaryContainer, + onSecondaryContainer = md_theme_light_onSecondaryContainer, + tertiary = md_theme_light_tertiary, + onTertiary = md_theme_light_onTertiary, + tertiaryContainer = md_theme_light_tertiaryContainer, + onTertiaryContainer = md_theme_light_onTertiaryContainer, + error = md_theme_light_error, + errorContainer = md_theme_light_errorContainer, + onError = md_theme_light_onError, + onErrorContainer = md_theme_light_onErrorContainer, + background = md_theme_light_background, + onBackground = md_theme_light_onBackground, + surface = md_theme_light_surface, + onSurface = md_theme_light_onSurface, + surfaceVariant = md_theme_light_surfaceVariant, + onSurfaceVariant = md_theme_light_onSurfaceVariant, + outline = md_theme_light_outline, + inverseOnSurface = md_theme_light_inverseOnSurface, + inverseSurface = md_theme_light_inverseSurface, + inversePrimary = md_theme_light_inversePrimary, + surfaceTint = md_theme_light_surfaceTint, + outlineVariant = md_theme_light_outlineVariant, + scrim = md_theme_light_scrim, + ) + + val DarkColors = darkColorScheme( + primary = md_theme_dark_primary, + onPrimary = md_theme_dark_onPrimary, + primaryContainer = md_theme_dark_primaryContainer, + onPrimaryContainer = md_theme_dark_onPrimaryContainer, + secondary = md_theme_dark_secondary, + onSecondary = md_theme_dark_onSecondary, + secondaryContainer = md_theme_dark_secondaryContainer, + onSecondaryContainer = md_theme_dark_onSecondaryContainer, + tertiary = md_theme_dark_tertiary, + onTertiary = md_theme_dark_onTertiary, + tertiaryContainer = md_theme_dark_tertiaryContainer, + onTertiaryContainer = md_theme_dark_onTertiaryContainer, + error = md_theme_dark_error, + errorContainer = md_theme_dark_errorContainer, + onError = md_theme_dark_onError, + onErrorContainer = md_theme_dark_onErrorContainer, + background = md_theme_dark_background, + onBackground = md_theme_dark_onBackground, + surface = md_theme_dark_surface, + onSurface = md_theme_dark_onSurface, + surfaceVariant = md_theme_dark_surfaceVariant, + onSurfaceVariant = md_theme_dark_onSurfaceVariant, + outline = md_theme_dark_outline, + inverseOnSurface = md_theme_dark_inverseOnSurface, + inverseSurface = md_theme_dark_inverseSurface, + inversePrimary = md_theme_dark_inversePrimary, + surfaceTint = md_theme_dark_surfaceTint, + outlineVariant = md_theme_dark_outlineVariant, + scrim = md_theme_dark_scrim, + ) + } \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 7de09152..016e204d 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -98,6 +98,7 @@ commons-text = { module = "org.apache.commons:commons-text", version.ref = "comm compose-accompanist-permissions = { module = "com.google.accompanist:accompanist-permissions", version.ref = "compose-accompanist" } compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "compose-bom" } compose-material = { module = "androidx.compose.material:material" } +compose-material3 = { group = "androidx.compose.material3", name = "material3" } compose-materialIconsExtended = { module = "androidx.compose.material:material-icons-extended" } compose-runtime-livedata = { module = "androidx.compose.runtime:runtime-livedata" } compose-ui-tooling = { module = "androidx.compose.ui:ui-tooling" } @@ -111,7 +112,7 @@ hilt-android-testing = { module = "com.google.dagger:hilt-android-testing", vers junit = { module = "junit:junit", version = "4.13.2" } kotlin-stdlib = { module = "org.jetbrains.kotlin:kotlin-stdlib", version.ref = "kotlin" } kotlinx-coroutines = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinx-coroutines" } -mikepenz-aboutLibraries = { module = "com.mikepenz:aboutlibraries-compose", version.ref = "mikepenz-aboutLibraries" } +mikepenz-aboutLibraries = { module = "com.mikepenz:aboutlibraries-compose-m3", version.ref = "mikepenz-aboutLibraries" } mockk-android = { module = "io.mockk:mockk-android", version.ref = "mockk" } nsk90-kstatemachine = { module = "io.github.nsk90:kstatemachine-jvm", version.ref = "nsk90-kstatemachine" } okhttp-base = { module = "com.squareup.okhttp3:okhttp", version.ref = "okhttp" }