From 60e64f5ded5a0572e8699b4938aa36b4b0659087 Mon Sep 17 00:00:00 2001 From: Evan Strat <evan10s@users.noreply.github.com> Date: Thu, 25 May 2023 00:07:52 -0400 Subject: [PATCH 01/33] Target SDK 33 --- app/build.gradle.kts | 4 ++-- attendance/build.gradle.kts | 4 ++-- auth/build.gradle.kts | 4 ++-- base/build.gradle.kts | 4 ++-- build.gradle.kts | 4 ++-- navigation/build.gradle.kts | 4 ++-- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 253413f..fb6bd83 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -71,11 +71,11 @@ android { create("release") { } } - compileSdk = 32 + compileSdk = 33 defaultConfig { applicationId = "org.robojackets.apiary" minSdk = 21 - targetSdk = 32 + targetSdk = 33 versionCode = 12 versionName = "1.0.0" vectorDrawables { diff --git a/attendance/build.gradle.kts b/attendance/build.gradle.kts index 4953318..cbcb6a4 100644 --- a/attendance/build.gradle.kts +++ b/attendance/build.gradle.kts @@ -46,10 +46,10 @@ dependencies { } android { - compileSdk = 32 + compileSdk = 33 defaultConfig { minSdk = 21 - targetSdk = 32 + targetSdk = 33 vectorDrawables { useSupportLibrary = true } diff --git a/auth/build.gradle.kts b/auth/build.gradle.kts index e6c79a8..1406388 100644 --- a/auth/build.gradle.kts +++ b/auth/build.gradle.kts @@ -52,10 +52,10 @@ dependencies { } android { - compileSdk = 32 + compileSdk = 33 defaultConfig { minSdk = 21 - targetSdk = 32 + targetSdk = 33 vectorDrawables { useSupportLibrary = true diff --git a/base/build.gradle.kts b/base/build.gradle.kts index ac41121..aba2aaf 100644 --- a/base/build.gradle.kts +++ b/base/build.gradle.kts @@ -44,10 +44,10 @@ hilt { } android { - compileSdk = 32 + compileSdk = 33 defaultConfig { minSdk = 21 - targetSdk = 32 + targetSdk = 33 vectorDrawables { useSupportLibrary = true diff --git a/build.gradle.kts b/build.gradle.kts index 9114a2d..8d8f272 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -9,8 +9,8 @@ buildscript { classpath("com.android.tools.build:gradle:7.3.1") classpath("com.google.dagger:hilt-android-gradle-plugin:2.40.1") classpath("com.google.android.libraries.mapsplatform.secrets-gradle-plugin:secrets-gradle-plugin:2.0.1") - classpath("com.google.gms:google-services:4.3.10") - classpath("com.google.android.gms:oss-licenses-plugin:0.10.5") + classpath("com.google.gms:google-services:4.3.15") + classpath("com.google.android.gms:oss-licenses-plugin:0.10.6") } } diff --git a/navigation/build.gradle.kts b/navigation/build.gradle.kts index 643e28b..980ebbf 100644 --- a/navigation/build.gradle.kts +++ b/navigation/build.gradle.kts @@ -31,10 +31,10 @@ dependencies { } android { - compileSdk = 32 + compileSdk = 33 defaultConfig { minSdk = 21 - targetSdk = 32 + targetSdk = 33 vectorDrawables { useSupportLibrary = true From 18e0b499deee0c90315f0cb1ddeee14cc1c75747 Mon Sep 17 00:00:00 2001 From: Evan Strat <evan10s@users.noreply.github.com> Date: Thu, 25 May 2023 01:35:22 -0400 Subject: [PATCH 02/33] Update dependency versions --- app/build.gradle.kts | 10 ++--- .../apiary/di/MainActivityModule.kt | 4 +- attendance/build.gradle.kts | 10 ++--- auth/build.gradle.kts | 8 ++-- base/build.gradle.kts | 10 ++--- build.gradle.kts | 16 +++---- buildSrc/src/main/java/Dependencies.kt | 45 +++++++++---------- gradle.properties | 5 ++- gradle/wrapper/gradle-wrapper.properties | 2 +- navigation/build.gradle.kts | 8 ++-- 10 files changed, 59 insertions(+), 59 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index fb6bd83..7ac1cdf 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -54,7 +54,7 @@ dependencies { implementation(NetworkDependencies.sandwich) // yum yum implementation(platform(NfcDependencies.nfc_firebase_bom)) - implementation(NfcDependencies.nfc_firebase_core) // Firebase BoM and Core are required when including TapLinx (line below) manually + implementation(NfcDependencies.nfc_firebase_analytics) // Firebase BoM and Analytics (f/k/a Core) are required when including TapLinx (line below) manually implementation(files(NfcDependencies.nxp_nfc_android_aar_path)) // Test dependencies @@ -92,15 +92,15 @@ android { compose = true } compileOptions { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 isCoreLibraryDesugaringEnabled = true } kotlinOptions { - jvmTarget = "1.8" + jvmTarget = "17" } composeOptions { - kotlinCompilerExtensionVersion = "1.2.0-beta03" + kotlinCompilerExtensionVersion = "1.4.7" } namespace = "org.robojackets.apiary" hilt { diff --git a/app/src/main/java/org/robojackets/apiary/di/MainActivityModule.kt b/app/src/main/java/org/robojackets/apiary/di/MainActivityModule.kt index e63cb91..e6be8c7 100644 --- a/app/src/main/java/org/robojackets/apiary/di/MainActivityModule.kt +++ b/app/src/main/java/org/robojackets/apiary/di/MainActivityModule.kt @@ -2,7 +2,7 @@ package org.robojackets.apiary.di import android.content.Context import com.nxp.nfclib.NxpNfcLib -import com.skydoves.sandwich.coroutines.CoroutinesResponseCallAdapterFactory +import com.skydoves.sandwich.adapters.ApiResponseCallAdapterFactory import com.squareup.moshi.Moshi import com.squareup.moshi.Types import dagger.Module @@ -76,7 +76,7 @@ object MainActivityModule { ): Retrofit = Retrofit.Builder() .client(okHttpClient) .baseUrl(globalSettings.appEnv.apiBaseUrl.toString()) - .addCallAdapterFactory(CoroutinesResponseCallAdapterFactory.create()) + .addCallAdapterFactory(ApiResponseCallAdapterFactory.create()) .addConverterFactory(MoshiConverterFactory.create(moshi)) .build() diff --git a/attendance/build.gradle.kts b/attendance/build.gradle.kts index cbcb6a4..d623c34 100644 --- a/attendance/build.gradle.kts +++ b/attendance/build.gradle.kts @@ -36,7 +36,7 @@ dependencies { implementation(NetworkDependencies.sandwich) implementation(platform(NfcDependencies.nfc_firebase_bom)) - implementation(NfcDependencies.nfc_firebase_core) // Firebase BoM and Core are required when including TapLinx (line below) manually + implementation(NfcDependencies.nfc_firebase_analytics) // Firebase BoM and Analytics (f/k/a Core) are required when including TapLinx (line below) manually compileOnly(files(NfcDependencies.nxp_nfc_android_aar_path)) // Test dependencies @@ -63,15 +63,15 @@ android { compose = true } compileOptions { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 isCoreLibraryDesugaringEnabled = true } kotlinOptions { - jvmTarget = "1.8" + jvmTarget = "17" } composeOptions { - kotlinCompilerExtensionVersion = "1.2.0-beta03" + kotlinCompilerExtensionVersion = "1.4.7" } namespace = "org.robojackets.apiary.attendance" hilt { diff --git a/auth/build.gradle.kts b/auth/build.gradle.kts index 1406388..7cb2b00 100644 --- a/auth/build.gradle.kts +++ b/auth/build.gradle.kts @@ -71,15 +71,15 @@ android { compose = true } compileOptions { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 isCoreLibraryDesugaringEnabled = true } kotlinOptions { - jvmTarget = "1.8" + jvmTarget = "17" } composeOptions { - kotlinCompilerExtensionVersion = "1.2.0-beta03" + kotlinCompilerExtensionVersion = "1.4.7" } namespace = "org.robojackets.apiary.auth" hilt { diff --git a/base/build.gradle.kts b/base/build.gradle.kts index aba2aaf..f4a15c0 100644 --- a/base/build.gradle.kts +++ b/base/build.gradle.kts @@ -31,7 +31,7 @@ dependencies { implementation(NetworkDependencies.sandwich) implementation(platform(NfcDependencies.nfc_firebase_bom)) - implementation(NfcDependencies.nfc_firebase_core) // Firebase BoM and Core are required when including TapLinx (line below) manually + implementation(NfcDependencies.nfc_firebase_analytics) // Firebase BoM and Analytics (f/k/a Core) are required when including TapLinx (line below) manually compileOnly(files(NfcDependencies.nxp_nfc_android_aar_path)) // Test dependencies @@ -62,15 +62,15 @@ android { compose = true } compileOptions { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 isCoreLibraryDesugaringEnabled = true } kotlinOptions { - jvmTarget = "1.8" + jvmTarget = "17" } composeOptions { - kotlinCompilerExtensionVersion = "1.2.0-beta03" + kotlinCompilerExtensionVersion = "1.4.7" } namespace = "org.robojackets.apiary.base" hilt { diff --git a/build.gradle.kts b/build.gradle.kts index 8d8f272..353df25 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -5,9 +5,9 @@ buildscript { mavenCentral() } dependencies { - classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.21") - classpath("com.android.tools.build:gradle:7.3.1") - classpath("com.google.dagger:hilt-android-gradle-plugin:2.40.1") + classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.21") + classpath("com.android.tools.build:gradle:8.0.1") + classpath("com.google.dagger:hilt-android-gradle-plugin:2.46.1") classpath("com.google.android.libraries.mapsplatform.secrets-gradle-plugin:secrets-gradle-plugin:2.0.1") classpath("com.google.gms:google-services:4.3.15") classpath("com.google.android.gms:oss-licenses-plugin:0.10.6") @@ -29,14 +29,14 @@ allprojects { } plugins { - id("io.gitlab.arturbosch.detekt").version("1.20.0") - id("com.autonomousapps.dependency-analysis").version("1.4.0") - id("com.github.ben-manes.versions").version("0.42.0") + id("io.gitlab.arturbosch.detekt").version("1.23.0") + id("com.autonomousapps.dependency-analysis").version("1.20.0") + id("com.github.ben-manes.versions").version("0.46.0") } tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile>().configureEach { kotlinOptions { - jvmTarget = "1.8" + jvmTarget = "17" } } @@ -71,7 +71,7 @@ tasks.register("detektAll", io.gitlab.arturbosch.detekt.Detekt::class) { } dependencies { - detektPlugins("io.gitlab.arturbosch.detekt:detekt-formatting:1.16.0") + detektPlugins("io.gitlab.arturbosch.detekt:detekt-formatting:1.22.0") } // from https://github.com/autonomousapps/dependency-analysis-android-gradle-plugin/wiki/ABI-filtering diff --git a/buildSrc/src/main/java/Dependencies.kt b/buildSrc/src/main/java/Dependencies.kt index e14fabe..056f4db 100644 --- a/buildSrc/src/main/java/Dependencies.kt +++ b/buildSrc/src/main/java/Dependencies.kt @@ -1,9 +1,9 @@ object ComposeDependencies { object Versions { - const val accompanist_version = "0.25.0" - const val compose_settings_version = "0.7.2" - const val compose_version = "1.1.1" - const val lifecycle_viewmodel_compose_version = "2.4.1" + const val accompanist_version = "0.30.1" + const val compose_settings_version = "0.27.0" + const val compose_version = "1.4.3" + const val lifecycle_viewmodel_compose_version = "2.6.1" } const val accompanist_systemuicontroller = @@ -37,7 +37,7 @@ object ComposeDependencies { object MaterialDependencies { object Versions { - const val material_android_version = "1.6.1" + const val material_android_version = "1.9.0" } const val material_android = @@ -46,11 +46,11 @@ object MaterialDependencies { object AndroidXDependencies { object Versions { - const val androidx_activity_compose_version = "1.4.0" - const val androidx_appcompat_version = "1.4.2" - const val androidx_browser_version = "1.4.0" - const val androidx_lifecycle_runtime_ktx_version = "2.4.1" - const val androidx_navigation_compose_version = "2.4.2" + const val androidx_activity_compose_version = "1.7.2" + const val androidx_appcompat_version = "1.6.1" + const val androidx_browser_version = "1.5.0" + const val androidx_lifecycle_runtime_ktx_version = "2.6.1" + const val androidx_navigation_compose_version = "2.5.3" } const val androidx_activity_compose = @@ -66,19 +66,16 @@ object AndroidXDependencies { object FirebaseDependencies { object Versions { - const val firebase_bom_version = "30.1.0" + const val firebase_bom_version = "32.0.0" } const val firebase_bom = "com.google.firebase:firebase-bom:${Versions.firebase_bom_version}" - const val firebase_core = "com.google.firebase:firebase-core" // No explicit version specified - // because of the inclusion of the Firebase BOM + const val firebase_analytics = "com.google.firebase:firebase-analytics-ktx" // versioned by BOM } object NfcDependencies { const val nfc_firebase_bom = FirebaseDependencies.firebase_bom - const val nfc_firebase_core = FirebaseDependencies.firebase_core // Duplicate definition - // with the goal of clarifying that the inclusion of Firebase Core here is specifically for - // the NXP NFC (TapLinx) library + const val nfc_firebase_analytics = FirebaseDependencies.firebase_analytics const val nxp_nfc_android_aar_path = "../libs/nxpnfcandroidlib-release.aar" } @@ -93,7 +90,7 @@ object AuthDependencies { object HiltDependencies { object Versions { const val hilt_navigation_compose_version = "1.0.0" - const val hilt_version = "2.42" + const val hilt_version = "2.44" } const val hilt = "com.google.dagger:hilt-android:${Versions.hilt_version}" @@ -107,10 +104,10 @@ object AndroidToolDependencies { object Versions { const val android_tools_desugar_version = "1.1.5" const val krate_version = "2.0.0" - const val gson_version = "2.9.0" - const val in_app_update_compose_version = "0.0.16" - const val open_source_licenses_version = "17.0.0" - const val sentry_version = "5.7.3" + const val gson_version = "2.10.1" + const val in_app_update_compose_version = "0.0.17" + const val open_source_licenses_version = "17.0.1" + const val sentry_version = "6.19.1" const val timber_version = "5.0.1" } @@ -129,12 +126,12 @@ object AndroidToolDependencies { object NetworkDependencies { object Versions { - const val moshi_version = "1.13.0" + const val moshi_version = "1.15.0" const val moshi_converter_factory_version = "2.9.0" - const val okhttp_bom_version = "4.9.3" + const val okhttp_bom_version = "4.11.0" const val retrofit_version = "2.9.0" const val retrofuture_version = "1.7.4" - const val sandwich_version = "1.2.5" + const val sandwich_version = "1.3.6" } const val moshi = "com.squareup.moshi:moshi:${Versions.moshi_version}" diff --git a/gradle.properties b/gradle.properties index 1728bde..20edcb1 100644 --- a/gradle.properties +++ b/gradle.properties @@ -5,4 +5,7 @@ org.gradle.jvmargs=-Xmx2048M -Dkotlin.daemon.jvm.options\="-Xmx2048M" kotlin.code.style=official #Android -android.useAndroidX=true \ No newline at end of file +android.useAndroidX=true +android.defaults.buildfeatures.buildconfig=true +android.nonTransitiveRClass=true +android.nonFinalResIds=true \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 6ee0b26..142d4cd 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ #Wed Dec 15 17:03:27 EST 2021 distributionBase=GRADLE_USER_HOME -distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-all.zip distributionPath=wrapper/dists zipStorePath=wrapper/dists zipStoreBase=GRADLE_USER_HOME diff --git a/navigation/build.gradle.kts b/navigation/build.gradle.kts index 980ebbf..f293d8a 100644 --- a/navigation/build.gradle.kts +++ b/navigation/build.gradle.kts @@ -50,14 +50,14 @@ android { } compileOptions { isCoreLibraryDesugaringEnabled = true - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 } kotlinOptions { - jvmTarget = "1.8" + jvmTarget = "17" } composeOptions { - kotlinCompilerExtensionVersion = "1.2.0-beta03" + kotlinCompilerExtensionVersion = "1.4.7" } namespace = "org.robojackets.apiary.navigation" hilt { From 3f9a8d932f4c194ed47359d4d1fab0a9f85aa804 Mon Sep 17 00:00:00 2001 From: Evan Strat <evan10s@users.noreply.github.com> Date: Sun, 20 Aug 2023 01:26:46 -0400 Subject: [PATCH 03/33] First pass at M3 update --- app/build.gradle.kts | 2 +- .../apiary/ApiaryMobileApplication.kt | 4 +- .../org/robojackets/apiary/MainActivity.kt | 17 ++++++--- .../robojackets/apiary/ui/global/AppTopBar.kt | 17 +++++---- .../apiary/ui/settings/Settings.kt | 8 ++-- .../apiary/ui/update/UpdateAvailable.kt | 16 ++++++-- .../apiary/ui/update/UpdateGate.kt | 2 +- attendance/build.gradle.kts | 1 + .../apiary/attendance/Attendance.kt | 11 ++++-- .../attendance/ui/AttendableSelection.kt | 17 ++++++--- .../ui/AttendableTypeSelectionScreen.kt | 37 +++++++++++++------ auth/build.gradle.kts | 1 + .../apiary/auth/ui/Authentication.kt | 27 +++++++++++--- .../ui/permissions/InsufficientPermissions.kt | 27 +++++++++----- .../permissions/MissingHiddenTeamsCallout.kt | 4 +- base/build.gradle.kts | 3 ++ .../apiary/base/ui/ActionPrompt.kt | 14 ++++--- .../apiary/base/ui/IconWithText.kt | 2 +- .../apiary/base/ui/callout/Callout.kt | 11 ++++-- .../apiary/base/ui/error/ErrorMessage.kt | 14 +++++-- .../apiary/base/ui/icons/ExtraIcons.kt | 23 ++++++------ .../apiary/base/ui/nfc/BuzzCardPrompt.kt | 14 ++++++- .../apiary/base/ui/nfc/NfcRequired.kt | 13 +++++-- .../robojackets/apiary/base/ui/theme/Shape.kt | 2 +- .../robojackets/apiary/base/ui/theme/Theme.kt | 21 +++++++++-- .../robojackets/apiary/base/ui/theme/Type.kt | 7 ++-- .../apiary/base/ui/util/LoadingSpinner.kt | 2 +- .../apiary/base/ui/util/MadeWithLove.kt | 2 +- build.gradle.kts | 2 +- buildSrc/src/main/java/Dependencies.kt | 6 ++- 30 files changed, 223 insertions(+), 104 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 7ac1cdf..9edde41 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -37,11 +37,11 @@ dependencies { implementation(ComposeDependencies.compose_ui_tooling) implementation(ComposeDependencies.compose_foundation) implementation(ComposeDependencies.compose_material) + implementation(ComposeDependencies.compose_material3) implementation(ComposeDependencies.compose_material_icons_core) implementation(ComposeDependencies.compose_material_icons_extended) implementation(ComposeDependencies.compose_settings) - implementation(HiltDependencies.hilt) kapt(HiltDependencies.hilt_android_compiler) implementation(HiltDependencies.hilt_navigation_compose) diff --git a/app/src/main/java/org/robojackets/apiary/ApiaryMobileApplication.kt b/app/src/main/java/org/robojackets/apiary/ApiaryMobileApplication.kt index 535df50..27fc2f8 100644 --- a/app/src/main/java/org/robojackets/apiary/ApiaryMobileApplication.kt +++ b/app/src/main/java/org/robojackets/apiary/ApiaryMobileApplication.kt @@ -8,8 +8,8 @@ import io.sentry.android.timber.SentryTimberIntegration import timber.log.Timber // Note: this class has to be in the same module as the @AndroidEntryPoint annotated class, which -// is MainActivity. In other words, you can't move this class to another module to solve -// dependency issues (use dependency injection instead!). +// is MainActivity. In other words, you can't move this class to another module to solve dependency +// issues (use dependency injection instead!). @HiltAndroidApp class ApiaryMobileApplication : Application() { override fun onCreate() { diff --git a/app/src/main/java/org/robojackets/apiary/MainActivity.kt b/app/src/main/java/org/robojackets/apiary/MainActivity.kt index ae3f25e..69036fc 100644 --- a/app/src/main/java/org/robojackets/apiary/MainActivity.kt +++ b/app/src/main/java/org/robojackets/apiary/MainActivity.kt @@ -8,10 +8,17 @@ import androidx.activity.compose.setContent import androidx.annotation.StringRes import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.padding -import androidx.compose.material.* +import androidx.compose.material.ExperimentalMaterialApi import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Settings import androidx.compose.material.icons.outlined.Contactless +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.NavigationBar +import androidx.compose.material3.NavigationBarItem +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Surface +import androidx.compose.material3.Text import androidx.compose.runtime.* import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.toArgb @@ -137,7 +144,7 @@ class MainActivity : ComponentActivity() { setContent { Apiary_MobileTheme { - window.statusBarColor = MaterialTheme.colors.primaryVariant.toArgb() + window.statusBarColor = MaterialTheme.colorScheme.secondary.toArgb() val navController = rememberNavController() val bottomSheetNavigator = rememberBottomSheetNavigator() navController.navigatorProvider += bottomSheetNavigator @@ -155,7 +162,7 @@ class MainActivity : ComponentActivity() { } // A surface container using the 'background' color from the theme - Surface(color = MaterialTheme.colors.background) { + Surface(color = MaterialTheme.colorScheme.background) { ModalBottomSheetLayout(bottomSheetNavigator) { UpdateGate( navReady = navReady, @@ -180,9 +187,9 @@ class MainActivity : ComponentActivity() { bottomBar = { val current = currentRoute(navController) if (shouldShowBottomNav(nfcEnabled, current)) { - BottomNavigation { + NavigationBar { navItems.forEach { screen -> - BottomNavigationItem( + NavigationBarItem( icon = { Icon( screen.icon, diff --git a/app/src/main/java/org/robojackets/apiary/ui/global/AppTopBar.kt b/app/src/main/java/org/robojackets/apiary/ui/global/AppTopBar.kt index bf23577..4d42b22 100644 --- a/app/src/main/java/org/robojackets/apiary/ui/global/AppTopBar.kt +++ b/app/src/main/java/org/robojackets/apiary/ui/global/AppTopBar.kt @@ -5,18 +5,19 @@ import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding -import androidx.compose.material.MaterialTheme -import androidx.compose.material.Text -import androidx.compose.material.TopAppBar +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.material3.TopAppBar import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import org.robojackets.apiary.base.ui.IconWithText import org.robojackets.apiary.base.ui.icons.WarningIcon +@OptIn(ExperimentalMaterial3Api::class) @Composable fun AppTopBar(isProdEnv: Boolean) { Column { @@ -24,7 +25,7 @@ fun AppTopBar(isProdEnv: Boolean) { title = { Text( text = "MyRoboJackets", - style = MaterialTheme.typography.h5, + style = MaterialTheme.typography.headlineSmall, fontWeight = FontWeight.W800 ) }, @@ -34,16 +35,16 @@ fun AppTopBar(isProdEnv: Boolean) { Box( Modifier .fillMaxWidth() - .background(MaterialTheme.colors.error) + .background(MaterialTheme.colorScheme.error) .align(Alignment.CenterHorizontally) .padding(vertical = 4.dp) ) { IconWithText( - icon = { WarningIcon(tint = Color.White) }, + icon = { WarningIcon(tint = MaterialTheme.colorScheme.onError) }, text = { Text( "Non-production server", modifier = Modifier.padding(start = 4.dp), - color = Color.White + color = MaterialTheme.colorScheme.onError ) } ) } diff --git a/app/src/main/java/org/robojackets/apiary/ui/settings/Settings.kt b/app/src/main/java/org/robojackets/apiary/ui/settings/Settings.kt index 374875f..481aba8 100644 --- a/app/src/main/java/org/robojackets/apiary/ui/settings/Settings.kt +++ b/app/src/main/java/org/robojackets/apiary/ui/settings/Settings.kt @@ -8,11 +8,11 @@ import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll -import androidx.compose.material.Icon -import androidx.compose.material.MaterialTheme -import androidx.compose.material.Text import androidx.compose.material.icons.Icons import androidx.compose.material.icons.outlined.* +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState @@ -143,7 +143,7 @@ fun SettingsScreen( } val state by viewModel.state.collectAsState() - val secondaryThemeColor = MaterialTheme.colors.background + val secondaryThemeColor = MaterialTheme.colorScheme.background ContentPadding { Settings( appEnv = viewModel.globalSettings.appEnv, diff --git a/app/src/main/java/org/robojackets/apiary/ui/update/UpdateAvailable.kt b/app/src/main/java/org/robojackets/apiary/ui/update/UpdateAvailable.kt index d214674..0bed163 100644 --- a/app/src/main/java/org/robojackets/apiary/ui/update/UpdateAvailable.kt +++ b/app/src/main/java/org/robojackets/apiary/ui/update/UpdateAvailable.kt @@ -2,7 +2,12 @@ package org.robojackets.apiary.ui.update import android.app.Activity import androidx.compose.foundation.layout.* -import androidx.compose.material.* +import androidx.compose.material.AlertDialog +import androidx.compose.material3.Button +import androidx.compose.material3.CircularProgressIndicator +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.material3.TextButton import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -16,6 +21,9 @@ import org.robojackets.apiary.base.ui.util.getActivity import se.warting.inappupdate.compose.rememberInAppUpdateState import timber.log.Timber +// TODO: M3 upgrade: +// - Implement M3 AlertDialog + // Just a random number so we can identify our update request later if necessary const val UPDATE_REQUEST_CODE = 1999 @@ -87,7 +95,7 @@ fun RequiredUpdatePrompt() { UpdateIcon(Modifier .padding(bottom = 18.dp) .size(96.dp)) - Text("Update to continue", style = MaterialTheme.typography.h4) + Text("Update to continue", style = MaterialTheme.typography.headlineMedium) Text("To continue using MyRoboJackets, install the latest version. It'll only take a minute.", textAlign = TextAlign.Center, modifier = Modifier.padding(24.dp) @@ -110,7 +118,7 @@ fun OptionalUpdatePrompt( UpdateIcon(Modifier .padding(bottom = 9.dp) .size(72.dp)) - Text("Update available", style = MaterialTheme.typography.h5) + Text("Update available", style = MaterialTheme.typography.headlineSmall) Text("Install the latest version of MyRoboJackets for the latest features and " + "bug fixes. It'll only take a minute.", textAlign = TextAlign.Center, @@ -133,7 +141,7 @@ fun UpdateInProgress() { modifier = Modifier.fillMaxHeight(), ) { CircularProgressIndicator(Modifier.padding(bottom = 28.dp)) - Text("Please wait...", style = MaterialTheme.typography.h5) + Text("Please wait...", style = MaterialTheme.typography.headlineSmall) Text("We're finishing installing an update. It'll just be a minute or two!", textAlign = TextAlign.Center, modifier = Modifier.padding(20.dp) diff --git a/app/src/main/java/org/robojackets/apiary/ui/update/UpdateGate.kt b/app/src/main/java/org/robojackets/apiary/ui/update/UpdateGate.kt index 14a32d0..2a7cbec 100644 --- a/app/src/main/java/org/robojackets/apiary/ui/update/UpdateGate.kt +++ b/app/src/main/java/org/robojackets/apiary/ui/update/UpdateGate.kt @@ -1,6 +1,6 @@ package org.robojackets.apiary.ui.update -import androidx.compose.material.Text +import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.rememberCoroutineScope diff --git a/attendance/build.gradle.kts b/attendance/build.gradle.kts index d623c34..415502e 100644 --- a/attendance/build.gradle.kts +++ b/attendance/build.gradle.kts @@ -19,6 +19,7 @@ dependencies { implementation(AndroidToolDependencies.timber) implementation(ComposeDependencies.compose_material) + implementation(ComposeDependencies.compose_material3) implementation(ComposeDependencies.compose_ui) implementation(ComposeDependencies.lifecycle_viewmodel_compose) diff --git a/attendance/src/main/java/org/robojackets/apiary/attendance/Attendance.kt b/attendance/src/main/java/org/robojackets/apiary/attendance/Attendance.kt index ea6ac4c..ac53f75 100644 --- a/attendance/src/main/java/org/robojackets/apiary/attendance/Attendance.kt +++ b/attendance/src/main/java/org/robojackets/apiary/attendance/Attendance.kt @@ -1,8 +1,13 @@ package org.robojackets.apiary.attendance -import androidx.compose.foundation.layout.* -import androidx.compose.material.Button -import androidx.compose.material.Text +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.material3.Button +import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState diff --git a/attendance/src/main/java/org/robojackets/apiary/attendance/ui/AttendableSelection.kt b/attendance/src/main/java/org/robojackets/apiary/attendance/ui/AttendableSelection.kt index bb59cb3..3c69000 100644 --- a/attendance/src/main/java/org/robojackets/apiary/attendance/ui/AttendableSelection.kt +++ b/attendance/src/main/java/org/robojackets/apiary/attendance/ui/AttendableSelection.kt @@ -4,7 +4,13 @@ import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.itemsIndexed -import androidx.compose.material.* +import androidx.compose.material.ExperimentalMaterialApi +import androidx.compose.material3.Button +import androidx.compose.material3.CircularProgressIndicator +import androidx.compose.material3.Divider +import androidx.compose.material3.ListItem +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.collectAsState @@ -36,12 +42,11 @@ private fun <T> AttendableList( LazyColumn { itemsIndexed(attendables) { idx, attendable -> ListItem( + headlineContent = { attendableContent(attendable) }, Modifier.clickable { onAttendableSelected(attendable) } - ) { - attendableContent(attendable) - } + ) if (idx < attendables.size - 1) { Divider() } @@ -102,7 +107,7 @@ fun AttendableSelectionScreen( onAttendableSelected = { viewModel.onAttendableSelected(it.toAttendable()) }, - title = { Text("Select a team", style = MaterialTheme.typography.h5) }, + title = { Text("Select a team", style = MaterialTheme.typography.headlineSmall) }, callout = { if (state.missingHiddenTeams == true) { Spacer(Modifier.height(4.dp)) @@ -121,7 +126,7 @@ fun AttendableSelectionScreen( onAttendableSelected = { viewModel.onAttendableSelected(it.toAttendable()) }, - title = { Text("Select an event", style = MaterialTheme.typography.h5) } + title = { Text("Select an event", style = MaterialTheme.typography.headlineSmall) } ) { Text(it.name) } diff --git a/attendance/src/main/java/org/robojackets/apiary/attendance/ui/AttendableTypeSelectionScreen.kt b/attendance/src/main/java/org/robojackets/apiary/attendance/ui/AttendableTypeSelectionScreen.kt index 52b637c..9543a34 100644 --- a/attendance/src/main/java/org/robojackets/apiary/attendance/ui/AttendableTypeSelectionScreen.kt +++ b/attendance/src/main/java/org/robojackets/apiary/attendance/ui/AttendableTypeSelectionScreen.kt @@ -1,8 +1,17 @@ package org.robojackets.apiary.attendance.ui import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.* -import androidx.compose.material.* +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.defaultMinSize +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.size +import androidx.compose.material.ExperimentalMaterialApi +import androidx.compose.material3.Divider +import androidx.compose.material3.ListItem +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState @@ -58,26 +67,32 @@ fun AttendableTypeSelectionScreen( Modifier .fillMaxWidth() .fillMaxHeight()) { - Text("What do you want to take attendance for?", style = MaterialTheme.typography.h5) + Text("What do you want to take attendance for?", style = MaterialTheme.typography.headlineSmall) Spacer(Modifier.defaultMinSize(minHeight = 16.dp)) Divider() ListItem( - icon = { GroupsIcon(Modifier.size(36.dp)) }, + leadingContent = { + GroupsIcon(Modifier.size(36.dp)) + }, + headlineContent = { + Text("Team", style = MaterialTheme.typography.titleLarge) + }, modifier = Modifier .defaultMinSize(minHeight = 80.dp) .clickable { viewModel.navigateToAttendableSelection(AttendableType.Team) } - ) { - Text("Team", style = MaterialTheme.typography.h6) - } + ) Divider() ListItem( - icon = { EventIcon(Modifier.size(36.dp)) }, + leadingContent = { + EventIcon(Modifier.size(36.dp)) + }, + headlineContent = { + Text("Event", style = MaterialTheme.typography.titleLarge) + }, modifier = Modifier .defaultMinSize(minHeight = 80.dp) .clickable { viewModel.navigateToAttendableSelection(AttendableType.Event) } - ) { - Text("Event", style = MaterialTheme.typography.h6) - } + ) Divider() } } diff --git a/auth/build.gradle.kts b/auth/build.gradle.kts index 7cb2b00..e6a7fa7 100644 --- a/auth/build.gradle.kts +++ b/auth/build.gradle.kts @@ -29,6 +29,7 @@ dependencies { implementation(ComposeDependencies.accompanist_systemuicontroller) implementation(ComposeDependencies.compose_foundation) implementation(ComposeDependencies.compose_material) + implementation(ComposeDependencies.compose_material3) implementation(ComposeDependencies.compose_ui) implementation(ComposeDependencies.compose_ui_tooling) diff --git a/auth/src/main/java/org/robojackets/apiary/auth/ui/Authentication.kt b/auth/src/main/java/org/robojackets/apiary/auth/ui/Authentication.kt index fdb287b..793be11 100644 --- a/auth/src/main/java/org/robojackets/apiary/auth/ui/Authentication.kt +++ b/auth/src/main/java/org/robojackets/apiary/auth/ui/Authentication.kt @@ -7,7 +7,19 @@ import androidx.compose.foundation.Image import androidx.compose.foundation.layout.* import androidx.compose.foundation.selection.selectable import androidx.compose.foundation.selection.selectableGroup -import androidx.compose.material.* +import androidx.compose.material.AlertDialog +import androidx.compose.material.BottomSheetScaffold +import androidx.compose.material.BottomSheetScaffoldState +import androidx.compose.material.BottomSheetValue +import androidx.compose.material.ExperimentalMaterialApi +import androidx.compose.material.rememberBottomSheetScaffoldState +import androidx.compose.material.rememberBottomSheetState +import androidx.compose.material3.Button +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.RadioButton +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.material3.TextButton import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -27,6 +39,11 @@ import org.robojackets.apiary.base.AppEnvironment import org.robojackets.apiary.base.ui.theme.BottomSheetShape import org.robojackets.apiary.base.ui.util.MadeWithLove +// TODO: M3 upgrade +// - Update to M3 BottomSheet +// - Update to M3 AlertDialog +// - Test auth behavior with new theme + @OptIn(ExperimentalMaterialApi::class, androidx.compose.ui.ExperimentalComposeUiApi::class) @Suppress("LongMethod", "MagicNumber") @Composable @@ -46,7 +63,7 @@ private fun Authentication( val coroutineScope = rememberCoroutineScope() val systemUiController = rememberSystemUiController() - val backgroundColor = MaterialTheme.colors.background + val backgroundColor = MaterialTheme.colorScheme.background SideEffect { systemUiController.setSystemBarsColor(backgroundColor) } @@ -115,7 +132,7 @@ private fun Authentication( ) }) { Surface( - color = MaterialTheme.colors.background, + color = MaterialTheme.colorScheme.background, modifier = Modifier.padding(8.dp) ) { Column( @@ -207,7 +224,7 @@ private fun ChangeEnvironmentBottomSheetContent( "Change server", modifier = Modifier .padding(16.dp), - style = MaterialTheme.typography.h5 + style = MaterialTheme.typography.headlineSmall ) Column(Modifier.selectableGroup()) { @@ -230,7 +247,7 @@ private fun ChangeEnvironmentBottomSheetContent( ) Text( text = "${it.name} (${it.apiBaseUrl})", - style = MaterialTheme.typography.body1.merge(), + style = MaterialTheme.typography.bodyLarge.merge(), modifier = Modifier.padding(start = 16.dp) ) } diff --git a/auth/src/main/java/org/robojackets/apiary/auth/ui/permissions/InsufficientPermissions.kt b/auth/src/main/java/org/robojackets/apiary/auth/ui/permissions/InsufficientPermissions.kt index f904049..a3cc943 100644 --- a/auth/src/main/java/org/robojackets/apiary/auth/ui/permissions/InsufficientPermissions.kt +++ b/auth/src/main/java/org/robojackets/apiary/auth/ui/permissions/InsufficientPermissions.kt @@ -3,9 +3,17 @@ package org.robojackets.apiary.auth.ui.permissions import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items -import androidx.compose.material.* +import androidx.compose.material.AlertDialog +import androidx.compose.material.ExperimentalMaterialApi import androidx.compose.material.icons.Icons import androidx.compose.material.icons.outlined.CheckCircle +import androidx.compose.material3.Divider +import androidx.compose.material3.Icon +import androidx.compose.material3.ListItem +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.OutlinedButton +import androidx.compose.material3.Text +import androidx.compose.material3.TextButton import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -21,6 +29,9 @@ import org.robojackets.apiary.base.ui.theme.danger import org.robojackets.apiary.base.ui.theme.success import org.robojackets.apiary.base.ui.util.ContentPadding +// TODO: M3 upgrade +// - Update to M3 AlertDialog + @Composable fun InsufficientPermissions( featureName: String, @@ -40,7 +51,7 @@ fun InsufficientPermissions( ErrorIcon(Modifier.size(90.dp), tint = danger) Text( text = "$featureName unavailable", - style = MaterialTheme.typography.h4 + style = MaterialTheme.typography.headlineMedium, ) Text( text = "You don't have permission to use this feature. Please ask in #it-helpdesk for assistance.", @@ -88,8 +99,8 @@ fun PermissionDetailsDialog( ) { Text( text = "Required permissions", - style = MaterialTheme.typography.h5, - color = MaterialTheme.colors.onBackground, + style = MaterialTheme.typography.headlineSmall, + color = MaterialTheme.colorScheme.onBackground, modifier = Modifier.padding(bottom = 20.dp) ) Divider() @@ -123,9 +134,8 @@ fun PermissionDetailsDialog( @OptIn(ExperimentalMaterialApi::class) @Composable fun PermissionsListItem(hasPermission: Boolean, permissionName: String) { - ListItem( - icon = { + leadingContent = { when (hasPermission) { true -> Icon( Icons.Outlined.CheckCircle, @@ -136,9 +146,8 @@ fun PermissionsListItem(hasPermission: Boolean, permissionName: String) { false -> ErrorIcon(Modifier.size(28.dp), tint = danger) } }, - ) { - Text(permissionName) - } + headlineContent = { Text(permissionName) }, + ) } @Composable diff --git a/auth/src/main/java/org/robojackets/apiary/auth/ui/permissions/MissingHiddenTeamsCallout.kt b/auth/src/main/java/org/robojackets/apiary/auth/ui/permissions/MissingHiddenTeamsCallout.kt index e1e107e..ffbe887 100644 --- a/auth/src/main/java/org/robojackets/apiary/auth/ui/permissions/MissingHiddenTeamsCallout.kt +++ b/auth/src/main/java/org/robojackets/apiary/auth/ui/permissions/MissingHiddenTeamsCallout.kt @@ -3,8 +3,8 @@ package org.robojackets.apiary.auth.ui.permissions import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.padding -import androidx.compose.material.OutlinedButton -import androidx.compose.material.Text +import androidx.compose.material3.OutlinedButton +import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp diff --git a/base/build.gradle.kts b/base/build.gradle.kts index f4a15c0..bfeca8d 100644 --- a/base/build.gradle.kts +++ b/base/build.gradle.kts @@ -18,10 +18,13 @@ dependencies { implementation(ComposeDependencies.compose_foundation) implementation(ComposeDependencies.compose_material) + implementation(ComposeDependencies.compose_material3) implementation(ComposeDependencies.compose_ui) implementation(ComposeDependencies.compose_ui_tooling) implementation(ComposeDependencies.accompanist_nav_material) + implementation(MaterialDependencies.material_android) + implementation(HiltDependencies.hilt) kapt(HiltDependencies.hilt_android_compiler) diff --git a/base/src/main/java/org/robojackets/apiary/base/ui/ActionPrompt.kt b/base/src/main/java/org/robojackets/apiary/base/ui/ActionPrompt.kt index f4bd538..7d48683 100644 --- a/base/src/main/java/org/robojackets/apiary/base/ui/ActionPrompt.kt +++ b/base/src/main/java/org/robojackets/apiary/base/ui/ActionPrompt.kt @@ -1,8 +1,12 @@ package org.robojackets.apiary.base.ui -import androidx.compose.foundation.layout.* -import androidx.compose.material.MaterialTheme -import androidx.compose.material.Text +import androidx.compose.foundation.layout.Arrangement +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.MaterialTheme +import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -28,7 +32,7 @@ fun ActionPrompt( icon() Text( text = title, - style = MaterialTheme.typography.h4, + style = MaterialTheme.typography.headlineMedium, modifier = Modifier.padding(top = 6.dp), textAlign = TextAlign.Center, ) @@ -40,7 +44,7 @@ fun ActionPrompt( subtitle?.let { Text( text = subtitle, - style = MaterialTheme.typography.subtitle1, + style = MaterialTheme.typography.titleMedium, textAlign = TextAlign.Center, ) } diff --git a/base/src/main/java/org/robojackets/apiary/base/ui/IconWithText.kt b/base/src/main/java/org/robojackets/apiary/base/ui/IconWithText.kt index 55ba14f..bc90d7d 100644 --- a/base/src/main/java/org/robojackets/apiary/base/ui/IconWithText.kt +++ b/base/src/main/java/org/robojackets/apiary/base/ui/IconWithText.kt @@ -4,7 +4,7 @@ import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding -import androidx.compose.material.Text +import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier diff --git a/base/src/main/java/org/robojackets/apiary/base/ui/callout/Callout.kt b/base/src/main/java/org/robojackets/apiary/base/ui/callout/Callout.kt index a48fcc4..0b3c333 100644 --- a/base/src/main/java/org/robojackets/apiary/base/ui/callout/Callout.kt +++ b/base/src/main/java/org/robojackets/apiary/base/ui/callout/Callout.kt @@ -4,8 +4,8 @@ import androidx.compose.foundation.background import androidx.compose.foundation.border import androidx.compose.foundation.layout.* import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.MaterialTheme -import androidx.compose.material.Text +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -19,6 +19,9 @@ import org.robojackets.apiary.base.ui.theme.warningDarkSubtle import org.robojackets.apiary.base.ui.theme.warningLightMuted import org.robojackets.apiary.base.ui.theme.warningLightSubtle +// TODO: M3 upgrade +// - Implement replacement for isLight + @Composable fun Callout( title: @Composable () -> Unit, @@ -49,7 +52,7 @@ fun WarningCallout( padding: PaddingValues? = null, body: @Composable () -> Unit, ) { - val isLightTheme = MaterialTheme.colors.isLight + val isLightTheme = true // TODO: M3 upgrade, previously: MaterialTheme.colors.isLight Callout( title = { @@ -57,7 +60,7 @@ fun WarningCallout( Text( titleText, modifier = Modifier.padding(start = 8.dp), - style = MaterialTheme.typography.h6 + style = MaterialTheme.typography.titleLarge ) } }, diff --git a/base/src/main/java/org/robojackets/apiary/base/ui/error/ErrorMessage.kt b/base/src/main/java/org/robojackets/apiary/base/ui/error/ErrorMessage.kt index 7354e7b..c8e9f2a 100644 --- a/base/src/main/java/org/robojackets/apiary/base/ui/error/ErrorMessage.kt +++ b/base/src/main/java/org/robojackets/apiary/base/ui/error/ErrorMessage.kt @@ -2,10 +2,16 @@ package org.robojackets.apiary.base.ui.error import android.content.Intent import android.net.Uri -import androidx.compose.foundation.layout.* -import androidx.compose.material.Button -import androidx.compose.material.OutlinedButton -import androidx.compose.material.Text +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.material3.Button +import androidx.compose.material3.OutlinedButton +import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier diff --git a/base/src/main/java/org/robojackets/apiary/base/ui/icons/ExtraIcons.kt b/base/src/main/java/org/robojackets/apiary/base/ui/icons/ExtraIcons.kt index 058fabd..baf992f 100644 --- a/base/src/main/java/org/robojackets/apiary/base/ui/icons/ExtraIcons.kt +++ b/base/src/main/java/org/robojackets/apiary/base/ui/icons/ExtraIcons.kt @@ -1,10 +1,9 @@ package org.robojackets.apiary.base.ui.icons -import androidx.compose.material.Icon -import androidx.compose.material.LocalContentAlpha -import androidx.compose.material.LocalContentColor import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Warning +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.Color @@ -14,7 +13,7 @@ import org.robojackets.apiary.base.R @Composable fun ContactlessIcon( modifier: Modifier, - tint: Color = LocalContentColor.current.copy(alpha = LocalContentAlpha.current) + tint: Color = MaterialTheme.colorScheme.onSurface ) { Icon( painter = painterResource(id = R.drawable.ic_outline_contactless_24dp), @@ -27,7 +26,7 @@ fun ContactlessIcon( @Composable fun WarningIcon( modifier: Modifier = Modifier, - tint: Color = LocalContentColor.current.copy(alpha = LocalContentAlpha.current) + tint: Color = MaterialTheme.colorScheme.onSurface ) { Icon( Icons.Default.Warning, @@ -40,7 +39,7 @@ fun WarningIcon( @Composable fun ErrorIcon( modifier: Modifier = Modifier, - tint: Color = LocalContentColor.current.copy(alpha = LocalContentAlpha.current) + tint: Color = MaterialTheme.colorScheme.onSurface ) { Icon( painter = painterResource(id = R.drawable.ic_baseline_error_outline_24), @@ -53,7 +52,7 @@ fun ErrorIcon( @Composable fun CreditCardIcon( modifier: Modifier = Modifier, - tint: Color = LocalContentColor.current.copy(alpha = LocalContentAlpha.current) + tint: Color = MaterialTheme.colorScheme.onSurface ) { Icon( painter = painterResource(id = R.drawable.ic_baseline_credit_card_24), @@ -66,7 +65,7 @@ fun CreditCardIcon( @Composable fun PendingIcon( modifier: Modifier = Modifier, - tint: Color = LocalContentColor.current.copy(alpha = LocalContentAlpha.current) + tint: Color = MaterialTheme.colorScheme.onSurface ) { Icon( painter = painterResource(id = R.drawable.ic_outline_pending_24dp), @@ -79,7 +78,7 @@ fun PendingIcon( @Composable fun GroupsIcon( modifier: Modifier = Modifier, - tint: Color = LocalContentColor.current.copy(alpha = LocalContentAlpha.current) + tint: Color = MaterialTheme.colorScheme.onSurface, ) { Icon( painter = painterResource(id = R.drawable.ic_outline_groups_24dp), @@ -92,7 +91,7 @@ fun GroupsIcon( @Composable fun EventIcon( modifier: Modifier = Modifier, - tint: Color = LocalContentColor.current.copy(alpha = LocalContentAlpha.current) + tint: Color = MaterialTheme.colorScheme.onSurface ) { Icon( painter = painterResource(id = R.drawable.ic_outline_event_24dp), @@ -105,7 +104,7 @@ fun EventIcon( @Composable fun UpdateIcon( modifier: Modifier = Modifier, - tint: Color = LocalContentColor.current.copy(alpha = LocalContentAlpha.current) + tint: Color = MaterialTheme.colorScheme.onSurface ) { Icon( painter = painterResource(id = R.drawable.ic_baseline_update_24), @@ -118,7 +117,7 @@ fun UpdateIcon( @Composable fun TaskAltIcon( modifier: Modifier = Modifier, - tint: Color = LocalContentColor.current.copy(alpha = LocalContentAlpha.current) + tint: Color = MaterialTheme.colorScheme.onSurface ) { Icon( painter = painterResource(id = R.drawable.ic_outline_task_alt_24dp), diff --git a/base/src/main/java/org/robojackets/apiary/base/ui/nfc/BuzzCardPrompt.kt b/base/src/main/java/org/robojackets/apiary/base/ui/nfc/BuzzCardPrompt.kt index 6f034a9..b53e4ee 100644 --- a/base/src/main/java/org/robojackets/apiary/base/ui/nfc/BuzzCardPrompt.kt +++ b/base/src/main/java/org/robojackets/apiary/base/ui/nfc/BuzzCardPrompt.kt @@ -5,7 +5,12 @@ import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.text.KeyboardOptions -import androidx.compose.material.* +import androidx.compose.material.AlertDialog +import androidx.compose.material3.Button +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.OutlinedTextField +import androidx.compose.material3.Text +import androidx.compose.material3.TextButton import androidx.compose.runtime.* import androidx.compose.ui.Alignment.Companion.CenterHorizontally import androidx.compose.ui.Modifier @@ -27,6 +32,11 @@ import org.robojackets.apiary.base.ui.theme.danger import timber.log.Timber import java.nio.charset.StandardCharsets +// TODO: M3 upgrade +// - Switch to M3 AlertDialog +// - Verify icon/text colors are correct in dark mode +// - Verify Contactless icon color is correct in light mode + /** * Show a prompt for BuzzCards and call a callback function each time a valid GTID is obtained. * @@ -185,7 +195,7 @@ fun ManualGtidEntryPrompt( Text("Submit") } }, - title = { Text(text = "Manual GTID entry", style = MaterialTheme.typography.h5) }, + title = { Text(text = "Manual GTID entry", style = MaterialTheme.typography.headlineSmall) }, text = { Column { Text("Type the entire 9-digit GTID, starting with 90") diff --git a/base/src/main/java/org/robojackets/apiary/base/ui/nfc/NfcRequired.kt b/base/src/main/java/org/robojackets/apiary/base/ui/nfc/NfcRequired.kt index 06f0df7..c1f2a36 100644 --- a/base/src/main/java/org/robojackets/apiary/base/ui/nfc/NfcRequired.kt +++ b/base/src/main/java/org/robojackets/apiary/base/ui/nfc/NfcRequired.kt @@ -6,9 +6,13 @@ import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.size -import androidx.compose.material.Button -import androidx.compose.material.Text -import androidx.compose.runtime.* +import androidx.compose.material3.Button +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext @@ -18,6 +22,9 @@ import org.robojackets.apiary.base.ui.icons.ErrorIcon import org.robojackets.apiary.base.ui.theme.danger import org.robojackets.apiary.base.ui.theme.warningLightEmphasis +// TODO: M3 upgrade +// - Opening the app with NFC disabled causes a crash + @Composable fun NfcRequired(nfcEnabled: Boolean, gatedComposable: @Composable () -> Unit) { val context = LocalContext.current diff --git a/base/src/main/java/org/robojackets/apiary/base/ui/theme/Shape.kt b/base/src/main/java/org/robojackets/apiary/base/ui/theme/Shape.kt index 20bcac2..ddad505 100644 --- a/base/src/main/java/org/robojackets/apiary/base/ui/theme/Shape.kt +++ b/base/src/main/java/org/robojackets/apiary/base/ui/theme/Shape.kt @@ -1,7 +1,7 @@ package org.robojackets.apiary.base.ui.theme import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.Shapes +import androidx.compose.material3.Shapes import androidx.compose.ui.unit.dp val Shapes = Shapes( diff --git a/base/src/main/java/org/robojackets/apiary/base/ui/theme/Theme.kt b/base/src/main/java/org/robojackets/apiary/base/ui/theme/Theme.kt index 1f76d50..3e2fd5a 100644 --- a/base/src/main/java/org/robojackets/apiary/base/ui/theme/Theme.kt +++ b/base/src/main/java/org/robojackets/apiary/base/ui/theme/Theme.kt @@ -1,9 +1,11 @@ package org.robojackets.apiary.base.ui.theme import androidx.compose.foundation.isSystemInDarkTheme -import androidx.compose.material.MaterialTheme import androidx.compose.material.darkColors import androidx.compose.material.lightColors +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.darkColorScheme +import androidx.compose.material3.lightColorScheme import androidx.compose.runtime.Composable import androidx.compose.ui.graphics.Color @@ -28,19 +30,30 @@ private val LightColorPalette = lightColors( */ ) +val LightColorScheme = lightColorScheme( + primary = Gold, + secondary = GoldDark, + tertiary = Color.Black, +) +val DarkColorScheme = darkColorScheme( + primary = Gold, + secondary = GoldDark, + tertiary = Color.White, +) + @Composable fun Apiary_MobileTheme( darkTheme: Boolean = isSystemInDarkTheme(), content: @Composable() () -> Unit ) { val colors = if (darkTheme) { - DarkColorPalette + DarkColorScheme } else { - LightColorPalette + LightColorScheme } MaterialTheme( - colors = colors, + colorScheme = colors, typography = Typography, shapes = Shapes, content = content diff --git a/base/src/main/java/org/robojackets/apiary/base/ui/theme/Type.kt b/base/src/main/java/org/robojackets/apiary/base/ui/theme/Type.kt index d67ef35..2398b76 100644 --- a/base/src/main/java/org/robojackets/apiary/base/ui/theme/Type.kt +++ b/base/src/main/java/org/robojackets/apiary/base/ui/theme/Type.kt @@ -1,6 +1,6 @@ package org.robojackets.apiary.base.ui.theme -import androidx.compose.material.Typography +import androidx.compose.material3.Typography import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.text.font.FontWeight @@ -8,13 +8,14 @@ import androidx.compose.ui.unit.sp // Set of Material typography styles to start with val Typography = Typography( - body1 = TextStyle( + bodyLarge = TextStyle( fontFamily = FontFamily.Default, fontWeight = FontWeight.Normal, fontSize = 16.sp ), /* Other default text styles to override */ - button = TextStyle( + labelLarge = TextStyle( + fontFamily = FontFamily.Default, fontWeight = FontWeight.Medium, fontSize = 14.sp, // letterSpacing = 1.25.sp diff --git a/base/src/main/java/org/robojackets/apiary/base/ui/util/LoadingSpinner.kt b/base/src/main/java/org/robojackets/apiary/base/ui/util/LoadingSpinner.kt index 7c49776..2ecc73a 100644 --- a/base/src/main/java/org/robojackets/apiary/base/ui/util/LoadingSpinner.kt +++ b/base/src/main/java/org/robojackets/apiary/base/ui/util/LoadingSpinner.kt @@ -4,7 +4,7 @@ import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.material.CircularProgressIndicator +import androidx.compose.material3.CircularProgressIndicator import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier diff --git a/base/src/main/java/org/robojackets/apiary/base/ui/util/MadeWithLove.kt b/base/src/main/java/org/robojackets/apiary/base/ui/util/MadeWithLove.kt index c6da7b1..4e7f57e 100644 --- a/base/src/main/java/org/robojackets/apiary/base/ui/util/MadeWithLove.kt +++ b/base/src/main/java/org/robojackets/apiary/base/ui/util/MadeWithLove.kt @@ -1,6 +1,6 @@ package org.robojackets.apiary.base.ui.util -import androidx.compose.material.Text +import androidx.compose.material3.Text import androidx.compose.runtime.Composable @Composable diff --git a/build.gradle.kts b/build.gradle.kts index 353df25..a81b354 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -6,7 +6,7 @@ buildscript { } dependencies { classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.21") - classpath("com.android.tools.build:gradle:8.0.1") + classpath("com.android.tools.build:gradle:8.1.0") classpath("com.google.dagger:hilt-android-gradle-plugin:2.46.1") classpath("com.google.android.libraries.mapsplatform.secrets-gradle-plugin:secrets-gradle-plugin:2.0.1") classpath("com.google.gms:google-services:4.3.15") diff --git a/buildSrc/src/main/java/Dependencies.kt b/buildSrc/src/main/java/Dependencies.kt index 056f4db..9d3a185 100644 --- a/buildSrc/src/main/java/Dependencies.kt +++ b/buildSrc/src/main/java/Dependencies.kt @@ -4,6 +4,7 @@ object ComposeDependencies { const val compose_settings_version = "0.27.0" const val compose_version = "1.4.3" const val lifecycle_viewmodel_compose_version = "2.6.1" + const val compose_material3_version = "1.1.1" } const val accompanist_systemuicontroller = @@ -25,7 +26,7 @@ object ComposeDependencies { "androidx.compose.runtime:runtime-livedata:${Versions.compose_version}" const val compose_settings = - "com.github.alorma:compose-settings-ui:${Versions.compose_settings_version}" + "com.github.alorma:compose-settings-ui-m3:${Versions.compose_settings_version}" const val compose_ui = "androidx.compose.ui:ui:${Versions.compose_version}" const val compose_ui_test = "androidx.compose.ui:ui-test-junit4:${Versions.compose_version}" @@ -33,6 +34,9 @@ object ComposeDependencies { const val lifecycle_viewmodel_compose = "androidx.lifecycle:lifecycle-viewmodel-compose:${Versions.lifecycle_viewmodel_compose_version}" + + const val compose_material3 = + "androidx.compose.material3:material3:${Versions.compose_material3_version}" } object MaterialDependencies { From 54edda1cf4e080e83868051fc35bcb018e4a41aa Mon Sep 17 00:00:00 2001 From: Evan Strat <evan10s@users.noreply.github.com> Date: Sun, 20 Aug 2023 01:28:07 -0400 Subject: [PATCH 04/33] add app launch todo --- app/src/main/java/org/robojackets/apiary/MainActivity.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/src/main/java/org/robojackets/apiary/MainActivity.kt b/app/src/main/java/org/robojackets/apiary/MainActivity.kt index 69036fc..97348f8 100644 --- a/app/src/main/java/org/robojackets/apiary/MainActivity.kt +++ b/app/src/main/java/org/robojackets/apiary/MainActivity.kt @@ -62,6 +62,8 @@ import org.robojackets.apiary.ui.update.UpdateInProgress import timber.log.Timber import javax.inject.Inject +// TODO: see if we can make app launch screen match light/dark mode? + sealed class Screen( val navigationDestination: String, @StringRes val resourceId: Int, From f56d5e0679a4a75ca58f4b5ab33160c672ec68af Mon Sep 17 00:00:00 2001 From: Evan Strat <evan10s@users.noreply.github.com> Date: Sun, 20 Aug 2023 17:41:05 -0400 Subject: [PATCH 05/33] Remainder of M3 upgrade --- app/build.gradle.kts | 1 - .../org/robojackets/apiary/MainActivity.kt | 3 - .../apiary/ui/update/UpdateAvailable.kt | 2 +- attendance/build.gradle.kts | 3 - .../attendance/ui/AttendableSelection.kt | 3 - .../ui/AttendableTypeSelectionScreen.kt | 2 - auth/build.gradle.kts | 1 - .../apiary/auth/ui/Authentication.kt | 215 +++++++++--------- .../ui/permissions/InsufficientPermissions.kt | 22 +- base/build.gradle.kts | 1 - .../apiary/base/ui/nfc/BuzzCardPrompt.kt | 2 +- .../robojackets/apiary/base/ui/theme/Theme.kt | 23 -- buildSrc/src/main/java/Dependencies.kt | 6 +- 13 files changed, 127 insertions(+), 157 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 9edde41..8fe5451 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -36,7 +36,6 @@ dependencies { implementation(ComposeDependencies.lifecycle_viewmodel_compose) implementation(ComposeDependencies.compose_ui_tooling) implementation(ComposeDependencies.compose_foundation) - implementation(ComposeDependencies.compose_material) implementation(ComposeDependencies.compose_material3) implementation(ComposeDependencies.compose_material_icons_core) implementation(ComposeDependencies.compose_material_icons_extended) diff --git a/app/src/main/java/org/robojackets/apiary/MainActivity.kt b/app/src/main/java/org/robojackets/apiary/MainActivity.kt index 97348f8..0ae1af0 100644 --- a/app/src/main/java/org/robojackets/apiary/MainActivity.kt +++ b/app/src/main/java/org/robojackets/apiary/MainActivity.kt @@ -8,7 +8,6 @@ import androidx.activity.compose.setContent import androidx.annotation.StringRes import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.padding -import androidx.compose.material.ExperimentalMaterialApi import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Settings import androidx.compose.material.icons.outlined.Contactless @@ -125,7 +124,6 @@ class MainActivity : ComponentActivity() { } @OptIn(ExperimentalMaterialNavigationApi::class) - @ExperimentalMaterialApi @Suppress("LongMethod") override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -242,7 +240,6 @@ class MainActivity : ComponentActivity() { @Suppress("LongMethod") @OptIn(ExperimentalMaterialNavigationApi::class) - @ExperimentalMaterialApi @Composable private fun AppNavigation( navController: NavHostController, diff --git a/app/src/main/java/org/robojackets/apiary/ui/update/UpdateAvailable.kt b/app/src/main/java/org/robojackets/apiary/ui/update/UpdateAvailable.kt index 0bed163..1fc505e 100644 --- a/app/src/main/java/org/robojackets/apiary/ui/update/UpdateAvailable.kt +++ b/app/src/main/java/org/robojackets/apiary/ui/update/UpdateAvailable.kt @@ -2,7 +2,7 @@ package org.robojackets.apiary.ui.update import android.app.Activity import androidx.compose.foundation.layout.* -import androidx.compose.material.AlertDialog +import androidx.compose.material3.AlertDialog import androidx.compose.material3.Button import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.MaterialTheme diff --git a/attendance/build.gradle.kts b/attendance/build.gradle.kts index 415502e..4df0cbe 100644 --- a/attendance/build.gradle.kts +++ b/attendance/build.gradle.kts @@ -18,7 +18,6 @@ dependencies { coreLibraryDesugaring(AndroidToolDependencies.android_tools_desugar_jdk) implementation(AndroidToolDependencies.timber) - implementation(ComposeDependencies.compose_material) implementation(ComposeDependencies.compose_material3) implementation(ComposeDependencies.compose_ui) implementation(ComposeDependencies.lifecycle_viewmodel_compose) @@ -26,8 +25,6 @@ dependencies { implementation(HiltDependencies.hilt) kapt(HiltDependencies.hilt_android_compiler) - implementation(MaterialDependencies.material_android) - implementation(NetworkDependencies.moshi) kapt(NetworkDependencies.moshi_kotlin_codegen) implementation(NetworkDependencies.okhttp) diff --git a/attendance/src/main/java/org/robojackets/apiary/attendance/ui/AttendableSelection.kt b/attendance/src/main/java/org/robojackets/apiary/attendance/ui/AttendableSelection.kt index 3c69000..ad127f5 100644 --- a/attendance/src/main/java/org/robojackets/apiary/attendance/ui/AttendableSelection.kt +++ b/attendance/src/main/java/org/robojackets/apiary/attendance/ui/AttendableSelection.kt @@ -4,7 +4,6 @@ import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.itemsIndexed -import androidx.compose.material.ExperimentalMaterialApi import androidx.compose.material3.Button import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.Divider @@ -27,7 +26,6 @@ import org.robojackets.apiary.base.ui.icons.WarningIcon import org.robojackets.apiary.base.ui.theme.danger import org.robojackets.apiary.base.ui.util.ContentPadding -@ExperimentalMaterialApi @Composable private fun <T> AttendableList( attendables: List<T>, @@ -56,7 +54,6 @@ private fun <T> AttendableList( } @Suppress("LongMethod") -@ExperimentalMaterialApi @Composable fun AttendableSelectionScreen( viewModel: AttendanceViewModel, diff --git a/attendance/src/main/java/org/robojackets/apiary/attendance/ui/AttendableTypeSelectionScreen.kt b/attendance/src/main/java/org/robojackets/apiary/attendance/ui/AttendableTypeSelectionScreen.kt index 9543a34..5f475cc 100644 --- a/attendance/src/main/java/org/robojackets/apiary/attendance/ui/AttendableTypeSelectionScreen.kt +++ b/attendance/src/main/java/org/robojackets/apiary/attendance/ui/AttendableTypeSelectionScreen.kt @@ -7,7 +7,6 @@ import androidx.compose.foundation.layout.defaultMinSize import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.size -import androidx.compose.material.ExperimentalMaterialApi import androidx.compose.material3.Divider import androidx.compose.material3.ListItem import androidx.compose.material3.MaterialTheme @@ -27,7 +26,6 @@ import org.robojackets.apiary.base.ui.icons.GroupsIcon import org.robojackets.apiary.base.ui.util.ContentPadding import org.robojackets.apiary.base.ui.util.LoadingSpinner -@ExperimentalMaterialApi @Composable fun AttendableTypeSelectionScreen( viewModel: AttendableTypeSelectionViewModel, diff --git a/auth/build.gradle.kts b/auth/build.gradle.kts index e6a7fa7..daf62ac 100644 --- a/auth/build.gradle.kts +++ b/auth/build.gradle.kts @@ -28,7 +28,6 @@ dependencies { implementation(ComposeDependencies.accompanist_systemuicontroller) implementation(ComposeDependencies.compose_foundation) - implementation(ComposeDependencies.compose_material) implementation(ComposeDependencies.compose_material3) implementation(ComposeDependencies.compose_ui) implementation(ComposeDependencies.compose_ui_tooling) diff --git a/auth/src/main/java/org/robojackets/apiary/auth/ui/Authentication.kt b/auth/src/main/java/org/robojackets/apiary/auth/ui/Authentication.kt index 793be11..e59ed6f 100644 --- a/auth/src/main/java/org/robojackets/apiary/auth/ui/Authentication.kt +++ b/auth/src/main/java/org/robojackets/apiary/auth/ui/Authentication.kt @@ -7,19 +7,16 @@ import androidx.compose.foundation.Image import androidx.compose.foundation.layout.* import androidx.compose.foundation.selection.selectable import androidx.compose.foundation.selection.selectableGroup -import androidx.compose.material.AlertDialog -import androidx.compose.material.BottomSheetScaffold -import androidx.compose.material.BottomSheetScaffoldState -import androidx.compose.material.BottomSheetValue -import androidx.compose.material.ExperimentalMaterialApi -import androidx.compose.material.rememberBottomSheetScaffoldState -import androidx.compose.material.rememberBottomSheetState +import androidx.compose.material3.AlertDialog import androidx.compose.material3.Button +import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.ModalBottomSheet import androidx.compose.material3.RadioButton -import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.material3.TextButton +import androidx.compose.material3.rememberBottomSheetScaffoldState +import androidx.compose.material3.rememberModalBottomSheetState import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -27,7 +24,6 @@ import androidx.compose.ui.res.painterResource import androidx.compose.ui.semantics.Role import androidx.compose.ui.unit.dp import com.google.accompanist.systemuicontroller.rememberSystemUiController -import kotlinx.coroutines.launch import net.openid.appauth.AuthorizationException import net.openid.appauth.AuthorizationResponse import org.robojackets.apiary.auth.R @@ -36,7 +32,6 @@ import org.robojackets.apiary.auth.model.AuthenticationViewModel import org.robojackets.apiary.auth.model.LoginStatus.* import org.robojackets.apiary.auth.oauth2.AuthManager import org.robojackets.apiary.base.AppEnvironment -import org.robojackets.apiary.base.ui.theme.BottomSheetShape import org.robojackets.apiary.base.ui.util.MadeWithLove // TODO: M3 upgrade @@ -44,7 +39,7 @@ import org.robojackets.apiary.base.ui.util.MadeWithLove // - Update to M3 AlertDialog // - Test auth behavior with new theme -@OptIn(ExperimentalMaterialApi::class, androidx.compose.ui.ExperimentalComposeUiApi::class) +@OptIn(ExperimentalMaterial3Api::class) @Suppress("LongMethod", "MagicNumber") @Composable private fun Authentication( @@ -53,13 +48,7 @@ private fun Authentication( onAppEnvChange: (newEnv: AppEnvironment) -> Unit, viewModel: AuthenticationViewModel, ) { - // You have to `remember` two things here for some reason - // In any case, thanks to https://proandroiddev.com/getting-your-bottomsheetscaffold-working-on-jetpack-compose-beta-03-aa829b0c9b6c - val scaffoldState = rememberBottomSheetScaffoldState( - bottomSheetState = rememberBottomSheetState( - initialValue = BottomSheetValue.Collapsed - ) - ) + val scaffoldState = rememberBottomSheetScaffoldState() val coroutineScope = rememberCoroutineScope() val systemUiController = rememberSystemUiController() @@ -99,11 +88,13 @@ private fun Authentication( viewModel.navigateToAttendance() } } + ex != null -> viewModel.recordAuthError(ex) else -> viewModel.recordAuthError(null) } } } + authException != null -> viewModel.recordAuthError(authException) } } else { @@ -111,113 +102,125 @@ private fun Authentication( } } - BottomSheetScaffold( - scaffoldState = scaffoldState, - sheetShape = BottomSheetShape, - sheetPeekHeight = 0.dp, - sheetContent = { - Column( - Modifier - .fillMaxWidth() - .defaultMinSize(minHeight = 56.dp), - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.SpaceEvenly, - content = { - ChangeEnvironmentBottomSheetContent( - viewState, - onAppEnvChange, - scaffoldState - ) - } - ) - }) { - Surface( - color = MaterialTheme.colorScheme.background, - modifier = Modifier.padding(8.dp) + var showChangeEnvBottomSheet by remember { mutableStateOf(false) } + + + if (showChangeEnvBottomSheet) { + ChangeEnvBottomSheet( + onDismiss = { showChangeEnvBottomSheet = false }, + viewState = viewState, + onAppEnvChange = { + showChangeEnvBottomSheet = false + onAppEnvChange(it) + } + ) + } + + Column( + modifier = Modifier + .fillMaxWidth() + .fillMaxHeight(), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.SpaceBetween + ) { + Image( + painter = painterResource(id = R.drawable.ic_robobuzz_white_outline), + contentDescription = "RoboJackets logo", + modifier = Modifier + .fillMaxWidth(.45f) + .weight(1.0f) + ) + Column( + modifier = Modifier.weight(.5f), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.SpaceAround ) { - Column( - modifier = Modifier - .fillMaxWidth() - .fillMaxHeight(), - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.SpaceBetween + + Button( + onClick = { + val authRequest = authManager.getAuthRequest() + launcher.launch( + authManager.authService.getAuthorizationRequestIntent( + authRequest + ) + ) + }, ) { - Image( - painter = painterResource(id = R.drawable.ic_robobuzz_white_outline), - contentDescription = "RoboJackets logo", - modifier = Modifier - .fillMaxWidth(.45f) - .weight(1.0f) - ) - Column( - modifier = Modifier.weight(.5f), - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.SpaceAround - ) { + Text("Sign in with MyRoboJackets") + } + } - Button( - onClick = { - val authRequest = authManager.getAuthRequest() - launcher.launch( - authManager.authService.getAuthorizationRequestIntent( - authRequest - ) - ) - }, - ) { - Text("Sign in with MyRoboJackets") + if (viewState.loginStatus == ERROR) { + AlertDialog( + onDismissRequest = { + viewModel.setLoginStatus(NOT_STARTED) + }, + confirmButton = { + TextButton(onClick = { viewModel.setLoginStatus(NOT_STARTED) }) { + Text("Close") } - } - - if (viewState.loginStatus == ERROR) { - AlertDialog( - onDismissRequest = { - viewModel.setLoginStatus(NOT_STARTED) - }, - confirmButton = { - TextButton(onClick = { viewModel.setLoginStatus(NOT_STARTED) }) { - Text("Close") - } - }, - title = { Text("Login failed") }, - text = { - Text( - "${viewState.loginErrorMessage}\n\nTry logging in again. " + - "If that does not work, please post in #it-helpdesk in Slack." - ) - }, + }, + title = { Text("Login failed") }, + text = { + Text( + "${viewState.loginErrorMessage}\n\nTry logging in again. " + + "If that does not work, please post in #it-helpdesk in Slack." ) - } + }, + ) + } - TextButton(onClick = { - coroutineScope.launch { - scaffoldState.bottomSheetState.expand() - } - }) { - Text("Change server") - } - Text("Server: ${viewState.appEnv.name} (${viewState.appEnv.apiBaseUrl})") - MadeWithLove() - } + TextButton(onClick = { + showChangeEnvBottomSheet = true + }) { + Text("Change server") } + Text("Server: ${viewState.appEnv.name} (${viewState.appEnv.apiBaseUrl})") + MadeWithLove() + } +} + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun ChangeEnvBottomSheet( + onDismiss: () -> Unit, + viewState: AuthenticationState, + onAppEnvChange: (newEnv: AppEnvironment) -> Unit +) { + val modalBottomSheetState = rememberModalBottomSheetState() + + ModalBottomSheet( + onDismissRequest = { onDismiss() }, + sheetState = modalBottomSheetState, + ) { + Column( + Modifier + .padding(bottom = 40.dp) + .fillMaxWidth() + .defaultMinSize(minHeight = 56.dp), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.SpaceEvenly, + content = { + ChangeEnvironmentBottomSheetContent( + viewState, + onAppEnvChange, + ) + } + ) } } -@OptIn(ExperimentalMaterialApi::class) +@OptIn(ExperimentalMaterial3Api::class) @Composable private fun ChangeEnvironmentBottomSheetContent( viewState: AuthenticationState, onAppEnvChange: (newEnv: AppEnvironment) -> Unit, - scaffoldState: BottomSheetScaffoldState ) { val coroutineScope = rememberCoroutineScope() var unsavedAppEnvSelection by remember { mutableStateOf(viewState.appEnv) } val appEnvChoices = AppEnvironment.values() val saveNewAppEnvChoice: (() -> Unit) = { onAppEnvChange(unsavedAppEnvSelection) - coroutineScope.launch { - scaffoldState.bottomSheetState.collapse() - } } Text( @@ -265,7 +268,7 @@ private fun ChangeEnvironmentBottomSheetContent( @Composable fun AuthenticationScreen( viewModel: AuthenticationViewModel, - authManager: AuthManager + authManager: AuthManager, ) { val viewState by viewModel.state.collectAsState() Authentication( diff --git a/auth/src/main/java/org/robojackets/apiary/auth/ui/permissions/InsufficientPermissions.kt b/auth/src/main/java/org/robojackets/apiary/auth/ui/permissions/InsufficientPermissions.kt index a3cc943..54faec2 100644 --- a/auth/src/main/java/org/robojackets/apiary/auth/ui/permissions/InsufficientPermissions.kt +++ b/auth/src/main/java/org/robojackets/apiary/auth/ui/permissions/InsufficientPermissions.kt @@ -1,12 +1,17 @@ package org.robojackets.apiary.auth.ui.permissions -import androidx.compose.foundation.layout.* +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items -import androidx.compose.material.AlertDialog -import androidx.compose.material.ExperimentalMaterialApi import androidx.compose.material.icons.Icons import androidx.compose.material.icons.outlined.CheckCircle +import androidx.compose.material3.AlertDialog import androidx.compose.material3.Divider import androidx.compose.material3.Icon import androidx.compose.material3.ListItem @@ -14,13 +19,16 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.material3.OutlinedButton import androidx.compose.material3.Text import androidx.compose.material3.TextButton -import androidx.compose.runtime.* +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import androidx.core.content.ContextCompat.* import org.robojackets.apiary.auth.model.Permission import org.robojackets.apiary.auth.model.Permission.* import org.robojackets.apiary.base.ui.error.GoToItHelpdesk @@ -29,9 +37,6 @@ import org.robojackets.apiary.base.ui.theme.danger import org.robojackets.apiary.base.ui.theme.success import org.robojackets.apiary.base.ui.util.ContentPadding -// TODO: M3 upgrade -// - Update to M3 AlertDialog - @Composable fun InsufficientPermissions( featureName: String, @@ -131,7 +136,6 @@ fun PermissionDetailsDialog( ) } -@OptIn(ExperimentalMaterialApi::class) @Composable fun PermissionsListItem(hasPermission: Boolean, permissionName: String) { ListItem( diff --git a/base/build.gradle.kts b/base/build.gradle.kts index bfeca8d..cd90e77 100644 --- a/base/build.gradle.kts +++ b/base/build.gradle.kts @@ -17,7 +17,6 @@ dependencies { implementation(AndroidToolDependencies.timber) implementation(ComposeDependencies.compose_foundation) - implementation(ComposeDependencies.compose_material) implementation(ComposeDependencies.compose_material3) implementation(ComposeDependencies.compose_ui) implementation(ComposeDependencies.compose_ui_tooling) diff --git a/base/src/main/java/org/robojackets/apiary/base/ui/nfc/BuzzCardPrompt.kt b/base/src/main/java/org/robojackets/apiary/base/ui/nfc/BuzzCardPrompt.kt index b53e4ee..94e32ea 100644 --- a/base/src/main/java/org/robojackets/apiary/base/ui/nfc/BuzzCardPrompt.kt +++ b/base/src/main/java/org/robojackets/apiary/base/ui/nfc/BuzzCardPrompt.kt @@ -5,7 +5,7 @@ import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.text.KeyboardOptions -import androidx.compose.material.AlertDialog +import androidx.compose.material3.AlertDialog import androidx.compose.material3.Button import androidx.compose.material3.MaterialTheme import androidx.compose.material3.OutlinedTextField diff --git a/base/src/main/java/org/robojackets/apiary/base/ui/theme/Theme.kt b/base/src/main/java/org/robojackets/apiary/base/ui/theme/Theme.kt index 3e2fd5a..deb2e15 100644 --- a/base/src/main/java/org/robojackets/apiary/base/ui/theme/Theme.kt +++ b/base/src/main/java/org/robojackets/apiary/base/ui/theme/Theme.kt @@ -1,35 +1,12 @@ package org.robojackets.apiary.base.ui.theme import androidx.compose.foundation.isSystemInDarkTheme -import androidx.compose.material.darkColors -import androidx.compose.material.lightColors import androidx.compose.material3.MaterialTheme import androidx.compose.material3.darkColorScheme import androidx.compose.material3.lightColorScheme import androidx.compose.runtime.Composable import androidx.compose.ui.graphics.Color -private val DarkColorPalette = darkColors( - primary = GoldLight, - primaryVariant = GoldDark, - secondary = Color.White, -) - -private val LightColorPalette = lightColors( - primary = Gold, - primaryVariant = GoldDark, - secondary = Color.Black, - - /* Other default colors to override - background = Color.White, - surface = Color.White, - onPrimary = Color.White, - onSecondary = Color.Black, - onBackground = Color.Black, - onSurface = Color.Black, - */ -) - val LightColorScheme = lightColorScheme( primary = Gold, secondary = GoldDark, diff --git a/buildSrc/src/main/java/Dependencies.kt b/buildSrc/src/main/java/Dependencies.kt index 9d3a185..74470a1 100644 --- a/buildSrc/src/main/java/Dependencies.kt +++ b/buildSrc/src/main/java/Dependencies.kt @@ -15,7 +15,8 @@ object ComposeDependencies { const val compose_foundation = "androidx.compose.foundation:foundation:${Versions.compose_version}" - const val compose_material = "androidx.compose.material:material:${Versions.compose_version}" + const val compose_material3 = + "androidx.compose.material3:material3:${Versions.compose_material3_version}" const val compose_material_icons_core = "androidx.compose.material:material-icons-core:${Versions.compose_version}" const val compose_material_icons_extended = @@ -35,8 +36,7 @@ object ComposeDependencies { const val lifecycle_viewmodel_compose = "androidx.lifecycle:lifecycle-viewmodel-compose:${Versions.lifecycle_viewmodel_compose_version}" - const val compose_material3 = - "androidx.compose.material3:material3:${Versions.compose_material3_version}" + } object MaterialDependencies { From b7eb39c34591d421e171553d2ddf046d086ed8a7 Mon Sep 17 00:00:00 2001 From: Evan Strat <evan10s@users.noreply.github.com> Date: Sun, 20 Aug 2023 19:27:00 -0400 Subject: [PATCH 06/33] Dependency updates --- app/build.gradle.kts | 3 ++- app/src/main/java/org/robojackets/apiary/MainActivity.kt | 6 +++--- attendance/build.gradle.kts | 6 +++--- auth/build.gradle.kts | 6 +++--- base/build.gradle.kts | 6 +++--- build.gradle.kts | 5 +++-- buildSrc/src/main/java/Dependencies.kt | 6 +++--- navigation/build.gradle.kts | 4 ++-- 8 files changed, 22 insertions(+), 20 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 8fe5451..fbf6dad 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -3,6 +3,7 @@ plugins { kotlin("android") id("kotlin-android") kotlin("kapt") + id("com.google.devtools.ksp") id("dagger.hilt.android.plugin") id("com.google.android.libraries.mapsplatform.secrets-gradle-plugin") id("com.google.android.gms.oss-licenses-plugin") @@ -99,7 +100,7 @@ android { jvmTarget = "17" } composeOptions { - kotlinCompilerExtensionVersion = "1.4.7" + kotlinCompilerExtensionVersion = "1.5.1" } namespace = "org.robojackets.apiary" hilt { diff --git a/app/src/main/java/org/robojackets/apiary/MainActivity.kt b/app/src/main/java/org/robojackets/apiary/MainActivity.kt index 0ae1af0..a192ae7 100644 --- a/app/src/main/java/org/robojackets/apiary/MainActivity.kt +++ b/app/src/main/java/org/robojackets/apiary/MainActivity.kt @@ -272,7 +272,7 @@ class MainActivity : ComponentActivity() { navArgument("attendableType") { type = NavType.StringType } ), ) { - val attendableType = it.arguments?.get("attendableType") + val attendableType = it.arguments?.getString("attendableType") AttendableSelectionScreen( hiltViewModel(), @@ -287,8 +287,8 @@ class MainActivity : ComponentActivity() { navArgument("attendableId") { type = NavType.IntType }, ) ) { - val attendableType = it.arguments?.get("attendableType") - val attendableId = it.arguments?.get("attendableId") + val attendableType = it.arguments?.getString("attendableType") + val attendableId = it.arguments?.getInt("attendableId") AttendanceScreen( hiltViewModel(), diff --git a/attendance/build.gradle.kts b/attendance/build.gradle.kts index 4df0cbe..878df10 100644 --- a/attendance/build.gradle.kts +++ b/attendance/build.gradle.kts @@ -3,6 +3,7 @@ plugins { kotlin("android") id("kotlin-android") kotlin("kapt") + id("com.google.devtools.ksp") id("dagger.hilt.android.plugin") id("com.google.android.libraries.mapsplatform.secrets-gradle-plugin") } @@ -26,7 +27,7 @@ dependencies { kapt(HiltDependencies.hilt_android_compiler) implementation(NetworkDependencies.moshi) - kapt(NetworkDependencies.moshi_kotlin_codegen) + ksp(NetworkDependencies.moshi_kotlin_codegen) implementation(NetworkDependencies.okhttp) implementation(platform(NetworkDependencies.okhttp_bom)) implementation(NetworkDependencies.retrofit) @@ -47,7 +48,6 @@ android { compileSdk = 33 defaultConfig { minSdk = 21 - targetSdk = 33 vectorDrawables { useSupportLibrary = true } @@ -69,7 +69,7 @@ android { jvmTarget = "17" } composeOptions { - kotlinCompilerExtensionVersion = "1.4.7" + kotlinCompilerExtensionVersion = "1.5.1" } namespace = "org.robojackets.apiary.attendance" hilt { diff --git a/auth/build.gradle.kts b/auth/build.gradle.kts index daf62ac..785301f 100644 --- a/auth/build.gradle.kts +++ b/auth/build.gradle.kts @@ -3,6 +3,7 @@ plugins { kotlin("android") id("kotlin-android") kotlin("kapt") + id("com.google.devtools.ksp") id("dagger.hilt.android.plugin") id("com.google.android.libraries.mapsplatform.secrets-gradle-plugin") } @@ -38,7 +39,7 @@ dependencies { implementation(MaterialDependencies.material_android) implementation(NetworkDependencies.moshi) - kapt(NetworkDependencies.moshi_kotlin_codegen) + ksp(NetworkDependencies.moshi_kotlin_codegen) implementation(NetworkDependencies.okhttp) implementation(platform(NetworkDependencies.okhttp_bom)) implementation(NetworkDependencies.retrofit) @@ -55,7 +56,6 @@ android { compileSdk = 33 defaultConfig { minSdk = 21 - targetSdk = 33 vectorDrawables { useSupportLibrary = true @@ -79,7 +79,7 @@ android { jvmTarget = "17" } composeOptions { - kotlinCompilerExtensionVersion = "1.4.7" + kotlinCompilerExtensionVersion = "1.5.1" } namespace = "org.robojackets.apiary.auth" hilt { diff --git a/base/build.gradle.kts b/base/build.gradle.kts index cd90e77..1373472 100644 --- a/base/build.gradle.kts +++ b/base/build.gradle.kts @@ -3,6 +3,7 @@ plugins { kotlin("android") id("kotlin-android") kotlin("kapt") + id("com.google.devtools.ksp") id("dagger.hilt.android.plugin") id("com.google.android.libraries.mapsplatform.secrets-gradle-plugin") } @@ -28,7 +29,7 @@ dependencies { kapt(HiltDependencies.hilt_android_compiler) implementation(NetworkDependencies.moshi) - kapt(NetworkDependencies.moshi_kotlin_codegen) + ksp(NetworkDependencies.moshi_kotlin_codegen) implementation(NetworkDependencies.retrofit) implementation(NetworkDependencies.sandwich) @@ -49,7 +50,6 @@ android { compileSdk = 33 defaultConfig { minSdk = 21 - targetSdk = 33 vectorDrawables { useSupportLibrary = true @@ -72,7 +72,7 @@ android { jvmTarget = "17" } composeOptions { - kotlinCompilerExtensionVersion = "1.4.7" + kotlinCompilerExtensionVersion = "1.5.1" } namespace = "org.robojackets.apiary.base" hilt { diff --git a/build.gradle.kts b/build.gradle.kts index a81b354..64ac937 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -5,7 +5,7 @@ buildscript { mavenCentral() } dependencies { - classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.21") + classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.0") classpath("com.android.tools.build:gradle:8.1.0") classpath("com.google.dagger:hilt-android-gradle-plugin:2.46.1") classpath("com.google.android.libraries.mapsplatform.secrets-gradle-plugin:secrets-gradle-plugin:2.0.1") @@ -29,8 +29,9 @@ allprojects { } plugins { + id("com.google.devtools.ksp").version("1.9.0-1.0.13").apply(false) id("io.gitlab.arturbosch.detekt").version("1.23.0") - id("com.autonomousapps.dependency-analysis").version("1.20.0") + id("com.autonomousapps.dependency-analysis").version("1.21.0") id("com.github.ben-manes.versions").version("0.46.0") } diff --git a/buildSrc/src/main/java/Dependencies.kt b/buildSrc/src/main/java/Dependencies.kt index 74470a1..2426b55 100644 --- a/buildSrc/src/main/java/Dependencies.kt +++ b/buildSrc/src/main/java/Dependencies.kt @@ -94,7 +94,7 @@ object AuthDependencies { object HiltDependencies { object Versions { const val hilt_navigation_compose_version = "1.0.0" - const val hilt_version = "2.44" + const val hilt_version = "2.46.1" } const val hilt = "com.google.dagger:hilt-android:${Versions.hilt_version}" @@ -111,7 +111,7 @@ object AndroidToolDependencies { const val gson_version = "2.10.1" const val in_app_update_compose_version = "0.0.17" const val open_source_licenses_version = "17.0.1" - const val sentry_version = "6.19.1" + const val sentry_version = "6.28.0" const val timber_version = "5.0.1" } @@ -135,7 +135,7 @@ object NetworkDependencies { const val okhttp_bom_version = "4.11.0" const val retrofit_version = "2.9.0" const val retrofuture_version = "1.7.4" - const val sandwich_version = "1.3.6" + const val sandwich_version = "1.3.8" } const val moshi = "com.squareup.moshi:moshi:${Versions.moshi_version}" diff --git a/navigation/build.gradle.kts b/navigation/build.gradle.kts index f293d8a..716c8a1 100644 --- a/navigation/build.gradle.kts +++ b/navigation/build.gradle.kts @@ -3,6 +3,7 @@ plugins { kotlin("android") id("kotlin-android") kotlin("kapt") + id("com.google.devtools.ksp") id("dagger.hilt.android.plugin") id("com.google.android.libraries.mapsplatform.secrets-gradle-plugin") } @@ -34,7 +35,6 @@ android { compileSdk = 33 defaultConfig { minSdk = 21 - targetSdk = 33 vectorDrawables { useSupportLibrary = true @@ -57,7 +57,7 @@ android { jvmTarget = "17" } composeOptions { - kotlinCompilerExtensionVersion = "1.4.7" + kotlinCompilerExtensionVersion = "1.5.1" } namespace = "org.robojackets.apiary.navigation" hilt { From 9d1cc96285c9b5511ff7a909836ee9a3c5a6db65 Mon Sep 17 00:00:00 2001 From: Evan Strat <evan10s@users.noreply.github.com> Date: Sun, 20 Aug 2023 19:31:31 -0400 Subject: [PATCH 07/33] Cleanup M3 upgrade todos --- .../java/org/robojackets/apiary/ui/update/UpdateAvailable.kt | 3 --- .../java/org/robojackets/apiary/auth/ui/Authentication.kt | 5 ----- .../org/robojackets/apiary/base/ui/nfc/BuzzCardPrompt.kt | 5 ----- 3 files changed, 13 deletions(-) diff --git a/app/src/main/java/org/robojackets/apiary/ui/update/UpdateAvailable.kt b/app/src/main/java/org/robojackets/apiary/ui/update/UpdateAvailable.kt index 1fc505e..3717ace 100644 --- a/app/src/main/java/org/robojackets/apiary/ui/update/UpdateAvailable.kt +++ b/app/src/main/java/org/robojackets/apiary/ui/update/UpdateAvailable.kt @@ -21,9 +21,6 @@ import org.robojackets.apiary.base.ui.util.getActivity import se.warting.inappupdate.compose.rememberInAppUpdateState import timber.log.Timber -// TODO: M3 upgrade: -// - Implement M3 AlertDialog - // Just a random number so we can identify our update request later if necessary const val UPDATE_REQUEST_CODE = 1999 diff --git a/auth/src/main/java/org/robojackets/apiary/auth/ui/Authentication.kt b/auth/src/main/java/org/robojackets/apiary/auth/ui/Authentication.kt index e59ed6f..f785a01 100644 --- a/auth/src/main/java/org/robojackets/apiary/auth/ui/Authentication.kt +++ b/auth/src/main/java/org/robojackets/apiary/auth/ui/Authentication.kt @@ -34,11 +34,6 @@ import org.robojackets.apiary.auth.oauth2.AuthManager import org.robojackets.apiary.base.AppEnvironment import org.robojackets.apiary.base.ui.util.MadeWithLove -// TODO: M3 upgrade -// - Update to M3 BottomSheet -// - Update to M3 AlertDialog -// - Test auth behavior with new theme - @OptIn(ExperimentalMaterial3Api::class) @Suppress("LongMethod", "MagicNumber") @Composable diff --git a/base/src/main/java/org/robojackets/apiary/base/ui/nfc/BuzzCardPrompt.kt b/base/src/main/java/org/robojackets/apiary/base/ui/nfc/BuzzCardPrompt.kt index 94e32ea..1ca0477 100644 --- a/base/src/main/java/org/robojackets/apiary/base/ui/nfc/BuzzCardPrompt.kt +++ b/base/src/main/java/org/robojackets/apiary/base/ui/nfc/BuzzCardPrompt.kt @@ -32,11 +32,6 @@ import org.robojackets.apiary.base.ui.theme.danger import timber.log.Timber import java.nio.charset.StandardCharsets -// TODO: M3 upgrade -// - Switch to M3 AlertDialog -// - Verify icon/text colors are correct in dark mode -// - Verify Contactless icon color is correct in light mode - /** * Show a prompt for BuzzCards and call a callback function each time a valid GTID is obtained. * From ad28be1e14fde45482f09fb3313159247af1b3e8 Mon Sep 17 00:00:00 2001 From: Evan Strat <evan10s@users.noreply.github.com> Date: Sun, 20 Aug 2023 19:46:00 -0400 Subject: [PATCH 08/33] Use android-build-box 1.25 for Java 17 support --- ci/dockerfiles/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/dockerfiles/Dockerfile b/ci/dockerfiles/Dockerfile index a51916d..b2ddf9d 100644 --- a/ci/dockerfiles/Dockerfile +++ b/ci/dockerfiles/Dockerfile @@ -1,6 +1,6 @@ # This value is overridden during Concourse jobs to use a local copy of the image. # If you are changing the base image here, you should also change it in the Concourse pipeline configuration. -ARG base_image=mingc/android-build-box:1.24.0 +ARG base_image=mingc/android-build-box:1.25.0 FROM ${base_image} LABEL maintainer="RoboJackets <hello@robojackets.org>" From cdfa2c57f3d9d9de34f567c868ef960484f6603e Mon Sep 17 00:00:00 2001 From: Evan Strat <evan10s@users.noreply.github.com> Date: Fri, 1 Sep 2023 00:12:49 -0400 Subject: [PATCH 09/33] Update detekt config to remove deprecated rules --- ci/detekt/detekt.yml | 57 +++++++++++++------------------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/ci/detekt/detekt.yml b/ci/detekt/detekt.yml index 418dc11..c2b990c 100644 --- a/ci/detekt/detekt.yml +++ b/ci/detekt/detekt.yml @@ -85,7 +85,7 @@ complexity: threshold: 10 includeStaticDeclarations: false includePrivateDeclarations: false - ComplexMethod: + CyclomaticComplexMethod: active: true threshold: 15 ignoreSingleWhenExpression: false @@ -302,7 +302,6 @@ formatting: active: false autoCorrect: true indentSize: 4 - continuationIndentSize: 4 MaximumLineLength: active: true maxLineLength: 120 @@ -411,7 +410,6 @@ naming: parameterPattern: '[a-z][A-Za-z0-9]*' privateParameterPattern: '[a-z][A-Za-z0-9]*' excludeClassPattern: '$^' - ignoreOverridden: true EnumNaming: active: true excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] @@ -433,7 +431,6 @@ naming: excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] functionPattern: '([a-z][a-zA-Z0-9]*)|(`.*`)' excludeClassPattern: '$^' - ignoreOverridden: true ignoreAnnotated: - 'Composable' FunctionParameterNaming: @@ -441,7 +438,6 @@ naming: excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] parameterPattern: '[a-z][A-Za-z0-9]*' excludeClassPattern: '$^' - ignoreOverridden: true InvalidPackageDeclaration: active: false excludes: ['**/*.kts'] @@ -487,7 +483,6 @@ naming: variablePattern: '[a-z][A-Za-z0-9]*' privateVariablePattern: '(_)?[a-z][A-Za-z0-9]*' excludeClassPattern: '$^' - ignoreOverridden: true performance: active: true @@ -512,8 +507,6 @@ potential-bugs: active: false DoubleMutabilityForCollection: active: false - DuplicateCaseInWhenExpression: - active: true EqualsAlwaysReturnsTrueOrFalse: active: true EqualsWithHashCodeExist: @@ -526,7 +519,7 @@ potential-bugs: active: false IgnoredReturnValue: active: false - restrictToAnnotatedMethods: true + restrictToConfig: true returnValueAnnotations: - '*.CheckReturnValue' - '*.CheckResult' @@ -544,17 +537,12 @@ potential-bugs: LateinitUsage: active: false excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] - excludeAnnotatedProperties: [] + ignoreAnnotated: [] ignoreOnClassesPattern: '' MapGetWithNotNullAssertionOperator: active: false - MissingWhenCase: - active: true - allowElseExpression: true NullableToStringCall: active: false - RedundantElseInWhen: - active: true UnconditionalJumpStatementInLoop: active: false UnnecessaryNotNullOperator: @@ -584,7 +572,8 @@ style: active: false DataClassContainsFunctions: active: false - conversionFunctionPrefix: 'to' + conversionFunctionPrefix: + - to DataClassShouldBeImmutable: active: false DestructuringDeclarationWithTooManyEntries: @@ -603,10 +592,11 @@ style: includeLineWrapping: false ForbiddenComment: active: true - values: - - 'TODO:' - - 'FIXME:' - - 'STOPSHIP:' + comments: + - reason: 'Forbidden FIXME todo marker in comment, please fix the problem.' + value: 'FIXME:' + - reason: 'Forbidden STOPSHIP todo marker in comment, please address the problem before shipping the code.' + value: 'STOPSHIP:' allowedPatterns: '' ForbiddenImport: active: false @@ -617,12 +607,6 @@ style: methods: - 'kotlin.io.println' - 'kotlin.io.print' - ForbiddenPublicDataClass: - active: true - excludes: ['**'] - ignorePackages: - - '*.internal' - - '*.internal.*' ForbiddenVoid: active: false ignoreOverridden: false @@ -631,15 +615,9 @@ style: active: true ignoreOverridableFunction: true ignoreActualFunction: true - excludedFunctions: '' - excludeAnnotatedFunction: + excludedFunctions: [] + ignoreAnnotated: - 'dagger.Provides' - LibraryCodeMustSpecifyReturnType: - active: true - excludes: ['**'] - LibraryEntitiesShouldNotBePublic: - active: true - excludes: ['**'] LoopWithTooManyJumpStatements: active: true maxJumpCount: 1 @@ -661,8 +639,6 @@ style: ignoreEnums: false ignoreRanges: false ignoreExtensionFunctions: true - MandatoryBracesIfStatements: - active: false MandatoryBracesLoops: active: false MaxLineLength: @@ -704,7 +680,8 @@ style: ReturnCount: active: true max: 2 - excludedFunctions: 'equals' + excludedFunctions: + - equals excludeLabeled: false excludeReturnFromLambda: true excludeGuardClauses: false @@ -722,10 +699,10 @@ style: active: false UnderscoresInNumericLiterals: active: false - acceptableDecimalLength: 5 + acceptableLength: 5 UnnecessaryAbstractClass: active: true - excludeAnnotatedClasses: + ignoreAnnotated: - 'dagger.Module' UnnecessaryAnnotationUseSiteTarget: active: false @@ -756,7 +733,7 @@ style: active: false UseDataClass: active: false - excludeAnnotatedClasses: [] + ignoreAnnotated: [] allowVars: false UseEmptyCounterpart: active: false From 9f3ee8df790427027d3966e044db4e8978a3e4da Mon Sep 17 00:00:00 2001 From: Evan Strat <evan10s@users.noreply.github.com> Date: Fri, 1 Sep 2023 00:13:32 -0400 Subject: [PATCH 10/33] Update detekt plugin version --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index 64ac937..8d61bf1 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -72,7 +72,7 @@ tasks.register("detektAll", io.gitlab.arturbosch.detekt.Detekt::class) { } dependencies { - detektPlugins("io.gitlab.arturbosch.detekt:detekt-formatting:1.22.0") + detektPlugins("io.gitlab.arturbosch.detekt:detekt-formatting:1.23.0") } // from https://github.com/autonomousapps/dependency-analysis-android-gradle-plugin/wiki/ABI-filtering From 0f7e0862c963f3616005e81826ff8d6982de97dc Mon Sep 17 00:00:00 2001 From: Evan Strat <evan10s@users.noreply.github.com> Date: Fri, 1 Sep 2023 00:13:52 -0400 Subject: [PATCH 11/33] Update comment --- ci/dockerfiles/Dockerfile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ci/dockerfiles/Dockerfile b/ci/dockerfiles/Dockerfile index b2ddf9d..c596687 100644 --- a/ci/dockerfiles/Dockerfile +++ b/ci/dockerfiles/Dockerfile @@ -1,5 +1,6 @@ # This value is overridden during Concourse jobs to use a local copy of the image. -# If you are changing the base image here, you should also change it in the Concourse pipeline configuration. +# If you are changing the base image here, you should also change it in the Concourse pipeline configuration +# in https://github.com/RoboJackets/concourse-pipeline-library/blob/main/pipelines/information-technology/apiary-mobile-docker-build.yml ARG base_image=mingc/android-build-box:1.25.0 FROM ${base_image} From bddb438f7fb7c661a8822d5daccb13e716165ca3 Mon Sep 17 00:00:00 2001 From: Evan Strat <evan10s@users.noreply.github.com> Date: Fri, 1 Sep 2023 00:14:12 -0400 Subject: [PATCH 12/33] Style fixes --- .../org/robojackets/apiary/MainActivity.kt | 7 ++-- .../apiary/di/MainActivityModule.kt | 7 ++-- .../apiary/network/UserAgentInterceptor.kt | 10 ++++-- .../robojackets/apiary/ui/global/AppTopBar.kt | 6 ++-- .../apiary/ui/settings/Settings.kt | 14 +++++--- .../apiary/ui/settings/SettingsViewModel.kt | 15 ++++++--- .../apiary/ui/update/UpdateAvailable.kt | 33 ++++++++++++------- .../apiary/ui/update/UpdateGate.kt | 15 ++++++--- .../model/AttendableTypeSelectionViewModel.kt | 9 +++-- .../attendance/model/AttendanceViewModel.kt | 15 ++++++--- .../ui/AttendableTypeSelectionScreen.kt | 7 ++-- .../apiary/auth/ui/Authentication.kt | 6 ---- .../permissions/MissingHiddenTeamsCallout.kt | 6 ++-- .../apiary/base/ui/ActionPrompt.kt | 6 ++-- .../apiary/base/ui/callout/Callout.kt | 6 ++-- .../apiary/base/ui/nfc/NfcRequired.kt | 3 +- buildSrc/src/main/java/Dependencies.kt | 2 -- 17 files changed, 109 insertions(+), 58 deletions(-) diff --git a/app/src/main/java/org/robojackets/apiary/MainActivity.kt b/app/src/main/java/org/robojackets/apiary/MainActivity.kt index a192ae7..0f926ec 100644 --- a/app/src/main/java/org/robojackets/apiary/MainActivity.kt +++ b/app/src/main/java/org/robojackets/apiary/MainActivity.kt @@ -246,8 +246,11 @@ class MainActivity : ComponentActivity() { modifier: Modifier = Modifier, ) { val startDestination = - if (!authStateManager.current.isAuthorized) NavigationDestinations.authentication - else NavigationDestinations.attendanceSubgraph + if (!authStateManager.current.isAuthorized) { + NavigationDestinations.authentication + } else { + NavigationDestinations.attendanceSubgraph + } NavHost( navController = navController, diff --git a/app/src/main/java/org/robojackets/apiary/di/MainActivityModule.kt b/app/src/main/java/org/robojackets/apiary/di/MainActivityModule.kt index e6be8c7..b5aa650 100644 --- a/app/src/main/java/org/robojackets/apiary/di/MainActivityModule.kt +++ b/app/src/main/java/org/robojackets/apiary/di/MainActivityModule.kt @@ -45,8 +45,11 @@ object MainActivityModule { ): OkHttpClient { val loggingInterceptor = HttpLoggingInterceptor() loggingInterceptor.setLevel( - if (BuildConfig.DEBUG) HttpLoggingInterceptor.Level.BODY - else HttpLoggingInterceptor.Level.BASIC + if (BuildConfig.DEBUG) { + HttpLoggingInterceptor.Level.BODY + } else { + HttpLoggingInterceptor.Level.BASIC + } ) // Only log detailed // network requests in debug builds loggingInterceptor.redactHeader("Authorization") // Redact access tokens in headers diff --git a/app/src/main/java/org/robojackets/apiary/network/UserAgentInterceptor.kt b/app/src/main/java/org/robojackets/apiary/network/UserAgentInterceptor.kt index dcd8d26..cafceb1 100644 --- a/app/src/main/java/org/robojackets/apiary/network/UserAgentInterceptor.kt +++ b/app/src/main/java/org/robojackets/apiary/network/UserAgentInterceptor.kt @@ -24,9 +24,13 @@ class UserAgentInterceptor(context: Context) : Interceptor { private fun getApplicationName(context: Context): String { val applicationInfo = context.applicationInfo val stringId = applicationInfo.labelRes - return if (stringId == 0) applicationInfo.nonLocalizedLabel.toString() else context.getString( + return if (stringId == 0) { + applicationInfo.nonLocalizedLabel.toString() + } else { + context.getString( stringId ) + } } private fun getDeviceName(): String { @@ -34,7 +38,9 @@ class UserAgentInterceptor(context: Context) : Interceptor { val model = Build.MODEL return if (model.startsWith(manufacturer)) { model.replaceFirstChar { it.titlecase() } - } else manufacturer.replaceFirstChar { it.titlecase() } + " " + model + } else { + manufacturer.replaceFirstChar { it.titlecase() } + " " + model + } } override fun intercept(chain: Interceptor.Chain): Response { diff --git a/app/src/main/java/org/robojackets/apiary/ui/global/AppTopBar.kt b/app/src/main/java/org/robojackets/apiary/ui/global/AppTopBar.kt index 4d42b22..d077626 100644 --- a/app/src/main/java/org/robojackets/apiary/ui/global/AppTopBar.kt +++ b/app/src/main/java/org/robojackets/apiary/ui/global/AppTopBar.kt @@ -41,11 +41,13 @@ fun AppTopBar(isProdEnv: Boolean) { ) { IconWithText( icon = { WarningIcon(tint = MaterialTheme.colorScheme.onError) }, - text = { Text( + text = { + Text( "Non-production server", modifier = Modifier.padding(start = 4.dp), color = MaterialTheme.colorScheme.onError - ) } + ) + } ) } } diff --git a/app/src/main/java/org/robojackets/apiary/ui/settings/Settings.kt b/app/src/main/java/org/robojackets/apiary/ui/settings/Settings.kt index 481aba8..9e8b3ec 100644 --- a/app/src/main/java/org/robojackets/apiary/ui/settings/Settings.kt +++ b/app/src/main/java/org/robojackets/apiary/ui/settings/Settings.kt @@ -34,7 +34,7 @@ import org.robojackets.apiary.ui.update.UpdateStatus @Suppress("LongMethod", "LongParameterList") @Composable - private fun Settings( +private fun Settings( appEnv: AppEnvironment, user: UserInfo?, onLogout: () -> Unit, @@ -76,17 +76,21 @@ import org.robojackets.apiary.ui.update.UpdateStatus SettingsMenuLink( icon = { Icon(Icons.Outlined.Home, contentDescription = "home") }, title = { Text(text = "Server") }, - subtitle = { Text( + subtitle = { + Text( text = "${appEnv.name} (${appEnv.apiBaseUrl})" - ) }, + ) + }, onClick = {} ) SettingsMenuLink( icon = { Icon(Icons.Outlined.Build, contentDescription = "build") }, title = { Text(text = "Version") }, - subtitle = { Text( + subtitle = { + Text( text = "${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE})" - ) }, + ) + }, onClick = {} ) SettingsMenuLink( diff --git a/app/src/main/java/org/robojackets/apiary/ui/settings/SettingsViewModel.kt b/app/src/main/java/org/robojackets/apiary/ui/settings/SettingsViewModel.kt index 8734317..e6c543e 100644 --- a/app/src/main/java/org/robojackets/apiary/ui/settings/SettingsViewModel.kt +++ b/app/src/main/java/org/robojackets/apiary/ui/settings/SettingsViewModel.kt @@ -35,9 +35,11 @@ class SettingsViewModel @Inject constructor( val authStateManager: AuthStateManager, ) : ViewModel() { val privacyPolicyUrl: Uri = Uri.withAppendedPath(globalSettings.appEnv.apiBaseUrl, "privacy") - val makeAWishUrl: Uri = Uri.parse("https://docs.google.com/forms/d/e/1FAIpQLSelERsYq3" + + val makeAWishUrl: Uri = Uri.parse( + "https://docs.google.com/forms/d/e/1FAIpQLSelERsYq3" + "gLmHbWvVCWha5iCU8z3r9VYC0hCN4ArLpMAiysaQ/viewform?entry.1338203640=MyRoboJackets%20" + - "Android") + "Android" + ) var customTabsClient: CustomTabsClient? = null val customTabsServiceConnection = object : CustomTabsServiceConnection() { @@ -67,10 +69,13 @@ class SettingsViewModel @Inject constructor( init { viewModelScope.launch { - combine(listOf( + combine( + listOf( user, - )) { - flows -> SettingsState( + ) + ) { + flows -> + SettingsState( flows[0] as UserInfo? ) }.catch { throwable -> throw throwable } diff --git a/app/src/main/java/org/robojackets/apiary/ui/update/UpdateAvailable.kt b/app/src/main/java/org/robojackets/apiary/ui/update/UpdateAvailable.kt index 3717ace..1926b98 100644 --- a/app/src/main/java/org/robojackets/apiary/ui/update/UpdateAvailable.kt +++ b/app/src/main/java/org/robojackets/apiary/ui/update/UpdateAvailable.kt @@ -72,10 +72,14 @@ fun InstallUpdateButton(onIgnoreUpdate: () -> Unit = {}) { }, title = { Text("Update failed") }, text = { - Text("${ - updateError ?: ("An unknown error occurred while starting the " + - "update.") - }\n\nPlease try again, or post in #it-helpdesk for assistance.") + Text( + "${ + updateError ?: ( + "An unknown error occurred while starting the " + + "update." + ) + }\n\nPlease try again, or post in #it-helpdesk for assistance." + ) } ) } @@ -89,11 +93,14 @@ fun RequiredUpdatePrompt() { verticalArrangement = Arrangement.Center, modifier = Modifier.fillMaxHeight(), ) { - UpdateIcon(Modifier + UpdateIcon( + Modifier .padding(bottom = 18.dp) - .size(96.dp)) + .size(96.dp) + ) Text("Update to continue", style = MaterialTheme.typography.headlineMedium) - Text("To continue using MyRoboJackets, install the latest version. It'll only take a minute.", + Text( + "To continue using MyRoboJackets, install the latest version. It'll only take a minute.", textAlign = TextAlign.Center, modifier = Modifier.padding(24.dp) ) @@ -112,11 +119,14 @@ fun OptionalUpdatePrompt( verticalArrangement = Arrangement.Center, modifier = Modifier.fillMaxHeight(.5F), ) { - UpdateIcon(Modifier + UpdateIcon( + Modifier .padding(bottom = 9.dp) - .size(72.dp)) + .size(72.dp) + ) Text("Update available", style = MaterialTheme.typography.headlineSmall) - Text("Install the latest version of MyRoboJackets for the latest features and " + + Text( + "Install the latest version of MyRoboJackets for the latest features and " + "bug fixes. It'll only take a minute.", textAlign = TextAlign.Center, modifier = Modifier.padding(20.dp) @@ -139,7 +149,8 @@ fun UpdateInProgress() { ) { CircularProgressIndicator(Modifier.padding(bottom = 28.dp)) Text("Please wait...", style = MaterialTheme.typography.headlineSmall) - Text("We're finishing installing an update. It'll just be a minute or two!", + Text( + "We're finishing installing an update. It'll just be a minute or two!", textAlign = TextAlign.Center, modifier = Modifier.padding(20.dp) ) diff --git a/app/src/main/java/org/robojackets/apiary/ui/update/UpdateGate.kt b/app/src/main/java/org/robojackets/apiary/ui/update/UpdateGate.kt index 2a7cbec..168005b 100644 --- a/app/src/main/java/org/robojackets/apiary/ui/update/UpdateGate.kt +++ b/app/src/main/java/org/robojackets/apiary/ui/update/UpdateGate.kt @@ -80,7 +80,8 @@ fun UpdateGate( Lifecycle.Event.ON_RESUME -> { if (result is AppUpdateResult.Available) { if (result.updateInfo.updateAvailability() - == UpdateAvailability.DEVELOPER_TRIGGERED_UPDATE_IN_PROGRESS) { + == UpdateAvailability.DEVELOPER_TRIGGERED_UPDATE_IN_PROGRESS + ) { context.getActivity() ?.let { result.startImmediateUpdate(it, UPDATE_REQUEST_CODE) } } @@ -160,10 +161,14 @@ fun UpdateStatus() { isImmediateUpdateOptional(priority, staleness) when { - immediateRequired -> Text("Required update available (priority: " + - "$priority, staleness: $staleness)") - immediateOptional -> Text("Optional update available (priority: " + - "$priority, staleness: $staleness)") + immediateRequired -> Text( + "Required update available (priority: " + + "$priority, staleness: $staleness)" + ) + immediateOptional -> Text( + "Optional update available (priority: " + + "$priority, staleness: $staleness)" + ) else -> Text("Available") } } diff --git a/attendance/src/main/java/org/robojackets/apiary/attendance/model/AttendableTypeSelectionViewModel.kt b/attendance/src/main/java/org/robojackets/apiary/attendance/model/AttendableTypeSelectionViewModel.kt index 844e487..a87359d 100644 --- a/attendance/src/main/java/org/robojackets/apiary/attendance/model/AttendableTypeSelectionViewModel.kt +++ b/attendance/src/main/java/org/robojackets/apiary/attendance/model/AttendableTypeSelectionViewModel.kt @@ -3,7 +3,11 @@ package org.robojackets.apiary.attendance.model import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import com.skydoves.sandwich.* +import com.skydoves.sandwich.StatusCode +import com.skydoves.sandwich.message +import com.skydoves.sandwich.onError +import com.skydoves.sandwich.onException +import com.skydoves.sandwich.onSuccess import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow @@ -88,7 +92,8 @@ class AttendableTypeSelectionViewModel @Inject constructor( "A server error occurred while checking if you have permission to " + "use this feature. Check your internet connection and try " + "again, or ask in #it-helpdesk for assistance." - else -> "An error occurred while checking if you have permission to use " + + else -> + "An error occurred while checking if you have permission to use " + "this feature. Check your internet connection and try again, or " + "ask in #it-helpdesk for assistance." } diff --git a/attendance/src/main/java/org/robojackets/apiary/attendance/model/AttendanceViewModel.kt b/attendance/src/main/java/org/robojackets/apiary/attendance/model/AttendanceViewModel.kt index f180a1a..24a10e7 100644 --- a/attendance/src/main/java/org/robojackets/apiary/attendance/model/AttendanceViewModel.kt +++ b/attendance/src/main/java/org/robojackets/apiary/attendance/model/AttendanceViewModel.kt @@ -50,7 +50,8 @@ class AttendanceViewModel @Inject constructor( init { viewModelScope.launch { - combine(listOf( + combine( + listOf( lastAttendee, screenState, totalAttendees, @@ -61,8 +62,10 @@ class AttendanceViewModel @Inject constructor( selectedAttendable, error, missingHiddenTeams - )) { - flows -> AttendanceState( + ) + ) { + flows -> + AttendanceState( flows[0] as AttendanceStoreResult?, flows[1] as AttendanceScreenState, flows[2] as Int, @@ -125,7 +128,8 @@ class AttendanceViewModel @Inject constructor( loadingAttendables.value = true viewModelScope.launch { if (attendableType == AttendableType.Team && - (attendableTeams.value.isEmpty() || forceRefresh)) { + (attendableTeams.value.isEmpty() || forceRefresh) + ) { meetingsRepository.getTeams().onSuccess { attendableTeams.value = this.data.teams .filter { it.attendable } @@ -141,7 +145,8 @@ class AttendanceViewModel @Inject constructor( } } if (attendableType == AttendableType.Event && - (attendableEvents.value.isEmpty() || forceRefresh)) { + (attendableEvents.value.isEmpty() || forceRefresh) + ) { meetingsRepository.getEvents().onSuccess { attendableEvents.value = this.data.events }.onError { diff --git a/attendance/src/main/java/org/robojackets/apiary/attendance/ui/AttendableTypeSelectionScreen.kt b/attendance/src/main/java/org/robojackets/apiary/attendance/ui/AttendableTypeSelectionScreen.kt index 5f475cc..0a644e6 100644 --- a/attendance/src/main/java/org/robojackets/apiary/attendance/ui/AttendableTypeSelectionScreen.kt +++ b/attendance/src/main/java/org/robojackets/apiary/attendance/ui/AttendableTypeSelectionScreen.kt @@ -26,6 +26,7 @@ import org.robojackets.apiary.base.ui.icons.GroupsIcon import org.robojackets.apiary.base.ui.util.ContentPadding import org.robojackets.apiary.base.ui.util.LoadingSpinner +@Suppress("LongMethod") @Composable fun AttendableTypeSelectionScreen( viewModel: AttendableTypeSelectionViewModel, @@ -45,7 +46,8 @@ fun AttendableTypeSelectionScreen( if (state.permissionsCheckError?.isNotEmpty() == true) { ErrorMessageWithRetry( message = state.permissionsCheckError ?: "An unknown error occurred", - onRetry = { viewModel.checkUserAttendanceAccess(forceRefresh = true) }) + onRetry = { viewModel.checkUserAttendanceAccess(forceRefresh = true) } + ) return@ContentPadding } @@ -64,7 +66,8 @@ fun AttendableTypeSelectionScreen( Column( Modifier .fillMaxWidth() - .fillMaxHeight()) { + .fillMaxHeight() + ) { Text("What do you want to take attendance for?", style = MaterialTheme.typography.headlineSmall) Spacer(Modifier.defaultMinSize(minHeight = 16.dp)) Divider() diff --git a/auth/src/main/java/org/robojackets/apiary/auth/ui/Authentication.kt b/auth/src/main/java/org/robojackets/apiary/auth/ui/Authentication.kt index f785a01..ed8c943 100644 --- a/auth/src/main/java/org/robojackets/apiary/auth/ui/Authentication.kt +++ b/auth/src/main/java/org/robojackets/apiary/auth/ui/Authentication.kt @@ -15,7 +15,6 @@ import androidx.compose.material3.ModalBottomSheet import androidx.compose.material3.RadioButton import androidx.compose.material3.Text import androidx.compose.material3.TextButton -import androidx.compose.material3.rememberBottomSheetScaffoldState import androidx.compose.material3.rememberModalBottomSheetState import androidx.compose.runtime.* import androidx.compose.ui.Alignment @@ -43,9 +42,6 @@ private fun Authentication( onAppEnvChange: (newEnv: AppEnvironment) -> Unit, viewModel: AuthenticationViewModel, ) { - val scaffoldState = rememberBottomSheetScaffoldState() - val coroutineScope = rememberCoroutineScope() - val systemUiController = rememberSystemUiController() val backgroundColor = MaterialTheme.colorScheme.background SideEffect { @@ -99,7 +95,6 @@ private fun Authentication( var showChangeEnvBottomSheet by remember { mutableStateOf(false) } - if (showChangeEnvBottomSheet) { ChangeEnvBottomSheet( onDismiss = { showChangeEnvBottomSheet = false }, @@ -211,7 +206,6 @@ private fun ChangeEnvironmentBottomSheetContent( viewState: AuthenticationState, onAppEnvChange: (newEnv: AppEnvironment) -> Unit, ) { - val coroutineScope = rememberCoroutineScope() var unsavedAppEnvSelection by remember { mutableStateOf(viewState.appEnv) } val appEnvChoices = AppEnvironment.values() val saveNewAppEnvChoice: (() -> Unit) = { diff --git a/auth/src/main/java/org/robojackets/apiary/auth/ui/permissions/MissingHiddenTeamsCallout.kt b/auth/src/main/java/org/robojackets/apiary/auth/ui/permissions/MissingHiddenTeamsCallout.kt index ffbe887..f8f8240 100644 --- a/auth/src/main/java/org/robojackets/apiary/auth/ui/permissions/MissingHiddenTeamsCallout.kt +++ b/auth/src/main/java/org/robojackets/apiary/auth/ui/permissions/MissingHiddenTeamsCallout.kt @@ -17,8 +17,10 @@ fun MissingHiddenTeamsCallout(onRefreshTeams: () -> Unit) { padding = PaddingValues(start = 12.dp, top = 10.dp, end = 12.dp, bottom = 7.dp) ) { Column { - Text("You don't have permission to view all teams, including " + - "training teams. Ask in #it-helpdesk for access.") + Text( + "You don't have permission to view all teams, including " + + "training teams. Ask in #it-helpdesk for access." + ) OutlinedButton(onClick = onRefreshTeams, Modifier.padding(top = 0.dp)) { Text("Refresh teams") } diff --git a/base/src/main/java/org/robojackets/apiary/base/ui/ActionPrompt.kt b/base/src/main/java/org/robojackets/apiary/base/ui/ActionPrompt.kt index 7d48683..ccab524 100644 --- a/base/src/main/java/org/robojackets/apiary/base/ui/ActionPrompt.kt +++ b/base/src/main/java/org/robojackets/apiary/base/ui/ActionPrompt.kt @@ -78,7 +78,9 @@ fun ActionPromptCardReadErrorWrongType() { title = "Card read error", subtitle = "Try tapping again" ) { - IconWithText(icon = { WarningIcon(tint = danger) }, - text = "We only support BuzzCards 😉") + IconWithText( + icon = { WarningIcon(tint = danger) }, + text = "We only support BuzzCards 😉" + ) } } diff --git a/base/src/main/java/org/robojackets/apiary/base/ui/callout/Callout.kt b/base/src/main/java/org/robojackets/apiary/base/ui/callout/Callout.kt index 0b3c333..433d3fe 100644 --- a/base/src/main/java/org/robojackets/apiary/base/ui/callout/Callout.kt +++ b/base/src/main/java/org/robojackets/apiary/base/ui/callout/Callout.kt @@ -79,7 +79,9 @@ private fun WarningCalloutPreview() { WarningCallout( titleText = "Some teams are hidden", ) { - Text("Your account doesn't have permission to view all teams, including training " + - "teams. Ask in #it-helpdesk for access.") + Text( + "Your account doesn't have permission to view all teams, including training " + + "teams. Ask in #it-helpdesk for access." + ) } } diff --git a/base/src/main/java/org/robojackets/apiary/base/ui/nfc/NfcRequired.kt b/base/src/main/java/org/robojackets/apiary/base/ui/nfc/NfcRequired.kt index c1f2a36..1653d76 100644 --- a/base/src/main/java/org/robojackets/apiary/base/ui/nfc/NfcRequired.kt +++ b/base/src/main/java/org/robojackets/apiary/base/ui/nfc/NfcRequired.kt @@ -33,7 +33,8 @@ fun NfcRequired(nfcEnabled: Boolean, gatedComposable: @Composable () -> Unit) { if (nfcEnabled) { gatedComposable() } else { - Column(Modifier.fillMaxHeight(), + Column( + Modifier.fillMaxHeight(), verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally ) { diff --git a/buildSrc/src/main/java/Dependencies.kt b/buildSrc/src/main/java/Dependencies.kt index 2426b55..251d753 100644 --- a/buildSrc/src/main/java/Dependencies.kt +++ b/buildSrc/src/main/java/Dependencies.kt @@ -35,8 +35,6 @@ object ComposeDependencies { const val lifecycle_viewmodel_compose = "androidx.lifecycle:lifecycle-viewmodel-compose:${Versions.lifecycle_viewmodel_compose_version}" - - } object MaterialDependencies { From eb537cdd9bb4f8ff189f5b6a45a3a7611003d538 Mon Sep 17 00:00:00 2001 From: Evan Strat <evan10s@users.noreply.github.com> Date: Wed, 19 Jun 2024 23:54:56 -0400 Subject: [PATCH 13/33] Use Java 17 --- .github/workflows/build.yml | 2 +- .github/workflows/internal-test-release.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c8a15b8..cb7f0fc 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -24,7 +24,7 @@ jobs: - name: Set up JDK uses: actions/setup-java@v4 with: - java-version: '11' + java-version: '17' distribution: 'corretto' cache: gradle diff --git a/.github/workflows/internal-test-release.yml b/.github/workflows/internal-test-release.yml index 0f45d34..e449cb4 100644 --- a/.github/workflows/internal-test-release.yml +++ b/.github/workflows/internal-test-release.yml @@ -23,7 +23,7 @@ jobs: - name: Set up JDK uses: actions/setup-java@v4 with: - java-version: '11' + java-version: '17' distribution: 'corretto' cache: gradle From 59b9e9636e368a6094a17fecbd82f923a7db4119 Mon Sep 17 00:00:00 2001 From: Evan Strat <evan10s@users.noreply.github.com> Date: Wed, 19 Jun 2024 23:55:15 -0400 Subject: [PATCH 14/33] Update dependencies and finish M3 upgrade --- Gemfile.lock | 16 +-- README.md | 2 +- app/build.gradle.kts | 6 +- .../org/robojackets/apiary/MainActivity.kt | 15 ++- attendance/build.gradle.kts | 4 +- auth/build.gradle.kts | 4 +- base/build.gradle.kts | 4 +- .../robojackets/apiary/base/ui/theme/Color.kt | 75 +++++++++++ .../robojackets/apiary/base/ui/theme/Theme.kt | 118 +++++++++++++++--- build.gradle.kts | 12 +- buildSrc/src/main/java/Dependencies.kt | 49 ++++---- gradle.properties | 1 - gradle/wrapper/gradle-wrapper.properties | 2 +- navigation/build.gradle.kts | 4 +- 14 files changed, 239 insertions(+), 73 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 89deb36..158cf10 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -207,18 +207,4 @@ GEM nanaimo (~> 0.3.0) rexml (~> 3.2.4) xcpretty (0.3.0) - rouge (~> 2.0.7) - xcpretty-travis-formatter (1.0.1) - xcpretty (~> 0.2, >= 0.0.7) - -PLATFORMS - x64-mingw32 - x86_64-linux - -DEPENDENCIES - dotenv (~> 2.7) - fastlane - fastlane-plugin-sentry - -BUNDLED WITH - 2.3.1 + rouge (~> 2 \ No newline at end of file diff --git a/README.md b/README.md index e87b90c..6285b40 100644 --- a/README.md +++ b/README.md @@ -101,7 +101,7 @@ command does, so you can get around any errors stemming from this by aliasing th to `which`. - You need to install [GitVersion](https://github.com/GitTools/GitVersion) yourself. -## Release management +## Release management Below are some instructions on the MyRoboJackets Android release process. Note that you will need additional permissions on this repo and the MyRoboJackets Android Google Play application to diff --git a/app/build.gradle.kts b/app/build.gradle.kts index fbf6dad..59ab7e2 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -44,6 +44,7 @@ dependencies { implementation(HiltDependencies.hilt) kapt(HiltDependencies.hilt_android_compiler) + implementation(HiltDependencies.dagger_producer) implementation(HiltDependencies.hilt_navigation_compose) implementation(NetworkDependencies.moshi_converter_factory) @@ -71,11 +72,11 @@ android { create("release") { } } - compileSdk = 33 + compileSdk = 35 defaultConfig { applicationId = "org.robojackets.apiary" minSdk = 21 - targetSdk = 33 + targetSdk = 35 versionCode = 12 versionName = "1.0.0" vectorDrawables { @@ -90,6 +91,7 @@ android { } buildFeatures { compose = true + buildConfig = true } compileOptions { sourceCompatibility = JavaVersion.VERSION_17 diff --git a/app/src/main/java/org/robojackets/apiary/MainActivity.kt b/app/src/main/java/org/robojackets/apiary/MainActivity.kt index 0f926ec..17b05e8 100644 --- a/app/src/main/java/org/robojackets/apiary/MainActivity.kt +++ b/app/src/main/java/org/robojackets/apiary/MainActivity.kt @@ -18,19 +18,28 @@ import androidx.compose.material3.NavigationBarItem import androidx.compose.material3.Scaffold import androidx.compose.material3.Surface import androidx.compose.material3.Text -import androidx.compose.runtime.* +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.toArgb import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.res.stringResource import androidx.hilt.navigation.compose.hiltViewModel -import androidx.navigation.* import androidx.navigation.NavDestination.Companion.hierarchy import androidx.navigation.NavGraph.Companion.findStartDestination +import androidx.navigation.NavHostController +import androidx.navigation.NavType import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable import androidx.navigation.compose.currentBackStackEntryAsState import androidx.navigation.compose.rememberNavController +import androidx.navigation.navArgument +import androidx.navigation.navigation +import androidx.navigation.plusAssign import com.google.accompanist.navigation.material.ExperimentalMaterialNavigationApi import com.google.accompanist.navigation.material.ModalBottomSheetLayout import com.google.accompanist.navigation.material.bottomSheet @@ -144,7 +153,7 @@ class MainActivity : ComponentActivity() { setContent { Apiary_MobileTheme { - window.statusBarColor = MaterialTheme.colorScheme.secondary.toArgb() + window.statusBarColor = MaterialTheme.colorScheme.secondary.toArgb() // FIXME: deprecated val navController = rememberNavController() val bottomSheetNavigator = rememberBottomSheetNavigator() navController.navigatorProvider += bottomSheetNavigator diff --git a/attendance/build.gradle.kts b/attendance/build.gradle.kts index 878df10..d01cde1 100644 --- a/attendance/build.gradle.kts +++ b/attendance/build.gradle.kts @@ -25,6 +25,7 @@ dependencies { implementation(HiltDependencies.hilt) kapt(HiltDependencies.hilt_android_compiler) + implementation(HiltDependencies.dagger_producer) implementation(NetworkDependencies.moshi) ksp(NetworkDependencies.moshi_kotlin_codegen) @@ -45,7 +46,7 @@ dependencies { } android { - compileSdk = 33 + compileSdk = 35 defaultConfig { minSdk = 21 vectorDrawables { @@ -59,6 +60,7 @@ android { } buildFeatures { compose = true + buildConfig = true } compileOptions { sourceCompatibility = JavaVersion.VERSION_17 diff --git a/auth/build.gradle.kts b/auth/build.gradle.kts index 785301f..a222271 100644 --- a/auth/build.gradle.kts +++ b/auth/build.gradle.kts @@ -35,6 +35,7 @@ dependencies { implementation(HiltDependencies.hilt) kapt(HiltDependencies.hilt_android_compiler) + implementation(HiltDependencies.dagger_producer) implementation(MaterialDependencies.material_android) @@ -53,7 +54,7 @@ dependencies { } android { - compileSdk = 33 + compileSdk = 35 defaultConfig { minSdk = 21 @@ -69,6 +70,7 @@ android { } buildFeatures { compose = true + buildConfig = true } compileOptions { sourceCompatibility = JavaVersion.VERSION_17 diff --git a/base/build.gradle.kts b/base/build.gradle.kts index 1373472..4a268f2 100644 --- a/base/build.gradle.kts +++ b/base/build.gradle.kts @@ -27,6 +27,7 @@ dependencies { implementation(HiltDependencies.hilt) kapt(HiltDependencies.hilt_android_compiler) + implementation(HiltDependencies.dagger_producer) implementation(NetworkDependencies.moshi) ksp(NetworkDependencies.moshi_kotlin_codegen) @@ -47,7 +48,7 @@ hilt { } android { - compileSdk = 33 + compileSdk = 35 defaultConfig { minSdk = 21 @@ -62,6 +63,7 @@ android { } buildFeatures { compose = true + buildConfig = true } compileOptions { sourceCompatibility = JavaVersion.VERSION_17 diff --git a/base/src/main/java/org/robojackets/apiary/base/ui/theme/Color.kt b/base/src/main/java/org/robojackets/apiary/base/ui/theme/Color.kt index 19bfdb7..83b55a0 100644 --- a/base/src/main/java/org/robojackets/apiary/base/ui/theme/Color.kt +++ b/base/src/main/java/org/robojackets/apiary/base/ui/theme/Color.kt @@ -7,6 +7,8 @@ val Gold = Color(0xFFEEB211) val GoldLight = Color(0xFFFFE450) val GoldDark = Color(0xFFB78300) +val neutral = Color(0xFF949088) + val danger = Color(0xFFB00020) // Color inspiration from GitHub Primer CSS: https://primer.style/css/ @@ -26,3 +28,76 @@ val warningDarkMuted = Color(0x66BB8009) // outline val success = Color(0xFF4CAF50) val webNavBarBackground = Color(0xFF343A40) + +// Imported from Material theme generator +val primaryLight = Color(0xFFEEB211) // Gold +val onPrimaryLight = Color(0xFF000000) +val primaryContainerLight = Color(0xFFF7BA1E) +val onPrimaryContainerLight = Color(0xFF453100) +val secondaryLight = Color(0xFFB78300) +val onSecondaryLight = Color(0xFFFFFFFF) +val secondaryContainerLight = Color(0xFFFFE0A6) +val onSecondaryContainerLight = Color(0xFF5C450F) +val tertiaryLight = Color(0xFF526600) +val onTertiaryLight = Color(0xFFFFFFFF) +val tertiaryContainerLight = Color(0xFFB3D04F) +val onTertiaryContainerLight = Color(0xFF2D3900) +val errorLight = Color(0xFFBA1A1A) +val onErrorLight = Color(0xFFFFFFFF) +val errorContainerLight = Color(0xFFFFDAD6) +val onErrorContainerLight = Color(0xFF410002) +val backgroundLight = Color(0xFFFFF8F2) +val onBackgroundLight = Color(0xFF201B11) +val surfaceLight = Color(0xFFFFF8F2) +val onSurfaceLight = Color(0xFF201B11) +val surfaceVariantLight = Color(0xFFF0E0C7) +val onSurfaceVariantLight = Color(0xFF504533) +val outlineLight = Color(0xFF827661) +val outlineVariantLight = Color(0xFFD4C5AC) +val scrimLight = Color(0xFF000000) +val inverseSurfaceLight = Color(0xFF363025) +val inverseOnSurfaceLight = Color(0xFFFBEFDF) +val inversePrimaryLight = Color(0xFFFABD22) +val surfaceDimLight = Color(0xFFE4D8C9) +val surfaceBrightLight = Color(0xFFFFF8F2) +val surfaceContainerLowestLight = Color(0xFFFFFFFF) +val surfaceContainerLowLight = Color(0xFFFEF2E2) +val surfaceContainerLight = Color(0xFFF8ECDC) +val surfaceContainerHighLight = Color(0xFFF2E7D7) +val surfaceContainerHighestLight = Color(0xFFECE1D1) + +val primaryDark = Color(0xFFFFDB95) +val onPrimaryDark = Color(0xFF402D00) +val primaryContainerDark = Color(0xFFE7AC03) +val onPrimaryContainerDark = Color(0xFF382700) +val secondaryDark = Color(0xFFE4C281) +val onSecondaryDark = Color(0xFF402D00) +val secondaryContainerDark = Color(0xFF4F3904) +val onSecondaryContainerDark = Color(0xFFEECC89) +val tertiaryDark = Color(0xFFCDEC67) +val onTertiaryDark = Color(0xFF293500) +val tertiaryContainerDark = Color(0xFFA4C142) +val onTertiaryContainerDark = Color(0xFF232D00) +val errorDark = Color(0xFFFFB4AB) +val onErrorDark = Color(0xFF690005) +val errorContainerDark = Color(0xFF93000A) +val onErrorContainerDark = Color(0xFFFFDAD6) +val backgroundDark = Color(0xFF17130A) +val onBackgroundDark = Color(0xFFECE1D1) +val surfaceDark = Color(0xFF17130A) +val onSurfaceDark = Color(0xFFECE1D1) +val surfaceVariantDark = Color(0xFF504533) +val onSurfaceVariantDark = Color(0xFFD4C5AC) +val outlineDark = Color(0xFF9C8F79) +val outlineVariantDark = Color(0xFF504533) +val scrimDark = Color(0xFF000000) +val inverseSurfaceDark = Color(0xFFECE1D1) +val inverseOnSurfaceDark = Color(0xFF363025) +val inversePrimaryDark = Color(0xFF7A5900) +val surfaceDimDark = Color(0xFF17130A) +val surfaceBrightDark = Color(0xFF3F382D) +val surfaceContainerLowestDark = Color(0xFF120E06) +val surfaceContainerLowDark = Color(0xFF201B11) +val surfaceContainerDark = Color(0xFF241F15) +val surfaceContainerHighDark = Color(0xFF2F291F) +val surfaceContainerHighestDark = Color(0xFF3A3429) \ No newline at end of file diff --git a/base/src/main/java/org/robojackets/apiary/base/ui/theme/Theme.kt b/base/src/main/java/org/robojackets/apiary/base/ui/theme/Theme.kt index deb2e15..ca745e2 100644 --- a/base/src/main/java/org/robojackets/apiary/base/ui/theme/Theme.kt +++ b/base/src/main/java/org/robojackets/apiary/base/ui/theme/Theme.kt @@ -1,38 +1,124 @@ package org.robojackets.apiary.base.ui.theme +import android.app.Activity +import android.os.Build 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.ui.graphics.Color +import androidx.compose.runtime.SideEffect +import androidx.compose.ui.graphics.toArgb +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.platform.LocalView +import androidx.core.view.WindowCompat -val LightColorScheme = lightColorScheme( - primary = Gold, - secondary = GoldDark, - tertiary = Color.Black, +private val lightScheme = lightColorScheme( + primary = primaryLight, + onPrimary = onPrimaryLight, + primaryContainer = primaryContainerLight, + onPrimaryContainer = onPrimaryContainerLight, + secondary = secondaryLight, + onSecondary = onSecondaryLight, + secondaryContainer = secondaryContainerLight, + onSecondaryContainer = onSecondaryContainerLight, + tertiary = tertiaryLight, + onTertiary = onTertiaryLight, + tertiaryContainer = tertiaryContainerLight, + onTertiaryContainer = onTertiaryContainerLight, + error = errorLight, + onError = onErrorLight, + errorContainer = errorContainerLight, + onErrorContainer = onErrorContainerLight, + background = backgroundLight, + onBackground = onBackgroundLight, + surface = surfaceLight, + onSurface = onSurfaceLight, + surfaceVariant = surfaceVariantLight, + onSurfaceVariant = onSurfaceVariantLight, + outline = outlineLight, + outlineVariant = outlineVariantLight, + scrim = scrimLight, + inverseSurface = inverseSurfaceLight, + inverseOnSurface = inverseOnSurfaceLight, + inversePrimary = inversePrimaryLight, + surfaceDim = surfaceDimLight, + surfaceBright = surfaceBrightLight, + surfaceContainerLowest = surfaceContainerLowestLight, + surfaceContainerLow = surfaceContainerLowLight, + surfaceContainer = surfaceContainerLight, + surfaceContainerHigh = surfaceContainerHighLight, + surfaceContainerHighest = surfaceContainerHighestLight, ) -val DarkColorScheme = darkColorScheme( - primary = Gold, - secondary = GoldDark, - tertiary = Color.White, + +private val darkScheme = darkColorScheme( + primary = primaryDark, + onPrimary = onPrimaryDark, + primaryContainer = primaryContainerDark, + onPrimaryContainer = onPrimaryContainerDark, + secondary = secondaryDark, + onSecondary = onSecondaryDark, + secondaryContainer = secondaryContainerDark, + onSecondaryContainer = onSecondaryContainerDark, + tertiary = tertiaryDark, + onTertiary = onTertiaryDark, + tertiaryContainer = tertiaryContainerDark, + onTertiaryContainer = onTertiaryContainerDark, + error = errorDark, + onError = onErrorDark, + errorContainer = errorContainerDark, + onErrorContainer = onErrorContainerDark, + background = backgroundDark, + onBackground = onBackgroundDark, + surface = surfaceDark, + onSurface = onSurfaceDark, + surfaceVariant = surfaceVariantDark, + onSurfaceVariant = onSurfaceVariantDark, + outline = outlineDark, + outlineVariant = outlineVariantDark, + scrim = scrimDark, + inverseSurface = inverseSurfaceDark, + inverseOnSurface = inverseOnSurfaceDark, + inversePrimary = inversePrimaryDark, + surfaceDim = surfaceDimDark, + surfaceBright = surfaceBrightDark, + surfaceContainerLowest = surfaceContainerLowestDark, + surfaceContainerLow = surfaceContainerLowDark, + surfaceContainer = surfaceContainerDark, + surfaceContainerHigh = surfaceContainerHighDark, + surfaceContainerHighest = surfaceContainerHighestDark, ) @Composable fun Apiary_MobileTheme( darkTheme: Boolean = isSystemInDarkTheme(), + // Dynamic color is available on Android 12+ + dynamicColor: Boolean = false, content: @Composable() () -> Unit ) { - val colors = if (darkTheme) { - DarkColorScheme - } else { - LightColorScheme + val colorScheme = when { + dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> { + val context = LocalContext.current + if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context) + } + + darkTheme -> darkScheme + else -> lightScheme + } + val view = LocalView.current + if (!view.isInEditMode) { + SideEffect { + val window = (view.context as Activity).window + window.statusBarColor = colorScheme.primary.toArgb() // FIXME + WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars = darkTheme + } } MaterialTheme( - colorScheme = colors, + colorScheme = colorScheme, typography = Typography, - shapes = Shapes, content = content ) -} +} \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index 8d61bf1..c7dc063 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,15 +1,15 @@ buildscript { repositories { - gradlePluginPortal() google() + gradlePluginPortal() mavenCentral() } dependencies { classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.0") - classpath("com.android.tools.build:gradle:8.1.0") + classpath("com.android.tools.build:gradle:8.5.0") classpath("com.google.dagger:hilt-android-gradle-plugin:2.46.1") classpath("com.google.android.libraries.mapsplatform.secrets-gradle-plugin:secrets-gradle-plugin:2.0.1") - classpath("com.google.gms:google-services:4.3.15") + classpath("com.google.gms:google-services:4.4.2") classpath("com.google.android.gms:oss-licenses-plugin:0.10.6") } } @@ -65,9 +65,9 @@ tasks.register("detektAll", io.gitlab.arturbosch.detekt.Detekt::class) { include(kotlinFiles) exclude(resourceFiles, buildFiles) reports { - html.enabled = true - xml.enabled = false - txt.enabled = false + html.required.set(true) + xml.required.set(false) + txt.required.set(false) } } diff --git a/buildSrc/src/main/java/Dependencies.kt b/buildSrc/src/main/java/Dependencies.kt index 251d753..c52eaf3 100644 --- a/buildSrc/src/main/java/Dependencies.kt +++ b/buildSrc/src/main/java/Dependencies.kt @@ -1,10 +1,10 @@ object ComposeDependencies { object Versions { - const val accompanist_version = "0.30.1" - const val compose_settings_version = "0.27.0" - const val compose_version = "1.4.3" - const val lifecycle_viewmodel_compose_version = "2.6.1" - const val compose_material3_version = "1.1.1" + const val accompanist_version = "0.34.0" + const val compose_settings_version = "2.4.0" + const val compose_version = "1.6.8" + const val lifecycle_viewmodel_compose_version = "2.8.2" + const val compose_material3_version = "1.2.1" } const val accompanist_systemuicontroller = @@ -27,7 +27,7 @@ object ComposeDependencies { "androidx.compose.runtime:runtime-livedata:${Versions.compose_version}" const val compose_settings = - "com.github.alorma:compose-settings-ui-m3:${Versions.compose_settings_version}" + "com.github.alorma.compose-settings:ui-tiles:${Versions.compose_settings_version}" const val compose_ui = "androidx.compose.ui:ui:${Versions.compose_version}" const val compose_ui_test = "androidx.compose.ui:ui-test-junit4:${Versions.compose_version}" @@ -39,7 +39,7 @@ object ComposeDependencies { object MaterialDependencies { object Versions { - const val material_android_version = "1.9.0" + const val material_android_version = "1.12.0" } const val material_android = @@ -48,11 +48,11 @@ object MaterialDependencies { object AndroidXDependencies { object Versions { - const val androidx_activity_compose_version = "1.7.2" - const val androidx_appcompat_version = "1.6.1" - const val androidx_browser_version = "1.5.0" - const val androidx_lifecycle_runtime_ktx_version = "2.6.1" - const val androidx_navigation_compose_version = "2.5.3" + const val androidx_activity_compose_version = "1.9.0" + const val androidx_appcompat_version = "1.7.0" + const val androidx_browser_version = "1.8.0" + const val androidx_lifecycle_runtime_ktx_version = "2.8.2" + const val androidx_navigation_compose_version = "2.7.7" } const val androidx_activity_compose = @@ -68,7 +68,7 @@ object AndroidXDependencies { object FirebaseDependencies { object Versions { - const val firebase_bom_version = "32.0.0" + const val firebase_bom_version = "33.1.0" } const val firebase_bom = "com.google.firebase:firebase-bom:${Versions.firebase_bom_version}" @@ -91,25 +91,26 @@ object AuthDependencies { object HiltDependencies { object Versions { - const val hilt_navigation_compose_version = "1.0.0" + const val hilt_navigation_compose_version = "1.2.0" const val hilt_version = "2.46.1" } const val hilt = "com.google.dagger:hilt-android:${Versions.hilt_version}" const val hilt_android_compiler = "com.google.dagger:hilt-android-compiler:${Versions.hilt_version}" + const val dagger_producer = "com.google.dagger:dagger-producers:${Versions.hilt_version}" const val hilt_navigation_compose = "androidx.hilt:hilt-navigation-compose:${Versions.hilt_navigation_compose_version}" } object AndroidToolDependencies { object Versions { - const val android_tools_desugar_version = "1.1.5" + const val android_tools_desugar_version = "2.0.4" const val krate_version = "2.0.0" - const val gson_version = "2.10.1" - const val in_app_update_compose_version = "0.0.17" - const val open_source_licenses_version = "17.0.1" - const val sentry_version = "6.28.0" + const val gson_version = "2.11.0" + const val in_app_update_compose_version = "0.0.17" // TODO: Update to newer version with breaking changes + const val open_source_licenses_version = "17.1.0" + const val sentry_version = "7.10.0" const val timber_version = "5.0.1" } @@ -128,12 +129,12 @@ object AndroidToolDependencies { object NetworkDependencies { object Versions { - const val moshi_version = "1.15.0" - const val moshi_converter_factory_version = "2.9.0" - const val okhttp_bom_version = "4.11.0" - const val retrofit_version = "2.9.0" + const val moshi_version = "1.15.1" + const val moshi_converter_factory_version = "2.11.0" + const val okhttp_bom_version = "4.12.0" + const val retrofit_version = "2.11.0" const val retrofuture_version = "1.7.4" - const val sandwich_version = "1.3.8" + const val sandwich_version = "1.3.9" // TODO: Upgrade to v2 } const val moshi = "com.squareup.moshi:moshi:${Versions.moshi_version}" diff --git a/gradle.properties b/gradle.properties index 20edcb1..896ce41 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,6 +6,5 @@ kotlin.code.style=official #Android android.useAndroidX=true -android.defaults.buildfeatures.buildconfig=true android.nonTransitiveRClass=true android.nonFinalResIds=true \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 142d4cd..e49c70f 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ #Wed Dec 15 17:03:27 EST 2021 distributionBase=GRADLE_USER_HOME -distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-all.zip distributionPath=wrapper/dists zipStorePath=wrapper/dists zipStoreBase=GRADLE_USER_HOME diff --git a/navigation/build.gradle.kts b/navigation/build.gradle.kts index 716c8a1..30da45e 100644 --- a/navigation/build.gradle.kts +++ b/navigation/build.gradle.kts @@ -24,6 +24,7 @@ dependencies { implementation(HiltDependencies.hilt) kapt(HiltDependencies.hilt_android_compiler) + implementation(HiltDependencies.dagger_producer) implementation(MaterialDependencies.material_android) @@ -32,7 +33,7 @@ dependencies { } android { - compileSdk = 33 + compileSdk = 35 defaultConfig { minSdk = 21 @@ -47,6 +48,7 @@ android { } buildFeatures { compose = true + buildConfig = true } compileOptions { isCoreLibraryDesugaringEnabled = true From f65fd28b58749ae5872b2b73ce6f4aa25bb80621 Mon Sep 17 00:00:00 2001 From: Evan Strat <evan10s@users.noreply.github.com> Date: Thu, 20 Jun 2024 22:44:57 -0400 Subject: [PATCH 15/33] Fix ruby lock file? --- Gemfile.lock | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 158cf10..89deb36 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -207,4 +207,18 @@ GEM nanaimo (~> 0.3.0) rexml (~> 3.2.4) xcpretty (0.3.0) - rouge (~> 2 \ No newline at end of file + rouge (~> 2.0.7) + xcpretty-travis-formatter (1.0.1) + xcpretty (~> 0.2, >= 0.0.7) + +PLATFORMS + x64-mingw32 + x86_64-linux + +DEPENDENCIES + dotenv (~> 2.7) + fastlane + fastlane-plugin-sentry + +BUNDLED WITH + 2.3.1 From e14cb27a86cb94dd8c9f8b00aa6421577b184dc5 Mon Sep 17 00:00:00 2001 From: Evan Strat <evan10s@users.noreply.github.com> Date: Sat, 22 Jun 2024 22:22:46 -0400 Subject: [PATCH 16/33] In-app update cleanup, update Hilt version, move from kapt to ksp --- README.md | 16 +- app/build.gradle.kts | 8 +- .../apiary/ui/update/UpdateAvailable.kt | 109 +++++--- .../apiary/ui/update/UpdateGate.kt | 237 ++++++++---------- attendance/build.gradle.kts | 6 +- auth/build.gradle.kts | 6 +- base/build.gradle.kts | 6 +- .../robojackets/apiary/base/ui/theme/Color.kt | 2 +- .../robojackets/apiary/base/ui/theme/Theme.kt | 2 +- build.gradle.kts | 5 +- buildSrc/src/main/java/Dependencies.kt | 7 +- navigation/build.gradle.kts | 6 +- 12 files changed, 212 insertions(+), 198 deletions(-) diff --git a/README.md b/README.md index 6285b40..5ac4b77 100644 --- a/README.md +++ b/README.md @@ -116,17 +116,17 @@ merged in close proximity. Our Concourse pipeline has jobs to automatically hand signing, and uploading production releases of the app. 1. After you've merged all PRs to be included in the release, ensure the `.update-priority` -file is set correctly according to the table below. Use priority 2 as the default. If you want to -use priority 4 or 5, post in #apiary-mobile first. +file is set correctly according to the table below. Use priority 1 as the default. If you want to +use priority 5, post in #apiary-mobile first. 1. Update priority affects if and how often users receive in-app update prompts to update the app to the latest version. +2. -| Update priority | Description | Examples | Update timeline for users | -| --- | --- |--- | --- | -| 0/1/2 | Very low or low priority | UI touchups that don't impact functionality, releases with options to opt-in to beta features | No prompt initially. Optional prompt starting 14 days after release. Immediate update 21 days after release. | -| 3 | Medium priority | Medium-priority bug fixes, performance improvements, non-time-sensitive feature launches | No prompts for the first 3 days. Optional starting 4 days after release. Immediate update 21 days after release. | -| 4 | High priority or time-sensitive | High priority bug fixes, time-sensitive feature launches | Optional for the first 24 hours, then immediate. | -| 5 | Critical bug fixes | Crashes/bugs impacting major features, urgent vulnerabilities | Immediate update required. | +| Update priority | Description | Examples | +|-----------------|-------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------| +| 1 | Optional update with prompts when the update is first available, then every 8 days. | UI touchups that don't impact functionality, releases with options to opt-in to beta features | +| 3 | Optional update with prompts when the update is first available, then every 4 days. | Medium-priority bug fixes, performance improvements, new features | +| 5 | Required update with immediate prompt and no option to decline. | Crashes/bugs impacting major features, urgent vulnerabilities | 2. Create a new release on `main` using a tag with a name like `v1.0.0`. Use semantic versioning to determine how to increment the version number. diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 59ab7e2..38a2646 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -2,7 +2,7 @@ plugins { id("com.android.application") kotlin("android") id("kotlin-android") - kotlin("kapt") +// kotlin("kapt") // FIXME: remove if unneeded id("com.google.devtools.ksp") id("dagger.hilt.android.plugin") id("com.google.android.libraries.mapsplatform.secrets-gradle-plugin") @@ -43,8 +43,8 @@ dependencies { implementation(ComposeDependencies.compose_settings) implementation(HiltDependencies.hilt) - kapt(HiltDependencies.hilt_android_compiler) - implementation(HiltDependencies.dagger_producer) + ksp(HiltDependencies.hilt_android_compiler) +// implementation(HiltDependencies.dagger_producer) // FIXME: remove if unneeded implementation(HiltDependencies.hilt_navigation_compose) implementation(NetworkDependencies.moshi_converter_factory) @@ -77,7 +77,7 @@ android { applicationId = "org.robojackets.apiary" minSdk = 21 targetSdk = 35 - versionCode = 12 + versionCode = 21 versionName = "1.0.0" vectorDrawables { useSupportLibrary = true diff --git a/app/src/main/java/org/robojackets/apiary/ui/update/UpdateAvailable.kt b/app/src/main/java/org/robojackets/apiary/ui/update/UpdateAvailable.kt index 1926b98..fbf2529 100644 --- a/app/src/main/java/org/robojackets/apiary/ui/update/UpdateAvailable.kt +++ b/app/src/main/java/org/robojackets/apiary/ui/update/UpdateAvailable.kt @@ -1,39 +1,48 @@ package org.robojackets.apiary.ui.update -import android.app.Activity -import androidx.compose.foundation.layout.* +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size import androidx.compose.material3.AlertDialog import androidx.compose.material3.Button import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.material3.TextButton -import androidx.compose.runtime.* +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import com.google.android.play.core.ktx.AppUpdateResult +import kotlinx.coroutines.launch import org.robojackets.apiary.base.ui.icons.UpdateIcon -import org.robojackets.apiary.base.ui.util.getActivity +import se.warting.inappupdate.compose.InAppUpdateState +import se.warting.inappupdate.compose.Mode import se.warting.inappupdate.compose.rememberInAppUpdateState import timber.log.Timber -// Just a random number so we can identify our update request later if necessary -const val UPDATE_REQUEST_CODE = 1999 - -fun triggerImmediateUpdate(appUpdateResult: AppUpdateResult.Available, activity: Activity) { - appUpdateResult.startImmediateUpdate(activity, UPDATE_REQUEST_CODE) -} - +@Suppress("LongMethod") @Composable fun InstallUpdateButton(onIgnoreUpdate: () -> Unit = {}) { - val updateState = rememberInAppUpdateState() + val inAppUpdateState = rememberInAppUpdateState( + highPrioritizeUpdates = 5, + mediumPrioritizeUpdates = 3, + promptIntervalHighPrioritizeUpdateInDays = 1, + promptIntervalMediumPrioritizeUpdateInDays = 4, + promptIntervalLowPrioritizeUpdateInDays = 8, + ) var updateCanceled by remember { mutableStateOf(false) } - val context = LocalContext.current + val scope = rememberCoroutineScope() var updateError by remember { mutableStateOf<String?>(null) } when (updateCanceled) { @@ -42,19 +51,45 @@ fun InstallUpdateButton(onIgnoreUpdate: () -> Unit = {}) { } false -> { Button(onClick = { - val result = updateState.appUpdateResult - if (result is AppUpdateResult.Available) { - context.getActivity()?.let { triggerImmediateUpdate(result, it) } ?: run { - Timber.e("Context.getActivity() was null while trying to start immediate update") - updateError = "An update is available, but we were unable to start the update process." + when (inAppUpdateState) { + is InAppUpdateState.DownloadedUpdate -> { + scope.launch { + inAppUpdateState.appUpdateResult.completeUpdate() + } + } + + is InAppUpdateState.RequiredUpdate -> { + inAppUpdateState.onStartUpdate() + } + + is InAppUpdateState.OptionalUpdate -> { + inAppUpdateState.onStartUpdate(Mode.IMMEDIATE) } - } else { - Timber.e("User is in update flow but no update was available") - updateError = "Sorry! It seems there are no updates to install." + + is InAppUpdateState.InProgressUpdate -> { + Timber.w("UpdateAvailable: inAppUpdateState is InProgressUpdate") + updateError = "The update can't be started because an update is already in" + + " progress" + } + + is InAppUpdateState.Error -> { + Timber.e( + "UpdateAvailable: inAppUpdateState is Error: ${inAppUpdateState.exception}" + ) + updateError = + "An update is available, but an error occurred while trying to start" + + " it." + } + else -> { + updateError = "The update can't be started right now" + } + } + if (updateError?.isNotBlank() == true) { + Timber.e("Update error: $updateError") + updateCanceled = true } - updateCanceled = true }) { - Text("Download and install update") + Text("Update now") } } } @@ -95,8 +130,8 @@ fun RequiredUpdatePrompt() { ) { UpdateIcon( Modifier - .padding(bottom = 18.dp) - .size(96.dp) + .padding(bottom = 18.dp) + .size(96.dp) ) Text("Update to continue", style = MaterialTheme.typography.headlineMedium) Text( @@ -114,6 +149,13 @@ fun RequiredUpdatePrompt() { fun OptionalUpdatePrompt( onIgnoreUpdate: () -> Unit ) { + val inAppUpdateState = rememberInAppUpdateState( + highPrioritizeUpdates = 5, + mediumPrioritizeUpdates = 3, + promptIntervalHighPrioritizeUpdateInDays = 1, + promptIntervalMediumPrioritizeUpdateInDays = 4, + promptIntervalLowPrioritizeUpdateInDays = 8, + ) Column( horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center, @@ -121,8 +163,8 @@ fun OptionalUpdatePrompt( ) { UpdateIcon( Modifier - .padding(bottom = 9.dp) - .size(72.dp) + .padding(bottom = 9.dp) + .size(72.dp) ) Text("Update available", style = MaterialTheme.typography.headlineSmall) Text( @@ -132,8 +174,13 @@ fun OptionalUpdatePrompt( modifier = Modifier.padding(20.dp) ) InstallUpdateButton(onIgnoreUpdate) - TextButton(onClick = onIgnoreUpdate) { - Text("Remind me later") + TextButton(onClick = { + if (inAppUpdateState is InAppUpdateState.OptionalUpdate) { + inAppUpdateState.onDeclineUpdate() + } + onIgnoreUpdate() + }) { + Text("Not now") } } } diff --git a/app/src/main/java/org/robojackets/apiary/ui/update/UpdateGate.kt b/app/src/main/java/org/robojackets/apiary/ui/update/UpdateGate.kt index 168005b..8bc2c2b 100644 --- a/app/src/main/java/org/robojackets/apiary/ui/update/UpdateGate.kt +++ b/app/src/main/java/org/robojackets/apiary/ui/update/UpdateGate.kt @@ -3,64 +3,10 @@ package org.robojackets.apiary.ui.update import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.rememberCoroutineScope -import androidx.compose.ui.platform.LocalContext -import androidx.lifecycle.Lifecycle -import com.google.android.play.core.install.model.AppUpdateType -import com.google.android.play.core.install.model.UpdateAvailability -import com.google.android.play.core.ktx.AppUpdateResult -import com.google.android.play.core.ktx.clientVersionStalenessDays -import com.google.android.play.core.ktx.updatePriority -import kotlinx.coroutines.launch -import org.robojackets.apiary.base.ui.util.OnLifecycleEvent -import org.robojackets.apiary.base.ui.util.getActivity +import se.warting.inappupdate.compose.InAppUpdateState import se.warting.inappupdate.compose.rememberInAppUpdateState import timber.log.Timber -const val UPDATE_PRIORITY_LOWEST = 0 -const val UPDATE_PRIORITY_LOWER = 1 -const val UPDATE_PRIORITY_LOW = 2 -const val UPDATE_PRIORITY_MEDIUM = 3 -const val UPDATE_PRIORITY_HIGH = 4 -const val UPDATE_PRIORITY_HIGHEST = 5 - -const val OPT_UPDATE_STALENESS_THRESHOLD_LOW_PRIORITY = 14 -const val OPT_UPDATE_STALENESS_THRESHOLD_MEDIUM_PRIORITY = 4 - -fun isImmediateUpdateOptional(priority: Int, staleness: Int): Boolean { - return when (priority) { - UPDATE_PRIORITY_LOWEST, - UPDATE_PRIORITY_LOWER, - UPDATE_PRIORITY_LOW -> staleness >= OPT_UPDATE_STALENESS_THRESHOLD_LOW_PRIORITY - UPDATE_PRIORITY_MEDIUM -> staleness >= OPT_UPDATE_STALENESS_THRESHOLD_MEDIUM_PRIORITY - UPDATE_PRIORITY_HIGH -> true - UPDATE_PRIORITY_HIGHEST -> true - else -> { - Timber.w("Unknown priority $priority when evaluating for flexible update") - false - } - } -} - -const val REQ_UPDATE_STALENESS_THRESHOLD_LOW_PRIORITY = 21 -const val REQ_UPDATE_STALENESS_THRESHOLD_MEDIUM_PRIORITY = 21 -const val REQ_UPDATE_STALENESS_THRESHOLD_HIGH_PRIORITY = 1 - -fun isImmediateUpdateRequired(priority: Int, staleness: Int): Boolean { - return when (priority) { - UPDATE_PRIORITY_LOWEST, - UPDATE_PRIORITY_LOWER, - UPDATE_PRIORITY_LOW -> staleness >= REQ_UPDATE_STALENESS_THRESHOLD_LOW_PRIORITY - UPDATE_PRIORITY_MEDIUM -> staleness >= REQ_UPDATE_STALENESS_THRESHOLD_MEDIUM_PRIORITY - UPDATE_PRIORITY_HIGH -> staleness >= REQ_UPDATE_STALENESS_THRESHOLD_HIGH_PRIORITY - UPDATE_PRIORITY_HIGHEST -> true - else -> { - Timber.w("Unknown priority $priority when evaluating for immediate update") - false - } - } -} - @Suppress("ComplexMethod", "LongMethod") @Composable fun UpdateGate( @@ -71,108 +17,127 @@ fun UpdateGate( content: @Composable () -> Unit, ) { content() - val updateState = rememberInAppUpdateState() - val scope = rememberCoroutineScope() - val result = updateState.appUpdateResult - val context = LocalContext.current - OnLifecycleEvent { owner, event -> - when (event) { - Lifecycle.Event.ON_RESUME -> { - if (result is AppUpdateResult.Available) { - if (result.updateInfo.updateAvailability() - == UpdateAvailability.DEVELOPER_TRIGGERED_UPDATE_IN_PROGRESS - ) { - context.getActivity() - ?.let { result.startImmediateUpdate(it, UPDATE_REQUEST_CODE) } + val inAppUpdateState = rememberInAppUpdateState( + highPrioritizeUpdates = 5, + mediumPrioritizeUpdates = 3, + promptIntervalHighPrioritizeUpdateInDays = 1, + promptIntervalMediumPrioritizeUpdateInDays = 4, + promptIntervalLowPrioritizeUpdateInDays = 8, + ) + + when (inAppUpdateState) { + is InAppUpdateState.DownloadedUpdate -> { + if (inAppUpdateState.isRequiredUpdate) { + LaunchedEffect(navReady) { + if (navReady) { + onShowRequiredUpdatePrompt() + } + } + } else { + LaunchedEffect(navReady) { + if (navReady) { + onShowOptionalUpdatePrompt() } } } - else -> Unit + content() } - } - - when (result) { - is AppUpdateResult.NotAvailable -> Unit - is AppUpdateResult.Available -> { - val priority = result.updateInfo.updatePriority - val staleness = result.updateInfo.clientVersionStalenessDays ?: -1 - - val immediateAllowed = - result.updateInfo.isUpdateTypeAllowed(AppUpdateType.IMMEDIATE) - val immediateRequired = immediateAllowed && - isImmediateUpdateRequired(priority, staleness) - val immediateOptional = immediateAllowed && - !immediateRequired && - isImmediateUpdateOptional(priority, staleness) - - when { - immediateRequired -> { - LaunchedEffect(navReady) { - if (navReady) { - onShowRequiredUpdatePrompt() - } - } - } - immediateOptional -> { - LaunchedEffect(navReady) { - if (navReady) { - onShowOptionalUpdatePrompt() - } - } + is InAppUpdateState.InProgressUpdate -> { + Timber.i("Update in progress: ${inAppUpdateState.installState.bytesDownloaded}") + LaunchedEffect(navReady) { + if (navReady) { + onShowUpdateInProgressScreen() } - else -> { - Timber.d("An update is available but no action is required currently") - content() + } + UpdateInProgress() + } + + InAppUpdateState.Loading -> { + Timber.i("In-app update - loading state") + content() + } + InAppUpdateState.NotAvailable -> { + content() + } + is InAppUpdateState.OptionalUpdate -> { + LaunchedEffect(navReady) { + if (navReady && inAppUpdateState.shouldPrompt) { + onShowOptionalUpdatePrompt() // FIXME: test this } } + content() } - is AppUpdateResult.InProgress -> Unit - is AppUpdateResult.Downloaded -> { - LaunchedEffect(result) { - if (navReady) { - onShowUpdateInProgressScreen() - scope.launch { - result.completeUpdate() - } + + is InAppUpdateState.RequiredUpdate -> { + LaunchedEffect(navReady) { + if (navReady && inAppUpdateState.shouldPrompt) { + onShowRequiredUpdatePrompt() // FIXME: test this } } + content() + } + + is InAppUpdateState.Error -> { + content() } } } @Composable fun UpdateStatus() { - val updateState = rememberInAppUpdateState() + val inAppUpdateState = rememberInAppUpdateState( + highPrioritizeUpdates = 5, + mediumPrioritizeUpdates = 3, + promptIntervalHighPrioritizeUpdateInDays = 1, + promptIntervalMediumPrioritizeUpdateInDays = 4, + promptIntervalLowPrioritizeUpdateInDays = 8, + ) + when (inAppUpdateState) { + is InAppUpdateState.DownloadedUpdate -> { + if (inAppUpdateState.isRequiredUpdate) { + Text("Downloaded > required") + } else { + Text("Downloaded > optional") + } + } - when (val result = updateState.appUpdateResult) { - is AppUpdateResult.NotAvailable -> Text("Up to date") - is AppUpdateResult.Available -> { - val priority = result.updateInfo.updatePriority - val staleness = result.updateInfo.clientVersionStalenessDays ?: -1 + is InAppUpdateState.InProgressUpdate -> { + Text( + "In progress (${inAppUpdateState.installState.bytesDownloaded}/" + + "${inAppUpdateState.installState.totalBytesToDownload}) bytes) " + + "| Install status: ${inAppUpdateState.installState.installStatus} " + + "| Error code: ${inAppUpdateState.installState.installErrorCode} " + + "| Package name: ${inAppUpdateState.installState.packageName}" + ) + } - val immediateAllowed = - result.updateInfo.isUpdateTypeAllowed(AppUpdateType.IMMEDIATE) + InAppUpdateState.Loading -> { + Text("Loading") + } + InAppUpdateState.NotAvailable -> { + Text("Not available") + } + is InAppUpdateState.OptionalUpdate -> { + Text( + "Optional update | Should prompt: ${inAppUpdateState.shouldPrompt} " + + "| Priority: ${inAppUpdateState.appUpdateInfo.priority}" + + "| Staleness: ${inAppUpdateState.appUpdateInfo.staleDays}" + + "| Version code: ${inAppUpdateState.appUpdateInfo.versionCode}" + ) + } - val immediateRequired = immediateAllowed && - isImmediateUpdateRequired(priority, staleness) - val immediateOptional = immediateAllowed && - !immediateRequired && - isImmediateUpdateOptional(priority, staleness) + is InAppUpdateState.RequiredUpdate -> { + Text( + "Required update | Should prompt: ${inAppUpdateState.shouldPrompt} " + + "| Priority: ${inAppUpdateState.appUpdateInfo.priority}" + + "| Staleness: ${inAppUpdateState.appUpdateInfo.staleDays}" + + "| Version code: ${inAppUpdateState.appUpdateInfo.versionCode}" + ) + } - when { - immediateRequired -> Text( - "Required update available (priority: " + - "$priority, staleness: $staleness)" - ) - immediateOptional -> Text( - "Optional update available (priority: " + - "$priority, staleness: $staleness)" - ) - else -> Text("Available") - } + is InAppUpdateState.Error -> { + Text("Error: ${inAppUpdateState.exception}") } - is AppUpdateResult.InProgress -> Text("Update in progress") - is AppUpdateResult.Downloaded -> Text("Update downloaded") } } diff --git a/attendance/build.gradle.kts b/attendance/build.gradle.kts index d01cde1..bce3244 100644 --- a/attendance/build.gradle.kts +++ b/attendance/build.gradle.kts @@ -2,7 +2,7 @@ plugins { id("com.android.library") kotlin("android") id("kotlin-android") - kotlin("kapt") +// kotlin("kapt") id("com.google.devtools.ksp") id("dagger.hilt.android.plugin") id("com.google.android.libraries.mapsplatform.secrets-gradle-plugin") @@ -24,8 +24,8 @@ dependencies { implementation(ComposeDependencies.lifecycle_viewmodel_compose) implementation(HiltDependencies.hilt) - kapt(HiltDependencies.hilt_android_compiler) - implementation(HiltDependencies.dagger_producer) + ksp(HiltDependencies.hilt_android_compiler) +// implementation(HiltDependencies.dagger_producer) implementation(NetworkDependencies.moshi) ksp(NetworkDependencies.moshi_kotlin_codegen) diff --git a/auth/build.gradle.kts b/auth/build.gradle.kts index a222271..ce39cb3 100644 --- a/auth/build.gradle.kts +++ b/auth/build.gradle.kts @@ -2,7 +2,7 @@ plugins { id("com.android.library") kotlin("android") id("kotlin-android") - kotlin("kapt") +// kotlin("kapt") id("com.google.devtools.ksp") id("dagger.hilt.android.plugin") id("com.google.android.libraries.mapsplatform.secrets-gradle-plugin") @@ -34,8 +34,8 @@ dependencies { implementation(ComposeDependencies.compose_ui_tooling) implementation(HiltDependencies.hilt) - kapt(HiltDependencies.hilt_android_compiler) - implementation(HiltDependencies.dagger_producer) + ksp(HiltDependencies.hilt_android_compiler) +// implementation(HiltDependencies.dagger_producer) implementation(MaterialDependencies.material_android) diff --git a/base/build.gradle.kts b/base/build.gradle.kts index 4a268f2..9d23205 100644 --- a/base/build.gradle.kts +++ b/base/build.gradle.kts @@ -2,7 +2,7 @@ plugins { id("com.android.library") kotlin("android") id("kotlin-android") - kotlin("kapt") +// kotlin("kapt") id("com.google.devtools.ksp") id("dagger.hilt.android.plugin") id("com.google.android.libraries.mapsplatform.secrets-gradle-plugin") @@ -26,8 +26,8 @@ dependencies { implementation(MaterialDependencies.material_android) implementation(HiltDependencies.hilt) - kapt(HiltDependencies.hilt_android_compiler) - implementation(HiltDependencies.dagger_producer) + ksp(HiltDependencies.hilt_android_compiler) +// implementation(HiltDependencies.dagger_producer) implementation(NetworkDependencies.moshi) ksp(NetworkDependencies.moshi_kotlin_codegen) diff --git a/base/src/main/java/org/robojackets/apiary/base/ui/theme/Color.kt b/base/src/main/java/org/robojackets/apiary/base/ui/theme/Color.kt index 83b55a0..281d309 100644 --- a/base/src/main/java/org/robojackets/apiary/base/ui/theme/Color.kt +++ b/base/src/main/java/org/robojackets/apiary/base/ui/theme/Color.kt @@ -100,4 +100,4 @@ val surfaceContainerLowestDark = Color(0xFF120E06) val surfaceContainerLowDark = Color(0xFF201B11) val surfaceContainerDark = Color(0xFF241F15) val surfaceContainerHighDark = Color(0xFF2F291F) -val surfaceContainerHighestDark = Color(0xFF3A3429) \ No newline at end of file +val surfaceContainerHighestDark = Color(0xFF3A3429) diff --git a/base/src/main/java/org/robojackets/apiary/base/ui/theme/Theme.kt b/base/src/main/java/org/robojackets/apiary/base/ui/theme/Theme.kt index ca745e2..b4a30f5 100644 --- a/base/src/main/java/org/robojackets/apiary/base/ui/theme/Theme.kt +++ b/base/src/main/java/org/robojackets/apiary/base/ui/theme/Theme.kt @@ -121,4 +121,4 @@ fun Apiary_MobileTheme( typography = Typography, content = content ) -} \ No newline at end of file +} diff --git a/build.gradle.kts b/build.gradle.kts index c7dc063..f7c2d54 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -7,7 +7,8 @@ buildscript { dependencies { classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.0") classpath("com.android.tools.build:gradle:8.5.0") - classpath("com.google.dagger:hilt-android-gradle-plugin:2.46.1") + classpath("com.google.dagger:hilt-android-gradle-plugin:2.51.1") // This version needs to + // match the version for other Hilt dependencies defined in Dependencies.kt classpath("com.google.android.libraries.mapsplatform.secrets-gradle-plugin:secrets-gradle-plugin:2.0.1") classpath("com.google.gms:google-services:4.4.2") classpath("com.google.android.gms:oss-licenses-plugin:0.10.6") @@ -42,7 +43,7 @@ tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile>().configureEach } tasks.register("clean", Delete::class) { - delete(rootProject.buildDir) + delete(rootProject.layout.buildDirectory) } val projectSource = file(projectDir) diff --git a/buildSrc/src/main/java/Dependencies.kt b/buildSrc/src/main/java/Dependencies.kt index c52eaf3..8a587f8 100644 --- a/buildSrc/src/main/java/Dependencies.kt +++ b/buildSrc/src/main/java/Dependencies.kt @@ -92,7 +92,8 @@ object AuthDependencies { object HiltDependencies { object Versions { const val hilt_navigation_compose_version = "1.2.0" - const val hilt_version = "2.46.1" + const val hilt_version = "2.51.1" // If you update this version, you also need to update + // the com.google.dagger:hilt-android-gradle-plugin version in build.gradle files } const val hilt = "com.google.dagger:hilt-android:${Versions.hilt_version}" @@ -108,7 +109,7 @@ object AndroidToolDependencies { const val android_tools_desugar_version = "2.0.4" const val krate_version = "2.0.0" const val gson_version = "2.11.0" - const val in_app_update_compose_version = "0.0.17" // TODO: Update to newer version with breaking changes + const val in_app_update_compose_version = "1.2.0" const val open_source_licenses_version = "17.1.0" const val sentry_version = "7.10.0" const val timber_version = "5.0.1" @@ -118,7 +119,7 @@ object AndroidToolDependencies { "com.android.tools:desugar_jdk_libs:${Versions.android_tools_desugar_version}" const val gson = "com.google.code.gson:gson:${Versions.gson_version}" const val in_app_update_compose = - "se.warting.in-app-update:in-app-update-compose:${Versions.in_app_update_compose_version}" + "se.warting.in-app-update:in-app-update-compose-mui:${Versions.in_app_update_compose_version}" const val krate = "hu.autsoft:krate:${Versions.krate_version}" const val open_source_licenses = "com.google.android.gms:play-services-oss-licenses:${Versions.open_source_licenses_version}" diff --git a/navigation/build.gradle.kts b/navigation/build.gradle.kts index 30da45e..0c7c10d 100644 --- a/navigation/build.gradle.kts +++ b/navigation/build.gradle.kts @@ -2,7 +2,7 @@ plugins { id("com.android.library") kotlin("android") id("kotlin-android") - kotlin("kapt") +// kotlin("kapt") id("com.google.devtools.ksp") id("dagger.hilt.android.plugin") id("com.google.android.libraries.mapsplatform.secrets-gradle-plugin") @@ -23,8 +23,8 @@ dependencies { implementation(AndroidXDependencies.androidx_navigation_compose) implementation(HiltDependencies.hilt) - kapt(HiltDependencies.hilt_android_compiler) - implementation(HiltDependencies.dagger_producer) + ksp(HiltDependencies.hilt_android_compiler) +// implementation(HiltDependencies.dagger_producer) implementation(MaterialDependencies.material_android) From 91ec7bb50989d02bf72954619eb6d93b99146c4e Mon Sep 17 00:00:00 2001 From: Evan Strat <evan10s@users.noreply.github.com> Date: Thu, 4 Jul 2024 13:40:14 -0400 Subject: [PATCH 17/33] Final fixes --- app/build.gradle.kts | 6 ++--- .../org/robojackets/apiary/MainActivity.kt | 11 ++++----- .../apiary/di/MainActivityModule.kt | 2 +- .../robojackets/apiary/ui/global/AppTopBar.kt | 9 +++++++ .../apiary/ui/update/UpdateGate.kt | 4 ++-- attendance/build.gradle.kts | 6 ++--- .../model/AttendableTypeSelectionViewModel.kt | 6 +++-- .../attendance/model/AttendanceViewModel.kt | 12 ++++++---- auth/build.gradle.kts | 8 +++---- .../apiary/auth/ui/Authentication.kt | 24 +++++++++++++++---- .../permissions/MissingHiddenTeamsCallout.kt | 5 ++-- base/build.gradle.kts | 8 +++---- .../apiary/base/ui/ActionPrompt.kt | 4 ++-- .../apiary/base/ui/callout/Callout.kt | 12 ++++++---- .../apiary/base/ui/nfc/NfcRequired.kt | 3 --- .../robojackets/apiary/base/ui/theme/Theme.kt | 9 +++++-- build.gradle.kts | 2 +- buildSrc/src/main/java/Dependencies.kt | 21 ++++++++-------- navigation/build.gradle.kts | 4 ---- 19 files changed, 89 insertions(+), 67 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 38a2646..46c0f8c 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -2,7 +2,6 @@ plugins { id("com.android.application") kotlin("android") id("kotlin-android") -// kotlin("kapt") // FIXME: remove if unneeded id("com.google.devtools.ksp") id("dagger.hilt.android.plugin") id("com.google.android.libraries.mapsplatform.secrets-gradle-plugin") @@ -32,7 +31,7 @@ dependencies { implementation(AuthDependencies.appauth) - implementation(ComposeDependencies.accompanist_nav_material) + implementation(ComposeDependencies.compose_material_navigation) implementation(ComposeDependencies.compose_ui) implementation(ComposeDependencies.lifecycle_viewmodel_compose) implementation(ComposeDependencies.compose_ui_tooling) @@ -44,7 +43,6 @@ dependencies { implementation(HiltDependencies.hilt) ksp(HiltDependencies.hilt_android_compiler) -// implementation(HiltDependencies.dagger_producer) // FIXME: remove if unneeded implementation(HiltDependencies.hilt_navigation_compose) implementation(NetworkDependencies.moshi_converter_factory) @@ -53,6 +51,8 @@ dependencies { implementation(NetworkDependencies.okhttp_logging_interceptor) implementation(NetworkDependencies.retrofit) implementation(NetworkDependencies.sandwich) // yum yum + implementation(NetworkDependencies.sandwich_retrofit) + implementation(NetworkDependencies.sandwich_retrofit_serialization) implementation(platform(NfcDependencies.nfc_firebase_bom)) implementation(NfcDependencies.nfc_firebase_analytics) // Firebase BoM and Analytics (f/k/a Core) are required when including TapLinx (line below) manually diff --git a/app/src/main/java/org/robojackets/apiary/MainActivity.kt b/app/src/main/java/org/robojackets/apiary/MainActivity.kt index 17b05e8..b638bc0 100644 --- a/app/src/main/java/org/robojackets/apiary/MainActivity.kt +++ b/app/src/main/java/org/robojackets/apiary/MainActivity.kt @@ -11,6 +11,9 @@ import androidx.compose.foundation.layout.padding import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Settings import androidx.compose.material.icons.outlined.Contactless +import androidx.compose.material.navigation.ModalBottomSheetLayout +import androidx.compose.material.navigation.bottomSheet +import androidx.compose.material.navigation.rememberBottomSheetNavigator import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.NavigationBar @@ -40,10 +43,6 @@ import androidx.navigation.compose.rememberNavController import androidx.navigation.navArgument import androidx.navigation.navigation import androidx.navigation.plusAssign -import com.google.accompanist.navigation.material.ExperimentalMaterialNavigationApi -import com.google.accompanist.navigation.material.ModalBottomSheetLayout -import com.google.accompanist.navigation.material.bottomSheet -import com.google.accompanist.navigation.material.rememberBottomSheetNavigator import com.nxp.nfclib.NxpNfcLib import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.flow.launchIn @@ -132,7 +131,6 @@ class MainActivity : ComponentActivity() { nfcLib.registerActivity(this, BuildConfig.taplinxKey, BuildConfig.taplinxOfflineKey) } - @OptIn(ExperimentalMaterialNavigationApi::class) @Suppress("LongMethod") override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -153,7 +151,7 @@ class MainActivity : ComponentActivity() { setContent { Apiary_MobileTheme { - window.statusBarColor = MaterialTheme.colorScheme.secondary.toArgb() // FIXME: deprecated + window.statusBarColor = MaterialTheme.colorScheme.secondary.toArgb() val navController = rememberNavController() val bottomSheetNavigator = rememberBottomSheetNavigator() navController.navigatorProvider += bottomSheetNavigator @@ -248,7 +246,6 @@ class MainActivity : ComponentActivity() { currentScreen != NavigationDestinations.updateInProgress @Suppress("LongMethod") - @OptIn(ExperimentalMaterialNavigationApi::class) @Composable private fun AppNavigation( navController: NavHostController, diff --git a/app/src/main/java/org/robojackets/apiary/di/MainActivityModule.kt b/app/src/main/java/org/robojackets/apiary/di/MainActivityModule.kt index b5aa650..1acf3b5 100644 --- a/app/src/main/java/org/robojackets/apiary/di/MainActivityModule.kt +++ b/app/src/main/java/org/robojackets/apiary/di/MainActivityModule.kt @@ -2,7 +2,7 @@ package org.robojackets.apiary.di import android.content.Context import com.nxp.nfclib.NxpNfcLib -import com.skydoves.sandwich.adapters.ApiResponseCallAdapterFactory +import com.skydoves.sandwich.retrofit.adapters.ApiResponseCallAdapterFactory import com.squareup.moshi.Moshi import com.squareup.moshi.Types import dagger.Module diff --git a/app/src/main/java/org/robojackets/apiary/ui/global/AppTopBar.kt b/app/src/main/java/org/robojackets/apiary/ui/global/AppTopBar.kt index d077626..6d75fdd 100644 --- a/app/src/main/java/org/robojackets/apiary/ui/global/AppTopBar.kt +++ b/app/src/main/java/org/robojackets/apiary/ui/global/AppTopBar.kt @@ -9,9 +9,11 @@ import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.material3.TopAppBar +import androidx.compose.material3.TopAppBarColors import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import org.robojackets.apiary.base.ui.IconWithText @@ -22,6 +24,13 @@ import org.robojackets.apiary.base.ui.icons.WarningIcon fun AppTopBar(isProdEnv: Boolean) { Column { TopAppBar( + colors = TopAppBarColors( + containerColor = MaterialTheme.colorScheme.primary, + scrolledContainerColor = Color.Unspecified, + navigationIconContentColor = Color.Unspecified, + titleContentColor = Color.Unspecified, + actionIconContentColor = Color.Unspecified, + ), title = { Text( text = "MyRoboJackets", diff --git a/app/src/main/java/org/robojackets/apiary/ui/update/UpdateGate.kt b/app/src/main/java/org/robojackets/apiary/ui/update/UpdateGate.kt index 8bc2c2b..a8ed0da 100644 --- a/app/src/main/java/org/robojackets/apiary/ui/update/UpdateGate.kt +++ b/app/src/main/java/org/robojackets/apiary/ui/update/UpdateGate.kt @@ -63,7 +63,7 @@ fun UpdateGate( is InAppUpdateState.OptionalUpdate -> { LaunchedEffect(navReady) { if (navReady && inAppUpdateState.shouldPrompt) { - onShowOptionalUpdatePrompt() // FIXME: test this + onShowOptionalUpdatePrompt() } } content() @@ -72,7 +72,7 @@ fun UpdateGate( is InAppUpdateState.RequiredUpdate -> { LaunchedEffect(navReady) { if (navReady && inAppUpdateState.shouldPrompt) { - onShowRequiredUpdatePrompt() // FIXME: test this + onShowRequiredUpdatePrompt() } } content() diff --git a/attendance/build.gradle.kts b/attendance/build.gradle.kts index bce3244..a233cea 100644 --- a/attendance/build.gradle.kts +++ b/attendance/build.gradle.kts @@ -2,7 +2,6 @@ plugins { id("com.android.library") kotlin("android") id("kotlin-android") -// kotlin("kapt") id("com.google.devtools.ksp") id("dagger.hilt.android.plugin") id("com.google.android.libraries.mapsplatform.secrets-gradle-plugin") @@ -13,8 +12,6 @@ dependencies { implementation(project(mapOf("path" to ":base"))) implementation(project(mapOf("path" to ":navigation"))) implementation(project(mapOf("path" to ":auth"))) - implementation("androidx.navigation:navigation-common-ktx:2.3.5") - // Dependencies coreLibraryDesugaring(AndroidToolDependencies.android_tools_desugar_jdk) implementation(AndroidToolDependencies.timber) @@ -25,7 +22,6 @@ dependencies { implementation(HiltDependencies.hilt) ksp(HiltDependencies.hilt_android_compiler) -// implementation(HiltDependencies.dagger_producer) implementation(NetworkDependencies.moshi) ksp(NetworkDependencies.moshi_kotlin_codegen) @@ -34,6 +30,8 @@ dependencies { implementation(NetworkDependencies.retrofit) implementation(NetworkDependencies.retrofuture) implementation(NetworkDependencies.sandwich) + implementation(NetworkDependencies.sandwich_retrofit) + implementation(NetworkDependencies.sandwich_retrofit_serialization) implementation(platform(NfcDependencies.nfc_firebase_bom)) implementation(NfcDependencies.nfc_firebase_analytics) // Firebase BoM and Analytics (f/k/a Core) are required when including TapLinx (line below) manually diff --git a/attendance/src/main/java/org/robojackets/apiary/attendance/model/AttendableTypeSelectionViewModel.kt b/attendance/src/main/java/org/robojackets/apiary/attendance/model/AttendableTypeSelectionViewModel.kt index a87359d..de42a4c 100644 --- a/attendance/src/main/java/org/robojackets/apiary/attendance/model/AttendableTypeSelectionViewModel.kt +++ b/attendance/src/main/java/org/robojackets/apiary/attendance/model/AttendableTypeSelectionViewModel.kt @@ -8,6 +8,7 @@ import com.skydoves.sandwich.message import com.skydoves.sandwich.onError import com.skydoves.sandwich.onException import com.skydoves.sandwich.onSuccess +import com.skydoves.sandwich.retrofit.statusCode import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow @@ -15,7 +16,8 @@ import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.combine import kotlinx.coroutines.launch import org.robojackets.apiary.auth.model.Permission -import org.robojackets.apiary.auth.model.Permission.* +import org.robojackets.apiary.auth.model.Permission.CREATE_ATTENDANCE +import org.robojackets.apiary.auth.model.Permission.READ_USERS import org.robojackets.apiary.auth.model.UserInfo import org.robojackets.apiary.auth.network.UserRepository import org.robojackets.apiary.auth.util.getMissingPermissions @@ -99,7 +101,7 @@ class AttendableTypeSelectionViewModel @Inject constructor( } } .onException { - Timber.e(this.exception) + Timber.e(this.throwable) permissionsCheckError.value = "An error occurred while checking if you have " + "permission to use this feature. Check your internet connection and " + "try again, or ask in #it-helpdesk for assistance." diff --git a/attendance/src/main/java/org/robojackets/apiary/attendance/model/AttendanceViewModel.kt b/attendance/src/main/java/org/robojackets/apiary/attendance/model/AttendanceViewModel.kt index 24a10e7..7e88964 100644 --- a/attendance/src/main/java/org/robojackets/apiary/attendance/model/AttendanceViewModel.kt +++ b/attendance/src/main/java/org/robojackets/apiary/attendance/model/AttendanceViewModel.kt @@ -9,9 +9,13 @@ import com.skydoves.sandwich.onError import com.skydoves.sandwich.onException import com.skydoves.sandwich.onSuccess import dagger.hilt.android.lifecycle.HiltViewModel -import kotlinx.coroutines.flow.* +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.catch +import kotlinx.coroutines.flow.combine import kotlinx.coroutines.launch -import org.robojackets.apiary.attendance.model.AttendanceScreenState.* +import org.robojackets.apiary.attendance.model.AttendanceScreenState.Loading +import org.robojackets.apiary.attendance.model.AttendanceScreenState.ReadyForTap import org.robojackets.apiary.attendance.network.AttendanceRepository import org.robojackets.apiary.base.model.Attendable import org.robojackets.apiary.base.model.AttendableType @@ -191,7 +195,7 @@ class AttendanceViewModel @Inject constructor( error.value = "Unable to fetch team info" }.onException { Timber.e( - this.exception, + this.throwable, "Exception occurred while fetching attendable teams" ) error.value = "Unable to fetch team info" @@ -209,7 +213,7 @@ class AttendanceViewModel @Inject constructor( error.value = "Unable to fetch event info" }.onException { Timber.e( - this.exception, + this.throwable, "Exception occurred while fetching attendable events" ) error.value = "Unable to fetch event info" diff --git a/auth/build.gradle.kts b/auth/build.gradle.kts index ce39cb3..0ffc5e3 100644 --- a/auth/build.gradle.kts +++ b/auth/build.gradle.kts @@ -2,7 +2,6 @@ plugins { id("com.android.library") kotlin("android") id("kotlin-android") -// kotlin("kapt") id("com.google.devtools.ksp") id("dagger.hilt.android.plugin") id("com.google.android.libraries.mapsplatform.secrets-gradle-plugin") @@ -22,7 +21,7 @@ dependencies { implementation(AndroidToolDependencies.timber) implementation(AndroidXDependencies.androidx_activity_compose) - implementation(AndroidXDependencies.androidx_lifecycle_runtime_ktx) + implementation(AndroidXDependencies.androidx_lifecycle_runtime) implementation(AndroidXDependencies.androidx_navigation_compose) implementation(AuthDependencies.appauth) @@ -35,9 +34,6 @@ dependencies { implementation(HiltDependencies.hilt) ksp(HiltDependencies.hilt_android_compiler) -// implementation(HiltDependencies.dagger_producer) - - implementation(MaterialDependencies.material_android) implementation(NetworkDependencies.moshi) ksp(NetworkDependencies.moshi_kotlin_codegen) @@ -46,6 +42,8 @@ dependencies { implementation(NetworkDependencies.retrofit) implementation(NetworkDependencies.retrofuture) implementation(NetworkDependencies.sandwich) + implementation(NetworkDependencies.sandwich_retrofit) + implementation(NetworkDependencies.sandwich_retrofit_serialization) // Test dependencies androidTestImplementation(ComposeDependencies.compose_ui_test) diff --git a/auth/src/main/java/org/robojackets/apiary/auth/ui/Authentication.kt b/auth/src/main/java/org/robojackets/apiary/auth/ui/Authentication.kt index ed8c943..1903a52 100644 --- a/auth/src/main/java/org/robojackets/apiary/auth/ui/Authentication.kt +++ b/auth/src/main/java/org/robojackets/apiary/auth/ui/Authentication.kt @@ -1,10 +1,17 @@ package org.robojackets.apiary.auth.ui -import android.app.Activity.* +import android.app.Activity.RESULT_OK import androidx.activity.compose.rememberLauncherForActivityResult import androidx.activity.result.contract.ActivityResultContracts import androidx.compose.foundation.Image -import androidx.compose.foundation.layout.* +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.defaultMinSize +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding import androidx.compose.foundation.selection.selectable import androidx.compose.foundation.selection.selectableGroup import androidx.compose.material3.AlertDialog @@ -16,7 +23,13 @@ import androidx.compose.material3.RadioButton import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.material3.rememberModalBottomSheetState -import androidx.compose.runtime.* +import androidx.compose.runtime.Composable +import androidx.compose.runtime.SideEffect +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.painterResource @@ -28,12 +41,13 @@ import net.openid.appauth.AuthorizationResponse import org.robojackets.apiary.auth.R import org.robojackets.apiary.auth.model.AuthenticationState import org.robojackets.apiary.auth.model.AuthenticationViewModel -import org.robojackets.apiary.auth.model.LoginStatus.* +import org.robojackets.apiary.auth.model.LoginStatus.COMPLETE +import org.robojackets.apiary.auth.model.LoginStatus.ERROR +import org.robojackets.apiary.auth.model.LoginStatus.NOT_STARTED import org.robojackets.apiary.auth.oauth2.AuthManager import org.robojackets.apiary.base.AppEnvironment import org.robojackets.apiary.base.ui.util.MadeWithLove -@OptIn(ExperimentalMaterial3Api::class) @Suppress("LongMethod", "MagicNumber") @Composable private fun Authentication( diff --git a/auth/src/main/java/org/robojackets/apiary/auth/ui/permissions/MissingHiddenTeamsCallout.kt b/auth/src/main/java/org/robojackets/apiary/auth/ui/permissions/MissingHiddenTeamsCallout.kt index f8f8240..0869601 100644 --- a/auth/src/main/java/org/robojackets/apiary/auth/ui/permissions/MissingHiddenTeamsCallout.kt +++ b/auth/src/main/java/org/robojackets/apiary/auth/ui/permissions/MissingHiddenTeamsCallout.kt @@ -19,9 +19,10 @@ fun MissingHiddenTeamsCallout(onRefreshTeams: () -> Unit) { Column { Text( "You don't have permission to view all teams, including " + - "training teams. Ask in #it-helpdesk for access." + "training teams. Ask in #it-helpdesk for access.", + Modifier.padding(top = 4.dp) ) - OutlinedButton(onClick = onRefreshTeams, Modifier.padding(top = 0.dp)) { + OutlinedButton(onClick = onRefreshTeams, Modifier.padding(top = 4.dp)) { Text("Refresh teams") } } diff --git a/base/build.gradle.kts b/base/build.gradle.kts index 9d23205..05a1ab6 100644 --- a/base/build.gradle.kts +++ b/base/build.gradle.kts @@ -2,7 +2,6 @@ plugins { id("com.android.library") kotlin("android") id("kotlin-android") -// kotlin("kapt") id("com.google.devtools.ksp") id("dagger.hilt.android.plugin") id("com.google.android.libraries.mapsplatform.secrets-gradle-plugin") @@ -21,18 +20,17 @@ dependencies { implementation(ComposeDependencies.compose_material3) implementation(ComposeDependencies.compose_ui) implementation(ComposeDependencies.compose_ui_tooling) - implementation(ComposeDependencies.accompanist_nav_material) - - implementation(MaterialDependencies.material_android) + implementation(ComposeDependencies.compose_material_navigation) implementation(HiltDependencies.hilt) ksp(HiltDependencies.hilt_android_compiler) -// implementation(HiltDependencies.dagger_producer) implementation(NetworkDependencies.moshi) ksp(NetworkDependencies.moshi_kotlin_codegen) implementation(NetworkDependencies.retrofit) implementation(NetworkDependencies.sandwich) + implementation(NetworkDependencies.sandwich_retrofit) + implementation(NetworkDependencies.sandwich_retrofit_serialization) implementation(platform(NfcDependencies.nfc_firebase_bom)) implementation(NfcDependencies.nfc_firebase_analytics) // Firebase BoM and Analytics (f/k/a Core) are required when including TapLinx (line below) manually diff --git a/base/src/main/java/org/robojackets/apiary/base/ui/ActionPrompt.kt b/base/src/main/java/org/robojackets/apiary/base/ui/ActionPrompt.kt index ccab524..4ef5d93 100644 --- a/base/src/main/java/org/robojackets/apiary/base/ui/ActionPrompt.kt +++ b/base/src/main/java/org/robojackets/apiary/base/ui/ActionPrompt.kt @@ -27,7 +27,7 @@ fun ActionPrompt( Column( verticalArrangement = Arrangement.SpaceBetween, horizontalAlignment = Alignment.CenterHorizontally, - modifier = Modifier.fillMaxWidth().padding(bottom = 8.dp) + modifier = Modifier.fillMaxWidth().padding(bottom = 8.dp, start = 4.dp, end = 4.dp) ) { icon() Text( @@ -44,7 +44,7 @@ fun ActionPrompt( subtitle?.let { Text( text = subtitle, - style = MaterialTheme.typography.titleMedium, + style = MaterialTheme.typography.bodyLarge, textAlign = TextAlign.Center, ) } diff --git a/base/src/main/java/org/robojackets/apiary/base/ui/callout/Callout.kt b/base/src/main/java/org/robojackets/apiary/base/ui/callout/Callout.kt index 433d3fe..04a7101 100644 --- a/base/src/main/java/org/robojackets/apiary/base/ui/callout/Callout.kt +++ b/base/src/main/java/org/robojackets/apiary/base/ui/callout/Callout.kt @@ -2,7 +2,11 @@ package org.robojackets.apiary.base.ui.callout import androidx.compose.foundation.background import androidx.compose.foundation.border -import androidx.compose.foundation.layout.* +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text @@ -15,13 +19,11 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import org.robojackets.apiary.base.ui.IconWithText import org.robojackets.apiary.base.ui.icons.ErrorIcon +import org.robojackets.apiary.base.ui.theme.isLight import org.robojackets.apiary.base.ui.theme.warningDarkSubtle import org.robojackets.apiary.base.ui.theme.warningLightMuted import org.robojackets.apiary.base.ui.theme.warningLightSubtle -// TODO: M3 upgrade -// - Implement replacement for isLight - @Composable fun Callout( title: @Composable () -> Unit, @@ -52,7 +54,7 @@ fun WarningCallout( padding: PaddingValues? = null, body: @Composable () -> Unit, ) { - val isLightTheme = true // TODO: M3 upgrade, previously: MaterialTheme.colors.isLight + val isLightTheme = MaterialTheme.colorScheme.isLight() Callout( title = { diff --git a/base/src/main/java/org/robojackets/apiary/base/ui/nfc/NfcRequired.kt b/base/src/main/java/org/robojackets/apiary/base/ui/nfc/NfcRequired.kt index 1653d76..370b76c 100644 --- a/base/src/main/java/org/robojackets/apiary/base/ui/nfc/NfcRequired.kt +++ b/base/src/main/java/org/robojackets/apiary/base/ui/nfc/NfcRequired.kt @@ -22,9 +22,6 @@ import org.robojackets.apiary.base.ui.icons.ErrorIcon import org.robojackets.apiary.base.ui.theme.danger import org.robojackets.apiary.base.ui.theme.warningLightEmphasis -// TODO: M3 upgrade -// - Opening the app with NFC disabled causes a crash - @Composable fun NfcRequired(nfcEnabled: Boolean, gatedComposable: @Composable () -> Unit) { val context = LocalContext.current diff --git a/base/src/main/java/org/robojackets/apiary/base/ui/theme/Theme.kt b/base/src/main/java/org/robojackets/apiary/base/ui/theme/Theme.kt index b4a30f5..4d2aae7 100644 --- a/base/src/main/java/org/robojackets/apiary/base/ui/theme/Theme.kt +++ b/base/src/main/java/org/robojackets/apiary/base/ui/theme/Theme.kt @@ -3,6 +3,7 @@ package org.robojackets.apiary.base.ui.theme import android.app.Activity import android.os.Build import androidx.compose.foundation.isSystemInDarkTheme +import androidx.compose.material3.ColorScheme import androidx.compose.material3.MaterialTheme import androidx.compose.material3.darkColorScheme import androidx.compose.material3.dynamicDarkColorScheme @@ -10,6 +11,7 @@ import androidx.compose.material3.dynamicLightColorScheme import androidx.compose.material3.lightColorScheme import androidx.compose.runtime.Composable import androidx.compose.runtime.SideEffect +import androidx.compose.ui.graphics.luminance import androidx.compose.ui.graphics.toArgb import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalView @@ -91,10 +93,13 @@ private val darkScheme = darkColorScheme( surfaceContainerHighest = surfaceContainerHighestDark, ) +// From https://stackoverflow.com/a/71594753 +@Suppress("MagicNumber") +fun ColorScheme.isLight() = this.background.luminance() > 0.5 + @Composable fun Apiary_MobileTheme( darkTheme: Boolean = isSystemInDarkTheme(), - // Dynamic color is available on Android 12+ dynamicColor: Boolean = false, content: @Composable() () -> Unit ) { @@ -111,7 +116,7 @@ fun Apiary_MobileTheme( if (!view.isInEditMode) { SideEffect { val window = (view.context as Activity).window - window.statusBarColor = colorScheme.primary.toArgb() // FIXME + window.statusBarColor = colorScheme.primary.toArgb() WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars = darkTheme } } diff --git a/build.gradle.kts b/build.gradle.kts index f7c2d54..cddc6b1 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,8 +1,8 @@ buildscript { repositories { google() - gradlePluginPortal() mavenCentral() + gradlePluginPortal() } dependencies { classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.0") diff --git a/buildSrc/src/main/java/Dependencies.kt b/buildSrc/src/main/java/Dependencies.kt index 8a587f8..f366345 100644 --- a/buildSrc/src/main/java/Dependencies.kt +++ b/buildSrc/src/main/java/Dependencies.kt @@ -5,12 +5,11 @@ object ComposeDependencies { const val compose_version = "1.6.8" const val lifecycle_viewmodel_compose_version = "2.8.2" const val compose_material3_version = "1.2.1" + const val compose_material_navigation_version = "1.7.0-beta01" } const val accompanist_systemuicontroller = "com.google.accompanist:accompanist-systemuicontroller:${Versions.accompanist_version}" - const val accompanist_nav_material = - "com.google.accompanist:accompanist-navigation-material:${Versions.accompanist_version}" const val compose_foundation = "androidx.compose.foundation:foundation:${Versions.compose_version}" @@ -21,10 +20,8 @@ object ComposeDependencies { "androidx.compose.material:material-icons-core:${Versions.compose_version}" const val compose_material_icons_extended = "androidx.compose.material:material-icons-extended:${Versions.compose_version}" - - const val compose_runtime = "androidx.compose.runtime:runtime:${Versions.compose_version}" - const val compose_runtime_livedata = - "androidx.compose.runtime:runtime-livedata:${Versions.compose_version}" + const val compose_material_navigation = + "androidx.compose.material:material-navigation:${Versions.compose_material_navigation_version}" const val compose_settings = "com.github.alorma.compose-settings:ui-tiles:${Versions.compose_settings_version}" @@ -51,7 +48,7 @@ object AndroidXDependencies { const val androidx_activity_compose_version = "1.9.0" const val androidx_appcompat_version = "1.7.0" const val androidx_browser_version = "1.8.0" - const val androidx_lifecycle_runtime_ktx_version = "2.8.2" + const val androidx_lifecycle_runtime_version = "2.8.2" const val androidx_navigation_compose_version = "2.7.7" } @@ -60,8 +57,8 @@ object AndroidXDependencies { const val androidx_appcompat = "androidx.appcompat:appcompat:${Versions.androidx_appcompat_version}" const val androidx_browser = "androidx.browser:browser:${Versions.androidx_browser_version}" - const val androidx_lifecycle_runtime_ktx = - "androidx.lifecycle:lifecycle-runtime-ktx:${Versions.androidx_lifecycle_runtime_ktx_version}" + const val androidx_lifecycle_runtime = + "androidx.lifecycle:lifecycle-runtime:${Versions.androidx_lifecycle_runtime_version}" const val androidx_navigation_compose = "androidx.navigation:navigation-compose:${Versions.androidx_navigation_compose_version}" } @@ -135,7 +132,7 @@ object NetworkDependencies { const val okhttp_bom_version = "4.12.0" const val retrofit_version = "2.11.0" const val retrofuture_version = "1.7.4" - const val sandwich_version = "1.3.9" // TODO: Upgrade to v2 + const val sandwich_version = "2.0.8" } const val moshi = "com.squareup.moshi:moshi:${Versions.moshi_version}" @@ -148,6 +145,10 @@ object NetworkDependencies { const val retrofit = "com.squareup.retrofit2:retrofit:${Versions.retrofit_version}" const val retrofuture = "net.sourceforge.streamsupport:android-retrofuture:${Versions.retrofuture_version}" const val sandwich = "com.github.skydoves:sandwich:${Versions.sandwich_version}" + const val sandwich_retrofit = + "com.github.skydoves:sandwich-retrofit:${Versions.sandwich_version}" + const val sandwich_retrofit_serialization = + "com.github.skydoves:sandwich-retrofit-serialization:${Versions.sandwich_version}" } object TestDependencies { diff --git a/navigation/build.gradle.kts b/navigation/build.gradle.kts index 0c7c10d..e466d60 100644 --- a/navigation/build.gradle.kts +++ b/navigation/build.gradle.kts @@ -2,7 +2,6 @@ plugins { id("com.android.library") kotlin("android") id("kotlin-android") -// kotlin("kapt") id("com.google.devtools.ksp") id("dagger.hilt.android.plugin") id("com.google.android.libraries.mapsplatform.secrets-gradle-plugin") @@ -24,9 +23,6 @@ dependencies { implementation(HiltDependencies.hilt) ksp(HiltDependencies.hilt_android_compiler) -// implementation(HiltDependencies.dagger_producer) - - implementation(MaterialDependencies.material_android) // Test dependencies androidTestImplementation(TestDependencies.junit) From b59ae30a7dda8bb63e03d59cb08ede79ebe4e001 Mon Sep 17 00:00:00 2001 From: Evan Strat <evan10s@users.noreply.github.com> Date: Thu, 4 Jul 2024 13:54:55 -0400 Subject: [PATCH 18/33] Remove unnecessary themes.xml files --- attendance/src/main/res/values-night/themes.xml | 16 ---------------- attendance/src/main/res/values/themes.xml | 16 ---------------- auth/src/main/res/values-night/themes.xml | 16 ---------------- auth/src/main/res/values/themes.xml | 16 ---------------- 4 files changed, 64 deletions(-) delete mode 100644 attendance/src/main/res/values-night/themes.xml delete mode 100644 attendance/src/main/res/values/themes.xml delete mode 100644 auth/src/main/res/values-night/themes.xml delete mode 100644 auth/src/main/res/values/themes.xml diff --git a/attendance/src/main/res/values-night/themes.xml b/attendance/src/main/res/values-night/themes.xml deleted file mode 100644 index f864a73..0000000 --- a/attendance/src/main/res/values-night/themes.xml +++ /dev/null @@ -1,16 +0,0 @@ -<resources xmlns:tools="http://schemas.android.com/tools"> - <!-- Base application theme. --> - <style name="Theme.Apiary_Mobile" parent="Theme.MaterialComponents.DayNight.DarkActionBar"> - <!-- Primary brand color. --> - <item name="colorPrimary">@color/purple_200</item> - <item name="colorPrimaryVariant">@color/purple_700</item> - <item name="colorOnPrimary">@color/black</item> - <!-- Secondary brand color. --> - <item name="colorSecondary">@color/teal_200</item> - <item name="colorSecondaryVariant">@color/teal_200</item> - <item name="colorOnSecondary">@color/black</item> - <!-- Status bar color. --> - <item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item> - <!-- Customize your theme here. --> - </style> -</resources> \ No newline at end of file diff --git a/attendance/src/main/res/values/themes.xml b/attendance/src/main/res/values/themes.xml deleted file mode 100644 index a17b26e..0000000 --- a/attendance/src/main/res/values/themes.xml +++ /dev/null @@ -1,16 +0,0 @@ -<resources xmlns:tools="http://schemas.android.com/tools"> - <!-- Base application theme. --> - <style name="Theme.Apiary_Mobile" parent="Theme.MaterialComponents.DayNight.DarkActionBar"> - <!-- Primary brand color. --> - <item name="colorPrimary">@color/purple_500</item> - <item name="colorPrimaryVariant">@color/purple_700</item> - <item name="colorOnPrimary">@color/white</item> - <!-- Secondary brand color. --> - <item name="colorSecondary">@color/teal_200</item> - <item name="colorSecondaryVariant">@color/teal_700</item> - <item name="colorOnSecondary">@color/black</item> - <!-- Status bar color. --> - <item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item> - <!-- Customize your theme here. --> - </style> -</resources> \ No newline at end of file diff --git a/auth/src/main/res/values-night/themes.xml b/auth/src/main/res/values-night/themes.xml deleted file mode 100644 index f864a73..0000000 --- a/auth/src/main/res/values-night/themes.xml +++ /dev/null @@ -1,16 +0,0 @@ -<resources xmlns:tools="http://schemas.android.com/tools"> - <!-- Base application theme. --> - <style name="Theme.Apiary_Mobile" parent="Theme.MaterialComponents.DayNight.DarkActionBar"> - <!-- Primary brand color. --> - <item name="colorPrimary">@color/purple_200</item> - <item name="colorPrimaryVariant">@color/purple_700</item> - <item name="colorOnPrimary">@color/black</item> - <!-- Secondary brand color. --> - <item name="colorSecondary">@color/teal_200</item> - <item name="colorSecondaryVariant">@color/teal_200</item> - <item name="colorOnSecondary">@color/black</item> - <!-- Status bar color. --> - <item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item> - <!-- Customize your theme here. --> - </style> -</resources> \ No newline at end of file diff --git a/auth/src/main/res/values/themes.xml b/auth/src/main/res/values/themes.xml deleted file mode 100644 index a17b26e..0000000 --- a/auth/src/main/res/values/themes.xml +++ /dev/null @@ -1,16 +0,0 @@ -<resources xmlns:tools="http://schemas.android.com/tools"> - <!-- Base application theme. --> - <style name="Theme.Apiary_Mobile" parent="Theme.MaterialComponents.DayNight.DarkActionBar"> - <!-- Primary brand color. --> - <item name="colorPrimary">@color/purple_500</item> - <item name="colorPrimaryVariant">@color/purple_700</item> - <item name="colorOnPrimary">@color/white</item> - <!-- Secondary brand color. --> - <item name="colorSecondary">@color/teal_200</item> - <item name="colorSecondaryVariant">@color/teal_700</item> - <item name="colorOnSecondary">@color/black</item> - <!-- Status bar color. --> - <item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item> - <!-- Customize your theme here. --> - </style> -</resources> \ No newline at end of file From 3541cbd153017faca252a0b9513e2b8d9d30a437 Mon Sep 17 00:00:00 2001 From: Evan Strat <evan10s@users.noreply.github.com> Date: Thu, 4 Jul 2024 14:16:05 -0400 Subject: [PATCH 19/33] Remove unused dependencies --- buildSrc/src/main/java/Dependencies.kt | 9 --------- 1 file changed, 9 deletions(-) diff --git a/buildSrc/src/main/java/Dependencies.kt b/buildSrc/src/main/java/Dependencies.kt index f366345..d91b0bf 100644 --- a/buildSrc/src/main/java/Dependencies.kt +++ b/buildSrc/src/main/java/Dependencies.kt @@ -34,15 +34,6 @@ object ComposeDependencies { "androidx.lifecycle:lifecycle-viewmodel-compose:${Versions.lifecycle_viewmodel_compose_version}" } -object MaterialDependencies { - object Versions { - const val material_android_version = "1.12.0" - } - - const val material_android = - "com.google.android.material:material:${Versions.material_android_version}" -} - object AndroidXDependencies { object Versions { const val androidx_activity_compose_version = "1.9.0" From bb3bf1fad537ddce4d58bdb4b2320f6f6682bb1c Mon Sep 17 00:00:00 2001 From: Evan Strat <evan10s@users.noreply.github.com> Date: Thu, 4 Jul 2024 14:18:49 -0400 Subject: [PATCH 20/33] change plugin repo order to optimize builds --- settings.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings.gradle.kts b/settings.gradle.kts index 826960a..e8742c2 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,8 +1,8 @@ pluginManagement { repositories { google() - gradlePluginPortal() mavenCentral() + gradlePluginPortal() } } From afe5c612816ea13483860dceabe171d5320caae3 Mon Sep 17 00:00:00 2001 From: Evan Strat <evan10s@users.noreply.github.com> Date: Sun, 14 Jul 2024 14:38:15 -0400 Subject: [PATCH 21/33] Add back material dependency --- app/build.gradle.kts | 2 ++ attendance/build.gradle.kts | 2 ++ auth/build.gradle.kts | 2 ++ base/build.gradle.kts | 2 ++ build.gradle.kts | 2 +- buildSrc/src/main/java/Dependencies.kt | 9 +++++++++ 6 files changed, 18 insertions(+), 1 deletion(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 46c0f8c..26e8d4c 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -45,6 +45,8 @@ dependencies { ksp(HiltDependencies.hilt_android_compiler) implementation(HiltDependencies.hilt_navigation_compose) + implementation(MaterialDependencies.material_android) + implementation(NetworkDependencies.moshi_converter_factory) implementation(NetworkDependencies.okhttp) implementation(platform(NetworkDependencies.okhttp_bom)) diff --git a/attendance/build.gradle.kts b/attendance/build.gradle.kts index a233cea..2a6a0c5 100644 --- a/attendance/build.gradle.kts +++ b/attendance/build.gradle.kts @@ -23,6 +23,8 @@ dependencies { implementation(HiltDependencies.hilt) ksp(HiltDependencies.hilt_android_compiler) + implementation(MaterialDependencies.material_android) + implementation(NetworkDependencies.moshi) ksp(NetworkDependencies.moshi_kotlin_codegen) implementation(NetworkDependencies.okhttp) diff --git a/auth/build.gradle.kts b/auth/build.gradle.kts index 0ffc5e3..ab545e9 100644 --- a/auth/build.gradle.kts +++ b/auth/build.gradle.kts @@ -35,6 +35,8 @@ dependencies { implementation(HiltDependencies.hilt) ksp(HiltDependencies.hilt_android_compiler) + implementation(MaterialDependencies.material_android) + implementation(NetworkDependencies.moshi) ksp(NetworkDependencies.moshi_kotlin_codegen) implementation(NetworkDependencies.okhttp) diff --git a/base/build.gradle.kts b/base/build.gradle.kts index 05a1ab6..81c6e58 100644 --- a/base/build.gradle.kts +++ b/base/build.gradle.kts @@ -25,6 +25,8 @@ dependencies { implementation(HiltDependencies.hilt) ksp(HiltDependencies.hilt_android_compiler) + implementation(MaterialDependencies.material_android) + implementation(NetworkDependencies.moshi) ksp(NetworkDependencies.moshi_kotlin_codegen) implementation(NetworkDependencies.retrofit) diff --git a/build.gradle.kts b/build.gradle.kts index cddc6b1..4e4923e 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -6,7 +6,7 @@ buildscript { } dependencies { classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.0") - classpath("com.android.tools.build:gradle:8.5.0") + classpath("com.android.tools.build:gradle:8.5.1") classpath("com.google.dagger:hilt-android-gradle-plugin:2.51.1") // This version needs to // match the version for other Hilt dependencies defined in Dependencies.kt classpath("com.google.android.libraries.mapsplatform.secrets-gradle-plugin:secrets-gradle-plugin:2.0.1") diff --git a/buildSrc/src/main/java/Dependencies.kt b/buildSrc/src/main/java/Dependencies.kt index d91b0bf..6ddc2fd 100644 --- a/buildSrc/src/main/java/Dependencies.kt +++ b/buildSrc/src/main/java/Dependencies.kt @@ -34,6 +34,15 @@ object ComposeDependencies { "androidx.lifecycle:lifecycle-viewmodel-compose:${Versions.lifecycle_viewmodel_compose_version}" } +object MaterialDependencies { + object Versions { + const val material_android_version = "1.6.1" + } + + const val material_android = + "com.google.android.material:material:${Versions.material_android_version}" +} + object AndroidXDependencies { object Versions { const val androidx_activity_compose_version = "1.9.0" From 7dbde523e80c65bb3073ba57aec965fa1ad2adcd Mon Sep 17 00:00:00 2001 From: Kristaps Berzinch <kristapsberzinch@gmail.com> Date: Sun, 14 Jul 2024 15:12:45 -0400 Subject: [PATCH 22/33] Add CodeQL analysis for Ruby --- .github/workflows/build.yml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index cb7f0fc..0031e77 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -46,7 +46,7 @@ jobs: - name: Initialize CodeQL uses: github/codeql-action/init@v3 with: - languages: java-kotlin + languages: java-kotlin,ruby queries: security-extended,security-and-quality - name: Grant execute permission for gradlew @@ -85,11 +85,16 @@ jobs: GOOGLE_PLAY_PRIVATE_KEY: ${{ secrets.GOOGLE_PLAY_PRIVATE_KEY }} IS_CI: true - - name: Perform CodeQL Analysis + - name: Perform CodeQL Analysis for Java/Kotlin uses: github/codeql-action/analyze@v3 with: category: "/language:java-kotlin" + - name: Perform CodeQL Analysis for Ruby + uses: github/codeql-action/analyze@v3 + with: + category: "/language:ruby" + - name: Generate and submit dependency graph uses: gradle/actions/dependency-submission@v3 From b772ac618f6705768acfa71788549f697da3c0e0 Mon Sep 17 00:00:00 2001 From: Kristaps Berzinch <kristapsberzinch@gmail.com> Date: Sun, 14 Jul 2024 15:42:03 -0400 Subject: [PATCH 23/33] Move Ruby analysis to separate workflow --- .github/workflows/build.yml | 7 +------ .github/workflows/ruby-codeql.yml | 31 +++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 6 deletions(-) create mode 100644 .github/workflows/ruby-codeql.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0031e77..c44948e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -46,7 +46,7 @@ jobs: - name: Initialize CodeQL uses: github/codeql-action/init@v3 with: - languages: java-kotlin,ruby + languages: java-kotlin queries: security-extended,security-and-quality - name: Grant execute permission for gradlew @@ -90,11 +90,6 @@ jobs: with: category: "/language:java-kotlin" - - name: Perform CodeQL Analysis for Ruby - uses: github/codeql-action/analyze@v3 - with: - category: "/language:ruby" - - name: Generate and submit dependency graph uses: gradle/actions/dependency-submission@v3 diff --git a/.github/workflows/ruby-codeql.yml b/.github/workflows/ruby-codeql.yml new file mode 100644 index 0000000..d23c9b2 --- /dev/null +++ b/.github/workflows/ruby-codeql.yml @@ -0,0 +1,31 @@ +name: CodeQL Analysis + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +jobs: + analyze: + + runs-on: ubuntu-latest + + permissions: + security-events: write + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v3 + with: + languages: ruby + build-mode: none + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v3 + with: + category: "/language:ruby" From 9638bc4c4604927d2eb0769dc78b00d1b068f896 Mon Sep 17 00:00:00 2001 From: Kristaps Berzinch <kristapsberzinch@gmail.com> Date: Sun, 14 Jul 2024 15:59:19 -0400 Subject: [PATCH 24/33] Rename job for clarity --- .github/workflows/ruby-codeql.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ruby-codeql.yml b/.github/workflows/ruby-codeql.yml index d23c9b2..1ada5ca 100644 --- a/.github/workflows/ruby-codeql.yml +++ b/.github/workflows/ruby-codeql.yml @@ -7,7 +7,7 @@ on: branches: [ "main" ] jobs: - analyze: + ruby: runs-on: ubuntu-latest From 3e5a347aace7ab8da0317e03074eb71c850118b3 Mon Sep 17 00:00:00 2001 From: Kristaps Berzinch <kristapsberzinch@gmail.com> Date: Sun, 14 Jul 2024 16:06:06 -0400 Subject: [PATCH 25/33] Remove redundant comment from Ruby CodeQL workflow --- .github/workflows/ruby-codeql.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/ruby-codeql.yml b/.github/workflows/ruby-codeql.yml index 1ada5ca..29291cc 100644 --- a/.github/workflows/ruby-codeql.yml +++ b/.github/workflows/ruby-codeql.yml @@ -18,7 +18,6 @@ jobs: - name: Checkout repository uses: actions/checkout@v4 - # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL uses: github/codeql-action/init@v3 with: From f732a951d989ae362401d42805276143f7b782c8 Mon Sep 17 00:00:00 2001 From: Kristaps Berzinch <kristapsberzinch@gmail.com> Date: Sun, 14 Jul 2024 16:07:15 -0400 Subject: [PATCH 26/33] Trim trailing whitespace in README --- README.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 5ac4b77..ca337f7 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ NFC functionality uses the NXP MIFARE TapLinx Android SDK. You must provide a l license key from the TapLinx Developer Center on https://www.mifare.net/en/products/tools/taplinx/. Additionally, important licensing information about the TapLinx library is included in the [`libs`](libs) -directory, including the [license](libs/LA_OPT_NXP_Software_License.txt) +directory, including the [license](libs/LA_OPT_NXP_Software_License.txt) and [Software Content Register](libs/Taplinx_Android_SDK_SCR.txt). **Note:** For RoboJackets developers, reach out in #apiary-mobile in Slack to obtain our keys. @@ -31,7 +31,7 @@ sentryDsn=SENTRY_DSN_HERE There are 5 modules encompassing features and utilities. - **app** - The main application module - + Note: To avoid circular dependencies, the below modules **must not** have the **app** module as a dependency. Place such code in the `base` (or a new) module. @@ -42,12 +42,12 @@ dependency. Place such code in the `base` (or a new) module. #### Dependency management -Dependency versions are managed centrally in +Dependency versions are managed centrally in [Dependencies.kt](buildSrc/src/main/java/Dependencies.kt) in the `buildSrc` module. If you change a version in `Dependencies.kt`, make sure to manually sync Gradle because Android Studio might not recognize that the change requires a Gradle sync. -After adding a dependency in `Dependencies.kt`, you must also add it to the appropriate Gradle +After adding a dependency in `Dependencies.kt`, you must also add it to the appropriate Gradle Script (take a look at a `build.gradle.kts` file for one of the modules for examples). ### Environment configuration @@ -101,7 +101,7 @@ command does, so you can get around any errors stemming from this by aliasing th to `which`. - You need to install [GitVersion](https://github.com/GitTools/GitVersion) yourself. -## Release management +## Release management Below are some instructions on the MyRoboJackets Android release process. Note that you will need additional permissions on this repo and the MyRoboJackets Android Google Play application to @@ -120,7 +120,7 @@ file is set correctly according to the table below. Use priority 1 as the defaul use priority 5, post in #apiary-mobile first. 1. Update priority affects if and how often users receive in-app update prompts to update the app to the latest version. -2. +2. | Update priority | Description | Examples | |-----------------|-------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------| @@ -132,22 +132,22 @@ app to the latest version. to determine how to increment the version number. 1. Go to https://github.com/RoboJackets/apiary-mobile/releases 2. Press the **Draft a new release** button. - 3. Decide on the new version tag; it **must** start with `v`. In general, you should increment -the previous release's version using [semantic versioning](https://semver.org/) guidelines (most + 3. Decide on the new version tag; it **must** start with `v`. In general, you should increment +the previous release's version using [semantic versioning](https://semver.org/) guidelines (most releases will be a 0.1.0 (minor) or 0.0.1 (patch) increment). Press **Choose a tag**, then enter the new tag name to create it on publish. 4. Leave **Release title** blank. Instead, press **Generate release notes**. The release title and description should automatically fill in with the changes since the last release. 1. In general, you shouldn't need to manually set the value of the `Previous tag` field, unless the release notes seem incorrect. -3. When you publish the release (which creates a new tag), a Concourse job to create a draft Google +3. When you publish the release (which creates a new tag), a Concourse job to create a draft Google Play internal test release will begin shortly. 1. If it doesn't start, a common reason is that it wasn't alphabetically the latest tag, so the [`tagged-release`](https://concourse.sandbox.aws.robojackets.net/teams/information-technology/pipelines/apiary-mobile/resources/tagged-release) resource didn't trigger a new build. We can disable old versions of the resource to trigger a new build. 4. If the Concourse [build-release job](https://concourse.sandbox.aws.robojackets.net/teams/information-technology/pipelines/apiary-mobile/jobs/build-release) -finishes successfully, you'll find a new draft release on the Internal Test track in Google Play. +finishes successfully, you'll find a new draft release on the Internal Test track in Google Play. At this point, you should do some small QA efforts to verify the new build. Post in #apiary-mobile to have some people help you test. Note that access to the internal test track must be granted via the Google Play Console. From 1b00a68070fee7f60c70513a5830553fcee055ff Mon Sep 17 00:00:00 2001 From: Evan Strat <evan10s@users.noreply.github.com> Date: Wed, 17 Jul 2024 22:14:25 -0400 Subject: [PATCH 27/33] Remove fade transitions from app navigations --- .../java/org/robojackets/apiary/MainActivity.kt | 16 +++++++++++++--- .../apiary/ui/settings/SettingsViewModel.kt | 9 +++++++-- .../apiary/navigation/NavigationDirections.kt | 6 ++++-- 3 files changed, 24 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/org/robojackets/apiary/MainActivity.kt b/app/src/main/java/org/robojackets/apiary/MainActivity.kt index b638bc0..4abb8a3 100644 --- a/app/src/main/java/org/robojackets/apiary/MainActivity.kt +++ b/app/src/main/java/org/robojackets/apiary/MainActivity.kt @@ -6,6 +6,8 @@ import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.annotation.StringRes +import androidx.compose.animation.EnterTransition +import androidx.compose.animation.ExitTransition import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.padding import androidx.compose.material.icons.Icons @@ -87,7 +89,7 @@ sealed class Screen( object Settings : Screen( - NavigationDestinations.settings, + NavigationDestinations.settingsSubgraph, R.string.settings, Icons.Filled.Settings, "settings" @@ -262,6 +264,8 @@ class MainActivity : ComponentActivity() { navController = navController, startDestination = startDestination, modifier = modifier, + enterTransition = { EnterTransition.None }, + exitTransition = { ExitTransition.None }, ) { composable(NavigationDestinations.authentication) { AuthenticationScreen(hiltViewModel(), authManager) @@ -307,9 +311,15 @@ class MainActivity : ComponentActivity() { ) } } - composable(NavigationDestinations.settings) { - SettingsScreen(hiltViewModel()) + navigation( + startDestination = NavigationDestinations.settings, + route = NavigationDestinations.settingsSubgraph, + ) { + composable(NavigationDestinations.settings) { + SettingsScreen(hiltViewModel()) + } } + composable(NavigationDestinations.requiredUpdatePrompt) { RequiredUpdatePrompt() } diff --git a/app/src/main/java/org/robojackets/apiary/ui/settings/SettingsViewModel.kt b/app/src/main/java/org/robojackets/apiary/ui/settings/SettingsViewModel.kt index e6c543e..0ce8ff0 100644 --- a/app/src/main/java/org/robojackets/apiary/ui/settings/SettingsViewModel.kt +++ b/app/src/main/java/org/robojackets/apiary/ui/settings/SettingsViewModel.kt @@ -7,12 +7,16 @@ import androidx.browser.customtabs.CustomTabsClient import androidx.browser.customtabs.CustomTabsIntent import androidx.browser.customtabs.CustomTabsServiceConnection import androidx.compose.ui.graphics.toArgb +import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.skydoves.sandwich.getOrThrow import dagger.hilt.android.lifecycle.HiltViewModel import io.sentry.Sentry -import kotlinx.coroutines.flow.* +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.catch +import kotlinx.coroutines.flow.combine import kotlinx.coroutines.launch import org.robojackets.apiary.auth.AuthStateManager import org.robojackets.apiary.auth.model.UserInfo @@ -28,6 +32,7 @@ import io.sentry.protocol.User as SentryUser @HiltViewModel class SettingsViewModel @Inject constructor( + @Suppress("UnusedPrivateMember") private val savedStateHandle: SavedStateHandle, val globalSettings: GlobalSettings, val navigationManager: NavigationManager, val serverInfoRepository: ServerInfoRepository, @@ -76,7 +81,7 @@ class SettingsViewModel @Inject constructor( ) { flows -> SettingsState( - flows[0] as UserInfo? + flows[0] ) }.catch { throwable -> throw throwable } .collect { _state.value = it } diff --git a/navigation/src/main/java/org/robojackets/apiary/navigation/NavigationDirections.kt b/navigation/src/main/java/org/robojackets/apiary/navigation/NavigationDirections.kt index 700a105..dd43110 100644 --- a/navigation/src/main/java/org/robojackets/apiary/navigation/NavigationDirections.kt +++ b/navigation/src/main/java/org/robojackets/apiary/navigation/NavigationDirections.kt @@ -5,7 +5,8 @@ import androidx.navigation.NavOptions // Based on https://proandroiddev.com/how-to-make-jetpack-compose-navigation-easier-and-testable-b4b19fd5f2e4 object NavigationDestinations { const val authentication = "authentication" - const val settings = "settings" + const val settingsSubgraph = "settings" + const val settings = "settingsMain" const val attendanceSubgraph = "attendance" const val attendableTypeSelection = "attendableTypeSelection" const val attendableSelection = "attendableSelection" @@ -20,7 +21,8 @@ object NavigationActions { fun anyScreenToAuthentication() = object : NavigationAction { override val destination = NavigationDestinations.authentication override val navOptions = NavOptions.Builder() - .setPopUpTo(0, true) +// .setPopUpTo(NavigationDestinations.authentication, true) + .setLaunchSingleTop(true) .build() } } From 8427876d2277fbaa244525bc08ec7170460030e5 Mon Sep 17 00:00:00 2001 From: Evan Strat <evan10s@users.noreply.github.com> Date: Wed, 17 Jul 2024 22:14:30 -0400 Subject: [PATCH 28/33] Update release instructions --- README.md | 44 +++++++++----------------------------------- 1 file changed, 9 insertions(+), 35 deletions(-) diff --git a/README.md b/README.md index ca337f7..8073594 100644 --- a/README.md +++ b/README.md @@ -73,12 +73,6 @@ is a helpful resource. Detekt is used for linting Kotlin code. The recommended command to run it is -_(Windows)_ -```bash -./gradlew detektAll -PdetektAutoFix=true -``` - -_(*nix)_ ```bash ./gradlew detektAll -PdetektAutoFix=true ``` @@ -87,7 +81,7 @@ The detektAutoFix parameter will automatically fix simple issues. ### Fastlane -We use Fastlane to automate steps of the Android release process, in combination with Concourse CI. +We use Fastlane to automate steps of the Android release process, in combination with Github Actions. To install Fastlane, you'll need Ruby with the development kit installed. On Windows, install the latest 64-bit version of Ruby+Devkit from https://rubyinstaller.org/downloads/. @@ -115,12 +109,11 @@ App releases don't have to perfectly coincide with PRs being merged, especially merged in close proximity. Our Concourse pipeline has jobs to automatically handle building, signing, and uploading production releases of the app. -1. After you've merged all PRs to be included in the release, ensure the `.update-priority` -file is set correctly according to the table below. Use priority 1 as the default. If you want to -use priority 5, post in #apiary-mobile first. - 1. Update priority affects if and how often users receive in-app update prompts to update the -app to the latest version. -2. +1. After you've merged all PRs to be included in the release, open the [Release to Internal Test](https://github.com/RoboJackets/apiary-mobile/actions/workflows/internal-test-release.yml) + Github Actions pipeline. +2. Find the `Run workflow` button. Use the table below to enter a value for the `update_priority`. + Update priority is an integer passed to Google Play, and it determines update nag behavior + (frequency/intensity) in the app. | Update priority | Description | Examples | |-----------------|-------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------| @@ -128,31 +121,12 @@ app to the latest version. | 3 | Optional update with prompts when the update is first available, then every 4 days. | Medium-priority bug fixes, performance improvements, new features | | 5 | Required update with immediate prompt and no option to decline. | Crashes/bugs impacting major features, urgent vulnerabilities | -2. Create a new release on `main` using a tag with a name like `v1.0.0`. Use semantic versioning -to determine how to increment the version number. - 1. Go to https://github.com/RoboJackets/apiary-mobile/releases - 2. Press the **Draft a new release** button. - 3. Decide on the new version tag; it **must** start with `v`. In general, you should increment -the previous release's version using [semantic versioning](https://semver.org/) guidelines (most -releases will be a 0.1.0 (minor) or 0.0.1 (patch) increment). Press **Choose a tag**, then enter the -new tag name to create it on publish. - 4. Leave **Release title** blank. Instead, press **Generate release notes**. The release title -and description should automatically fill in with the changes since the last release. - 1. In general, you shouldn't need to manually set the value of the `Previous tag` field, - unless the release notes seem incorrect. -3. When you publish the release (which creates a new tag), a Concourse job to create a draft Google -Play internal test release will begin shortly. - 1. If it doesn't start, a common reason is that it wasn't alphabetically the latest tag, so the - [`tagged-release`](https://concourse.sandbox.aws.robojackets.net/teams/information-technology/pipelines/apiary-mobile/resources/tagged-release) - resource didn't trigger a new build. We can disable old versions of the resource to trigger a new - build. -4. If the Concourse [build-release job](https://concourse.sandbox.aws.robojackets.net/teams/information-technology/pipelines/apiary-mobile/jobs/build-release) -finishes successfully, you'll find a new draft release on the Internal Test track in Google Play. +3. If the build runs successfully, you'll find a new draft release on the Internal Test track in Google Play. At this point, you should do some small QA efforts to verify the new build. Post in #apiary-mobile to have some people help you test. Note that access to the internal test track must be granted via the Google Play Console. 1. Internal testers may need to uninstall the app to see the update if it was recently published. -6. If no issues are found, it's time to release! Promote the build to the Production track in +4. If no issues are found, it's time to release! Promote the build to the Production track in Google Play, add release notes, and save the release. -7. Google Play typically spends a day or two reviewing the release, then makes it available. In +5. Google Play typically spends a day or two reviewing the release, then makes it available. In general, expect it to take at least ~24 hours for a production release to be available to users. \ No newline at end of file From 6acceb052cde19570b1a22c9d0c7b9b3633fe894 Mon Sep 17 00:00:00 2001 From: Evan Strat <evan10s@users.noreply.github.com> Date: Wed, 17 Jul 2024 22:19:34 -0400 Subject: [PATCH 29/33] Refactor repeated update state code --- .../apiary/ui/update/UpdateAvailable.kt | 17 ++--------- .../apiary/ui/update/UpdateGate.kt | 30 ++++++++----------- 2 files changed, 15 insertions(+), 32 deletions(-) diff --git a/app/src/main/java/org/robojackets/apiary/ui/update/UpdateAvailable.kt b/app/src/main/java/org/robojackets/apiary/ui/update/UpdateAvailable.kt index fbf2529..a1f2c0c 100644 --- a/app/src/main/java/org/robojackets/apiary/ui/update/UpdateAvailable.kt +++ b/app/src/main/java/org/robojackets/apiary/ui/update/UpdateAvailable.kt @@ -27,19 +27,12 @@ import kotlinx.coroutines.launch import org.robojackets.apiary.base.ui.icons.UpdateIcon import se.warting.inappupdate.compose.InAppUpdateState import se.warting.inappupdate.compose.Mode -import se.warting.inappupdate.compose.rememberInAppUpdateState import timber.log.Timber @Suppress("LongMethod") @Composable fun InstallUpdateButton(onIgnoreUpdate: () -> Unit = {}) { - val inAppUpdateState = rememberInAppUpdateState( - highPrioritizeUpdates = 5, - mediumPrioritizeUpdates = 3, - promptIntervalHighPrioritizeUpdateInDays = 1, - promptIntervalMediumPrioritizeUpdateInDays = 4, - promptIntervalLowPrioritizeUpdateInDays = 8, - ) + val inAppUpdateState = rememberInAppUpdateStateWithDefaults() var updateCanceled by remember { mutableStateOf(false) } val scope = rememberCoroutineScope() @@ -149,13 +142,7 @@ fun RequiredUpdatePrompt() { fun OptionalUpdatePrompt( onIgnoreUpdate: () -> Unit ) { - val inAppUpdateState = rememberInAppUpdateState( - highPrioritizeUpdates = 5, - mediumPrioritizeUpdates = 3, - promptIntervalHighPrioritizeUpdateInDays = 1, - promptIntervalMediumPrioritizeUpdateInDays = 4, - promptIntervalLowPrioritizeUpdateInDays = 8, - ) + val inAppUpdateState = rememberInAppUpdateStateWithDefaults() Column( horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center, diff --git a/app/src/main/java/org/robojackets/apiary/ui/update/UpdateGate.kt b/app/src/main/java/org/robojackets/apiary/ui/update/UpdateGate.kt index a8ed0da..9315fa9 100644 --- a/app/src/main/java/org/robojackets/apiary/ui/update/UpdateGate.kt +++ b/app/src/main/java/org/robojackets/apiary/ui/update/UpdateGate.kt @@ -7,6 +7,17 @@ import se.warting.inappupdate.compose.InAppUpdateState import se.warting.inappupdate.compose.rememberInAppUpdateState import timber.log.Timber +@Composable +fun rememberInAppUpdateStateWithDefaults(): InAppUpdateState { + return rememberInAppUpdateState( + highPrioritizeUpdates = 5, + mediumPrioritizeUpdates = 3, + promptIntervalHighPrioritizeUpdateInDays = 1, + promptIntervalMediumPrioritizeUpdateInDays = 4, + promptIntervalLowPrioritizeUpdateInDays = 8, + ) +} + @Suppress("ComplexMethod", "LongMethod") @Composable fun UpdateGate( @@ -17,15 +28,7 @@ fun UpdateGate( content: @Composable () -> Unit, ) { content() - val inAppUpdateState = rememberInAppUpdateState( - highPrioritizeUpdates = 5, - mediumPrioritizeUpdates = 3, - promptIntervalHighPrioritizeUpdateInDays = 1, - promptIntervalMediumPrioritizeUpdateInDays = 4, - promptIntervalLowPrioritizeUpdateInDays = 8, - ) - - when (inAppUpdateState) { + when (val inAppUpdateState = rememberInAppUpdateStateWithDefaults()) { is InAppUpdateState.DownloadedUpdate -> { if (inAppUpdateState.isRequiredUpdate) { LaunchedEffect(navReady) { @@ -86,14 +89,7 @@ fun UpdateGate( @Composable fun UpdateStatus() { - val inAppUpdateState = rememberInAppUpdateState( - highPrioritizeUpdates = 5, - mediumPrioritizeUpdates = 3, - promptIntervalHighPrioritizeUpdateInDays = 1, - promptIntervalMediumPrioritizeUpdateInDays = 4, - promptIntervalLowPrioritizeUpdateInDays = 8, - ) - when (inAppUpdateState) { + when (val inAppUpdateState = rememberInAppUpdateStateWithDefaults()) { is InAppUpdateState.DownloadedUpdate -> { if (inAppUpdateState.isRequiredUpdate) { Text("Downloaded > required") From 04a5f9cd69d875f26b1ebf3b4d01b3bc69e98e5b Mon Sep 17 00:00:00 2001 From: Evan Strat <evan10s@users.noreply.github.com> Date: Wed, 17 Jul 2024 23:09:01 -0400 Subject: [PATCH 30/33] Fix bug where optional update bottom sheet background didn't match dark theme --- .../apiary/ui/update/UpdateAvailable.kt | 52 ++++++++++--------- 1 file changed, 28 insertions(+), 24 deletions(-) diff --git a/app/src/main/java/org/robojackets/apiary/ui/update/UpdateAvailable.kt b/app/src/main/java/org/robojackets/apiary/ui/update/UpdateAvailable.kt index a1f2c0c..e8afabd 100644 --- a/app/src/main/java/org/robojackets/apiary/ui/update/UpdateAvailable.kt +++ b/app/src/main/java/org/robojackets/apiary/ui/update/UpdateAvailable.kt @@ -10,6 +10,7 @@ import androidx.compose.material3.AlertDialog import androidx.compose.material3.Button import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable @@ -143,31 +144,34 @@ fun OptionalUpdatePrompt( onIgnoreUpdate: () -> Unit ) { val inAppUpdateState = rememberInAppUpdateStateWithDefaults() - Column( - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.Center, - modifier = Modifier.fillMaxHeight(.5F), - ) { - UpdateIcon( - Modifier - .padding(bottom = 9.dp) - .size(72.dp) - ) - Text("Update available", style = MaterialTheme.typography.headlineSmall) - Text( - "Install the latest version of MyRoboJackets for the latest features and " + - "bug fixes. It'll only take a minute.", - textAlign = TextAlign.Center, - modifier = Modifier.padding(20.dp) - ) - InstallUpdateButton(onIgnoreUpdate) - TextButton(onClick = { - if (inAppUpdateState is InAppUpdateState.OptionalUpdate) { - inAppUpdateState.onDeclineUpdate() + Surface { + Column( + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center, + modifier = Modifier.fillMaxHeight(.5F), + ) { + UpdateIcon( + Modifier + .padding(bottom = 9.dp) + .size(72.dp) + ) + Text("Update available", style = MaterialTheme.typography.headlineSmall) + Text( + "Install the latest version of MyRoboJackets for the latest features and " + + "bug fixes. It'll only take a minute.", + textAlign = TextAlign.Center, + modifier = Modifier.padding(20.dp) + ) + InstallUpdateButton(onIgnoreUpdate) + TextButton(onClick = { + Timber.w("DEBUG: Optional update declined. $inAppUpdateState") + if (inAppUpdateState is InAppUpdateState.OptionalUpdate) { + inAppUpdateState.onDeclineUpdate() + } + onIgnoreUpdate() + }) { + Text("Not now") } - onIgnoreUpdate() - }) { - Text("Not now") } } } From 54709679497a198177d47b9ce2a7f1b1d606e5ff Mon Sep 17 00:00:00 2001 From: Evan Strat <evan10s@users.noreply.github.com> Date: Wed, 17 Jul 2024 23:09:14 -0400 Subject: [PATCH 31/33] Fix copy spacing --- .../org/robojackets/apiary/ui/update/UpdateGate.kt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/org/robojackets/apiary/ui/update/UpdateGate.kt b/app/src/main/java/org/robojackets/apiary/ui/update/UpdateGate.kt index 9315fa9..aa4978e 100644 --- a/app/src/main/java/org/robojackets/apiary/ui/update/UpdateGate.kt +++ b/app/src/main/java/org/robojackets/apiary/ui/update/UpdateGate.kt @@ -117,18 +117,18 @@ fun UpdateStatus() { is InAppUpdateState.OptionalUpdate -> { Text( "Optional update | Should prompt: ${inAppUpdateState.shouldPrompt} " + - "| Priority: ${inAppUpdateState.appUpdateInfo.priority}" + - "| Staleness: ${inAppUpdateState.appUpdateInfo.staleDays}" + - "| Version code: ${inAppUpdateState.appUpdateInfo.versionCode}" + " | Priority: ${inAppUpdateState.appUpdateInfo.priority}" + + " | Staleness: ${inAppUpdateState.appUpdateInfo.staleDays}" + + " | Version code: ${inAppUpdateState.appUpdateInfo.versionCode}" ) } is InAppUpdateState.RequiredUpdate -> { Text( "Required update | Should prompt: ${inAppUpdateState.shouldPrompt} " + - "| Priority: ${inAppUpdateState.appUpdateInfo.priority}" + - "| Staleness: ${inAppUpdateState.appUpdateInfo.staleDays}" + - "| Version code: ${inAppUpdateState.appUpdateInfo.versionCode}" + " | Priority: ${inAppUpdateState.appUpdateInfo.priority}" + + " | Staleness: ${inAppUpdateState.appUpdateInfo.staleDays}" + + " | Version code: ${inAppUpdateState.appUpdateInfo.versionCode}" ) } From 08496901f33984b03ace281edc6c234701a85190 Mon Sep 17 00:00:00 2001 From: Evan Strat <evan10s@users.noreply.github.com> Date: Wed, 17 Jul 2024 23:09:28 -0400 Subject: [PATCH 32/33] Add debug buttons in settings to test update screens --- .../apiary/ui/settings/Settings.kt | 40 ++++++++++++++++++- .../apiary/ui/settings/SettingsViewModel.kt | 12 ++++++ 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/org/robojackets/apiary/ui/settings/Settings.kt b/app/src/main/java/org/robojackets/apiary/ui/settings/Settings.kt index 9e8b3ec..7bda8ca 100644 --- a/app/src/main/java/org/robojackets/apiary/ui/settings/Settings.kt +++ b/app/src/main/java/org/robojackets/apiary/ui/settings/Settings.kt @@ -9,7 +9,15 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.outlined.* +import androidx.compose.material.icons.outlined.Build +import androidx.compose.material.icons.outlined.Feedback +import androidx.compose.material.icons.outlined.Home +import androidx.compose.material.icons.outlined.Info +import androidx.compose.material.icons.outlined.Logout +import androidx.compose.material.icons.outlined.Person +import androidx.compose.material.icons.outlined.PrivacyTip +import androidx.compose.material.icons.outlined.Update +import androidx.compose.material.icons.outlined.VerifiedUser import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text @@ -41,6 +49,9 @@ private fun Settings( onOpenPrivacyPolicy: () -> Unit, onOpenMakeAWish: () -> Unit, onRefreshUser: () -> Unit, + onNavigateToOptionalUpdateBottomSheet: () -> Unit, + onNavigateToRequiredUpdatePrompt: () -> Unit, + onNavigateToUpdateInProgress: () -> Unit, ) { val context = LocalContext.current @@ -66,6 +77,21 @@ private fun Settings( subtitle = { Text(text = user?.allPermissions?.joinToString(separator = ", ") ?: "None") }, onClick = { onRefreshUser() } ) + SettingsMenuLink( + icon = { Icon(Icons.Outlined.Update, contentDescription = "update") }, + title = { Text(text = "DEBUG: Open optional update bottom sheet") }, + onClick = { onNavigateToOptionalUpdateBottomSheet() } + ) + SettingsMenuLink( + icon = { Icon(Icons.Outlined.Update, contentDescription = "update") }, + title = { Text(text = "DEBUG: Open required update prompt") }, + onClick = { onNavigateToRequiredUpdatePrompt() } + ) + SettingsMenuLink( + icon = { Icon(Icons.Outlined.Update, contentDescription = "update") }, + title = { Text(text = "DEBUG: Open update in progress screen") }, + onClick = { onNavigateToUpdateInProgress() } + ) } SettingsMenuLink( icon = { Icon(Icons.Outlined.Logout, contentDescription = "logout") }, @@ -165,6 +191,15 @@ fun SettingsScreen( }, onRefreshUser = { viewModel.getUser(forceRefresh = true) + }, + onNavigateToOptionalUpdateBottomSheet = { + viewModel.navigateToOptionalUpdateBottomSheet() + }, + onNavigateToRequiredUpdatePrompt = { + viewModel.navigateToRequiredUpdatePrompt() + }, + onNavigateToUpdateInProgress = { + viewModel.navigateToUpdateInProgress() } ) } @@ -181,5 +216,8 @@ private fun SettingsPreview() { onOpenPrivacyPolicy = {}, onOpenMakeAWish = {}, onRefreshUser = {}, + onNavigateToOptionalUpdateBottomSheet = {}, + onNavigateToRequiredUpdatePrompt = {}, + onNavigateToUpdateInProgress = {}, ) } diff --git a/app/src/main/java/org/robojackets/apiary/ui/settings/SettingsViewModel.kt b/app/src/main/java/org/robojackets/apiary/ui/settings/SettingsViewModel.kt index 0ce8ff0..d3202ea 100644 --- a/app/src/main/java/org/robojackets/apiary/ui/settings/SettingsViewModel.kt +++ b/app/src/main/java/org/robojackets/apiary/ui/settings/SettingsViewModel.kt @@ -98,6 +98,18 @@ class SettingsViewModel @Inject constructor( navigateToLogin() } + fun navigateToOptionalUpdateBottomSheet() { + navigationManager.navigate(NavigationActions.UpdatePrompts.anyScreenToOptionalUpdatePrompt()) + } + + fun navigateToRequiredUpdatePrompt() { + navigationManager.navigate(NavigationActions.UpdatePrompts.anyScreenToRequiredUpdatePrompt()) + } + + fun navigateToUpdateInProgress() { + navigationManager.navigate(NavigationActions.UpdatePrompts.anyScreenToUpdateInProgress()) + } + fun getCustomTabsIntent(toolbarColor: Int = webNavBarBackground.toArgb()): CustomTabsIntent { val customTabsBuilder = CustomTabsIntent.Builder() From ed920eb423bbd5a8db1057c52723e065f725aa27 Mon Sep 17 00:00:00 2001 From: Evan Strat <evan10s@users.noreply.github.com> Date: Wed, 17 Jul 2024 23:09:49 -0400 Subject: [PATCH 33/33] revert version code change --- app/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 26e8d4c..a3dcadf 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -79,7 +79,7 @@ android { applicationId = "org.robojackets.apiary" minSdk = 21 targetSdk = 35 - versionCode = 21 + versionCode = 12 versionName = "1.0.0" vectorDrawables { useSupportLibrary = true