Skip to content

Commit

Permalink
Merge pull request #2 from hiranthaR/development
Browse files Browse the repository at this point in the history
login interface
  • Loading branch information
hiranthaR authored Feb 21, 2020
2 parents b4718a2 + 26685b7 commit 0a3bf03
Show file tree
Hide file tree
Showing 27 changed files with 405 additions and 12 deletions.
5 changes: 4 additions & 1 deletion mobile/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,13 @@ android {

dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.core:core-ktx:1.1.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation 'androidx.lifecycle:lifecycle-extensions:2.0.0'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.0.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,19 @@ import android.app.Application
import lk.eclk.locationservice.data.Repository
import lk.eclk.locationservice.data.RepositoryImpl
import lk.eclk.locationservice.data.db.AppDatabase
import lk.eclk.locationservice.data.proviers.JWTProvider
import lk.eclk.locationservice.data.proviers.JWTProviderImpl
import lk.eclk.locationservice.data.remote.ConnectivityInterceptor
import lk.eclk.locationservice.data.remote.ConnectivityInterceptorImpl
import lk.eclk.locationservice.data.remote.api.LocationServiceApiService
import lk.eclk.locationservice.ui.signin.SignInViewModelFactory
import lk.eclk.locationservice.ui.splash.SplashScreenViewModelFactory
import org.kodein.di.Kodein
import org.kodein.di.KodeinAware
import org.kodein.di.android.x.androidXModule
import org.kodein.di.generic.bind
import org.kodein.di.generic.instance
import org.kodein.di.generic.provider
import org.kodein.di.generic.singleton


Expand All @@ -26,6 +31,9 @@ class LocationServiceApplication : Application(), KodeinAware {
//database
bind() from singleton { AppDatabase(instance()) }

//providers
bind<JWTProvider>() with singleton { JWTProviderImpl(instance()) }

bind<ConnectivityInterceptor>() with singleton {
ConnectivityInterceptorImpl(
instance()
Expand All @@ -36,7 +44,10 @@ class LocationServiceApplication : Application(), KodeinAware {
bind() from singleton { LocationServiceApiService(instance()) }

//Repository
bind<Repository>() with singleton { RepositoryImpl() }
bind<Repository>() with singleton { RepositoryImpl(instance()) }

//view model factories
bind() from provider { SplashScreenViewModelFactory(instance()) }
bind() from provider { SignInViewModelFactory(instance()) }
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package lk.eclk.locationservice.data

import androidx.lifecycle.LiveData
import lk.eclk.locationservice.internal.AuthState

interface Repository {

//repository for handle all data flows inside the android app
fun getAuthState(): LiveData<AuthState>
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,28 @@
package lk.eclk.locationservice.data

class RepositoryImpl() : Repository {}
import androidx.lifecycle.LiveData
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import lk.eclk.locationservice.data.proviers.JWTProvider
import lk.eclk.locationservice.internal.AuthState

class RepositoryImpl(
private val jwtProvider: JWTProvider
) : Repository {

init {
jwtProvider.apply {
authState.observeForever {
GlobalScope.launch(Dispatchers.IO) {
// there should handle auth state's data
// eg: fetching user data
}
}
}
}

override fun getAuthState(): LiveData<AuthState> = jwtProvider.authState


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package lk.eclk.locationservice.data.proviers

import androidx.lifecycle.LiveData
import lk.eclk.locationservice.internal.AuthState

interface JWTProvider {
val authState: LiveData<AuthState>
fun getJWT(): String?
fun setJWT(token: String): Boolean
fun unsetJWT(): Boolean
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package lk.eclk.locationservice.data.proviers

import android.content.Context
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import lk.eclk.locationservice.internal.AuthState

private const val JWT_TOKEN = "jwt_token"

class JWTProviderImpl(context: Context) : PreferenceProvider(context), JWTProvider {

// any view model can observe auth state using this live data
override val authState: LiveData<AuthState> get() = _authState
private val _authState by lazy { MutableLiveData<AuthState>() }

init {
setAuthState(getJWT())
}

override fun getJWT(): String? {
return preference.getString(JWT_TOKEN, null)
}

override fun setJWT(token: String): Boolean {
setAuthState(token)
return preference.edit().putString(JWT_TOKEN, token).commit()
}

override fun unsetJWT(): Boolean {
setAuthState(null)
return preference.edit().remove(JWT_TOKEN).commit()
}

private fun setAuthState(jwt: String?) {
if (jwt.isNullOrEmpty()) _authState.postValue(AuthState.NEED_LOGIN)
if (!jwt.isNullOrEmpty()) _authState.postValue(AuthState.LOGGED_IN)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package lk.eclk.locationservice.data.proviers

import android.content.Context
import android.content.SharedPreferences
import androidx.preference.PreferenceManager

abstract class PreferenceProvider(context: Context) {
// shared preference for cache data
private val appContext = context.applicationContext
protected val preference: SharedPreferences
get() = PreferenceManager.getDefaultSharedPreferences(
appContext
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package lk.eclk.locationservice.internal

enum class AuthState {
LOGGED_IN,
NEED_LOGIN
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package lk.eclk.locationservice.ui.signin

import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.lifecycle.ViewModelProvider

import lk.eclk.locationservice.R
import org.kodein.di.Kodein
import org.kodein.di.KodeinAware
import org.kodein.di.android.x.closestKodein
import org.kodein.di.generic.instance

class SignInFragment : Fragment(), KodeinAware {

override val kodein: Kodein by closestKodein()
private lateinit var viewModel: SignInViewModel
private val viewModelFactory: SignInViewModelFactory by instance()


override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.sign_in_fragment, container, false)
}

override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
viewModel = ViewModelProvider(this, viewModelFactory).get(SignInViewModel::class.java)
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package lk.eclk.locationservice.ui.signin

import androidx.lifecycle.ViewModel
import lk.eclk.locationservice.data.Repository

class SignInViewModel(private val repository: Repository) : ViewModel() {
// TODO: Implement the ViewModel
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package lk.eclk.locationservice.ui.signin

import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import lk.eclk.locationservice.data.Repository

class SignInViewModelFactory(private val repository: Repository) :
ViewModelProvider.NewInstanceFactory() {

@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
return SignInViewModel(repository) as T
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package lk.eclk.locationservice.ui.splash

import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import androidx.navigation.NavController
import androidx.navigation.Navigation

import lk.eclk.locationservice.R
import lk.eclk.locationservice.internal.AuthState
import org.kodein.di.Kodein
import org.kodein.di.KodeinAware
import org.kodein.di.android.x.closestKodein
import org.kodein.di.generic.instance

class SplashScreenFragment : Fragment(), KodeinAware {
override val kodein: Kodein by closestKodein()
private lateinit var viewModel: SplashScreenViewModel
private val viewModelFactory: SplashScreenViewModelFactory by instance()
private lateinit var navController: NavController

override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.splash_screen_fragment, container, false)
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewModel = ViewModelProvider(this, viewModelFactory).get(SplashScreenViewModel::class.java)
navController = Navigation.findNavController(view)
bindUI()
}

private fun bindUI() {
viewModel.authState.observe(this, Observer {
if (it == null) return@Observer
when (it) {
AuthState.NEED_LOGIN -> navController.navigate(R.id.action_splashScreenFragment_to_signInFragment)
}
})
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package lk.eclk.locationservice.ui.splash

import androidx.lifecycle.ViewModel
import lk.eclk.locationservice.data.Repository

class SplashScreenViewModel(private val repository: Repository) : ViewModel() {
val authState by lazy { repository.getAuthState() }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package lk.eclk.locationservice.ui.splash

import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import lk.eclk.locationservice.data.Repository

class SplashScreenViewModelFactory(private val repository: Repository) :
ViewModelProvider.NewInstanceFactory() {

@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
return SplashScreenViewModel(repository) as T
}
}
6 changes: 6 additions & 0 deletions mobile/app/src/main/res/anim/fade_in.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<alpha android:fromAlpha="0"
android:toAlpha="1"
android:duration="300"/>
</set>
6 changes: 6 additions & 0 deletions mobile/app/src/main/res/anim/fade_out.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<alpha android:fromAlpha="1"
android:toAlpha="0"
android:duration="300"/>
</set>
6 changes: 6 additions & 0 deletions mobile/app/src/main/res/anim/slide_in_down.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate android:fromXDelta="0%" android:toXDelta="0%"
android:fromYDelta="100%" android:toYDelta="0%"
android:duration="300"/>
</set>
6 changes: 6 additions & 0 deletions mobile/app/src/main/res/anim/slide_in_left.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate android:fromXDelta="-100%" android:toXDelta="0%"
android:fromYDelta="0%" android:toYDelta="0%"
android:duration="300"/>
</set>
6 changes: 6 additions & 0 deletions mobile/app/src/main/res/anim/slide_in_right.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate android:fromXDelta="100%" android:toXDelta="0%"
android:fromYDelta="0%" android:toYDelta="0%"
android:duration="300"/>
</set>
6 changes: 6 additions & 0 deletions mobile/app/src/main/res/anim/slide_out_down.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate android:fromXDelta="0%" android:toXDelta="0%"
android:fromYDelta="0%" android:toYDelta="100%"
android:duration="300"/>
</set>
6 changes: 6 additions & 0 deletions mobile/app/src/main/res/anim/slide_out_left.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate android:fromXDelta="0%" android:toXDelta="-100%"
android:fromYDelta="0%" android:toYDelta="0%"
android:duration="300"/>
</set>
6 changes: 6 additions & 0 deletions mobile/app/src/main/res/anim/slide_out_right.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate android:fromXDelta="0%" android:toXDelta="100%"
android:fromYDelta="0%" android:toYDelta="0%"
android:duration="300"/>
</set>
15 changes: 7 additions & 8 deletions mobile/app/src/main/res/layout/activity_main.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,12 @@
android:layout_height="match_parent"
tools:context=".ui.MainActivity">

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<fragment
android:name="androidx.navigation.fragment.NavHostFragment"
android:id="@+id/nav_host_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:navGraph="@navigation/main_navigation" />

</androidx.constraintlayout.widget.ConstraintLayout>
Loading

0 comments on commit 0a3bf03

Please sign in to comment.