diff --git a/client/build.gradle b/client/build.gradle
index 5cab0595..d4c99c64 100644
--- a/client/build.gradle
+++ b/client/build.gradle
@@ -15,8 +15,8 @@ android {
applicationId "com.jraska.github.client"
minSdkVersion 21
targetSdkVersion 28
- versionName '0.15.7'
- versionCode 47
+ versionName '0.16.0'
+ versionCode 48
multiDexEnabled true
testInstrumentationRunner "com.jraska.github.client.TestRunner"
@@ -62,7 +62,7 @@ android {
unitTests.returnDefaultValues = true
}
- dynamicFeatures = [":feature:about"]
+ dynamicFeatures = [":feature:about", ":feature:settings"]
}
dependencies {
@@ -74,7 +74,7 @@ dependencies {
api project(':lib-dynamic-features')
api project(':feature:push')
api project(':feature:users')
- api project(':feature:settings')
+ api project(':feature:settings_entrance')
api project(':feature:about_entrance')
api project(':feature:shortcuts')
diff --git a/client/src/main/java/com/jraska/github/client/AppComponent.kt b/client/src/main/java/com/jraska/github/client/AppComponent.kt
index 677d4838..21734e45 100644
--- a/client/src/main/java/com/jraska/github/client/AppComponent.kt
+++ b/client/src/main/java/com/jraska/github/client/AppComponent.kt
@@ -11,7 +11,7 @@ import com.jraska.github.client.http.HttpComponent
import com.jraska.github.client.identity.IdentityModule
import com.jraska.github.client.identity.IdentityProvider
import com.jraska.github.client.push.PushModule
-import com.jraska.github.client.settings.SettingsModule
+import com.jraska.github.client.settings.entrance.SettingsEntranceModule
import com.jraska.github.client.shortcuts.ShortcutsModule
import com.jraska.github.client.users.UsersModule
import dagger.BindsInstance
@@ -27,7 +27,7 @@ import dagger.Subcomponent
IdentityModule::class,
UsersModule::class,
PushModule::class,
- SettingsModule::class,
+ SettingsEntranceModule::class,
AboutFeatureEntranceModule::class,
ShortcutsModule::class],
dependencies = [
diff --git a/feature/settings/build.gradle b/feature/settings/build.gradle
index dd7c0712..52764183 100644
--- a/feature/settings/build.gradle
+++ b/feature/settings/build.gradle
@@ -1,4 +1,4 @@
-apply plugin: 'com.android.library'
+apply plugin: 'com.android.dynamic-feature'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'
apply plugin: 'kotlin-android-extensions'
@@ -18,6 +18,8 @@ android {
dependencies {
api project(':core')
api project(':core-android')
+ implementation project(':lib-dynamic-features')
+ implementation project(':client')
api 'com.airbnb.android:epoxy:3.7.0'
api 'com.jraska:console:1.0.0'
diff --git a/feature/settings/src/main/AndroidManifest.xml b/feature/settings/src/main/AndroidManifest.xml
index 295df240..1585df3a 100644
--- a/feature/settings/src/main/AndroidManifest.xml
+++ b/feature/settings/src/main/AndroidManifest.xml
@@ -1,7 +1,18 @@
-
+
+
+
+
+
+
+
diff --git a/feature/settings/src/main/java/com/jraska/github/client/settings/SettingsActivity.kt b/feature/settings/src/main/java/com/jraska/github/client/settings/SettingsActivity.kt
index dac1df31..653f2de8 100644
--- a/feature/settings/src/main/java/com/jraska/github/client/settings/SettingsActivity.kt
+++ b/feature/settings/src/main/java/com/jraska/github/client/settings/SettingsActivity.kt
@@ -1,17 +1,31 @@
package com.jraska.github.client.settings
import android.app.Activity
+import android.content.Context
import android.content.Intent
import android.os.Bundle
+import androidx.lifecycle.ViewModelProvider
+import androidx.lifecycle.ViewModelProviders
import androidx.recyclerview.widget.LinearLayoutManager
import com.airbnb.epoxy.SimpleEpoxyAdapter
+import com.google.android.play.core.splitcompat.SplitCompat
+import com.jraska.github.client.DynamicFeaturesComponent
import com.jraska.github.client.core.android.BaseActivity
-import com.jraska.github.client.core.android.viewModel
+import com.jraska.github.client.core.android.ViewModelFactory
+import com.jraska.github.client.dynamicFeaturesComponent
+import dagger.Component
import kotlinx.android.synthetic.main.activity_settings.toolbar
import kotlinx.android.synthetic.main.content_settings.settings_recycler
internal class SettingsActivity : BaseActivity() {
- private val viewModel: SettingsViewModel by lazy { viewModel(SettingsViewModel::class.java) }
+ private val viewModel: SettingsViewModel by lazy {
+ ViewModelProviders.of(this, viewModelFactory()).get(SettingsViewModel::class.java)
+ }
+
+ override fun attachBaseContext(newBase: Context?) {
+ super.attachBaseContext(newBase)
+ SplitCompat.install(this)
+ }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -29,10 +43,18 @@ internal class SettingsActivity : BaseActivity() {
viewModel.onPurchaseSubmitted(value)
}
- companion object {
- fun start(inActivity: Activity) {
- val intent = Intent(inActivity, SettingsActivity::class.java)
- inActivity.startActivity(intent)
- }
+ private fun viewModelFactory(): ViewModelProvider.Factory {
+ return DaggerSettingsComponent.builder()
+ .dynamicFeaturesComponent(dynamicFeaturesComponent())
+ .build()
+ .viewModelFactory()
}
}
+
+@Component(
+ modules = [SettingsModule::class],
+ dependencies = [DynamicFeaturesComponent::class]
+)
+internal interface SettingsComponent {
+ fun viewModelFactory(): ViewModelFactory
+}
diff --git a/feature/settings/src/main/java/com/jraska/github/client/settings/SettingsFeature.kt b/feature/settings/src/main/java/com/jraska/github/client/settings/SettingsFeature.kt
new file mode 100644
index 00000000..c633f6aa
--- /dev/null
+++ b/feature/settings/src/main/java/com/jraska/github/client/settings/SettingsFeature.kt
@@ -0,0 +1,13 @@
+package com.jraska.github.client.settings
+
+import androidx.annotation.Keep
+import com.jraska.github.client.dynamicbase.DynamicFeature
+import timber.log.Timber
+
+@Keep // used by reflection
+class SettingsFeature : DynamicFeature {
+ override fun onFeatureCreate() {
+ SetupConsoleLogging().onCreate()
+ Timber.i("Settings feature loaded")
+ }
+}
diff --git a/feature/settings/src/main/java/com/jraska/github/client/settings/SettingsModule.kt b/feature/settings/src/main/java/com/jraska/github/client/settings/SettingsModule.kt
index 023d64ac..ec8f7b71 100644
--- a/feature/settings/src/main/java/com/jraska/github/client/settings/SettingsModule.kt
+++ b/feature/settings/src/main/java/com/jraska/github/client/settings/SettingsModule.kt
@@ -1,15 +1,10 @@
package com.jraska.github.client.settings
-import android.app.Activity
import androidx.lifecycle.ViewModel
-import com.jraska.github.client.core.android.LinkLauncher
-import com.jraska.github.client.core.android.OnAppCreate
import dagger.Module
import dagger.Provides
import dagger.multibindings.ClassKey
import dagger.multibindings.IntoMap
-import dagger.multibindings.IntoSet
-import okhttp3.HttpUrl
@Module
object SettingsModule {
@@ -20,31 +15,4 @@ object SettingsModule {
internal fun provideUserDetailModel(viewModel: SettingsViewModel): ViewModel {
return viewModel
}
-
- @JvmStatic
- @Provides
- @IntoSet
- internal fun consoleLoggingSetup(): OnAppCreate {
- return SetupConsoleLogging()
- }
-
- @JvmStatic
- @Provides
- @IntoSet
- internal fun provideSettingsLauncher(): LinkLauncher {
- return object : LinkLauncher {
- override fun launch(inActivity: Activity, deepLink: HttpUrl): LinkLauncher.Result {
- return if ("/settings" == deepLink.encodedPath) {
- SettingsActivity.start(inActivity)
- LinkLauncher.Result.LAUNCHED
- } else {
- LinkLauncher.Result.NOT_LAUNCHED
- }
- }
-
- override fun priority(): LinkLauncher.Priority {
- return LinkLauncher.Priority.EXACT_MATCH
- }
- }
- }
}
diff --git a/feature/settings/src/main/java/com/jraska/github/client/settings/SettingsViewModel.kt b/feature/settings/src/main/java/com/jraska/github/client/settings/SettingsViewModel.kt
index 04d7d5c4..25edfe02 100644
--- a/feature/settings/src/main/java/com/jraska/github/client/settings/SettingsViewModel.kt
+++ b/feature/settings/src/main/java/com/jraska/github/client/settings/SettingsViewModel.kt
@@ -5,7 +5,10 @@ import com.jraska.github.client.analytics.AnalyticsEvent
import com.jraska.github.client.analytics.EventAnalytics
import javax.inject.Inject
-internal class SettingsViewModel @Inject constructor(private val eventAnalytics: EventAnalytics) : ViewModel() {
+internal class SettingsViewModel @Inject
+constructor(
+ private val eventAnalytics: EventAnalytics
+) : ViewModel() {
fun onPurchaseSubmitted(value: String) {
val money = value.toDoubleOrNull() ?: return
diff --git a/feature/settings/src/main/java/com/jraska/github/client/settings/SetupConsoleLogging.kt b/feature/settings/src/main/java/com/jraska/github/client/settings/SetupConsoleLogging.kt
index 1a32076e..85d64e4b 100644
--- a/feature/settings/src/main/java/com/jraska/github/client/settings/SetupConsoleLogging.kt
+++ b/feature/settings/src/main/java/com/jraska/github/client/settings/SetupConsoleLogging.kt
@@ -1,13 +1,11 @@
package com.jraska.github.client.settings
-import android.app.Application
import android.util.Log
import com.jraska.console.timber.ConsoleTree
-import com.jraska.github.client.core.android.OnAppCreate
import timber.log.Timber
-internal class SetupConsoleLogging : OnAppCreate {
- override fun onCreate(app: Application) {
+internal class SetupConsoleLogging {
+ fun onCreate() {
if (BuildConfig.DEBUG) {
Timber.plant(ConsoleTree.create())
} else {
diff --git a/feature/settings_entrance/.gitignore b/feature/settings_entrance/.gitignore
new file mode 100644
index 00000000..796b96d1
--- /dev/null
+++ b/feature/settings_entrance/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/feature/settings_entrance/build.gradle b/feature/settings_entrance/build.gradle
new file mode 100644
index 00000000..4a14173c
--- /dev/null
+++ b/feature/settings_entrance/build.gradle
@@ -0,0 +1,25 @@
+apply plugin: 'com.android.library'
+apply plugin: 'kotlin-android'
+apply plugin: 'kotlin-kapt'
+apply plugin: 'kotlin-android-extensions'
+
+android {
+ compileSdkVersion 28
+ defaultConfig {
+ minSdkVersion 21
+ }
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+}
+
+dependencies {
+ api project(':core')
+ api project(':core-android')
+ implementation project(':lib-dynamic-features')
+
+ implementation 'com.google.dagger:dagger:2.24'
+ kapt 'com.google.dagger:dagger-compiler:2.24'
+}
diff --git a/feature/settings_entrance/src/main/AndroidManifest.xml b/feature/settings_entrance/src/main/AndroidManifest.xml
new file mode 100644
index 00000000..875234aa
--- /dev/null
+++ b/feature/settings_entrance/src/main/AndroidManifest.xml
@@ -0,0 +1 @@
+
diff --git a/feature/settings_entrance/src/main/java/com/jraska/github/client/settings/entrance/SettingsEntranceModule.kt b/feature/settings_entrance/src/main/java/com/jraska/github/client/settings/entrance/SettingsEntranceModule.kt
new file mode 100644
index 00000000..2f9e85c8
--- /dev/null
+++ b/feature/settings_entrance/src/main/java/com/jraska/github/client/settings/entrance/SettingsEntranceModule.kt
@@ -0,0 +1,28 @@
+package com.jraska.github.client.settings.entrance
+
+import android.content.Context
+import com.jraska.github.client.about.entrance.internal.DynamicSettingsLinkLauncher
+import com.jraska.github.client.about.entrance.internal.ReflectiveSettingsFeatureProvider
+import com.jraska.github.client.core.android.LinkLauncher
+import com.jraska.github.client.dynamicbase.DynamicFeatureSpec
+import dagger.Module
+import dagger.Provides
+import dagger.multibindings.IntoSet
+
+@Module
+object SettingsEntranceModule {
+ @JvmStatic
+ @Provides
+ @IntoSet
+ internal fun provideSettingsLauncher(launcher: DynamicSettingsLinkLauncher): LinkLauncher {
+ return launcher
+ }
+
+ @JvmStatic
+ @Provides
+ @IntoSet
+ internal fun featureProvider(context: Context): DynamicFeatureSpec {
+ val settingsFeatureName = context.getString(R.string.title_dynamic_feature_settings)
+ return DynamicFeatureSpec(settingsFeatureName, ReflectiveSettingsFeatureProvider())
+ }
+}
diff --git a/feature/settings_entrance/src/main/java/com/jraska/github/client/settings/entrance/internal/DynamicSettingsLinkLauncher.kt b/feature/settings_entrance/src/main/java/com/jraska/github/client/settings/entrance/internal/DynamicSettingsLinkLauncher.kt
new file mode 100644
index 00000000..e54eff31
--- /dev/null
+++ b/feature/settings_entrance/src/main/java/com/jraska/github/client/settings/entrance/internal/DynamicSettingsLinkLauncher.kt
@@ -0,0 +1,47 @@
+package com.jraska.github.client.about.entrance.internal
+
+import android.app.Activity
+import android.content.Intent
+import com.jraska.github.client.core.android.LinkLauncher
+import com.jraska.github.client.core.android.TopActivityProvider
+import com.jraska.github.client.dynamicbase.DynamicFeatureInstaller
+import com.jraska.github.client.rx.AppSchedulers
+import com.jraska.github.client.settings.entrance.R
+import okhttp3.HttpUrl
+import timber.log.Timber
+import javax.inject.Inject
+
+internal class DynamicSettingsLinkLauncher @Inject constructor(
+ val installer: DynamicFeatureInstaller,
+ val appSchedulers: AppSchedulers,
+ val topActivityProvider: TopActivityProvider
+) : LinkLauncher {
+ override fun launch(inActivity: Activity, deepLink: HttpUrl): LinkLauncher.Result {
+ return if ("/settings" == deepLink.encodedPath) {
+ installAndLaunchSettingsFeature(inActivity)
+ LinkLauncher.Result.LAUNCHED
+ } else {
+ LinkLauncher.Result.NOT_LAUNCHED
+ }
+ }
+
+ override fun priority(): LinkLauncher.Priority = LinkLauncher.Priority.EXACT_MATCH
+
+ private fun installAndLaunchSettingsFeature(inActivity: Activity) {
+ val aboutFeature = inActivity.getString(R.string.title_dynamic_feature_settings)
+
+ installer.ensureInstalled(aboutFeature)
+ .subscribeOn(appSchedulers.io)
+ .observeOn(appSchedulers.mainThread)
+ .subscribe({
+ val activity = topActivityProvider.get()
+ activity.startActivity(launchIntent(activity))
+ }, { Timber.e(it) })
+ }
+
+ private fun launchIntent(inActivity: Activity): Intent {
+ return Intent().apply {
+ setClassName(inActivity.packageName, "com.jraska.github.client.settings.SettingsActivity")
+ }
+ }
+}
diff --git a/feature/settings_entrance/src/main/java/com/jraska/github/client/settings/entrance/internal/ReflectiveSettingsFeatureProvider.kt b/feature/settings_entrance/src/main/java/com/jraska/github/client/settings/entrance/internal/ReflectiveSettingsFeatureProvider.kt
new file mode 100644
index 00000000..513d1fca
--- /dev/null
+++ b/feature/settings_entrance/src/main/java/com/jraska/github/client/settings/entrance/internal/ReflectiveSettingsFeatureProvider.kt
@@ -0,0 +1,10 @@
+package com.jraska.github.client.about.entrance.internal
+
+import com.jraska.github.client.dynamicbase.DynamicFeature
+import javax.inject.Provider
+
+internal class ReflectiveSettingsFeatureProvider : Provider {
+ override fun get(): DynamicFeature {
+ return Class.forName("com.jraska.github.client.settings.SettingsFeature").newInstance() as DynamicFeature
+ }
+}
diff --git a/feature/settings_entrance/src/main/res/values/strings.xml b/feature/settings_entrance/src/main/res/values/strings.xml
new file mode 100644
index 00000000..446e8daf
--- /dev/null
+++ b/feature/settings_entrance/src/main/res/values/strings.xml
@@ -0,0 +1,3 @@
+
+ settings
+
diff --git a/settings.gradle b/settings.gradle
index 8c8c75fa..133530c7 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -9,6 +9,7 @@ include ':client',
':feature:users',
':feature:push',
+ ':feature:settings_entrance',
':feature:settings',
':feature:about_entrance',
':feature:about',