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

Fix part of #4: Introduce domain module #64

Merged
merged 10 commits into from
Aug 23, 2019
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
/.idea/navEditor.xml
/.idea/assetWizardSettings.xml
app/build
domain/build
model/build
utility/build
.DS_Store
Expand Down
10 changes: 10 additions & 0 deletions .idea/codeStyles/Project.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions .idea/gradle.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

110 changes: 58 additions & 52 deletions app/build.gradle
Original file line number Diff line number Diff line change
@@ -1,65 +1,71 @@
apply plugin: 'com.android.application'

apply plugin: 'kotlin-android'

apply plugin: 'kotlin-android-extensions'

android {
compileSdkVersion 29
buildToolsVersion "29.0.1"
defaultConfig {
applicationId "org.oppia.app"
minSdkVersion 16
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
compileSdkVersion 29
buildToolsVersion "29.0.1"
defaultConfig {
applicationId "org.oppia.app"
minSdkVersion 16
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
testOptions {
unitTests {
includeAndroidResources = true
}
}
dataBinding {
enabled = true
}
testOptions {
unitTests {
includeAndroidResources = true
}
}

// https://proandroiddev.com/isolated-fragments-unit-tests-that-run-both-instrumented-and-on-the-jvm-with-the-same-source-code-283db2e9be5d
sourceSets {
androidTest {
java.srcDirs += "src/sharedTest/java"
kotlin.srcDirs += "src/sharedTest/java"
}
test {
java.srcDirs += "src/sharedTest/java"
kotlin.srcDirs += "src/sharedTest/java"
}
// https://proandroiddev.com/isolated-fragments-unit-tests-that-run-both-instrumented-and-on-the-jvm-with-the-same-source-code-283db2e9be5d
sourceSets {
androidTest {
java.srcDirs += "src/sharedTest/java"
kotlin.srcDirs += "src/sharedTest/java"
}
test {
java.srcDirs += "src/sharedTest/java"
kotlin.srcDirs += "src/sharedTest/java"
}
}
}

dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'androidx.appcompat:appcompat:1.0.2'
implementation 'androidx.core:core-ktx:1.0.2'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
api 'com.google.guava:guava:28.0-android'

testImplementation 'androidx.test:core:1.2.0'
testImplementation 'androidx.test.ext:junit:1.1.1'
testImplementation 'org.robolectric:robolectric:4.3'
testImplementation "com.google.truth:truth:0.43"
testImplementation 'androidx.test.espresso:espresso-core:3.2.0'

androidTestImplementation 'androidx.test:core:1.2.0'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test:runner:1.2.0'
androidTestImplementation "com.google.truth:truth:0.43"
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'

implementation project(":model")
implementation project(":utility")
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation(
'android.arch.lifecycle:extensions:1.1.1',
'androidx.appcompat:appcompat:1.0.2',
'androidx.constraintlayout:constraintlayout:1.1.3',
'androidx.core:core-ktx:1.0.2',
'androidx.lifecycle:lifecycle-runtime-ktx:2.2.0-alpha03',
"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version",
)
testImplementation(
'androidx.test:core:1.2.0',
'androidx.test.espresso:espresso-core:3.2.0',
'androidx.test.ext:junit:1.1.1',
'com.google.truth:truth:0.43',
'org.robolectric:robolectric:4.3',
)
androidTestImplementation(
'androidx.test:core:1.2.0',
'androidx.test.espresso:espresso-core:3.2.0',
'androidx.test.ext:junit:1.1.1',
'androidx.test:runner:1.2.0',
'com.google.truth:truth:0.43',
)
implementation project(":model")
implementation project(":domain")
implementation project(":utility")
}
42 changes: 2 additions & 40 deletions app/src/main/java/org/oppia/app/HomeActivity.kt
Original file line number Diff line number Diff line change
@@ -1,52 +1,14 @@
package org.oppia.app

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.widget.TextView
import com.google.common.util.concurrent.FutureCallback
import com.google.common.util.concurrent.Futures
import com.google.common.util.concurrent.ListenableFuture
import com.google.common.util.concurrent.MoreExecutors.directExecutor
import org.oppia.app.model.UserAppHistory
import org.oppia.util.data.AsyncDataSource
import androidx.appcompat.app.AppCompatActivity

/** The central activity for all users entering the app. */
class HomeActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.home_activity)
}

override fun onStart() {
super.onStart()
// TODO(BenHenning): Convert this to LiveData rather than risk an async operation completing outside of the
// activity's lifecycle. Also, a directExecutor() in this context could be a really bad idea if it isn't the main
// thread.
Futures.addCallback(getUserAppHistory().pendingOperation, object: FutureCallback<UserAppHistory> {
override fun onSuccess(result: UserAppHistory?) {
if (result != null && result.alreadyOpenedApp) {
getWelcomeTextView().setText(R.string.welcome_back_text)
}
}

override fun onFailure(t: Throwable) {
// TODO(BenHenning): Replace this log statement with a clearer logging API.
Log.e("HomeActivity", "Failed to retrieve user app history", t)
}
}, directExecutor())
}

private fun getWelcomeTextView(): TextView {
return findViewById(R.id.welcome_text_view)
}

private fun getUserAppHistory(): AsyncDataSource<UserAppHistory> {
// TODO(BenHenning): Retrieve this from a domain provider.
return object: AsyncDataSource<UserAppHistory> {
override val pendingOperation: ListenableFuture<UserAppHistory>
get() = Futures.immediateFuture(UserAppHistory.newBuilder().setAlreadyOpenedApp(false).build())
}
supportFragmentManager.beginTransaction().add(R.id.home_fragment_placeholder, HomeFragment()).commitNow()
}
}
55 changes: 55 additions & 0 deletions app/src/main/java/org/oppia/app/HomeFragment.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package org.oppia.app

import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.lifecycle.LiveData
import androidx.lifecycle.Transformations
import androidx.lifecycle.ViewModelProviders
import org.oppia.app.databinding.HomeFragmentBinding
import org.oppia.app.model.UserAppHistory
import org.oppia.domain.UserAppHistoryController
import org.oppia.util.data.AsyncResult

/** Fragment that contains an introduction to the app. */
class HomeFragment : Fragment() {
private val userAppHistoryController = UserAppHistoryController()

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val binding = HomeFragmentBinding.inflate(inflater, container, /* attachToRoot= */ false)
val viewModel = getUserAppHistoryViewModel()
val appUserHistory = getUserAppHistory()
viewModel.userAppHistoryLiveData = appUserHistory
// NB: Both the view model and lifecycle owner must be set in order to correctly bind LiveData elements to
// data-bound view models.
binding.let {
it.viewModel = viewModel
it.lifecycleOwner = this
}

// TODO(#70): Mark that the user opened the app once it's persisted to disk.

return binding.root
}

private fun getUserAppHistoryViewModel(): UserAppHistoryViewModel {
return ViewModelProviders.of(this).get(UserAppHistoryViewModel::class.java)
}

private fun getUserAppHistory(): LiveData<UserAppHistory> {
// If there's an error loading the data, assume the default.
return Transformations.map(
userAppHistoryController.getUserAppHistory()
) { result: AsyncResult<UserAppHistory> -> processUserAppHistoryResult(result) }
}

private fun processUserAppHistoryResult(appHistoryResult: AsyncResult<UserAppHistory>): UserAppHistory {
if (appHistoryResult.isFailure()) {
Log.e("HomeFragment", "Failed to retrieve user app history", appHistoryResult.error)
}
return appHistoryResult.getOrDefault(UserAppHistory.getDefaultInstance())
}
}
10 changes: 10 additions & 0 deletions app/src/main/java/org/oppia/app/UserAppHistoryViewModel.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package org.oppia.app

import androidx.lifecycle.LiveData
import androidx.lifecycle.ViewModel
import org.oppia.app.model.UserAppHistory

/** [ViewModel] for user app usage history. */
class UserAppHistoryViewModel: ViewModel() {
var userAppHistoryLiveData: LiveData<UserAppHistory>? = null
}
18 changes: 3 additions & 15 deletions app/src/main/res/layout/home_activity.xml
Original file line number Diff line number Diff line change
@@ -1,20 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/home_fragment_placeholder"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".HomeActivity">

<TextView
android:id="@+id/welcome_text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/welcome_text"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>
tools:context=".HomeActivity" />
28 changes: 28 additions & 0 deletions app/src/main/res/layout/home_fragment.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<layout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">

<data>
<import type="org.oppia.app.R"/>
<variable
name="viewModel"
type="org.oppia.app.UserAppHistoryViewModel"/>
</data>

<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">

<TextView
android:id="@+id/welcome_text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{viewModel.userAppHistoryLiveData.getAlreadyOpenedApp() ? R.string.welcome_back_text : R.string.welcome_text}"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"/>

</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
34 changes: 17 additions & 17 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,27 +1,27 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
ext.kotlin_version = '1.3.41'
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.4.2'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.10'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
ext.kotlin_version = '1.3.41'
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.4.2'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.10'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}

allprojects {
repositories {
google()
jcenter()
}
repositories {
google()
jcenter()
}
}

task clean(type: Delete) {
delete rootProject.buildDir
delete rootProject.buildDir
}
Loading