Skip to content

Commit fef67bb

Browse files
committed
Add spotless with ktlint and ktfmt
1 parent 161405d commit fef67bb

File tree

376 files changed

+7802
-7663
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

376 files changed

+7802
-7663
lines changed

.editorconfig

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
[*.{kt,kts}]
2+
# Compose allows PascalCase for @Composable functions
3+
ktlint_standard_function-naming = disabled
4+
# Enforce no wildcard imports
5+
ktlint_standard_no-wildcard-imports = enabled
6+
# Filename should match class name is not always desired
7+
ktlint_standard_filename = disabled
8+
# Backing properties naming can be different
9+
ktlint_standard_backing-property-naming = disabled

.gitattributes

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1+
* text=auto eol=lf
12
**/snapshots/**/*.png filter=lfs diff=lfs merge=lfs -text

.github/workflows/pr-check.yml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,22 @@ on:
55
branches: [ "**" ]
66

77
jobs:
8+
spotless:
9+
runs-on: ubuntu-latest
10+
steps:
11+
- uses: actions/checkout@v4
12+
- name: Set up JDK 17
13+
uses: actions/setup-java@v4
14+
with:
15+
java-version: '17'
16+
distribution: 'temurin'
17+
- name: Setup Gradle
18+
uses: gradle/actions/setup-gradle@v4
19+
- name: Grant execute permission for gradlew
20+
run: chmod +x gradlew
21+
- name: Run Spotless Check
22+
run: ./gradlew spotlessCheck
23+
824
lint:
925
runs-on: ubuntu-latest
1026
environment: staging

README.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,26 @@
5353
* [Kotlin Multiplatform](https://kotlinlang.org/docs/multiplatform.html)
5454
* Native Android/iOS View and ViewModel layer
5555

56+
### Code Quality & Formatting
57+
58+
We use **Spotless** to maintain a consistent code style across the project. It integrates two main tools:
59+
- **ktfmt (Google Style):** A deterministic formatter that ensures all Kotlin code follows a unified structure.
60+
- **ktlint:** A linter that enforces additional best practices and code smells (e.g., forbidding wildcard imports).
61+
62+
#### Formatting Commands
63+
- **Check formatting:** `./gradlew spotlessCheck`
64+
- **Apply formatting:** `./gradlew spotlessApply`
65+
66+
#### Git Hooks
67+
To ensure code is formatted before every commit, we use a pre-commit hook. You can install it by running:
68+
```bash
69+
./scripts/install-git-hooks.sh
70+
```
71+
This hook will automatically run `spotlessApply` and stage any formatting changes whenever you commit.
72+
73+
#### CI Integration
74+
Formatting is automatically verified on every Pull Request via GitHub Actions.
75+
5676
<!-- GETTING STARTED -->
5777

5878
## 📖 Getting Started

android/app-newm/build.gradle.kts

Lines changed: 25 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ import java.text.SimpleDateFormat
22
import java.util.Date
33

44
apply(from = "../../gradle_include/compose.gradle")
5+
56
apply(from = "../../gradle_include/circuit.gradle")
7+
68
apply(from = "../../gradle_include/flipper.gradle")
79

810
plugins {
@@ -15,7 +17,6 @@ plugins {
1517
alias(libs.plugins.compose.multiplatform)
1618
}
1719

18-
1920
android {
2021
compileSdk = libs.versions.android.compileSdk.get().toInt()
2122
ndkVersion = "27.0.12077973"
@@ -32,18 +33,14 @@ android {
3233
testApplicationId = "io.newm.test"
3334
}
3435

35-
lint {
36-
baseline = file("lint-baseline.xml")
37-
}
36+
lint { baseline = file("lint-baseline.xml") }
3837

3938
packaging {
4039
resources {
4140
merges += "META-INF/LICENSE.md"
4241
merges += "META-INF/LICENSE-notice.md"
4342
}
44-
jniLibs {
45-
useLegacyPackaging = true
46-
}
43+
jniLibs { useLegacyPackaging = true }
4744
}
4845

4946
buildTypes {
@@ -53,7 +50,7 @@ android {
5350
isMinifyEnabled = false
5451
proguardFiles(
5552
getDefaultProguardFile("proguard-android-optimize.txt"),
56-
"proguard-rules.pro"
53+
"proguard-rules.pro",
5754
)
5855
}
5956
debug {
@@ -80,28 +77,23 @@ android {
8077
resValue(
8178
"string",
8279
"account_type",
83-
"$applicationId${applicationIdSuffix.orEmpty()}.account"
80+
"$applicationId${applicationIdSuffix.orEmpty()}.account",
8481
)
8582
}
8683
}
8784

88-
buildFeatures {
89-
buildConfig = true
90-
}
85+
buildFeatures { buildConfig = true }
9186

9287
compileOptions {
9388
sourceCompatibility = JavaVersion.VERSION_11
9489
targetCompatibility = JavaVersion.VERSION_11
9590
isCoreLibraryDesugaringEnabled = true
9691
}
9792

98-
kapt {
99-
correctErrorTypes = true
100-
}
93+
kapt { correctErrorTypes = true }
10194
}
10295

10396
dependencies {
104-
10597
implementation(libs.process.phoenix)
10698
coreLibraryDesugaring(libs.desugar.jdk.libs)
10799
implementation(libs.androidx.core.ktx)
@@ -123,15 +115,15 @@ dependencies {
123115
implementation(libs.cmp.image.pick.n.crop)
124116
implementation(platform(libs.firebase.bom))
125117
implementation(libs.androidx.material.icons.extended)
126-
implementation(project(Modules.barcodeScanner))
127-
implementation(project(Modules.coreAndroidImplementations))
128-
implementation(project(Modules.coreResources))
129-
implementation(project(Modules.coreTheme))
130-
implementation(project(Modules.coreUiUtils))
131-
implementation(project(Modules.login))
132-
implementation(project(Modules.musicPlayer))
133-
implementation(project(Modules.shared))
134-
implementation(project(Modules.sharedComposeFeatures))
118+
implementation(project(Modules.BARCODE_SCANNER))
119+
implementation(project(Modules.CORE_ANDROID_IMPLEMENTATIONS))
120+
implementation(project(Modules.CORE_RESOURCES))
121+
implementation(project(Modules.CORE_THEME))
122+
implementation(project(Modules.CORE_UI_UTILS))
123+
implementation(project(Modules.LOGIN))
124+
implementation(project(Modules.MUSIC_PLAYER))
125+
implementation(project(Modules.SHARED))
126+
implementation(project(Modules.SHARED_COMPOSE_FEATURES))
135127

136128
testImplementation(libs.junit)
137129
testImplementation(libs.mockk)
@@ -141,11 +133,7 @@ dependencies {
141133
androidTestImplementation(libs.mockk.android)
142134
}
143135

144-
kotlin {
145-
compilerOptions {
146-
jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_11)
147-
}
148-
}
136+
kotlin { compilerOptions { jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_11) } }
149137

150138
sentry {
151139
org.set("project-newm")
@@ -157,7 +145,6 @@ sentry {
157145
telemetry.set(true)
158146
}
159147

160-
161148
/**
162149
* Generates a version code based on the current date and time in the format `yyMMddHH`.
163150
*
@@ -167,8 +154,8 @@ sentry {
167154
* - `dd`: The current day of the month.
168155
* - `HH`: The current hour (24-hour format).
169156
*
170-
* The function formats the current date and time using `SimpleDateFormat`,
171-
* converts it into a string, and then parses it as an integer.
157+
* The function formats the current date and time using `SimpleDateFormat`, converts it into a
158+
* string, and then parses it as an integer.
172159
*
173160
* @return An integer representing the current date and time in the format `yyMMddHH`.
174161
*/
@@ -178,7 +165,8 @@ fun getCurrentDateTimeVersionCode(): Int {
178165
}
179166

180167
/**
181-
* Generates a custom version name based on the provided major version and the current date and time.
168+
* Generates a custom version name based on the provided major version and the current date and
169+
* time.
182170
*
183171
* The version name follows the format: `major.yyMMdd.HHmm`, where:
184172
* - `major`: The major version number passed as a parameter.
@@ -187,7 +175,8 @@ fun getCurrentDateTimeVersionCode(): Int {
187175
* - `HH`: The current hour in 24-hour format.
188176
* - `mm`: The current minute.
189177
*
190-
* The function retrieves the current date and time using `SimpleDateFormat` to format each component.
178+
* The function retrieves the current date and time using `SimpleDateFormat` to format each
179+
* component.
191180
*
192181
* Example output for `major = 1` on October 1st, 2024 at 13:45 would be: `1.241001.1345`.
193182
*
@@ -206,4 +195,4 @@ fun getCustomVersionName(major: Int): String {
206195
val minute = minuteFormat.format(Date())
207196

208197
return "$major.$year$monthDay.$hour$minute"
209-
}
198+
}

android/app-newm/src/debug/java/io/newm/DebugNewmApplication.kt

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,24 +6,25 @@ import com.facebook.flipper.plugins.databases.DatabasesFlipperPlugin
66
import com.facebook.flipper.plugins.inspector.DescriptorMapping
77
import com.facebook.flipper.plugins.inspector.InspectorFlipperPlugin
88
import com.facebook.flipper.plugins.navigation.NavigationFlipperPlugin
9-
import com.facebook.flipper.plugins.sharedpreferences.SharedPreferencesFlipperPlugin
109
import com.facebook.soloader.SoLoader
1110

1211
class DebugNewmApplication : NewmApplication() {
1312
override fun onCreate() {
1413
SoLoader.init(this, false)
15-
AndroidFlipperClient.getInstance(this).apply {
16-
addPlugin(
17-
InspectorFlipperPlugin(
18-
this@DebugNewmApplication,
19-
DescriptorMapping.withDefaults()
14+
AndroidFlipperClient
15+
.getInstance(this)
16+
.apply {
17+
addPlugin(
18+
InspectorFlipperPlugin(
19+
this@DebugNewmApplication,
20+
DescriptorMapping.withDefaults(),
21+
),
2022
)
21-
)
22-
addPlugin(CrashReporterPlugin.getInstance())
23-
addPlugin(DatabasesFlipperPlugin(this@DebugNewmApplication))
24-
addPlugin(NavigationFlipperPlugin.getInstance())
25-
}.start()
23+
addPlugin(CrashReporterPlugin.getInstance())
24+
addPlugin(DatabasesFlipperPlugin(this@DebugNewmApplication))
25+
addPlugin(NavigationFlipperPlugin.getInstance())
26+
}.start()
2627

2728
super.onCreate()
2829
}
29-
}
30+
}

android/app-newm/src/main/java/io/newm/AppLaunchGhostActivity.kt

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,16 +28,15 @@ class AppLaunchGhostActivity : ComponentActivity() {
2828
@OptIn(FlowPreview::class)
2929
override fun onCreate(savedInstanceState: Bundle?) {
3030
super.onCreate(savedInstanceState)
31-
installSplashScreen().apply {
32-
setKeepOnScreenCondition { true }
33-
}
31+
installSplashScreen().apply { setKeepOnScreenCondition { true } }
3432

3533
lifecycleScope.launch {
3634
val isLoggedIn = userSession.isLoggedIn()
3735

3836
if (isLoggedIn) {
3937
try {
40-
userDetailsUseCase.fetchLoggedInUserDetailsFlow()
38+
userDetailsUseCase
39+
.fetchLoggedInUserDetailsFlow()
4140
.filterNotNull()
4241
.onEach(featureFlagMager::identifyUser)
4342
.timeout(3.seconds)
@@ -46,7 +45,7 @@ class AppLaunchGhostActivity : ComponentActivity() {
4645
logger.error(
4746
tag,
4847
"Failed to identify feature flag because fetching user details failed.",
49-
e
48+
e,
5049
)
5150
} finally {
5251
launchHomeActivity()

0 commit comments

Comments
 (0)