Desktop shortcuts
This commit is contained in:
@@ -3,13 +3,15 @@ package org.koitharu.kotatsu.core.db
|
||||
import androidx.room.*
|
||||
import org.koitharu.kotatsu.core.db.entity.MangaEntity
|
||||
import org.koitharu.kotatsu.core.db.entity.MangaTagsEntity
|
||||
import org.koitharu.kotatsu.core.db.entity.MangaWithTags
|
||||
import org.koitharu.kotatsu.core.db.entity.TagEntity
|
||||
|
||||
@Dao
|
||||
abstract class MangaDao {
|
||||
|
||||
@Query("SELECT * FROM manga")
|
||||
abstract suspend fun getAllManga(): List<MangaEntity>
|
||||
@Transaction
|
||||
@Query("SELECT * FROM manga WHERE manga_id = :id")
|
||||
abstract suspend fun find(id: Long): MangaWithTags?
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.IGNORE)
|
||||
abstract suspend fun insert(manga: MangaEntity): Long
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
package org.koitharu.kotatsu.core.db.entity
|
||||
|
||||
import androidx.room.Embedded
|
||||
import androidx.room.Junction
|
||||
import androidx.room.Relation
|
||||
|
||||
data class MangaWithTags(
|
||||
@Embedded val manga: MangaEntity,
|
||||
@Relation(
|
||||
parentColumn = "manga_id",
|
||||
entityColumn = "tag_id",
|
||||
associateBy = Junction(MangaTagsEntity::class)
|
||||
)
|
||||
val tags: List<TagEntity>
|
||||
) {
|
||||
|
||||
fun toManga() = manga.toManga(tags.map {
|
||||
it.toMangaTag()
|
||||
}.toSet())
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package org.koitharu.kotatsu.core.exceptions
|
||||
|
||||
import java.lang.NullPointerException
|
||||
|
||||
class MangaNotFoundException(s: String? = null) : RuntimeException(s)
|
||||
@@ -3,14 +3,17 @@ package org.koitharu.kotatsu.domain
|
||||
import org.koin.core.KoinComponent
|
||||
import org.koin.core.inject
|
||||
import org.koitharu.kotatsu.core.db.MangaDatabase
|
||||
import org.koitharu.kotatsu.core.db.entity.MangaEntity
|
||||
import org.koitharu.kotatsu.core.db.entity.MangaPrefsEntity
|
||||
import org.koitharu.kotatsu.core.db.entity.TagEntity
|
||||
import org.koitharu.kotatsu.core.model.Manga
|
||||
import org.koitharu.kotatsu.core.prefs.ReaderMode
|
||||
|
||||
class MangaPreferencesRepository : KoinComponent {
|
||||
class MangaDataRepository : KoinComponent {
|
||||
|
||||
private val db: MangaDatabase by inject()
|
||||
|
||||
suspend fun saveData(mangaId: Long, mode: ReaderMode) {
|
||||
suspend fun savePreferences(mangaId: Long, mode: ReaderMode) {
|
||||
db.preferencesDao().upsert(
|
||||
MangaPrefsEntity(
|
||||
mangaId = mangaId,
|
||||
@@ -22,4 +25,12 @@ class MangaPreferencesRepository : KoinComponent {
|
||||
suspend fun getReaderMode(mangaId: Long): ReaderMode? {
|
||||
return db.preferencesDao().find(mangaId)?.let { ReaderMode.valueOf(it.mode) }
|
||||
}
|
||||
|
||||
suspend fun findMangaById(mangaId: Long): Manga? {
|
||||
return db.mangaDao().find(mangaId)?.toManga()
|
||||
}
|
||||
|
||||
suspend fun storeManga(manga: Manga) {
|
||||
db.mangaDao().upsert(MangaEntity.from(manga), manga.tags.map(TagEntity.Companion::fromMangaTag))
|
||||
}
|
||||
}
|
||||
@@ -40,12 +40,13 @@ class MangaDetailsActivity : BaseActivity(), MangaDetailsView {
|
||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||
pager.adapter = MangaDetailsAdapter(resources, supportFragmentManager)
|
||||
tabs.setupWithViewPager(pager)
|
||||
intent?.getParcelableExtra<Manga>(EXTRA_MANGA)?.let {
|
||||
presenter.loadDetails(
|
||||
manga = it,
|
||||
force = savedInstanceState?.containsKey(MvpDelegate.MOXY_DELEGATE_TAGS_KEY) != true
|
||||
)
|
||||
} ?: finish()
|
||||
if (savedInstanceState?.containsKey(MvpDelegate.MOXY_DELEGATE_TAGS_KEY) != true) {
|
||||
intent?.getParcelableExtra<Manga>(EXTRA_MANGA)?.let {
|
||||
presenter.loadDetails(it, true)
|
||||
} ?: intent?.getLongExtra(EXTRA_MANGA_ID, 0)?.takeUnless { it == 0L }?.let {
|
||||
presenter.findMangaById(it)
|
||||
} ?: finish()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onMangaUpdated(manga: Manga) {
|
||||
@@ -69,7 +70,12 @@ class MangaDetailsActivity : BaseActivity(), MangaDetailsView {
|
||||
}
|
||||
|
||||
override fun onError(e: Throwable) {
|
||||
Snackbar.make(pager, e.getDisplayMessage(resources), Snackbar.LENGTH_LONG).show()
|
||||
if (manga == null) {
|
||||
Toast.makeText(this, e.getDisplayMessage(resources), Toast.LENGTH_LONG).show()
|
||||
finish()
|
||||
} else {
|
||||
Snackbar.make(pager, e.getDisplayMessage(resources), Snackbar.LENGTH_LONG).show()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
|
||||
@@ -82,8 +88,8 @@ class MangaDetailsActivity : BaseActivity(), MangaDetailsView {
|
||||
manga?.source != null && manga?.source != MangaSource.LOCAL
|
||||
menu.findItem(R.id.action_delete).isVisible =
|
||||
manga?.source == MangaSource.LOCAL
|
||||
menu.findItem(R.id.action_shortcut).isVisible = BuildConfig.DEBUG &&
|
||||
ShortcutManagerCompat.isRequestPinShortcutSupported(this)
|
||||
menu.findItem(R.id.action_shortcut).isVisible =
|
||||
ShortcutManagerCompat.isRequestPinShortcutSupported(this)
|
||||
return super.onPrepareOptionsMenu(menu)
|
||||
}
|
||||
|
||||
@@ -142,11 +148,16 @@ class MangaDetailsActivity : BaseActivity(), MangaDetailsView {
|
||||
companion object {
|
||||
|
||||
private const val EXTRA_MANGA = "manga"
|
||||
private const val EXTRA_MANGA_ID = "manga_id"
|
||||
|
||||
const val ACTION_MANGA_VIEW = "${BuildConfig.APPLICATION_ID}.action.VIEW_MANGA"
|
||||
|
||||
fun newIntent(context: Context, manga: Manga) =
|
||||
Intent(context, MangaDetailsActivity::class.java)
|
||||
.putExtra(EXTRA_MANGA, manga)
|
||||
|
||||
fun newIntent(context: Context, mangaId: Long) =
|
||||
Intent(context, MangaDetailsActivity::class.java)
|
||||
.putExtra(EXTRA_MANGA_ID, mangaId)
|
||||
}
|
||||
}
|
||||
@@ -7,9 +7,11 @@ import kotlinx.coroutines.withContext
|
||||
import moxy.InjectViewState
|
||||
import moxy.presenterScope
|
||||
import org.koitharu.kotatsu.BuildConfig
|
||||
import org.koitharu.kotatsu.core.exceptions.MangaNotFoundException
|
||||
import org.koitharu.kotatsu.core.model.Manga
|
||||
import org.koitharu.kotatsu.core.model.MangaSource
|
||||
import org.koitharu.kotatsu.core.parser.LocalMangaRepository
|
||||
import org.koitharu.kotatsu.domain.MangaDataRepository
|
||||
import org.koitharu.kotatsu.domain.MangaProviderFactory
|
||||
import org.koitharu.kotatsu.domain.favourites.FavouritesRepository
|
||||
import org.koitharu.kotatsu.domain.favourites.OnFavouritesChangeListener
|
||||
@@ -37,6 +39,27 @@ class MangaDetailsPresenter private constructor() : BasePresenter<MangaDetailsVi
|
||||
FavouritesRepository.subscribe(this)
|
||||
}
|
||||
|
||||
fun findMangaById(id: Long) {
|
||||
presenterScope.launch {
|
||||
viewState.onLoadingStateChanged(true)
|
||||
try {
|
||||
val manga = withContext(Dispatchers.IO) {
|
||||
MangaDataRepository().findMangaById(id)
|
||||
} ?: throw MangaNotFoundException("Cannot find manga by id")
|
||||
viewState.onMangaUpdated(manga)
|
||||
loadDetails(manga, true)
|
||||
} catch (_: CancellationException){
|
||||
} catch (e: Throwable) {
|
||||
if (BuildConfig.DEBUG) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
viewState.onError(e)
|
||||
} finally {
|
||||
viewState.onLoadingStateChanged(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun loadDetails(manga: Manga, force: Boolean = false) {
|
||||
if (!force && this.manga == manga) {
|
||||
return
|
||||
@@ -52,6 +75,7 @@ class MangaDetailsPresenter private constructor() : BasePresenter<MangaDetailsVi
|
||||
}
|
||||
viewState.onMangaUpdated(data)
|
||||
this@MangaDetailsPresenter.manga = data
|
||||
} catch (_: CancellationException){
|
||||
} catch (e: Throwable) {
|
||||
if (BuildConfig.DEBUG) {
|
||||
e.printStackTrace()
|
||||
|
||||
@@ -12,7 +12,7 @@ import org.koitharu.kotatsu.BuildConfig
|
||||
import org.koitharu.kotatsu.core.model.Manga
|
||||
import org.koitharu.kotatsu.core.model.MangaPage
|
||||
import org.koitharu.kotatsu.core.prefs.ReaderMode
|
||||
import org.koitharu.kotatsu.domain.MangaPreferencesRepository
|
||||
import org.koitharu.kotatsu.domain.MangaDataRepository
|
||||
import org.koitharu.kotatsu.domain.MangaProviderFactory
|
||||
import org.koitharu.kotatsu.domain.MangaUtils
|
||||
import org.koitharu.kotatsu.domain.history.HistoryRepository
|
||||
@@ -43,12 +43,12 @@ class ReaderPresenter : BasePresenter<ReaderView>() {
|
||||
?: throw RuntimeException("Chapter ${chapterId} not found")
|
||||
val pages = repo.getPages(chapter)
|
||||
if (!isInitialized) {
|
||||
val prefs = MangaPreferencesRepository()
|
||||
val prefs = MangaDataRepository()
|
||||
var mode = prefs.getReaderMode(manga.id)
|
||||
if (mode == null) {
|
||||
mode = MangaUtils.determineReaderMode(pages)
|
||||
if (mode != null) {
|
||||
prefs.saveData(
|
||||
prefs.savePreferences(
|
||||
mangaId = manga.id,
|
||||
mode = mode
|
||||
)
|
||||
@@ -84,7 +84,7 @@ class ReaderPresenter : BasePresenter<ReaderView>() {
|
||||
page = state.page
|
||||
)
|
||||
if (mode != null) {
|
||||
MangaPreferencesRepository().saveData(
|
||||
MangaDataRepository().savePreferences(
|
||||
mangaId = state.manga.id,
|
||||
mode = mode
|
||||
)
|
||||
|
||||
@@ -12,6 +12,7 @@ import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.core.model.Manga
|
||||
import org.koitharu.kotatsu.domain.MangaDataRepository
|
||||
import org.koitharu.kotatsu.ui.details.MangaDetailsActivity
|
||||
import org.koitharu.kotatsu.utils.ext.safe
|
||||
|
||||
@@ -27,6 +28,7 @@ object ShortcutUtils {
|
||||
}.toBitmap()
|
||||
}
|
||||
}
|
||||
MangaDataRepository().storeManga(manga)
|
||||
return ShortcutInfoCompat.Builder(context, manga.id.toString())
|
||||
.setShortLabel(manga.title)
|
||||
.setLongLabel(manga.title)
|
||||
@@ -34,7 +36,7 @@ object ShortcutUtils {
|
||||
IconCompat.createWithBitmap(it)
|
||||
} ?: IconCompat.createWithResource(context, R.drawable.ic_launcher_foreground))
|
||||
.setIntent(
|
||||
MangaDetailsActivity.newIntent(context, manga.copy(chapters = null))
|
||||
MangaDetailsActivity.newIntent(context, manga.id)
|
||||
.setAction(MangaDetailsActivity.ACTION_MANGA_VIEW)
|
||||
)
|
||||
.build()
|
||||
|
||||
Reference in New Issue
Block a user