diff --git a/UIViews/build.gradle b/UIViews/build.gradle
index bc2f87d6b..a92010e3d 100644
--- a/UIViews/build.gradle
+++ b/UIViews/build.gradle
@@ -63,6 +63,8 @@ dependencies {
 
     implementation 'com.github.pwittchen:reactivenetwork-rx2:3.0.8'
 
+    implementation koin.koin
+
     implementation project(':Models')
     implementation project(':favoritesdatabase')
 
diff --git a/UIViews/src/main/java/com/programmersbox/uiviews/AllFragment.kt b/UIViews/src/main/java/com/programmersbox/uiviews/AllFragment.kt
index 939dca0ec..ce3d7f1bc 100644
--- a/UIViews/src/main/java/com/programmersbox/uiviews/AllFragment.kt
+++ b/UIViews/src/main/java/com/programmersbox/uiviews/AllFragment.kt
@@ -64,7 +64,7 @@ class AllFragment : BaseListFragment() {
 
         binding.allList.apply {
             adapter = this@AllFragment.adapter
-            layoutManager = createLayoutManager(this@AllFragment.requireContext())
+            layoutManager = info.createLayoutManager(this@AllFragment.requireContext())
             addOnScrollListener(object : EndlessScrollingListener(layoutManager!!) {
                 override fun onLoadMore(page: Int, totalItemsCount: Int, view: RecyclerView?) {
                     if (sourcePublish.value!!.canScroll && binding.searchInfo.text.isNullOrEmpty()) {
diff --git a/UIViews/src/main/java/com/programmersbox/uiviews/BaseListFragment.kt b/UIViews/src/main/java/com/programmersbox/uiviews/BaseListFragment.kt
index 1472fb2f4..fa5b3a2b9 100644
--- a/UIViews/src/main/java/com/programmersbox/uiviews/BaseListFragment.kt
+++ b/UIViews/src/main/java/com/programmersbox/uiviews/BaseListFragment.kt
@@ -4,12 +4,15 @@ import android.os.Bundle
 import android.view.View
 import androidx.annotation.CallSuper
 import androidx.recyclerview.widget.RecyclerView
+import org.koin.android.ext.android.inject
 
-abstract class BaseListFragment : BaseFragment(), GenericInfo by BaseMainActivity.genericInfo {
+abstract class BaseListFragment : BaseFragment() {
     protected lateinit var adapter: ItemListAdapter<RecyclerView.ViewHolder>
 
+    protected val info: GenericInfo by inject()
+
     @CallSuper
     override fun viewCreated(view: View, savedInstanceState: Bundle?) {
-        adapter = createAdapter(this@BaseListFragment.requireContext(), this)
+        adapter = info.createAdapter(this@BaseListFragment.requireContext(), this)
     }
 }
\ No newline at end of file
diff --git a/UIViews/src/main/java/com/programmersbox/uiviews/BaseMainActivity.kt b/UIViews/src/main/java/com/programmersbox/uiviews/BaseMainActivity.kt
index c62ceb49c..7b5249750 100644
--- a/UIViews/src/main/java/com/programmersbox/uiviews/BaseMainActivity.kt
+++ b/UIViews/src/main/java/com/programmersbox/uiviews/BaseMainActivity.kt
@@ -16,22 +16,23 @@ import com.squareup.okhttp.Request
 import io.reactivex.disposables.CompositeDisposable
 import io.reactivex.rxkotlin.addTo
 import kotlinx.coroutines.launch
-import kotlin.properties.Delegates
+import org.koin.android.ext.android.inject
 
-abstract class BaseMainActivity : AppCompatActivity(), GenericInfo {
+abstract class BaseMainActivity : AppCompatActivity() {
 
     protected val disposable = CompositeDisposable()
 
     private var currentNavController: LiveData<NavController>? = null
 
+    protected val genericInfo: GenericInfo by inject()
+
     protected abstract fun onCreate()
 
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
-        genericInfo = this
         setContentView(R.layout.base_main_activity)
 
-        toSource(currentService.orEmpty())?.let { sourcePublish.onNext(it) }
+        genericInfo.toSource(currentService.orEmpty())?.let { sourcePublish.onNext(it) }
 
         if (savedInstanceState == null) {
             setupBottomNavBar()
@@ -112,8 +113,4 @@ abstract class BaseMainActivity : AppCompatActivity(), GenericInfo {
         super.onDestroy()
     }
 
-    companion object {
-        var genericInfo by Delegates.notNull<GenericInfo>()
-    }
-
 }
\ No newline at end of file
diff --git a/UIViews/src/main/java/com/programmersbox/uiviews/DetailsFragment.kt b/UIViews/src/main/java/com/programmersbox/uiviews/DetailsFragment.kt
index 680097bf9..cd704e102 100644
--- a/UIViews/src/main/java/com/programmersbox/uiviews/DetailsFragment.kt
+++ b/UIViews/src/main/java/com/programmersbox/uiviews/DetailsFragment.kt
@@ -36,6 +36,7 @@ import io.reactivex.rxkotlin.subscribeBy
 import io.reactivex.schedulers.Schedulers
 import io.reactivex.subjects.BehaviorSubject
 import me.zhanghai.android.fastscroll.FastScrollerBuilder
+import org.koin.android.ext.android.inject
 
 class DetailsFragment : Fragment() {
 
@@ -51,7 +52,7 @@ class DetailsFragment : Fragment() {
 
     private val disposable = CompositeDisposable()
 
-    private val adapter by lazy { ChapterAdapter(requireContext(), BaseMainActivity.genericInfo, dao) }
+    private val adapter by lazy { ChapterAdapter(requireContext(), inject<GenericInfo>().value, dao) }
 
     private val itemListener = FirebaseDb.FirebaseListener()
     private val chapterListener = FirebaseDb.FirebaseListener()
diff --git a/UIViews/src/main/java/com/programmersbox/uiviews/FavoriteFragment.kt b/UIViews/src/main/java/com/programmersbox/uiviews/FavoriteFragment.kt
index d2c1adee5..5b07925ee 100644
--- a/UIViews/src/main/java/com/programmersbox/uiviews/FavoriteFragment.kt
+++ b/UIViews/src/main/java/com/programmersbox/uiviews/FavoriteFragment.kt
@@ -33,6 +33,7 @@ import io.reactivex.rxkotlin.Flowables
 import io.reactivex.rxkotlin.addTo
 import io.reactivex.schedulers.Schedulers
 import io.reactivex.subjects.BehaviorSubject
+import org.koin.android.ext.android.inject
 import java.util.concurrent.TimeUnit
 
 class FavoriteFragment : BaseFragment() {
@@ -40,7 +41,8 @@ class FavoriteFragment : BaseFragment() {
     private val dao by lazy { ItemDatabase.getInstance(requireContext()).itemDao() }
     private val disposable = CompositeDisposable()
 
-    private val sources by lazy { BaseMainActivity.genericInfo.sourceList() }
+    private val genericInfo by inject<GenericInfo>()
+    private val sources by lazy { genericInfo.sourceList() }
     private val sourcePublisher = BehaviorSubject.createDefault(sources.toMutableList())
     private var sourcesList by behaviorDelegate(sourcePublisher)
     private val adapter by lazy { FavoriteAdapter() }
@@ -164,12 +166,12 @@ class FavoriteFragment : BaseFragment() {
         override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FavoriteHolder =
             FavoriteHolder(FavoriteItemBinding.inflate(requireContext().layoutInflater, parent, false))
 
-        override fun FavoriteHolder.onBind(item: Pair<String, List<DbModel>>, position: Int) = bind(item.second)
+        override fun FavoriteHolder.onBind(item: Pair<String, List<DbModel>>, position: Int) = bind(item.second, genericInfo)
     }
 
     class FavoriteHolder(private val binding: FavoriteItemBinding) : RecyclerView.ViewHolder(binding.root) {
 
-        fun bind(info: List<DbModel>) {
+        fun bind(info: List<DbModel>, genericInfo: GenericInfo) {
             binding.show = info.random()
             Glide.with(itemView.context)
                 .asBitmap()
@@ -183,13 +185,13 @@ class FavoriteFragment : BaseFragment() {
 
             binding.root.setOnClickListener {
                 if (info.size == 1) {
-                    val item = info.firstOrNull()?.let { BaseMainActivity.genericInfo.toSource(it.source)?.let { it1 -> it.toItemModel(it1) } }
+                    val item = info.firstOrNull()?.let { genericInfo.toSource(it.source)?.let { it1 -> it.toItemModel(it1) } }
                     binding.root.findNavController().navigate(FavoriteFragmentDirections.actionFavoriteFragmentToDetailsFragment(item))
                 } else {
                     MaterialAlertDialogBuilder(itemView.context)
                         .setTitle(R.string.chooseASource)
                         .setItems(info.map { "${it.source} - ${it.title}" }.toTypedArray()) { d, i ->
-                            val item = info[i].let { BaseMainActivity.genericInfo.toSource(it.source)?.let { it1 -> it.toItemModel(it1) } }
+                            val item = info[i].let { genericInfo.toSource(it.source)?.let { it1 -> it.toItemModel(it1) } }
                             binding.root.findNavController().navigate(FavoriteFragmentDirections.actionFavoriteFragmentToDetailsFragment(item))
                             d.dismiss()
                         }
diff --git a/UIViews/src/main/java/com/programmersbox/uiviews/OtakuApp.kt b/UIViews/src/main/java/com/programmersbox/uiviews/OtakuApp.kt
index 12225f016..52dcb8c0c 100644
--- a/UIViews/src/main/java/com/programmersbox/uiviews/OtakuApp.kt
+++ b/UIViews/src/main/java/com/programmersbox/uiviews/OtakuApp.kt
@@ -13,6 +13,9 @@ import com.programmersbox.helpfulutils.createNotificationGroup
 import com.programmersbox.loggingutils.Loged
 import com.programmersbox.uiviews.utils.shouldCheck
 import io.reactivex.plugins.RxJavaPlugins
+import org.koin.android.ext.koin.androidContext
+import org.koin.android.ext.koin.androidLogger
+import org.koin.core.context.startKoin
 import java.util.concurrent.TimeUnit
 
 abstract class OtakuApp : Application() {
@@ -35,6 +38,11 @@ abstract class OtakuApp : Application() {
             //FirebaseCrashlytics.getInstance().recordException(it)
         }
 
+        startKoin {
+            androidLogger()
+            androidContext(this@OtakuApp)
+        }
+
         onCreated()
 
         val work = WorkManager.getInstance(this)
diff --git a/UIViews/src/main/java/com/programmersbox/uiviews/RecentFragment.kt b/UIViews/src/main/java/com/programmersbox/uiviews/RecentFragment.kt
index d6fcf4d40..7cfe67c2f 100644
--- a/UIViews/src/main/java/com/programmersbox/uiviews/RecentFragment.kt
+++ b/UIViews/src/main/java/com/programmersbox/uiviews/RecentFragment.kt
@@ -52,7 +52,7 @@ class RecentFragment : BaseListFragment() {
 
         binding.recentList.apply {
             adapter = this@RecentFragment.adapter
-            layoutManager = createLayoutManager(this@RecentFragment.requireContext())
+            layoutManager = info.createLayoutManager(this@RecentFragment.requireContext())
             addOnScrollListener(object : EndlessScrollingListener(layoutManager!!) {
                 override fun onLoadMore(page: Int, totalItemsCount: Int, view: RecyclerView?) {
                     if (sourcePublish.value!!.canScroll) {
diff --git a/UIViews/src/main/java/com/programmersbox/uiviews/SettingsFragment.kt b/UIViews/src/main/java/com/programmersbox/uiviews/SettingsFragment.kt
index 1c84e7694..813aedad3 100644
--- a/UIViews/src/main/java/com/programmersbox/uiviews/SettingsFragment.kt
+++ b/UIViews/src/main/java/com/programmersbox/uiviews/SettingsFragment.kt
@@ -41,6 +41,7 @@ import io.reactivex.rxkotlin.addTo
 import io.reactivex.rxkotlin.subscribeBy
 import io.reactivex.schedulers.Schedulers
 import kotlinx.coroutines.*
+import org.koin.android.ext.android.inject
 import java.io.File
 import java.io.FileOutputStream
 import java.io.IOException
@@ -56,11 +57,11 @@ class SettingsFragment : PreferenceFragmentCompat() {
 
     private val disposable: CompositeDisposable = CompositeDisposable()
 
+    private val genericInfo: GenericInfo by inject()
+
     override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
         setPreferencesFromResource(R.xml.root_preferences, rootKey)
 
-        val genericInfo = BaseMainActivity.genericInfo
-
         accountPreferences()
         generalPreferences(genericInfo)
         aboutPreferences(genericInfo)
diff --git a/animeworld/build.gradle b/animeworld/build.gradle
index 1ff5ddd32..d28f23d52 100644
--- a/animeworld/build.gradle
+++ b/animeworld/build.gradle
@@ -113,4 +113,6 @@ dependencies {
 
     //Custom Libraries
     implementation jakepurple13Tools.helpfultools
+
+    implementation koin.koin
 }
\ No newline at end of file
diff --git a/animeworld/src/main/java/com/programmersbox/animeworld/AnimeApp.kt b/animeworld/src/main/java/com/programmersbox/animeworld/AnimeApp.kt
index d30394ec3..ec5146384 100644
--- a/animeworld/src/main/java/com/programmersbox/animeworld/AnimeApp.kt
+++ b/animeworld/src/main/java/com/programmersbox/animeworld/AnimeApp.kt
@@ -22,12 +22,15 @@ import com.tonyodev.fetch2.*
 import com.tonyodev.fetch2.Fetch.Impl.setDefaultInstanceConfiguration
 import com.tonyodev.fetch2core.Downloader
 import com.tonyodev.fetch2core.deleteFile
+import org.koin.core.context.loadKoinModules
 import java.net.HttpURLConnection
 import javax.net.ssl.*
 
 class AnimeApp : OtakuApp() {
     override fun onCreated() {
 
+        loadKoinModules(appModule)
+
         logo = R.mipmap.ic_launcher
         notificationLogo = R.mipmap.ic_launcher_foreground
 
diff --git a/animeworld/src/main/java/com/programmersbox/animeworld/GenericAnime.kt b/animeworld/src/main/java/com/programmersbox/animeworld/GenericAnime.kt
new file mode 100644
index 000000000..3e8873f0c
--- /dev/null
+++ b/animeworld/src/main/java/com/programmersbox/animeworld/GenericAnime.kt
@@ -0,0 +1,286 @@
+package com.programmersbox.animeworld
+
+import android.Manifest
+import android.content.Context
+import android.content.Intent
+import android.net.Uri
+import android.widget.Toast
+import androidx.core.content.ContextCompat
+import androidx.lifecycle.lifecycleScope
+import androidx.mediarouter.app.MediaRouteDialogFactory
+import androidx.preference.Preference
+import androidx.preference.SwitchPreference
+import androidx.recyclerview.widget.LinearLayoutManager
+import androidx.recyclerview.widget.RecyclerView
+import com.google.android.gms.cast.framework.CastContext
+import com.obsez.android.lib.filechooser.ChooserDialog
+import com.programmersbox.anime_sources.Sources
+import com.programmersbox.anime_sources.anime.Movies
+import com.programmersbox.anime_sources.anime.Torrents
+import com.programmersbox.anime_sources.anime.WcoStream
+import com.programmersbox.anime_sources.anime.Yts
+import com.programmersbox.animeworld.cast.ExpandedControlsActivity
+import com.programmersbox.animeworld.ytsdatabase.Torrent
+import com.programmersbox.gsonutils.fromJson
+import com.programmersbox.helpfulutils.requestPermissions
+import com.programmersbox.helpfulutils.runOnUIThread
+import com.programmersbox.helpfulutils.sharedPrefNotNullDelegate
+import com.programmersbox.models.ApiService
+import com.programmersbox.models.ChapterModel
+import com.programmersbox.models.sourcePublish
+import com.programmersbox.uiviews.BaseListFragment
+import com.programmersbox.uiviews.GenericInfo
+import com.programmersbox.uiviews.ItemListAdapter
+import com.programmersbox.uiviews.SettingsDsl
+import com.tonyodev.fetch2.*
+import io.reactivex.disposables.CompositeDisposable
+import io.reactivex.rxkotlin.addTo
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.GlobalScope
+import kotlinx.coroutines.launch
+import org.koin.dsl.module
+
+val appModule = module {
+    single<GenericInfo> { GenericAnime(get()) }
+}
+
+class GenericAnime(val context: Context) : GenericInfo {
+
+    private var Context.wcoRecent by sharedPrefNotNullDelegate(true)
+
+    private val disposable = CompositeDisposable()
+
+    override val showMiddleChapterButton: Boolean
+        get() = true
+
+    override val apkString: String
+        get() = "animeworld-debug.apk"
+
+    override fun createAdapter(context: Context, baseListFragment: BaseListFragment): ItemListAdapter<RecyclerView.ViewHolder> =
+        (AnimeAdapter(context, baseListFragment) as ItemListAdapter<RecyclerView.ViewHolder>)
+
+    override fun createLayoutManager(context: Context): RecyclerView.LayoutManager = LinearLayoutManager(context)
+
+    override fun downloadChapter(chapterModel: ChapterModel, title: String) {
+        if (chapterModel.source == Yts) {
+            Toast.makeText(context, R.string.yts_no_stream, Toast.LENGTH_SHORT).show()
+            return
+        }
+        MainActivity.activity.lifecycleScope.launch(Dispatchers.IO) {
+            val link = chapterModel.getChapterInfo().blockingGet().firstOrNull()?.link
+            MainActivity.activity.runOnUiThread {
+                MainActivity.activity.startActivity(
+                    Intent(context, VideoPlayerActivity::class.java).apply {
+                        putExtra("showPath", link)
+                        putExtra("showName", chapterModel.name)
+                        putExtra("downloadOrStream", true)
+                    }
+                )
+            }
+        }
+    }
+
+    private val fetch = Fetch.getDefaultInstance()
+
+    override fun chapterOnClick(model: ChapterModel, allChapters: List<ChapterModel>, context: Context) {
+        MainActivity.activity.requestPermissions(Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE) { p ->
+            if (p.isGranted) {
+                Toast.makeText(context, R.string.downloading_dots_no_percent, Toast.LENGTH_SHORT).show()
+
+                when (model.source) {
+                    Yts -> {
+                        val f = model.extras["torrents"].toString().fromJson<Torrents>()?.let {
+                            val m = model.extras["info"].toString().fromJson<Movies>()
+                            Torrent(
+                                title = m?.title.orEmpty(),
+                                banner_url = m?.background_image.orEmpty(),
+                                url = it.url.orEmpty(),
+                                hash = it.hash.orEmpty(),
+                                quality = it.quality.orEmpty(),
+                                type = it.type.orEmpty(),
+                                seeds = it.seeds?.toInt() ?: 0,
+                                peers = it.peers?.toInt() ?: 0,
+                                size_pretty = it.size.orEmpty(),
+                                size = it.size_bytes?.toLong() ?: 0L,
+                                date_uploaded = it.date_uploaded.orEmpty(),
+                                date_uploaded_unix = it.date_uploaded_unix.toString(),
+                                movieId = m?.id?.toInt() ?: 0,
+                                imdbCode = m?.imdb_code.orEmpty(),
+                            )
+                        }
+
+                        val serviceIntent = Intent(context, DownloadService::class.java)
+                        serviceIntent.putExtra(DownloadService.TORRENT_JOB, f)
+                        context.startService(serviceIntent)
+                    }
+                    else -> {
+                        GlobalScope.launch { fetchIt(model) }
+                    }
+                }
+            }
+        }
+    }
+
+    private fun fetchIt(ep: ChapterModel) {
+
+        fetch.setGlobalNetworkType(NetworkType.ALL)
+
+        fun getNameFromUrl(url: String): String {
+            return Uri.parse(url).lastPathSegment?.let { if (it.isNotEmpty()) it else ep.name } ?: ep.name
+        }
+
+        val requestList = arrayListOf<Request>()
+        val url = ep.getChapterInfo()
+            .doOnError { runOnUIThread { Toast.makeText(context, R.string.something_went_wrong, Toast.LENGTH_SHORT).show() } }
+            .onErrorReturnItem(emptyList())
+            .blockingGet()
+        for (i in url) {
+
+            val filePath = context.folderLocation + getNameFromUrl(i.link!!) + "${ep.name}.mp4"
+            val request = Request(i.link!!, filePath)
+            request.priority = Priority.HIGH
+            request.networkType = NetworkType.ALL
+            request.enqueueAction = EnqueueAction.REPLACE_EXISTING
+            request.extras.map.toProperties()["URL_INTENT"] = ep.url
+            request.extras.map.toProperties()["NAME_INTENT"] = ep.name
+
+            request.addHeader("Accept-Language", "en-US,en;q=0.5")
+            request.addHeader("User-Agent", "\"Mozilla/5.0 (Windows NT 10.0; WOW64; rv:40.0) Gecko/20100101 Firefox/40.0\"")
+            request.addHeader("Accept", "text/html,video/mp4,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8")
+            request.addHeader("Access-Control-Allow-Origin", "*")
+            request.addHeader("Referer", "http://thewebsite.com")
+            request.addHeader("Connection", "keep-alive")
+
+            i.headers.entries.forEach { request.headers[it.key] = it.value }
+
+            requestList.add(request)
+
+        }
+        fetch.enqueue(requestList) {}
+    }
+
+    override fun sourceList(): List<ApiService> = Sources.values().toList()
+
+    override fun toSource(s: String): ApiService? = try {
+        Sources.valueOf(s)
+    } catch (e: IllegalArgumentException) {
+        null
+    }
+
+    override fun customPreferences(preferenceScreen: SettingsDsl) {
+
+        preferenceScreen.viewSettings {
+            it.addPreference(
+                Preference(it.context).apply {
+                    title = context.getString(R.string.video_menu_title)
+                    icon = ContextCompat.getDrawable(it.context, R.drawable.ic_baseline_video_library_24)
+                    setOnPreferenceClickListener {
+                        openVideos()
+                        true
+                    }
+                }
+            )
+
+            val casting = Preference(it.context).apply {
+                title = context.getString(R.string.cast_menu_title)
+                icon = ContextCompat.getDrawable(it.context, R.drawable.ic_baseline_cast_24)
+                setOnPreferenceClickListener {
+                    if (MainActivity.cast.isCastActive()) {
+                        context.startActivity(Intent(context, ExpandedControlsActivity::class.java))
+                    } else {
+                        MediaRouteDialogFactory.getDefault().onCreateChooserDialogFragment()
+                            .also { it.routeSelector = CastContext.getSharedInstance(context).mergedSelector }
+                            .show(MainActivity.activity.supportFragmentManager, "media_chooser")
+                    }
+                    true
+                }
+            }
+
+            MainActivity.cast.sessionConnected()
+                .subscribe(casting::setVisible)
+                .addTo(disposable)
+
+            MainActivity.cast.sessionStatus()
+                .map { if (it) R.drawable.ic_baseline_cast_connected_24 else R.drawable.ic_baseline_cast_24 }
+                .subscribe(casting::setIcon)
+                .addTo(disposable)
+
+            it.addPreference(casting)
+
+            it.addPreference(
+                Preference(it.context).apply {
+                    title = context.getString(R.string.downloads_menu_title)
+                    icon = ContextCompat.getDrawable(it.context, R.drawable.ic_baseline_download_24)
+                    setOnPreferenceClickListener {
+                        openDownloads()
+                        true
+                    }
+                }
+            )
+        }
+
+        preferenceScreen.generalSettings {
+
+            it.addPreference(
+                SwitchPreference(it.context).apply {
+                    title = context.getString(R.string.wco_recent_title)
+                    summary = context.getString(R.string.wco_recent_info)
+                    key = "wco_recent"
+                    isChecked = context.wcoRecent
+                    setOnPreferenceChangeListener { _, newValue ->
+                        WcoStream.RECENT_TYPE = newValue as Boolean
+                        context.wcoRecent = newValue
+                        true
+                    }
+                    icon = ContextCompat.getDrawable(it.context, R.drawable.ic_baseline_article_24)
+                    sourcePublish.subscribe { api ->
+                        isVisible = api == Sources.WCO_CARTOON || api == Sources.WCO_DUBBED ||
+                                api == Sources.WCO_MOVIES || api == Sources.WCO_SUBBED || api == Sources.WCO_OVA
+                    }
+                        .addTo(disposable)
+                }
+            )
+
+            it.addPreference(
+                Preference(it.context).apply {
+                    title = context.getString(R.string.folder_location)
+                    summary = it.context.folderLocation
+                    icon = ContextCompat.getDrawable(it.context, R.drawable.ic_baseline_folder_24)
+                    setOnPreferenceClickListener {
+                        MainActivity.activity.requestPermissions(
+                            Manifest.permission.READ_EXTERNAL_STORAGE,
+                            Manifest.permission.WRITE_EXTERNAL_STORAGE,
+                        ) {
+                            if (it.isGranted) {
+                                ChooserDialog(context)
+                                    .withIcon(R.mipmap.ic_launcher)
+                                    .withResources(R.string.choose_a_directory, R.string.chooseText, R.string.cancelText)
+                                    .withFilter(true, false)
+                                    .withStartFile(context.folderLocation)
+                                    .enableOptions(true)
+                                    .withChosenListener { dir, _ ->
+                                        context.folderLocation = "$dir/"
+                                        println(dir)
+                                        summary = context.folderLocation
+                                    }
+                                    .build()
+                                    .show()
+                            }
+                        }
+                        true
+                    }
+                }
+            )
+        }
+
+    }
+
+    private fun openDownloads() {
+        DownloadViewerFragment().show(MainActivity.activity.supportFragmentManager, "downloadViewer")
+    }
+
+    private fun openVideos() {
+        ViewVideosFragment().show(MainActivity.activity.supportFragmentManager, "videoViewer")
+    }
+
+}
diff --git a/animeworld/src/main/java/com/programmersbox/animeworld/MainActivity.kt b/animeworld/src/main/java/com/programmersbox/animeworld/MainActivity.kt
index fbebc00a7..30ea0643e 100644
--- a/animeworld/src/main/java/com/programmersbox/animeworld/MainActivity.kt
+++ b/animeworld/src/main/java/com/programmersbox/animeworld/MainActivity.kt
@@ -1,47 +1,21 @@
 package com.programmersbox.animeworld
 
-import android.Manifest
 import android.content.Context
-import android.content.Intent
 import android.net.Uri
-import android.widget.Toast
-import androidx.core.content.ContextCompat
-import androidx.lifecycle.lifecycleScope
-import androidx.mediarouter.app.MediaRouteDialogFactory
-import androidx.preference.Preference
-import androidx.preference.SwitchPreference
-import androidx.recyclerview.widget.LinearLayoutManager
-import androidx.recyclerview.widget.RecyclerView
-import com.google.android.gms.cast.framework.CastContext
-import com.obsez.android.lib.filechooser.ChooserDialog
 import com.programmersbox.anime_sources.Sources
-import com.programmersbox.anime_sources.anime.*
+import com.programmersbox.anime_sources.anime.WcoStream
 import com.programmersbox.animeworld.cast.CastHelper
-import com.programmersbox.animeworld.cast.ExpandedControlsActivity
-import com.programmersbox.animeworld.ytsdatabase.Torrent
-import com.programmersbox.gsonutils.fromJson
-import com.programmersbox.helpfulutils.requestPermissions
 import com.programmersbox.helpfulutils.sharedPrefNotNullDelegate
-import com.programmersbox.models.ApiService
-import com.programmersbox.models.ChapterModel
 import com.programmersbox.models.sourcePublish
-import com.programmersbox.uiviews.BaseListFragment
 import com.programmersbox.uiviews.BaseMainActivity
-import com.programmersbox.uiviews.ItemListAdapter
-import com.programmersbox.uiviews.SettingsDsl
 import com.programmersbox.uiviews.utils.currentService
-import com.tonyodev.fetch2.*
-import io.reactivex.rxkotlin.addTo
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.GlobalScope
-import kotlinx.coroutines.launch
 
 class MainActivity : BaseMainActivity() {
 
     companion object {
         const val VIEW_DOWNLOADS = "animeworld://view_downloads"
         const val VIEW_VIDEOS = "animeworld://view_videos"
-        private lateinit var activity: MainActivity
+        lateinit var activity: MainActivity
         val cast: CastHelper = CastHelper()
     }
 
@@ -69,231 +43,6 @@ class MainActivity : BaseMainActivity() {
 
     }
 
-    override val showMiddleChapterButton: Boolean
-        get() = true
-
-    override val apkString: String
-        get() = "animeworld-debug.apk"
-
-    override fun createAdapter(context: Context, baseListFragment: BaseListFragment): ItemListAdapter<RecyclerView.ViewHolder> =
-        (AnimeAdapter(context, baseListFragment) as ItemListAdapter<RecyclerView.ViewHolder>)
-
-    override fun createLayoutManager(context: Context): RecyclerView.LayoutManager = LinearLayoutManager(context)
-
-    override fun downloadChapter(chapterModel: ChapterModel, title: String) {
-        if (chapterModel.source == Yts) {
-            Toast.makeText(this, R.string.yts_no_stream, Toast.LENGTH_SHORT).show()
-            return
-        }
-        lifecycleScope.launch(Dispatchers.IO) {
-            val link = chapterModel.getChapterInfo().blockingGet().firstOrNull()?.link
-            runOnUiThread {
-                startActivity(
-                    Intent(this@MainActivity, VideoPlayerActivity::class.java).apply {
-                        putExtra("showPath", link)
-                        putExtra("showName", chapterModel.name)
-                        putExtra("downloadOrStream", true)
-                    }
-                )
-            }
-        }
-    }
-
-    private val fetch = Fetch.getDefaultInstance()
-
-    override fun chapterOnClick(model: ChapterModel, allChapters: List<ChapterModel>, context: Context) {
-        requestPermissions(Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE) { p ->
-            if (p.isGranted) {
-                Toast.makeText(this, R.string.downloading_dots_no_percent, Toast.LENGTH_SHORT).show()
-
-                when (model.source) {
-                    Yts -> {
-                        val f = model.extras["torrents"].toString().fromJson<Torrents>()?.let {
-                            val m = model.extras["info"].toString().fromJson<Movies>()
-                            Torrent(
-                                title = m?.title.orEmpty(),
-                                banner_url = m?.background_image.orEmpty(),
-                                url = it.url.orEmpty(),
-                                hash = it.hash.orEmpty(),
-                                quality = it.quality.orEmpty(),
-                                type = it.type.orEmpty(),
-                                seeds = it.seeds?.toInt() ?: 0,
-                                peers = it.peers?.toInt() ?: 0,
-                                size_pretty = it.size.orEmpty(),
-                                size = it.size_bytes?.toLong() ?: 0L,
-                                date_uploaded = it.date_uploaded.orEmpty(),
-                                date_uploaded_unix = it.date_uploaded_unix.toString(),
-                                movieId = m?.id?.toInt() ?: 0,
-                                imdbCode = m?.imdb_code.orEmpty(),
-                            )
-                        }
-
-                        val serviceIntent = Intent(this, DownloadService::class.java)
-                        serviceIntent.putExtra(DownloadService.TORRENT_JOB, f)
-                        startService(serviceIntent)
-                    }
-                    else -> {
-                        GlobalScope.launch { fetchIt(model) }
-                    }
-                }
-            }
-        }
-    }
-
-    private fun fetchIt(ep: ChapterModel) {
-
-        fetch.setGlobalNetworkType(NetworkType.ALL)
-
-        fun getNameFromUrl(url: String): String {
-            return Uri.parse(url).lastPathSegment?.let { if (it.isNotEmpty()) it else ep.name } ?: ep.name
-        }
-
-        val requestList = arrayListOf<Request>()
-        val url = ep.getChapterInfo()
-            .doOnError { runOnUiThread { Toast.makeText(this@MainActivity, R.string.something_went_wrong, Toast.LENGTH_SHORT).show() } }
-            .onErrorReturnItem(emptyList())
-            .blockingGet()
-        for (i in url) {
-
-            val filePath = folderLocation + getNameFromUrl(i.link!!) + "${ep.name}.mp4"
-            val request = Request(i.link!!, filePath)
-            request.priority = Priority.HIGH
-            request.networkType = NetworkType.ALL
-            request.enqueueAction = EnqueueAction.REPLACE_EXISTING
-            request.extras.map.toProperties()["URL_INTENT"] = ep.url
-            request.extras.map.toProperties()["NAME_INTENT"] = ep.name
-
-            request.addHeader("Accept-Language", "en-US,en;q=0.5")
-            request.addHeader("User-Agent", "\"Mozilla/5.0 (Windows NT 10.0; WOW64; rv:40.0) Gecko/20100101 Firefox/40.0\"")
-            request.addHeader("Accept", "text/html,video/mp4,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8")
-            request.addHeader("Access-Control-Allow-Origin", "*")
-            request.addHeader("Referer", "http://thewebsite.com")
-            request.addHeader("Connection", "keep-alive")
-
-            i.headers.entries.forEach { request.headers[it.key] = it.value }
-
-            requestList.add(request)
-
-        }
-        fetch.enqueue(requestList) {}
-    }
-
-    override fun sourceList(): List<ApiService> = Sources.values().toList()
-
-    override fun toSource(s: String): ApiService? = try {
-        Sources.valueOf(s)
-    } catch (e: IllegalArgumentException) {
-        null
-    }
-
-    override fun customPreferences(preferenceScreen: SettingsDsl) {
-
-        preferenceScreen.viewSettings {
-            it.addPreference(
-                Preference(it.context).apply {
-                    title = getString(R.string.video_menu_title)
-                    icon = ContextCompat.getDrawable(it.context, R.drawable.ic_baseline_video_library_24)
-                    setOnPreferenceClickListener {
-                        openVideos()
-                        true
-                    }
-                }
-            )
-
-            val casting = Preference(it.context).apply {
-                title = getString(R.string.cast_menu_title)
-                icon = ContextCompat.getDrawable(it.context, R.drawable.ic_baseline_cast_24)
-                setOnPreferenceClickListener {
-                    if (cast.isCastActive()) {
-                        startActivity(Intent(this@MainActivity, ExpandedControlsActivity::class.java))
-                    } else {
-                        MediaRouteDialogFactory.getDefault().onCreateChooserDialogFragment()
-                            .also { it.routeSelector = CastContext.getSharedInstance(applicationContext).mergedSelector }
-                            .show(activity.supportFragmentManager, "media_chooser")
-                    }
-                    true
-                }
-            }
-
-            cast.sessionConnected()
-                .subscribe(casting::setVisible)
-                .addTo(disposable)
-
-            cast.sessionStatus()
-                .map { if (it) R.drawable.ic_baseline_cast_connected_24 else R.drawable.ic_baseline_cast_24 }
-                .subscribe(casting::setIcon)
-                .addTo(disposable)
-
-            it.addPreference(casting)
-
-            it.addPreference(
-                Preference(it.context).apply {
-                    title = getString(R.string.downloads_menu_title)
-                    icon = ContextCompat.getDrawable(it.context, R.drawable.ic_baseline_download_24)
-                    setOnPreferenceClickListener {
-                        openDownloads()
-                        true
-                    }
-                }
-            )
-        }
-
-        preferenceScreen.generalSettings {
-
-            it.addPreference(
-                SwitchPreference(it.context).apply {
-                    title = getString(R.string.wco_recent_title)
-                    summary = getString(R.string.wco_recent_info)
-                    key = "wco_recent"
-                    isChecked = wcoRecent
-                    setOnPreferenceChangeListener { _, newValue ->
-                        WcoStream.RECENT_TYPE = newValue as Boolean
-                        wcoRecent = newValue
-                        true
-                    }
-                    icon = ContextCompat.getDrawable(it.context, R.drawable.ic_baseline_article_24)
-                    sourcePublish.subscribe {
-                        isVisible = it == Sources.WCO_CARTOON || it == Sources.WCO_DUBBED ||
-                                it == Sources.WCO_MOVIES || it == Sources.WCO_SUBBED || it == Sources.WCO_OVA
-                    }
-                        .addTo(disposable)
-                }
-            )
-
-            it.addPreference(
-                Preference(it.context).apply {
-                    title = getString(R.string.folder_location)
-                    summary = it.context.folderLocation
-                    icon = ContextCompat.getDrawable(it.context, R.drawable.ic_baseline_folder_24)
-                    setOnPreferenceClickListener {
-                        requestPermissions(
-                            Manifest.permission.READ_EXTERNAL_STORAGE,
-                            Manifest.permission.WRITE_EXTERNAL_STORAGE,
-                        ) {
-                            if (it.isGranted) {
-                                ChooserDialog(this@MainActivity)
-                                    .withIcon(R.mipmap.ic_launcher)
-                                    .withResources(R.string.choose_a_directory, R.string.chooseText, R.string.cancelText)
-                                    .withFilter(true, false)
-                                    .withStartFile(folderLocation)
-                                    .enableOptions(true)
-                                    .withChosenListener { dir, _ ->
-                                        folderLocation = "$dir/"
-                                        println(dir)
-                                        summary = folderLocation
-                                    }
-                                    .build()
-                                    .show()
-                            }
-                        }
-                        true
-                    }
-                }
-            )
-        }
-
-    }
-
     private fun openDownloads() {
         DownloadViewerFragment().show(activity.supportFragmentManager, "downloadViewer")
     }
diff --git a/build.gradle b/build.gradle
index e212350a0..7b1ca1fd3 100644
--- a/build.gradle
+++ b/build.gradle
@@ -37,6 +37,13 @@ buildscript {
 
     ext.room_version = "2.3.0"
 
+    def koin_version = "3.0.2"
+
+    // Koin main features for Android (Scope,ViewModel ...)
+    ext.koinAndroid = "io.insert-koin:koin-android:$koin_version"
+    // Koin Android - experimental builder extensions
+    ext.koinAndroidExt = "io.insert-koin:koin-android-ext:$koin_version"
+
     ext {
         jakepurple13Tools = [
                 helpfultools: [flowutils, gsonutils, helpfulutils, loggingutils, dragswipe, funutils, rxutils, thirdpartyutils]
@@ -48,6 +55,8 @@ buildscript {
                         "androidx.room:room-rxjava2:$room_version"
                 ]
         ]
+
+        koin = [koin: [koinAndroid, koinAndroidExt]]
     }
 
     repositories {
diff --git a/mangaworld/build.gradle b/mangaworld/build.gradle
index 6f8681a60..4be761774 100644
--- a/mangaworld/build.gradle
+++ b/mangaworld/build.gradle
@@ -87,4 +87,6 @@ dependencies {
 
     //Custom Libraries
     implementation jakepurple13Tools.helpfultools
+
+    implementation koin.koin
 }
\ No newline at end of file
diff --git a/mangaworld/src/main/java/com/programmersbox/mangaworld/GenericManga.kt b/mangaworld/src/main/java/com/programmersbox/mangaworld/GenericManga.kt
new file mode 100644
index 000000000..628051aca
--- /dev/null
+++ b/mangaworld/src/main/java/com/programmersbox/mangaworld/GenericManga.kt
@@ -0,0 +1,102 @@
+package com.programmersbox.mangaworld
+
+import android.Manifest
+import android.app.DownloadManager
+import android.content.Context
+import android.content.Intent
+import android.os.Environment
+import androidx.core.net.toUri
+import androidx.recyclerview.widget.GridLayoutManager
+import androidx.recyclerview.widget.RecyclerView
+import com.programmersbox.gsonutils.toJson
+import com.programmersbox.helpfulutils.downloadManager
+import com.programmersbox.helpfulutils.requestPermissions
+import com.programmersbox.manga_sources.Sources
+import com.programmersbox.models.ApiService
+import com.programmersbox.models.ChapterModel
+import com.programmersbox.models.Storage
+import com.programmersbox.uiviews.BaseListFragment
+import com.programmersbox.uiviews.GenericInfo
+import com.programmersbox.uiviews.ItemListAdapter
+import com.programmersbox.uiviews.utils.AutoFitGridLayoutManager
+import com.programmersbox.uiviews.utils.ChapterModelSerializer
+import io.reactivex.android.schedulers.AndroidSchedulers
+import io.reactivex.disposables.CompositeDisposable
+import io.reactivex.rxkotlin.addTo
+import io.reactivex.rxkotlin.subscribeBy
+import io.reactivex.schedulers.Schedulers
+import org.koin.dsl.module
+import java.io.File
+
+val appModule = module {
+    single<GenericInfo> { GenericManga(get()) }
+}
+
+class GenericManga(val context: Context) : GenericInfo {
+
+    private val disposable = CompositeDisposable()
+
+    override val showMiddleChapterButton: Boolean get() = false
+
+    override val apkString: String get() = "mangaworld-debug.apk"
+
+    override fun createAdapter(context: Context, baseListFragment: BaseListFragment): ItemListAdapter<RecyclerView.ViewHolder> =
+        (MangaGalleryAdapter(context, baseListFragment) as ItemListAdapter<RecyclerView.ViewHolder>)
+
+    override fun createLayoutManager(context: Context): RecyclerView.LayoutManager =
+        AutoFitGridLayoutManager(context, 360).apply { orientation = GridLayoutManager.VERTICAL }
+
+    override fun chapterOnClick(model: ChapterModel, allChapters: List<ChapterModel>, context: Context) {
+
+        context.startActivity(
+            Intent(context, ReadActivity::class.java).apply {
+                putExtra("currentChapter", model.toJson(ChapterModel::class.java to ChapterModelSerializer()))
+                putExtra("allChapters", allChapters.toJson(ChapterModel::class.java to ChapterModelSerializer()))
+                putExtra("mangaTitle", model.name)
+                putExtra("mangaUrl", model.url)
+            }
+        )
+
+    }
+
+    private fun downloadFullChapter(model: ChapterModel, title: String) {
+        val fileLocation = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).toString() + "/MangaWorld/"
+
+        val direct = File("$fileLocation$title/${model.name}/")
+        if (!direct.exists()) direct.mkdir()
+
+        model.getChapterInfo()
+            .subscribeOn(Schedulers.io())
+            .observeOn(AndroidSchedulers.mainThread())
+            .map { it.mapNotNull(Storage::link) }
+            .map {
+                it.mapIndexed { index, s ->
+                    DownloadManager.Request(s.toUri())
+                        .setDestinationInExternalPublicDir(Environment.DIRECTORY_PICTURES, "MangaWorld/$title/${model.name}/$index.png")
+                        .setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
+                        .setAllowedOverRoaming(true)
+                        .setAllowedNetworkTypes(DownloadManager.Request.NETWORK_MOBILE or DownloadManager.Request.NETWORK_WIFI)
+                        .setMimeType("image/jpeg")
+                        .setTitle(model.name)
+                        .addRequestHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) Gecko/20100101 Firefox/77")
+                        .addRequestHeader("Accept-Language", "en-US,en;q=0.5")
+                }
+            }
+            .subscribeBy { it.forEach(context.downloadManager::enqueue) }
+            .addTo(disposable)
+    }
+
+    override fun downloadChapter(chapterModel: ChapterModel, title: String) {
+        MainActivity.activity.requestPermissions(Manifest.permission.WRITE_EXTERNAL_STORAGE) { p ->
+            if (p.isGranted) downloadFullChapter(chapterModel, title)
+        }
+    }
+
+    override fun sourceList(): List<ApiService> = Sources.values().toList()
+
+    override fun toSource(s: String): ApiService? = try {
+        Sources.valueOf(s)
+    } catch (e: IllegalArgumentException) {
+        null
+    }
+}
\ No newline at end of file
diff --git a/mangaworld/src/main/java/com/programmersbox/mangaworld/MainActivity.kt b/mangaworld/src/main/java/com/programmersbox/mangaworld/MainActivity.kt
index cdc0ffb5f..4688cc0f0 100644
--- a/mangaworld/src/main/java/com/programmersbox/mangaworld/MainActivity.kt
+++ b/mangaworld/src/main/java/com/programmersbox/mangaworld/MainActivity.kt
@@ -1,38 +1,22 @@
 package com.programmersbox.mangaworld
 
-import android.Manifest
-import android.app.DownloadManager
-import android.content.Context
-import android.content.Intent
-import android.os.Environment
-import androidx.core.net.toUri
-import androidx.recyclerview.widget.GridLayoutManager
-import androidx.recyclerview.widget.RecyclerView
 import com.github.piasy.biv.BigImageViewer
 import com.github.piasy.biv.loader.glide.GlideImageLoader
-import com.programmersbox.gsonutils.toJson
-import com.programmersbox.helpfulutils.downloadManager
-import com.programmersbox.helpfulutils.requestPermissions
 import com.programmersbox.manga_sources.Sources
-import com.programmersbox.models.ApiService
-import com.programmersbox.models.ChapterModel
 import com.programmersbox.models.sourcePublish
-import com.programmersbox.uiviews.BaseListFragment
 import com.programmersbox.uiviews.BaseMainActivity
-import com.programmersbox.uiviews.ItemListAdapter
-import com.programmersbox.uiviews.utils.AutoFitGridLayoutManager
-import com.programmersbox.uiviews.utils.ChapterModelSerializer
 import com.programmersbox.uiviews.utils.currentService
-import io.reactivex.android.schedulers.AndroidSchedulers
-import io.reactivex.rxkotlin.addTo
-import io.reactivex.rxkotlin.subscribeBy
-import io.reactivex.schedulers.Schedulers
-import java.io.File
 
 class MainActivity : BaseMainActivity() {
 
+    companion object {
+        lateinit var activity: MainActivity
+    }
+
     override fun onCreate() {
 
+        activity = this
+
         BigImageViewer.initialize(GlideImageLoader.with(applicationContext))
 
         if (currentService == null) {
@@ -41,70 +25,4 @@ class MainActivity : BaseMainActivity() {
         }
     }
 
-    override val showMiddleChapterButton: Boolean
-        get() = false
-
-    override val apkString: String
-        get() = "mangaworld-debug.apk"
-
-    override fun createAdapter(context: Context, baseListFragment: BaseListFragment): ItemListAdapter<RecyclerView.ViewHolder> =
-        (MangaGalleryAdapter(context, baseListFragment) as ItemListAdapter<RecyclerView.ViewHolder>)
-
-    override fun createLayoutManager(context: Context): RecyclerView.LayoutManager =
-        AutoFitGridLayoutManager(context, 360).apply { orientation = GridLayoutManager.VERTICAL }
-
-    override fun chapterOnClick(model: ChapterModel, allChapters: List<ChapterModel>, context: Context) {
-
-        startActivity(
-            Intent(this, ReadActivity::class.java).apply {
-                putExtra("currentChapter", model.toJson(ChapterModel::class.java to ChapterModelSerializer()))
-                putExtra("allChapters", allChapters.toJson(ChapterModel::class.java to ChapterModelSerializer()))
-                putExtra("mangaTitle", model.name)
-                putExtra("mangaUrl", model.url)
-            }
-        )
-
-    }
-
-    private fun downloadFullChapter(model: ChapterModel, title: String) {
-        val fileLocation = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).toString() + "/MangaWorld/"
-
-        val direct = File("$fileLocation$title/${model.name}/")
-        if (!direct.exists()) direct.mkdir()
-
-        model.getChapterInfo()
-            .subscribeOn(Schedulers.io())
-            .observeOn(AndroidSchedulers.mainThread())
-            .map { it.mapNotNull { it.link } }
-            .map {
-                it.mapIndexed { index, s ->
-                    DownloadManager.Request(s.toUri())
-                        .setDestinationInExternalPublicDir(Environment.DIRECTORY_PICTURES, "MangaWorld/$title/${model.name}/$index.png")
-                        .setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
-                        .setAllowedOverRoaming(true)
-                        .setAllowedNetworkTypes(DownloadManager.Request.NETWORK_MOBILE or DownloadManager.Request.NETWORK_WIFI)
-                        .setMimeType("image/jpeg")
-                        .setTitle(model.name)
-                        .addRequestHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) Gecko/20100101 Firefox/77")
-                        .addRequestHeader("Accept-Language", "en-US,en;q=0.5")
-                }
-            }
-            .subscribeBy { it.forEach { downloadManager.enqueue(it) } }
-            .addTo(disposable)
-    }
-
-    override fun downloadChapter(chapterModel: ChapterModel, title: String) {
-        requestPermissions(Manifest.permission.WRITE_EXTERNAL_STORAGE) { p ->
-            if (p.isGranted) downloadFullChapter(chapterModel, title)
-        }
-    }
-
-    override fun sourceList(): List<ApiService> = Sources.values().toList()
-
-    override fun toSource(s: String): ApiService? = try {
-        Sources.valueOf(s)
-    } catch (e: IllegalArgumentException) {
-        null
-    }
-
-}
+}
\ No newline at end of file
diff --git a/mangaworld/src/main/java/com/programmersbox/mangaworld/MangaApp.kt b/mangaworld/src/main/java/com/programmersbox/mangaworld/MangaApp.kt
index bc2f40fd0..74bb01dd6 100644
--- a/mangaworld/src/main/java/com/programmersbox/mangaworld/MangaApp.kt
+++ b/mangaworld/src/main/java/com/programmersbox/mangaworld/MangaApp.kt
@@ -8,10 +8,13 @@ import com.programmersbox.manga_sources.Sources
 import com.programmersbox.uiviews.OtakuApp
 import com.programmersbox.uiviews.UpdateWorker
 import com.programmersbox.uiviews.utils.FirebaseDb
+import org.koin.core.context.loadKoinModules
 
 class MangaApp : OtakuApp() {
     override fun onCreated() {
 
+        loadKoinModules(appModule)
+
         logo = R.mipmap.ic_launcher
         notificationLogo = R.drawable.manga_world_round_logo
 
diff --git a/mangaworld/src/main/java/com/programmersbox/mangaworld/ReadActivity.kt b/mangaworld/src/main/java/com/programmersbox/mangaworld/ReadActivity.kt
index 7f054c840..165961c12 100644
--- a/mangaworld/src/main/java/com/programmersbox/mangaworld/ReadActivity.kt
+++ b/mangaworld/src/main/java/com/programmersbox/mangaworld/ReadActivity.kt
@@ -26,9 +26,10 @@ import com.programmersbox.gsonutils.fromJson
 import com.programmersbox.helpfulutils.*
 import com.programmersbox.mangaworld.databinding.ActivityReadBinding
 import com.programmersbox.models.ChapterModel
+import com.programmersbox.models.Storage
 import com.programmersbox.rxutils.invoke
 import com.programmersbox.rxutils.toLatestFlowable
-import com.programmersbox.uiviews.BaseMainActivity
+import com.programmersbox.uiviews.GenericInfo
 import com.programmersbox.uiviews.utils.ChapterModelDeserializer
 import com.programmersbox.uiviews.utils.batteryAlertPercent
 import io.reactivex.android.schedulers.AndroidSchedulers
@@ -38,6 +39,7 @@ import io.reactivex.rxkotlin.addTo
 import io.reactivex.rxkotlin.subscribeBy
 import io.reactivex.schedulers.Schedulers
 import io.reactivex.subjects.PublishSubject
+import org.koin.android.ext.android.inject
 import java.io.File
 import java.util.*
 import kotlin.math.roundToInt
@@ -70,11 +72,14 @@ class ReadActivity : AppCompatActivity() {
         }
     }*/
 
+
+    private val genericInfo by inject<GenericInfo>()
+
     private val adapter2: PageAdapter by lazy {
         loader.let {
             val list = intent.getStringExtra("allChapters")
-                ?.fromJson<List<ChapterModel>>(ChapterModel::class.java to ChapterModelDeserializer(BaseMainActivity.genericInfo))
-                .orEmpty().also { println(it) }
+                ?.fromJson<List<ChapterModel>>(ChapterModel::class.java to ChapterModelDeserializer(genericInfo))
+                .orEmpty().also(::println)
             //intent.getObjectExtra<List<ChapterModel>>("allChapters") ?: emptyList()
             val url = intent.getStringExtra("mangaUrl") ?: ""
             val mangaUrl = intent.getStringExtra("mangaInfoUrl") ?: ""
@@ -173,7 +178,7 @@ class ReadActivity : AppCompatActivity() {
 
         mangaTitle = intent.getStringExtra("mangaTitle")
         model = intent.getStringExtra("currentChapter")
-            ?.fromJson<ChapterModel>(ChapterModel::class.java to ChapterModelDeserializer(BaseMainActivity.genericInfo))
+            ?.fromJson<ChapterModel>(ChapterModel::class.java to ChapterModelDeserializer(genericInfo))
 
         //titleManga.text = mangaTitle
         loadPages(model)
@@ -204,7 +209,7 @@ class ReadActivity : AppCompatActivity() {
             .start()
         adapter2.setListNotify(emptyList())
         model?.getChapterInfo()
-            ?.map { it.mapNotNull { it.link } }
+            ?.map { it.mapNotNull(Storage::link) }
             ?.subscribeOn(Schedulers.io())
             ?.observeOn(AndroidSchedulers.mainThread())
             ?.doOnError { Toast.makeText(this, it.localizedMessage, Toast.LENGTH_SHORT).show() }
@@ -217,7 +222,7 @@ class ReadActivity : AppCompatActivity() {
                     .start()
                 adapter2.setListNotify(pages)
                 //adapter.addItems(pages)
-                binding.readView.layoutManager!!.scrollToPosition(model?.url?.let { defaultSharedPref.getInt(it, 0) } ?: 0)
+                //binding.readView.layoutManager!!.scrollToPosition(model.url.let { defaultSharedPref.getInt(it, 0) })
             }
             ?.addTo(disposable)
     }
diff --git a/novelworld/build.gradle b/novelworld/build.gradle
index 27e6afc53..a27372317 100644
--- a/novelworld/build.gradle
+++ b/novelworld/build.gradle
@@ -74,4 +74,6 @@ dependencies {
 
     //Custom Libraries
     implementation jakepurple13Tools.helpfultools
+
+    implementation koin.koin
 }
\ No newline at end of file
diff --git a/novelworld/src/main/java/com/programmersbox/novelworld/GenericNovel.kt b/novelworld/src/main/java/com/programmersbox/novelworld/GenericNovel.kt
new file mode 100644
index 000000000..3c4bcf91f
--- /dev/null
+++ b/novelworld/src/main/java/com/programmersbox/novelworld/GenericNovel.kt
@@ -0,0 +1,50 @@
+package com.programmersbox.novelworld
+
+import android.content.Context
+import android.content.Intent
+import androidx.recyclerview.widget.LinearLayoutManager
+import androidx.recyclerview.widget.RecyclerView
+import com.programmersbox.gsonutils.toJson
+import com.programmersbox.models.ApiService
+import com.programmersbox.models.ChapterModel
+import com.programmersbox.novel_sources.Sources
+import com.programmersbox.uiviews.BaseListFragment
+import com.programmersbox.uiviews.GenericInfo
+import com.programmersbox.uiviews.ItemListAdapter
+import com.programmersbox.uiviews.utils.ChapterModelSerializer
+import org.koin.dsl.module
+
+val appModule = module {
+    single<GenericInfo> { GenericNovel(get()) }
+}
+
+class GenericNovel(val context: Context) : GenericInfo {
+    override fun createAdapter(context: Context, baseListFragment: BaseListFragment): ItemListAdapter<RecyclerView.ViewHolder> =
+        (NovelAdapter(context, baseListFragment) as ItemListAdapter<RecyclerView.ViewHolder>)
+
+    override fun createLayoutManager(context: Context): RecyclerView.LayoutManager = LinearLayoutManager(context)
+
+    override fun chapterOnClick(model: ChapterModel, allChapters: List<ChapterModel>, context: Context) {
+        context.startActivity(
+            Intent(context, ReadingActivity::class.java).apply {
+                putExtra("model", model.toJson(ChapterModel::class.java to ChapterModelSerializer()))
+            }
+        )
+    }
+
+    override fun sourceList(): List<ApiService> = Sources.values().toList()
+
+    override fun toSource(s: String): ApiService? = try {
+        Sources.valueOf(s)
+    } catch (e: IllegalArgumentException) {
+        null
+    }
+
+    override fun downloadChapter(chapterModel: ChapterModel, title: String) {
+
+    }
+
+    override val apkString: String get() = "novelworld-debug.apk"
+
+    override val showMiddleChapterButton: Boolean get() = false
+}
\ No newline at end of file
diff --git a/novelworld/src/main/java/com/programmersbox/novelworld/MainActivity.kt b/novelworld/src/main/java/com/programmersbox/novelworld/MainActivity.kt
index 9f300d0a5..a9d114fbf 100644
--- a/novelworld/src/main/java/com/programmersbox/novelworld/MainActivity.kt
+++ b/novelworld/src/main/java/com/programmersbox/novelworld/MainActivity.kt
@@ -1,18 +1,8 @@
 package com.programmersbox.novelworld
 
-import android.content.Context
-import android.content.Intent
-import androidx.recyclerview.widget.LinearLayoutManager
-import androidx.recyclerview.widget.RecyclerView
-import com.programmersbox.gsonutils.toJson
-import com.programmersbox.models.ApiService
-import com.programmersbox.models.ChapterModel
 import com.programmersbox.models.sourcePublish
 import com.programmersbox.novel_sources.Sources
-import com.programmersbox.uiviews.BaseListFragment
 import com.programmersbox.uiviews.BaseMainActivity
-import com.programmersbox.uiviews.ItemListAdapter
-import com.programmersbox.uiviews.utils.ChapterModelSerializer
 import com.programmersbox.uiviews.utils.currentService
 
 class MainActivity : BaseMainActivity() {
@@ -27,33 +17,4 @@ class MainActivity : BaseMainActivity() {
 
     }
 
-    override fun createAdapter(context: Context, baseListFragment: BaseListFragment): ItemListAdapter<RecyclerView.ViewHolder> =
-        (NovelAdapter(context, baseListFragment) as ItemListAdapter<RecyclerView.ViewHolder>)
-
-    override fun createLayoutManager(context: Context): RecyclerView.LayoutManager = LinearLayoutManager(context)
-
-    override fun chapterOnClick(model: ChapterModel, allChapters: List<ChapterModel>, context: Context) {
-        startActivity(
-            Intent(this, ReadingActivity::class.java).apply {
-                putExtra("model", model.toJson(ChapterModel::class.java to ChapterModelSerializer()))
-            }
-        )
-    }
-
-    override fun sourceList(): List<ApiService> = Sources.values().toList()
-
-    override fun toSource(s: String): ApiService? = try {
-        Sources.valueOf(s)
-    } catch (e: IllegalArgumentException) {
-        null
-    }
-
-    override fun downloadChapter(chapterModel: ChapterModel, title: String) {
-
-    }
-
-    override val apkString: String get() = "novelworld-debug.apk"
-
-    override val showMiddleChapterButton: Boolean get() = false
-
 }
\ No newline at end of file
diff --git a/novelworld/src/main/java/com/programmersbox/novelworld/NovelApp.kt b/novelworld/src/main/java/com/programmersbox/novelworld/NovelApp.kt
index 6fbe8a2cd..4f230e8cb 100644
--- a/novelworld/src/main/java/com/programmersbox/novelworld/NovelApp.kt
+++ b/novelworld/src/main/java/com/programmersbox/novelworld/NovelApp.kt
@@ -4,10 +4,13 @@ import com.programmersbox.novel_sources.Sources
 import com.programmersbox.uiviews.OtakuApp
 import com.programmersbox.uiviews.UpdateWorker
 import com.programmersbox.uiviews.utils.FirebaseDb
+import org.koin.core.context.loadKoinModules
 
 class NovelApp : OtakuApp() {
     override fun onCreated() {
 
+        loadKoinModules(appModule)
+
         logo = R.mipmap.ic_launcher
         notificationLogo = R.mipmap.ic_launcher_foreground
 
diff --git a/novelworld/src/main/java/com/programmersbox/novelworld/ReadingActivity.kt b/novelworld/src/main/java/com/programmersbox/novelworld/ReadingActivity.kt
index 86fd04977..64114e1d6 100644
--- a/novelworld/src/main/java/com/programmersbox/novelworld/ReadingActivity.kt
+++ b/novelworld/src/main/java/com/programmersbox/novelworld/ReadingActivity.kt
@@ -16,7 +16,7 @@ import com.programmersbox.models.ChapterModel
 import com.programmersbox.novelworld.databinding.ActivityReadingBinding
 import com.programmersbox.rxutils.invoke
 import com.programmersbox.rxutils.toLatestFlowable
-import com.programmersbox.uiviews.BaseMainActivity
+import com.programmersbox.uiviews.GenericInfo
 import com.programmersbox.uiviews.utils.ChapterModelDeserializer
 import com.programmersbox.uiviews.utils.batteryAlertPercent
 import io.reactivex.android.schedulers.AndroidSchedulers
@@ -26,6 +26,7 @@ import io.reactivex.rxkotlin.addTo
 import io.reactivex.rxkotlin.subscribeBy
 import io.reactivex.schedulers.Schedulers
 import io.reactivex.subjects.PublishSubject
+import org.koin.android.ext.android.inject
 import kotlin.math.roundToInt
 
 class ReadingActivity : AppCompatActivity() {
@@ -46,6 +47,8 @@ class ReadingActivity : AppCompatActivity() {
         UNKNOWN(GoogleMaterial.Icon.gmd_battery_unknown)
     }
 
+    private val genericInfo by inject<GenericInfo>()
+
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
 
@@ -56,7 +59,7 @@ class ReadingActivity : AppCompatActivity() {
         batterySetup()
 
         intent.getStringExtra("model")
-            ?.fromJson<ChapterModel>(ChapterModel::class.java to ChapterModelDeserializer(BaseMainActivity.genericInfo))
+            ?.fromJson<ChapterModel>(ChapterModel::class.java to ChapterModelDeserializer(genericInfo))
             ?.getChapterInfo()
             ?.subscribeOn(Schedulers.io())
             ?.observeOn(AndroidSchedulers.mainThread())