Update history fragment

This commit is contained in:
Koitharu
2020-02-23 14:43:40 +02:00
parent d7eebcd795
commit ac935eb203
10 changed files with 129 additions and 16 deletions

View File

@@ -27,6 +27,9 @@ abstract class HistoryDao {
@Query("UPDATE history SET page = :page, chapter_id = :chapterId, updated_at = :updatedAt WHERE manga_id = :mangaId")
abstract suspend fun update(mangaId: Long, page: Int, chapterId: Long, updatedAt: Long): Int
@Query("DELETE FROM history WHERE manga_id = :mangaId")
abstract suspend fun delete(mangaId: Long)
suspend fun update(entity: HistoryEntity) = update(entity.mangaId, entity.page, entity.chapterId, entity.updatedAt)
@Transaction

View File

@@ -53,6 +53,11 @@ class HistoryRepository : KoinComponent {
notifyHistoryChanged()
}
suspend fun delete(manga: Manga) {
db.historyDao().delete(manga.id)
notifyHistoryChanged()
}
companion object {
private val listeners = HashSet<OnHistoryChangeListener>()

View File

@@ -2,11 +2,9 @@ package org.koitharu.kotatsu.ui.main.list
import android.content.SharedPreferences
import android.os.Bundle
import android.view.Menu
import android.view.MenuInflater
import android.view.MenuItem
import android.view.View
import android.view.*
import androidx.annotation.CallSuper
import androidx.appcompat.widget.PopupMenu
import androidx.core.view.GravityCompat
import androidx.core.view.isVisible
import androidx.drawerlayout.widget.DrawerLayout
@@ -42,7 +40,7 @@ abstract class MangaListFragment<E> : BaseFragment(R.layout.fragment_list), Mang
private val settings by inject<AppSettings>()
private lateinit var adapter: MangaListAdapter
private var adapter: MangaListAdapter? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -65,6 +63,7 @@ abstract class MangaListFragment<E> : BaseFragment(R.layout.fragment_list), Mang
}
override fun onDestroyView() {
adapter = null
settings.unsubscribe(this)
super.onDestroyView()
}
@@ -103,8 +102,23 @@ abstract class MangaListFragment<E> : BaseFragment(R.layout.fragment_list), Mang
startActivity(MangaDetailsActivity.newIntent(context ?: return, item))
}
override fun onItemLongClick(item: Manga, position: Int, view: View): Boolean {
val menu = PopupMenu(context ?: return false, view)
onCreatePopupMenu(menu.menuInflater, menu.menu, item)
return if (menu.menu.hasVisibleItems()) {
menu.setOnMenuItemClickListener {
onPopupMenuItemSelected(it, item)
}
menu.gravity = GravityCompat.END or Gravity.TOP
menu.show()
true
} else {
false
}
}
override fun onListChanged(list: List<Manga>) {
adapter.replaceData(list)
adapter?.replaceData(list)
if (list.isEmpty()) {
setUpEmptyListHolder()
layout_holder.isVisible = true
@@ -114,7 +128,20 @@ abstract class MangaListFragment<E> : BaseFragment(R.layout.fragment_list), Mang
}
override fun onListAppended(list: List<Manga>) {
adapter.appendData(list)
adapter?.appendData(list)
}
@CallSuper
override fun onItemRemoved(item: Manga) {
adapter?.let {
it.removeItem(item)
if (it.itemCount == 0) {
setUpEmptyListHolder()
layout_holder.isVisible = true
} else {
layout_holder.isVisible = false
}
}
}
override fun onError(e: Exception) {
@@ -181,7 +208,7 @@ abstract class MangaListFragment<E> : BaseFragment(R.layout.fragment_list), Mang
recyclerView.adapter = null
recyclerView.layoutManager = null
recyclerView.clearItemDecorations()
adapter.listMode = mode
adapter?.listMode = mode
recyclerView.layoutManager = when (mode) {
ListMode.GRID -> GridLayoutManager(ctx, 3)
else -> LinearLayoutManager(ctx)
@@ -196,7 +223,7 @@ abstract class MangaListFragment<E> : BaseFragment(R.layout.fragment_list), Mang
)
}
)
adapter.notifyDataSetChanged()
adapter?.notifyDataSetChanged()
recyclerView.firstItem = position
}
@@ -213,4 +240,8 @@ abstract class MangaListFragment<E> : BaseFragment(R.layout.fragment_list), Mang
else -> null
}
}
protected open fun onCreatePopupMenu(inflater: MenuInflater, menu: Menu, data: Manga) = Unit
protected open fun onPopupMenuItemSelected(item: MenuItem, data: Manga) = false
}

View File

@@ -23,4 +23,7 @@ interface MangaListView<E> : MvpView {
@StateStrategyType(AddToEndSingleStrategy::class)
fun onInitFilter(sortOrders: List<SortOrder>, tags: List<MangaTag>, currentFilter: MangaFilter?)
@StateStrategyType(AddToEndStrategy::class)
fun onItemRemoved(item: Manga)
}

View File

@@ -6,6 +6,7 @@ import android.view.MenuItem
import kotlinx.android.synthetic.main.fragment_list.*
import moxy.ktx.moxyPresenter
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.model.Manga
import org.koitharu.kotatsu.ui.main.list.MangaListFragment
import org.koitharu.kotatsu.ui.main.list.MangaListView

View File

@@ -3,14 +3,18 @@ package org.koitharu.kotatsu.ui.main.list.history
import android.view.Menu
import android.view.MenuInflater
import android.view.MenuItem
import androidx.appcompat.app.AlertDialog
import com.google.android.material.snackbar.Snackbar
import kotlinx.android.synthetic.main.fragment_list.*
import moxy.ktx.moxyPresenter
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.model.Manga
import org.koitharu.kotatsu.core.model.MangaHistory
import org.koitharu.kotatsu.ui.main.list.MangaListFragment
import org.koitharu.kotatsu.ui.main.list.MangaListView
import org.koitharu.kotatsu.utils.ext.ellipsize
class HistoryListFragment : MangaListFragment<MangaHistory>(), MangaListView<MangaHistory>{
class HistoryListFragment : MangaListFragment<MangaHistory>(), MangaListView<MangaHistory> {
private val presenter by moxyPresenter(factory = ::HistoryListPresenter)
@@ -23,12 +27,20 @@ class HistoryListFragment : MangaListFragment<MangaHistory>(), MangaListView<Man
super.onCreateOptionsMenu(menu, inflater)
}
override fun onOptionsItemSelected(item: MenuItem) = when(item.itemId) {
R.id.action_clear_history -> {
presenter.clearHistory()
true
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return when (item.itemId) {
R.id.action_clear_history -> {
AlertDialog.Builder(context ?: return false)
.setTitle(R.string.clear_history)
.setMessage(R.string.text_clear_history_prompt)
.setNegativeButton(android.R.string.cancel, null)
.setPositiveButton(R.string.clear) { _, _ ->
presenter.clearHistory()
}.show()
true
}
else -> super.onOptionsItemSelected(item)
}
else -> super.onOptionsItemSelected(item)
}
override fun getTitle(): CharSequence? {
@@ -40,6 +52,31 @@ class HistoryListFragment : MangaListFragment<MangaHistory>(), MangaListView<Man
textView_holder.setCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, 0, 0)
}
override fun onCreatePopupMenu(inflater: MenuInflater, menu: Menu, data: Manga) {
super.onCreatePopupMenu(inflater, menu, data)
inflater.inflate(R.menu.popup_history, menu)
}
override fun onPopupMenuItemSelected(item: MenuItem, data: Manga): Boolean {
return when (item.itemId) {
R.id.action_remove -> {
presenter.removeFromHistory(data)
true
}
else -> super.onPopupMenuItemSelected(item, data)
}
}
override fun onItemRemoved(item: Manga) {
super.onItemRemoved(item)
Snackbar.make(
recyclerView, getString(
R.string._s_removed_from_history,
item.title.ellipsize(14)
), Snackbar.LENGTH_SHORT
).show()
}
companion object {
fun newInstance() = HistoryListFragment()

View File

@@ -5,6 +5,7 @@ import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import moxy.InjectViewState
import org.koitharu.kotatsu.BuildConfig
import org.koitharu.kotatsu.core.model.Manga
import org.koitharu.kotatsu.core.model.MangaHistory
import org.koitharu.kotatsu.domain.history.HistoryRepository
import org.koitharu.kotatsu.ui.common.BasePresenter
@@ -61,4 +62,19 @@ class HistoryListPresenter : BasePresenter<MangaListView<MangaHistory>>() {
}
}
}
fun removeFromHistory(manga: Manga) {
launch {
try {
withContext(Dispatchers.IO) {
repository.delete(manga)
}
viewState.onItemRemoved(manga)
} catch (e: Exception) {
if (BuildConfig.DEBUG) {
e.printStackTrace()
}
}
}
}
}

View File

@@ -57,4 +57,8 @@ fun String.transliterate(skipMissing: Boolean): String {
fun String.toFileName() = this.transliterate(false)
.replace(Regex("[^a-z0-9_\\-]", setOf(RegexOption.IGNORE_CASE)), " ")
.replace(Regex("\\s+"), "_")
.replace(Regex("\\s+"), "_")
fun String.ellipsize(maxLength: Int) = if (this.length > maxLength) {
this.take(maxLength - 1) + Typography.ellipsis
} else this

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<menu
xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/action_remove"
android:title="@string/remove" />
</menu>

View File

@@ -61,4 +61,8 @@
<string name="dark">Dark</string>
<string name="automatic">Automatic</string>
<string name="pages">Pages</string>
<string name="clear">Clear</string>
<string name="text_clear_history_prompt">Are you rally want to clear all your reading history? This action cannot be undone.</string>
<string name="remove">Remove</string>
<string name="_s_removed_from_history">\"%s\" removed from history</string>
</resources>