master 14a19cf4771d cached
71 files
81.0 KB
22.9k tokens
1 requests
Download .txt
Repository: probelalkhan/android-mvvm-architecture
Branch: master
Commit: 14a19cf4771d
Files: 71
Total size: 81.0 KB

Directory structure:
gitextract_u139hf2o/

├── .gitignore
├── .idea/
│   ├── codeStyles/
│   │   ├── Project.xml
│   │   └── codeStyleConfig.xml
│   ├── encodings.xml
│   ├── gradle.xml
│   ├── misc.xml
│   ├── runConfigurations.xml
│   └── vcs.xml
├── app/
│   ├── .gitignore
│   ├── build.gradle
│   ├── proguard-rules.pro
│   └── src/
│       ├── androidTest/
│       │   └── java/
│       │       └── net/
│       │           └── simplifiedcoding/
│       │               └── mvvmsampleapp/
│       │                   └── ExampleInstrumentedTest.kt
│       ├── main/
│       │   ├── AndroidManifest.xml
│       │   ├── java/
│       │   │   └── net/
│       │   │       └── simplifiedcoding/
│       │   │           └── mvvmsampleapp/
│       │   │               ├── MVVMApplication.kt
│       │   │               ├── data/
│       │   │               │   ├── db/
│       │   │               │   │   ├── AppDatabase.kt
│       │   │               │   │   ├── QuoteDao.kt
│       │   │               │   │   ├── UserDao.kt
│       │   │               │   │   └── entities/
│       │   │               │   │       ├── Quote.kt
│       │   │               │   │       └── User.kt
│       │   │               │   ├── network/
│       │   │               │   │   ├── MyApi.kt
│       │   │               │   │   ├── NetworkConnectionInterceptor.kt
│       │   │               │   │   ├── SafeApiRequest.kt
│       │   │               │   │   └── responses/
│       │   │               │   │       ├── AuthResponse.kt
│       │   │               │   │       └── QuotesResponse.kt
│       │   │               │   ├── preferences/
│       │   │               │   │   └── PreferenceProvider.kt
│       │   │               │   └── repositories/
│       │   │               │       ├── QuotesRepository.kt
│       │   │               │       └── UserRepository.kt
│       │   │               ├── ui/
│       │   │               │   ├── auth/
│       │   │               │   │   ├── AuthViewModel.kt
│       │   │               │   │   ├── AuthViewModelFactory.kt
│       │   │               │   │   ├── LoginActivity.kt
│       │   │               │   │   └── SignupActivity.kt
│       │   │               │   └── home/
│       │   │               │       ├── HomeActivity.kt
│       │   │               │       ├── profile/
│       │   │               │       │   ├── ProfileFragment.kt
│       │   │               │       │   ├── ProfileViewModel.kt
│       │   │               │       │   └── ProfileViewModelFactory.kt
│       │   │               │       └── quotes/
│       │   │               │           ├── QuoteItem.kt
│       │   │               │           ├── QuotesFragment.kt
│       │   │               │           ├── QuotesViewModel.kt
│       │   │               │           └── QuotesViewModelFactory.kt
│       │   │               └── util/
│       │   │                   ├── Coroutines.kt
│       │   │                   ├── Delegates.kt
│       │   │                   ├── Exceptions.kt
│       │   │                   └── ViewUtils.kt
│       │   └── res/
│       │       ├── drawable/
│       │       │   ├── edit_text_round_gray_background.xml
│       │       │   ├── ic_app_logo.xml
│       │       │   ├── ic_email.xml
│       │       │   ├── ic_launcher_background.xml
│       │       │   ├── ic_lock.xml
│       │       │   └── ic_name.xml
│       │       ├── drawable-v24/
│       │       │   └── ic_launcher_foreground.xml
│       │       ├── layout/
│       │       │   ├── activity_home.xml
│       │       │   ├── activity_login.xml
│       │       │   ├── activity_signup.xml
│       │       │   ├── item_quote.xml
│       │       │   ├── profile_fragment.xml
│       │       │   └── quotes_fragment.xml
│       │       ├── menu/
│       │       │   └── nav_menu.xml
│       │       ├── mipmap-anydpi-v26/
│       │       │   ├── ic_launcher.xml
│       │       │   └── ic_launcher_round.xml
│       │       ├── navigation/
│       │       │   └── nav_graph.xml
│       │       └── values/
│       │           ├── colors.xml
│       │           ├── strings.xml
│       │           └── styles.xml
│       └── test/
│           └── java/
│               └── net/
│                   └── simplifiedcoding/
│                       └── mvvmsampleapp/
│                           └── ExampleUnitTest.kt
├── build.gradle
├── gradle/
│   └── wrapper/
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
└── settings.gradle

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
*.iml
.gradle
/local.properties
/.idea/caches
/.idea/libraries
/.idea/modules.xml
/.idea/workspace.xml
/.idea/navEditor.xml
/.idea/assetWizardSettings.xml
.DS_Store
/build
/captures
.externalNativeBuild


================================================
FILE: .idea/codeStyles/Project.xml
================================================
<component name="ProjectCodeStyleConfiguration">
  <code_scheme name="Project" version="173">
    <JetCodeStyleSettings>
      <option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
    </JetCodeStyleSettings>
    <codeStyleSettings language="XML">
      <arrangement>
        <rules>
          <section>
            <rule>
              <match>
                <AND>
                  <NAME>xmlns:android</NAME>
                  <XML_ATTRIBUTE />
                  <XML_NAMESPACE>^$</XML_NAMESPACE>
                </AND>
              </match>
            </rule>
          </section>
          <section>
            <rule>
              <match>
                <AND>
                  <NAME>xmlns:.*</NAME>
                  <XML_ATTRIBUTE />
                  <XML_NAMESPACE>^$</XML_NAMESPACE>
                </AND>
              </match>
              <order>BY_NAME</order>
            </rule>
          </section>
          <section>
            <rule>
              <match>
                <AND>
                  <NAME>.*:id</NAME>
                  <XML_ATTRIBUTE />
                  <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
                </AND>
              </match>
            </rule>
          </section>
          <section>
            <rule>
              <match>
                <AND>
                  <NAME>.*:name</NAME>
                  <XML_ATTRIBUTE />
                  <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
                </AND>
              </match>
            </rule>
          </section>
          <section>
            <rule>
              <match>
                <AND>
                  <NAME>name</NAME>
                  <XML_ATTRIBUTE />
                  <XML_NAMESPACE>^$</XML_NAMESPACE>
                </AND>
              </match>
            </rule>
          </section>
          <section>
            <rule>
              <match>
                <AND>
                  <NAME>style</NAME>
                  <XML_ATTRIBUTE />
                  <XML_NAMESPACE>^$</XML_NAMESPACE>
                </AND>
              </match>
            </rule>
          </section>
          <section>
            <rule>
              <match>
                <AND>
                  <NAME>.*</NAME>
                  <XML_ATTRIBUTE />
                  <XML_NAMESPACE>^$</XML_NAMESPACE>
                </AND>
              </match>
              <order>BY_NAME</order>
            </rule>
          </section>
          <section>
            <rule>
              <match>
                <AND>
                  <NAME>.*</NAME>
                  <XML_ATTRIBUTE />
                  <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
                </AND>
              </match>
              <order>ANDROID_ATTRIBUTE_ORDER</order>
            </rule>
          </section>
          <section>
            <rule>
              <match>
                <AND>
                  <NAME>.*</NAME>
                  <XML_ATTRIBUTE />
                  <XML_NAMESPACE>.*</XML_NAMESPACE>
                </AND>
              </match>
              <order>BY_NAME</order>
            </rule>
          </section>
        </rules>
      </arrangement>
    </codeStyleSettings>
    <codeStyleSettings language="kotlin">
      <option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
    </codeStyleSettings>
  </code_scheme>
</component>

================================================
FILE: .idea/codeStyles/codeStyleConfig.xml
================================================
<component name="ProjectCodeStyleConfiguration">
  <state>
    <option name="USE_PER_PROJECT_SETTINGS" value="true" />
  </state>
</component>

================================================
FILE: .idea/encodings.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
  <component name="Encoding" addBOMForNewFiles="with NO BOM" />
</project>

================================================
FILE: .idea/gradle.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
  <component name="GradleMigrationSettings" migrationVersion="1" />
  <component name="GradleSettings">
    <option name="linkedExternalProjectsSettings">
      <GradleProjectSettings>
        <option name="testRunner" value="PLATFORM" />
        <option name="distributionType" value="DEFAULT_WRAPPED" />
        <option name="externalProjectPath" value="$PROJECT_DIR$" />
        <option name="modules">
          <set>
            <option value="$PROJECT_DIR$" />
            <option value="$PROJECT_DIR$/app" />
          </set>
        </option>
        <option name="resolveModulePerSourceSet" value="false" />
      </GradleProjectSettings>
    </option>
  </component>
</project>

================================================
FILE: .idea/misc.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
  <component name="CMakeSettings">
    <configurations>
      <configuration PROFILE_NAME="Debug" CONFIG_NAME="Debug" />
    </configurations>
  </component>
  <component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" project-jdk-name="1.8" project-jdk-type="JavaSDK">
    <output url="file://$PROJECT_DIR$/build/classes" />
  </component>
  <component name="ProjectType">
    <option name="id" value="Android" />
  </component>
</project>

================================================
FILE: .idea/runConfigurations.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
  <component name="RunConfigurationProducerService">
    <option name="ignoredProducers">
      <set>
        <option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" />
        <option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" />
        <option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" />
      </set>
    </option>
  </component>
</project>

================================================
FILE: .idea/vcs.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
  <component name="VcsDirectoryMappings">
    <mapping directory="$PROJECT_DIR$" vcs="Git" />
  </component>
</project>

================================================
FILE: app/.gitignore
================================================
/build


================================================
FILE: app/build.gradle
================================================
apply plugin: 'com.android.application'

apply plugin: 'kotlin-android'

apply plugin: 'kotlin-android-extensions'

//kotlin kapt and navigation safeargs plugin
apply plugin: 'kotlin-kapt'

apply plugin: "androidx.navigation.safeargs"

android {
    compileSdkVersion 29
    defaultConfig {
        applicationId "net.simplifiedcoding.mvvmsampleapp"
        minSdkVersion 26
        targetSdkVersion 29
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    dataBinding {
        enabled = true
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
    implementation 'androidx.appcompat:appcompat:1.1.0'
    implementation 'androidx.core:core-ktx:1.2.0'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    implementation 'androidx.legacy:legacy-support-v4:1.0.0'
    implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test:runner:1.2.0'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'

    //Retrofit and GSON
    implementation 'com.squareup.retrofit2:retrofit:2.6.2'
    implementation 'com.squareup.retrofit2:converter-gson:2.6.2'

    //Kotlin Coroutines
    implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.3"
    implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.3"

    // ViewModel and LiveData
    implementation "androidx.lifecycle:lifecycle-extensions:2.2.0"

    //New Material Design
    implementation 'com.google.android.material:material:1.2.0-alpha06'

    //Kodein Dependency Injection
    implementation "org.kodein.di:kodein-di-generic-jvm:6.2.1"
    implementation "org.kodein.di:kodein-di-framework-android-x:6.2.1"

    //Android Room
    implementation "androidx.room:room-runtime:2.2.5"
    implementation "androidx.room:room-ktx:2.2.5"
    kapt "androidx.room:room-compiler:2.2.5"

    //Android Navigation Architecture
    implementation "androidx.navigation:navigation-fragment-ktx:2.3.0-alpha06"
    implementation "androidx.navigation:navigation-ui-ktx:2.3.0-alpha06"

    implementation 'com.xwray:groupie:2.3.0'
    implementation 'com.xwray:groupie-kotlin-android-extensions:2.3.0'
    implementation 'com.xwray:groupie-databinding:2.3.0'

    implementation "androidx.preference:preference-ktx:1.1.1"
}


================================================
FILE: app/proguard-rules.pro
================================================
# 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


================================================
FILE: app/src/androidTest/java/net/simplifiedcoding/mvvmsampleapp/ExampleInstrumentedTest.kt
================================================
package net.simplifiedcoding.mvvmsampleapp

import androidx.test.InstrumentationRegistry
import androidx.test.runner.AndroidJUnit4

import org.junit.Test
import org.junit.runner.RunWith

import org.junit.Assert.*

/**
 * Instrumented test, which will execute on an Android device.
 *
 * See [testing documentation](http://d.android.com/tools/testing).
 */
@RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest {
    @Test
    fun useAppContext() {
        // Context of the app under test.
        val appContext = InstrumentationRegistry.getTargetContext()
        assertEquals("net.simplifiedcoding.mvvmsampleapp", appContext.packageName)
    }
}


================================================
FILE: app/src/main/AndroidManifest.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          xmlns:tools="http://schemas.android.com/tools"
          package="net.simplifiedcoding.mvvmsampleapp">


    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    <uses-permission android:name="android.permission.INTERNET"/>

    <application
            android:name=".MVVMApplication"
            android:allowBackup="true"
            android:icon="@mipmap/ic_launcher"
            android:label="@string/app_name"
            android:roundIcon="@mipmap/ic_launcher_round"
            android:supportsRtl="true"
            android:theme="@style/AppTheme"
            tools:ignore="AllowBackup,GoogleAppIndexingWarning">
        <activity android:name=".ui.home.HomeActivity">
        </activity>
        <activity android:name=".ui.auth.SignupActivity">
        </activity>
        <activity android:name=".ui.auth.LoginActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>

                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
    </application>

</manifest>

================================================
FILE: app/src/main/java/net/simplifiedcoding/mvvmsampleapp/MVVMApplication.kt
================================================
package net.simplifiedcoding.mvvmsampleapp

import android.app.Application
import net.simplifiedcoding.mvvmsampleapp.data.db.AppDatabase
import net.simplifiedcoding.mvvmsampleapp.data.network.MyApi
import net.simplifiedcoding.mvvmsampleapp.data.network.NetworkConnectionInterceptor
import net.simplifiedcoding.mvvmsampleapp.data.preferences.PreferenceProvider
import net.simplifiedcoding.mvvmsampleapp.data.repositories.QuotesRepository
import net.simplifiedcoding.mvvmsampleapp.data.repositories.UserRepository
import net.simplifiedcoding.mvvmsampleapp.ui.auth.AuthViewModelFactory
import net.simplifiedcoding.mvvmsampleapp.ui.home.profile.ProfileViewModelFactory
import net.simplifiedcoding.mvvmsampleapp.ui.home.quotes.QuotesViewModelFactory
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

class MVVMApplication : Application(), KodeinAware {

    override val kodein = Kodein.lazy {
        import(androidXModule(this@MVVMApplication))

        bind() from singleton { NetworkConnectionInterceptor(instance()) }
        bind() from singleton { MyApi(instance()) }
        bind() from singleton { AppDatabase(instance()) }
        bind() from singleton { PreferenceProvider(instance()) }
        bind() from singleton { UserRepository(instance(), instance()) }
        bind() from singleton { QuotesRepository(instance(), instance(), instance()) }
        bind() from provider { AuthViewModelFactory(instance()) }
        bind() from provider { ProfileViewModelFactory(instance()) }
        bind() from provider{ QuotesViewModelFactory(instance())}


    }

}

================================================
FILE: app/src/main/java/net/simplifiedcoding/mvvmsampleapp/data/db/AppDatabase.kt
================================================
package net.simplifiedcoding.mvvmsampleapp.data.db

import android.content.Context
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
import net.simplifiedcoding.mvvmsampleapp.data.db.entities.Quote
import net.simplifiedcoding.mvvmsampleapp.data.db.entities.User

@Database(
    entities = [User::class, Quote::class],
    version = 1
)
abstract class AppDatabase : RoomDatabase() {

    abstract fun getUserDao(): UserDao
    abstract fun getQuoteDao(): QuoteDao

    companion object {

        @Volatile
        private var instance: AppDatabase? = null
        private val LOCK = Any()

        operator fun invoke(context: Context) = instance ?: synchronized(LOCK) {
            instance ?: buildDatabase(context).also {
                instance = it
            }
        }

        private fun buildDatabase(context: Context) =
            Room.databaseBuilder(
                context.applicationContext,
                AppDatabase::class.java,
                "MyDatabase.db"
            ).build()
    }
}

================================================
FILE: app/src/main/java/net/simplifiedcoding/mvvmsampleapp/data/db/QuoteDao.kt
================================================
package net.simplifiedcoding.mvvmsampleapp.data.db

import androidx.lifecycle.LiveData
import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import net.simplifiedcoding.mvvmsampleapp.data.db.entities.Quote

@Dao
interface QuoteDao {

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    fun saveAllQuotes(quotes : List<Quote>)

    @Query("SELECT * FROM Quote")
    fun getQuotes() : LiveData<List<Quote>>

}

================================================
FILE: app/src/main/java/net/simplifiedcoding/mvvmsampleapp/data/db/UserDao.kt
================================================
package net.simplifiedcoding.mvvmsampleapp.data.db

import androidx.lifecycle.LiveData
import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import net.simplifiedcoding.mvvmsampleapp.data.db.entities.CURRENT_USER_ID
import net.simplifiedcoding.mvvmsampleapp.data.db.entities.User

@Dao
interface UserDao{

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun upsert(user: User) : Long

    @Query("SELECT * FROM user WHERE uid = $CURRENT_USER_ID")
    fun getuser() : LiveData<User>

}

================================================
FILE: app/src/main/java/net/simplifiedcoding/mvvmsampleapp/data/db/entities/Quote.kt
================================================
package net.simplifiedcoding.mvvmsampleapp.data.db.entities

import androidx.room.Entity
import androidx.room.PrimaryKey

@Entity
data class Quote(
    @PrimaryKey(autoGenerate = false)
    val id: Int,
    val quote: String,
    val author: String,
    val thumbnail: String,
    val created_at: String?,
    val updated_at: String?
)

================================================
FILE: app/src/main/java/net/simplifiedcoding/mvvmsampleapp/data/db/entities/User.kt
================================================
package net.simplifiedcoding.mvvmsampleapp.data.db.entities

import androidx.room.Entity
import androidx.room.PrimaryKey

const val CURRENT_USER_ID = 0

@Entity
data class User(
    var id: Int? = null,
    var name: String? = null,
    var email: String? = null,
    var password: String? = null,
    var email_verified_at: String? = null,
    var created_at: String? = null,
    var updated_at: String? = null
){
    @PrimaryKey(autoGenerate = false)
    var uid: Int = CURRENT_USER_ID
}

================================================
FILE: app/src/main/java/net/simplifiedcoding/mvvmsampleapp/data/network/MyApi.kt
================================================
package net.simplifiedcoding.mvvmsampleapp.data.network

import net.simplifiedcoding.mvvmsampleapp.data.network.responses.AuthResponse
import net.simplifiedcoding.mvvmsampleapp.data.network.responses.QuotesResponse
import okhttp3.OkHttpClient
import okhttp3.ResponseBody
import retrofit2.Call
import retrofit2.Response
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import retrofit2.http.Field
import retrofit2.http.FormUrlEncoded
import retrofit2.http.GET
import retrofit2.http.POST

interface MyApi {

    @FormUrlEncoded
    @POST("login")
    suspend fun userLogin(
        @Field("email") email: String,
        @Field("password") password: String
    ) : Response<AuthResponse>

    @FormUrlEncoded
    @POST("signup")
    suspend fun userSignup(
        @Field("name") name: String,
        @Field("email") email: String,
        @Field("password") password: String
    ) : Response<AuthResponse>

    @GET("quotes")
    suspend fun getQuotes() : Response<QuotesResponse>

    companion object{
        operator fun invoke(
            networkConnectionInterceptor: NetworkConnectionInterceptor
        ) : MyApi{

            val okkHttpclient = OkHttpClient.Builder()
                .addInterceptor(networkConnectionInterceptor)
                .build()

            return Retrofit.Builder()
                .client(okkHttpclient)
                .baseUrl("https://api.simplifiedcoding.in/course-apis/mvvm/")
                .addConverterFactory(GsonConverterFactory.create())
                .build()
                .create(MyApi::class.java)
        }
    }

}



================================================
FILE: app/src/main/java/net/simplifiedcoding/mvvmsampleapp/data/network/NetworkConnectionInterceptor.kt
================================================
package net.simplifiedcoding.mvvmsampleapp.data.network

import android.content.Context
import android.net.ConnectivityManager
import android.net.NetworkCapabilities
import net.simplifiedcoding.mvvmsampleapp.util.NoInternetException
import okhttp3.Interceptor
import okhttp3.Response

class NetworkConnectionInterceptor(
    context: Context
) : Interceptor {

    private val applicationContext = context.applicationContext

    override fun intercept(chain: Interceptor.Chain): Response {
        if (!isInternetAvailable())
            throw NoInternetException("Make sure you have an active data connection")
        return chain.proceed(chain.request())
    }

    private fun isInternetAvailable(): Boolean {
        var result = false
        val connectivityManager =
            applicationContext.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager?
        connectivityManager?.let {
            it.getNetworkCapabilities(connectivityManager.activeNetwork)?.apply {
                result = when {
                    hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> true
                    hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> true
                    else -> false
                }
            }
        }
        return result
    }

}

================================================
FILE: app/src/main/java/net/simplifiedcoding/mvvmsampleapp/data/network/SafeApiRequest.kt
================================================
package net.simplifiedcoding.mvvmsampleapp.data.network

import net.simplifiedcoding.mvvmsampleapp.util.ApiException
import org.json.JSONException
import org.json.JSONObject
import retrofit2.Response

abstract class SafeApiRequest {

    suspend fun<T: Any> apiRequest(call: suspend () -> Response<T>) : T{
        val response = call.invoke()
        if(response.isSuccessful){
            return response.body()!!
        }else{
            val error = response.errorBody()?.string()
            val message = StringBuilder()
            error?.let{
                try{
                    message.append(JSONObject(it).getString("message"))
                }catch(e: JSONException){ }
                message.append("\n")
            }
            message.append("Error Code: ${response.code()}")
            throw ApiException(message.toString())
        }
    }

}

================================================
FILE: app/src/main/java/net/simplifiedcoding/mvvmsampleapp/data/network/responses/AuthResponse.kt
================================================
package net.simplifiedcoding.mvvmsampleapp.data.network.responses

import net.simplifiedcoding.mvvmsampleapp.data.db.entities.User

data class AuthResponse(
    val isSuccessful : Boolean?,
    val message: String?,
    val user: User?
)

================================================
FILE: app/src/main/java/net/simplifiedcoding/mvvmsampleapp/data/network/responses/QuotesResponse.kt
================================================
package net.simplifiedcoding.mvvmsampleapp.data.network.responses

import net.simplifiedcoding.mvvmsampleapp.data.db.entities.Quote

data class QuotesResponse (
    val isSuccessful: Boolean,
    val quotes: List<Quote>
)

================================================
FILE: app/src/main/java/net/simplifiedcoding/mvvmsampleapp/data/preferences/PreferenceProvider.kt
================================================
package net.simplifiedcoding.mvvmsampleapp.data.preferences

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

private const val KEY_SAVED_AT = "key_saved_at"

class PreferenceProvider(
    context: Context
) {

    private val appContext = context.applicationContext

    private val preference: SharedPreferences
        get() = PreferenceManager.getDefaultSharedPreferences(appContext)


    fun savelastSavedAt(savedAt: String) {
        preference.edit().putString(
            KEY_SAVED_AT,
            savedAt
        ).apply()
    }

    fun getLastSavedAt(): String? {
        return preference.getString(KEY_SAVED_AT, null)
    }

}

================================================
FILE: app/src/main/java/net/simplifiedcoding/mvvmsampleapp/data/repositories/QuotesRepository.kt
================================================
package net.simplifiedcoding.mvvmsampleapp.data.repositories

import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import net.simplifiedcoding.mvvmsampleapp.data.db.AppDatabase
import net.simplifiedcoding.mvvmsampleapp.data.db.entities.Quote
import net.simplifiedcoding.mvvmsampleapp.data.network.MyApi
import net.simplifiedcoding.mvvmsampleapp.data.network.SafeApiRequest
import net.simplifiedcoding.mvvmsampleapp.data.preferences.PreferenceProvider
import net.simplifiedcoding.mvvmsampleapp.util.Coroutines
import java.lang.Exception
import java.time.LocalDateTime
import java.time.temporal.ChronoUnit

private val MINIMUM_INTERVAL = 6

class QuotesRepository(
    private val api: MyApi,
    private val db: AppDatabase,
    private val prefs: PreferenceProvider
) : SafeApiRequest() {

    private val quotes = MutableLiveData<List<Quote>>()

    init {
        quotes.observeForever {
            saveQuotes(it)
        }
    }

    suspend fun getQuotes(): LiveData<List<Quote>> {
        return withContext(Dispatchers.IO) {
            fetchQuotes()
            db.getQuoteDao().getQuotes()
        }
    }

    private suspend fun fetchQuotes() {
        val lastSavedAt = prefs.getLastSavedAt()

        if (lastSavedAt == null || isFetchNeeded(LocalDateTime.parse(lastSavedAt))) {
            try {
                val response = apiRequest { api.getQuotes() }
                quotes.postValue(response.quotes)
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }
    }

    private fun isFetchNeeded(savedAt: LocalDateTime): Boolean {
        return ChronoUnit.HOURS.between(savedAt, LocalDateTime.now()) > MINIMUM_INTERVAL
    }


    private fun saveQuotes(quotes: List<Quote>) {
        Coroutines.io {
            prefs.savelastSavedAt(LocalDateTime.now().toString())
            db.getQuoteDao().saveAllQuotes(quotes)
        }
    }

}

================================================
FILE: app/src/main/java/net/simplifiedcoding/mvvmsampleapp/data/repositories/UserRepository.kt
================================================
package net.simplifiedcoding.mvvmsampleapp.data.repositories

import net.simplifiedcoding.mvvmsampleapp.data.db.AppDatabase
import net.simplifiedcoding.mvvmsampleapp.data.db.entities.User
import net.simplifiedcoding.mvvmsampleapp.data.network.MyApi
import net.simplifiedcoding.mvvmsampleapp.data.network.SafeApiRequest
import net.simplifiedcoding.mvvmsampleapp.data.network.responses.AuthResponse
import retrofit2.Response

class UserRepository(
    private val api: MyApi,
    private val db: AppDatabase
) : SafeApiRequest() {

    suspend fun userLogin(email: String, password: String): AuthResponse {
        return apiRequest { api.userLogin(email, password) }
    }

    suspend fun userSignup(
        name: String,
        email: String,
        password: String
    ) : AuthResponse {
        return apiRequest{ api.userSignup(name, email, password)}
    }

    suspend fun saveUser(user: User) = db.getUserDao().upsert(user)

    fun getUser() = db.getUserDao().getuser()

}

================================================
FILE: app/src/main/java/net/simplifiedcoding/mvvmsampleapp/ui/auth/AuthViewModel.kt
================================================
package net.simplifiedcoding.mvvmsampleapp.ui.auth

import androidx.lifecycle.ViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import net.simplifiedcoding.mvvmsampleapp.data.db.entities.User
import net.simplifiedcoding.mvvmsampleapp.data.repositories.UserRepository


class AuthViewModel(
    private val repository: UserRepository
) : ViewModel() {

    fun getLoggedInUser() = repository.getUser()

    suspend fun userLogin(
        email: String,
        password: String
    ) = withContext(Dispatchers.IO) { repository.userLogin(email, password) }

    suspend fun userSignup(
        name: String,
        email: String,
        password: String
    ) = withContext(Dispatchers.IO) { repository.userSignup(name, email, password) }

    suspend fun saveLoggedInUser(user: User) = repository.saveUser(user)

}

================================================
FILE: app/src/main/java/net/simplifiedcoding/mvvmsampleapp/ui/auth/AuthViewModelFactory.kt
================================================
package net.simplifiedcoding.mvvmsampleapp.ui.auth

import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import net.simplifiedcoding.mvvmsampleapp.data.repositories.UserRepository

@Suppress("UNCHECKED_CAST")
class AuthViewModelFactory(
    private val repository: UserRepository
) : ViewModelProvider.NewInstanceFactory() {

    override fun <T : ViewModel?> create(modelClass: Class<T>): T {
        return AuthViewModel(repository) as T
    }
}

================================================
FILE: app/src/main/java/net/simplifiedcoding/mvvmsampleapp/ui/auth/LoginActivity.kt
================================================
package net.simplifiedcoding.mvvmsampleapp.ui.auth

import android.content.Intent
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.databinding.DataBindingUtil
import androidx.lifecycle.*
import kotlinx.android.synthetic.main.activity_login.*
import kotlinx.coroutines.launch
import net.simplifiedcoding.mvvmsampleapp.R
import net.simplifiedcoding.mvvmsampleapp.data.db.entities.User
import net.simplifiedcoding.mvvmsampleapp.databinding.ActivityLoginBinding
import net.simplifiedcoding.mvvmsampleapp.ui.home.HomeActivity
import net.simplifiedcoding.mvvmsampleapp.util.*
import org.kodein.di.KodeinAware
import org.kodein.di.android.kodein
import org.kodein.di.generic.instance


class LoginActivity : AppCompatActivity(), KodeinAware {

    override val kodein by kodein()
    private val factory: AuthViewModelFactory by instance()

    private lateinit var binding: ActivityLoginBinding
    private lateinit var viewModel: AuthViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        binding = DataBindingUtil.setContentView(this, R.layout.activity_login)
        viewModel = ViewModelProvider(this, factory).get(AuthViewModel::class.java)


        viewModel.getLoggedInUser().observe(this, Observer { user ->
            if (user != null) {
                Intent(this, HomeActivity::class.java).also {
                    it.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
                    startActivity(it)
                }
            }
        })

        binding.buttonSignIn.setOnClickListener {
            loginUser()
        }

        binding.textViewSignUp.setOnClickListener {
            startActivity(Intent(this, SignupActivity::class.java))
        }
    }

    private fun loginUser() {
        val email = binding.editTextEmail.text.toString().trim()
        val password = binding.editTextPassword.text.toString().trim()

        lifecycleScope.launch {
            try {
                val authResponse = viewModel.userLogin(email, password)
                if (authResponse.user != null) {
                    viewModel.saveLoggedInUser(authResponse.user)
                } else {
                    binding.rootLayout.snackbar(authResponse.message!!)
                }
            } catch (e: ApiException) {
                e.printStackTrace()
            } catch (e: NoInternetException) {
                e.printStackTrace()
            }
        }
    }
}


================================================
FILE: app/src/main/java/net/simplifiedcoding/mvvmsampleapp/ui/auth/SignupActivity.kt
================================================
package net.simplifiedcoding.mvvmsampleapp.ui.auth

import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.databinding.DataBindingUtil
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.ViewModelProviders
import androidx.lifecycle.lifecycleScope
import kotlinx.android.synthetic.main.activity_login.*
import kotlinx.coroutines.launch
import net.simplifiedcoding.mvvmsampleapp.R
import net.simplifiedcoding.mvvmsampleapp.data.db.entities.User
import net.simplifiedcoding.mvvmsampleapp.databinding.ActivitySignupBinding
import net.simplifiedcoding.mvvmsampleapp.ui.home.HomeActivity
import net.simplifiedcoding.mvvmsampleapp.util.*
import org.kodein.di.KodeinAware
import org.kodein.di.android.kodein
import org.kodein.di.generic.instance

class SignupActivity : AppCompatActivity(), KodeinAware {

    override val kodein by kodein()
    private val factory: AuthViewModelFactory by instance()

    private lateinit var binding: ActivitySignupBinding
    private lateinit var viewModel: AuthViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        binding = DataBindingUtil.setContentView(this, R.layout.activity_signup)
        viewModel = ViewModelProvider(this, factory).get(AuthViewModel::class.java)

        viewModel.getLoggedInUser().observe(this, Observer { user ->
            if (user != null) {
                Intent(this, HomeActivity::class.java).also {
                    it.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
                    startActivity(it)
                }
            }
        })

        binding.buttonSignUp.setOnClickListener {
            userSignup()
        }
    }

    private fun userSignup() {
        val name = binding.editTextName.text.toString().trim()
        val email = binding.editTextEmail.text.toString().trim()
        val password = binding.editTextPassword.text.toString().trim()
        val password1 = binding.editTextPassword.text.toString().trim()

        //@todo add input validations

        lifecycleScope.launch {
            try {
                val authResponse = viewModel.userSignup(name, email, password)
                if (authResponse.user != null) {
                    viewModel.saveLoggedInUser(authResponse.user)
                } else {
                    binding.root.snackbar(authResponse.message!!)
                }
            } catch (e: ApiException) {
                e.printStackTrace()
            } catch (e: NoInternetException) {
                e.printStackTrace()
            }
        }
    }

}


================================================
FILE: app/src/main/java/net/simplifiedcoding/mvvmsampleapp/ui/home/HomeActivity.kt
================================================
package net.simplifiedcoding.mvvmsampleapp.ui.home

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.navigation.Navigation
import androidx.navigation.ui.NavigationUI
import kotlinx.android.synthetic.main.activity_home.*
import net.simplifiedcoding.mvvmsampleapp.R

class HomeActivity : AppCompatActivity() {

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

        setSupportActionBar(toolbar)

        val navController = Navigation.findNavController(this, R.id.fragment)
        NavigationUI.setupWithNavController(nav_view, navController)
        NavigationUI.setupActionBarWithNavController(this,navController, drawer_layout)
    }

    override fun onSupportNavigateUp(): Boolean {
        return NavigationUI.navigateUp(
            Navigation.findNavController(this, R.id.fragment),
            drawer_layout
        )
    }
}


================================================
FILE: app/src/main/java/net/simplifiedcoding/mvvmsampleapp/ui/home/profile/ProfileFragment.kt
================================================
package net.simplifiedcoding.mvvmsampleapp.ui.home.profile

import androidx.lifecycle.ViewModelProviders
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.databinding.DataBindingUtil

import net.simplifiedcoding.mvvmsampleapp.R
import net.simplifiedcoding.mvvmsampleapp.databinding.ProfileFragmentBinding
import org.kodein.di.android.x.kodein
import org.kodein.di.KodeinAware
import org.kodein.di.generic.instance

class ProfileFragment : Fragment(), KodeinAware {

    override val kodein by kodein()

    private lateinit var viewModel: ProfileViewModel
    private val factory: ProfileViewModelFactory by instance()

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val binding: ProfileFragmentBinding =
            DataBindingUtil.inflate(inflater, R.layout.profile_fragment, container, false)
        viewModel = ViewModelProviders.of(this, factory).get(ProfileViewModel::class.java)
        binding.viewmodel = viewModel
        binding.lifecycleOwner = this
        return binding.root
    }


}


================================================
FILE: app/src/main/java/net/simplifiedcoding/mvvmsampleapp/ui/home/profile/ProfileViewModel.kt
================================================
package net.simplifiedcoding.mvvmsampleapp.ui.home.profile

import androidx.lifecycle.ViewModel;
import net.simplifiedcoding.mvvmsampleapp.data.repositories.UserRepository

class ProfileViewModel(
    repository: UserRepository
) : ViewModel() {

    val user = repository.getUser()

}


================================================
FILE: app/src/main/java/net/simplifiedcoding/mvvmsampleapp/ui/home/profile/ProfileViewModelFactory.kt
================================================
package net.simplifiedcoding.mvvmsampleapp.ui.home.profile

import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import net.simplifiedcoding.mvvmsampleapp.data.repositories.UserRepository

@Suppress("UNCHECKED_CAST")
class ProfileViewModelFactory(
    private val repository: UserRepository
) : ViewModelProvider.NewInstanceFactory() {

    override fun <T : ViewModel?> create(modelClass: Class<T>): T {
        return ProfileViewModel(repository) as T
    }
}

================================================
FILE: app/src/main/java/net/simplifiedcoding/mvvmsampleapp/ui/home/quotes/QuoteItem.kt
================================================
package net.simplifiedcoding.mvvmsampleapp.ui.home.quotes

import com.xwray.groupie.databinding.BindableItem
import net.simplifiedcoding.mvvmsampleapp.R
import net.simplifiedcoding.mvvmsampleapp.data.db.entities.Quote
import net.simplifiedcoding.mvvmsampleapp.databinding.ItemQuoteBinding

class QuoteItem(
    private val quote: Quote
) : BindableItem<ItemQuoteBinding>(){

    override fun getLayout() = R.layout.item_quote

    override fun bind(viewBinding: ItemQuoteBinding, position: Int) {
        viewBinding.setQuote(quote)
    }
}

================================================
FILE: app/src/main/java/net/simplifiedcoding/mvvmsampleapp/ui/home/quotes/QuotesFragment.kt
================================================
package net.simplifiedcoding.mvvmsampleapp.ui.home.quotes

import androidx.lifecycle.ViewModelProviders
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.recyclerview.widget.LinearLayoutManager
import com.xwray.groupie.GroupAdapter
import com.xwray.groupie.ViewHolder
import kotlinx.android.synthetic.main.quotes_fragment.*

import net.simplifiedcoding.mvvmsampleapp.R
import net.simplifiedcoding.mvvmsampleapp.data.db.entities.Quote
import net.simplifiedcoding.mvvmsampleapp.util.Coroutines
import net.simplifiedcoding.mvvmsampleapp.util.hide
import net.simplifiedcoding.mvvmsampleapp.util.show
import net.simplifiedcoding.mvvmsampleapp.util.toast
import org.kodein.di.KodeinAware
import org.kodein.di.android.x.kodein
import org.kodein.di.generic.instance

class QuotesFragment : Fragment(), KodeinAware {

    override val kodein by kodein()

    private val factory: QuotesViewModelFactory by instance()

    private lateinit var viewModel: QuotesViewModel

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

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
        viewModel = ViewModelProviders.of(this, factory).get(QuotesViewModel::class.java)
        bindUI()
    }


    private fun bindUI() = Coroutines.main {
        progress_bar.show()
        viewModel.quotes.await().observe(this, Observer {
            progress_bar.hide()
            initRecyclerView(it.toQuoteItem())
        })
    }

    private fun initRecyclerView(quoteItem: List<QuoteItem>) {

        val mAdapter = GroupAdapter<ViewHolder>().apply {
            addAll(quoteItem)
        }

        recyclerview.apply {
            layoutManager = LinearLayoutManager(context)
            setHasFixedSize(true)
            adapter = mAdapter
        }

    }


    private fun List<Quote>.toQuoteItem() : List<QuoteItem>{
        return this.map {
            QuoteItem(it)
        }
    }

}


================================================
FILE: app/src/main/java/net/simplifiedcoding/mvvmsampleapp/ui/home/quotes/QuotesViewModel.kt
================================================
package net.simplifiedcoding.mvvmsampleapp.ui.home.quotes

import androidx.lifecycle.ViewModel;
import net.simplifiedcoding.mvvmsampleapp.data.repositories.QuotesRepository
import net.simplifiedcoding.mvvmsampleapp.util.lazyDeferred

class QuotesViewModel(
    repository: QuotesRepository
) : ViewModel() {

    val quotes by lazyDeferred {
        repository.getQuotes()
    }
}


================================================
FILE: app/src/main/java/net/simplifiedcoding/mvvmsampleapp/ui/home/quotes/QuotesViewModelFactory.kt
================================================
package net.simplifiedcoding.mvvmsampleapp.ui.home.quotes

import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import net.simplifiedcoding.mvvmsampleapp.data.repositories.QuotesRepository
import net.simplifiedcoding.mvvmsampleapp.data.repositories.UserRepository

@Suppress("UNCHECKED_CAST")
class QuotesViewModelFactory(
    private val repository: QuotesRepository
) : ViewModelProvider.NewInstanceFactory() {

    override fun <T : ViewModel?> create(modelClass: Class<T>): T {
        return QuotesViewModel(repository) as T
    }
}

================================================
FILE: app/src/main/java/net/simplifiedcoding/mvvmsampleapp/util/Coroutines.kt
================================================
package net.simplifiedcoding.mvvmsampleapp.util

import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch

object Coroutines {

    fun main(work: suspend (() -> Unit)) =
        CoroutineScope(Dispatchers.Main).launch {
            work()
        }

    fun io(work: suspend (() -> Unit)) =
        CoroutineScope(Dispatchers.IO).launch {
            work()
        }

}

================================================
FILE: app/src/main/java/net/simplifiedcoding/mvvmsampleapp/util/Delegates.kt
================================================
package net.simplifiedcoding.mvvmsampleapp.util

import kotlinx.coroutines.*

fun<T> lazyDeferred(block: suspend CoroutineScope.() -> T): Lazy<Deferred<T>>{
    return lazy {
        GlobalScope.async(start = CoroutineStart.LAZY) {
            block.invoke(this)
        }
    }
}

================================================
FILE: app/src/main/java/net/simplifiedcoding/mvvmsampleapp/util/Exceptions.kt
================================================
package net.simplifiedcoding.mvvmsampleapp.util

import java.io.IOException

class ApiException(message: String) : IOException(message)
class NoInternetException(message: String) : IOException(message)

================================================
FILE: app/src/main/java/net/simplifiedcoding/mvvmsampleapp/util/ViewUtils.kt
================================================
package net.simplifiedcoding.mvvmsampleapp.util

import android.content.Context
import android.view.View
import android.widget.ProgressBar
import android.widget.Toast
import com.google.android.material.snackbar.Snackbar


fun Context.toast(message: String){
    Toast.makeText(this, message, Toast.LENGTH_LONG ).show()
}

fun ProgressBar.show(){
    visibility = View.VISIBLE
}

fun ProgressBar.hide(){
    visibility = View.GONE
}

fun View.snackbar(message: String){
    Snackbar.make(this, message, Snackbar.LENGTH_LONG).also { snackbar ->
        snackbar.setAction("Ok") {
            snackbar.dismiss()
        }
    }.show()
}


================================================
FILE: app/src/main/res/drawable/edit_text_round_gray_background.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
       android:shape="rectangle" android:padding="10dp">

    <solid android:color="#f1f3f4"/>

    <corners
            android:bottomRightRadius="8dp"
            android:bottomLeftRadius="8dp"
            android:topLeftRadius="8dp"
            android:topRightRadius="8dp"/>
</shape>

================================================
FILE: app/src/main/res/drawable/ic_app_logo.xml
================================================
<vector android:height="24dp" android:viewportHeight="512"
    android:viewportWidth="512" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
    <path android:fillColor="#3b4a51" android:pathData="m309.027,287.813 l42.438,42.438 -21.211,21.211 -42.438,-42.438zM309.027,287.813"/>
    <path android:fillColor="#3b4a51" android:pathData="m330.25,160.535 l21.211,21.211 -42.434,42.434 -21.211,-21.211zM330.25,160.535"/>
    <path android:fillColor="#465a61" android:pathData="m181.746,160.535 l42.438,42.434 -21.211,21.211 -42.438,-42.434zM181.746,160.535"/>
    <path android:fillColor="#465a61" android:pathData="m202.973,287.813 l21.211,21.211 -42.434,42.438 -21.211,-21.211zM202.973,287.813"/>
    <path android:fillColor="#465a61" android:pathData="m312.5,241h93.5v30h-93.5zM312.5,241"/>
    <path android:fillColor="#596c76" android:pathData="m241,106h30v90h-30zM241,106"/>
    <path android:fillColor="#465a61" android:pathData="m256,106h15v90h-15zM256,106"/>
    <path android:fillColor="#596c76" android:pathData="m106,241h90v30h-90zM106,241"/>
    <path android:fillColor="#596c76" android:pathData="m241,316h30v90h-30zM241,316"/>
    <path android:fillColor="#465a61" android:pathData="m256,316h15v90h-15zM256,316"/>
    <path android:fillColor="#b5baf3" android:pathData="m256,181c-41.398,0 -75,33.602 -75,75s33.602,75 75,75 75,-33.602 75,-75 -33.602,-75 -75,-75zM256,181"/>
    <path android:fillColor="#979fef" android:pathData="m451,316c-33.09,0 -60,-26.91 -60,-60s26.91,-60 60,-60 61,26.91 61,60 -27.91,60 -61,60zM451,316"/>
    <path android:fillColor="#b5baf3" android:pathData="m61,316c-33.09,0 -61,-26.91 -61,-60s27.91,-60 61,-60 60,26.91 60,60 -26.91,60 -60,60zM61,316"/>
    <path android:fillColor="#b5baf3" android:pathData="m256,391c-33,0 -60,28 -60,61s27,60 60,60 60,-27 60,-60 -27,-61 -60,-61zM256,391"/>
    <path android:fillColor="#b5baf3" android:pathData="m256,0c-33,0 -60,28 -60,61s27,60 60,60 60,-27 60,-60 -27,-61 -60,-61zM256,0"/>
    <path android:fillColor="#979fef" android:pathData="m330.238,181.746c-17.488,-17.488 -17.652,-45.949 0,-63.633 16.977,-16.992 46.641,-16.992 63.648,0 17.629,17.633 17.543,46.102 0,63.648 -17.645,17.609 -46.102,17.531 -63.648,-0.016zM330.238,181.746"/>
    <path android:fillColor="#b5baf3" android:pathData="m118.113,393.887c-17.633,-17.633 -17.547,-46.102 0,-63.648 17.023,-17.008 46.672,-16.961 63.648,0.016 17.543,17.543 17.602,46.016 -0.016,63.633 -17.531,17.563 -46.016,17.617 -63.633,0zM118.113,393.887"/>
    <path android:fillColor="#979fef" android:pathData="m330.238,393.887c-17.613,-17.645 -17.531,-46.102 0.016,-63.648 16.945,-16.949 46.598,-17.008 63.633,0 17.563,17.566 17.617,46.031 0,63.648 -17.633,17.633 -46.102,17.547 -63.648,0zM330.238,393.887"/>
    <path android:fillColor="#b5baf3" android:pathData="m118.113,181.746c-17.563,-17.531 -17.617,-46.016 0,-63.633 16.992,-16.992 46.672,-16.992 63.648,0 17.602,17.633 17.547,46.086 -0.016,63.648 -17.543,17.543 -46.016,17.602 -63.633,-0.016zM118.113,181.746"/>
    <path android:fillColor="#979fef" android:pathData="m316,452c0,33 -27,60 -60,60v-121c33,0 60,28 60,61zM316,452"/>
    <path android:fillColor="#979fef" android:pathData="m256,121v-121c33,0 60,28 60,61s-27,60 -60,60zM256,121"/>
    <path android:fillColor="#979fef" android:pathData="m256,331v-150c41.398,0 75,33.602 75,75s-33.602,75 -75,75zM256,331"/>
</vector>


================================================
FILE: app/src/main/res/drawable/ic_email.xml
================================================
<vector android:height="24dp" android:tint="#616363"
    android:viewportHeight="24.0" android:viewportWidth="24.0"
    android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
    <path android:fillColor="#FF000000" android:pathData="M20,4L4,4c-1.1,0 -1.99,0.9 -1.99,2L2,18c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2L22,6c0,-1.1 -0.9,-2 -2,-2zM20,8l-8,5 -8,-5L4,6l8,5 8,-5v2z"/>
</vector>


================================================
FILE: app/src/main/res/drawable/ic_launcher_background.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<vector
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:height="108dp"
        android:width="108dp"
        android:viewportHeight="108"
        android:viewportWidth="108">
    <path android:fillColor="#008577"
          android:pathData="M0,0h108v108h-108z"/>
    <path android:fillColor="#00000000" android:pathData="M9,0L9,108"
          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
    <path android:fillColor="#00000000" android:pathData="M19,0L19,108"
          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
    <path android:fillColor="#00000000" android:pathData="M29,0L29,108"
          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
    <path android:fillColor="#00000000" android:pathData="M39,0L39,108"
          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
    <path android:fillColor="#00000000" android:pathData="M49,0L49,108"
          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
    <path android:fillColor="#00000000" android:pathData="M59,0L59,108"
          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
    <path android:fillColor="#00000000" android:pathData="M69,0L69,108"
          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
    <path android:fillColor="#00000000" android:pathData="M79,0L79,108"
          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
    <path android:fillColor="#00000000" android:pathData="M89,0L89,108"
          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
    <path android:fillColor="#00000000" android:pathData="M99,0L99,108"
          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
    <path android:fillColor="#00000000" android:pathData="M0,9L108,9"
          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
    <path android:fillColor="#00000000" android:pathData="M0,19L108,19"
          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
    <path android:fillColor="#00000000" android:pathData="M0,29L108,29"
          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
    <path android:fillColor="#00000000" android:pathData="M0,39L108,39"
          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
    <path android:fillColor="#00000000" android:pathData="M0,49L108,49"
          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
    <path android:fillColor="#00000000" android:pathData="M0,59L108,59"
          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
    <path android:fillColor="#00000000" android:pathData="M0,69L108,69"
          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
    <path android:fillColor="#00000000" android:pathData="M0,79L108,79"
          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
    <path android:fillColor="#00000000" android:pathData="M0,89L108,89"
          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
    <path android:fillColor="#00000000" android:pathData="M0,99L108,99"
          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
    <path android:fillColor="#00000000" android:pathData="M19,29L89,29"
          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
    <path android:fillColor="#00000000" android:pathData="M19,39L89,39"
          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
    <path android:fillColor="#00000000" android:pathData="M19,49L89,49"
          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
    <path android:fillColor="#00000000" android:pathData="M19,59L89,59"
          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
    <path android:fillColor="#00000000" android:pathData="M19,69L89,69"
          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
    <path android:fillColor="#00000000" android:pathData="M19,79L89,79"
          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
    <path android:fillColor="#00000000" android:pathData="M29,19L29,89"
          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
    <path android:fillColor="#00000000" android:pathData="M39,19L39,89"
          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
    <path android:fillColor="#00000000" android:pathData="M49,19L49,89"
          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
    <path android:fillColor="#00000000" android:pathData="M59,19L59,89"
          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
    <path android:fillColor="#00000000" android:pathData="M69,19L69,89"
          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
    <path android:fillColor="#00000000" android:pathData="M79,19L79,89"
          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
</vector>


================================================
FILE: app/src/main/res/drawable/ic_lock.xml
================================================
<vector android:height="24dp" android:tint="#616363"
    android:viewportHeight="24.0" android:viewportWidth="24.0"
    android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
    <path android:fillColor="#FF000000" android:pathData="M18,8h-1L17,6c0,-2.76 -2.24,-5 -5,-5S7,3.24 7,6v2L6,8c-1.1,0 -2,0.9 -2,2v10c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2L20,10c0,-1.1 -0.9,-2 -2,-2zM12,17c-1.1,0 -2,-0.9 -2,-2s0.9,-2 2,-2 2,0.9 2,2 -0.9,2 -2,2zM15.1,8L8.9,8L8.9,6c0,-1.71 1.39,-3.1 3.1,-3.1 1.71,0 3.1,1.39 3.1,3.1v2z"/>
</vector>


================================================
FILE: app/src/main/res/drawable/ic_name.xml
================================================
<vector android:height="24dp" android:tint="#616363"
    android:viewportHeight="24.0" android:viewportWidth="24.0"
    android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
    <path android:fillColor="#FF000000" android:pathData="M3,5v14c0,1.1 0.89,2 2,2h14c1.1,0 2,-0.9 2,-2L21,5c0,-1.1 -0.9,-2 -2,-2L5,3c-1.11,0 -2,0.9 -2,2zM15,9c0,1.66 -1.34,3 -3,3s-3,-1.34 -3,-3 1.34,-3 3,-3 3,1.34 3,3zM6,17c0,-2 4,-3.1 6,-3.1s6,1.1 6,3.1v1L6,18v-1z"/>
</vector>


================================================
FILE: app/src/main/res/drawable-v24/ic_launcher_foreground.xml
================================================
<vector xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:aapt="http://schemas.android.com/aapt"
        android:width="108dp"
        android:height="108dp"
        android:viewportHeight="108"
        android:viewportWidth="108">
    <path
            android:fillType="evenOdd"
            android:pathData="M32,64C32,64 38.39,52.99 44.13,50.95C51.37,48.37 70.14,49.57 70.14,49.57L108.26,87.69L108,109.01L75.97,107.97L32,64Z"
            android:strokeColor="#00000000"
            android:strokeWidth="1">
        <aapt:attr name="android:fillColor">
            <gradient
                    android:endX="78.5885"
                    android:endY="90.9159"
                    android:startX="48.7653"
                    android:startY="61.0927"
                    android:type="linear">
                <item
                        android:color="#44000000"
                        android:offset="0.0"/>
                <item
                        android:color="#00000000"
                        android:offset="1.0"/>
            </gradient>
        </aapt:attr>
    </path>
    <path
            android:fillColor="#FFFFFF"
            android:fillType="nonZero"
            android:pathData="M66.94,46.02L66.94,46.02C72.44,50.07 76,56.61 76,64L32,64C32,56.61 35.56,50.11 40.98,46.06L36.18,41.19C35.45,40.45 35.45,39.3 36.18,38.56C36.91,37.81 38.05,37.81 38.78,38.56L44.25,44.05C47.18,42.57 50.48,41.71 54,41.71C57.48,41.71 60.78,42.57 63.68,44.05L69.11,38.56C69.84,37.81 70.98,37.81 71.71,38.56C72.44,39.3 72.44,40.45 71.71,41.19L66.94,46.02ZM62.94,56.92C64.08,56.92 65,56.01 65,54.88C65,53.76 64.08,52.85 62.94,52.85C61.8,52.85 60.88,53.76 60.88,54.88C60.88,56.01 61.8,56.92 62.94,56.92ZM45.06,56.92C46.2,56.92 47.13,56.01 47.13,54.88C47.13,53.76 46.2,52.85 45.06,52.85C43.92,52.85 43,53.76 43,54.88C43,56.01 43.92,56.92 45.06,56.92Z"
            android:strokeColor="#00000000"
            android:strokeWidth="1"/>
</vector>


================================================
FILE: app/src/main/res/layout/activity_home.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:id="@+id/drawer_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".ui.home.HomeActivity">

    <LinearLayout
            android:orientation="vertical"
            android:layout_width="match_parent"
            android:layout_height="match_parent">

        <androidx.appcompat.widget.Toolbar
                android:id="@+id/toolbar"
                android:background="?colorPrimary"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"/>

        <fragment
                android:name="androidx.navigation.fragment.NavHostFragment"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                app:navGraph="@navigation/nav_graph"
                app:defaultNavHost="true"
                android:id="@+id/fragment"/>
    </LinearLayout>

    <com.google.android.material.navigation.NavigationView
            android:id="@+id/nav_view"
            app:menu="@menu/nav_menu"
            android:layout_gravity="start"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"/>

</androidx.drawerlayout.widget.DrawerLayout>

================================================
FILE: app/src/main/res/layout/activity_login.xml
================================================
<?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"
        xmlns:tools="http://schemas.android.com/tools">

    <androidx.coordinatorlayout.widget.CoordinatorLayout
            android:id="@+id/root_layout"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="#E2E2E2"
            tools:context=".ui.auth.LoginActivity">


        <RelativeLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:padding="16dp">

            <ImageView
                    android:id="@+id/image_view_logo"
                    android:layout_width="80dp"
                    android:layout_height="80dp"
                    android:layout_centerHorizontal="true"
                    android:layout_marginTop="75dp"
                    android:background="@drawable/ic_app_logo" />

            <LinearLayout
                    android:id="@+id/linearLayout1"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_below="@id/image_view_logo"
                    android:orientation="vertical">

                <TextView
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_gravity="center_horizontal"
                        android:text="architect your app with"
                        android:textAppearance="@style/TextAppearance.AppCompat.Large"
                        android:textColor="#465A61"
                        app:fontFamily="cursive" />

                <TextView
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_gravity="center_horizontal"
                        android:text="MVVM"
                        android:textAllCaps="false"
                        android:textAppearance="@style/TextAppearance.AppCompat.Display2"
                        android:textColor="#969EEE"
                        android:textStyle="bold"
                        android:typeface="monospace"
                        app:fontFamily="casual" />

            </LinearLayout>

            <LinearLayout
                    android:id="@+id/linearLayout2"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_below="@id/linearLayout1"
                    android:background="#ffffff"
                    android:orientation="vertical"
                    android:padding="18dp">

                <EditText
                        android:id="@+id/edit_text_email"
                        android:layout_width="match_parent"
                        android:layout_height="match_parent"
                        android:layout_marginBottom="12dp"
                        android:background="@drawable/edit_text_round_gray_background"
                        android:drawableLeft="@drawable/ic_email"
                        android:drawablePadding="16dp"
                        android:hint="belal@gmail.com"
                        android:inputType="textEmailAddress"
                        android:padding="12dp" />

                <EditText
                        android:id="@+id/edit_text_password"
                        android:layout_width="match_parent"
                        android:layout_height="match_parent"
                        android:layout_marginBottom="12dp"
                        android:background="@drawable/edit_text_round_gray_background"
                        android:drawableLeft="@drawable/ic_lock"
                        android:drawablePadding="16dp"
                        android:hint="password"
                        android:inputType="textPassword"
                        android:padding="12dp" />

                <TextView
                        android:id="@+id/text_view_forget_password"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_marginBottom="12dp"
                        android:text="Forget Password?"
                        android:textAppearance="@style/TextAppearance.AppCompat.Medium"
                        android:textColor="@color/colorPrimaryDark" />

                <Button
                        android:id="@+id/button_sign_in"
                        android:layout_width="150dp"
                        android:layout_height="wrap_content"
                        android:layout_gravity="center_horizontal"
                        android:text="Sign In"
                        android:textAllCaps="false" />

            </LinearLayout>

            <TextView
                    android:id="@+id/text_view_sign_up"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_below="@id/linearLayout2"
                    android:layout_centerHorizontal="true"
                    android:layout_marginTop="12dp"
                    android:text="Don't have an account?\nSign Up Here"
                    android:textAlignment="center"
                    android:textAppearance="@style/TextAppearance.AppCompat.Large"
                    android:textColor="@color/colorPrimary" />

        </RelativeLayout>

        <ProgressBar
                android:id="@+id/progress_bar"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center_horizontal|center_vertical"
                android:visibility="invisible" />


    </androidx.coordinatorlayout.widget.CoordinatorLayout>

</layout>




================================================
FILE: app/src/main/res/layout/activity_signup.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<layout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        xmlns:app="http://schemas.android.com/apk/res-auto"
>

    <androidx.coordinatorlayout.widget.CoordinatorLayout
            android:layout_width="match_parent"
            android:background="#E2E2E2"
            android:layout_height="match_parent"
            tools:context=".ui.auth.SignupActivity">


        <RelativeLayout
                android:padding="16dp"
                android:layout_width="match_parent"
                android:layout_height="wrap_content">

            <ImageView
                    android:layout_marginTop="45dp"
                    android:id="@+id/image_view_logo"
                    android:layout_centerHorizontal="true"
                    android:background="@drawable/ic_app_logo"
                    android:layout_width="80dp"
                    android:layout_height="80dp"
            />

            <LinearLayout
                    android:id="@+id/linearLayout1"
                    android:layout_below="@id/image_view_logo"
                    android:orientation="vertical"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content">

                <TextView
                        android:layout_gravity="center_horizontal"
                        android:text="architect your app with"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:textAppearance="@style/TextAppearance.AppCompat.Large" app:fontFamily="cursive"
                        android:textColor="#465A61"/>

                <TextView
                        android:layout_gravity="center_horizontal"
                        android:text="MVVM"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:textAppearance="@style/TextAppearance.AppCompat.Display2"
                        app:fontFamily="casual" android:textStyle="bold" android:textAllCaps="false"
                        android:typeface="monospace" android:textColor="#969EEE"/>

            </LinearLayout>

            <LinearLayout
                    android:id="@+id/linearLayout2"
                    android:padding="18dp"
                    android:background="#ffffff"
                    android:layout_below="@id/linearLayout1"
                    android:orientation="vertical"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content">

                <EditText
                        android:id="@+id/edit_text_name"
                        android:hint="Belal Khan"
                        android:inputType="text"
                        android:drawablePadding="16dp"
                        android:drawableLeft="@drawable/ic_name"
                        android:background="@drawable/edit_text_round_gray_background"
                        android:layout_width="match_parent"
                        android:padding="12dp"
                        android:layout_marginBottom="12dp"
                        android:layout_height="match_parent"/>

                <EditText
                        android:id="@+id/edit_text_email"
                        android:hint="belal@gmail.com"
                        android:inputType="textEmailAddress"
                        android:drawablePadding="16dp"
                        android:drawableLeft="@drawable/ic_email"
                        android:background="@drawable/edit_text_round_gray_background"
                        android:layout_width="match_parent"
                        android:padding="12dp"
                        android:layout_marginBottom="12dp"
                        android:layout_height="match_parent"/>

                <EditText
                        android:id="@+id/edit_text_password"
                        android:inputType="textPassword"
                        android:hint="password"
                        android:drawablePadding="16dp"
                        android:drawableLeft="@drawable/ic_lock"
                        android:background="@drawable/edit_text_round_gray_background"
                        android:layout_width="match_parent"
                        android:layout_marginBottom="12dp"
                        android:padding="12dp"
                        android:layout_height="match_parent"/>

                <EditText
                        android:id="@+id/edit_text_password_confirm"
                        android:inputType="textPassword"
                        android:hint="confirm password"
                        android:drawablePadding="16dp"
                        android:drawableLeft="@drawable/ic_lock"
                        android:background="@drawable/edit_text_round_gray_background"
                        android:layout_width="match_parent"
                        android:layout_marginBottom="12dp"
                        android:padding="12dp"
                        android:layout_height="match_parent"/>

                <TextView
                        android:id="@+id/text_view_forget_password"
                        android:textColor="@color/colorPrimaryDark"
                        android:layout_marginBottom="12dp"
                        android:textAppearance="@style/TextAppearance.AppCompat.Medium"
                        android:text="Forget Password?"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"/>

                <Button
                        android:id="@+id/button_sign_up"
                        android:layout_gravity="center_horizontal"
                        android:textAllCaps="false"
                        android:text="Sign Up"
                        android:layout_width="150dp"
                        android:layout_height="wrap_content"/>

            </LinearLayout>

            <TextView
                    android:id="@+id/text_view_login"
                    android:layout_marginTop="12dp"
                    android:textColor="@color/colorPrimary"
                    android:layout_centerHorizontal="true"
                    android:textAppearance="@style/TextAppearance.AppCompat.Large"
                    android:layout_below="@id/linearLayout2"
                    android:textAlignment="center"
                    android:text="Already have an account?\nSign in Here"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"/>

        </RelativeLayout>

        <ProgressBar
                android:visibility="invisible"
                android:id="@+id/progress_bar"
                android:layout_gravity="center_horizontal|center_vertical"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"/>


    </androidx.coordinatorlayout.widget.CoordinatorLayout>
</layout>






================================================
FILE: app/src/main/res/layout/item_quote.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools">
    <data>
        <variable name="quote"
                  type="net.simplifiedcoding.mvvmsampleapp.data.db.entities.Quote"/>
    </data>

    <com.google.android.material.card.MaterialCardView
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

        <RelativeLayout
                android:padding="12dp"
                android:layout_width="match_parent"
                android:layout_height="match_parent">

            <TextView
                    android:textAppearance="@style/TextAppearance.AppCompat.Headline"
                    android:id="@+id/quote"
                    android:textColor="@color/colorPrimaryDark"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:text="@{`'`+quote.quote+`'`}"
                    tools:text="Success doesn’t just find you. You have to go out and get it."/>

            <TextView
                    android:textColor="@color/colorPrimary"
                    android:textAppearance="@style/TextAppearance.AppCompat.Medium"
                    tools:text="- Belal Khan"
                    android:text="@{`-` + quote.author}"
                    android:layout_alignParentEnd="true"
                    android:layout_below="@id/quote"
                    android:id="@+id/author"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_alignParentRight="true"
                    android:textStyle="italic"/>

            <TextView
                    android:layout_marginTop="7dp"
                    android:layout_below="@id/author"
                    android:background="@color/colorPrimary"
                    android:layout_width="match_parent"
                    android:layout_height="1dp"/>

        </RelativeLayout>
    </com.google.android.material.card.MaterialCardView>
</layout>

================================================
FILE: app/src/main/res/layout/profile_fragment.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<layout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
>
    <data>

        <variable name="viewmodel"
                  type="net.simplifiedcoding.mvvmsampleapp.ui.home.profile.ProfileViewModel"
        />

    </data>

    <FrameLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            tools:context=".ui.home.profile.ProfileFragment">

        <LinearLayout
                android:layout_gravity="center_horizontal|center_vertical"
                android:orientation="vertical"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content">

            <TextView
                    android:layout_gravity="center_horizontal"
                    android:text="Welcome"
                    android:textColor="@color/colorPrimary"
                    android:textAppearance="@style/TextAppearance.AppCompat.Medium"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"/>

            <TextView
                    android:layout_gravity="center_horizontal"
                    tools:text="Belal Khan"
                    android:text="@{viewmodel.user.name}"
                    android:textColor="@color/colorPrimaryDark"
                    android:textAppearance="@style/TextAppearance.AppCompat.Headline"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"/>
            <TextView
                    android:layout_gravity="center_horizontal"
                    tools:text="probelalkhan@gmail.com"
                    android:text="@{viewmodel.user.email}"
                    android:textColor="@color/colorPrimaryDark"
                    android:textAppearance="@style/TextAppearance.AppCompat.Medium"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"/>


        </LinearLayout>


    </FrameLayout>
</layout>


================================================
FILE: app/src/main/res/layout/quotes_fragment.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".ui.home.quotes.QuotesFragment">

    <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/recyclerview"
            tools:listitem="@layout/item_quote"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>

    <ProgressBar
            android:layout_gravity="center_horizontal|center_vertical"
            android:id="@+id/progress_bar"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>

</FrameLayout>

================================================
FILE: app/src/main/res/menu/nav_menu.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">

    <item
            android:title="Home"
            android:id="@+id/profileFragment"
    />

    <item
            android:title="Quotes"
            android:id="@+id/quotesFragment"
    />

</menu>

================================================
FILE: app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
    <background android:drawable="@drawable/ic_launcher_background"/>
    <foreground android:drawable="@drawable/ic_launcher_foreground"/>
</adaptive-icon>

================================================
FILE: app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
    <background android:drawable="@drawable/ic_launcher_background"/>
    <foreground android:drawable="@drawable/ic_launcher_foreground"/>
</adaptive-icon>

================================================
FILE: app/src/main/res/navigation/nav_graph.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<navigation 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/nav_graph"
            app:startDestination="@id/profileFragment">

    <fragment android:id="@+id/profileFragment"
              android:name="net.simplifiedcoding.mvvmsampleapp.ui.home.profile.ProfileFragment"
              android:label="Profile" tools:layout="@layout/profile_fragment"/>
    <fragment android:id="@+id/quotesFragment"
              android:name="net.simplifiedcoding.mvvmsampleapp.ui.home.quotes.QuotesFragment"
              android:label="Quotes" tools:layout="@layout/quotes_fragment"/>
</navigation>

================================================
FILE: app/src/main/res/values/colors.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="colorPrimary">#969EEE</color>
    <color name="colorPrimaryDark">#555C96</color>
    <color name="colorAccent">#969EEE</color>
</resources>


================================================
FILE: app/src/main/res/values/strings.xml
================================================
<resources>
    <string name="app_name">MVVM Sample App</string>
</resources>


================================================
FILE: app/src/main/res/values/styles.xml
================================================
<resources>

    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.MaterialComponents.Light.NoActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>

</resources>


================================================
FILE: app/src/test/java/net/simplifiedcoding/mvvmsampleapp/ExampleUnitTest.kt
================================================
package net.simplifiedcoding.mvvmsampleapp

import org.junit.Test

import org.junit.Assert.*

/**
 * Example local unit test, which will execute on the development machine (host).
 *
 * See [testing documentation](http://d.android.com/tools/testing).
 */
class ExampleUnitTest {
    @Test
    fun addition_isCorrect() {
        assertEquals(4, 2 + 2)
    }
}


================================================
FILE: build.gradle
================================================
// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
    ext.kotlin_version = '1.3.50'
    repositories {
        google()
        jcenter()
        
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.5.0'
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
        //Android Navigation Safe Args Classpath
        classpath "androidx.navigation:navigation-safe-args-gradle-plugin:2.2.0-alpha02"
    }
}

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

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


================================================
FILE: gradle/wrapper/gradle-wrapper.properties
================================================
#Sun Sep 15 19:06:09 KST 2019
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip


================================================
FILE: gradle.properties
================================================
# Project-wide Gradle settings.
# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
org.gradle.jvmargs=-Xmx1536m
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
# AndroidX package structure to make it clearer which packages are bundled with the
# Android operating system, and which are packaged with your app's APK
# https://developer.android.com/topic/libraries/support-library/androidx-rn
android.useAndroidX=true
# Automatically convert third-party libraries to use AndroidX
android.enableJetifier=true
# Kotlin code style for this project: "official" or "obsolete":
kotlin.code.style=official
android.databinding.enableV2=true


================================================
FILE: gradlew
================================================
#!/usr/bin/env sh

##############################################################################
##
##  Gradle start up script for UN*X
##
##############################################################################

# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
    ls=`ls -ld "$PRG"`
    link=`expr "$ls" : '.*-> \(.*\)$'`
    if expr "$link" : '/.*' > /dev/null; then
        PRG="$link"
    else
        PRG=`dirname "$PRG"`"/$link"
    fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null

APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`

# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""

# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"

warn () {
    echo "$*"
}

die () {
    echo
    echo "$*"
    echo
    exit 1
}

# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
  CYGWIN* )
    cygwin=true
    ;;
  Darwin* )
    darwin=true
    ;;
  MINGW* )
    msys=true
    ;;
  NONSTOP* )
    nonstop=true
    ;;
esac

CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar

# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
        # IBM's JDK on AIX uses strange locations for the executables
        JAVACMD="$JAVA_HOME/jre/sh/java"
    else
        JAVACMD="$JAVA_HOME/bin/java"
    fi
    if [ ! -x "$JAVACMD" ] ; then
        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME

Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
    fi
else
    JAVACMD="java"
    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.

Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi

# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
    MAX_FD_LIMIT=`ulimit -H -n`
    if [ $? -eq 0 ] ; then
        if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
            MAX_FD="$MAX_FD_LIMIT"
        fi
        ulimit -n $MAX_FD
        if [ $? -ne 0 ] ; then
            warn "Could not set maximum file descriptor limit: $MAX_FD"
        fi
    else
        warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
    fi
fi

# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
    GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi

# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
    APP_HOME=`cygpath --path --mixed "$APP_HOME"`
    CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
    JAVACMD=`cygpath --unix "$JAVACMD"`

    # We build the pattern for arguments to be converted via cygpath
    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
    SEP=""
    for dir in $ROOTDIRSRAW ; do
        ROOTDIRS="$ROOTDIRS$SEP$dir"
        SEP="|"
    done
    OURCYGPATTERN="(^($ROOTDIRS))"
    # Add a user-defined pattern to the cygpath arguments
    if [ "$GRADLE_CYGPATTERN" != "" ] ; then
        OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
    fi
    # Now convert the arguments - kludge to limit ourselves to /bin/sh
    i=0
    for arg in "$@" ; do
        CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
        CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option

        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition
            eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
        else
            eval `echo args$i`="\"$arg\""
        fi
        i=$((i+1))
    done
    case $i in
        (0) set -- ;;
        (1) set -- "$args0" ;;
        (2) set -- "$args0" "$args1" ;;
        (3) set -- "$args0" "$args1" "$args2" ;;
        (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
        (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
        (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
        (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
        (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
        (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
    esac
fi

# Escape application args
save () {
    for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
    echo " "
}
APP_ARGS=$(save "$@")

# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"

# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
  cd "$(dirname "$0")"
fi

exec "$JAVACMD" "$@"


================================================
FILE: gradlew.bat
================================================
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem  Gradle startup script for Windows
@rem
@rem ##########################################################################

@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal

set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%

@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=

@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome

set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init

echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.

goto fail

:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe

if exist "%JAVA_EXE%" goto init

echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.

goto fail

:init
@rem Get command-line arguments, handling Windows variants

if not "%OS%" == "Windows_NT" goto win9xME_args

:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2

:win9xME_args_slurp
if "x%~1" == "x" goto execute

set CMD_LINE_ARGS=%*

:execute
@rem Setup the command line

set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar

@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%

:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd

:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1

:mainEnd
if "%OS%"=="Windows_NT" endlocal

:omega


================================================
FILE: settings.gradle
================================================
include ':app'
Download .txt
gitextract_u139hf2o/

├── .gitignore
├── .idea/
│   ├── codeStyles/
│   │   ├── Project.xml
│   │   └── codeStyleConfig.xml
│   ├── encodings.xml
│   ├── gradle.xml
│   ├── misc.xml
│   ├── runConfigurations.xml
│   └── vcs.xml
├── app/
│   ├── .gitignore
│   ├── build.gradle
│   ├── proguard-rules.pro
│   └── src/
│       ├── androidTest/
│       │   └── java/
│       │       └── net/
│       │           └── simplifiedcoding/
│       │               └── mvvmsampleapp/
│       │                   └── ExampleInstrumentedTest.kt
│       ├── main/
│       │   ├── AndroidManifest.xml
│       │   ├── java/
│       │   │   └── net/
│       │   │       └── simplifiedcoding/
│       │   │           └── mvvmsampleapp/
│       │   │               ├── MVVMApplication.kt
│       │   │               ├── data/
│       │   │               │   ├── db/
│       │   │               │   │   ├── AppDatabase.kt
│       │   │               │   │   ├── QuoteDao.kt
│       │   │               │   │   ├── UserDao.kt
│       │   │               │   │   └── entities/
│       │   │               │   │       ├── Quote.kt
│       │   │               │   │       └── User.kt
│       │   │               │   ├── network/
│       │   │               │   │   ├── MyApi.kt
│       │   │               │   │   ├── NetworkConnectionInterceptor.kt
│       │   │               │   │   ├── SafeApiRequest.kt
│       │   │               │   │   └── responses/
│       │   │               │   │       ├── AuthResponse.kt
│       │   │               │   │       └── QuotesResponse.kt
│       │   │               │   ├── preferences/
│       │   │               │   │   └── PreferenceProvider.kt
│       │   │               │   └── repositories/
│       │   │               │       ├── QuotesRepository.kt
│       │   │               │       └── UserRepository.kt
│       │   │               ├── ui/
│       │   │               │   ├── auth/
│       │   │               │   │   ├── AuthViewModel.kt
│       │   │               │   │   ├── AuthViewModelFactory.kt
│       │   │               │   │   ├── LoginActivity.kt
│       │   │               │   │   └── SignupActivity.kt
│       │   │               │   └── home/
│       │   │               │       ├── HomeActivity.kt
│       │   │               │       ├── profile/
│       │   │               │       │   ├── ProfileFragment.kt
│       │   │               │       │   ├── ProfileViewModel.kt
│       │   │               │       │   └── ProfileViewModelFactory.kt
│       │   │               │       └── quotes/
│       │   │               │           ├── QuoteItem.kt
│       │   │               │           ├── QuotesFragment.kt
│       │   │               │           ├── QuotesViewModel.kt
│       │   │               │           └── QuotesViewModelFactory.kt
│       │   │               └── util/
│       │   │                   ├── Coroutines.kt
│       │   │                   ├── Delegates.kt
│       │   │                   ├── Exceptions.kt
│       │   │                   └── ViewUtils.kt
│       │   └── res/
│       │       ├── drawable/
│       │       │   ├── edit_text_round_gray_background.xml
│       │       │   ├── ic_app_logo.xml
│       │       │   ├── ic_email.xml
│       │       │   ├── ic_launcher_background.xml
│       │       │   ├── ic_lock.xml
│       │       │   └── ic_name.xml
│       │       ├── drawable-v24/
│       │       │   └── ic_launcher_foreground.xml
│       │       ├── layout/
│       │       │   ├── activity_home.xml
│       │       │   ├── activity_login.xml
│       │       │   ├── activity_signup.xml
│       │       │   ├── item_quote.xml
│       │       │   ├── profile_fragment.xml
│       │       │   └── quotes_fragment.xml
│       │       ├── menu/
│       │       │   └── nav_menu.xml
│       │       ├── mipmap-anydpi-v26/
│       │       │   ├── ic_launcher.xml
│       │       │   └── ic_launcher_round.xml
│       │       ├── navigation/
│       │       │   └── nav_graph.xml
│       │       └── values/
│       │           ├── colors.xml
│       │           ├── strings.xml
│       │           └── styles.xml
│       └── test/
│           └── java/
│               └── net/
│                   └── simplifiedcoding/
│                       └── mvvmsampleapp/
│                           └── ExampleUnitTest.kt
├── build.gradle
├── gradle/
│   └── wrapper/
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
└── settings.gradle
Condensed preview — 71 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (93K chars).
[
  {
    "path": ".gitignore",
    "chars": 203,
    "preview": "*.iml\n.gradle\n/local.properties\n/.idea/caches\n/.idea/libraries\n/.idea/modules.xml\n/.idea/workspace.xml\n/.idea/navEditor."
  },
  {
    "path": ".idea/codeStyles/Project.xml",
    "chars": 3461,
    "preview": "<component name=\"ProjectCodeStyleConfiguration\">\n  <code_scheme name=\"Project\" version=\"173\">\n    <JetCodeStyleSettings>"
  },
  {
    "path": ".idea/codeStyles/codeStyleConfig.xml",
    "chars": 142,
    "preview": "<component name=\"ProjectCodeStyleConfiguration\">\n  <state>\n    <option name=\"USE_PER_PROJECT_SETTINGS\" value=\"true\" />\n "
  },
  {
    "path": ".idea/encodings.xml",
    "chars": 135,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"Encoding\" addBOMForNewFiles=\"with NO BOM"
  },
  {
    "path": ".idea/gradle.xml",
    "chars": 748,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"GradleMigrationSettings\" migrationVersio"
  },
  {
    "path": ".idea/misc.xml",
    "chars": 515,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"CMakeSettings\">\n    <configurations>\n   "
  },
  {
    "path": ".idea/runConfigurations.xml",
    "chars": 564,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"RunConfigurationProducerService\">\n    <o"
  },
  {
    "path": ".idea/vcs.xml",
    "chars": 180,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"VcsDirectoryMappings\">\n    <mapping dire"
  },
  {
    "path": "app/.gitignore",
    "chars": 7,
    "preview": "/build\n"
  },
  {
    "path": "app/build.gradle",
    "chars": 2694,
    "preview": "apply plugin: 'com.android.application'\n\napply plugin: 'kotlin-android'\n\napply plugin: 'kotlin-android-extensions'\n\n//ko"
  },
  {
    "path": "app/proguard-rules.pro",
    "chars": 751,
    "preview": "# Add project specific ProGuard rules here.\n# You can control the set of applied configuration files using the\n# proguar"
  },
  {
    "path": "app/src/androidTest/java/net/simplifiedcoding/mvvmsampleapp/ExampleInstrumentedTest.kt",
    "chars": 656,
    "preview": "package net.simplifiedcoding.mvvmsampleapp\n\nimport androidx.test.InstrumentationRegistry\nimport androidx.test.runner.And"
  },
  {
    "path": "app/src/main/AndroidManifest.xml",
    "chars": 1230,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n          xm"
  },
  {
    "path": "app/src/main/java/net/simplifiedcoding/mvvmsampleapp/MVVMApplication.kt",
    "chars": 1771,
    "preview": "package net.simplifiedcoding.mvvmsampleapp\n\nimport android.app.Application\nimport net.simplifiedcoding.mvvmsampleapp.dat"
  },
  {
    "path": "app/src/main/java/net/simplifiedcoding/mvvmsampleapp/data/db/AppDatabase.kt",
    "chars": 1054,
    "preview": "package net.simplifiedcoding.mvvmsampleapp.data.db\n\nimport android.content.Context\nimport androidx.room.Database\nimport "
  },
  {
    "path": "app/src/main/java/net/simplifiedcoding/mvvmsampleapp/data/db/QuoteDao.kt",
    "chars": 478,
    "preview": "package net.simplifiedcoding.mvvmsampleapp.data.db\n\nimport androidx.lifecycle.LiveData\nimport androidx.room.Dao\nimport a"
  },
  {
    "path": "app/src/main/java/net/simplifiedcoding/mvvmsampleapp/data/db/UserDao.kt",
    "chars": 567,
    "preview": "package net.simplifiedcoding.mvvmsampleapp.data.db\n\nimport androidx.lifecycle.LiveData\nimport androidx.room.Dao\nimport a"
  },
  {
    "path": "app/src/main/java/net/simplifiedcoding/mvvmsampleapp/data/db/entities/Quote.kt",
    "chars": 335,
    "preview": "package net.simplifiedcoding.mvvmsampleapp.data.db.entities\n\nimport androidx.room.Entity\nimport androidx.room.PrimaryKey"
  },
  {
    "path": "app/src/main/java/net/simplifiedcoding/mvvmsampleapp/data/db/entities/User.kt",
    "chars": 489,
    "preview": "package net.simplifiedcoding.mvvmsampleapp.data.db.entities\n\nimport androidx.room.Entity\nimport androidx.room.PrimaryKey"
  },
  {
    "path": "app/src/main/java/net/simplifiedcoding/mvvmsampleapp/data/network/MyApi.kt",
    "chars": 1608,
    "preview": "package net.simplifiedcoding.mvvmsampleapp.data.network\n\nimport net.simplifiedcoding.mvvmsampleapp.data.network.response"
  },
  {
    "path": "app/src/main/java/net/simplifiedcoding/mvvmsampleapp/data/network/NetworkConnectionInterceptor.kt",
    "chars": 1291,
    "preview": "package net.simplifiedcoding.mvvmsampleapp.data.network\n\nimport android.content.Context\nimport android.net.ConnectivityM"
  },
  {
    "path": "app/src/main/java/net/simplifiedcoding/mvvmsampleapp/data/network/SafeApiRequest.kt",
    "chars": 870,
    "preview": "package net.simplifiedcoding.mvvmsampleapp.data.network\n\nimport net.simplifiedcoding.mvvmsampleapp.util.ApiException\nimp"
  },
  {
    "path": "app/src/main/java/net/simplifiedcoding/mvvmsampleapp/data/network/responses/AuthResponse.kt",
    "chars": 237,
    "preview": "package net.simplifiedcoding.mvvmsampleapp.data.network.responses\n\nimport net.simplifiedcoding.mvvmsampleapp.data.db.ent"
  },
  {
    "path": "app/src/main/java/net/simplifiedcoding/mvvmsampleapp/data/network/responses/QuotesResponse.kt",
    "chars": 221,
    "preview": "package net.simplifiedcoding.mvvmsampleapp.data.network.responses\n\nimport net.simplifiedcoding.mvvmsampleapp.data.db.ent"
  },
  {
    "path": "app/src/main/java/net/simplifiedcoding/mvvmsampleapp/data/preferences/PreferenceProvider.kt",
    "chars": 710,
    "preview": "package net.simplifiedcoding.mvvmsampleapp.data.preferences\n\nimport android.content.Context\nimport android.content.Share"
  },
  {
    "path": "app/src/main/java/net/simplifiedcoding/mvvmsampleapp/data/repositories/QuotesRepository.kt",
    "chars": 1997,
    "preview": "package net.simplifiedcoding.mvvmsampleapp.data.repositories\n\nimport androidx.lifecycle.LiveData\nimport androidx.lifecyc"
  },
  {
    "path": "app/src/main/java/net/simplifiedcoding/mvvmsampleapp/data/repositories/UserRepository.kt",
    "chars": 984,
    "preview": "package net.simplifiedcoding.mvvmsampleapp.data.repositories\n\nimport net.simplifiedcoding.mvvmsampleapp.data.db.AppDatab"
  },
  {
    "path": "app/src/main/java/net/simplifiedcoding/mvvmsampleapp/ui/auth/AuthViewModel.kt",
    "chars": 851,
    "preview": "package net.simplifiedcoding.mvvmsampleapp.ui.auth\n\nimport androidx.lifecycle.ViewModel\nimport kotlinx.coroutines.Dispat"
  },
  {
    "path": "app/src/main/java/net/simplifiedcoding/mvvmsampleapp/ui/auth/AuthViewModelFactory.kt",
    "chars": 474,
    "preview": "package net.simplifiedcoding.mvvmsampleapp.ui.auth\n\nimport androidx.lifecycle.ViewModel\nimport androidx.lifecycle.ViewMo"
  },
  {
    "path": "app/src/main/java/net/simplifiedcoding/mvvmsampleapp/ui/auth/LoginActivity.kt",
    "chars": 2520,
    "preview": "package net.simplifiedcoding.mvvmsampleapp.ui.auth\n\nimport android.content.Intent\nimport android.os.Bundle\nimport androi"
  },
  {
    "path": "app/src/main/java/net/simplifiedcoding/mvvmsampleapp/ui/auth/SignupActivity.kt",
    "chars": 2706,
    "preview": "package net.simplifiedcoding.mvvmsampleapp.ui.auth\n\nimport android.content.Intent\nimport androidx.appcompat.app.AppCompa"
  },
  {
    "path": "app/src/main/java/net/simplifiedcoding/mvvmsampleapp/ui/home/HomeActivity.kt",
    "chars": 974,
    "preview": "package net.simplifiedcoding.mvvmsampleapp.ui.home\n\nimport androidx.appcompat.app.AppCompatActivity\nimport android.os.Bu"
  },
  {
    "path": "app/src/main/java/net/simplifiedcoding/mvvmsampleapp/ui/home/profile/ProfileFragment.kt",
    "chars": 1220,
    "preview": "package net.simplifiedcoding.mvvmsampleapp.ui.home.profile\n\nimport androidx.lifecycle.ViewModelProviders\nimport android."
  },
  {
    "path": "app/src/main/java/net/simplifiedcoding/mvvmsampleapp/ui/home/profile/ProfileViewModel.kt",
    "chars": 286,
    "preview": "package net.simplifiedcoding.mvvmsampleapp.ui.home.profile\n\nimport androidx.lifecycle.ViewModel;\nimport net.simplifiedco"
  },
  {
    "path": "app/src/main/java/net/simplifiedcoding/mvvmsampleapp/ui/home/profile/ProfileViewModelFactory.kt",
    "chars": 488,
    "preview": "package net.simplifiedcoding.mvvmsampleapp.ui.home.profile\n\nimport androidx.lifecycle.ViewModel\nimport androidx.lifecycl"
  },
  {
    "path": "app/src/main/java/net/simplifiedcoding/mvvmsampleapp/ui/home/quotes/QuoteItem.kt",
    "chars": 540,
    "preview": "package net.simplifiedcoding.mvvmsampleapp.ui.home.quotes\n\nimport com.xwray.groupie.databinding.BindableItem\nimport net."
  },
  {
    "path": "app/src/main/java/net/simplifiedcoding/mvvmsampleapp/ui/home/quotes/QuotesFragment.kt",
    "chars": 2264,
    "preview": "package net.simplifiedcoding.mvvmsampleapp.ui.home.quotes\n\nimport androidx.lifecycle.ViewModelProviders\nimport android.o"
  },
  {
    "path": "app/src/main/java/net/simplifiedcoding/mvvmsampleapp/ui/home/quotes/QuotesViewModel.kt",
    "chars": 381,
    "preview": "package net.simplifiedcoding.mvvmsampleapp.ui.home.quotes\n\nimport androidx.lifecycle.ViewModel;\nimport net.simplifiedcod"
  },
  {
    "path": "app/src/main/java/net/simplifiedcoding/mvvmsampleapp/ui/home/quotes/QuotesViewModelFactory.kt",
    "chars": 564,
    "preview": "package net.simplifiedcoding.mvvmsampleapp.ui.home.quotes\n\nimport androidx.lifecycle.ViewModel\nimport androidx.lifecycle"
  },
  {
    "path": "app/src/main/java/net/simplifiedcoding/mvvmsampleapp/util/Coroutines.kt",
    "chars": 426,
    "preview": "package net.simplifiedcoding.mvvmsampleapp.util\n\nimport kotlinx.coroutines.CoroutineScope\nimport kotlinx.coroutines.Disp"
  },
  {
    "path": "app/src/main/java/net/simplifiedcoding/mvvmsampleapp/util/Delegates.kt",
    "chars": 280,
    "preview": "package net.simplifiedcoding.mvvmsampleapp.util\n\nimport kotlinx.coroutines.*\n\nfun<T> lazyDeferred(block: suspend Corouti"
  },
  {
    "path": "app/src/main/java/net/simplifiedcoding/mvvmsampleapp/util/Exceptions.kt",
    "chars": 201,
    "preview": "package net.simplifiedcoding.mvvmsampleapp.util\n\nimport java.io.IOException\n\nclass ApiException(message: String) : IOExc"
  },
  {
    "path": "app/src/main/java/net/simplifiedcoding/mvvmsampleapp/util/ViewUtils.kt",
    "chars": 634,
    "preview": "package net.simplifiedcoding.mvvmsampleapp.util\n\nimport android.content.Context\nimport android.view.View\nimport android."
  },
  {
    "path": "app/src/main/res/drawable/edit_text_round_gray_background.xml",
    "chars": 392,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<shape xmlns:android=\"http://schemas.android.com/apk/res/android\"\n       android:"
  },
  {
    "path": "app/src/main/res/drawable/ic_app_logo.xml",
    "chars": 3393,
    "preview": "<vector android:height=\"24dp\" android:viewportHeight=\"512\"\n    android:viewportWidth=\"512\" android:width=\"24dp\" xmlns:an"
  },
  {
    "path": "app/src/main/res/drawable/ic_email.xml",
    "chars": 408,
    "preview": "<vector android:height=\"24dp\" android:tint=\"#616363\"\n    android:viewportHeight=\"24.0\" android:viewportWidth=\"24.0\"\n    "
  },
  {
    "path": "app/src/main/res/drawable/ic_launcher_background.xml",
    "chars": 4887,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<vector\n        xmlns:android=\"http://schemas.android.com/apk/res/android\"\n      "
  },
  {
    "path": "app/src/main/res/drawable/ic_lock.xml",
    "chars": 548,
    "preview": "<vector android:height=\"24dp\" android:tint=\"#616363\"\n    android:viewportHeight=\"24.0\" android:viewportWidth=\"24.0\"\n    "
  },
  {
    "path": "app/src/main/res/drawable/ic_name.xml",
    "chars": 481,
    "preview": "<vector android:height=\"24dp\" android:tint=\"#616363\"\n    android:viewportHeight=\"24.0\" android:viewportWidth=\"24.0\"\n    "
  },
  {
    "path": "app/src/main/res/drawable-v24/ic_launcher_foreground.xml",
    "chars": 1969,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n        xmlns:aapt=\"http://schemas.android.com/aapt\"\n"
  },
  {
    "path": "app/src/main/res/layout/activity_home.xml",
    "chars": 1528,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<androidx.drawerlayout.widget.DrawerLayout\n        xmlns:android=\"http://schemas."
  },
  {
    "path": "app/src/main/res/layout/activity_login.xml",
    "chars": 6029,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n        xmlns:"
  },
  {
    "path": "app/src/main/res/layout/activity_signup.xml",
    "chars": 7170,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layout\n        xmlns:android=\"http://schemas.android.com/apk/res/android\"\n      "
  },
  {
    "path": "app/src/main/res/layout/item_quote.xml",
    "chars": 2144,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n        xmlns:"
  },
  {
    "path": "app/src/main/res/layout/profile_fragment.xml",
    "chars": 2124,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layout\n        xmlns:android=\"http://schemas.android.com/apk/res/android\"\n      "
  },
  {
    "path": "app/src/main/res/layout/quotes_fragment.xml",
    "chars": 803,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<FrameLayout\n        xmlns:android=\"http://schemas.android.com/apk/res/android\"\n "
  },
  {
    "path": "app/src/main/res/menu/nav_menu.xml",
    "chars": 308,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<menu xmlns:android=\"http://schemas.android.com/apk/res/android\">\n\n    <item\n    "
  },
  {
    "path": "app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml",
    "chars": 270,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<adaptive-icon xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <b"
  },
  {
    "path": "app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml",
    "chars": 270,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<adaptive-icon xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <b"
  },
  {
    "path": "app/src/main/res/navigation/nav_graph.xml",
    "chars": 774,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<navigation xmlns:android=\"http://schemas.android.com/apk/res/android\"\n          "
  },
  {
    "path": "app/src/main/res/values/colors.xml",
    "chars": 208,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <color name=\"colorPrimary\">#969EEE</color>\n    <color name=\"color"
  },
  {
    "path": "app/src/main/res/values/strings.xml",
    "chars": 78,
    "preview": "<resources>\n    <string name=\"app_name\">MVVM Sample App</string>\n</resources>\n"
  },
  {
    "path": "app/src/main/res/values/styles.xml",
    "chars": 390,
    "preview": "<resources>\n\n    <!-- Base application theme. -->\n    <style name=\"AppTheme\" parent=\"Theme.MaterialComponents.Light.NoAc"
  },
  {
    "path": "app/src/test/java/net/simplifiedcoding/mvvmsampleapp/ExampleUnitTest.kt",
    "chars": 359,
    "preview": "package net.simplifiedcoding.mvvmsampleapp\n\nimport org.junit.Test\n\nimport org.junit.Assert.*\n\n/**\n * Example local unit "
  },
  {
    "path": "build.gradle",
    "chars": 799,
    "preview": "// Top-level build file where you can add configuration options common to all sub-projects/modules.\n\nbuildscript {\n    e"
  },
  {
    "path": "gradle/wrapper/gradle-wrapper.properties",
    "chars": 232,
    "preview": "#Sun Sep 15 19:06:09 KST 2019\ndistributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\nzipStoreBase=GRADLE_USER_"
  },
  {
    "path": "gradle.properties",
    "chars": 1197,
    "preview": "# Project-wide Gradle settings.\n# IDE (e.g. Android Studio) users:\n# Gradle settings configured through the IDE *will ov"
  },
  {
    "path": "gradlew",
    "chars": 5296,
    "preview": "#!/usr/bin/env sh\n\n##############################################################################\n##\n##  Gradle start up"
  },
  {
    "path": "gradlew.bat",
    "chars": 2176,
    "preview": "@if \"%DEBUG%\" == \"\" @echo off\n@rem ##########################################################################\n@rem\n@rem "
  },
  {
    "path": "settings.gradle",
    "chars": 15,
    "preview": "include ':app'\n"
  }
]

// ... and 1 more files (download for full content)

About this extraction

This page contains the full source code of the probelalkhan/android-mvvm-architecture GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 71 files (81.0 KB), approximately 22.9k tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!