Desktop shortcuts

This commit is contained in:
Koitharu
2020-03-05 20:12:08 +02:00
parent e528cc38ae
commit c60683eb42
8 changed files with 93 additions and 18 deletions

View File

@@ -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

View File

@@ -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())
}

View File

@@ -0,0 +1,5 @@
package org.koitharu.kotatsu.core.exceptions
import java.lang.NullPointerException
class MangaNotFoundException(s: String? = null) : RuntimeException(s)

View File

@@ -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))
}
}

View File

@@ -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)
}
}

View File

@@ -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()

View File

@@ -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
)

View File

@@ -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()