DI refactoring
This commit is contained in:
@@ -3,37 +3,25 @@ package org.koitharu.kotatsu
|
||||
import android.app.Application
|
||||
import android.os.StrictMode
|
||||
import androidx.appcompat.app.AppCompatDelegate
|
||||
import androidx.room.Room
|
||||
import coil.Coil
|
||||
import coil.ComponentRegistry
|
||||
import coil.ImageLoader
|
||||
import coil.util.CoilUtils
|
||||
import okhttp3.CookieJar
|
||||
import okhttp3.OkHttpClient
|
||||
import org.koin.android.ext.android.get
|
||||
import org.koin.android.ext.koin.androidContext
|
||||
import org.koin.android.ext.koin.androidLogger
|
||||
import org.koin.core.context.startKoin
|
||||
import org.koin.core.logger.Level
|
||||
import org.koin.dsl.module
|
||||
import org.koitharu.kotatsu.core.db.DatabasePrePopulateCallback
|
||||
import org.koitharu.kotatsu.core.db.MangaDatabase
|
||||
import org.koitharu.kotatsu.core.db.migrations.*
|
||||
import org.koitharu.kotatsu.core.local.CbzFetcher
|
||||
import org.koitharu.kotatsu.core.db.databaseModule
|
||||
import org.koitharu.kotatsu.core.github.githubModule
|
||||
import org.koitharu.kotatsu.core.local.PagesCache
|
||||
import org.koitharu.kotatsu.core.local.cookies.PersistentCookieJar
|
||||
import org.koitharu.kotatsu.core.local.cookies.cache.SetCookieCache
|
||||
import org.koitharu.kotatsu.core.local.cookies.persistence.SharedPrefsCookiePersistor
|
||||
import org.koitharu.kotatsu.core.network.networkModule
|
||||
import org.koitharu.kotatsu.core.parser.LocalMangaRepository
|
||||
import org.koitharu.kotatsu.core.parser.UserAgentInterceptor
|
||||
import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||
import org.koitharu.kotatsu.domain.MangaDataRepository
|
||||
import org.koitharu.kotatsu.domain.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.domain.MangaSearchRepository
|
||||
import org.koitharu.kotatsu.domain.favourites.FavouritesRepository
|
||||
import org.koitharu.kotatsu.domain.history.HistoryRepository
|
||||
import org.koitharu.kotatsu.domain.tracking.TrackingRepository
|
||||
import org.koitharu.kotatsu.ui.base.uiModule
|
||||
import org.koitharu.kotatsu.ui.utils.AppCrashHandler
|
||||
import org.koitharu.kotatsu.ui.widget.WidgetUpdater
|
||||
import org.koitharu.kotatsu.utils.CacheUtils
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
class KotatsuApp : Application() {
|
||||
|
||||
@@ -57,9 +45,8 @@ class KotatsuApp : Application() {
|
||||
)
|
||||
}
|
||||
initKoin()
|
||||
initCoil(get())
|
||||
Thread.setDefaultUncaughtExceptionHandler(AppCrashHandler(applicationContext))
|
||||
AppCompatDelegate.setDefaultNightMode(AppSettings(this).theme)
|
||||
AppCompatDelegate.setDefaultNightMode(get<AppSettings>().theme)
|
||||
val widgetUpdater = WidgetUpdater(applicationContext)
|
||||
FavouritesRepository.subscribe(widgetUpdater)
|
||||
HistoryRepository.subscribe(widgetUpdater)
|
||||
@@ -67,66 +54,23 @@ class KotatsuApp : Application() {
|
||||
|
||||
private fun initKoin() {
|
||||
startKoin {
|
||||
androidLogger(Level.ERROR)
|
||||
androidContext(applicationContext)
|
||||
androidContext(this@KotatsuApp)
|
||||
modules(
|
||||
networkModule,
|
||||
databaseModule,
|
||||
githubModule,
|
||||
uiModule,
|
||||
module {
|
||||
single<CookieJar> {
|
||||
PersistentCookieJar(
|
||||
SetCookieCache(),
|
||||
SharedPrefsCookiePersistor(applicationContext)
|
||||
)
|
||||
}
|
||||
factory {
|
||||
okHttp(get())
|
||||
.cache(CacheUtils.createHttpCache(applicationContext))
|
||||
.build()
|
||||
}
|
||||
single {
|
||||
mangaDb().build()
|
||||
}
|
||||
single {
|
||||
MangaLoaderContext()
|
||||
}
|
||||
single {
|
||||
AppSettings(applicationContext)
|
||||
}
|
||||
single {
|
||||
PagesCache(applicationContext)
|
||||
}
|
||||
single { FavouritesRepository(get()) }
|
||||
single { HistoryRepository(get()) }
|
||||
single { TrackingRepository(get()) }
|
||||
single { MangaDataRepository(get()) }
|
||||
single { MangaSearchRepository() }
|
||||
single { MangaLoaderContext() }
|
||||
single { AppSettings(get()) }
|
||||
single { PagesCache(get()) }
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun initCoil(cookieJar: CookieJar) {
|
||||
Coil.setImageLoader(
|
||||
ImageLoader.Builder(applicationContext)
|
||||
.okHttpClient(
|
||||
okHttp(cookieJar)
|
||||
.cache(CoilUtils.createDefaultCache(applicationContext))
|
||||
.build()
|
||||
).componentRegistry(
|
||||
ComponentRegistry.Builder()
|
||||
.add(CbzFetcher())
|
||||
.build()
|
||||
)
|
||||
.build()
|
||||
)
|
||||
}
|
||||
|
||||
private fun okHttp(cookieJar: CookieJar) = OkHttpClient.Builder().apply {
|
||||
connectTimeout(20, TimeUnit.SECONDS)
|
||||
readTimeout(60, TimeUnit.SECONDS)
|
||||
writeTimeout(20, TimeUnit.SECONDS)
|
||||
cookieJar(cookieJar)
|
||||
addInterceptor(UserAgentInterceptor)
|
||||
}
|
||||
|
||||
private fun mangaDb() = Room.databaseBuilder(
|
||||
applicationContext,
|
||||
MangaDatabase::class.java,
|
||||
"kotatsu-db"
|
||||
).addMigrations(Migration1To2, Migration2To3, Migration3To4, Migration4To5, Migration5To6)
|
||||
.addCallback(DatabasePrePopulateCallback(resources))
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package org.koitharu.kotatsu.core.db
|
||||
|
||||
import androidx.room.Room
|
||||
import org.koin.android.ext.koin.androidContext
|
||||
import org.koin.dsl.module
|
||||
import org.koitharu.kotatsu.core.db.migrations.*
|
||||
|
||||
val databaseModule
|
||||
get() = module {
|
||||
single {
|
||||
Room.databaseBuilder(
|
||||
androidContext(),
|
||||
MangaDatabase::class.java,
|
||||
"kotatsu-db"
|
||||
).addMigrations(
|
||||
Migration1To2(),
|
||||
Migration2To3(),
|
||||
Migration3To4(),
|
||||
Migration4To5(),
|
||||
Migration5To6()
|
||||
).addCallback(
|
||||
DatabasePrePopulateCallback(androidContext().resources)
|
||||
).build()
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
package org.koitharu.kotatsu.core.db
|
||||
|
||||
import androidx.room.*
|
||||
import org.koitharu.kotatsu.core.db.entity.HistoryEntity
|
||||
import org.koitharu.kotatsu.core.db.entity.HistoryWithManga
|
||||
import org.koitharu.kotatsu.core.db.entity.MangaEntity
|
||||
|
||||
|
||||
@Dao
|
||||
abstract class HistoryDao {
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
@Transaction
|
||||
@Query("SELECT * FROM history ORDER BY updated_at DESC LIMIT :limit OFFSET :offset")
|
||||
abstract suspend fun findAll(offset: Int, limit: Int): List<HistoryWithManga>
|
||||
|
||||
@Query("SELECT * FROM manga WHERE manga_id IN (SELECT manga_id FROM history)")
|
||||
abstract suspend fun findAllManga(): List<MangaEntity>
|
||||
|
||||
@Query("SELECT * FROM history WHERE manga_id = :id")
|
||||
abstract suspend fun find(id: Long): HistoryEntity?
|
||||
|
||||
@Query("DELETE FROM history")
|
||||
abstract suspend fun clear()
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.IGNORE)
|
||||
abstract suspend fun insert(entity: HistoryEntity): Long
|
||||
|
||||
@Query("UPDATE history SET page = :page, chapter_id = :chapterId, scroll = :scroll, updated_at = :updatedAt WHERE manga_id = :mangaId")
|
||||
abstract suspend fun update(mangaId: Long, page: Int, chapterId: Long, scroll: Float, 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.scroll, entity.updatedAt)
|
||||
|
||||
@Transaction
|
||||
open suspend fun upsert(entity: HistoryEntity): Boolean {
|
||||
return if (update(entity) == 0) {
|
||||
insert(entity)
|
||||
true
|
||||
} else false
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,6 +2,7 @@ package org.koitharu.kotatsu.core.db
|
||||
|
||||
import androidx.room.Database
|
||||
import androidx.room.RoomDatabase
|
||||
import org.koitharu.kotatsu.core.db.dao.*
|
||||
import org.koitharu.kotatsu.core.db.entity.*
|
||||
|
||||
@Database(
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.koitharu.kotatsu.core.db
|
||||
package org.koitharu.kotatsu.core.db.dao
|
||||
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Insert
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.koitharu.kotatsu.core.db
|
||||
package org.koitharu.kotatsu.core.db.dao
|
||||
|
||||
import androidx.room.*
|
||||
import org.koitharu.kotatsu.core.db.entity.FavouriteEntity
|
||||
@@ -0,0 +1,54 @@
|
||||
package org.koitharu.kotatsu.core.db.dao
|
||||
|
||||
import androidx.room.*
|
||||
import org.koitharu.kotatsu.core.db.entity.HistoryEntity
|
||||
import org.koitharu.kotatsu.core.db.entity.HistoryWithManga
|
||||
import org.koitharu.kotatsu.core.db.entity.MangaEntity
|
||||
|
||||
|
||||
@Dao
|
||||
abstract class HistoryDao {
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
@Transaction
|
||||
@Query("SELECT * FROM history ORDER BY updated_at DESC LIMIT :limit OFFSET :offset")
|
||||
abstract suspend fun findAll(offset: Int, limit: Int): List<HistoryWithManga>
|
||||
|
||||
@Query("SELECT * FROM manga WHERE manga_id IN (SELECT manga_id FROM history)")
|
||||
abstract suspend fun findAllManga(): List<MangaEntity>
|
||||
|
||||
@Query("SELECT * FROM history WHERE manga_id = :id")
|
||||
abstract suspend fun find(id: Long): HistoryEntity?
|
||||
|
||||
@Query("DELETE FROM history")
|
||||
abstract suspend fun clear()
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.IGNORE)
|
||||
abstract suspend fun insert(entity: HistoryEntity): Long
|
||||
|
||||
@Query("UPDATE history SET page = :page, chapter_id = :chapterId, scroll = :scroll, updated_at = :updatedAt WHERE manga_id = :mangaId")
|
||||
abstract suspend fun update(
|
||||
mangaId: Long,
|
||||
page: Int,
|
||||
chapterId: Long,
|
||||
scroll: Float,
|
||||
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.scroll, entity.updatedAt)
|
||||
|
||||
@Transaction
|
||||
open suspend fun upsert(entity: HistoryEntity): Boolean {
|
||||
return if (update(entity) == 0) {
|
||||
insert(entity)
|
||||
true
|
||||
} else false
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.koitharu.kotatsu.core.db
|
||||
package org.koitharu.kotatsu.core.db.dao
|
||||
|
||||
import androidx.room.*
|
||||
import org.koitharu.kotatsu.core.db.entity.MangaEntity
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.koitharu.kotatsu.core.db
|
||||
package org.koitharu.kotatsu.core.db.dao
|
||||
|
||||
import androidx.room.*
|
||||
import org.koitharu.kotatsu.core.db.entity.MangaPrefsEntity
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.koitharu.kotatsu.core.db
|
||||
package org.koitharu.kotatsu.core.db.dao
|
||||
|
||||
import androidx.room.*
|
||||
import org.koitharu.kotatsu.core.db.entity.TagEntity
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.koitharu.kotatsu.core.db
|
||||
package org.koitharu.kotatsu.core.db.dao
|
||||
|
||||
import androidx.room.*
|
||||
import org.koitharu.kotatsu.core.db.entity.TrackLogEntity
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.koitharu.kotatsu.core.db
|
||||
package org.koitharu.kotatsu.core.db.dao
|
||||
|
||||
import androidx.room.*
|
||||
import org.koitharu.kotatsu.core.db.entity.TrackEntity
|
||||
@@ -3,7 +3,7 @@ package org.koitharu.kotatsu.core.db.migrations
|
||||
import androidx.room.migration.Migration
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
|
||||
object Migration1To2 : Migration(1, 2) {
|
||||
class Migration1To2 : Migration(1, 2) {
|
||||
/**
|
||||
* Adding foreign keys
|
||||
*/
|
||||
|
||||
@@ -3,7 +3,7 @@ package org.koitharu.kotatsu.core.db.migrations
|
||||
import androidx.room.migration.Migration
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
|
||||
object Migration2To3 : Migration(2, 3) {
|
||||
class Migration2To3 : Migration(2, 3) {
|
||||
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("ALTER TABLE history ADD COLUMN scroll REAL NOT NULL DEFAULT 0")
|
||||
|
||||
@@ -3,7 +3,7 @@ package org.koitharu.kotatsu.core.db.migrations
|
||||
import androidx.room.migration.Migration
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
|
||||
object Migration3To4 : Migration(3, 4) {
|
||||
class Migration3To4 : Migration(3, 4) {
|
||||
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("CREATE TABLE IF NOT EXISTS tracks (manga_id INTEGER NOT NULL, chapters_total INTEGER NOT NULL, last_chapter_id INTEGER NOT NULL, chapters_new INTEGER NOT NULL, last_check INTEGER NOT NULL, last_notified_id INTEGER NOT NULL, PRIMARY KEY(manga_id), FOREIGN KEY(manga_id) REFERENCES manga(manga_id) ON UPDATE NO ACTION ON DELETE CASCADE )")
|
||||
|
||||
@@ -3,7 +3,7 @@ package org.koitharu.kotatsu.core.db.migrations
|
||||
import androidx.room.migration.Migration
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
|
||||
object Migration4To5 : Migration(4, 5) {
|
||||
class Migration4To5 : Migration(4, 5) {
|
||||
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("ALTER TABLE favourite_categories ADD COLUMN sort_key INTEGER NOT NULL DEFAULT 0")
|
||||
|
||||
@@ -3,7 +3,7 @@ package org.koitharu.kotatsu.core.db.migrations
|
||||
import androidx.room.migration.Migration
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
|
||||
object Migration5To6 : Migration(5, 6) {
|
||||
class Migration5To6 : Migration(5, 6) {
|
||||
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("CREATE TABLE IF NOT EXISTS track_logs (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, manga_id INTEGER NOT NULL, chapters TEXT NOT NULL, created_at INTEGER NOT NULL, FOREIGN KEY(manga_id) REFERENCES manga(manga_id) ON UPDATE NO ACTION ON DELETE CASCADE)")
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
package org.koitharu.kotatsu.core.github
|
||||
|
||||
import org.koin.dsl.module
|
||||
|
||||
val githubModule
|
||||
get() = module {
|
||||
single {
|
||||
GithubRepository(get())
|
||||
}
|
||||
}
|
||||
@@ -2,14 +2,10 @@ package org.koitharu.kotatsu.core.github
|
||||
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import org.koin.core.component.KoinComponent
|
||||
import org.koin.core.component.inject
|
||||
import org.koitharu.kotatsu.utils.ext.await
|
||||
import org.koitharu.kotatsu.utils.ext.parseJson
|
||||
|
||||
class GithubRepository : KoinComponent {
|
||||
|
||||
private val okHttp by inject<OkHttpClient>()
|
||||
class GithubRepository(private val okHttp: OkHttpClient) {
|
||||
|
||||
suspend fun getLatestVersion(): AppVersion {
|
||||
val request = Request.Builder()
|
||||
|
||||
@@ -2,9 +2,12 @@ package org.koitharu.kotatsu.core.local
|
||||
|
||||
import java.io.File
|
||||
import java.io.FilenameFilter
|
||||
import java.util.*
|
||||
|
||||
class CbzFilter : FilenameFilter {
|
||||
|
||||
override fun accept(dir: File, name: String) =
|
||||
name.endsWith(".cbz", ignoreCase = true) || name.endsWith(".zip", ignoreCase = true)
|
||||
override fun accept(dir: File, name: String): Boolean {
|
||||
val ext = name.substringAfterLast('.', "").toLowerCase(Locale.ROOT)
|
||||
return ext == "cbz" || ext == "zip"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package org.koitharu.kotatsu.core.network
|
||||
|
||||
import okhttp3.CookieJar
|
||||
import okhttp3.OkHttpClient
|
||||
import org.koin.android.ext.koin.androidContext
|
||||
import org.koin.dsl.module
|
||||
import org.koitharu.kotatsu.core.network.cookies.PersistentCookieJar
|
||||
import org.koitharu.kotatsu.core.network.cookies.cache.SetCookieCache
|
||||
import org.koitharu.kotatsu.core.network.cookies.persistence.SharedPrefsCookiePersistor
|
||||
import org.koitharu.kotatsu.core.parser.UserAgentInterceptor
|
||||
import org.koitharu.kotatsu.utils.CacheUtils
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
val networkModule
|
||||
get() = module {
|
||||
single<CookieJar> {
|
||||
PersistentCookieJar(
|
||||
SetCookieCache(),
|
||||
SharedPrefsCookiePersistor(androidContext())
|
||||
)
|
||||
}
|
||||
single {
|
||||
OkHttpClient.Builder().apply {
|
||||
connectTimeout(20, TimeUnit.SECONDS)
|
||||
readTimeout(60, TimeUnit.SECONDS)
|
||||
writeTimeout(20, TimeUnit.SECONDS)
|
||||
cookieJar(get())
|
||||
cache(CacheUtils.createHttpCache(androidContext()))
|
||||
addInterceptor(UserAgentInterceptor())
|
||||
}.build()
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.koitharu.kotatsu.core.local.cookies
|
||||
package org.koitharu.kotatsu.core.network.cookies
|
||||
|
||||
import okhttp3.CookieJar
|
||||
|
||||
@@ -13,12 +13,12 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.koitharu.kotatsu.core.local.cookies
|
||||
package org.koitharu.kotatsu.core.network.cookies
|
||||
|
||||
import okhttp3.Cookie
|
||||
import okhttp3.HttpUrl
|
||||
import org.koitharu.kotatsu.core.local.cookies.cache.CookieCache
|
||||
import org.koitharu.kotatsu.core.local.cookies.persistence.CookiePersistor
|
||||
import org.koitharu.kotatsu.core.network.cookies.cache.CookieCache
|
||||
import org.koitharu.kotatsu.core.network.cookies.persistence.CookiePersistor
|
||||
import java.util.*
|
||||
|
||||
class PersistentCookieJar(
|
||||
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.koitharu.kotatsu.core.local.cookies.cache
|
||||
package org.koitharu.kotatsu.core.network.cookies.cache
|
||||
|
||||
import okhttp3.Cookie
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.koitharu.kotatsu.core.local.cookies.cache
|
||||
package org.koitharu.kotatsu.core.network.cookies.cache
|
||||
|
||||
import okhttp3.Cookie
|
||||
import java.util.*
|
||||
@@ -13,16 +13,17 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.koitharu.kotatsu.core.local.cookies.cache
|
||||
package org.koitharu.kotatsu.core.network.cookies.cache
|
||||
|
||||
import okhttp3.Cookie
|
||||
import org.koitharu.kotatsu.core.local.cookies.cache.IdentifiableCookie.Companion.decorateAll
|
||||
import org.koitharu.kotatsu.core.network.cookies.cache.IdentifiableCookie.Companion.decorateAll
|
||||
import java.util.*
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
|
||||
class SetCookieCache : CookieCache {
|
||||
|
||||
private val cookies: MutableSet<IdentifiableCookie> = Collections.newSetFromMap(ConcurrentHashMap())
|
||||
private val cookies: MutableSet<IdentifiableCookie> =
|
||||
Collections.newSetFromMap(ConcurrentHashMap())
|
||||
|
||||
override fun addAll(newCookies: Collection<Cookie>) {
|
||||
for (cookie in decorateAll(newCookies)) {
|
||||
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.koitharu.kotatsu.core.local.cookies.persistence
|
||||
package org.koitharu.kotatsu.core.network.cookies.persistence
|
||||
|
||||
import okhttp3.Cookie
|
||||
|
||||
@@ -23,6 +23,7 @@ import okhttp3.Cookie
|
||||
interface CookiePersistor {
|
||||
|
||||
fun loadAll(): List<Cookie>
|
||||
|
||||
/**
|
||||
* Persist all cookies, existing cookies will be overwritten.
|
||||
*
|
||||
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.koitharu.kotatsu.core.local.cookies.persistence
|
||||
package org.koitharu.kotatsu.core.network.cookies.persistence
|
||||
|
||||
import android.util.Log
|
||||
import okhttp3.Cookie
|
||||
@@ -49,7 +49,8 @@ class SerializableCookie : Serializable {
|
||||
fun decode(encodedCookie: String): Cookie? {
|
||||
val bytes = hexStringToByteArray(encodedCookie)
|
||||
val byteArrayInputStream = ByteArrayInputStream(
|
||||
bytes)
|
||||
bytes
|
||||
)
|
||||
var cookie: Cookie? = null
|
||||
var objectInputStream: ObjectInputStream? = null
|
||||
try {
|
||||
@@ -107,6 +108,7 @@ class SerializableCookie : Serializable {
|
||||
|
||||
const val serialVersionUID = -8594045714036645534L
|
||||
private const val NON_VALID_EXPIRES_AT = -1L
|
||||
|
||||
/**
|
||||
* Using some super basic byte array <-> hex conversions so we don't
|
||||
* have to rely on any large Base64 libraries. Can be overridden if you
|
||||
@@ -141,7 +143,7 @@ class SerializableCookie : Serializable {
|
||||
var i = 0
|
||||
while (i < len) {
|
||||
data[i / 2] = ((Character.digit(hexString[i], 16) shl 4) + Character
|
||||
.digit(hexString[i + 1], 16)).toByte()
|
||||
.digit(hexString[i + 1], 16)).toByte()
|
||||
i += 2
|
||||
}
|
||||
return data
|
||||
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.koitharu.kotatsu.core.local.cookies.persistence
|
||||
package org.koitharu.kotatsu.core.network.cookies.persistence
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
@@ -25,7 +25,12 @@ import java.util.*
|
||||
class SharedPrefsCookiePersistor(private val sharedPreferences: SharedPreferences) :
|
||||
CookiePersistor {
|
||||
|
||||
constructor(context: Context) : this(context.getSharedPreferences("cookies", Context.MODE_PRIVATE))
|
||||
constructor(context: Context) : this(
|
||||
context.getSharedPreferences(
|
||||
"cookies",
|
||||
Context.MODE_PRIVATE
|
||||
)
|
||||
)
|
||||
|
||||
override fun loadAll(): List<Cookie> {
|
||||
val cookies: MutableList<Cookie> = ArrayList(sharedPreferences.all.size)
|
||||
@@ -0,0 +1,9 @@
|
||||
package org.koitharu.kotatsu.core.parser
|
||||
|
||||
import org.koin.dsl.bind
|
||||
import org.koin.dsl.module
|
||||
|
||||
val parserModule
|
||||
get() = module {
|
||||
single { LocalMangaRepository() } bind MangaRepository::class
|
||||
}
|
||||
@@ -1,13 +1,11 @@
|
||||
package org.koitharu.kotatsu.core.parser
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.os.Build
|
||||
import okhttp3.Interceptor
|
||||
import org.koitharu.kotatsu.BuildConfig
|
||||
import java.util.*
|
||||
|
||||
@SuppressLint("ConstantLocale")
|
||||
object UserAgentInterceptor : Interceptor {
|
||||
class UserAgentInterceptor : Interceptor {
|
||||
|
||||
private val userAgent = "Kotatsu/%s (Android %s; %s; %s %s; %s)".format(
|
||||
BuildConfig.VERSION_NAME,
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
package org.koitharu.kotatsu.domain
|
||||
|
||||
import androidx.room.withTransaction
|
||||
import org.koin.core.component.KoinComponent
|
||||
import org.koin.core.component.inject
|
||||
import org.koitharu.kotatsu.core.db.MangaDatabase
|
||||
import org.koitharu.kotatsu.core.db.entity.MangaEntity
|
||||
import org.koitharu.kotatsu.core.db.entity.MangaPrefsEntity
|
||||
@@ -10,9 +8,7 @@ import org.koitharu.kotatsu.core.db.entity.TagEntity
|
||||
import org.koitharu.kotatsu.core.model.Manga
|
||||
import org.koitharu.kotatsu.core.prefs.ReaderMode
|
||||
|
||||
class MangaDataRepository : KoinComponent {
|
||||
|
||||
private val db: MangaDatabase by inject()
|
||||
class MangaDataRepository(private val db: MangaDatabase) {
|
||||
|
||||
suspend fun savePreferences(manga: Manga, mode: ReaderMode) {
|
||||
val tags = manga.tags.map(TagEntity.Companion::fromMangaTag)
|
||||
|
||||
@@ -34,6 +34,7 @@ object MangaProviderFactory : KoinComponent {
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated("Use DI")
|
||||
fun createLocal(): LocalMangaRepository {
|
||||
var instance = cache[MangaSource.LOCAL]?.get()
|
||||
if (instance == null) {
|
||||
|
||||
@@ -2,13 +2,12 @@ package org.koitharu.kotatsu.domain
|
||||
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.flow
|
||||
import org.koin.core.component.KoinComponent
|
||||
import org.koitharu.kotatsu.core.model.Manga
|
||||
import org.koitharu.kotatsu.core.model.MangaSource
|
||||
import org.koitharu.kotatsu.core.model.SortOrder
|
||||
import java.util.*
|
||||
|
||||
class MangaSearchRepository : KoinComponent {
|
||||
class MangaSearchRepository {
|
||||
|
||||
fun globalSearch(query: String, batchSize: Int = 4): Flow<List<Manga>> = flow {
|
||||
val sources = MangaProviderFactory.getSources(false)
|
||||
|
||||
@@ -4,8 +4,6 @@ import androidx.collection.ArraySet
|
||||
import androidx.room.withTransaction
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.koin.core.component.KoinComponent
|
||||
import org.koin.core.component.inject
|
||||
import org.koitharu.kotatsu.core.db.MangaDatabase
|
||||
import org.koitharu.kotatsu.core.db.entity.FavouriteCategoryEntity
|
||||
import org.koitharu.kotatsu.core.db.entity.FavouriteEntity
|
||||
@@ -14,9 +12,7 @@ import org.koitharu.kotatsu.core.db.entity.TagEntity
|
||||
import org.koitharu.kotatsu.core.model.FavouriteCategory
|
||||
import org.koitharu.kotatsu.core.model.Manga
|
||||
|
||||
class FavouritesRepository : KoinComponent {
|
||||
|
||||
private val db: MangaDatabase by inject()
|
||||
class FavouritesRepository(private val db: MangaDatabase) {
|
||||
|
||||
suspend fun getAllManga(): List<Manga> {
|
||||
val entities = db.favouritesDao.findAll()
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package org.koitharu.kotatsu.domain.favourites
|
||||
|
||||
interface OnFavouritesChangeListener {
|
||||
fun interface OnFavouritesChangeListener {
|
||||
|
||||
fun onFavouritesChanged(mangaId: Long)
|
||||
|
||||
fun onCategoriesChanged()
|
||||
fun onCategoriesChanged() = Unit
|
||||
}
|
||||
@@ -14,10 +14,9 @@ import org.koitharu.kotatsu.core.model.Manga
|
||||
import org.koitharu.kotatsu.core.model.MangaHistory
|
||||
import org.koitharu.kotatsu.domain.tracking.TrackingRepository
|
||||
|
||||
class HistoryRepository : KoinComponent {
|
||||
class HistoryRepository(private val db: MangaDatabase) : KoinComponent {
|
||||
|
||||
private val db: MangaDatabase by inject()
|
||||
private val trackingRepository by lazy(::TrackingRepository)
|
||||
private val trackingRepository by inject<TrackingRepository>()
|
||||
|
||||
suspend fun getList(offset: Int, limit: Int = 20): List<Manga> {
|
||||
val entities = db.historyDao.findAll(offset, limit)
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
package org.koitharu.kotatsu.domain.tracking
|
||||
|
||||
import androidx.room.withTransaction
|
||||
import org.koin.core.component.KoinComponent
|
||||
import org.koin.core.component.inject
|
||||
import org.koitharu.kotatsu.core.db.MangaDatabase
|
||||
import org.koitharu.kotatsu.core.db.entity.TrackEntity
|
||||
import org.koitharu.kotatsu.core.db.entity.TrackLogEntity
|
||||
@@ -10,9 +8,7 @@ import org.koitharu.kotatsu.core.model.*
|
||||
import org.koitharu.kotatsu.domain.MangaProviderFactory
|
||||
import java.util.*
|
||||
|
||||
class TrackingRepository : KoinComponent {
|
||||
|
||||
private val db: MangaDatabase by inject()
|
||||
class TrackingRepository(private val db: MangaDatabase) {
|
||||
|
||||
suspend fun getNewChaptersCount(mangaId: Long): Int {
|
||||
val entity = db.tracksDao.find(mangaId) ?: return 0
|
||||
|
||||
@@ -1,14 +1,17 @@
|
||||
package org.koitharu.kotatsu.ui.common
|
||||
package org.koitharu.kotatsu.ui.base
|
||||
|
||||
import android.app.Dialog
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.annotation.CallSuper
|
||||
import androidx.annotation.LayoutRes
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import moxy.MvpAppCompatDialogFragment
|
||||
|
||||
abstract class AlertDialogFragment(@LayoutRes private val layoutResId: Int) : MvpAppCompatDialogFragment() {
|
||||
abstract class AlertDialogFragment(
|
||||
@LayoutRes private val layoutResId: Int
|
||||
) : MvpAppCompatDialogFragment() {
|
||||
|
||||
private var rootView: View? = null
|
||||
|
||||
@@ -24,12 +27,13 @@ abstract class AlertDialogFragment(@LayoutRes private val layoutResId: Int) : Mv
|
||||
.create()
|
||||
}
|
||||
|
||||
@CallSuper
|
||||
override fun onDestroyView() {
|
||||
rootView = null
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
||||
override fun getView(): View? {
|
||||
final override fun getView(): View? {
|
||||
return rootView
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.koitharu.kotatsu.ui.common
|
||||
package org.koitharu.kotatsu.ui.base
|
||||
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.koitharu.kotatsu.ui.common
|
||||
package org.koitharu.kotatsu.ui.base
|
||||
|
||||
import android.app.Dialog
|
||||
import android.os.Bundle
|
||||
@@ -13,7 +13,7 @@ import org.koitharu.kotatsu.utils.UiUtils
|
||||
abstract class BaseBottomSheet(@LayoutRes private val layoutResId: Int) :
|
||||
MvpBottomSheetDialogFragment() {
|
||||
|
||||
override fun onCreateView(
|
||||
final override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
@@ -1,14 +1,19 @@
|
||||
package org.koitharu.kotatsu.ui.common
|
||||
package org.koitharu.kotatsu.ui.base
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Parcelable
|
||||
import androidx.annotation.LayoutRes
|
||||
import coil.ImageLoader
|
||||
import moxy.MvpAppCompatFragment
|
||||
import org.koin.android.ext.android.inject
|
||||
import org.koitharu.kotatsu.utils.delegates.ParcelableArgumentDelegate
|
||||
import org.koitharu.kotatsu.utils.delegates.StringArgumentDelegate
|
||||
|
||||
abstract class BaseFragment(@LayoutRes contentLayoutId: Int) :
|
||||
MvpAppCompatFragment(contentLayoutId) {
|
||||
abstract class BaseFragment(
|
||||
@LayoutRes contentLayoutId: Int
|
||||
) : MvpAppCompatFragment(contentLayoutId) {
|
||||
|
||||
protected val coil by inject<ImageLoader>()
|
||||
|
||||
fun stringArg(name: String) = StringArgumentDelegate(name)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.koitharu.kotatsu.ui.common
|
||||
package org.koitharu.kotatsu.ui.base
|
||||
|
||||
import android.graphics.Color
|
||||
import android.os.Build
|
||||
@@ -12,11 +12,11 @@ abstract class BaseFullscreenActivity : BaseActivity() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
with(window) {
|
||||
// addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
|
||||
statusBarColor = Color.TRANSPARENT
|
||||
navigationBarColor = Color.TRANSPARENT
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
||||
attributes.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
|
||||
attributes.layoutInDisplayCutoutMode =
|
||||
WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
|
||||
}
|
||||
}
|
||||
showSystemUI()
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.koitharu.kotatsu.ui.common
|
||||
package org.koitharu.kotatsu.ui.base
|
||||
|
||||
import moxy.MvpView
|
||||
import moxy.viewstate.strategy.alias.AddToEndSingle
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.koitharu.kotatsu.ui.common
|
||||
package org.koitharu.kotatsu.ui.base
|
||||
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.preference.Preference
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.koitharu.kotatsu.ui.common
|
||||
package org.koitharu.kotatsu.ui.base
|
||||
|
||||
import kotlinx.coroutines.*
|
||||
import moxy.MvpPresenter
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.koitharu.kotatsu.ui.common
|
||||
package org.koitharu.kotatsu.ui.base
|
||||
|
||||
import android.app.Service
|
||||
import android.content.Intent
|
||||
@@ -7,18 +7,16 @@ import androidx.annotation.CallSuper
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.SupervisorJob
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
import kotlinx.coroutines.cancel
|
||||
|
||||
abstract class BaseService : Service(), CoroutineScope {
|
||||
abstract class BaseService : Service() {
|
||||
|
||||
private val job = SupervisorJob()
|
||||
|
||||
final override val coroutineContext: CoroutineContext
|
||||
get() = Dispatchers.Main.immediate + job
|
||||
@Suppress("MemberVisibilityCanBePrivate")
|
||||
val serviceScope = CoroutineScope(SupervisorJob() + Dispatchers.Main.immediate)
|
||||
|
||||
@CallSuper
|
||||
override fun onDestroy() {
|
||||
job.cancel()
|
||||
serviceScope.cancel()
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.koitharu.kotatsu.ui.common
|
||||
package org.koitharu.kotatsu.ui.base
|
||||
|
||||
import android.content.Context
|
||||
import android.view.View
|
||||
@@ -8,8 +8,10 @@ import org.koitharu.kotatsu.utils.ext.getThemeColor
|
||||
|
||||
class ChipsFactory(val context: Context) {
|
||||
|
||||
fun create(convertView: Chip? = null, text: CharSequence, @DrawableRes iconRes: Int = 0,
|
||||
tag: Any? = null, onClickListener: View.OnClickListener? = null): Chip {
|
||||
fun create(
|
||||
convertView: Chip? = null, text: CharSequence, @DrawableRes iconRes: Int = 0,
|
||||
tag: Any? = null, onClickListener: View.OnClickListener? = null
|
||||
): Chip {
|
||||
val chip = convertView ?: Chip(context).apply {
|
||||
setTextColor(context.getThemeColor(android.R.attr.textColorPrimary))
|
||||
isCloseIconVisible = false
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.koitharu.kotatsu.ui.common
|
||||
package org.koitharu.kotatsu.ui.base
|
||||
|
||||
import android.util.ArrayMap
|
||||
import moxy.MvpPresenter
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.koitharu.kotatsu.ui.common.dialog
|
||||
package org.koitharu.kotatsu.ui.base.dialog
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.koitharu.kotatsu.ui.common.dialog
|
||||
package org.koitharu.kotatsu.ui.base.dialog
|
||||
|
||||
import android.content.Context
|
||||
import android.content.DialogInterface
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.koitharu.kotatsu.ui.common.dialog
|
||||
package org.koitharu.kotatsu.ui.base.dialog
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
@@ -11,15 +11,17 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import kotlinx.android.synthetic.main.dialog_input.view.*
|
||||
import org.koitharu.kotatsu.R
|
||||
|
||||
class TextInputDialog private constructor(private val delegate: AlertDialog) :
|
||||
DialogInterface by delegate {
|
||||
class TextInputDialog private constructor(
|
||||
private val delegate: AlertDialog
|
||||
) : DialogInterface by delegate {
|
||||
|
||||
fun show() = delegate.show()
|
||||
|
||||
class Builder(context: Context) {
|
||||
|
||||
@SuppressLint("InflateParams")
|
||||
private val view = LayoutInflater.from(context).inflate(R.layout.dialog_input, null, false)
|
||||
private val view = LayoutInflater.from(context)
|
||||
.inflate(R.layout.dialog_input, null, false)
|
||||
|
||||
private val delegate = MaterialAlertDialogBuilder(context)
|
||||
.setView(view)
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.koitharu.kotatsu.ui.common.list
|
||||
package org.koitharu.kotatsu.ui.base.list
|
||||
|
||||
import androidx.recyclerview.widget.DiffUtil
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
@@ -1,8 +1,7 @@
|
||||
package org.koitharu.kotatsu.ui.common.list
|
||||
package org.koitharu.kotatsu.ui.base.list
|
||||
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import okhttp3.internal.toImmutableList
|
||||
import org.koin.core.component.KoinComponent
|
||||
import org.koitharu.kotatsu.utils.ext.replaceWith
|
||||
|
||||
@@ -12,7 +11,7 @@ abstract class BaseRecyclerAdapter<T, E>(private val onItemClickListener: OnRecy
|
||||
|
||||
protected val dataSet = ArrayList<T>() //TODO make private
|
||||
|
||||
val items get() = dataSet.toImmutableList()
|
||||
val items get() = dataSet as List<T>
|
||||
|
||||
val hasItems get() = dataSet.isNotEmpty()
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.koitharu.kotatsu.ui.common.list
|
||||
package org.koitharu.kotatsu.ui.base.list
|
||||
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.koitharu.kotatsu.ui.common.list
|
||||
package org.koitharu.kotatsu.ui.base.list
|
||||
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.koitharu.kotatsu.ui.common.list
|
||||
package org.koitharu.kotatsu.ui.base.list
|
||||
|
||||
import android.view.View
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.koitharu.kotatsu.ui.common.list
|
||||
package org.koitharu.kotatsu.ui.base.list
|
||||
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.koitharu.kotatsu.ui.common.list
|
||||
package org.koitharu.kotatsu.ui.base.list
|
||||
|
||||
import android.view.ViewGroup
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.koitharu.kotatsu.ui.common.list
|
||||
package org.koitharu.kotatsu.ui.base.list
|
||||
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.koitharu.kotatsu.ui.common.list.decor
|
||||
package org.koitharu.kotatsu.ui.base.list.decor
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Canvas
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.koitharu.kotatsu.ui.common.list.decor
|
||||
package org.koitharu.kotatsu.ui.base.list.decor
|
||||
|
||||
import android.graphics.Canvas
|
||||
import android.graphics.Rect
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.koitharu.kotatsu.ui.common.list.decor
|
||||
package org.koitharu.kotatsu.ui.base.list.decor
|
||||
|
||||
import android.graphics.Rect
|
||||
import android.view.View
|
||||
21
app/src/main/java/org/koitharu/kotatsu/ui/base/uiModule.kt
Normal file
21
app/src/main/java/org/koitharu/kotatsu/ui/base/uiModule.kt
Normal file
@@ -0,0 +1,21 @@
|
||||
package org.koitharu.kotatsu.ui.base
|
||||
|
||||
import coil.ComponentRegistry
|
||||
import coil.ImageLoader
|
||||
import okhttp3.OkHttpClient
|
||||
import org.koin.android.ext.koin.androidContext
|
||||
import org.koin.dsl.module
|
||||
import org.koitharu.kotatsu.core.local.CbzFetcher
|
||||
|
||||
val uiModule
|
||||
get() = module {
|
||||
single {
|
||||
ImageLoader.Builder(androidContext())
|
||||
.okHttpClient(get<OkHttpClient>())
|
||||
.componentRegistry(
|
||||
ComponentRegistry.Builder()
|
||||
.add(CbzFetcher())
|
||||
.build()
|
||||
).build()
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.koitharu.kotatsu.ui.common.widgets
|
||||
package org.koitharu.kotatsu.ui.base.widgets
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
@@ -61,7 +61,6 @@ class CheckableImageView @JvmOverloads constructor(
|
||||
|
||||
private companion object {
|
||||
|
||||
@JvmStatic
|
||||
private val CHECKED_STATE_SET = intArrayOf(android.R.attr.state_checked)
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
package org.koitharu.kotatsu.ui.common.widgets
|
||||
package org.koitharu.kotatsu.ui.base.widgets
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.widget.LinearLayout
|
||||
import androidx.appcompat.widget.AppCompatImageView
|
||||
import androidx.core.content.res.use
|
||||
import androidx.core.content.withStyledAttributes
|
||||
import org.koitharu.kotatsu.R
|
||||
|
||||
|
||||
@@ -15,10 +15,9 @@ class CoverImageView @JvmOverloads constructor(
|
||||
private var orientation: Int = HORIZONTAL
|
||||
|
||||
init {
|
||||
context.theme.obtainStyledAttributes(attrs, R.styleable.CoverImageView, defStyleAttr, 0)
|
||||
.use {
|
||||
orientation = it.getInt(R.styleable.CoverImageView_android_orientation, HORIZONTAL)
|
||||
}
|
||||
context.withStyledAttributes(attrs, R.styleable.CoverImageView, defStyleAttr) {
|
||||
orientation = getInt(R.styleable.CoverImageView_android_orientation, HORIZONTAL)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.koitharu.kotatsu.ui.common.widgets
|
||||
package org.koitharu.kotatsu.ui.base.widgets
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
@@ -11,7 +11,7 @@ import android.view.MenuItem
|
||||
import androidx.core.view.isVisible
|
||||
import kotlinx.android.synthetic.main.activity_browser.*
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.ui.common.BaseActivity
|
||||
import org.koitharu.kotatsu.ui.base.BaseActivity
|
||||
|
||||
@SuppressLint("SetJavaScriptEnabled")
|
||||
class BrowserActivity : BaseActivity(), BrowserCallback {
|
||||
|
||||
@@ -7,7 +7,7 @@ import kotlinx.android.synthetic.main.item_chapter.*
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.core.model.MangaChapter
|
||||
import org.koitharu.kotatsu.domain.history.ChapterExtra
|
||||
import org.koitharu.kotatsu.ui.common.list.BaseViewHolder
|
||||
import org.koitharu.kotatsu.ui.base.list.BaseViewHolder
|
||||
import org.koitharu.kotatsu.utils.ext.getThemeColor
|
||||
|
||||
class ChapterHolder(parent: ViewGroup) :
|
||||
|
||||
@@ -4,8 +4,8 @@ import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import org.koitharu.kotatsu.core.model.MangaChapter
|
||||
import org.koitharu.kotatsu.domain.history.ChapterExtra
|
||||
import org.koitharu.kotatsu.ui.common.list.BaseRecyclerAdapter
|
||||
import org.koitharu.kotatsu.ui.common.list.OnRecyclerItemClickListener
|
||||
import org.koitharu.kotatsu.ui.base.list.BaseRecyclerAdapter
|
||||
import org.koitharu.kotatsu.ui.base.list.OnRecyclerItemClickListener
|
||||
|
||||
class ChaptersAdapter(onItemClickListener: OnRecyclerItemClickListener<MangaChapter>) :
|
||||
BaseRecyclerAdapter<MangaChapter, ChapterExtra>(onItemClickListener) {
|
||||
|
||||
@@ -15,8 +15,8 @@ import kotlinx.android.synthetic.main.fragment_chapters.*
|
||||
import moxy.ktx.moxyPresenter
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.core.model.*
|
||||
import org.koitharu.kotatsu.ui.common.BaseFragment
|
||||
import org.koitharu.kotatsu.ui.common.list.OnRecyclerItemClickListener
|
||||
import org.koitharu.kotatsu.ui.base.BaseFragment
|
||||
import org.koitharu.kotatsu.ui.base.list.OnRecyclerItemClickListener
|
||||
import org.koitharu.kotatsu.ui.download.DownloadService
|
||||
import org.koitharu.kotatsu.ui.reader.ReaderActivity
|
||||
import org.koitharu.kotatsu.utils.ext.resolveDp
|
||||
|
||||
@@ -26,8 +26,8 @@ import org.koitharu.kotatsu.core.model.FavouriteCategory
|
||||
import org.koitharu.kotatsu.core.model.Manga
|
||||
import org.koitharu.kotatsu.core.model.MangaHistory
|
||||
import org.koitharu.kotatsu.core.model.MangaSource
|
||||
import org.koitharu.kotatsu.ui.base.BaseActivity
|
||||
import org.koitharu.kotatsu.ui.browser.BrowserActivity
|
||||
import org.koitharu.kotatsu.ui.common.BaseActivity
|
||||
import org.koitharu.kotatsu.ui.download.DownloadService
|
||||
import org.koitharu.kotatsu.utils.MangaShortcut
|
||||
import org.koitharu.kotatsu.utils.ShareHelper
|
||||
|
||||
@@ -6,7 +6,6 @@ import androidx.core.net.toUri
|
||||
import androidx.core.text.parseAsHtml
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import coil.load
|
||||
import com.google.android.material.chip.Chip
|
||||
import kotlinx.android.synthetic.main.fragment_details.*
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
@@ -17,15 +16,12 @@ import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.core.model.FavouriteCategory
|
||||
import org.koitharu.kotatsu.core.model.Manga
|
||||
import org.koitharu.kotatsu.core.model.MangaHistory
|
||||
import org.koitharu.kotatsu.ui.common.BaseFragment
|
||||
import org.koitharu.kotatsu.ui.base.BaseFragment
|
||||
import org.koitharu.kotatsu.ui.list.favourites.categories.select.FavouriteCategoriesDialog
|
||||
import org.koitharu.kotatsu.ui.reader.ReaderActivity
|
||||
import org.koitharu.kotatsu.ui.search.MangaSearchSheet
|
||||
import org.koitharu.kotatsu.utils.FileSizeUtils
|
||||
import org.koitharu.kotatsu.utils.ext.addChips
|
||||
import org.koitharu.kotatsu.utils.ext.showPopupMenu
|
||||
import org.koitharu.kotatsu.utils.ext.textAndVisible
|
||||
import org.koitharu.kotatsu.utils.ext.toFileOrNull
|
||||
import org.koitharu.kotatsu.utils.ext.*
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
class MangaDetailsFragment : BaseFragment(R.layout.fragment_details), MangaDetailsView,
|
||||
@@ -42,11 +38,11 @@ class MangaDetailsFragment : BaseFragment(R.layout.fragment_details), MangaDetai
|
||||
|
||||
override fun onMangaUpdated(manga: Manga) {
|
||||
this.manga = manga
|
||||
imageView_cover.load(manga.largeCoverUrl ?: manga.coverUrl) {
|
||||
fallback(R.drawable.ic_placeholder)
|
||||
crossfade(true)
|
||||
lifecycle(this@MangaDetailsFragment)
|
||||
}
|
||||
imageView_cover.newImageRequest(manga.largeCoverUrl ?: manga.coverUrl)
|
||||
.fallback(R.drawable.ic_placeholder)
|
||||
.crossfade(true)
|
||||
.lifecycle(this)
|
||||
.enqueueWith(coil)
|
||||
textView_title.text = manga.title
|
||||
textView_subtitle.textAndVisible = manga.altTitle
|
||||
textView_description.text = manga.description?.parseAsHtml()?.takeUnless(Spanned::isBlank)
|
||||
@@ -138,9 +134,11 @@ class MangaDetailsFragment : BaseFragment(R.layout.fragment_details), MangaDetai
|
||||
}
|
||||
v is Chip -> {
|
||||
when (val tag = v.tag) {
|
||||
is String -> MangaSearchSheet.show(activity?.supportFragmentManager
|
||||
?: childFragmentManager,
|
||||
manga?.source ?: return, tag)
|
||||
is String -> MangaSearchSheet.show(
|
||||
activity?.supportFragmentManager
|
||||
?: childFragmentManager,
|
||||
manga?.source ?: return, tag
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import moxy.InjectViewState
|
||||
import moxy.presenterScope
|
||||
import org.koin.core.component.inject
|
||||
import org.koitharu.kotatsu.BuildConfig
|
||||
import org.koitharu.kotatsu.core.exceptions.MangaNotFoundException
|
||||
import org.koitharu.kotatsu.core.model.Manga
|
||||
@@ -20,8 +21,8 @@ import org.koitharu.kotatsu.domain.favourites.OnFavouritesChangeListener
|
||||
import org.koitharu.kotatsu.domain.history.HistoryRepository
|
||||
import org.koitharu.kotatsu.domain.history.OnHistoryChangeListener
|
||||
import org.koitharu.kotatsu.domain.tracking.TrackingRepository
|
||||
import org.koitharu.kotatsu.ui.common.BasePresenter
|
||||
import org.koitharu.kotatsu.ui.common.SharedPresenterHolder
|
||||
import org.koitharu.kotatsu.ui.base.BasePresenter
|
||||
import org.koitharu.kotatsu.ui.base.SharedPresenterHolder
|
||||
import org.koitharu.kotatsu.utils.ext.safe
|
||||
import java.io.IOException
|
||||
|
||||
@@ -29,18 +30,15 @@ import java.io.IOException
|
||||
class MangaDetailsPresenter private constructor(private val key: Int) :
|
||||
BasePresenter<MangaDetailsView>(), OnHistoryChangeListener, OnFavouritesChangeListener {
|
||||
|
||||
private lateinit var historyRepository: HistoryRepository
|
||||
private lateinit var favouritesRepository: FavouritesRepository
|
||||
private lateinit var trackingRepository: TrackingRepository
|
||||
private lateinit var searchRepository: MangaSearchRepository
|
||||
private val historyRepository by inject<HistoryRepository>()
|
||||
private val favouritesRepository by inject<FavouritesRepository>()
|
||||
private val trackingRepository by inject<TrackingRepository>()
|
||||
private val searchRepository by inject<MangaSearchRepository>()
|
||||
private val mangaDataRepository by inject<MangaDataRepository>()
|
||||
|
||||
private var manga: Manga? = null
|
||||
|
||||
override fun onFirstViewAttach() {
|
||||
historyRepository = HistoryRepository()
|
||||
favouritesRepository = FavouritesRepository()
|
||||
trackingRepository = TrackingRepository()
|
||||
searchRepository = MangaSearchRepository()
|
||||
super.onFirstViewAttach()
|
||||
HistoryRepository.subscribe(this)
|
||||
FavouritesRepository.subscribe(this)
|
||||
@@ -51,7 +49,7 @@ class MangaDetailsPresenter private constructor(private val key: Int) :
|
||||
viewState.onLoadingStateChanged(true)
|
||||
try {
|
||||
val manga = withContext(Dispatchers.IO) {
|
||||
MangaDataRepository().findMangaById(id)
|
||||
mangaDataRepository.findMangaById(id)
|
||||
} ?: throw MangaNotFoundException("Cannot find manga by id")
|
||||
viewState.onMangaUpdated(manga)
|
||||
loadDetails(manga, true)
|
||||
@@ -105,7 +103,7 @@ class MangaDetailsPresenter private constructor(private val key: Int) :
|
||||
val original = repository.getRemoteManga(manga)
|
||||
repository.delete(manga) || throw IOException("Unable to delete file")
|
||||
safe {
|
||||
HistoryRepository().deleteOrSwap(manga, original)
|
||||
historyRepository.deleteOrSwap(manga, original)
|
||||
}
|
||||
}
|
||||
viewState.onMangaRemoved(manga)
|
||||
@@ -193,8 +191,6 @@ class MangaDetailsPresenter private constructor(private val key: Int) :
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCategoriesChanged() = Unit
|
||||
|
||||
override fun onDestroy() {
|
||||
HistoryRepository.unsubscribe(this)
|
||||
FavouritesRepository.unsubscribe(this)
|
||||
|
||||
@@ -8,7 +8,7 @@ import moxy.viewstate.strategy.alias.SingleState
|
||||
import org.koitharu.kotatsu.core.model.FavouriteCategory
|
||||
import org.koitharu.kotatsu.core.model.Manga
|
||||
import org.koitharu.kotatsu.core.model.MangaHistory
|
||||
import org.koitharu.kotatsu.ui.common.BaseMvpView
|
||||
import org.koitharu.kotatsu.ui.base.BaseMvpView
|
||||
|
||||
interface MangaDetailsView : BaseMvpView {
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import android.os.PowerManager
|
||||
import android.webkit.MimeTypeMap
|
||||
import android.widget.Toast
|
||||
import androidx.core.content.ContextCompat
|
||||
import coil.Coil
|
||||
import coil.ImageLoader
|
||||
import coil.request.ImageRequest
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
@@ -22,8 +22,8 @@ import org.koitharu.kotatsu.core.model.Manga
|
||||
import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||
import org.koitharu.kotatsu.domain.MangaProviderFactory
|
||||
import org.koitharu.kotatsu.domain.local.MangaZip
|
||||
import org.koitharu.kotatsu.ui.common.BaseService
|
||||
import org.koitharu.kotatsu.ui.common.dialog.CheckBoxAlertDialog
|
||||
import org.koitharu.kotatsu.ui.base.BaseService
|
||||
import org.koitharu.kotatsu.ui.base.dialog.CheckBoxAlertDialog
|
||||
import org.koitharu.kotatsu.utils.CacheUtils
|
||||
import org.koitharu.kotatsu.utils.ext.*
|
||||
import java.io.File
|
||||
@@ -40,6 +40,7 @@ class DownloadService : BaseService() {
|
||||
private val okHttp by inject<OkHttpClient>()
|
||||
private val cache by inject<PagesCache>()
|
||||
private val settings by inject<AppSettings>()
|
||||
private val imageLoader by inject<ImageLoader>()
|
||||
private val jobs = HashMap<Int, Job>()
|
||||
private val mutex = Mutex()
|
||||
|
||||
@@ -74,7 +75,7 @@ class DownloadService : BaseService() {
|
||||
}
|
||||
|
||||
private fun downloadManga(manga: Manga, chaptersIds: Set<Long>?, startId: Int): Job {
|
||||
return launch(Dispatchers.Default) {
|
||||
return serviceScope.launch(Dispatchers.Default) {
|
||||
mutex.lock()
|
||||
wakeLock.acquire(TimeUnit.HOURS.toMillis(1))
|
||||
notification.fillFrom(manga)
|
||||
@@ -88,7 +89,7 @@ class DownloadService : BaseService() {
|
||||
try {
|
||||
val repo = MangaProviderFactory.create(manga.source)
|
||||
val cover = safe {
|
||||
Coil.execute(
|
||||
imageLoader.execute(
|
||||
ImageRequest.Builder(this@DownloadService)
|
||||
.data(manga.coverUrl)
|
||||
.build()
|
||||
|
||||
@@ -9,7 +9,7 @@ import org.koin.android.ext.android.inject
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||
import org.koitharu.kotatsu.core.prefs.ListMode
|
||||
import org.koitharu.kotatsu.ui.common.AlertDialogFragment
|
||||
import org.koitharu.kotatsu.ui.base.AlertDialogFragment
|
||||
|
||||
class ListModeSelectDialog : AlertDialogFragment(R.layout.dialog_list_mode), View.OnClickListener {
|
||||
|
||||
@@ -56,7 +56,8 @@ class ListModeSelectDialog : AlertDialogFragment(R.layout.dialog_list_mode), Vie
|
||||
private const val TAG = "ListModeSelectDialog"
|
||||
|
||||
fun show(fm: FragmentManager) = ListModeSelectDialog()
|
||||
.show(fm,
|
||||
.show(
|
||||
fm,
|
||||
TAG
|
||||
)
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ import org.koitharu.kotatsu.core.model.MangaSource
|
||||
import org.koitharu.kotatsu.core.prefs.AppSection
|
||||
import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||
import org.koitharu.kotatsu.domain.MangaProviderFactory
|
||||
import org.koitharu.kotatsu.ui.common.BaseActivity
|
||||
import org.koitharu.kotatsu.ui.base.BaseActivity
|
||||
import org.koitharu.kotatsu.ui.list.favourites.FavouritesContainerFragment
|
||||
import org.koitharu.kotatsu.ui.list.feed.FeedFragment
|
||||
import org.koitharu.kotatsu.ui.list.history.HistoryListFragment
|
||||
|
||||
@@ -1,18 +1,20 @@
|
||||
package org.koitharu.kotatsu.ui.list
|
||||
|
||||
import moxy.InjectViewState
|
||||
import org.koin.core.component.inject
|
||||
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.base.BasePresenter
|
||||
import org.koitharu.kotatsu.ui.reader.ReaderState
|
||||
|
||||
@InjectViewState
|
||||
class MainPresenter : BasePresenter<MainView>() {
|
||||
|
||||
private val historyRepository by inject<HistoryRepository>()
|
||||
|
||||
fun openLastReader() {
|
||||
launchLoadingJob {
|
||||
val historyRepository = HistoryRepository()
|
||||
val manga = historyRepository.getList(0, 1).firstOrNull()
|
||||
?: throw EmptyHistoryException()
|
||||
val history = historyRepository.getOne(manga) ?: throw EmptyHistoryException()
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package org.koitharu.kotatsu.ui.list
|
||||
|
||||
import moxy.viewstate.strategy.alias.OneExecution
|
||||
import org.koitharu.kotatsu.ui.common.BaseMvpView
|
||||
import org.koitharu.kotatsu.ui.base.BaseMvpView
|
||||
import org.koitharu.kotatsu.ui.reader.ReaderState
|
||||
|
||||
interface MainView : BaseMvpView {
|
||||
|
||||
@@ -1,27 +1,35 @@
|
||||
package org.koitharu.kotatsu.ui.list
|
||||
|
||||
import android.view.ViewGroup
|
||||
import coil.clear
|
||||
import coil.load
|
||||
import coil.ImageLoader
|
||||
import coil.request.Disposable
|
||||
import kotlinx.android.synthetic.main.item_manga_grid.*
|
||||
import org.koin.core.component.inject
|
||||
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.list.BaseViewHolder
|
||||
import org.koitharu.kotatsu.ui.base.list.BaseViewHolder
|
||||
import org.koitharu.kotatsu.utils.ext.enqueueWith
|
||||
import org.koitharu.kotatsu.utils.ext.newImageRequest
|
||||
|
||||
class MangaGridHolder(parent: ViewGroup) : BaseViewHolder<Manga, MangaHistory?>(parent, R.layout.item_manga_grid) {
|
||||
class MangaGridHolder(parent: ViewGroup) :
|
||||
BaseViewHolder<Manga, MangaHistory?>(parent, R.layout.item_manga_grid) {
|
||||
|
||||
private val coil by inject<ImageLoader>()
|
||||
private var imageRequest: Disposable? = null
|
||||
|
||||
override fun onBind(data: Manga, extra: MangaHistory?) {
|
||||
imageView_cover.clear()
|
||||
textView_title.text = data.title
|
||||
imageView_cover.load(data.coverUrl) {
|
||||
placeholder(R.drawable.ic_placeholder)
|
||||
fallback(R.drawable.ic_placeholder)
|
||||
error(R.drawable.ic_placeholder)
|
||||
}
|
||||
imageRequest?.dispose()
|
||||
imageRequest = imageView_cover.newImageRequest(data.coverUrl)
|
||||
.placeholder(R.drawable.ic_placeholder)
|
||||
.fallback(R.drawable.ic_placeholder)
|
||||
.error(R.drawable.ic_placeholder)
|
||||
.enqueueWith(coil)
|
||||
}
|
||||
|
||||
override fun onRecycled() {
|
||||
imageView_cover.clear()
|
||||
imageRequest?.dispose()
|
||||
imageView_cover.setImageDrawable(null)
|
||||
}
|
||||
}
|
||||
@@ -4,15 +4,15 @@ import android.view.ViewGroup
|
||||
import org.koitharu.kotatsu.core.model.Manga
|
||||
import org.koitharu.kotatsu.core.model.MangaHistory
|
||||
import org.koitharu.kotatsu.core.prefs.ListMode
|
||||
import org.koitharu.kotatsu.ui.common.list.BaseRecyclerAdapter
|
||||
import org.koitharu.kotatsu.ui.common.list.OnRecyclerItemClickListener
|
||||
import org.koitharu.kotatsu.ui.base.list.BaseRecyclerAdapter
|
||||
import org.koitharu.kotatsu.ui.base.list.OnRecyclerItemClickListener
|
||||
|
||||
class MangaListAdapter(onItemClickListener: OnRecyclerItemClickListener<Manga>) :
|
||||
BaseRecyclerAdapter<Manga, MangaHistory?>(onItemClickListener) {
|
||||
|
||||
var listMode: ListMode = ListMode.LIST
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup) = when(listMode) {
|
||||
override fun onCreateViewHolder(parent: ViewGroup) = when (listMode) {
|
||||
ListMode.LIST -> MangaListHolder(parent)
|
||||
ListMode.DETAILED_LIST -> MangaListDetailsHolder(
|
||||
parent
|
||||
|
||||
@@ -3,29 +3,37 @@ package org.koitharu.kotatsu.ui.list
|
||||
import android.annotation.SuppressLint
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.view.isVisible
|
||||
import coil.clear
|
||||
import coil.load
|
||||
import coil.ImageLoader
|
||||
import coil.request.Disposable
|
||||
import kotlinx.android.synthetic.main.item_manga_list_details.*
|
||||
import org.koin.core.component.inject
|
||||
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.list.BaseViewHolder
|
||||
import org.koitharu.kotatsu.ui.base.list.BaseViewHolder
|
||||
import org.koitharu.kotatsu.utils.ext.enqueueWith
|
||||
import org.koitharu.kotatsu.utils.ext.newImageRequest
|
||||
import org.koitharu.kotatsu.utils.ext.textAndVisible
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
class MangaListDetailsHolder(parent: ViewGroup) : BaseViewHolder<Manga, MangaHistory?>(parent, R.layout.item_manga_list_details) {
|
||||
class MangaListDetailsHolder(
|
||||
parent: ViewGroup
|
||||
) : BaseViewHolder<Manga, MangaHistory?>(parent, R.layout.item_manga_list_details) {
|
||||
|
||||
private val coil by inject<ImageLoader>()
|
||||
private var imageRequest: Disposable? = null
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
override fun onBind(data: Manga, extra: MangaHistory?) {
|
||||
imageView_cover.clear()
|
||||
imageRequest?.dispose()
|
||||
textView_title.text = data.title
|
||||
textView_subtitle.textAndVisible = data.altTitle
|
||||
imageView_cover.load(data.coverUrl) {
|
||||
placeholder(R.drawable.ic_placeholder)
|
||||
fallback(R.drawable.ic_placeholder)
|
||||
error(R.drawable.ic_placeholder)
|
||||
}
|
||||
if(data.rating == Manga.NO_RATING) {
|
||||
imageView_cover.newImageRequest(data.coverUrl)
|
||||
.placeholder(R.drawable.ic_placeholder)
|
||||
.fallback(R.drawable.ic_placeholder)
|
||||
.error(R.drawable.ic_placeholder)
|
||||
.enqueueWith(coil)
|
||||
if (data.rating == Manga.NO_RATING) {
|
||||
textView_rating.isVisible = false
|
||||
} else {
|
||||
textView_rating.text = "${(data.rating * 10).roundToInt()}/10"
|
||||
@@ -37,6 +45,7 @@ class MangaListDetailsHolder(parent: ViewGroup) : BaseViewHolder<Manga, MangaHis
|
||||
}
|
||||
|
||||
override fun onRecycled() {
|
||||
imageView_cover.clear()
|
||||
imageRequest?.dispose()
|
||||
imageView_cover.setImageDrawable(null)
|
||||
}
|
||||
}
|
||||
@@ -22,13 +22,13 @@ import org.koitharu.kotatsu.core.model.MangaTag
|
||||
import org.koitharu.kotatsu.core.model.SortOrder
|
||||
import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||
import org.koitharu.kotatsu.core.prefs.ListMode
|
||||
import org.koitharu.kotatsu.ui.common.BaseFragment
|
||||
import org.koitharu.kotatsu.ui.common.list.OnRecyclerItemClickListener
|
||||
import org.koitharu.kotatsu.ui.common.list.PaginationScrollListener
|
||||
import org.koitharu.kotatsu.ui.common.list.ProgressBarAdapter
|
||||
import org.koitharu.kotatsu.ui.common.list.decor.ItemTypeDividerDecoration
|
||||
import org.koitharu.kotatsu.ui.common.list.decor.SectionItemDecoration
|
||||
import org.koitharu.kotatsu.ui.common.list.decor.SpacingItemDecoration
|
||||
import org.koitharu.kotatsu.ui.base.BaseFragment
|
||||
import org.koitharu.kotatsu.ui.base.list.OnRecyclerItemClickListener
|
||||
import org.koitharu.kotatsu.ui.base.list.PaginationScrollListener
|
||||
import org.koitharu.kotatsu.ui.base.list.ProgressBarAdapter
|
||||
import org.koitharu.kotatsu.ui.base.list.decor.ItemTypeDividerDecoration
|
||||
import org.koitharu.kotatsu.ui.base.list.decor.SectionItemDecoration
|
||||
import org.koitharu.kotatsu.ui.base.list.decor.SpacingItemDecoration
|
||||
import org.koitharu.kotatsu.ui.details.MangaDetailsActivity
|
||||
import org.koitharu.kotatsu.ui.list.filter.FilterAdapter
|
||||
import org.koitharu.kotatsu.ui.list.filter.OnFilterChangedListener
|
||||
@@ -48,7 +48,7 @@ abstract class MangaListFragment<E> : BaseFragment(R.layout.fragment_list),
|
||||
|
||||
private var adapter: MangaListAdapter? = null
|
||||
private var progressAdapter: ProgressBarAdapter? = null
|
||||
private var paginationListener : PaginationScrollListener? = null
|
||||
private var paginationListener: PaginationScrollListener? = null
|
||||
protected var isSwipeRefreshEnabled = true
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
|
||||
@@ -1,30 +1,38 @@
|
||||
package org.koitharu.kotatsu.ui.list
|
||||
|
||||
import android.view.ViewGroup
|
||||
import coil.clear
|
||||
import coil.load
|
||||
import coil.ImageLoader
|
||||
import coil.request.Disposable
|
||||
import kotlinx.android.synthetic.main.item_manga_list.*
|
||||
import org.koin.core.component.inject
|
||||
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.list.BaseViewHolder
|
||||
import org.koitharu.kotatsu.ui.base.list.BaseViewHolder
|
||||
import org.koitharu.kotatsu.utils.ext.enqueueWith
|
||||
import org.koitharu.kotatsu.utils.ext.newImageRequest
|
||||
import org.koitharu.kotatsu.utils.ext.textAndVisible
|
||||
|
||||
class MangaListHolder(parent: ViewGroup) :
|
||||
BaseViewHolder<Manga, MangaHistory?>(parent, R.layout.item_manga_list) {
|
||||
class MangaListHolder(
|
||||
parent: ViewGroup
|
||||
) : BaseViewHolder<Manga, MangaHistory?>(parent, R.layout.item_manga_list) {
|
||||
|
||||
private val coil by inject<ImageLoader>()
|
||||
private var imageRequest: Disposable? = null
|
||||
|
||||
override fun onBind(data: Manga, extra: MangaHistory?) {
|
||||
imageView_cover.clear()
|
||||
imageRequest?.dispose()
|
||||
textView_title.text = data.title
|
||||
textView_subtitle.textAndVisible = data.tags.joinToString(", ") { it.title }
|
||||
imageView_cover.load(data.coverUrl) {
|
||||
placeholder(R.drawable.ic_placeholder)
|
||||
fallback(R.drawable.ic_placeholder)
|
||||
error(R.drawable.ic_placeholder)
|
||||
}
|
||||
imageRequest = imageView_cover.newImageRequest(data.coverUrl)
|
||||
.placeholder(R.drawable.ic_placeholder)
|
||||
.fallback(R.drawable.ic_placeholder)
|
||||
.error(R.drawable.ic_placeholder)
|
||||
.enqueueWith(coil)
|
||||
}
|
||||
|
||||
override fun onRecycled() {
|
||||
imageView_cover.clear()
|
||||
imageRequest?.dispose()
|
||||
imageView_cover.setImageDrawable(null)
|
||||
}
|
||||
}
|
||||
@@ -21,11 +21,11 @@ import org.koitharu.kotatsu.core.model.MangaTag
|
||||
import org.koitharu.kotatsu.core.model.SortOrder
|
||||
import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||
import org.koitharu.kotatsu.core.prefs.ListMode
|
||||
import org.koitharu.kotatsu.ui.common.BaseBottomSheet
|
||||
import org.koitharu.kotatsu.ui.common.list.OnRecyclerItemClickListener
|
||||
import org.koitharu.kotatsu.ui.common.list.PaginationScrollListener
|
||||
import org.koitharu.kotatsu.ui.common.list.ProgressBarAdapter
|
||||
import org.koitharu.kotatsu.ui.common.list.decor.SpacingItemDecoration
|
||||
import org.koitharu.kotatsu.ui.base.BaseBottomSheet
|
||||
import org.koitharu.kotatsu.ui.base.list.OnRecyclerItemClickListener
|
||||
import org.koitharu.kotatsu.ui.base.list.PaginationScrollListener
|
||||
import org.koitharu.kotatsu.ui.base.list.ProgressBarAdapter
|
||||
import org.koitharu.kotatsu.ui.base.list.decor.SpacingItemDecoration
|
||||
import org.koitharu.kotatsu.ui.details.MangaDetailsActivity
|
||||
import org.koitharu.kotatsu.utils.UiUtils
|
||||
import org.koitharu.kotatsu.utils.ext.*
|
||||
|
||||
@@ -9,7 +9,7 @@ import org.koitharu.kotatsu.core.model.Manga
|
||||
import org.koitharu.kotatsu.core.model.MangaFilter
|
||||
import org.koitharu.kotatsu.core.model.MangaTag
|
||||
import org.koitharu.kotatsu.core.model.SortOrder
|
||||
import org.koitharu.kotatsu.ui.common.BaseMvpView
|
||||
import org.koitharu.kotatsu.ui.base.BaseMvpView
|
||||
|
||||
interface MangaListView<E> : BaseMvpView {
|
||||
|
||||
|
||||
@@ -13,14 +13,15 @@ import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.core.model.FavouriteCategory
|
||||
import org.koitharu.kotatsu.domain.favourites.FavouritesRepository
|
||||
import org.koitharu.kotatsu.domain.favourites.OnFavouritesChangeListener
|
||||
import org.koitharu.kotatsu.ui.common.BaseFragment
|
||||
import org.koitharu.kotatsu.ui.base.BaseFragment
|
||||
import org.koitharu.kotatsu.ui.list.favourites.categories.CategoriesActivity
|
||||
import org.koitharu.kotatsu.ui.list.favourites.categories.FavouriteCategoriesPresenter
|
||||
import org.koitharu.kotatsu.ui.list.favourites.categories.FavouriteCategoriesView
|
||||
import java.util.*
|
||||
import kotlin.collections.ArrayList
|
||||
|
||||
class FavouritesContainerFragment : BaseFragment(R.layout.fragment_favourites), FavouriteCategoriesView,
|
||||
class FavouritesContainerFragment : BaseFragment(R.layout.fragment_favourites),
|
||||
FavouriteCategoriesView,
|
||||
OnFavouritesChangeListener {
|
||||
|
||||
private val presenter by moxyPresenter(factory = ::FavouriteCategoriesPresenter)
|
||||
|
||||
@@ -1,36 +1,28 @@
|
||||
package org.koitharu.kotatsu.ui.list.favourites
|
||||
|
||||
import kotlinx.coroutines.CancellationException
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import moxy.InjectViewState
|
||||
import moxy.presenterScope
|
||||
import org.koin.core.component.get
|
||||
import org.koitharu.kotatsu.BuildConfig
|
||||
import org.koitharu.kotatsu.domain.favourites.FavouritesRepository
|
||||
import org.koitharu.kotatsu.ui.common.BasePresenter
|
||||
import org.koitharu.kotatsu.ui.base.BasePresenter
|
||||
import org.koitharu.kotatsu.ui.list.MangaListView
|
||||
|
||||
@InjectViewState
|
||||
class FavouritesListPresenter : BasePresenter<MangaListView<Unit>>() {
|
||||
|
||||
private lateinit var repository: FavouritesRepository
|
||||
|
||||
override fun onFirstViewAttach() {
|
||||
repository = FavouritesRepository()
|
||||
super.onFirstViewAttach()
|
||||
}
|
||||
private val repository = get<FavouritesRepository>()
|
||||
|
||||
fun loadList(categoryId: Long, offset: Int) {
|
||||
presenterScope.launch {
|
||||
viewState.onLoadingStateChanged(true)
|
||||
try {
|
||||
val list = withContext(Dispatchers.IO) {
|
||||
if (categoryId == 0L) {
|
||||
repository.getAllManga(offset = offset)
|
||||
} else {
|
||||
repository.getManga(categoryId = categoryId, offset = offset)
|
||||
}
|
||||
val list = if (categoryId == 0L) {
|
||||
repository.getAllManga(offset = offset)
|
||||
} else {
|
||||
repository.getManga(categoryId = categoryId, offset = offset)
|
||||
}
|
||||
if (offset == 0) {
|
||||
viewState.onListChanged(list)
|
||||
|
||||
@@ -5,10 +5,11 @@ import androidx.viewpager2.adapter.FragmentStateAdapter
|
||||
import com.google.android.material.tabs.TabLayout
|
||||
import com.google.android.material.tabs.TabLayoutMediator
|
||||
import org.koitharu.kotatsu.core.model.FavouriteCategory
|
||||
import org.koitharu.kotatsu.ui.common.list.AdapterUpdater
|
||||
import org.koitharu.kotatsu.ui.base.list.AdapterUpdater
|
||||
import org.koitharu.kotatsu.utils.ext.replaceWith
|
||||
|
||||
class FavouritesPagerAdapter(fragment: Fragment) : FragmentStateAdapter(fragment), TabLayoutMediator.TabConfigurationStrategy {
|
||||
class FavouritesPagerAdapter(fragment: Fragment) : FragmentStateAdapter(fragment),
|
||||
TabLayoutMediator.TabConfigurationStrategy {
|
||||
|
||||
private val dataSet = ArrayList<FavouriteCategory>()
|
||||
|
||||
|
||||
@@ -17,9 +17,9 @@ import kotlinx.android.synthetic.main.activity_categories.*
|
||||
import moxy.ktx.moxyPresenter
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.core.model.FavouriteCategory
|
||||
import org.koitharu.kotatsu.ui.common.BaseActivity
|
||||
import org.koitharu.kotatsu.ui.common.dialog.TextInputDialog
|
||||
import org.koitharu.kotatsu.ui.common.list.OnRecyclerItemClickListener
|
||||
import org.koitharu.kotatsu.ui.base.BaseActivity
|
||||
import org.koitharu.kotatsu.ui.base.dialog.TextInputDialog
|
||||
import org.koitharu.kotatsu.ui.base.list.OnRecyclerItemClickListener
|
||||
import org.koitharu.kotatsu.utils.ext.getDisplayMessage
|
||||
import org.koitharu.kotatsu.utils.ext.showPopupMenu
|
||||
|
||||
@@ -61,7 +61,9 @@ class CategoriesActivity : BaseActivity(), OnRecyclerItemClickListener<Favourite
|
||||
}
|
||||
|
||||
override fun onItemLongClick(item: FavouriteCategory, position: Int, view: View): Boolean {
|
||||
reorderHelper.startDrag(recyclerView.findViewHolderForAdapterPosition(position) ?: return false)
|
||||
reorderHelper.startDrag(
|
||||
recyclerView.findViewHolderForAdapterPosition(position) ?: return false
|
||||
)
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
@@ -5,9 +5,9 @@ import android.view.MotionEvent
|
||||
import android.view.ViewGroup
|
||||
import kotlinx.android.synthetic.main.item_category.*
|
||||
import org.koitharu.kotatsu.core.model.FavouriteCategory
|
||||
import org.koitharu.kotatsu.ui.common.list.BaseRecyclerAdapter
|
||||
import org.koitharu.kotatsu.ui.common.list.BaseViewHolder
|
||||
import org.koitharu.kotatsu.ui.common.list.OnRecyclerItemClickListener
|
||||
import org.koitharu.kotatsu.ui.base.list.BaseRecyclerAdapter
|
||||
import org.koitharu.kotatsu.ui.base.list.BaseViewHolder
|
||||
import org.koitharu.kotatsu.ui.base.list.OnRecyclerItemClickListener
|
||||
|
||||
class CategoriesAdapter(private val onItemClickListener: OnRecyclerItemClickListener<FavouriteCategory>) :
|
||||
BaseRecyclerAdapter<FavouriteCategory, Unit>() {
|
||||
@@ -25,7 +25,11 @@ class CategoriesAdapter(private val onItemClickListener: OnRecyclerItemClickList
|
||||
}
|
||||
holder.imageView_handle.setOnTouchListener { v, event ->
|
||||
if (event.actionMasked == MotionEvent.ACTION_DOWN) {
|
||||
onItemClickListener.onItemLongClick(holder.requireData(), holder.bindingAdapterPosition, v)
|
||||
onItemClickListener.onItemLongClick(
|
||||
holder.requireData(),
|
||||
holder.bindingAdapterPosition,
|
||||
v
|
||||
)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import android.view.ViewGroup
|
||||
import kotlinx.android.synthetic.main.item_category.*
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.core.model.FavouriteCategory
|
||||
import org.koitharu.kotatsu.ui.common.list.BaseViewHolder
|
||||
import org.koitharu.kotatsu.ui.base.list.BaseViewHolder
|
||||
|
||||
class CategoryHolder(parent: ViewGroup) :
|
||||
BaseViewHolder<FavouriteCategory, Unit>(parent, R.layout.item_category) {
|
||||
|
||||
@@ -3,20 +3,18 @@ package org.koitharu.kotatsu.ui.list.favourites.categories
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
import kotlinx.coroutines.sync.withLock
|
||||
import moxy.InjectViewState
|
||||
import org.koin.core.component.get
|
||||
import org.koitharu.kotatsu.core.model.Manga
|
||||
import org.koitharu.kotatsu.domain.favourites.FavouritesRepository
|
||||
import org.koitharu.kotatsu.ui.common.BasePresenter
|
||||
import org.koitharu.kotatsu.ui.base.BasePresenter
|
||||
|
||||
@InjectViewState
|
||||
class FavouriteCategoriesPresenter : BasePresenter<FavouriteCategoriesView>() {
|
||||
|
||||
private lateinit var repository: FavouritesRepository
|
||||
private val reorderMutex by lazy {
|
||||
Mutex()
|
||||
}
|
||||
private val repository = get<FavouritesRepository>()
|
||||
private val reorderMutex by lazy(LazyThreadSafetyMode.NONE) { Mutex() }
|
||||
|
||||
override fun onFirstViewAttach() {
|
||||
repository = FavouritesRepository()
|
||||
super.onFirstViewAttach()
|
||||
loadAllCategories()
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import moxy.viewstate.strategy.AddToEndSingleStrategy
|
||||
import moxy.viewstate.strategy.StateStrategyType
|
||||
import moxy.viewstate.strategy.alias.AddToEndSingle
|
||||
import org.koitharu.kotatsu.core.model.FavouriteCategory
|
||||
import org.koitharu.kotatsu.ui.common.BaseMvpView
|
||||
import org.koitharu.kotatsu.ui.base.BaseMvpView
|
||||
|
||||
interface FavouriteCategoriesView : BaseMvpView {
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@ import android.view.ViewGroup
|
||||
import android.widget.Checkable
|
||||
import androidx.core.util.set
|
||||
import org.koitharu.kotatsu.core.model.FavouriteCategory
|
||||
import org.koitharu.kotatsu.ui.common.list.BaseRecyclerAdapter
|
||||
import org.koitharu.kotatsu.ui.common.list.BaseViewHolder
|
||||
import org.koitharu.kotatsu.ui.base.list.BaseRecyclerAdapter
|
||||
import org.koitharu.kotatsu.ui.base.list.BaseViewHolder
|
||||
|
||||
class CategoriesSelectAdapter(private val listener: OnCategoryCheckListener) :
|
||||
BaseRecyclerAdapter<FavouriteCategory, Boolean>() {
|
||||
|
||||
@@ -4,7 +4,7 @@ import android.view.ViewGroup
|
||||
import kotlinx.android.synthetic.main.item_category_checkable.*
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.core.model.FavouriteCategory
|
||||
import org.koitharu.kotatsu.ui.common.list.BaseViewHolder
|
||||
import org.koitharu.kotatsu.ui.base.list.BaseViewHolder
|
||||
|
||||
class CategoryCheckableHolder(parent: ViewGroup) :
|
||||
BaseViewHolder<FavouriteCategory, Boolean>(parent, R.layout.item_category_checkable) {
|
||||
|
||||
@@ -10,8 +10,8 @@ import moxy.ktx.moxyPresenter
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.core.model.FavouriteCategory
|
||||
import org.koitharu.kotatsu.core.model.Manga
|
||||
import org.koitharu.kotatsu.ui.common.BaseBottomSheet
|
||||
import org.koitharu.kotatsu.ui.common.dialog.TextInputDialog
|
||||
import org.koitharu.kotatsu.ui.base.BaseBottomSheet
|
||||
import org.koitharu.kotatsu.ui.base.dialog.TextInputDialog
|
||||
import org.koitharu.kotatsu.ui.list.favourites.categories.FavouriteCategoriesPresenter
|
||||
import org.koitharu.kotatsu.ui.list.favourites.categories.FavouriteCategoriesView
|
||||
import org.koitharu.kotatsu.utils.ext.getDisplayMessage
|
||||
@@ -31,7 +31,8 @@ class FavouriteCategoriesDialog : BaseBottomSheet(R.layout.dialog_favorite_categ
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
adapter =
|
||||
CategoriesSelectAdapter(
|
||||
this)
|
||||
this
|
||||
)
|
||||
recyclerView_categories.adapter = adapter
|
||||
textView_add.setOnClickListener {
|
||||
createCategory()
|
||||
@@ -86,8 +87,10 @@ class FavouriteCategoriesDialog : BaseBottomSheet(R.layout.dialog_favorite_categ
|
||||
|
||||
fun show(fm: FragmentManager, manga: Manga) = FavouriteCategoriesDialog()
|
||||
.withArgs(1) {
|
||||
putParcelable(ARG_MANGA, manga)
|
||||
}.show(fm,
|
||||
TAG)
|
||||
putParcelable(ARG_MANGA, manga)
|
||||
}.show(
|
||||
fm,
|
||||
TAG
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -2,9 +2,9 @@ package org.koitharu.kotatsu.ui.list.feed
|
||||
|
||||
import android.view.ViewGroup
|
||||
import org.koitharu.kotatsu.core.model.TrackingLogItem
|
||||
import org.koitharu.kotatsu.ui.common.list.BaseRecyclerAdapter
|
||||
import org.koitharu.kotatsu.ui.common.list.BaseViewHolder
|
||||
import org.koitharu.kotatsu.ui.common.list.OnRecyclerItemClickListener
|
||||
import org.koitharu.kotatsu.ui.base.list.BaseRecyclerAdapter
|
||||
import org.koitharu.kotatsu.ui.base.list.BaseViewHolder
|
||||
import org.koitharu.kotatsu.ui.base.list.OnRecyclerItemClickListener
|
||||
|
||||
class FeedAdapter(onItemClickListener: OnRecyclerItemClickListener<TrackingLogItem>? = null) :
|
||||
BaseRecyclerAdapter<TrackingLogItem, Unit>(onItemClickListener) {
|
||||
|
||||
@@ -12,10 +12,10 @@ import moxy.MvpDelegate
|
||||
import moxy.ktx.moxyPresenter
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.core.model.TrackingLogItem
|
||||
import org.koitharu.kotatsu.ui.common.BaseFragment
|
||||
import org.koitharu.kotatsu.ui.common.list.OnRecyclerItemClickListener
|
||||
import org.koitharu.kotatsu.ui.common.list.PaginationScrollListener
|
||||
import org.koitharu.kotatsu.ui.common.list.decor.SpacingItemDecoration
|
||||
import org.koitharu.kotatsu.ui.base.BaseFragment
|
||||
import org.koitharu.kotatsu.ui.base.list.OnRecyclerItemClickListener
|
||||
import org.koitharu.kotatsu.ui.base.list.PaginationScrollListener
|
||||
import org.koitharu.kotatsu.ui.base.list.decor.SpacingItemDecoration
|
||||
import org.koitharu.kotatsu.ui.details.MangaDetailsActivity
|
||||
import org.koitharu.kotatsu.ui.tracker.TrackWorker
|
||||
import org.koitharu.kotatsu.utils.ext.callOnScrollListeners
|
||||
@@ -55,7 +55,7 @@ class FeedFragment : BaseFragment(R.layout.fragment_tracklogs), FeedView,
|
||||
inflater.inflate(R.menu.opt_feed, menu)
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem) = when(item.itemId) {
|
||||
override fun onOptionsItemSelected(item: MenuItem) = when (item.itemId) {
|
||||
R.id.action_update -> {
|
||||
TrackWorker.startNow(requireContext())
|
||||
Snackbar.make(recyclerView, R.string.feed_will_update_soon, Snackbar.LENGTH_LONG).show()
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user