Add Resume reading fab
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
package org.koitharu.kotatsu.core.exceptions
|
||||
|
||||
class EmptyHistoryException : RuntimeException()
|
||||
@@ -16,8 +16,8 @@ class HistoryRepository : KoinComponent {
|
||||
|
||||
private val db: MangaDatabase by inject()
|
||||
|
||||
suspend fun getList(offset: Int): List<Manga> {
|
||||
val entities = db.historyDao().findAll(offset, 20)
|
||||
suspend fun getList(offset: Int, limit: Int = 20): List<Manga> {
|
||||
val entities = db.historyDao().findAll(offset, limit)
|
||||
return entities.map { it.manga.toManga(it.tags.map(TagEntity::toMangaTag).toSet()) }
|
||||
}
|
||||
|
||||
|
||||
@@ -1,14 +1,20 @@
|
||||
package org.koitharu.kotatsu.ui.main
|
||||
|
||||
import android.content.SharedPreferences
|
||||
import android.content.res.ColorStateList
|
||||
import android.content.res.Configuration
|
||||
import android.graphics.Color
|
||||
import android.os.Bundle
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import androidx.appcompat.app.ActionBarDrawerToggle
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.swiperefreshlayout.widget.CircularProgressDrawable
|
||||
import com.google.android.material.navigation.NavigationView
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import kotlinx.android.synthetic.main.activity_main.*
|
||||
import moxy.ktx.moxyPresenter
|
||||
import org.koin.core.inject
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.core.model.MangaSource
|
||||
@@ -19,10 +25,16 @@ import org.koitharu.kotatsu.ui.main.list.favourites.FavouritesListFragment
|
||||
import org.koitharu.kotatsu.ui.main.list.history.HistoryListFragment
|
||||
import org.koitharu.kotatsu.ui.main.list.local.LocalListFragment
|
||||
import org.koitharu.kotatsu.ui.main.list.remote.RemoteListFragment
|
||||
import org.koitharu.kotatsu.ui.reader.ReaderActivity
|
||||
import org.koitharu.kotatsu.ui.reader.ReaderState
|
||||
import org.koitharu.kotatsu.ui.settings.SettingsActivity
|
||||
import org.koitharu.kotatsu.utils.ext.getDisplayMessage
|
||||
import org.koitharu.kotatsu.utils.ext.resolveDp
|
||||
|
||||
class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedListener,
|
||||
SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
SharedPreferences.OnSharedPreferenceChangeListener, MainView {
|
||||
|
||||
private val presenter by moxyPresenter(factory = ::MainPresenter)
|
||||
|
||||
private val settings by inject<AppSettings>()
|
||||
private lateinit var drawerToggle: ActionBarDrawerToggle
|
||||
@@ -40,7 +52,15 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList
|
||||
navigationView.setNavigationItemSelectedListener(this)
|
||||
settings.subscribe(this)
|
||||
|
||||
if (supportFragmentManager.findFragmentById(R.id.container) == null) {
|
||||
fab.imageTintList = ColorStateList.valueOf(Color.WHITE)
|
||||
fab.isVisible = true
|
||||
fab.setOnClickListener {
|
||||
presenter.openLastReader()
|
||||
}
|
||||
|
||||
supportFragmentManager.findFragmentById(R.id.container)?.let {
|
||||
fab.isVisible = it is HistoryListFragment
|
||||
} ?: run {
|
||||
navigationView.setCheckedItem(R.id.nav_history)
|
||||
setPrimaryFragment(HistoryListFragment.newInstance())
|
||||
}
|
||||
@@ -91,6 +111,27 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onOpenReader(state: ReaderState) {
|
||||
startActivity(ReaderActivity.newIntent(this, state))
|
||||
}
|
||||
|
||||
override fun onError(e: Throwable) {
|
||||
Snackbar.make(container, e.getDisplayMessage(resources), Snackbar.LENGTH_SHORT).show()
|
||||
}
|
||||
|
||||
override fun onLoadingStateChanged(isLoading: Boolean) {
|
||||
fab.isEnabled = !isLoading
|
||||
if (isLoading) {
|
||||
fab.setImageDrawable(CircularProgressDrawable(this).also {
|
||||
it.setColorSchemeColors(Color.WHITE)
|
||||
it.strokeWidth = resources.resolveDp(2f)
|
||||
it.start()
|
||||
})
|
||||
} else {
|
||||
fab.setImageResource(R.drawable.ic_read_fill)
|
||||
}
|
||||
}
|
||||
|
||||
private fun initSideMenu(remoteSources: List<MangaSource>) {
|
||||
val submenu = navigationView.menu.findItem(R.id.nav_remote_sources).subMenu
|
||||
submenu.removeGroup(R.id.group_remote_sources)
|
||||
@@ -110,5 +151,6 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList
|
||||
supportFragmentManager.beginTransaction()
|
||||
.replace(R.id.container, fragment)
|
||||
.commit()
|
||||
fab.isVisible = fragment is HistoryListFragment
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package org.koitharu.kotatsu.ui.main
|
||||
|
||||
import kotlinx.coroutines.CancellationException
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import moxy.InjectViewState
|
||||
import moxy.presenterScope
|
||||
import org.koitharu.kotatsu.core.exceptions.EmptyHistoryException
|
||||
import org.koitharu.kotatsu.domain.MangaProviderFactory
|
||||
import org.koitharu.kotatsu.domain.history.HistoryRepository
|
||||
import org.koitharu.kotatsu.ui.common.BasePresenter
|
||||
import org.koitharu.kotatsu.ui.reader.ReaderState
|
||||
|
||||
@InjectViewState
|
||||
class MainPresenter : BasePresenter<MainView>() {
|
||||
|
||||
fun openLastReader() {
|
||||
presenterScope.launch {
|
||||
viewState.onLoadingStateChanged(isLoading = true)
|
||||
try {
|
||||
val state = withContext(Dispatchers.IO) {
|
||||
val repo = HistoryRepository()
|
||||
val manga = repo.getList(0, 1).firstOrNull()
|
||||
?: throw EmptyHistoryException()
|
||||
val history = repo.getOne(manga) ?: throw EmptyHistoryException()
|
||||
ReaderState(
|
||||
MangaProviderFactory.create(manga.source).getDetails(manga),
|
||||
history.chapterId, history.page
|
||||
)
|
||||
}
|
||||
viewState.onOpenReader(state)
|
||||
} catch (_: CancellationException) {
|
||||
} catch (e: Throwable) {
|
||||
viewState.onError(e)
|
||||
} finally {
|
||||
viewState.onLoadingStateChanged(isLoading = false)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
12
app/src/main/java/org/koitharu/kotatsu/ui/main/MainView.kt
Normal file
12
app/src/main/java/org/koitharu/kotatsu/ui/main/MainView.kt
Normal file
@@ -0,0 +1,12 @@
|
||||
package org.koitharu.kotatsu.ui.main
|
||||
|
||||
import moxy.viewstate.strategy.alias.OneExecution
|
||||
import org.koitharu.kotatsu.core.model.MangaState
|
||||
import org.koitharu.kotatsu.ui.common.BaseMvpView
|
||||
import org.koitharu.kotatsu.ui.reader.ReaderState
|
||||
|
||||
interface MainView : BaseMvpView {
|
||||
|
||||
@OneExecution
|
||||
fun onOpenReader(state: ReaderState)
|
||||
}
|
||||
@@ -1,9 +1,14 @@
|
||||
package org.koitharu.kotatsu.ui.main.list.history
|
||||
|
||||
import android.content.res.ColorStateList
|
||||
import android.graphics.Color
|
||||
import android.os.Bundle
|
||||
import android.view.Menu
|
||||
import android.view.MenuInflater
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.core.view.isVisible
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import kotlinx.android.synthetic.main.fragment_list.*
|
||||
import moxy.ktx.moxyPresenter
|
||||
|
||||
@@ -4,6 +4,7 @@ import android.content.res.Resources
|
||||
import kotlinx.coroutines.delay
|
||||
import org.koitharu.kotatsu.BuildConfig
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.core.exceptions.EmptyHistoryException
|
||||
import org.koitharu.kotatsu.core.exceptions.UnsupportedFileException
|
||||
import java.io.IOException
|
||||
|
||||
@@ -35,6 +36,7 @@ suspend inline fun <T, R> T.retryUntilSuccess(maxAttempts: Int, action: T.() ->
|
||||
fun Throwable.getDisplayMessage(resources: Resources) = when (this) {
|
||||
is UnsupportedOperationException -> resources.getString(R.string.operation_not_supported)
|
||||
is UnsupportedFileException -> resources.getString(R.string.text_file_not_supported)
|
||||
is EmptyHistoryException -> resources.getString(R.string.history_is_empty)
|
||||
is IOException -> resources.getString(R.string.network_error)
|
||||
else -> if (BuildConfig.DEBUG) {
|
||||
message ?: resources.getString(R.string.error_occurred)
|
||||
|
||||
12
app/src/main/res/drawable/ic_read_fill.xml
Normal file
12
app/src/main/res/drawable/ic_read_fill.xml
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:tint="?attr/colorControlNormal"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#000"
|
||||
android:pathData="M12,8A3,3 0 0,0 15,5A3,3 0 0,0 12,2A3,3 0 0,0 9,5A3,3 0 0,0 12,8M12,11.54C9.64,9.35 6.5,8 3,8V19C6.5,19 9.64,20.35 12,22.54C14.36,20.35 17.5,19 21,19V8C17.5,8 14.36,9.35 12,11.54Z" />
|
||||
</vector>
|
||||
@@ -34,6 +34,20 @@
|
||||
android:layout_height="match_parent"
|
||||
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior" />
|
||||
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
android:id="@+id/fab"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="16dp"
|
||||
android:src="@drawable/ic_read_fill"
|
||||
android:visibility="gone"
|
||||
app:fabSize="normal"
|
||||
app:backgroundTint="?colorAccent"
|
||||
app:layout_anchor="@id/container"
|
||||
app:layout_anchorGravity="bottom|end"
|
||||
app:layout_behavior="com.google.android.material.behavior.HideBottomViewOnScrollBehavior"
|
||||
tools:visibility="visible" />
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
|
||||
<com.google.android.material.navigation.NavigationView
|
||||
|
||||
@@ -5,8 +5,7 @@
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/drawer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:openDrawer="end">
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
@@ -44,8 +43,8 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:gravity="center"
|
||||
android:textColor="?android:textColorSecondary"
|
||||
android:textAppearance="?android:textAppearanceMedium"
|
||||
android:textColor="?android:textColorSecondary"
|
||||
tools:text="@tools:sample/lorem[3]" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
Reference in New Issue
Block a user