len 9 жил өмнө
parent
commit
a598ebf72f

+ 0 - 4
app/src/main/AndroidManifest.xml

@@ -32,11 +32,7 @@
         </activity>
         <activity
             android:name=".ui.reader.ReaderActivity"
-            android:parentActivityName=".ui.manga.MangaActivity"
             android:theme="@style/Theme.Reader">
-            <meta-data
-                android:name="android.support.PARENT_ACTIVITY"
-                android:value=".ui.manga.MangaActivity" />
         </activity>
         <activity
             android:name=".ui.setting.SettingsActivity"

+ 14 - 1
app/src/main/java/eu/kanade/tachiyomi/event/ChapterCountEvent.kt

@@ -1,3 +1,16 @@
 package eu.kanade.tachiyomi.event
 
-class ChapterCountEvent(val count: Int)
+import rx.Observable
+import rx.subjects.BehaviorSubject
+
+class ChapterCountEvent() {
+
+    private val subject = BehaviorSubject.create<Int>()
+
+    val observable: Observable<Int>
+        get() = subject
+
+    fun emit(count: Int) {
+        subject.onNext(count)
+    }
+}

+ 6 - 7
app/src/main/java/eu/kanade/tachiyomi/ui/base/fragment/BaseRxFragment.java

@@ -12,7 +12,7 @@ import nucleus.view.PresenterLifecycleDelegate;
 import nucleus.view.ViewWithPresenter;
 
 /**
- * This class is an example of how an activity could controls it's presenter.
+ * This view is an example of how a view should control it's presenter.
  * You can inherit from this class or copy/paste this class's code to
  * create your own view implementation.
  *
@@ -87,12 +87,11 @@ public abstract class BaseRxFragment<P extends Presenter> extends BaseFragment i
     @Override
     public void onPause() {
         super.onPause();
-        presenterDelegate.onPause(getActivity().isFinishing() || shouldDestroyPresenter(this));
+        presenterDelegate.onPause(getActivity().isFinishing() || isRemoving(this));
     }
 
-    private boolean shouldDestroyPresenter(Fragment fragment) {
-        if (fragment == null) return false;
-        else return fragment.isRemoving() || shouldDestroyPresenter(fragment.getParentFragment());
+    private static boolean isRemoving(Fragment fragment) {
+        Fragment parent = fragment.getParentFragment();
+        return fragment.isRemoving() || (parent != null && isRemoving(parent));
     }
-
-}
+}

+ 10 - 0
app/src/main/java/eu/kanade/tachiyomi/ui/base/presenter/BasePresenter.kt

@@ -3,6 +3,7 @@ package eu.kanade.tachiyomi.ui.base.presenter
 import android.content.Context
 import nucleus.view.ViewWithPresenter
 import org.greenrobot.eventbus.EventBus
+import rx.Observable
 
 open class BasePresenter<V : ViewWithPresenter<*>> : RxPresenter<V>() {
 
@@ -16,4 +17,13 @@ open class BasePresenter<V : ViewWithPresenter<*>> : RxPresenter<V>() {
         EventBus.getDefault().unregister(this)
     }
 
+    fun <T> Observable<T>.subscribeFirst(onNext: (V, T) -> Unit, onError: ((V, Throwable) -> Unit)? = null)
+            = compose(deliverFirst<T>()).subscribe(split(onNext, onError))
+
+    fun <T> Observable<T>.subscribeLatestCache(onNext: (V, T) -> Unit, onError: ((V, Throwable) -> Unit)? = null)
+            = compose(deliverLatestCache<T>()).subscribe(split(onNext, onError))
+
+    fun <T> Observable<T>.subscribeReplay(onNext: (V, T) -> Unit, onError: ((V, Throwable) -> Unit)? = null)
+            = compose(deliverReplay<T>()).subscribe(split(onNext, onError))
+
 }

+ 4 - 5
app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaActivity.kt

@@ -13,15 +13,16 @@ import android.support.v4.app.FragmentPagerAdapter
 import android.support.v4.content.ContextCompat
 import eu.kanade.tachiyomi.R
 import eu.kanade.tachiyomi.data.database.models.Manga
+import eu.kanade.tachiyomi.event.MangaEvent
 import eu.kanade.tachiyomi.ui.base.activity.BaseRxActivity
 import eu.kanade.tachiyomi.ui.manga.chapter.ChaptersFragment
 import eu.kanade.tachiyomi.ui.manga.info.MangaInfoFragment
 import eu.kanade.tachiyomi.ui.manga.myanimelist.MyAnimeListFragment
+import eu.kanade.tachiyomi.util.SharedData
 import kotlinx.android.synthetic.main.activity_manga.*
 import kotlinx.android.synthetic.main.tab_layout.*
 import kotlinx.android.synthetic.main.toolbar.*
 import nucleus.factory.RequiresPresenter
-import org.greenrobot.eventbus.EventBus
 
 @RequiresPresenter(MangaPresenter::class)
 class MangaActivity : BaseRxActivity<MangaPresenter>() {
@@ -33,11 +34,9 @@ class MangaActivity : BaseRxActivity<MangaPresenter>() {
         val CHAPTERS_FRAGMENT = 1
         val MYANIMELIST_FRAGMENT = 2
 
-        fun newIntent(context: Context, manga: Manga?): Intent {
+        fun newIntent(context: Context, manga: Manga): Intent {
             val intent = Intent(context, MangaActivity::class.java)
-            if (manga != null) {
-                EventBus.getDefault().postSticky(manga)
-            }
+            SharedData.put(MangaEvent(manga))
             return intent
         }
     }

+ 12 - 27
app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaPresenter.kt

@@ -4,11 +4,10 @@ import android.os.Bundle
 import eu.kanade.tachiyomi.data.database.DatabaseHelper
 import eu.kanade.tachiyomi.data.database.models.Manga
 import eu.kanade.tachiyomi.data.mangasync.MangaSyncManager
+import eu.kanade.tachiyomi.event.ChapterCountEvent
 import eu.kanade.tachiyomi.event.MangaEvent
 import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
-import org.greenrobot.eventbus.EventBus
-import org.greenrobot.eventbus.Subscribe
-import org.greenrobot.eventbus.ThreadMode
+import eu.kanade.tachiyomi.util.SharedData
 import rx.Observable
 import javax.inject.Inject
 
@@ -37,32 +36,26 @@ class MangaPresenter : BasePresenter<MangaActivity>() {
      */
     private val MANGA_KEY = "manga_key"
 
-    /**
-     * Id of the restartable that notifies the view of a manga.
-     */
-    private val GET_MANGA = 1
-
     override fun onCreate(savedState: Bundle?) {
         super.onCreate(savedState)
 
-        if (savedState != null) {
+        if (savedState == null) {
+            manga = SharedData.get(MangaEvent::class.java)!!.manga
+        } else {
             manga = savedState.getSerializable(MANGA_KEY) as Manga
+            SharedData.put(MangaEvent(manga))
         }
 
-        restartableLatestCache(GET_MANGA,
-                { Observable.just(manga)
-                        .doOnNext { EventBus.getDefault().postSticky(MangaEvent(it)) } },
-                { view, manga -> view.onSetManga(manga) })
+        // Prepare a subject to communicate the chapters and info presenters for the chapter count.
+        SharedData.put(ChapterCountEvent())
 
-        if (savedState == null) {
-            registerForEvents()
-        }
+        add(Observable.just(manga)
+                .subscribeLatestCache({ view, manga -> view.onSetManga(manga) }))
     }
 
     override fun onDestroy() {
-        // Avoid new instances receiving wrong manga
-        EventBus.getDefault().removeStickyEvent(MangaEvent::class.java)
-
+        SharedData.remove(MangaEvent::class.java)
+        SharedData.remove(ChapterCountEvent::class.java)
         super.onDestroy()
     }
 
@@ -71,12 +64,4 @@ class MangaPresenter : BasePresenter<MangaActivity>() {
         super.onSave(state)
     }
 
-    @Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
-    fun onEvent(manga: Manga) {
-        EventBus.getDefault().removeStickyEvent(manga)
-        unregisterForEvents()
-        this.manga = manga
-        start(GET_MANGA)
-    }
-
 }

+ 22 - 38
app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChaptersPresenter.kt

@@ -15,9 +15,8 @@ import eu.kanade.tachiyomi.event.DownloadChaptersEvent
 import eu.kanade.tachiyomi.event.MangaEvent
 import eu.kanade.tachiyomi.event.ReaderEvent
 import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
+import eu.kanade.tachiyomi.util.SharedData
 import org.greenrobot.eventbus.EventBus
-import org.greenrobot.eventbus.Subscribe
-import org.greenrobot.eventbus.ThreadMode
 import rx.Observable
 import rx.android.schedulers.AndroidSchedulers
 import rx.schedulers.Schedulers
@@ -47,20 +46,15 @@ class ChaptersPresenter : BasePresenter<ChaptersFragment>() {
     var hasRequested: Boolean = false
         private set
 
-    private val GET_MANGA = 1
-    private val DB_CHAPTERS = 2
-    private val FETCH_CHAPTERS = 3
-    private val CHAPTER_STATUS_CHANGES = 4
+    private val DB_CHAPTERS = 1
+    private val FETCH_CHAPTERS = 2
+    private val CHAPTER_STATUS_CHANGES = 3
 
     override fun onCreate(savedState: Bundle?) {
         super.onCreate(savedState)
 
         chaptersSubject = PublishSubject.create()
 
-        startableLatestCache(GET_MANGA,
-                { Observable.just(manga) },
-                { view, manga -> view.onNextManga(manga) })
-
         startableLatestCache(DB_CHAPTERS,
                 { getDbChaptersObs() },
                 { view, chapters -> view.onNextChapters(chapters) })
@@ -75,36 +69,26 @@ class ChaptersPresenter : BasePresenter<ChaptersFragment>() {
                 { view, download -> view.onChapterStatusChange(download) },
                 { view, error -> Timber.e(error.cause, error.message) })
 
-        registerForEvents()
-    }
+        manga = SharedData.get(MangaEvent::class.java)!!.manga
+        add(Observable.just(manga)
+                .subscribeLatestCache({ view, manga -> view.onNextManga(manga) }))
 
-    override fun onDestroy() {
-        unregisterForEvents()
-        EventBus.getDefault().removeStickyEvent(ChapterCountEvent::class.java)
-        super.onDestroy()
-    }
+        source = sourceManager.get(manga.source)!!
+        start(DB_CHAPTERS)
 
-    @Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
-    fun onEvent(event: MangaEvent) {
-        this.manga = event.manga
-        start(GET_MANGA)
-
-        if (isUnsubscribed(DB_CHAPTERS)) {
-            source = sourceManager.get(manga.source)!!
-            start(DB_CHAPTERS)
-
-            add(db.getChapters(manga).asRxObservable()
-                    .subscribeOn(Schedulers.io())
-                    .doOnNext { chapters ->
-                        this.chapters = chapters
-                        EventBus.getDefault().postSticky(ChapterCountEvent(chapters.size))
-                        for (chapter in chapters) {
-                            setChapterStatus(chapter)
-                        }
-                        start(CHAPTER_STATUS_CHANGES)
+        add(db.getChapters(manga).asRxObservable()
+                .subscribeOn(Schedulers.io())
+                .doOnNext { chapters ->
+                    this.chapters = chapters
+                    SharedData.get(ChapterCountEvent::class.java)?.let {
+                        it.emit(chapters.size)
                     }
-                    .subscribe { chaptersSubject.onNext(it) })
-        }
+                    for (chapter in chapters) {
+                        setChapterStatus(chapter)
+                    }
+                    start(CHAPTER_STATUS_CHANGES)
+                }
+                .subscribe { chaptersSubject.onNext(it) })
     }
 
     fun fetchChaptersFromSource() {
@@ -179,7 +163,7 @@ class ChaptersPresenter : BasePresenter<ChaptersFragment>() {
     }
 
     fun onOpenChapter(chapter: Chapter) {
-        EventBus.getDefault().postSticky(ReaderEvent(manga, chapter))
+        SharedData.put(ReaderEvent(manga, chapter))
     }
 
     fun getNextUnreadChapter(): Chapter? {

+ 6 - 37
app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoPresenter.kt

@@ -9,8 +9,7 @@ import eu.kanade.tachiyomi.data.source.base.Source
 import eu.kanade.tachiyomi.event.ChapterCountEvent
 import eu.kanade.tachiyomi.event.MangaEvent
 import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
-import org.greenrobot.eventbus.Subscribe
-import org.greenrobot.eventbus.ThreadMode
+import eu.kanade.tachiyomi.util.SharedData
 import rx.Observable
 import rx.android.schedulers.AndroidSchedulers
 import rx.schedulers.Schedulers
@@ -50,11 +49,6 @@ class MangaInfoPresenter : BasePresenter<MangaInfoFragment>() {
      */
     @Inject lateinit var coverCache: CoverCache
 
-    /**
-     * Count of chapters.
-     */
-    private var count = -1
-
     /**
      * The id of the restartable.
      */
@@ -63,12 +57,7 @@ class MangaInfoPresenter : BasePresenter<MangaInfoFragment>() {
     /**
      * The id of the restartable.
      */
-    private val GET_CHAPTER_COUNT = 2
-
-    /**
-     * The id of the restartable.
-     */
-    private val FETCH_MANGA_INFO = 3
+    private val FETCH_MANGA_INFO = 2
 
     override fun onCreate(savedState: Bundle?) {
         super.onCreate(savedState)
@@ -78,39 +67,19 @@ class MangaInfoPresenter : BasePresenter<MangaInfoFragment>() {
                 { Observable.just(manga) },
                 { view, manga -> view.onNextManga(manga, source) })
 
-        // Update chapter count.
-        startableLatestCache(GET_CHAPTER_COUNT,
-                { Observable.just(count) },
-                { view, count -> view.setChapterCount(count) })
-
         // Fetch manga info from source.
         startableFirst(FETCH_MANGA_INFO,
                 { fetchMangaObs() },
                 { view, manga -> view.onFetchMangaDone() },
                 { view, error -> view.onFetchMangaError() })
 
-        // Listen for events.
-        registerForEvents()
-    }
-
-    override fun onDestroy() {
-        unregisterForEvents()
-        super.onDestroy()
-    }
-
-    @Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
-    fun onEvent(event: MangaEvent) {
-        manga = event.manga
+        manga = SharedData.get(MangaEvent::class.java)!!.manga
         source = sourceManager.get(manga.source)!!
         refreshManga()
-    }
 
-    @Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
-    fun onEvent(event: ChapterCountEvent) {
-        if (count != event.count) {
-            count = event.count
-            // Update chapter count
-            start(GET_CHAPTER_COUNT)
+        // Update chapter count
+        SharedData.get(ChapterCountEvent::class.java)?.let {
+            add(it.observable.subscribeLatestCache({ view, count -> view.setChapterCount(count) }))
         }
     }
 

+ 2 - 13
app/src/main/java/eu/kanade/tachiyomi/ui/manga/myanimelist/MyAnimeListPresenter.kt

@@ -9,9 +9,8 @@ import eu.kanade.tachiyomi.data.database.models.MangaSync
 import eu.kanade.tachiyomi.data.mangasync.MangaSyncManager
 import eu.kanade.tachiyomi.event.MangaEvent
 import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
+import eu.kanade.tachiyomi.util.SharedData
 import eu.kanade.tachiyomi.util.toast
-import org.greenrobot.eventbus.Subscribe
-import org.greenrobot.eventbus.ThreadMode
 import rx.Observable
 import rx.android.schedulers.AndroidSchedulers
 import rx.schedulers.Schedulers
@@ -59,17 +58,7 @@ class MyAnimeListPresenter : BasePresenter<MyAnimeListFragment>() {
                 { view, result -> view.onRefreshDone() },
                 { view, error -> view.onRefreshError(error) })
 
-        registerForEvents()
-    }
-
-    override fun onDestroy() {
-        unregisterForEvents()
-        super.onDestroy()
-    }
-
-    @Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
-    fun onEvent(event: MangaEvent) {
-        manga = event.manga
+        manga = SharedData.get(MangaEvent::class.java)!!.manga
         start(GET_MANGA_SYNC)
     }
 

+ 4 - 2
app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt

@@ -36,6 +36,7 @@ import kotlinx.android.synthetic.main.reader_menu.*
 import nucleus.factory.RequiresPresenter
 import rx.Subscription
 import rx.subscriptions.CompositeSubscription
+import timber.log.Timber
 import java.text.DecimalFormat
 
 @RequiresPresenter(ReaderPresenter::class)
@@ -83,7 +84,7 @@ class ReaderActivity : BaseRxActivity<ReaderPresenter>() {
     val preferences: PreferencesHelper
         get() = presenter.prefs
 
-    public override fun onCreate(savedState: Bundle?) {
+    override fun onCreate(savedState: Bundle?) {
         super.onCreate(savedState)
         setContentView(R.layout.activity_reader)
 
@@ -189,8 +190,9 @@ class ReaderActivity : BaseRxActivity<ReaderPresenter>() {
         }
     }
 
-    fun onChapterError() {
+    fun onChapterError(error: Throwable) {
         finish()
+        Timber.e(error, error.message)
         toast(R.string.page_list_error)
     }
 

+ 18 - 27
app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderPresenter.kt

@@ -17,9 +17,7 @@ import eu.kanade.tachiyomi.data.source.base.Source
 import eu.kanade.tachiyomi.data.source.model.Page
 import eu.kanade.tachiyomi.event.ReaderEvent
 import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
-import org.greenrobot.eventbus.EventBus
-import org.greenrobot.eventbus.Subscribe
-import org.greenrobot.eventbus.ThreadMode
+import eu.kanade.tachiyomi.util.SharedData
 import rx.Observable
 import rx.Subscription
 import rx.android.schedulers.AndroidSchedulers
@@ -72,19 +70,26 @@ class ReaderPresenter : BasePresenter<ReaderActivity>() {
     override fun onCreate(savedState: Bundle?) {
         super.onCreate(savedState)
 
-        if (savedState != null) {
+        if (savedState == null) {
+            val event = SharedData.remove(ReaderEvent::class.java)!!
+            manga = event.manga
+            chapter = event.chapter
+        } else {
             manga = savedState.getSerializable(MANGA_KEY) as Manga
-            source = sourceManager.get(manga.source)!!
             chapter = savedState.getSerializable(CHAPTER_KEY) as Chapter
             requestedPage = savedState.getInt(PAGE_KEY)
-            initializeSubjects()
         }
 
+        source = sourceManager.get(manga.source)!!
+
+        initializeSubjects()
+
         startableLatestCache(GET_ADJACENT_CHAPTERS,
                 { getAdjacentChaptersObservable() },
                 { view, pair -> view.onAdjacentChapters(pair.first, pair.second) })
 
-        startable(PRELOAD_NEXT_CHAPTER, { getPreloadNextChapterObservable() },
+        startable(PRELOAD_NEXT_CHAPTER,
+                { getPreloadNextChapterObservable() },
                 { },
                 { error -> Timber.e("Error preloading chapter") })
 
@@ -95,38 +100,24 @@ class ReaderPresenter : BasePresenter<ReaderActivity>() {
         restartableLatestCache(GET_PAGE_LIST,
                 { getPageListObservable(chapter) },
                 { view, chapter -> view.onChapterReady(manga, chapter, currentPage) },
-                { view, error -> view.onChapterError() })
+                { view, error -> view.onChapterError(error) })
 
         if (savedState == null) {
-            registerForEvents()
+            loadChapter(chapter)
+            if (prefs.autoUpdateMangaSync()) {
+                start(GET_MANGA_SYNC)
+            }
         }
     }
 
-    override fun onDestroy() {
-        unregisterForEvents()
-        super.onDestroy()
-    }
-
     override fun onSave(state: Bundle) {
         onChapterLeft()
         state.putSerializable(MANGA_KEY, manga)
         state.putSerializable(CHAPTER_KEY, chapter)
-        state.putSerializable(PAGE_KEY, requestedPage)
+        state.putSerializable(PAGE_KEY, currentPage?.pageNumber ?: 0)
         super.onSave(state)
     }
 
-    @Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
-    fun onEvent(event: ReaderEvent) {
-        EventBus.getDefault().removeStickyEvent(event)
-        manga = event.manga
-        source = sourceManager.get(manga.source)!!
-        initializeSubjects()
-        loadChapter(event.chapter)
-        if (prefs.autoUpdateMangaSync()) {
-            start(GET_MANGA_SYNC)
-        }
-    }
-
     private fun initializeSubjects() {
         // Listen for pages initialization events
         pageInitializerSubject = PublishSubject.create<Chapter>()

+ 2 - 1
app/src/main/java/eu/kanade/tachiyomi/ui/recent/RecentChaptersPresenter.kt

@@ -12,6 +12,7 @@ import eu.kanade.tachiyomi.data.source.SourceManager
 import eu.kanade.tachiyomi.event.DownloadChaptersEvent
 import eu.kanade.tachiyomi.event.ReaderEvent
 import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
+import eu.kanade.tachiyomi.util.SharedData
 import org.greenrobot.eventbus.EventBus
 import rx.Observable
 import rx.android.schedulers.AndroidSchedulers
@@ -256,7 +257,7 @@ class RecentChaptersPresenter : BasePresenter<RecentChaptersFragment>() {
      * @param item chapter that is opened
      */
     fun onOpenChapter(item: MangaChapter) {
-        EventBus.getDefault().postSticky(ReaderEvent(item.manga, item.chapter))
+        SharedData.put(ReaderEvent(item.manga, item.chapter))
     }
 
     /**

+ 45 - 0
app/src/main/java/eu/kanade/tachiyomi/util/SharedData.kt

@@ -0,0 +1,45 @@
+package eu.kanade.tachiyomi.util
+
+import java.util.*
+
+/**
+ * This singleton is used to share some objects within the application, useful to communicate
+ * different parts of the app.
+ *
+ * It stores the objects in a map using the type of the object as key, so that only one object per
+ * class is stored at once.
+ */
+object SharedData {
+
+    /**
+     * Map where the objects are saved.
+     */
+    private val map = HashMap<Class<*>, Any>()
+
+    /**
+     * Publish an object to the shared data.
+     *
+     * @param data the object to put.
+     */
+    fun <T : Any> put(data: T) {
+        map.put(data.javaClass, data)
+    }
+
+    /**
+     * Retrieves an object from the shared data.
+     *
+     * @param classType the class of the object to retrieve.
+     * @return an object of type T or null if it's not found.
+     */
+    @Suppress("UNCHECKED_CAST")
+    fun <T : Any> get(classType: Class<T>) = map[classType] as? T
+
+    /**
+     * Removes an object from the shared data.
+     *
+     * @param classType the class of the object to remove.
+     * @return the object removed, null otherwise.
+     */
+    fun <T : Any> remove(classType: Class<T>) = get(classType)?.apply { map.remove(classType) }
+
+}