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

Convert into a KMM module #121

Merged
merged 5 commits into from
Nov 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
88 changes: 47 additions & 41 deletions .github/workflows/android.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,64 +10,70 @@ jobs:
Build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: set up JDK 17
uses: actions/setup-java@v2
with:
java-version: '17'
distribution: 'adopt'
cache: gradle

- uses: actions/cache@v3
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
restore-keys: |
${{ runner.os }}-gradle-


- name: Make gradle wrapper executable
run: chmod +x gradlew

- name: Build with Gradle
run: ./gradlew build
- uses: actions/checkout@v4
- name: set up JDK 17
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'zulu'
cache: gradle

- name: Setup Gradle
uses: gradle/actions/setup-gradle@v4

- name: Make gradle wrapper executable
run: chmod +x gradlew

- name: Build with Gradle
run: ./gradlew build

Automation:
needs: Build
runs-on: ubuntu-latest
needs: build
steps:
- name: checkout
uses: actions/checkout@v4

- name: set up JDK 15
uses: actions/setup-java@v2
- name: set up JDK 17
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'adopt'
distribution: 'zulu'
cache: gradle

- uses: actions/cache@v3
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
restore-keys: |
${{ runner.os }}-gradle-


- name: Enable KVM
run: |
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
sudo udevadm control --reload-rules
sudo udevadm trigger --name-match=kvm

- name: Run UI Tests
- name: Gradle cache
uses: gradle/actions/setup-gradle@v3

- name: AVD cache
uses: actions/cache@v4
id: avd-cache
with:
path: |
~/.android/avd/*
~/.android/adb*
key: avd-29

- name: Create AVD and generate snapshot for caching
if: steps.avd-cache.outputs.cache-hit != 'true'
uses: reactivecircus/android-emulator-runner@v2
with:
api-level: 29
force-avd-creation: false
emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
disable-animations: false
script: echo "Generated AVD snapshot for caching."

- name: run tests
uses: reactivecircus/android-emulator-runner@v2
with:
api-level: 29
ndk: 21.0.6113669
cmake: 3.10.2.4988404
script: ./gradlew app:connectedCheck
force-avd-creation: false
emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
disable-animations: true
script: ./gradlew app:connectedCheck && killall -INT crashpad_handler || true
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -77,3 +77,4 @@ lint/generated/
lint/outputs/
lint/tmp/
# lint/reports/
.kotlin
10 changes: 3 additions & 7 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ android {

defaultConfig {
applicationId = "com.foreverrafs.datepickertimeline"
minSdk = 26
minSdk = 28
targetSdk = 35
versionCode = 1
versionName = "0.7.1"
Expand All @@ -22,11 +22,7 @@ android {
isMinifyEnabled = true
isShrinkResources = true
proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro")
}

getByName("debug") {
isMinifyEnabled = false
isDebuggable = true
signingConfig = signingConfigs.getByName("debug")
}
}

Expand All @@ -52,7 +48,6 @@ android {
compose = true
}


packaging {
resources {
excludes +=
Expand Down Expand Up @@ -91,6 +86,7 @@ dependencies {
// UI Tests
androidTestImplementation(libs.compose.ui.test.unit)
androidTestImplementation(libs.compose.ui.test.junit)
implementation(libs.kotlin.datetime)

implementation("com.godaddy.android.colorpicker:compose-color-picker-android:0.7.0")
debugImplementation(libs.compose.ui.test.manifest)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,26 @@ import androidx.compose.ui.platform.testTag
import com.foreverrafs.datepicker.DatePickerTimeline
import com.foreverrafs.datepicker.state.DatePickerState
import com.foreverrafs.datepicker.state.rememberDatePickerState
import kotlinx.datetime.Clock
import kotlinx.datetime.DateTimeUnit
import kotlinx.datetime.LocalDate
import kotlinx.datetime.TimeZone
import kotlinx.datetime.format.FormatStringsInDatetimeFormats
import kotlinx.datetime.format.byUnicodePattern
import kotlinx.datetime.minus
import kotlinx.datetime.todayIn
import org.junit.Test
import java.time.LocalDate
import java.time.format.DateTimeFormatter

/**
* Instrumented test, which will execute on an Android device.
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
@OptIn(FormatStringsInDatetimeFormats::class)
internal class DatePickerTimelineTests : BaseTest() {
private val dateFormatter = DateTimeFormatter.ofPattern("dd/MM/yyyy")
private val dateFormatter = LocalDate.Format {
byUnicodePattern("dd/MM/yyyy")
}

@Composable
fun TestDatePickerContent(
Expand Down Expand Up @@ -51,7 +60,7 @@ internal class DatePickerTimelineTests : BaseTest() {
@Test
fun verifyTimeLineAppearsCorrectly() {
var state: DatePickerState?
val initialDate = LocalDate.of(2020, 5, 12)
val initialDate = LocalDate(2020, 5, 12)

setContent {
state = rememberDatePickerState(initialDate)
Expand All @@ -60,7 +69,7 @@ internal class DatePickerTimelineTests : BaseTest() {
TestDatePickerContent(state = state, onButtonClicked = {
// Move to 20th June, 2020
state.smoothScrollToDate(
LocalDate.of(2020, 6, 20),
LocalDate(2020, 6, 20),
)
})
}
Expand All @@ -79,13 +88,13 @@ internal class DatePickerTimelineTests : BaseTest() {
setContent {
TestDatePickerContent(
state = rememberDatePickerState(
initialDate = LocalDate.now(),
initialDate = Clock.System.todayIn(TimeZone.UTC),
),
)
}

datePickerTimeLineRobot {
val today = dateFormatter.format(LocalDate.now())
val today = dateFormatter.format(Clock.System.todayIn(TimeZone.UTC))
// Given today's date
verifyDateIsDisplayed(date = today)

Expand All @@ -110,7 +119,7 @@ internal class DatePickerTimelineTests : BaseTest() {
state =
rememberDatePickerState(
initialDate =
LocalDate.of(
LocalDate(
2021,
5,
12,
Expand All @@ -133,7 +142,11 @@ internal class DatePickerTimelineTests : BaseTest() {
performClickOnNodeWithText(text = "Today")

// Verify that today's date comes into view
verifyDateIsDisplayed(date = dateFormatter.format(LocalDate.now()))
verifyDateIsDisplayed(
date = dateFormatter.format(
Clock.System.todayIn(TimeZone.UTC),
),
)
}
}

Expand All @@ -142,21 +155,21 @@ internal class DatePickerTimelineTests : BaseTest() {
var state: DatePickerState? = null

setContent {
state = rememberDatePickerState(initialDate = LocalDate.of(2021, 12, 12))
state = rememberDatePickerState(initialDate = LocalDate(2021, 12, 12))

TestDatePickerContent(state = state!!, pastDaysCount = 180)
}
datePickerTimeLineRobot {
// Programmatically change state to another date
state?.smoothScrollToDate(LocalDate.of(2022, 5, 12))
state?.smoothScrollToDate(LocalDate(2022, 5, 12))
verifyDateIsDisplayed(date = "12/05/2022")
}
}

@Test
fun verifyInvalidPastDateSelectsFirstDate() {
var state: DatePickerState? = null
val initialDate = LocalDate.of(2021, 12, 12)
val initialDate = LocalDate(2021, 12, 12)
val pastDaysCount = 10

setContent {
Expand All @@ -167,9 +180,9 @@ internal class DatePickerTimelineTests : BaseTest() {

datePickerTimeLineRobot {
// Scroll to an invalid date
state?.smoothScrollToDate(LocalDate.of(2017, 1, 1))
state?.smoothScrollToDate(LocalDate(2017, 1, 1))

val requiredDate = initialDate.minusDays(pastDaysCount.toLong())
val requiredDate = initialDate.minus(pastDaysCount.toLong(), DateTimeUnit.DAY)

verifyDateIsDisplayed(date = dateFormatter.format(requiredDate))
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
@file:OptIn(FormatStringsInDatetimeFormats::class)

package com.foreverrafs.datepickertimeline

import android.os.Bundle
Expand Down Expand Up @@ -38,8 +40,14 @@ import com.foreverrafs.datepickertimeline.ui.theme.DatepickertimelineTheme
import com.foreverrafs.datepickertimeline.ui.theme.Purple500
import com.godaddy.android.colorpicker.ClassicColorPicker
import com.godaddy.android.colorpicker.HsvColor
import java.time.LocalDate
import java.time.format.DateTimeFormatter
import kotlinx.datetime.Clock
import kotlinx.datetime.DateTimeUnit
import kotlinx.datetime.LocalDate
import kotlinx.datetime.TimeZone
import kotlinx.datetime.format.FormatStringsInDatetimeFormats
import kotlinx.datetime.format.byUnicodePattern
import kotlinx.datetime.plus
import kotlinx.datetime.todayIn
import kotlin.random.Random

class MainActivity : ComponentActivity() {
Expand Down Expand Up @@ -68,7 +76,7 @@ fun App() {
.fillMaxSize(),
) {
val datePickerState =
rememberDatePickerState(initialDate = LocalDate.of(2021, 5, 12))
rememberDatePickerState(initialDate = kotlinx.datetime.LocalDate(2021, 5, 12))

var mainBackgroundColor by remember { mutableStateOf(Purple500) }
var selectedDateBackgroundColor by remember {
Expand All @@ -78,7 +86,7 @@ fun App() {
mutableStateOf(Color.Black.copy(alpha = 0.35f))
}
var dateTextColor by remember { mutableStateOf(Color.White) }
val today = LocalDate.now()
val today = Clock.System.todayIn(TimeZone.currentSystemDefault())

DatePickerTimeline(
modifier = Modifier.wrapContentSize(),
Expand All @@ -91,10 +99,10 @@ fun App() {
dateTextColor = dateTextColor,
eventDates =
listOf(
today.plusDays(1),
today.plusDays(3),
today.plusDays(5),
today.plusDays(8),
today.plus(1, DateTimeUnit.DAY),
today.plus(3, DateTimeUnit.DAY),
today.plus(5, DateTimeUnit.DAY),
today.plus(8, DateTimeUnit.DAY),
),
todayLabel = {
Text(
Expand Down Expand Up @@ -168,7 +176,7 @@ fun App() {
.clip(RoundedCornerShape(8.dp)),
onClick = {
datePickerState.smoothScrollToDate(
LocalDate.now().plusDays(Random.nextLong(until = 50)),
today.plus(Random.nextLong(until = 50), DateTimeUnit.DAY),
)
},
) {
Expand All @@ -178,10 +186,9 @@ fun App() {
Text(
modifier = Modifier.fillMaxWidth(),
textAlign = TextAlign.Center,
text =
DateTimeFormatter
.ofPattern("MMMM dd, yyyy")
.format(datePickerState.selectedDate),
text = LocalDate.Format {
byUnicodePattern("MM dd, yyyy")
}.format(datePickerState.selectedDate),
style = MaterialTheme.typography.h6,
)
}
Expand Down
1 change: 1 addition & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ plugins {
alias(libs.plugins.android.application) apply false
alias(libs.plugins.kotlin.android) apply false
alias(libs.plugins.detekt) apply false
alias(libs.plugins.kotlin.multiplatform) apply false
alias(libs.plugins.compose.compiler) apply false
}

Expand Down
Loading