Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Android TLC: 2023 edition (with 2024 goodies) #65

Merged
merged 34 commits into from
Jul 18, 2024
Merged
Show file tree
Hide file tree
Changes from 27 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
60e64f5
Target SDK 33
evan10s May 25, 2023
18e0b49
Update dependency versions
evan10s May 25, 2023
3f9a8d9
First pass at M3 update
evan10s Aug 20, 2023
54edda1
add app launch todo
evan10s Aug 20, 2023
f56d5e0
Remainder of M3 upgrade
evan10s Aug 20, 2023
b7eb39c
Dependency updates
evan10s Aug 20, 2023
9d1cc96
Cleanup M3 upgrade todos
evan10s Aug 20, 2023
ad28be1
Use android-build-box 1.25 for Java 17 support
evan10s Aug 20, 2023
cdfa2c5
Update detekt config to remove deprecated rules
evan10s Sep 1, 2023
9f3ee8d
Update detekt plugin version
evan10s Sep 1, 2023
0f7e086
Update comment
evan10s Sep 1, 2023
bddb438
Style fixes
evan10s Sep 1, 2023
38e3cf8
Merge branch 'refs/heads/main' into evan/m3
evan10s Jun 19, 2024
eb537cd
Use Java 17
evan10s Jun 20, 2024
59b9e96
Update dependencies and finish M3 upgrade
evan10s Jun 20, 2024
f65fd28
Fix ruby lock file?
evan10s Jun 21, 2024
e14cb27
In-app update cleanup, update Hilt version, move from kapt to ksp
evan10s Jun 23, 2024
91ec7bb
Final fixes
evan10s Jul 4, 2024
b59ae30
Remove unnecessary themes.xml files
evan10s Jul 4, 2024
3541cbd
Remove unused dependencies
evan10s Jul 4, 2024
bb3bf1f
change plugin repo order to optimize builds
evan10s Jul 4, 2024
afe5c61
Add back material dependency
evan10s Jul 14, 2024
7dbde52
Add CodeQL analysis for Ruby
kberzinch Jul 14, 2024
b772ac6
Move Ruby analysis to separate workflow
kberzinch Jul 14, 2024
9638bc4
Rename job for clarity
kberzinch Jul 14, 2024
3e5a347
Remove redundant comment from Ruby CodeQL workflow
kberzinch Jul 14, 2024
f732a95
Trim trailing whitespace in README
kberzinch Jul 14, 2024
1b00a68
Remove fade transitions from app navigations
evan10s Jul 18, 2024
8427876
Update release instructions
evan10s Jul 18, 2024
6acceb0
Refactor repeated update state code
evan10s Jul 18, 2024
04a5f9c
Fix bug where optional update bottom sheet background didn't match da…
evan10s Jul 18, 2024
5470967
Fix copy spacing
evan10s Jul 18, 2024
0849690
Add debug buttons in settings to test update screens
evan10s Jul 18, 2024
ed920eb
revert version code change
evan10s Jul 18, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -85,7 +85,7 @@ 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"
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/internal-test-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
30 changes: 30 additions & 0 deletions .github/workflows/ruby-codeql.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: CodeQL Analysis

on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]

jobs:
ruby:

runs-on: ubuntu-latest

permissions:
security-events: write

steps:
- name: Checkout repository
uses: actions/checkout@v4

- 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"
32 changes: 16 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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.

Expand All @@ -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
Expand Down Expand Up @@ -116,38 +116,38 @@ 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.
evan10s marked this conversation as resolved.
Show resolved Hide resolved

| 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.
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.
Expand Down
30 changes: 17 additions & 13 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ plugins {
id("com.android.application")
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")
Expand Down Expand Up @@ -31,30 +31,33 @@ 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)
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)
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))
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_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
Expand All @@ -71,12 +74,12 @@ android {
create("release") {
}
}
compileSdk = 32
compileSdk = 35
defaultConfig {
applicationId = "org.robojackets.apiary"
minSdk = 21
targetSdk = 32
versionCode = 12
targetSdk = 35
versionCode = 21
versionName = "1.0.0"
vectorDrawables {
useSupportLibrary = true
Expand All @@ -90,17 +93,18 @@ android {
}
buildFeatures {
compose = true
buildConfig = 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.5.1"
}
namespace = "org.robojackets.apiary"
hilt {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down
55 changes: 35 additions & 20 deletions app/src/main/java/org/robojackets/apiary/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,27 +8,41 @@
import androidx.annotation.StringRes
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.padding
import androidx.compose.material.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Settings
import androidx.compose.material.icons.outlined.Contactless
import androidx.compose.runtime.*
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
import androidx.compose.material3.NavigationBarItem
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
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 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 androidx.navigation.navArgument
import androidx.navigation.navigation
import androidx.navigation.plusAssign
import com.nxp.nfclib.NxpNfcLib
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.flow.launchIn
Expand All @@ -55,6 +69,8 @@
import timber.log.Timber
import javax.inject.Inject

// TODO: see if we can make app launch screen match light/dark mode?
evan10s marked this conversation as resolved.
Show resolved Hide resolved

sealed class Screen(
val navigationDestination: String,
@StringRes val resourceId: Int,
Expand Down Expand Up @@ -115,8 +131,6 @@
nfcLib.registerActivity(this, BuildConfig.taplinxKey, BuildConfig.taplinxOfflineKey)
}

@OptIn(ExperimentalMaterialNavigationApi::class)
@ExperimentalMaterialApi
@Suppress("LongMethod")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Expand All @@ -137,7 +151,7 @@

setContent {
Apiary_MobileTheme {
window.statusBarColor = MaterialTheme.colors.primaryVariant.toArgb()
window.statusBarColor = MaterialTheme.colorScheme.secondary.toArgb()
kberzinch marked this conversation as resolved.
Dismissed
Show resolved Hide resolved
val navController = rememberNavController()
val bottomSheetNavigator = rememberBottomSheetNavigator()
navController.navigatorProvider += bottomSheetNavigator
Expand All @@ -155,7 +169,7 @@
}

// 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,
Expand All @@ -180,9 +194,9 @@
bottomBar = {
val current = currentRoute(navController)
if (shouldShowBottomNav(nfcEnabled, current)) {
BottomNavigation {
NavigationBar {
navItems.forEach { screen ->
BottomNavigationItem(
NavigationBarItem(
icon = {
Icon(
screen.icon,
Expand Down Expand Up @@ -232,16 +246,17 @@
currentScreen != NavigationDestinations.updateInProgress

@Suppress("LongMethod")
@OptIn(ExperimentalMaterialNavigationApi::class)
@ExperimentalMaterialApi
@Composable
private fun AppNavigation(
navController: NavHostController,
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,
Expand All @@ -266,7 +281,7 @@
navArgument("attendableType") { type = NavType.StringType }
),
) {
val attendableType = it.arguments?.get("attendableType")
val attendableType = it.arguments?.getString("attendableType")

AttendableSelectionScreen(
hiltViewModel(),
Expand All @@ -281,8 +296,8 @@
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(),
Expand Down
Loading
Loading