From 69db8a6537d718313a44474dabb9ad61a9efc314 Mon Sep 17 00:00:00 2001 From: Admin Date: Wed, 5 Feb 2020 20:59:28 +0200 Subject: [PATCH] Improve reader --- .../koitharu/kotatsu/core/db/FavouritesDao.kt | 4 +- .../koitharu/kotatsu/core/db/HistoryDao.kt | 4 +- .../domain/history/HistoryRepository.kt | 4 +- .../ui/common/BaseFullscreenActivity.kt | 18 +++++- .../ui/details/MangaDetailsActivity.kt | 9 ++- .../kotatsu/ui/reader/ReaderActivity.kt | 54 +++++++++++++---- .../koitharu/kotatsu/utils/GridTouchHelper.kt | 58 +++++++++++++++++++ .../org/koitharu/kotatsu/utils/ShareHelper.kt | 22 +++++++ app/src/main/res/drawable/ic_share.xml | 5 ++ app/src/main/res/layout/activity_reader.xml | 1 + app/src/main/res/menu/opt_details.xml | 25 +++++--- app/src/main/res/values/strings.xml | 4 ++ 12 files changed, 183 insertions(+), 25 deletions(-) create mode 100644 app/src/main/java/org/koitharu/kotatsu/utils/GridTouchHelper.kt create mode 100644 app/src/main/java/org/koitharu/kotatsu/utils/ShareHelper.kt create mode 100644 app/src/main/res/drawable/ic_share.xml diff --git a/app/src/main/java/org/koitharu/kotatsu/core/db/FavouritesDao.kt b/app/src/main/java/org/koitharu/kotatsu/core/db/FavouritesDao.kt index af246b399..9bbe39c7e 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/db/FavouritesDao.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/db/FavouritesDao.kt @@ -8,11 +8,11 @@ import org.koitharu.kotatsu.core.db.entity.FavouriteManga abstract class FavouritesDao { @Transaction - @Query("SELECT * FROM favourites ORDER BY :orderBy LIMIT :limit OFFSET :offset") + @Query("SELECT * FROM favourites GROUP BY manga_id ORDER BY :orderBy LIMIT :limit OFFSET :offset") abstract suspend fun findAll(offset: Int, limit: Int, orderBy: String): List @Transaction - @Query("SELECT * FROM favourites WHERE manga_id = :id") + @Query("SELECT * FROM favourites WHERE manga_id = :id GROUP BY manga_id") abstract suspend fun find(id: Long): FavouriteManga? @Insert(onConflict = OnConflictStrategy.IGNORE) diff --git a/app/src/main/java/org/koitharu/kotatsu/core/db/HistoryDao.kt b/app/src/main/java/org/koitharu/kotatsu/core/db/HistoryDao.kt index 83c3e2b78..1706d2ef5 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/db/HistoryDao.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/db/HistoryDao.kt @@ -13,10 +13,10 @@ abstract class HistoryDao { */ @Transaction @Query("SELECT * FROM history ORDER BY :orderBy LIMIT :limit OFFSET :offset") - abstract suspend fun getAll(offset: Int, limit: Int, orderBy: String): List + abstract suspend fun findAll(offset: Int, limit: Int, orderBy: String): List @Query("SELECT * FROM history WHERE manga_id = :id") - abstract suspend fun getOneOrNull(id: Long): HistoryEntity? + abstract suspend fun find(id: Long): HistoryEntity? @Query("DELETE FROM history") abstract suspend fun clear() diff --git a/app/src/main/java/org/koitharu/kotatsu/domain/history/HistoryRepository.kt b/app/src/main/java/org/koitharu/kotatsu/domain/history/HistoryRepository.kt index 290bb1c3b..d891534b3 100644 --- a/app/src/main/java/org/koitharu/kotatsu/domain/history/HistoryRepository.kt +++ b/app/src/main/java/org/koitharu/kotatsu/domain/history/HistoryRepository.kt @@ -17,7 +17,7 @@ class HistoryRepository : KoinComponent { private val db: MangaDatabase by inject() suspend fun getList(offset: Int): List { - val entities = db.historyDao().getAll(offset, 20, "updated_at") + val entities = db.historyDao().findAll(offset, 20, "updated_at") return entities.map { it.manga.toManga(it.tags.map(TagEntity::toMangaTag).toSet()) } } @@ -38,7 +38,7 @@ class HistoryRepository : KoinComponent { } suspend fun getOne(manga: Manga): MangaHistory? { - return db.historyDao().getOneOrNull(manga.id)?.let { + return db.historyDao().find(manga.id)?.let { MangaHistory( createdAt = Date(it.createdAt), updatedAt = Date(it.updatedAt), diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/common/BaseFullscreenActivity.kt b/app/src/main/java/org/koitharu/kotatsu/ui/common/BaseFullscreenActivity.kt index cecc08ab1..01d00ab73 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/common/BaseFullscreenActivity.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/common/BaseFullscreenActivity.kt @@ -1,15 +1,27 @@ package org.koitharu.kotatsu.ui.common +import android.os.Bundle import android.view.View abstract class BaseFullscreenActivity : BaseActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + window.decorView.setOnSystemUiVisibilityChangeListener { visibility -> + if (visibility and View.SYSTEM_UI_FLAG_FULLSCREEN == 0) { + onSystemUiShown() + } else { + onSystemUiHidden() + } + } + } + override fun onWindowFocusChanged(hasFocus: Boolean) { super.onWindowFocusChanged(hasFocus) if (hasFocus) hideSystemUI() } - private fun hideSystemUI() { + protected fun hideSystemUI() { window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY or View.SYSTEM_UI_FLAG_LAYOUT_STABLE or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION @@ -23,4 +35,8 @@ abstract class BaseFullscreenActivity : BaseActivity() { or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN) } + + protected open fun onSystemUiShown() = Unit + + protected open fun onSystemUiHidden() = Unit } \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/details/MangaDetailsActivity.kt b/app/src/main/java/org/koitharu/kotatsu/ui/details/MangaDetailsActivity.kt index 279b84bd7..f632c5470 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/details/MangaDetailsActivity.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/details/MangaDetailsActivity.kt @@ -12,12 +12,15 @@ import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.model.Manga import org.koitharu.kotatsu.core.model.MangaHistory import org.koitharu.kotatsu.ui.common.BaseActivity +import org.koitharu.kotatsu.utils.ShareHelper import org.koitharu.kotatsu.utils.ext.getDisplayMessage class MangaDetailsActivity : BaseActivity(), MangaDetailsView { val presenter by moxyPresenter(factory = ::MangaDetailsPresenter) + private var manga: Manga? = null + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_details) @@ -30,6 +33,7 @@ class MangaDetailsActivity : BaseActivity(), MangaDetailsView { } override fun onMangaUpdated(manga: Manga) { + this.manga = manga title = manga.title } @@ -47,7 +51,10 @@ class MangaDetailsActivity : BaseActivity(), MangaDetailsView { } override fun onOptionsItemSelected(item: MenuItem) = when (item.itemId) { - R.id.action_favourite -> { + R.id.action_share -> { + manga?.let { + ShareHelper.shareMangaLink(this, it) + } true } else -> super.onOptionsItemSelected(item) diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/reader/ReaderActivity.kt b/app/src/main/java/org/koitharu/kotatsu/ui/reader/ReaderActivity.kt index 2cce36dee..c1925ad8f 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/reader/ReaderActivity.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/reader/ReaderActivity.kt @@ -5,6 +5,7 @@ import android.content.Intent import android.os.Bundle import android.view.Menu import android.view.MenuItem +import android.view.MotionEvent import android.widget.Toast import androidx.core.view.isGone import androidx.core.view.isVisible @@ -16,9 +17,10 @@ import org.koitharu.kotatsu.core.model.Manga import org.koitharu.kotatsu.core.model.MangaHistory import org.koitharu.kotatsu.core.model.MangaPage import org.koitharu.kotatsu.ui.common.BaseFullscreenActivity +import org.koitharu.kotatsu.utils.GridTouchHelper import org.koitharu.kotatsu.utils.ext.showDialog -class ReaderActivity : BaseFullscreenActivity(), ReaderView { +class ReaderActivity : BaseFullscreenActivity(), ReaderView, GridTouchHelper.OnGridTouchListener { private val presenter by moxyPresenter { ReaderPresenter() } @@ -26,11 +28,13 @@ class ReaderActivity : BaseFullscreenActivity(), ReaderView { private lateinit var loader: PageLoader private lateinit var adapter: PagesAdapter + private lateinit var touchHelper: GridTouchHelper override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_reader) supportActionBar?.setDisplayHomeAsUpEnabled(true) + touchHelper = GridTouchHelper(this, this) toolbar_bottom.inflateMenu(R.menu.opt_reader_bottom) state = savedInstanceState?.getParcelable(EXTRA_STATE) @@ -76,7 +80,11 @@ class ReaderActivity : BaseFullscreenActivity(), ReaderView { override fun onOptionsItemSelected(item: MenuItem) = when (item.itemId) { R.id.action_chapters -> { - ChaptersDialog.show(supportFragmentManager, state.manga.chapters.orEmpty(), state.chapterId) + ChaptersDialog.show( + supportFragmentManager, + state.manga.chapters.orEmpty(), + state.chapterId + ) true } else -> super.onOptionsItemSelected(item) @@ -99,17 +107,43 @@ class ReaderActivity : BaseFullscreenActivity(), ReaderView { } } - private fun onTapCenter() { - if (appbar_top.isVisible) { - appbar_top.isGone = false - appbar_bottom.isGone = false - } else { - appbar_top.isGone = true - appbar_bottom.isGone = true - showSystemUI() + override fun onSystemUiShown() { + appbar_top.isGone = true + appbar_bottom.isGone = true + } + + override fun onSystemUiHidden() { + appbar_top.isGone = false + appbar_bottom.isGone = false + } + + override fun onGridTouch(area: Int) { + when (area) { + GridTouchHelper.AREA_CENTER -> { + if (appbar_top.isVisible) { + appbar_top.isVisible = false + appbar_bottom.isVisible = false + } else { + appbar_top.isVisible = true + appbar_bottom.isVisible = true + } + } + GridTouchHelper.AREA_TOP, + GridTouchHelper.AREA_LEFT -> { + pager.setCurrentItem(pager.currentItem - 1, true) + } + GridTouchHelper.AREA_BOTTOM, + GridTouchHelper.AREA_RIGHT -> { + pager.setCurrentItem(pager.currentItem + 1, true) + } } } + override fun dispatchTouchEvent(ev: MotionEvent): Boolean { + touchHelper.dispatchTouchEvent(ev) + return super.dispatchTouchEvent(ev) + } + companion object { private const val EXTRA_STATE = "state" diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/GridTouchHelper.kt b/app/src/main/java/org/koitharu/kotatsu/utils/GridTouchHelper.kt new file mode 100644 index 000000000..d4dd52dc4 --- /dev/null +++ b/app/src/main/java/org/koitharu/kotatsu/utils/GridTouchHelper.kt @@ -0,0 +1,58 @@ +package org.koitharu.kotatsu.utils + +import android.content.Context +import android.view.GestureDetector +import android.view.MotionEvent +import kotlin.math.roundToInt + +class GridTouchHelper(context: Context, private val listener: OnGridTouchListener) : + GestureDetector.SimpleOnGestureListener() { + + private val detector = GestureDetector(context, this) + private val width = context.resources.displayMetrics.widthPixels + private val height = context.resources.displayMetrics.heightPixels + + init { + detector.setIsLongpressEnabled(false) + detector.setOnDoubleTapListener(this) + } + + fun dispatchTouchEvent(event: MotionEvent) { + detector.onTouchEvent(event) + } + + override fun onSingleTapConfirmed(event: MotionEvent): Boolean { + val xIndex = (event.rawX * 2f / width).roundToInt() + val yIndex = (event.rawY * 2f / height).roundToInt() + listener.onGridTouch( + when (xIndex) { + 0 -> AREA_LEFT + 1 -> { + when (yIndex) { + 0 -> AREA_TOP + 1 -> AREA_CENTER + 2 -> AREA_BOTTOM + else -> return false + } + } + 2 -> AREA_RIGHT + else -> return false + } + ) + return true + } + + companion object { + + const val AREA_CENTER = 1 + const val AREA_LEFT = 2 + const val AREA_RIGHT = 3 + const val AREA_TOP = 4 + const val AREA_BOTTOM = 5 + } + + interface OnGridTouchListener { + + fun onGridTouch(area: Int) + } +} \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/ShareHelper.kt b/app/src/main/java/org/koitharu/kotatsu/utils/ShareHelper.kt new file mode 100644 index 000000000..26f692e2c --- /dev/null +++ b/app/src/main/java/org/koitharu/kotatsu/utils/ShareHelper.kt @@ -0,0 +1,22 @@ +package org.koitharu.kotatsu.utils + +import android.content.Context +import android.content.Intent +import org.koitharu.kotatsu.R +import org.koitharu.kotatsu.core.model.Manga + +object ShareHelper { + + @JvmStatic + fun shareMangaLink(context: Context, manga: Manga) { + val intent = Intent(Intent.ACTION_SEND) + intent.type = "text/plain" + intent.putExtra(Intent.EXTRA_TEXT, buildString { + append(manga.title) + append("\n \n") + append(manga.url) + }) + val shareIntent = Intent.createChooser(intent, context.getString(R.string.share_s, manga.title)) + context.startActivity(shareIntent) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_share.xml b/app/src/main/res/drawable/ic_share.xml new file mode 100644 index 000000000..8ed8e7e87 --- /dev/null +++ b/app/src/main/res/drawable/ic_share.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/layout/activity_reader.xml b/app/src/main/res/layout/activity_reader.xml index 5ca58e527..6dbf890ef 100644 --- a/app/src/main/res/layout/activity_reader.xml +++ b/app/src/main/res/layout/activity_reader.xml @@ -2,6 +2,7 @@ diff --git a/app/src/main/res/menu/opt_details.xml b/app/src/main/res/menu/opt_details.xml index 196e33866..9d2019bcd 100644 --- a/app/src/main/res/menu/opt_details.xml +++ b/app/src/main/res/menu/opt_details.xml @@ -1,11 +1,22 @@ - + - + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 4cb95703f..8e5ccdd56 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -30,4 +30,8 @@ Add new category Add Enter category name + Save + Share + Create shortcut… + Share %s \ No newline at end of file