Move shared code to new gradle module

This commit is contained in:
William Brawner 2020-07-22 19:04:11 -07:00
parent 573503a318
commit c1cf8d724f
38 changed files with 181 additions and 108 deletions

View file

@ -11,6 +11,7 @@
<set>
<option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/app" />
<option value="$PROJECT_DIR$/shared" />
<option value="$PROJECT_DIR$/wear" />
</set>
</option>

View file

@ -44,12 +44,9 @@ android {
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation project(':shared')
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.5'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.5'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-reactive:1.3.5'
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.core:core-ktx:1.2.0'
@ -58,12 +55,7 @@ dependencies {
implementation 'com.google.android.material:material:1.2.0-alpha05'
implementation 'androidx.recyclerview:recyclerview:1.1.0'
def room_version = "2.2.5"
implementation "androidx.room:room-runtime:$room_version"
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
kapt "androidx.room:room-compiler:$room_version"
implementation "androidx.room:room-ktx:$room_version"
testImplementation "androidx.room:room-testing:$room_version"
def nav_version = "2.2.1"
implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"

View file

@ -10,19 +10,6 @@
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name=".ItemListActivity"
android:label="@string/title_item_list"
android:theme="@style/AppTheme.NoActionBar"></activity>
<activity
android:name=".ItemDetailActivity"
android:label="@string/title_item_detail"
android:parentActivityName=".ItemListActivity"
android:theme="@style/AppTheme.NoActionBar">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="com.wbrawner.trainterval.ItemListActivity" />
</activity>
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

View file

@ -9,6 +9,9 @@ import android.widget.NumberPicker
import androidx.annotation.AttrRes
import androidx.annotation.StyleRes
import androidx.core.math.MathUtils
import com.wbrawner.trainterval.shared.IntervalDuration
import com.wbrawner.trainterval.shared.toIntervalDuration
import com.wbrawner.trainterval.shared.toMillis
import java.util.concurrent.TimeUnit
private const val MIN_DURATION = 0L
@ -21,11 +24,13 @@ class DurationPicker @JvmOverloads constructor(
@StyleRes defStyleRes: Int = 0
) : FrameLayout(context, attrs, defStyleAttr, defStyleRes) {
private var intervalDuration = IntervalDuration()
private var intervalDuration =
IntervalDuration()
var duration: Long
get() = intervalDuration.toMillis()
set(value) {
intervalDuration = MathUtils.clamp(value, MIN_DURATION, MAX_DURATION).toIntervalDuration()
intervalDuration =
MathUtils.clamp(value, MIN_DURATION, MAX_DURATION).toIntervalDuration()
hours.value = intervalDuration.hours.toInt()
minutes.value = intervalDuration.minutes.toInt()
seconds.value = intervalDuration.seconds.toInt()

View file

@ -2,6 +2,7 @@ package com.wbrawner.trainterval
import android.app.Application
import androidx.room.Room
import com.wbrawner.trainterval.shared.TraintervalDatabase
import com.wbrawner.trainterval.timerform.TimerFormViewModel
import com.wbrawner.trainterval.timerlist.TimerListViewModel
import org.koin.android.ext.koin.androidContext

View file

@ -16,8 +16,9 @@ import androidx.lifecycle.viewModelScope
import androidx.navigation.fragment.findNavController
import com.wbrawner.trainterval.Logger
import com.wbrawner.trainterval.R
import com.wbrawner.trainterval.model.IntervalTimerDao
import com.wbrawner.trainterval.model.Phase
import com.wbrawner.trainterval.shared.IntervalTimerDao
import com.wbrawner.trainterval.shared.IntervalTimerState
import com.wbrawner.trainterval.shared.Phase
import kotlinx.android.synthetic.main.fragment_active_timer.*
import kotlinx.coroutines.*
import org.koin.android.ext.android.inject
@ -78,9 +79,9 @@ class ActiveTimerFragment : Fragment() {
coroutineScope!!.launch {
activeTimerViewModel.timerState.observe(viewLifecycleOwner, Observer { state ->
when (state) {
is IntervalTimerActiveState.LoadingState -> renderLoading()
is IntervalTimerActiveState.TimerRunningState -> renderTimer(state)
is IntervalTimerActiveState.ExitState -> findNavController().navigateUp()
is IntervalTimerState.LoadingState -> renderLoading()
is IntervalTimerState.TimerRunningState -> renderTimer(state)
is IntervalTimerState.ExitState -> findNavController().navigateUp()
}
})
activeTimerViewModel.init(logger, timerDao, timerId)
@ -103,7 +104,7 @@ class ActiveTimerFragment : Fragment() {
}
}
private fun renderTimer(state: IntervalTimerActiveState.TimerRunningState) {
private fun renderTimer(state: IntervalTimerState.TimerRunningState) {
progressBar.visibility = View.GONE
timerLayout.referencedIds.forEach {
view?.findViewById<View>(it)?.visibility = View.VISIBLE

View file

@ -1,26 +1,22 @@
package com.wbrawner.trainterval.activetimer
import androidx.annotation.ColorRes
import androidx.annotation.DrawableRes
import androidx.annotation.StringRes
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.wbrawner.trainterval.Logger
import com.wbrawner.trainterval.R
import com.wbrawner.trainterval.activetimer.IntervalTimerActiveState.LoadingState
import com.wbrawner.trainterval.activetimer.IntervalTimerActiveState.TimerRunningState
import com.wbrawner.trainterval.model.IntervalTimer
import com.wbrawner.trainterval.model.IntervalTimerDao
import com.wbrawner.trainterval.model.Phase
import com.wbrawner.trainterval.toIntervalDuration
import com.wbrawner.trainterval.shared.IntervalTimer
import com.wbrawner.trainterval.shared.IntervalTimerDao
import com.wbrawner.trainterval.shared.IntervalTimerState
import com.wbrawner.trainterval.shared.IntervalTimerState.LoadingState
import com.wbrawner.trainterval.shared.IntervalTimerState.TimerRunningState
import com.wbrawner.trainterval.shared.Phase
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
class ActiveTimerViewModel : ViewModel() {
val timerState: MutableLiveData<IntervalTimerActiveState> = MutableLiveData(LoadingState)
val timerState: MutableLiveData<IntervalTimerState> = MutableLiveData(LoadingState)
private var timerJob: Job? = null
private lateinit var timer: IntervalTimer
private lateinit var logger: Logger
@ -201,42 +197,3 @@ class ActiveTimerViewModel : ViewModel() {
}
}
}
/**
* Used to represent the state while a user has a specific timer open.
*/
sealed class IntervalTimerActiveState {
object LoadingState : IntervalTimerActiveState()
class TimerRunningState(
val timerName: String,
val timeRemaining: String,
val currentSet: Int,
val currentRound: Int,
val soundId: Int?,
@StringRes val phase: Int,
@ColorRes val timerBackground: Int,
@DrawableRes val playPauseIcon: Int
) : IntervalTimerActiveState() {
constructor(
timer: IntervalTimer,
timeRemaining: Long,
currentSet: Int,
currentRound: Int,
phase: Phase,
timerRunning: Boolean
) : this(
timerName = timer.name,
phase = phase.stringRes,
timeRemaining = timeRemaining.toIntervalDuration().toString(),
currentSet = currentSet,
currentRound = currentRound,
timerBackground = phase.colorRes,
soundId = if (timerRunning && timeRemaining == timer.durationForPhase(phase))
phase.ordinal
else null,
playPauseIcon = if (timerRunning) R.drawable.ic_pause else R.drawable.ic_play_arrow
)
}
object ExitState : IntervalTimerActiveState()
}

View file

@ -10,7 +10,7 @@ import androidx.fragment.app.Fragment
import androidx.lifecycle.Observer
import androidx.navigation.fragment.findNavController
import com.wbrawner.trainterval.R
import com.wbrawner.trainterval.model.IntervalTimer
import com.wbrawner.trainterval.shared.IntervalTimer
import com.wbrawner.trainterval.timerform.IntervalTimerEditState.*
import kotlinx.android.synthetic.main.fragment_timer_form.*
import kotlinx.coroutines.CoroutineScope

View file

@ -3,8 +3,8 @@ package com.wbrawner.trainterval.timerform
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import com.wbrawner.trainterval.Logger
import com.wbrawner.trainterval.model.IntervalTimer
import com.wbrawner.trainterval.model.IntervalTimerDao
import com.wbrawner.trainterval.shared.IntervalTimer
import com.wbrawner.trainterval.shared.IntervalTimerDao
import com.wbrawner.trainterval.timerform.IntervalTimerEditState.*
class TimerFormViewModel(

View file

@ -8,8 +8,8 @@ import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import com.wbrawner.trainterval.R
import com.wbrawner.trainterval.model.IntervalTimer
import com.wbrawner.trainterval.toIntervalDuration
import com.wbrawner.trainterval.shared.IntervalTimer
import com.wbrawner.trainterval.shared.toIntervalDuration
class TimerListAdapter(
private val timerListViewModel: TimerListViewModel

View file

@ -12,7 +12,7 @@ import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.LinearLayoutManager
import com.wbrawner.trainterval.R
import com.wbrawner.trainterval.model.IntervalTimer
import com.wbrawner.trainterval.shared.IntervalTimer
import com.wbrawner.trainterval.timerlist.IntervalTimerListState.*
import kotlinx.android.synthetic.main.fragment_timer_list.*
import org.koin.android.ext.android.inject

View file

@ -3,8 +3,8 @@ package com.wbrawner.trainterval.timerlist
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import com.wbrawner.trainterval.Logger
import com.wbrawner.trainterval.model.IntervalTimer
import com.wbrawner.trainterval.model.IntervalTimerDao
import com.wbrawner.trainterval.shared.IntervalTimer
import com.wbrawner.trainterval.shared.IntervalTimerDao
import com.wbrawner.trainterval.timerlist.IntervalTimerListState.*
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.flow.collect

View file

@ -1,5 +1,4 @@
<resources>
<string name="app_name">Trainterval</string>
<string name="timer_name">Timer Name</string>
<string name="timer_description">Timer Description</string>
<string name="low_intensity_duration">Low Intensity Duration</string>
@ -16,11 +15,6 @@
<string name="skip_next">Skip Next</string>
<string name="start_timer">Start Timer</string>
<string name="rest_duration">Rest Duration</string>
<string name="phase_warm_up">Warm Up</string>
<string name="phase_low_intensity">Low Intensity</string>
<string name="phase_high_intensity">High Intensity</string>
<string name="phase_rest">Rest</string>
<string name="phase_cool_down">Cool Down</string>
<string name="title_item_list">Items</string>
<string name="title_item_detail">Item Detail</string>
<string name="timer_sets_formatted">Set: %1$d/%2$d</string>

View file

@ -1,7 +1,8 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
ext.kotlin_version = '1.3.70'
ext.kotlin_version = '1.3.72'
ext.room_version = '2.2.5'
repositories {
google()
jcenter()
@ -20,7 +21,6 @@ allprojects {
repositories {
google()
jcenter()
}
}

View file

@ -1,2 +1,3 @@
include ':shared'
rootProject.name='Interval Timer'
include ':app', ':wear'

1
shared/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
/build

43
shared/build.gradle Normal file
View file

@ -0,0 +1,43 @@
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'
android {
compileSdkVersion 30
buildToolsVersion "30.0.1"
defaultConfig {
minSdkVersion 23
targetSdkVersion 30
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles "consumer-rules.pro"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: "libs", include: ["*.jar"])
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
api 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.5'
api 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.5'
api 'org.jetbrains.kotlinx:kotlinx-coroutines-reactive:1.3.5'
implementation 'androidx.core:core-ktx:1.3.1'
implementation 'androidx.appcompat:appcompat:1.1.0'
kapt "androidx.room:room-compiler:$room_version"
implementation "androidx.room:room-ktx:$room_version"
testImplementation "androidx.room:room-testing:$room_version"
api "androidx.room:room-runtime:$room_version"
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
}

View file

21
shared/proguard-rules.pro vendored Normal file
View file

@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile

View file

@ -0,0 +1,4 @@
<manifest package="com.wbrawner.trainterval.shared">
/
</manifest>

View file

@ -1,4 +1,4 @@
package com.wbrawner.trainterval
package com.wbrawner.trainterval.shared
import java.util.concurrent.TimeUnit
@ -42,5 +42,9 @@ fun Long.toIntervalDuration(): IntervalDuration {
seconds -= minutes * SECONDS_IN_MINUTE
}
return IntervalDuration(hours, minutes, seconds)
return IntervalDuration(
hours,
minutes,
seconds
)
}

View file

@ -1,9 +1,8 @@
package com.wbrawner.trainterval.model
package com.wbrawner.trainterval.shared
import androidx.annotation.ColorRes
import androidx.annotation.StringRes
import androidx.room.*
import com.wbrawner.trainterval.R
import kotlinx.coroutines.flow.Flow
import java.util.concurrent.TimeUnit

View file

@ -0,0 +1,44 @@
package com.wbrawner.trainterval.shared
import androidx.annotation.ColorRes
import androidx.annotation.DrawableRes
import androidx.annotation.StringRes
/**
* Used to represent the state while a user has a specific timer open.
*/
sealed class IntervalTimerState {
object LoadingState : IntervalTimerState()
class TimerRunningState(
val timerName: String,
val timeRemaining: String,
val currentSet: Int,
val currentRound: Int,
val soundId: Int?,
@StringRes val phase: Int,
@ColorRes val timerBackground: Int,
@DrawableRes val playPauseIcon: Int
) : IntervalTimerState() {
constructor(
timer: IntervalTimer,
timeRemaining: Long,
currentSet: Int,
currentRound: Int,
phase: Phase,
timerRunning: Boolean
) : this(
timerName = timer.name,
phase = phase.stringRes,
timeRemaining = timeRemaining.toIntervalDuration().toString(),
currentSet = currentSet,
currentRound = currentRound,
timerBackground = phase.colorRes,
soundId = if (timerRunning && timeRemaining == timer.durationForPhase(phase))
phase.ordinal
else null,
playPauseIcon = if (timerRunning) R.drawable.ic_pause else R.drawable.ic_play_arrow
)
}
object ExitState : IntervalTimerState()
}

View file

@ -1,9 +1,7 @@
package com.wbrawner.trainterval
package com.wbrawner.trainterval.shared
import androidx.room.Database
import androidx.room.RoomDatabase
import com.wbrawner.trainterval.model.IntervalTimer
import com.wbrawner.trainterval.model.IntervalTimerDao
@Database(entities = [IntervalTimer::class], version = 1)
abstract class TraintervalDatabase : RoomDatabase() {

View file

@ -0,0 +1,8 @@
<resources>
<string name="app_name">Trainterval</string>
<string name="phase_warm_up">Warm Up</string>
<string name="phase_low_intensity">Low Intensity</string>
<string name="phase_high_intensity">High Intensity</string>
<string name="phase_rest">Rest</string>
<string name="phase_cool_down">Cool Down</string>
</resources>

View file

@ -25,10 +25,11 @@ android {
}
dependencies {
implementation fileTree(dir: "libs", include: ["*.jar"])
implementation project(':shared')
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation 'androidx.wear:wear:1.0.0'
implementation 'com.google.android.support:wearable:2.7.0'
implementation 'com.google.android.gms:play-services-wearable:17.0.0'
compileOnly 'com.google.android.wearable:wearable:2.7.0'
testImplementation 'junit:junit:4.12'
}

View file

@ -2,12 +2,26 @@ package com.wbrawner.trainterval.wear
import android.os.Bundle
import android.support.wearable.activity.WearableActivity
import com.google.android.gms.wearable.DataClient
import com.google.android.gms.wearable.DataEventBuffer
import com.google.android.gms.wearable.Wearable
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : WearableActivity() {
class MainActivity : WearableActivity(), DataClient.OnDataChangedListener {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
textView.text = "Hello, Wear OS!"
}
override fun onResume() {
super.onResume()
Wearable.getDataClient(this).addListener(this)
}
override fun onDataChanged(dataEvents: DataEventBuffer) {
dataEvents.forEach { event ->
event.type
}
}
}

View file

@ -1,3 +0,0 @@
<resources>
<string name="app_name">Trainterval</string>
</resources>