chore: code cleanup
This commit is contained in:
parent
386e02a564
commit
24147e746a
198 changed files with 1367 additions and 965 deletions
|
@ -7,11 +7,11 @@ import android.os.Bundle
|
|||
import androidx.multidex.MultiDex
|
||||
import androidx.multidex.MultiDexApplication
|
||||
import ani.dantotsu.addons.download.DownloadAddonManager
|
||||
import ani.dantotsu.addons.torrent.TorrentAddonManager
|
||||
import ani.dantotsu.aniyomi.anime.custom.AppModule
|
||||
import ani.dantotsu.aniyomi.anime.custom.PreferenceModule
|
||||
import ani.dantotsu.connections.comments.CommentsAPI
|
||||
import ani.dantotsu.connections.crashlytics.CrashlyticsInterface
|
||||
import ani.dantotsu.addons.torrent.TorrentAddonManager
|
||||
import ani.dantotsu.notifications.TaskScheduler
|
||||
import ani.dantotsu.others.DisabledReports
|
||||
import ani.dantotsu.parsers.AnimeSources
|
||||
|
|
|
@ -190,7 +190,7 @@ var loadMedia: Int? = null
|
|||
var loadIsMAL = false
|
||||
|
||||
val Int.toPx get() = TypedValue.applyDimension(
|
||||
TypedValue.COMPLEX_UNIT_DIP, this.toFloat(), Resources.getSystem().displayMetrics
|
||||
TypedValue.COMPLEX_UNIT_DIP, this.toFloat(), getSystem().displayMetrics
|
||||
).toInt()
|
||||
|
||||
fun initActivity(a: Activity) {
|
||||
|
@ -464,7 +464,7 @@ class InputFilterMinMax(
|
|||
}
|
||||
|
||||
|
||||
class ZoomOutPageTransformer() :
|
||||
class ZoomOutPageTransformer :
|
||||
ViewPager2.PageTransformer {
|
||||
override fun transformPage(view: View, position: Float) {
|
||||
if (position == 0.0f && PrefManager.getVal(PrefName.LayoutAnimations)) {
|
||||
|
|
|
@ -1,38 +1,23 @@
|
|||
package ani.dantotsu.addons
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Activity
|
||||
import android.app.DownloadManager
|
||||
import android.app.NotificationManager
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.Environment
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.content.getSystemService
|
||||
import androidx.core.net.toUri
|
||||
import ani.dantotsu.BuildConfig
|
||||
import ani.dantotsu.Mapper
|
||||
import ani.dantotsu.R
|
||||
import ani.dantotsu.client
|
||||
import ani.dantotsu.logError
|
||||
import ani.dantotsu.media.MediaType
|
||||
import ani.dantotsu.openLinkInBrowser
|
||||
import ani.dantotsu.others.AppUpdater
|
||||
import ani.dantotsu.settings.InstallerSteps
|
||||
import ani.dantotsu.toast
|
||||
import ani.dantotsu.util.Logger
|
||||
import eu.kanade.tachiyomi.extension.InstallStep
|
||||
import eu.kanade.tachiyomi.extension.util.ExtensionInstaller
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.MainScope
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.serialization.json.JsonArray
|
||||
import kotlinx.serialization.json.decodeFromJsonElement
|
||||
import rx.Observable
|
||||
import rx.android.schedulers.AndroidSchedulers
|
||||
|
||||
class AddonDownloader {
|
||||
|
@ -44,8 +29,8 @@ class AddonDownloader {
|
|||
Mapper.json.decodeFromJsonElement<AppUpdater.GithubResponse>(it)
|
||||
}
|
||||
val r = res.maxByOrNull {
|
||||
it.timeStamp()
|
||||
} ?: throw Exception("No Pre Release Found")
|
||||
it.timeStamp()
|
||||
} ?: throw Exception("No Pre Release Found")
|
||||
val v = r.tagName.substringAfter("v", "")
|
||||
val md = r.body ?: ""
|
||||
val version = v.ifEmpty { throw Exception("Weird Version : ${r.tagName}") }
|
||||
|
@ -101,8 +86,7 @@ class AddonDownloader {
|
|||
{ error -> installerSteps.onError(error) {} },
|
||||
{ installerSteps.onComplete {} }
|
||||
)
|
||||
}
|
||||
else openLinkInBrowser("https://github.com/repos/$repo/releases/tag/v$version")
|
||||
} else openLinkInBrowser("https://github.com/repos/$repo/releases/tag/v$version")
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
logError(e)
|
||||
|
|
|
@ -9,8 +9,8 @@ import ani.dantotsu.addons.download.DownloadAddon
|
|||
import ani.dantotsu.addons.download.DownloadAddonApi
|
||||
import ani.dantotsu.addons.download.DownloadAddonManager
|
||||
import ani.dantotsu.addons.download.DownloadLoadResult
|
||||
import ani.dantotsu.addons.torrent.TorrentAddonApi
|
||||
import ani.dantotsu.addons.torrent.TorrentAddon
|
||||
import ani.dantotsu.addons.torrent.TorrentAddonApi
|
||||
import ani.dantotsu.addons.torrent.TorrentAddonManager
|
||||
import ani.dantotsu.addons.torrent.TorrentLoadResult
|
||||
import ani.dantotsu.media.AddonType
|
||||
|
@ -56,7 +56,8 @@ class AddonLoader {
|
|||
throw error
|
||||
}
|
||||
|
||||
val extName = pkgManager.getApplicationLabel(appInfo).toString().substringAfter("Dantotsu: ")
|
||||
val extName =
|
||||
pkgManager.getApplicationLabel(appInfo).toString().substringAfter("Dantotsu: ")
|
||||
val versionName = pkgInfo.versionName
|
||||
val versionCode = PackageInfoCompat.getLongVersionCode(pkgInfo)
|
||||
|
||||
|
@ -64,7 +65,8 @@ class AddonLoader {
|
|||
Logger.log("Missing versionName for extension $extName")
|
||||
throw IllegalStateException("Missing versionName for extension $extName")
|
||||
}
|
||||
val classLoader = PathClassLoader(appInfo.sourceDir, appInfo.nativeLibraryDir, context.classLoader)
|
||||
val classLoader =
|
||||
PathClassLoader(appInfo.sourceDir, appInfo.nativeLibraryDir, context.classLoader)
|
||||
val loadedClass = try {
|
||||
Class.forName(className, false, classLoader)
|
||||
} catch (e: ClassNotFoundException) {
|
||||
|
@ -75,7 +77,7 @@ class AddonLoader {
|
|||
Logger.log("Extension load error: $extName ($className)")
|
||||
Logger.log(e)
|
||||
throw e
|
||||
}catch (e: Exception) {
|
||||
} catch (e: Exception) {
|
||||
Logger.log("Extension load error: $extName ($className)")
|
||||
Logger.log(e)
|
||||
throw e
|
||||
|
@ -84,7 +86,8 @@ class AddonLoader {
|
|||
|
||||
return when (type) {
|
||||
AddonType.TORRENT -> {
|
||||
val extension = instance as? TorrentAddonApi ?: throw IllegalStateException("Extension is not a TorrentAddonApi")
|
||||
val extension = instance as? TorrentAddonApi
|
||||
?: throw IllegalStateException("Extension is not a TorrentAddonApi")
|
||||
TorrentLoadResult.Success(
|
||||
TorrentAddon.Installed(
|
||||
name = extName,
|
||||
|
@ -96,8 +99,10 @@ class AddonLoader {
|
|||
)
|
||||
)
|
||||
}
|
||||
|
||||
AddonType.DOWNLOAD -> {
|
||||
val extension = instance as? DownloadAddonApi ?: throw IllegalStateException("Extension is not a DownloadAddonApi")
|
||||
val extension = instance as? DownloadAddonApi
|
||||
?: throw IllegalStateException("Extension is not a DownloadAddonApi")
|
||||
DownloadLoadResult.Success(
|
||||
DownloadAddon.Installed(
|
||||
name = extName,
|
||||
|
@ -120,6 +125,7 @@ class AddonLoader {
|
|||
TorrentAddonManager.TORRENT_CLASS,
|
||||
type
|
||||
)
|
||||
|
||||
AddonType.DOWNLOAD -> loadExtension(
|
||||
context,
|
||||
packageName,
|
||||
|
|
|
@ -6,7 +6,7 @@ import eu.kanade.tachiyomi.extension.InstallStep
|
|||
import eu.kanade.tachiyomi.extension.util.ExtensionInstaller
|
||||
import rx.Observable
|
||||
|
||||
abstract class AddonManager<T: Addon.Installed>(
|
||||
abstract class AddonManager<T : Addon.Installed>(
|
||||
private val context: Context
|
||||
) {
|
||||
abstract var extension: T?
|
||||
|
@ -31,14 +31,16 @@ abstract class AddonManager<T: Addon.Installed>(
|
|||
installer.uninstallApk(it)
|
||||
}
|
||||
}
|
||||
|
||||
fun addListenerAction(action: (AddonListener.ListenerAction) -> Unit) {
|
||||
onListenerAction = action
|
||||
}
|
||||
|
||||
fun removeListenerAction() {
|
||||
onListenerAction = null
|
||||
}
|
||||
|
||||
fun install(url: String): Observable<InstallStep> {
|
||||
return installer.downloadAndInstall(url, getPackageName()?: "", name, type)
|
||||
return installer.downloadAndInstall(url, getPackageName() ?: "", name, type)
|
||||
}
|
||||
}
|
|
@ -3,7 +3,6 @@ package ani.dantotsu.addons.download
|
|||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import androidx.core.content.ContextCompat
|
||||
import ani.dantotsu.addons.AddonListener
|
||||
import ani.dantotsu.addons.AddonLoader
|
||||
|
@ -26,7 +25,7 @@ internal class AddonInstallReceiver : BroadcastReceiver() {
|
|||
ContextCompat.registerReceiver(context, this, filter, ContextCompat.RECEIVER_EXPORTED)
|
||||
}
|
||||
|
||||
fun setListener(listener: AddonListener, type: AddonType) : AddonInstallReceiver {
|
||||
fun setListener(listener: AddonListener, type: AddonType): AddonInstallReceiver {
|
||||
this.listener = listener
|
||||
this.type = type
|
||||
return this
|
||||
|
|
|
@ -2,6 +2,6 @@ package ani.dantotsu.addons.download
|
|||
|
||||
import ani.dantotsu.addons.LoadResult
|
||||
|
||||
open class DownloadLoadResult: LoadResult() {
|
||||
open class DownloadLoadResult : LoadResult() {
|
||||
class Success(val extension: DownloadAddon.Installed) : DownloadLoadResult()
|
||||
}
|
|
@ -14,10 +14,7 @@ import ani.dantotsu.addons.download.AddonInstallReceiver
|
|||
import ani.dantotsu.media.AddonType
|
||||
import ani.dantotsu.util.Logger
|
||||
import eu.kanade.tachiyomi.extension.InstallStep
|
||||
import eu.kanade.tachiyomi.extension.util.ExtensionInstaller
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
class TorrentAddonManager(
|
||||
|
@ -98,7 +95,7 @@ class TorrentAddonManager(
|
|||
}
|
||||
}
|
||||
|
||||
private inner class InstallationListener : AddonListener {
|
||||
private inner class InstallationListener : AddonListener {
|
||||
override fun onAddonInstalled(result: LoadResult?) {
|
||||
if (result is TorrentLoadResult.Success) {
|
||||
extension = result.extension
|
||||
|
|
|
@ -2,6 +2,6 @@ package ani.dantotsu.addons.torrent
|
|||
|
||||
import ani.dantotsu.addons.LoadResult
|
||||
|
||||
open class TorrentLoadResult: LoadResult() {
|
||||
open class TorrentLoadResult : LoadResult() {
|
||||
class Success(val extension: TorrentAddon.Installed) : TorrentLoadResult()
|
||||
}
|
|
@ -22,7 +22,7 @@ import uy.kohesive.injekt.api.get
|
|||
import kotlin.coroutines.EmptyCoroutineContext
|
||||
|
||||
|
||||
class ServerService: Service() {
|
||||
class ServerService : Service() {
|
||||
private val serviceScope = CoroutineScope(EmptyCoroutineContext)
|
||||
private val applicationContext = Injekt.get<Application>()
|
||||
private val extension = Injekt.get<TorrentAddonManager>().extension!!.extension
|
||||
|
@ -42,6 +42,7 @@ class ServerService: Service() {
|
|||
notification(applicationContext)
|
||||
return START_STICKY
|
||||
}
|
||||
|
||||
ACTION_STOP -> {
|
||||
stopServer()
|
||||
return START_NOT_STICKY
|
||||
|
@ -109,7 +110,7 @@ class ServerService: Service() {
|
|||
const val ACTION_STOP = "stop_torrent_server"
|
||||
|
||||
fun isRunning(): Boolean {
|
||||
with (Injekt.get<Application>().getSystemService(ACTIVITY_SERVICE) as ActivityManager) {
|
||||
with(Injekt.get<Application>().getSystemService(ACTIVITY_SERVICE) as ActivityManager) {
|
||||
@Suppress("DEPRECATION") // We only need our services
|
||||
getRunningServices(Int.MAX_VALUE).forEach {
|
||||
if (ServerService::class.java.name.equals(it.service.className)) {
|
||||
|
|
|
@ -7,9 +7,9 @@ import androidx.core.content.ContextCompat
|
|||
import androidx.media3.common.util.UnstableApi
|
||||
import androidx.media3.database.StandaloneDatabaseProvider
|
||||
import ani.dantotsu.addons.download.DownloadAddonManager
|
||||
import ani.dantotsu.addons.torrent.TorrentAddonManager
|
||||
import ani.dantotsu.connections.crashlytics.CrashlyticsInterface
|
||||
import ani.dantotsu.download.DownloadsManager
|
||||
import ani.dantotsu.addons.torrent.TorrentAddonManager
|
||||
import ani.dantotsu.media.manga.MangaCache
|
||||
import ani.dantotsu.parsers.novel.NovelExtensionManager
|
||||
import eu.kanade.domain.base.BasePreferences
|
||||
|
|
|
@ -1188,7 +1188,7 @@ query (${"$"}page: Int = 1, ${"$"}id: Int, ${"$"}type: MediaType, ${"$"}isAdult:
|
|||
suspend fun recentlyUpdated(
|
||||
greater: Long = 0,
|
||||
lesser: Long = System.currentTimeMillis() / 1000 - 10000
|
||||
): MutableList<Media>? {
|
||||
): MutableList<Media> {
|
||||
suspend fun execute(page: Int = 1): Page? {
|
||||
val query = """{
|
||||
Page(page:$page,perPage:50) {
|
||||
|
|
|
@ -84,9 +84,9 @@ data class Notification(
|
|||
@SerialName("createdAt")
|
||||
val createdAt: Int,
|
||||
@SerialName("media")
|
||||
val media: ani.dantotsu.connections.anilist.api.Media? = null,
|
||||
val media: Media? = null,
|
||||
@SerialName("user")
|
||||
val user: ani.dantotsu.connections.anilist.api.User? = null,
|
||||
val user: User? = null,
|
||||
@SerialName("message")
|
||||
val message: MessageActivity? = null,
|
||||
@SerialName("activity")
|
||||
|
|
|
@ -355,7 +355,7 @@ class NovelDownloaderService : Service() {
|
|||
private fun saveMediaInfo(task: DownloadTask) {
|
||||
launchIO {
|
||||
val directory =
|
||||
DownloadsManager.getSubDirectory(
|
||||
getSubDirectory(
|
||||
this@NovelDownloaderService,
|
||||
MediaType.NOVEL,
|
||||
false,
|
||||
|
|
|
@ -101,7 +101,7 @@ class AnimePageAdapter : RecyclerView.Adapter<AnimePageAdapter.AnimePageViewHold
|
|||
ContextCompat.startActivity(
|
||||
view.context,
|
||||
Intent(view.context, ProfileActivity::class.java)
|
||||
.putExtra("userId", Anilist.userid),null
|
||||
.putExtra("userId", Anilist.userid), null
|
||||
)
|
||||
false
|
||||
}
|
||||
|
@ -110,7 +110,8 @@ class AnimePageAdapter : RecyclerView.Adapter<AnimePageAdapter.AnimePageViewHold
|
|||
trendingBinding.searchBar.performClick()
|
||||
}
|
||||
|
||||
trendingBinding.notificationCount.visibility = if (Anilist.unreadNotificationCount > 0) View.VISIBLE else View.GONE
|
||||
trendingBinding.notificationCount.visibility =
|
||||
if (Anilist.unreadNotificationCount > 0) View.VISIBLE else View.GONE
|
||||
trendingBinding.notificationCount.text = Anilist.unreadNotificationCount.toString()
|
||||
|
||||
listOf(
|
||||
|
@ -167,7 +168,8 @@ class AnimePageAdapter : RecyclerView.Adapter<AnimePageAdapter.AnimePageViewHold
|
|||
trendingBinding.trendingProgressBar.visibility = View.GONE
|
||||
trendingBinding.trendingViewPager.adapter = adaptor
|
||||
trendingBinding.trendingViewPager.offscreenPageLimit = 3
|
||||
trendingBinding.trendingViewPager.getChildAt(0).overScrollMode = RecyclerView.OVER_SCROLL_NEVER
|
||||
trendingBinding.trendingViewPager.getChildAt(0).overScrollMode =
|
||||
RecyclerView.OVER_SCROLL_NEVER
|
||||
trendingBinding.trendingViewPager.setPageTransformer(MediaPageTransformer())
|
||||
trendHandler = Handler(Looper.getMainLooper())
|
||||
trendRun = Runnable {
|
||||
|
@ -195,7 +197,7 @@ class AnimePageAdapter : RecyclerView.Adapter<AnimePageAdapter.AnimePageViewHold
|
|||
}
|
||||
|
||||
fun updateRecent(adaptor: MediaAdaptor) {
|
||||
binding.apply{
|
||||
binding.apply {
|
||||
init(
|
||||
adaptor,
|
||||
animeUpdatedRecyclerView,
|
||||
|
@ -210,8 +212,9 @@ class AnimePageAdapter : RecyclerView.Adapter<AnimePageAdapter.AnimePageViewHold
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
fun updateMovies(adaptor: MediaAdaptor) {
|
||||
binding.apply{
|
||||
binding.apply {
|
||||
init(
|
||||
adaptor,
|
||||
animeMoviesRecyclerView,
|
||||
|
@ -222,7 +225,7 @@ class AnimePageAdapter : RecyclerView.Adapter<AnimePageAdapter.AnimePageViewHold
|
|||
}
|
||||
|
||||
fun updateTopRated(adaptor: MediaAdaptor) {
|
||||
binding.apply{
|
||||
binding.apply {
|
||||
init(
|
||||
adaptor,
|
||||
animeTopRatedRecyclerView,
|
||||
|
@ -231,8 +234,9 @@ class AnimePageAdapter : RecyclerView.Adapter<AnimePageAdapter.AnimePageViewHold
|
|||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun updateMostFav(adaptor: MediaAdaptor) {
|
||||
binding.apply{
|
||||
binding.apply {
|
||||
init(
|
||||
adaptor,
|
||||
animeMostFavRecyclerView,
|
||||
|
@ -241,7 +245,8 @@ class AnimePageAdapter : RecyclerView.Adapter<AnimePageAdapter.AnimePageViewHold
|
|||
)
|
||||
}
|
||||
}
|
||||
fun init(adaptor: MediaAdaptor,recyclerView: RecyclerView, progress: View, title: View){
|
||||
|
||||
fun init(adaptor: MediaAdaptor, recyclerView: RecyclerView, progress: View, title: View) {
|
||||
progress.visibility = View.GONE
|
||||
recyclerView.adapter = adaptor
|
||||
recyclerView.layoutManager =
|
||||
|
@ -256,6 +261,7 @@ class AnimePageAdapter : RecyclerView.Adapter<AnimePageAdapter.AnimePageViewHold
|
|||
recyclerView.layoutAnimation =
|
||||
LayoutAnimationController(setSlideIn(), 0.25f)
|
||||
}
|
||||
|
||||
fun updateAvatar() {
|
||||
if (Anilist.avatar != null && ready.value == true) {
|
||||
trendingBinding.userAvatar.loadImage(Anilist.avatar)
|
||||
|
|
|
@ -81,7 +81,10 @@ class HomeFragment : Fragment() {
|
|||
binding.homeUserChaptersRead.text = Anilist.chapterRead.toString()
|
||||
binding.homeUserAvatar.loadImage(Anilist.avatar)
|
||||
val bannerAnimations: Boolean = PrefManager.getVal(PrefName.BannerAnimations)
|
||||
blurImage(if (bannerAnimations) binding.homeUserBg else binding.homeUserBgNoKen, Anilist.bg)
|
||||
blurImage(
|
||||
if (bannerAnimations) binding.homeUserBg else binding.homeUserBgNoKen,
|
||||
Anilist.bg
|
||||
)
|
||||
binding.homeUserDataProgressBar.visibility = View.GONE
|
||||
binding.homeNotificationCount.isVisible = Anilist.unreadNotificationCount > 0
|
||||
binding.homeNotificationCount.text = Anilist.unreadNotificationCount.toString()
|
||||
|
@ -128,7 +131,7 @@ class HomeFragment : Fragment() {
|
|||
it.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS)
|
||||
ContextCompat.startActivity(
|
||||
requireContext(), Intent(requireContext(), ProfileActivity::class.java)
|
||||
.putExtra("userId", Anilist.userid),null
|
||||
.putExtra("userId", Anilist.userid), null
|
||||
)
|
||||
false
|
||||
}
|
||||
|
@ -376,6 +379,7 @@ class HomeFragment : Fragment() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
if (!model.loaded) Refresh.activity[1]!!.postValue(true)
|
||||
if (_binding != null) {
|
||||
|
|
|
@ -172,7 +172,13 @@ class MangaFragment : Fragment() {
|
|||
}
|
||||
model.getPopularManhwa().observe(viewLifecycleOwner) {
|
||||
if (it != null) {
|
||||
mangaPageAdapter.updateTrendingManhwa(MediaAdaptor(0, it, requireActivity()))
|
||||
mangaPageAdapter.updateTrendingManhwa(
|
||||
MediaAdaptor(
|
||||
0,
|
||||
it,
|
||||
requireActivity()
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
model.getTopRated().observe(viewLifecycleOwner) {
|
||||
|
|
|
@ -101,7 +101,7 @@ class MangaPageAdapter : RecyclerView.Adapter<MangaPageAdapter.MangaPageViewHold
|
|||
ContextCompat.startActivity(
|
||||
view.context,
|
||||
Intent(view.context, ProfileActivity::class.java)
|
||||
.putExtra("userId", Anilist.userid),null
|
||||
.putExtra("userId", Anilist.userid), null
|
||||
)
|
||||
false
|
||||
}
|
||||
|
@ -156,7 +156,8 @@ class MangaPageAdapter : RecyclerView.Adapter<MangaPageAdapter.MangaPageViewHold
|
|||
trendingBinding.trendingProgressBar.visibility = View.GONE
|
||||
trendingBinding.trendingViewPager.adapter = adaptor
|
||||
trendingBinding.trendingViewPager.offscreenPageLimit = 3
|
||||
trendingBinding.trendingViewPager.getChildAt(0).overScrollMode = RecyclerView.OVER_SCROLL_NEVER
|
||||
trendingBinding.trendingViewPager.getChildAt(0).overScrollMode =
|
||||
RecyclerView.OVER_SCROLL_NEVER
|
||||
trendingBinding.trendingViewPager.setPageTransformer(MediaPageTransformer())
|
||||
trendHandler = Handler(Looper.getMainLooper())
|
||||
trendRun = Runnable {
|
||||
|
@ -191,6 +192,7 @@ class MangaPageAdapter : RecyclerView.Adapter<MangaPageAdapter.MangaPageViewHold
|
|||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun updateTrendingManhwa(adaptor: MediaAdaptor) {
|
||||
binding.apply {
|
||||
init(
|
||||
|
@ -201,6 +203,7 @@ class MangaPageAdapter : RecyclerView.Adapter<MangaPageAdapter.MangaPageViewHold
|
|||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun updateNovel(adaptor: MediaAdaptor) {
|
||||
binding.apply {
|
||||
init(
|
||||
|
@ -212,6 +215,7 @@ class MangaPageAdapter : RecyclerView.Adapter<MangaPageAdapter.MangaPageViewHold
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
fun updateTopRated(adaptor: MediaAdaptor) {
|
||||
binding.apply {
|
||||
init(
|
||||
|
@ -222,6 +226,7 @@ class MangaPageAdapter : RecyclerView.Adapter<MangaPageAdapter.MangaPageViewHold
|
|||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun updateMostFav(adaptor: MediaAdaptor) {
|
||||
binding.apply {
|
||||
init(
|
||||
|
@ -234,7 +239,8 @@ class MangaPageAdapter : RecyclerView.Adapter<MangaPageAdapter.MangaPageViewHold
|
|||
mangaPopular.startAnimation(setSlideUp())
|
||||
}
|
||||
}
|
||||
fun init(adaptor: MediaAdaptor,recyclerView: RecyclerView, progress: View, title: View){
|
||||
|
||||
fun init(adaptor: MediaAdaptor, recyclerView: RecyclerView, progress: View, title: View) {
|
||||
progress.visibility = View.GONE
|
||||
recyclerView.adapter = adaptor
|
||||
recyclerView.layoutManager =
|
||||
|
|
|
@ -95,8 +95,10 @@ class AuthorActivity : AppCompatActivity() {
|
|||
|
||||
binding.charactersRecycler.visibility = View.VISIBLE
|
||||
binding.charactersText.visibility = View.VISIBLE
|
||||
binding.charactersRecycler.adapter = CharacterAdapter(author!!.character ?: arrayListOf())
|
||||
binding.charactersRecycler.layoutManager = LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false)
|
||||
binding.charactersRecycler.adapter =
|
||||
CharacterAdapter(author!!.character ?: arrayListOf())
|
||||
binding.charactersRecycler.layoutManager =
|
||||
LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false)
|
||||
if (author!!.character.isNullOrEmpty()) {
|
||||
binding.charactersRecycler.visibility = View.GONE
|
||||
binding.charactersText.visibility = View.GONE
|
||||
|
@ -108,7 +110,7 @@ class AuthorActivity : AppCompatActivity() {
|
|||
if (it) {
|
||||
scope.launch {
|
||||
if (author != null)
|
||||
withContext(Dispatchers.IO) { model.loadAuthor(author!!)}
|
||||
withContext(Dispatchers.IO) { model.loadAuthor(author!!) }
|
||||
live.postValue(false)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ class AuthorAdapter(
|
|||
return AuthorViewHolder(binding)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder:AuthorViewHolder, position: Int) {
|
||||
override fun onBindViewHolder(holder: AuthorViewHolder, position: Int) {
|
||||
val binding = holder.binding
|
||||
setAnimation(binding.root.context, holder.binding.root)
|
||||
val author = authorList[position]
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package ani.dantotsu.media
|
||||
|
||||
import ani.dantotsu.connections.anilist.api.FuzzyDate
|
||||
import ani.dantotsu.connections.anilist.api.Query
|
||||
import java.io.Serializable
|
||||
|
||||
data class Character(
|
||||
|
|
|
@ -95,7 +95,8 @@ class CharacterDetailsActivity : AppCompatActivity(), AppBarLayout.OnOffsetChang
|
|||
}
|
||||
lifecycleScope.launch {
|
||||
withContext(Dispatchers.IO) {
|
||||
character.isFav = Anilist.query.isUserFav(AnilistMutations.FavType.CHARACTER, character.id)
|
||||
character.isFav =
|
||||
Anilist.query.isUserFav(AnilistMutations.FavType.CHARACTER, character.id)
|
||||
}
|
||||
withContext(Dispatchers.Main) {
|
||||
binding.characterFav.setImageResource(
|
||||
|
|
|
@ -29,10 +29,16 @@ class CharacterDetailsAdapter(private val character: Character, private val acti
|
|||
"${currActivity()!!.getString(R.string.birthday)} ${character.dateOfBirth.toString()}" else "") +
|
||||
(if (character.gender != "null")
|
||||
currActivity()!!.getString(R.string.gender) + " " + when (character.gender) {
|
||||
currActivity()!!.getString(R.string.male) -> currActivity()!!.getString(R.string.male)
|
||||
currActivity()!!.getString(R.string.female) -> currActivity()!!.getString(R.string.female)
|
||||
else -> character.gender
|
||||
} else "") + "\n" + character.description
|
||||
currActivity()!!.getString(R.string.male) -> currActivity()!!.getString(
|
||||
R.string.male
|
||||
)
|
||||
|
||||
currActivity()!!.getString(R.string.female) -> currActivity()!!.getString(
|
||||
R.string.female
|
||||
)
|
||||
|
||||
else -> character.gender
|
||||
} else "") + "\n" + character.description
|
||||
|
||||
binding.characterDesc.isTextSelectable
|
||||
val markWon = Markwon.builder(activity).usePlugin(SoftBreakAddsNewLinePlugin.create())
|
||||
|
|
|
@ -100,7 +100,7 @@ data class Media(
|
|||
startDate = apiMedia.startDate,
|
||||
endDate = apiMedia.endDate,
|
||||
favourites = apiMedia.favourites,
|
||||
timeUntilAiring = apiMedia.nextAiringEpisode?.timeUntilAiring?.let { it.toLong() * 1000},
|
||||
timeUntilAiring = apiMedia.nextAiringEpisode?.timeUntilAiring?.let { it.toLong() * 1000 },
|
||||
anime = if (apiMedia.type == MediaType.ANIME) Anime(
|
||||
totalEpisodes = apiMedia.episodes,
|
||||
nextAiringEpisode = apiMedia.nextAiringEpisode?.episode?.minus(1)
|
||||
|
@ -115,7 +115,8 @@ data class Media(
|
|||
this.userScore = mediaList.score?.toInt() ?: 0
|
||||
this.userStatus = mediaList.status?.toString()
|
||||
this.userUpdatedAt = mediaList.updatedAt?.toLong()
|
||||
this.genres = mediaList.media?.genres?.toMutableList() as? ArrayList<String>? ?: arrayListOf()
|
||||
this.genres =
|
||||
mediaList.media?.genres?.toMutableList() as? ArrayList<String>? ?: arrayListOf()
|
||||
}
|
||||
|
||||
constructor(mediaEdge: MediaEdge) : this(mediaEdge.node!!) {
|
||||
|
|
|
@ -149,14 +149,22 @@ class MediaAdaptor(
|
|||
(if (media.userScore != 0) R.drawable.item_user_score else R.drawable.item_score)
|
||||
)
|
||||
if (media.anime != null) {
|
||||
val itemTotal = " " + if ((media.anime.totalEpisodes ?: 0) != 1) currActivity()!!.getString(R.string.episode_plural) else currActivity()!!.getString(R.string.episode_singular)
|
||||
val itemTotal = " " + if ((media.anime.totalEpisodes
|
||||
?: 0) != 1
|
||||
) currActivity()!!.getString(R.string.episode_plural) else currActivity()!!.getString(
|
||||
R.string.episode_singular
|
||||
)
|
||||
b.itemTotal.text = itemTotal
|
||||
b.itemCompactTotal.text =
|
||||
if (media.anime.nextAiringEpisode != null) (media.anime.nextAiringEpisode.toString() + " / " + (media.anime.totalEpisodes
|
||||
?: "??").toString()) else (media.anime.totalEpisodes
|
||||
?: "??").toString()
|
||||
} else if (media.manga != null) {
|
||||
val itemTotal = " " + if ((media.manga.totalChapters ?: 0) != 1) currActivity()!!.getString(R.string.chapter_plural) else currActivity()!!.getString(R.string.chapter_singular)
|
||||
val itemTotal = " " + if ((media.manga.totalChapters
|
||||
?: 0) != 1
|
||||
) currActivity()!!.getString(R.string.chapter_plural) else currActivity()!!.getString(
|
||||
R.string.chapter_singular
|
||||
)
|
||||
b.itemTotal.text = itemTotal
|
||||
b.itemCompactTotal.text = "${media.manga.totalChapters ?: "??"}"
|
||||
}
|
||||
|
@ -183,7 +191,10 @@ class MediaAdaptor(
|
|||
AccelerateDecelerateInterpolator()
|
||||
)
|
||||
)
|
||||
blurImage(if (bannerAnimations) b.itemCompactBanner else b.itemCompactBannerNoKen , media.banner ?: media.cover)
|
||||
blurImage(
|
||||
if (bannerAnimations) b.itemCompactBanner else b.itemCompactBannerNoKen,
|
||||
media.banner ?: media.cover
|
||||
)
|
||||
b.itemCompactOngoing.isVisible =
|
||||
media.status == currActivity()!!.getString(R.string.status_releasing)
|
||||
b.itemCompactTitle.text = media.userPreferredName
|
||||
|
@ -232,7 +243,10 @@ class MediaAdaptor(
|
|||
AccelerateDecelerateInterpolator()
|
||||
)
|
||||
)
|
||||
blurImage(if (bannerAnimations) b.itemCompactBanner else b.itemCompactBannerNoKen , media.banner ?: media.cover)
|
||||
blurImage(
|
||||
if (bannerAnimations) b.itemCompactBanner else b.itemCompactBannerNoKen,
|
||||
media.banner ?: media.cover
|
||||
)
|
||||
b.itemCompactOngoing.isVisible =
|
||||
media.status == currActivity()!!.getString(R.string.status_releasing)
|
||||
b.itemCompactTitle.text = media.userPreferredName
|
||||
|
|
|
@ -109,7 +109,9 @@ class MediaDetailsActivity : AppCompatActivity(), AppBarLayout.OnOffsetChangedLi
|
|||
// Ui init
|
||||
|
||||
initActivity(this)
|
||||
binding.mediaViewPager.updateLayoutParams<ViewGroup.MarginLayoutParams> { bottomMargin = navBarHeight }
|
||||
binding.mediaViewPager.updateLayoutParams<ViewGroup.MarginLayoutParams> {
|
||||
bottomMargin = navBarHeight
|
||||
}
|
||||
val oldMargin = binding.mediaViewPager.marginBottom
|
||||
AndroidBug5497Workaround.assistActivity(this) {
|
||||
if (it) {
|
||||
|
@ -125,9 +127,11 @@ class MediaDetailsActivity : AppCompatActivity(), AppBarLayout.OnOffsetChangedLi
|
|||
}
|
||||
}
|
||||
val navBarRightMargin = if (resources.configuration.orientation ==
|
||||
Configuration.ORIENTATION_LANDSCAPE) navBarHeight else 0
|
||||
Configuration.ORIENTATION_LANDSCAPE
|
||||
) navBarHeight else 0
|
||||
val navBarBottomMargin = if (resources.configuration.orientation ==
|
||||
Configuration.ORIENTATION_LANDSCAPE) 0 else navBarHeight
|
||||
Configuration.ORIENTATION_LANDSCAPE
|
||||
) 0 else navBarHeight
|
||||
navBar.updateLayoutParams<ViewGroup.MarginLayoutParams> {
|
||||
rightMargin = navBarRightMargin
|
||||
bottomMargin = navBarBottomMargin
|
||||
|
@ -345,7 +349,13 @@ class MediaDetailsActivity : AppCompatActivity(), AppBarLayout.OnOffsetChangedLi
|
|||
adult = media.isAdult
|
||||
if (media.anime != null) {
|
||||
viewPager.adapter =
|
||||
ViewPagerAdapter(supportFragmentManager, lifecycle, SupportedMedia.ANIME, media, intent.getIntExtra("commentId", -1))
|
||||
ViewPagerAdapter(
|
||||
supportFragmentManager,
|
||||
lifecycle,
|
||||
SupportedMedia.ANIME,
|
||||
media,
|
||||
intent.getIntExtra("commentId", -1)
|
||||
)
|
||||
} else if (media.manga != null) {
|
||||
viewPager.adapter = ViewPagerAdapter(
|
||||
supportFragmentManager,
|
||||
|
@ -368,7 +378,8 @@ class MediaDetailsActivity : AppCompatActivity(), AppBarLayout.OnOffsetChangedLi
|
|||
} else {
|
||||
navBar.createTab(R.drawable.ic_round_import_contacts_24, R.string.read, R.id.read)
|
||||
}
|
||||
val commentTab = navBar.createTab(R.drawable.ic_round_comment_24, R.string.comments, R.id.comment)
|
||||
val commentTab =
|
||||
navBar.createTab(R.drawable.ic_round_comment_24, R.string.comments, R.id.comment)
|
||||
navBar.addTab(infoTab)
|
||||
navBar.addTab(watchTab)
|
||||
navBar.addTab(commentTab)
|
||||
|
@ -412,10 +423,12 @@ class MediaDetailsActivity : AppCompatActivity(), AppBarLayout.OnOffsetChangedLi
|
|||
override fun onConfigurationChanged(newConfig: Configuration) {
|
||||
super.onConfigurationChanged(newConfig)
|
||||
val rightMargin = if (resources.configuration.orientation ==
|
||||
Configuration.ORIENTATION_LANDSCAPE) navBarHeight else 0
|
||||
Configuration.ORIENTATION_LANDSCAPE
|
||||
) navBarHeight else 0
|
||||
val bottomMargin = if (resources.configuration.orientation ==
|
||||
Configuration.ORIENTATION_LANDSCAPE) 0 else navBarHeight
|
||||
val params : ViewGroup.MarginLayoutParams =
|
||||
Configuration.ORIENTATION_LANDSCAPE
|
||||
) 0 else navBarHeight
|
||||
val params: ViewGroup.MarginLayoutParams =
|
||||
navBar.layoutParams as ViewGroup.MarginLayoutParams
|
||||
params.updateMargins(right = rightMargin, bottom = bottomMargin)
|
||||
}
|
||||
|
@ -448,6 +461,7 @@ class MediaDetailsActivity : AppCompatActivity(), AppBarLayout.OnOffsetChangedLi
|
|||
SupportedMedia.MANGA -> MangaReadFragment()
|
||||
SupportedMedia.NOVEL -> NovelReadFragment()
|
||||
}
|
||||
|
||||
2 -> {
|
||||
val fragment = CommentsFragment()
|
||||
val bundle = Bundle()
|
||||
|
|
|
@ -56,9 +56,11 @@ class MediaDetailsViewModel : ViewModel() {
|
|||
media.anime != null -> {
|
||||
AnimeSources.list.size - 1
|
||||
}
|
||||
|
||||
media.format == "MANGA" || media.format == "ONE_SHOT" -> {
|
||||
MangaSources.list.size - 1
|
||||
}
|
||||
|
||||
else -> {
|
||||
NovelSources.list.size - 1
|
||||
}
|
||||
|
|
|
@ -145,7 +145,8 @@ class MediaInfoFragment : Fragment() {
|
|||
}
|
||||
binding.mediaInfoDurationContainer.visibility = View.VISIBLE
|
||||
binding.mediaInfoSeasonContainer.visibility = View.VISIBLE
|
||||
val seasonInfo = "${(media.anime.season ?: "??")} ${(media.anime.seasonYear ?: "??")}"
|
||||
val seasonInfo =
|
||||
"${(media.anime.season ?: "??")} ${(media.anime.seasonYear ?: "??")}"
|
||||
binding.mediaInfoSeason.text = seasonInfo
|
||||
|
||||
if (media.anime.mainStudio != null) {
|
||||
|
@ -182,9 +183,9 @@ class MediaInfoFragment : Fragment() {
|
|||
}
|
||||
binding.mediaInfoTotalTitle.setText(R.string.total_eps)
|
||||
val infoTotal = if (media.anime.nextAiringEpisode != null)
|
||||
"${media.anime.nextAiringEpisode} | ${media.anime.totalEpisodes ?: "~"}"
|
||||
"${media.anime.nextAiringEpisode} | ${media.anime.totalEpisodes ?: "~"}"
|
||||
else
|
||||
(media.anime.totalEpisodes ?: "~").toString()
|
||||
(media.anime.totalEpisodes ?: "~").toString()
|
||||
binding.mediaInfoTotal.text = infoTotal
|
||||
|
||||
} else if (media.manga != null) {
|
||||
|
@ -213,7 +214,8 @@ class MediaInfoFragment : Fragment() {
|
|||
(media.description ?: "null").replace("\\n", "<br>").replace("\\\"", "\""),
|
||||
HtmlCompat.FROM_HTML_MODE_LEGACY
|
||||
)
|
||||
val infoDesc = tripleTab + if (desc.toString() != "null") desc else getString(R.string.no_description_available)
|
||||
val infoDesc =
|
||||
tripleTab + if (desc.toString() != "null") desc else getString(R.string.no_description_available)
|
||||
binding.mediaInfoDescription.text = infoDesc
|
||||
|
||||
binding.mediaInfoDescription.setOnClickListener {
|
||||
|
@ -570,7 +572,7 @@ class MediaInfoFragment : Fragment() {
|
|||
parent.addView(root)
|
||||
}
|
||||
}
|
||||
if(!media.users.isNullOrEmpty() && !offline){
|
||||
if (!media.users.isNullOrEmpty() && !offline) {
|
||||
ItemTitleRecyclerBinding.inflate(
|
||||
LayoutInflater.from(context),
|
||||
parent,
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
package ani.dantotsu.media
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
|
|
|
@ -4,7 +4,7 @@ interface Type {
|
|||
fun asText(): String
|
||||
}
|
||||
|
||||
enum class MediaType: Type {
|
||||
enum class MediaType : Type {
|
||||
ANIME,
|
||||
MANGA,
|
||||
NOVEL;
|
||||
|
@ -18,18 +18,20 @@ enum class MediaType: Type {
|
|||
}
|
||||
|
||||
companion object {
|
||||
fun fromText(string : String): MediaType? {
|
||||
fun fromText(string: String): MediaType? {
|
||||
return when (string) {
|
||||
"Anime" -> ANIME
|
||||
"Manga" -> MANGA
|
||||
"Novel" -> NOVEL
|
||||
else -> { null }
|
||||
else -> {
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum class AddonType: Type {
|
||||
enum class AddonType : Type {
|
||||
TORRENT,
|
||||
DOWNLOAD;
|
||||
|
||||
|
@ -41,11 +43,13 @@ enum class AddonType: Type {
|
|||
}
|
||||
|
||||
companion object {
|
||||
fun fromText(string : String): AddonType? {
|
||||
fun fromText(string: String): AddonType? {
|
||||
return when (string) {
|
||||
"Torrent" -> TORRENT
|
||||
"Download" -> DOWNLOAD
|
||||
else -> { null }
|
||||
else -> {
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -78,8 +78,10 @@ class SearchActivity : AppCompatActivity() {
|
|||
source = intent.getStringExtra("source"),
|
||||
countryOfOrigin = intent.getStringExtra("country"),
|
||||
season = intent.getStringExtra("season"),
|
||||
seasonYear = if (intent.getStringExtra("type") == "ANIME") intent.getStringExtra("seasonYear")?.toIntOrNull() else null,
|
||||
startYear = if (intent.getStringExtra("type") == "MANGA") intent.getStringExtra("seasonYear")?.toIntOrNull() else null,
|
||||
seasonYear = if (intent.getStringExtra("type") == "ANIME") intent.getStringExtra("seasonYear")
|
||||
?.toIntOrNull() else null,
|
||||
startYear = if (intent.getStringExtra("type") == "MANGA") intent.getStringExtra("seasonYear")
|
||||
?.toIntOrNull() else null,
|
||||
results = mutableListOf(),
|
||||
hasNextPage = false
|
||||
)
|
||||
|
|
|
@ -13,7 +13,6 @@ import android.view.animation.AlphaAnimation
|
|||
import android.view.animation.Animation
|
||||
import android.view.inputmethod.EditorInfo
|
||||
import android.view.inputmethod.InputMethodManager
|
||||
import android.widget.ImageView
|
||||
import android.widget.PopupMenu
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.appcompat.content.res.AppCompatResources
|
||||
|
@ -60,6 +59,7 @@ class SearchAdapter(private val activity: SearchActivity, private val type: Stri
|
|||
}
|
||||
binding.filterTextView.setCompoundDrawablesWithIntrinsicBounds(filterDrawable, 0, 0, 0)
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SearchHeaderViewHolder {
|
||||
val binding =
|
||||
ItemSearchHeaderBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||
|
@ -129,36 +129,42 @@ class SearchAdapter(private val activity: SearchActivity, private val type: Stri
|
|||
activity.search()
|
||||
updateFilterTextViewDrawable()
|
||||
}
|
||||
|
||||
R.id.sort_by_popular -> {
|
||||
activity.result.sort = Anilist.sortBy[1]
|
||||
activity.updateChips.invoke()
|
||||
activity.search()
|
||||
updateFilterTextViewDrawable()
|
||||
}
|
||||
|
||||
R.id.sort_by_trending -> {
|
||||
activity.result.sort = Anilist.sortBy[2]
|
||||
activity.updateChips.invoke()
|
||||
activity.search()
|
||||
updateFilterTextViewDrawable()
|
||||
}
|
||||
|
||||
R.id.sort_by_recent -> {
|
||||
activity.result.sort = Anilist.sortBy[3]
|
||||
activity.updateChips.invoke()
|
||||
activity.search()
|
||||
updateFilterTextViewDrawable()
|
||||
}
|
||||
|
||||
R.id.sort_by_a_z -> {
|
||||
activity.result.sort = Anilist.sortBy[4]
|
||||
activity.updateChips.invoke()
|
||||
activity.search()
|
||||
updateFilterTextViewDrawable()
|
||||
}
|
||||
|
||||
R.id.sort_by_z_a -> {
|
||||
activity.result.sort = Anilist.sortBy[5]
|
||||
activity.updateChips.invoke()
|
||||
activity.search()
|
||||
updateFilterTextViewDrawable()
|
||||
}
|
||||
|
||||
R.id.sort_by_pure_pain -> {
|
||||
activity.result.sort = Anilist.sortBy[6]
|
||||
activity.updateChips.invoke()
|
||||
|
@ -325,7 +331,10 @@ class SearchAdapter(private val activity: SearchActivity, private val type: Stri
|
|||
}
|
||||
|
||||
|
||||
class SearchChipAdapter(val activity: SearchActivity, private val searchAdapter: SearchAdapter) :
|
||||
class SearchChipAdapter(
|
||||
val activity: SearchActivity,
|
||||
private val searchAdapter: SearchAdapter
|
||||
) :
|
||||
RecyclerView.Adapter<SearchChipAdapter.SearchChipViewHolder>() {
|
||||
private var chips = activity.result.toChipList()
|
||||
|
||||
|
|
|
@ -105,7 +105,8 @@ class SearchFilterBottomDialog : BottomSheetDialogFragment() {
|
|||
setSortByFilterImage()
|
||||
|
||||
binding.resetSearchFilter.setOnClickListener {
|
||||
val rotateAnimation = ObjectAnimator.ofFloat(binding.resetSearchFilter, "rotation", 180f, 540f)
|
||||
val rotateAnimation =
|
||||
ObjectAnimator.ofFloat(binding.resetSearchFilter, "rotation", 180f, 540f)
|
||||
rotateAnimation.duration = 500
|
||||
rotateAnimation.interpolator = AccelerateDecelerateInterpolator()
|
||||
rotateAnimation.start()
|
||||
|
@ -113,7 +114,8 @@ class SearchFilterBottomDialog : BottomSheetDialogFragment() {
|
|||
}
|
||||
|
||||
binding.resetSearchFilter.setOnLongClickListener {
|
||||
val rotateAnimation = ObjectAnimator.ofFloat(binding.resetSearchFilter, "rotation", 180f, 540f)
|
||||
val rotateAnimation =
|
||||
ObjectAnimator.ofFloat(binding.resetSearchFilter, "rotation", 180f, 540f)
|
||||
rotateAnimation.duration = 500
|
||||
rotateAnimation.interpolator = AccelerateDecelerateInterpolator()
|
||||
rotateAnimation.start()
|
||||
|
@ -125,8 +127,10 @@ class SearchFilterBottomDialog : BottomSheetDialogFragment() {
|
|||
|
||||
CoroutineScope(Dispatchers.Main).launch {
|
||||
activity.result.apply {
|
||||
status = binding.searchStatus.text.toString().replace(" ", "_").ifBlank { null }
|
||||
source = binding.searchSource.text.toString().replace(" ", "_").ifBlank { null }
|
||||
status =
|
||||
binding.searchStatus.text.toString().replace(" ", "_").ifBlank { null }
|
||||
source =
|
||||
binding.searchSource.text.toString().replace(" ", "_").ifBlank { null }
|
||||
format = binding.searchFormat.text.toString().ifBlank { null }
|
||||
season = binding.searchSeason.text.toString().ifBlank { null }
|
||||
startYear = binding.searchYear.text.toString().toIntOrNull()
|
||||
|
@ -206,21 +210,25 @@ class SearchFilterBottomDialog : BottomSheetDialogFragment() {
|
|||
binding.countryFilter.setImageResource(R.drawable.ic_round_globe_search_googlefonts)
|
||||
startBounceZoomAnimation(binding.countryFilter)
|
||||
}
|
||||
|
||||
R.id.country_china -> {
|
||||
activity.result.countryOfOrigin = "CN"
|
||||
binding.countryFilter.setImageResource(R.drawable.ic_round_globe_china_googlefonts)
|
||||
startBounceZoomAnimation(binding.countryFilter)
|
||||
}
|
||||
|
||||
R.id.country_south_korea -> {
|
||||
activity.result.countryOfOrigin = "KR"
|
||||
binding.countryFilter.setImageResource(R.drawable.ic_round_globe_south_korea_googlefonts)
|
||||
startBounceZoomAnimation(binding.countryFilter)
|
||||
}
|
||||
|
||||
R.id.country_japan -> {
|
||||
activity.result.countryOfOrigin = "JP"
|
||||
binding.countryFilter.setImageResource(R.drawable.ic_round_globe_japan_googlefonts)
|
||||
startBounceZoomAnimation(binding.countryFilter)
|
||||
}
|
||||
|
||||
R.id.country_taiwan -> {
|
||||
activity.result.countryOfOrigin = "TW"
|
||||
binding.countryFilter.setImageResource(R.drawable.ic_round_globe_taiwan_googlefonts)
|
||||
|
@ -257,7 +265,8 @@ class SearchFilterBottomDialog : BottomSheetDialogFragment() {
|
|||
binding.searchFilterCancel.setOnClickListener {
|
||||
dismiss()
|
||||
}
|
||||
val format = if (activity.result.type == "ANIME") Anilist.animeStatus else Anilist.mangaStatus
|
||||
val format =
|
||||
if (activity.result.type == "ANIME") Anilist.animeStatus else Anilist.mangaStatus
|
||||
binding.searchStatus.setText(activity.result.status?.replace("_", " "))
|
||||
binding.searchStatus.setAdapter(
|
||||
ArrayAdapter(
|
||||
|
|
|
@ -12,7 +12,6 @@ import kotlinx.coroutines.withContext
|
|||
import okhttp3.Request
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import java.io.File
|
||||
|
||||
class SubtitleDownloader {
|
||||
|
||||
|
|
|
@ -330,6 +330,7 @@ class AnimeWatchAdapter(
|
|||
0
|
||||
)
|
||||
}
|
||||
|
||||
val chipText = "${names[limit * (position)]} - ${names[last - 1]}"
|
||||
chip.text = chipText
|
||||
chip.setTextColor(
|
||||
|
@ -412,10 +413,12 @@ class AnimeWatchAdapter(
|
|||
if (ep.filler) binding.itemEpisodeFillerView.visibility = View.VISIBLE
|
||||
|
||||
binding.animeSourceContinueText.text =
|
||||
currActivity()!!.getString(R.string.continue_episode, ep.number, if (ep.filler)
|
||||
currActivity()!!.getString(R.string.filler_tag)
|
||||
else
|
||||
"", cleanedTitle)
|
||||
currActivity()!!.getString(
|
||||
R.string.continue_episode, ep.number, if (ep.filler)
|
||||
currActivity()!!.getString(R.string.filler_tag)
|
||||
else
|
||||
"", cleanedTitle
|
||||
)
|
||||
binding.animeSourceContinue.setOnClickListener {
|
||||
fragment.onEpisodeClick(continueEp)
|
||||
}
|
||||
|
@ -441,11 +444,14 @@ class AnimeWatchAdapter(
|
|||
if (!sourceFound && PrefManager.getVal(PrefName.SearchSources) && autoSelect) {
|
||||
if (binding.animeSource.adapter.count > media.selected!!.sourceIndex + 1) {
|
||||
val nextIndex = media.selected!!.sourceIndex + 1
|
||||
binding.animeSource.setText(binding.animeSource.adapter
|
||||
.getItem(nextIndex).toString(), false)
|
||||
binding.animeSource.setText(
|
||||
binding.animeSource.adapter
|
||||
.getItem(nextIndex).toString(), false
|
||||
)
|
||||
fragment.onSourceChange(nextIndex).apply {
|
||||
binding.animeSourceTitle.text = showUserText
|
||||
showUserTextListener = { MainScope().launch { binding.animeSourceTitle.text = it } }
|
||||
showUserTextListener =
|
||||
{ MainScope().launch { binding.animeSourceTitle.text = it } }
|
||||
binding.animeSourceDubbed.isChecked = selectDub
|
||||
binding.animeSourceDubbedCont.isVisible = isDubAvailableSeparately()
|
||||
setLanguageList(0, nextIndex)
|
||||
|
|
|
@ -199,7 +199,8 @@ class AnimeWatchFragment : Fragment() {
|
|||
ConcatAdapter(headerAdapter, episodeAdapter)
|
||||
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
val offline = !isOnline(binding.root.context) || PrefManager.getVal(PrefName.OfflineMode)
|
||||
val offline =
|
||||
!isOnline(binding.root.context) || PrefManager.getVal(PrefName.OfflineMode)
|
||||
if (offline) {
|
||||
media.selected!!.sourceIndex = model.watchSources!!.list.lastIndex
|
||||
} else {
|
||||
|
|
|
@ -486,12 +486,14 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
|
|||
}
|
||||
rotation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE
|
||||
}
|
||||
|
||||
in 225..315 -> {
|
||||
if (rotation != ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) {
|
||||
exoRotate.visibility = View.VISIBLE
|
||||
}
|
||||
rotation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
|
||||
}
|
||||
|
||||
in 315..360, in 0..45 -> {
|
||||
if (rotation != ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) {
|
||||
exoRotate.visibility = View.VISIBLE
|
||||
|
@ -1396,7 +1398,8 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
|
|||
subClick()
|
||||
}
|
||||
}
|
||||
val sub: MutableList<MediaItem.SubtitleConfiguration> = emptyList<MediaItem.SubtitleConfiguration>().toMutableList()
|
||||
val sub: MutableList<MediaItem.SubtitleConfiguration> =
|
||||
emptyList<MediaItem.SubtitleConfiguration>().toMutableList()
|
||||
ext.subtitles.forEach { subtitle ->
|
||||
val subtitleUrl = if (!hasExtSubtitles) video!!.file.url else subtitle.file.url
|
||||
//var localFile: String? = null
|
||||
|
@ -1865,7 +1868,10 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
|
|||
exoPlayer.seekTo((new.interval.endTime * 1000).toLong())
|
||||
skippedTimeStamps.add(new)
|
||||
}
|
||||
if (PrefManager.getVal(PrefName.AutoSkipRecap) && new.skipType == "recap" && !skippedTimeStamps.contains(new)) {
|
||||
if (PrefManager.getVal(PrefName.AutoSkipRecap) && new.skipType == "recap" && !skippedTimeStamps.contains(
|
||||
new
|
||||
)
|
||||
) {
|
||||
exoPlayer.seekTo((new.interval.endTime * 1000).toLong())
|
||||
skippedTimeStamps.add(new)
|
||||
}
|
||||
|
@ -1910,12 +1916,15 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
|
|||
val audioTracks: ArrayList<Tracks.Group> = arrayListOf()
|
||||
val subTracks: ArrayList<Tracks.Group> = arrayListOf(dummyTrack)
|
||||
tracks.groups.forEach {
|
||||
println("Track__: $it\nTrack__: ${it.length}\nTrack__: ${it.isSelected}\n" +
|
||||
"Track__: ${it.type}\nTrack__: ${it.mediaTrackGroup.id}")
|
||||
println(
|
||||
"Track__: $it\nTrack__: ${it.length}\nTrack__: ${it.isSelected}\n" +
|
||||
"Track__: ${it.type}\nTrack__: ${it.mediaTrackGroup.id}"
|
||||
)
|
||||
when (it.type) {
|
||||
TRACK_TYPE_AUDIO -> {
|
||||
if (it.isSupported(true)) audioTracks.add(it)
|
||||
}
|
||||
|
||||
TRACK_TYPE_TEXT -> {
|
||||
if (!hasExtSubtitles) {
|
||||
if (it.isSupported(true)) subTracks.add(it)
|
||||
|
@ -1951,7 +1960,8 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
|
|||
onSetTrackGroupOverride(dummyTrack, TRACK_TYPE_TEXT)
|
||||
}
|
||||
}
|
||||
else -> { }
|
||||
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1966,6 +1976,7 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
|
|||
isPlayerPlaying = true
|
||||
sourceClick()
|
||||
}
|
||||
|
||||
else -> {
|
||||
toast("Player Error ${error.errorCode} (${error.errorCodeName}) : ${error.message}")
|
||||
Injekt.get<CrashlyticsInterface>().logException(error)
|
||||
|
|
|
@ -24,6 +24,7 @@ import androidx.recyclerview.widget.LinearLayoutManager
|
|||
import androidx.recyclerview.widget.RecyclerView
|
||||
import ani.dantotsu.BottomSheetDialogFragment
|
||||
import ani.dantotsu.R
|
||||
import ani.dantotsu.addons.torrent.TorrentAddonManager
|
||||
import ani.dantotsu.connections.crashlytics.CrashlyticsInterface
|
||||
import ani.dantotsu.copyToClipboard
|
||||
import ani.dantotsu.currActivity
|
||||
|
@ -32,7 +33,6 @@ import ani.dantotsu.databinding.ItemStreamBinding
|
|||
import ani.dantotsu.databinding.ItemUrlBinding
|
||||
import ani.dantotsu.download.DownloadedType
|
||||
import ani.dantotsu.download.video.Helper
|
||||
import ani.dantotsu.addons.torrent.TorrentAddonManager
|
||||
import ani.dantotsu.hideSystemBars
|
||||
import ani.dantotsu.media.Media
|
||||
import ani.dantotsu.media.MediaDetailsViewModel
|
||||
|
@ -233,11 +233,12 @@ class SelectorDialogFragment : BottomSheetDialogFragment() {
|
|||
}
|
||||
|
||||
private val externalPlayerResult = registerForActivityResult(
|
||||
ActivityResultContracts.StartActivityForResult()) { result: ActivityResult ->
|
||||
ActivityResultContracts.StartActivityForResult()
|
||||
) { result: ActivityResult ->
|
||||
Logger.log(result.data.toString())
|
||||
}
|
||||
|
||||
private fun exportMagnetIntent(episode: Episode, video: Video) : Intent {
|
||||
private fun exportMagnetIntent(episode: Episode, video: Video): Intent {
|
||||
val amnis = "com.amnis"
|
||||
return Intent(Intent.ACTION_VIEW).apply {
|
||||
component = ComponentName(amnis, "$amnis.gui.player.PlayerActivity")
|
||||
|
@ -445,7 +446,11 @@ class SelectorDialogFragment : BottomSheetDialogFragment() {
|
|||
SubtitleDownloader.downloadSubtitle(
|
||||
requireContext(),
|
||||
subtitleToDownload!!.file.url,
|
||||
DownloadedType(media!!.mainName(), media!!.anime!!.episodes!![media!!.anime!!.selectedEpisode!!]!!.number, MediaType.ANIME)
|
||||
DownloadedType(
|
||||
media!!.mainName(),
|
||||
media!!.anime!!.episodes!![media!!.anime!!.selectedEpisode!!]!!.number,
|
||||
MediaType.ANIME
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -477,7 +482,7 @@ class SelectorDialogFragment : BottomSheetDialogFragment() {
|
|||
if (extractor.videos.size > episode.selectedVideo) extractor.videos[episode.selectedVideo] else null
|
||||
val subtitleNames = subtitles.map { it.language }
|
||||
var subtitleToDownload: Subtitle? = null
|
||||
val activity = currActivity()?:requireActivity()
|
||||
val activity = currActivity() ?: requireActivity()
|
||||
if (subtitles.isNotEmpty()) {
|
||||
val alertDialog = AlertDialog.Builder(context, R.style.MyPopup)
|
||||
.setTitle("Download Subtitle")
|
||||
|
@ -551,9 +556,13 @@ class SelectorDialogFragment : BottomSheetDialogFragment() {
|
|||
if (video.format == VideoType.CONTAINER) {
|
||||
binding.urlSize.isVisible = video.size != null
|
||||
// if video size is null or 0, show "Unknown Size" else show the size in MB
|
||||
val sizeText = getString(R.string.mb_size, "${if (video.extraNote != null) " : " else ""}${
|
||||
if (video.size == 0.0) getString(R.string.size_unknown) else DecimalFormat("#.##").format(video.size ?: 0)
|
||||
}")
|
||||
val sizeText = getString(
|
||||
R.string.mb_size, "${if (video.extraNote != null) " : " else ""}${
|
||||
if (video.size == 0.0) getString(R.string.size_unknown) else DecimalFormat("#.##").format(
|
||||
video.size ?: 0
|
||||
)
|
||||
}"
|
||||
)
|
||||
binding.urlSize.text = sizeText
|
||||
}
|
||||
binding.urlNote.visibility = View.VISIBLE
|
||||
|
|
|
@ -67,7 +67,11 @@ class SubtitleDialogFragment : BottomSheetDialogFragment() {
|
|||
binding.subtitleTitle.setText(R.string.none)
|
||||
model.getMedia().observe(viewLifecycleOwner) { media ->
|
||||
val mediaID: Int = media.id
|
||||
val selSubs = PrefManager.getNullableCustomVal("subLang_${mediaID}", null, String::class.java)
|
||||
val selSubs = PrefManager.getNullableCustomVal(
|
||||
"subLang_${mediaID}",
|
||||
null,
|
||||
String::class.java
|
||||
)
|
||||
if (episode.selectedSubtitle != null && selSubs != "None") {
|
||||
binding.root.setCardBackgroundColor(TRANSPARENT)
|
||||
}
|
||||
|
@ -107,7 +111,11 @@ class SubtitleDialogFragment : BottomSheetDialogFragment() {
|
|||
model.getMedia().observe(viewLifecycleOwner) { media ->
|
||||
val mediaID: Int = media.id
|
||||
val selSubs: String? =
|
||||
PrefManager.getNullableCustomVal("subLang_${mediaID}", null, String::class.java)
|
||||
PrefManager.getNullableCustomVal(
|
||||
"subLang_${mediaID}",
|
||||
null,
|
||||
String::class.java
|
||||
)
|
||||
if (episode.selectedSubtitle != position - 1 && selSubs != subtitles[position - 1].language) {
|
||||
binding.root.setCardBackgroundColor(TRANSPARENT)
|
||||
}
|
||||
|
|
|
@ -5,7 +5,6 @@ import android.view.LayoutInflater
|
|||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.annotation.OptIn
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.media3.common.C.TRACK_TYPE_AUDIO
|
||||
import androidx.media3.common.C.TrackType
|
||||
import androidx.media3.common.Tracks
|
||||
|
@ -20,7 +19,7 @@ import java.util.Locale
|
|||
|
||||
@OptIn(UnstableApi::class)
|
||||
class TrackGroupDialogFragment(
|
||||
instance: ExoplayerView, trackGroups: ArrayList<Tracks.Group>, type : @TrackType Int
|
||||
instance: ExoplayerView, trackGroups: ArrayList<Tracks.Group>, type: @TrackType Int
|
||||
) : BottomSheetDialogFragment() {
|
||||
private var _binding: BottomSheetSubtitlesBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
|
@ -70,21 +69,28 @@ class TrackGroupDialogFragment(
|
|||
trackGroups[position].let { trackGroup ->
|
||||
when (val language = trackGroup.getTrackFormat(0).language?.lowercase()) {
|
||||
null -> {
|
||||
binding.subtitleTitle.text = getString(R.string.unknown_track, "Track $position")
|
||||
binding.subtitleTitle.text =
|
||||
getString(R.string.unknown_track, "Track $position")
|
||||
}
|
||||
|
||||
"none" -> {
|
||||
binding.subtitleTitle.text = getString(R.string.disabled_track)
|
||||
}
|
||||
|
||||
else -> {
|
||||
val locale = if (language.contains("-")) {
|
||||
val parts = language.split("-")
|
||||
try {
|
||||
Locale(parts[0], parts[1])
|
||||
} catch (ignored: Exception) { null }
|
||||
} catch (ignored: Exception) {
|
||||
null
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
Locale(language)
|
||||
} catch (ignored: Exception) { null }
|
||||
} catch (ignored: Exception) {
|
||||
null
|
||||
}
|
||||
}
|
||||
binding.subtitleTitle.text = locale?.let {
|
||||
"[${it.language}] ${it.displayName}"
|
||||
|
|
|
@ -60,7 +60,8 @@ class CommentItem(
|
|||
override fun bind(viewBinding: ItemCommentsBinding, position: Int) {
|
||||
binding = viewBinding
|
||||
setAnimation(binding.root.context, binding.root)
|
||||
viewBinding.commentRepliesList.layoutManager = LinearLayoutManager(commentsFragment.activity)
|
||||
viewBinding.commentRepliesList.layoutManager =
|
||||
LinearLayoutManager(commentsFragment.activity)
|
||||
viewBinding.commentRepliesList.adapter = adapter
|
||||
val isUserComment = CommentsAPI.userId == comment.userId
|
||||
val levelColor = getAvatarColor(comment.totalVotes, backgroundColor)
|
||||
|
@ -112,16 +113,20 @@ class CommentItem(
|
|||
|
||||
viewBinding.commentUserName.setOnClickListener {
|
||||
ContextCompat.startActivity(
|
||||
commentsFragment.activity, Intent(commentsFragment.activity, ProfileActivity::class.java)
|
||||
commentsFragment.activity,
|
||||
Intent(commentsFragment.activity, ProfileActivity::class.java)
|
||||
.putExtra("userId", comment.userId.toInt())
|
||||
.putExtra("userLVL","[${levelColor.second}]"), null
|
||||
.putExtra("userLVL", "[${levelColor.second}]"),
|
||||
null
|
||||
)
|
||||
}
|
||||
viewBinding.commentUserAvatar.setOnClickListener {
|
||||
ContextCompat.startActivity(
|
||||
commentsFragment.activity, Intent(commentsFragment.activity, ProfileActivity::class.java)
|
||||
commentsFragment.activity,
|
||||
Intent(commentsFragment.activity, ProfileActivity::class.java)
|
||||
.putExtra("userId", comment.userId.toInt())
|
||||
.putExtra("userLVL","[${levelColor.second}]"), null
|
||||
.putExtra("userLVL", "[${levelColor.second}]"),
|
||||
null
|
||||
)
|
||||
}
|
||||
viewBinding.commentText.setOnLongClickListener {
|
||||
|
@ -143,8 +148,10 @@ class CommentItem(
|
|||
viewBinding.commentInfo.setOnClickListener {
|
||||
val popup = PopupMenu(commentsFragment.requireContext(), viewBinding.commentInfo)
|
||||
popup.menuInflater.inflate(R.menu.profile_details_menu, popup.menu)
|
||||
popup.menu.findItem(R.id.commentDelete)?.isVisible = isUserComment || CommentsAPI.isAdmin || CommentsAPI.isMod
|
||||
popup.menu.findItem(R.id.commentBanUser)?.isVisible = (CommentsAPI.isAdmin || CommentsAPI.isMod) && !isUserComment
|
||||
popup.menu.findItem(R.id.commentDelete)?.isVisible =
|
||||
isUserComment || CommentsAPI.isAdmin || CommentsAPI.isMod
|
||||
popup.menu.findItem(R.id.commentBanUser)?.isVisible =
|
||||
(CommentsAPI.isAdmin || CommentsAPI.isMod) && !isUserComment
|
||||
popup.menu.findItem(R.id.commentReport)?.isVisible = !isUserComment
|
||||
popup.setOnMenuItemClickListener { item ->
|
||||
when (item.itemId) {
|
||||
|
@ -273,12 +280,16 @@ class CommentItem(
|
|||
}
|
||||
|
||||
fun replying(isReplying: Boolean) {
|
||||
binding.commentReply.text = if (isReplying) commentsFragment.activity.getString(R.string.cancel) else "Reply"
|
||||
binding.commentReply.text =
|
||||
if (isReplying) commentsFragment.activity.getString(R.string.cancel) else "Reply"
|
||||
this.isReplying = isReplying
|
||||
}
|
||||
|
||||
fun editing(isEditing: Boolean) {
|
||||
binding.commentEdit.text = if (isEditing) commentsFragment.activity.getString(R.string.cancel) else commentsFragment.activity.getString(R.string.edit)
|
||||
binding.commentEdit.text =
|
||||
if (isEditing) commentsFragment.activity.getString(R.string.cancel) else commentsFragment.activity.getString(
|
||||
R.string.edit
|
||||
)
|
||||
this.isEditing = isEditing
|
||||
}
|
||||
|
||||
|
@ -286,7 +297,7 @@ class CommentItem(
|
|||
subCommentIds.add(id)
|
||||
}
|
||||
|
||||
private fun removeSubCommentIds(){
|
||||
private fun removeSubCommentIds() {
|
||||
subCommentIds.forEach { id ->
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val parentComments = parentSection.groups as? List<CommentItem> ?: emptyList()
|
||||
|
@ -306,11 +317,13 @@ class CommentItem(
|
|||
viewBinding.commentUpVote.alpha = 1f
|
||||
viewBinding.commentDownVote.setImageResource(R.drawable.ic_round_upvote_inactive_24)
|
||||
}
|
||||
|
||||
-1 -> {
|
||||
viewBinding.commentUpVote.setImageResource(R.drawable.ic_round_upvote_inactive_24)
|
||||
viewBinding.commentDownVote.setImageResource(R.drawable.ic_round_upvote_active_24)
|
||||
viewBinding.commentDownVote.alpha = 1f
|
||||
}
|
||||
|
||||
else -> {
|
||||
viewBinding.commentUpVote.setImageResource(R.drawable.ic_round_upvote_inactive_24)
|
||||
viewBinding.commentDownVote.setImageResource(R.drawable.ic_round_upvote_inactive_24)
|
||||
|
@ -355,7 +368,8 @@ class CommentItem(
|
|||
|
||||
private fun getAvatarColor(voteCount: Int, backgroundColor: Int): Pair<Int, Int> {
|
||||
val level = if (voteCount < 0) 0 else sqrt(abs(voteCount.toDouble()) / 0.8).toInt()
|
||||
val colorString = if (level > usernameColors.size - 1) usernameColors[usernameColors.size - 1] else usernameColors[level]
|
||||
val colorString =
|
||||
if (level > usernameColors.size - 1) usernameColors[usernameColors.size - 1] else usernameColors[level]
|
||||
var color = Color.parseColor(colorString)
|
||||
val ratio = getContrastRatio(color, backgroundColor)
|
||||
if (ratio < 4.5) {
|
||||
|
@ -373,16 +387,17 @@ class CommentItem(
|
|||
* @param callback the callback to call when the user clicks yes
|
||||
*/
|
||||
private fun dialogBuilder(title: String, message: String, callback: () -> Unit) {
|
||||
val alertDialog = android.app.AlertDialog.Builder(commentsFragment.activity, R.style.MyPopup)
|
||||
.setTitle(title)
|
||||
.setMessage(message)
|
||||
.setPositiveButton("Yes") { dialog, _ ->
|
||||
callback()
|
||||
dialog.dismiss()
|
||||
}
|
||||
.setNegativeButton("No") { dialog, _ ->
|
||||
dialog.dismiss()
|
||||
}
|
||||
val alertDialog =
|
||||
android.app.AlertDialog.Builder(commentsFragment.activity, R.style.MyPopup)
|
||||
.setTitle(title)
|
||||
.setMessage(message)
|
||||
.setPositiveButton("Yes") { dialog, _ ->
|
||||
callback()
|
||||
dialog.dismiss()
|
||||
}
|
||||
.setNegativeButton("No") { dialog, _ ->
|
||||
dialog.dismiss()
|
||||
}
|
||||
val dialog = alertDialog.show()
|
||||
dialog?.window?.setDimAmount(0.8f)
|
||||
}
|
||||
|
|
|
@ -75,7 +75,10 @@ class CommentsFragment : Fragment() {
|
|||
super.onViewCreated(view, savedInstanceState)
|
||||
activity = requireActivity() as MediaDetailsActivity
|
||||
|
||||
binding.commentsListContainer.setBaseline(activity.navBar, activity.binding.commentInputLayout)
|
||||
binding.commentsListContainer.setBaseline(
|
||||
activity.navBar,
|
||||
activity.binding.commentInputLayout
|
||||
)
|
||||
|
||||
//get the media id from the intent
|
||||
val mediaId = arguments?.getInt("mediaId") ?: -1
|
||||
|
@ -301,7 +304,7 @@ class CommentsFragment : Fragment() {
|
|||
|
||||
activity.binding.commentLabel.setOnClickListener {
|
||||
//alert dialog to enter a number, with a cancel and ok button
|
||||
val alertDialog = android.app.AlertDialog.Builder(activity, R.style.MyPopup)
|
||||
val alertDialog = AlertDialog.Builder(activity, R.style.MyPopup)
|
||||
.setTitle("Enter a chapter/episode number tag")
|
||||
.setView(R.layout.dialog_edittext)
|
||||
.setPositiveButton("OK") { dialog, _ ->
|
||||
|
@ -577,7 +580,7 @@ class CommentsFragment : Fragment() {
|
|||
* Called when the user tries to comment for the first time
|
||||
*/
|
||||
private fun showCommentRulesDialog() {
|
||||
val alertDialog = android.app.AlertDialog.Builder(activity, R.style.MyPopup)
|
||||
val alertDialog = AlertDialog.Builder(activity, R.style.MyPopup)
|
||||
.setTitle("Commenting Rules")
|
||||
.setMessage(
|
||||
"I WILL BAN YOU WITHOUT HESITATION\n" +
|
||||
|
|
|
@ -343,6 +343,7 @@ class MangaChapterAdapter(
|
|||
fun updateType(t: Int) {
|
||||
type = t
|
||||
}
|
||||
|
||||
private fun formatDate(timestamp: Long?): String {
|
||||
timestamp ?: return "" // Return empty string if timestamp is null
|
||||
|
||||
|
@ -366,6 +367,7 @@ class MangaChapterAdapter(
|
|||
else -> "Just now"
|
||||
}
|
||||
}
|
||||
|
||||
1L -> "1 day ago"
|
||||
in 2..6 -> "$daysDifference days ago"
|
||||
else -> SimpleDateFormat("dd MMM yyyy", Locale.getDefault()).format(targetDate)
|
||||
|
|
|
@ -229,7 +229,7 @@ class MangaReadAdapter(
|
|||
refresh = true
|
||||
val intent = Intent(fragment.requireContext(), CookieCatcher::class.java)
|
||||
.putExtra("url", url)
|
||||
ContextCompat.startActivity(fragment.requireContext(), intent, null)
|
||||
startActivity(fragment.requireContext(), intent, null)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -258,8 +258,10 @@ class MangaReadAdapter(
|
|||
dialogBinding.animeScanlatorContainer.isVisible = options.count() > 1
|
||||
dialogBinding.scanlatorNo.text = "${options.count()}"
|
||||
dialogBinding.animeScanlatorTop.setOnClickListener {
|
||||
val dialogView2 = LayoutInflater.from(currContext()).inflate(R.layout.custom_dialog_layout, null)
|
||||
val checkboxContainer = dialogView2.findViewById<LinearLayout>(R.id.checkboxContainer)
|
||||
val dialogView2 =
|
||||
LayoutInflater.from(currContext()).inflate(R.layout.custom_dialog_layout, null)
|
||||
val checkboxContainer =
|
||||
dialogView2.findViewById<LinearLayout>(R.id.checkboxContainer)
|
||||
val tickAllButton = dialogView2.findViewById<ImageButton>(R.id.toggleButton)
|
||||
|
||||
// Function to get the right image resource for the toggle button
|
||||
|
@ -441,7 +443,11 @@ class MangaReadAdapter(
|
|||
if (media.manga?.chapters != null) {
|
||||
val chapters = media.manga.chapters!!.keys.toTypedArray()
|
||||
val anilistEp = (media.userProgress ?: 0).plus(1)
|
||||
val appEp = PrefManager.getNullableCustomVal("${media.id}_current_chp", null, String::class.java)
|
||||
val appEp = PrefManager.getNullableCustomVal(
|
||||
"${media.id}_current_chp",
|
||||
null,
|
||||
String::class.java
|
||||
)
|
||||
?.toIntOrNull() ?: 1
|
||||
var continueEp = (if (anilistEp > appEp) anilistEp else appEp).toString()
|
||||
val filteredChapters = chapters.filter { chapterKey ->
|
||||
|
@ -470,7 +476,11 @@ class MangaReadAdapter(
|
|||
val ep = media.manga.chapters!![continueEp]!!
|
||||
binding.itemEpisodeImage.loadImage(media.banner ?: media.cover)
|
||||
binding.animeSourceContinueText.text =
|
||||
currActivity()!!.getString(R.string.continue_chapter, ep.number, if (!ep.title.isNullOrEmpty()) ep.title else "")
|
||||
currActivity()!!.getString(
|
||||
R.string.continue_chapter,
|
||||
ep.number,
|
||||
if (!ep.title.isNullOrEmpty()) ep.title else ""
|
||||
)
|
||||
binding.animeSourceContinue.setOnClickListener {
|
||||
fragment.onMangaChapterClick(continueEp)
|
||||
}
|
||||
|
@ -491,11 +501,14 @@ class MangaReadAdapter(
|
|||
if (!sourceFound && PrefManager.getVal(PrefName.SearchSources)) {
|
||||
if (binding.animeSource.adapter.count > media.selected!!.sourceIndex + 1) {
|
||||
val nextIndex = media.selected!!.sourceIndex + 1
|
||||
binding.animeSource.setText(binding.animeSource.adapter
|
||||
.getItem(nextIndex).toString(), false)
|
||||
binding.animeSource.setText(
|
||||
binding.animeSource.adapter
|
||||
.getItem(nextIndex).toString(), false
|
||||
)
|
||||
fragment.onSourceChange(nextIndex).apply {
|
||||
binding.animeSourceTitle.text = showUserText
|
||||
showUserTextListener = { MainScope().launch { binding.animeSourceTitle.text = it } }
|
||||
showUserTextListener =
|
||||
{ MainScope().launch { binding.animeSourceTitle.text = it } }
|
||||
setLanguageList(0, nextIndex)
|
||||
}
|
||||
subscribeButton(false)
|
||||
|
|
|
@ -42,8 +42,8 @@ import ani.dantotsu.isOnline
|
|||
import ani.dantotsu.media.Media
|
||||
import ani.dantotsu.media.MediaDetailsActivity
|
||||
import ani.dantotsu.media.MediaDetailsViewModel
|
||||
import ani.dantotsu.media.MediaType
|
||||
import ani.dantotsu.media.MediaNameAdapter
|
||||
import ani.dantotsu.media.MediaType
|
||||
import ani.dantotsu.media.manga.mangareader.ChapterLoaderDialog
|
||||
import ani.dantotsu.navBarHeight
|
||||
import ani.dantotsu.notifications.subscription.SubscriptionHelper
|
||||
|
@ -203,8 +203,10 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
|
|||
ConcatAdapter(headerAdapter, chapterAdapter)
|
||||
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
val offline = !isOnline(binding.root.context) || PrefManager.getVal(PrefName.OfflineMode)
|
||||
if (offline) media.selected!!.sourceIndex = model.mangaReadSources!!.list.lastIndex
|
||||
val offline =
|
||||
!isOnline(binding.root.context) || PrefManager.getVal(PrefName.OfflineMode)
|
||||
if (offline) media.selected!!.sourceIndex =
|
||||
model.mangaReadSources!!.list.lastIndex
|
||||
model.loadMangaChapters(media, media.selected!!.sourceIndex)
|
||||
}
|
||||
loaded = true
|
||||
|
|
|
@ -42,7 +42,8 @@ abstract class BaseImageAdapter(
|
|||
|
||||
override fun onAttachedToRecyclerView(recyclerView: RecyclerView) {
|
||||
images = if (settings.layout == CurrentReaderSettings.Layouts.PAGED
|
||||
&& settings.direction == CurrentReaderSettings.Directions.BOTTOM_TO_TOP) {
|
||||
&& settings.direction == CurrentReaderSettings.Directions.BOTTOM_TO_TOP
|
||||
) {
|
||||
chapterImages.reversed()
|
||||
} else {
|
||||
chapterImages
|
||||
|
|
|
@ -56,8 +56,8 @@ import ani.dantotsu.isOnline
|
|||
import ani.dantotsu.logError
|
||||
import ani.dantotsu.media.Media
|
||||
import ani.dantotsu.media.MediaDetailsViewModel
|
||||
import ani.dantotsu.media.MediaSingleton
|
||||
import ani.dantotsu.media.MediaNameAdapter
|
||||
import ani.dantotsu.media.MediaSingleton
|
||||
import ani.dantotsu.media.manga.MangaCache
|
||||
import ani.dantotsu.media.manga.MangaChapter
|
||||
import ani.dantotsu.others.ImageViewDialog
|
||||
|
@ -129,10 +129,12 @@ class MangaReaderActivity : AppCompatActivity() {
|
|||
var sliding = false
|
||||
var isAnimating = false
|
||||
|
||||
private val directionRLBT get() = defaultSettings.direction == RIGHT_TO_LEFT
|
||||
|| defaultSettings.direction == BOTTOM_TO_TOP
|
||||
private val directionPagedBT get() = defaultSettings.layout == CurrentReaderSettings.Layouts.PAGED
|
||||
&& defaultSettings.direction == CurrentReaderSettings.Directions.BOTTOM_TO_TOP
|
||||
private val directionRLBT
|
||||
get() = defaultSettings.direction == RIGHT_TO_LEFT
|
||||
|| defaultSettings.direction == BOTTOM_TO_TOP
|
||||
private val directionPagedBT
|
||||
get() = defaultSettings.layout == CurrentReaderSettings.Layouts.PAGED
|
||||
&& defaultSettings.direction == CurrentReaderSettings.Directions.BOTTOM_TO_TOP
|
||||
|
||||
override fun onAttachedToWindow() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P && !PrefManager.getVal<Boolean>(PrefName.ShowSystemBars)) {
|
||||
|
@ -229,7 +231,7 @@ class MangaReaderActivity : AppCompatActivity() {
|
|||
binding.mangaReaderRecycler.scrollToPosition((value.toInt() - 1) / (dualPage { 2 }
|
||||
?: 1))
|
||||
else
|
||||
if (defaultSettings.direction == CurrentReaderSettings.Directions.BOTTOM_TO_TOP ) {
|
||||
if (defaultSettings.direction == CurrentReaderSettings.Directions.BOTTOM_TO_TOP) {
|
||||
binding.mangaReaderPager.currentItem =
|
||||
(maxChapterPage.toInt() - value.toInt()) / (dualPage { 2 } ?: 1)
|
||||
} else {
|
||||
|
@ -345,7 +347,11 @@ class MangaReaderActivity : AppCompatActivity() {
|
|||
if (currentChapterIndex > 0) change(currentChapterIndex - 1)
|
||||
else snackString(getString(R.string.first_chapter))
|
||||
} else {
|
||||
if (chaptersArr.size > currentChapterIndex + 1) progress { change(currentChapterIndex + 1) }
|
||||
if (chaptersArr.size > currentChapterIndex + 1) progress {
|
||||
change(
|
||||
currentChapterIndex + 1
|
||||
)
|
||||
}
|
||||
else snackString(getString(R.string.next_chapter_not_found))
|
||||
}
|
||||
}
|
||||
|
@ -355,7 +361,11 @@ class MangaReaderActivity : AppCompatActivity() {
|
|||
}
|
||||
binding.mangaReaderPreviousChapter.setOnClickListener {
|
||||
if (directionRLBT) {
|
||||
if (chaptersArr.size > currentChapterIndex + 1) progress { change(currentChapterIndex + 1) }
|
||||
if (chaptersArr.size > currentChapterIndex + 1) progress {
|
||||
change(
|
||||
currentChapterIndex + 1
|
||||
)
|
||||
}
|
||||
else snackString(getString(R.string.next_chapter_not_found))
|
||||
} else {
|
||||
if (currentChapterIndex > 0) change(currentChapterIndex - 1)
|
||||
|
@ -372,11 +382,15 @@ class MangaReaderActivity : AppCompatActivity() {
|
|||
currentChapterIndex = chaptersArr.indexOf(chap.number)
|
||||
binding.mangaReaderChapterSelect.setSelection(currentChapterIndex)
|
||||
if (directionRLBT) {
|
||||
binding.mangaReaderNextChap.text = chaptersTitleArr.getOrNull(currentChapterIndex - 1) ?: ""
|
||||
binding.mangaReaderPrevChap.text = chaptersTitleArr.getOrNull(currentChapterIndex + 1) ?: ""
|
||||
binding.mangaReaderNextChap.text =
|
||||
chaptersTitleArr.getOrNull(currentChapterIndex - 1) ?: ""
|
||||
binding.mangaReaderPrevChap.text =
|
||||
chaptersTitleArr.getOrNull(currentChapterIndex + 1) ?: ""
|
||||
} else {
|
||||
binding.mangaReaderNextChap.text = chaptersTitleArr.getOrNull(currentChapterIndex + 1) ?: ""
|
||||
binding.mangaReaderPrevChap.text = chaptersTitleArr.getOrNull(currentChapterIndex - 1) ?: ""
|
||||
binding.mangaReaderNextChap.text =
|
||||
chaptersTitleArr.getOrNull(currentChapterIndex + 1) ?: ""
|
||||
binding.mangaReaderPrevChap.text =
|
||||
chaptersTitleArr.getOrNull(currentChapterIndex - 1) ?: ""
|
||||
}
|
||||
applySettings()
|
||||
val context = this
|
||||
|
@ -389,10 +403,12 @@ class MangaReaderActivity : AppCompatActivity() {
|
|||
"nothing" -> mutableListOf(
|
||||
RPC.Link(getString(R.string.view_manga), media.shareLink ?: ""),
|
||||
)
|
||||
|
||||
"dantotsu" -> mutableListOf(
|
||||
RPC.Link(getString(R.string.view_manga), media.shareLink ?: ""),
|
||||
RPC.Link("Read on Dantotsu", getString(R.string.dantotsu))
|
||||
)
|
||||
|
||||
"anilist" -> {
|
||||
val userId = PrefManager.getVal<String>(PrefName.AnilistUserId)
|
||||
val anilistLink = "https://anilist.co/user/$userId/"
|
||||
|
@ -401,6 +417,7 @@ class MangaReaderActivity : AppCompatActivity() {
|
|||
RPC.Link("View My AniList", anilistLink)
|
||||
)
|
||||
}
|
||||
|
||||
else -> mutableListOf()
|
||||
}
|
||||
val presence = RPC.createPresence(
|
||||
|
@ -411,7 +428,12 @@ class MangaReaderActivity : AppCompatActivity() {
|
|||
details = chap.title?.takeIf { it.isNotEmpty() }
|
||||
?: getString(R.string.chapter_num, chap.number),
|
||||
state = "${chap.number}/${media.manga?.totalChapters ?: "??"}",
|
||||
largeImage = media.cover?.let { cover -> RPC.Link(media.userPreferredName, cover) },
|
||||
largeImage = media.cover?.let { cover ->
|
||||
RPC.Link(
|
||||
media.userPreferredName,
|
||||
cover
|
||||
)
|
||||
},
|
||||
buttons = buttons
|
||||
)
|
||||
)
|
||||
|
@ -918,7 +940,12 @@ class MangaReaderActivity : AppCompatActivity() {
|
|||
isAnimating = true
|
||||
ObjectAnimator.ofFloat(binding.mangaReaderCont, "alpha", 1f, 0f)
|
||||
.setDuration(controllerDuration).start()
|
||||
ObjectAnimator.ofFloat(binding.mangaReaderBottomLayout, "translationY", 0f, 128f)
|
||||
ObjectAnimator.ofFloat(
|
||||
binding.mangaReaderBottomLayout,
|
||||
"translationY",
|
||||
0f,
|
||||
128f
|
||||
)
|
||||
.apply { interpolator = overshoot;duration = controllerDuration;start() }
|
||||
ObjectAnimator.ofFloat(binding.mangaReaderTopLayout, "translationY", 0f, -128f)
|
||||
.apply { interpolator = overshoot;duration = controllerDuration;start() }
|
||||
|
|
|
@ -113,7 +113,12 @@ class NovelReadFragment : Fragment(),
|
|||
) {
|
||||
try {
|
||||
val directory =
|
||||
DownloadsManager.getSubDirectory(context?:currContext()!!, MediaType.NOVEL, false, novel.name)
|
||||
DownloadsManager.getSubDirectory(
|
||||
context ?: currContext()!!,
|
||||
MediaType.NOVEL,
|
||||
false,
|
||||
novel.name
|
||||
)
|
||||
val file = directory?.findFile(novel.name)
|
||||
if (file?.exists() == false) return false
|
||||
val fileUri = file?.uri ?: return false
|
||||
|
|
|
@ -181,7 +181,7 @@ class NovelResponseAdapter(
|
|||
if (position != -1) {
|
||||
list[position].extra?.remove("0")
|
||||
list[position].extra?.set("0", "Downloading: $progress%")
|
||||
Logger.log( "updateDownloadProgress: $progress, position: $position")
|
||||
Logger.log("updateDownloadProgress: $progress, position: $position")
|
||||
notifyItemChanged(position)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -292,7 +292,11 @@ class NovelReaderActivity : AppCompatActivity(), EbookReaderEventListener {
|
|||
applySettings()
|
||||
}
|
||||
|
||||
val cfi = PrefManager.getNullableCustomVal("${sanitizedBookId}_progress", null, String::class.java)
|
||||
val cfi = PrefManager.getNullableCustomVal(
|
||||
"${sanitizedBookId}_progress",
|
||||
null,
|
||||
String::class.java
|
||||
)
|
||||
|
||||
cfi?.let { binding.bookReader.goto(it) }
|
||||
binding.progress.visibility = View.GONE
|
||||
|
|
|
@ -70,8 +70,10 @@ class ListActivity : AppCompatActivity() {
|
|||
setContentView(binding.root)
|
||||
|
||||
val anime = intent.getBooleanExtra("anime", true)
|
||||
binding.listTitle.text = getString(R.string.user_list, intent.getStringExtra("username"),
|
||||
if (anime) getString(R.string.anime) else getString(R.string.manga))
|
||||
binding.listTitle.text = getString(
|
||||
R.string.user_list, intent.getStringExtra("username"),
|
||||
if (anime) getString(R.string.anime) else getString(R.string.manga)
|
||||
)
|
||||
binding.listTabLayout.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
|
||||
override fun onTabSelected(tab: TabLayout.Tab?) {
|
||||
this@ListActivity.selectedTabIdx = tab?.position ?: 0
|
||||
|
@ -158,7 +160,8 @@ class ListActivity : AppCompatActivity() {
|
|||
}
|
||||
|
||||
binding.filter.setOnClickListener {
|
||||
val genres = PrefManager.getVal<Set<String>>(PrefName.GenresList).toMutableSet().sorted()
|
||||
val genres =
|
||||
PrefManager.getVal<Set<String>>(PrefName.GenresList).toMutableSet().sorted()
|
||||
val popup = PopupMenu(this, it)
|
||||
popup.menu.add("All")
|
||||
genres.forEach { genre ->
|
||||
|
|
|
@ -5,7 +5,10 @@ import android.graphics.Rect
|
|||
import android.view.View
|
||||
import android.widget.FrameLayout
|
||||
|
||||
class AndroidBug5497Workaround private constructor(activity: Activity, private val callback: (Boolean) -> Unit) {
|
||||
class AndroidBug5497Workaround private constructor(
|
||||
activity: Activity,
|
||||
private val callback: (Boolean) -> Unit
|
||||
) {
|
||||
private val mChildOfContent: View
|
||||
private var usableHeightPrevious = 0
|
||||
private val frameLayoutParams: FrameLayout.LayoutParams
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package ani.dantotsu.others
|
||||
|
||||
import android.app.DownloadManager
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
|
@ -8,7 +7,6 @@ import android.content.pm.PackageManager
|
|||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.os.Environment
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.content.ContextCompat
|
||||
import ani.dantotsu.FileUrl
|
||||
import ani.dantotsu.R
|
||||
|
@ -19,9 +17,6 @@ import ani.dantotsu.parsers.Book
|
|||
import ani.dantotsu.settings.saving.PrefManager
|
||||
import ani.dantotsu.settings.saving.PrefName
|
||||
import ani.dantotsu.toast
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import java.io.File
|
||||
|
||||
object Download {
|
||||
|
|
|
@ -2,10 +2,10 @@ package ani.dantotsu.others
|
|||
|
||||
import ani.dantotsu.FileUrl
|
||||
import ani.dantotsu.client
|
||||
import ani.dantotsu.util.Logger
|
||||
import ani.dantotsu.media.Media
|
||||
import ani.dantotsu.media.anime.Episode
|
||||
import ani.dantotsu.tryWithSuspend
|
||||
import ani.dantotsu.util.Logger
|
||||
import com.google.gson.Gson
|
||||
import com.lagradost.nicehttp.NiceResponse
|
||||
import kotlinx.serialization.SerialName
|
||||
|
|
|
@ -56,9 +56,10 @@ class OutlineTextView : AppCompatTextView {
|
|||
setStrokeWidth(strokeWidth)
|
||||
}
|
||||
|
||||
private val Float.toPx get() = TypedValue.applyDimension(
|
||||
TypedValue.COMPLEX_UNIT_DIP, this, Resources.getSystem().displayMetrics
|
||||
)
|
||||
private val Float.toPx
|
||||
get() = TypedValue.applyDimension(
|
||||
TypedValue.COMPLEX_UNIT_DIP, this, Resources.getSystem().displayMetrics
|
||||
)
|
||||
|
||||
private fun setStrokeWidth(width: Float) {
|
||||
strokeWidth = width.toPx
|
||||
|
|
|
@ -50,7 +50,7 @@ class Xpandable @JvmOverloads constructor(
|
|||
}
|
||||
}
|
||||
postDelayed({
|
||||
listeners.forEach{
|
||||
listeners.forEach {
|
||||
it.onRetract()
|
||||
}
|
||||
}, 300)
|
||||
|
@ -66,7 +66,7 @@ class Xpandable @JvmOverloads constructor(
|
|||
}
|
||||
}
|
||||
postDelayed({
|
||||
listeners.forEach{
|
||||
listeners.forEach {
|
||||
it.onExpand()
|
||||
}
|
||||
}, 300)
|
||||
|
|
|
@ -24,7 +24,8 @@ class CookieCatcher : AppCompatActivity() {
|
|||
|
||||
//get url from intent
|
||||
val url = intent.getStringExtra("url") ?: getString(R.string.cursed_yt)
|
||||
val headers: Map<String, String> = intent.getSerializableExtraCompat("headers") as? Map<String, String> ?: emptyMap()
|
||||
val headers: Map<String, String> =
|
||||
intent.getSerializableExtraCompat("headers") as? Map<String, String> ?: emptyMap()
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
||||
val process = Application.getProcessName()
|
||||
|
|
|
@ -5,8 +5,8 @@ import ani.dantotsu.currContext
|
|||
import ani.dantotsu.download.DownloadsManager
|
||||
import ani.dantotsu.download.DownloadsManager.Companion.getSubDirectory
|
||||
import ani.dantotsu.download.anime.AnimeDownloaderService.AnimeDownloadTask.Companion.getTaskName
|
||||
import ani.dantotsu.media.MediaType
|
||||
import ani.dantotsu.media.MediaNameAdapter
|
||||
import ani.dantotsu.media.MediaType
|
||||
import ani.dantotsu.tryWithSuspend
|
||||
import ani.dantotsu.util.Logger
|
||||
import eu.kanade.tachiyomi.animesource.model.SAnime
|
||||
|
@ -43,7 +43,7 @@ class OfflineAnimeParser : AnimeParser() {
|
|||
if (it.isDirectory) {
|
||||
val episode = Episode(
|
||||
it.name!!,
|
||||
getTaskName(animeLink,it.name!!),
|
||||
getTaskName(animeLink, it.name!!),
|
||||
it.name,
|
||||
null,
|
||||
null,
|
||||
|
|
|
@ -28,7 +28,7 @@ class OfflineNovelParser : NovelParser() {
|
|||
directory.listFiles().forEach {
|
||||
if (it.isDirectory) {
|
||||
val chapter = Book(
|
||||
it.name?:"Unknown",
|
||||
it.name ?: "Unknown",
|
||||
it.uri.toString(),
|
||||
null,
|
||||
listOf(it.uri.toString())
|
||||
|
@ -63,7 +63,7 @@ class OfflineNovelParser : NovelParser() {
|
|||
if (directory?.exists() == true) {
|
||||
directory.listFiles().forEach {
|
||||
if (it.isDirectory) {
|
||||
names.add(it.name?: "Unknown")
|
||||
names.add(it.name ?: "Unknown")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -62,55 +62,57 @@ internal class NovelExtensionInstaller(private val context: Context) {
|
|||
* @param url The url of the apk.
|
||||
* @param extension The extension to install.
|
||||
*/
|
||||
fun downloadAndInstall(url: String, extension: NovelExtension): Observable<InstallStep> = Observable.defer {
|
||||
val pkgName = extension.pkgName
|
||||
fun downloadAndInstall(url: String, extension: NovelExtension): Observable<InstallStep> =
|
||||
Observable.defer {
|
||||
val pkgName = extension.pkgName
|
||||
|
||||
val oldDownload = activeDownloads[pkgName]
|
||||
if (oldDownload != null) {
|
||||
deleteDownload(pkgName)
|
||||
}
|
||||
|
||||
val sourcePath = context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS)?.absolutePath
|
||||
//if the file is already downloaded, remove it
|
||||
val fileToDelete = File("$sourcePath/${url.toUri().lastPathSegment}")
|
||||
if (fileToDelete.exists()) {
|
||||
if (fileToDelete.delete()) {
|
||||
Logger.log("APK file deleted successfully.")
|
||||
} else {
|
||||
Logger.log("Failed to delete APK file.")
|
||||
val oldDownload = activeDownloads[pkgName]
|
||||
if (oldDownload != null) {
|
||||
deleteDownload(pkgName)
|
||||
}
|
||||
} else {
|
||||
Logger.log("APK file not found.")
|
||||
|
||||
val sourcePath =
|
||||
context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS)?.absolutePath
|
||||
//if the file is already downloaded, remove it
|
||||
val fileToDelete = File("$sourcePath/${url.toUri().lastPathSegment}")
|
||||
if (fileToDelete.exists()) {
|
||||
if (fileToDelete.delete()) {
|
||||
Logger.log("APK file deleted successfully.")
|
||||
} else {
|
||||
Logger.log("Failed to delete APK file.")
|
||||
}
|
||||
} else {
|
||||
Logger.log("APK file not found.")
|
||||
}
|
||||
|
||||
// Register the receiver after removing (and unregistering) the previous download
|
||||
downloadReceiver.register()
|
||||
|
||||
val downloadUri = url.toUri()
|
||||
val request = DownloadManager.Request(downloadUri)
|
||||
.setTitle(extension.name)
|
||||
.setMimeType(APK_MIME)
|
||||
.setDestinationInExternalFilesDir(
|
||||
context,
|
||||
Environment.DIRECTORY_DOWNLOADS,
|
||||
downloadUri.lastPathSegment
|
||||
)
|
||||
.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
|
||||
val id = downloadManager.enqueue(request)
|
||||
activeDownloads[pkgName] = id
|
||||
|
||||
downloadsRelay.filter { it.first == id }
|
||||
.map { it.second }
|
||||
// Poll download status
|
||||
.mergeWith(pollStatus(id))
|
||||
// Stop when the application is installed or errors
|
||||
.takeUntil { it.isCompleted() }
|
||||
// Always notify on main thread
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
// Always remove the download when unsubscribed
|
||||
.doOnUnsubscribe { deleteDownload(pkgName) }
|
||||
}
|
||||
|
||||
// Register the receiver after removing (and unregistering) the previous download
|
||||
downloadReceiver.register()
|
||||
|
||||
val downloadUri = url.toUri()
|
||||
val request = DownloadManager.Request(downloadUri)
|
||||
.setTitle(extension.name)
|
||||
.setMimeType(APK_MIME)
|
||||
.setDestinationInExternalFilesDir(
|
||||
context,
|
||||
Environment.DIRECTORY_DOWNLOADS,
|
||||
downloadUri.lastPathSegment
|
||||
)
|
||||
.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
|
||||
val id = downloadManager.enqueue(request)
|
||||
activeDownloads[pkgName] = id
|
||||
|
||||
downloadsRelay.filter { it.first == id }
|
||||
.map { it.second }
|
||||
// Poll download status
|
||||
.mergeWith(pollStatus(id))
|
||||
// Stop when the application is installed or errors
|
||||
.takeUntil { it.isCompleted() }
|
||||
// Always notify on main thread
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
// Always remove the download when unsubscribed
|
||||
.doOnUnsubscribe { deleteDownload(pkgName) }
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an observable that polls the given download id for its status every second, as the
|
||||
* manager doesn't have any notification system. It'll stop once the download finishes.
|
||||
|
|
|
@ -15,7 +15,8 @@ import com.xwray.groupie.viewbinding.GroupieViewHolder
|
|||
class ChartItem(
|
||||
private val title: String,
|
||||
private val aaOptions: AAOptions,
|
||||
private val activity: ProfileActivity): BindableItem<ItemChartBinding>() {
|
||||
private val activity: ProfileActivity
|
||||
) : BindableItem<ItemChartBinding>() {
|
||||
private lateinit var binding: ItemChartBinding
|
||||
override fun bind(viewBinding: ItemChartBinding, position: Int) {
|
||||
binding = viewBinding
|
||||
|
@ -78,6 +79,7 @@ class ChartItem(
|
|||
viewHolder.setIsRecyclable(false)
|
||||
super.bind(viewHolder, position, payloads, onItemClickListener, onItemLongClickListener)
|
||||
}
|
||||
|
||||
override fun getViewType(): Int {
|
||||
return 0
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ import kotlinx.coroutines.launch
|
|||
import kotlinx.coroutines.withContext
|
||||
|
||||
|
||||
class FollowActivity : AppCompatActivity(){
|
||||
class FollowActivity : AppCompatActivity() {
|
||||
private lateinit var binding: ActivityFollowBinding
|
||||
val adapter = GroupieAdapter()
|
||||
var users: List<User>? = null
|
||||
|
@ -37,7 +37,9 @@ class FollowActivity : AppCompatActivity(){
|
|||
initActivity(this)
|
||||
binding = ActivityFollowBinding.inflate(layoutInflater)
|
||||
binding.listToolbar.updateLayoutParams<MarginLayoutParams> { topMargin = statusBarHeight }
|
||||
binding.listFrameLayout.updateLayoutParams<MarginLayoutParams> { bottomMargin = navBarHeight }
|
||||
binding.listFrameLayout.updateLayoutParams<MarginLayoutParams> {
|
||||
bottomMargin = navBarHeight
|
||||
}
|
||||
setContentView(binding.root)
|
||||
val layoutType = PrefManager.getVal<Int>(PrefName.FollowerLayout)
|
||||
selected = getSelected(layoutType)
|
||||
|
@ -54,7 +56,7 @@ class FollowActivity : AppCompatActivity(){
|
|||
binding.listBack.setOnClickListener { finish() }
|
||||
|
||||
val title = intent.getStringExtra("title")
|
||||
val userID= intent.getIntExtra("userId", 0)
|
||||
val userID = intent.getIntExtra("userId", 0)
|
||||
binding.listTitle.text = title
|
||||
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
|
@ -93,9 +95,20 @@ class FollowActivity : AppCompatActivity(){
|
|||
}
|
||||
users?.forEach { user ->
|
||||
if (getLayoutType(selected) == 0) {
|
||||
adapter.add(FollowerItem(user.id, user.name ?: "Unknown", user.avatar?.medium, user.bannerImage ?: user.avatar?.medium ) { onUserClick(it) })
|
||||
adapter.add(
|
||||
FollowerItem(
|
||||
user.id,
|
||||
user.name ?: "Unknown",
|
||||
user.avatar?.medium,
|
||||
user.bannerImage ?: user.avatar?.medium
|
||||
) { onUserClick(it) })
|
||||
} else {
|
||||
adapter.add(GridFollowerItem(user.id, user.name ?: "Unknown", user.avatar?.medium) { onUserClick(it) })
|
||||
adapter.add(
|
||||
GridFollowerItem(
|
||||
user.id,
|
||||
user.name ?: "Unknown",
|
||||
user.avatar?.medium
|
||||
) { onUserClick(it) })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ class FollowerItem(
|
|||
private val avatar: String?,
|
||||
private val banner: String?,
|
||||
val clickCallback: (Int) -> Unit
|
||||
): BindableItem<ItemFollowerBinding>() {
|
||||
) : BindableItem<ItemFollowerBinding>() {
|
||||
private lateinit var binding: ItemFollowerBinding
|
||||
|
||||
override fun bind(viewBinding: ItemFollowerBinding, position: Int) {
|
||||
|
|
|
@ -6,12 +6,12 @@ import ani.dantotsu.databinding.ItemFollowerGridBinding
|
|||
import ani.dantotsu.loadImage
|
||||
import com.xwray.groupie.viewbinding.BindableItem
|
||||
|
||||
class GridFollowerItem (
|
||||
class GridFollowerItem(
|
||||
private val id: Int,
|
||||
private val name: String,
|
||||
private val avatar: String?,
|
||||
val clickCallback: (Int) -> Unit
|
||||
): BindableItem<ItemFollowerGridBinding>() {
|
||||
) : BindableItem<ItemFollowerGridBinding>() {
|
||||
private lateinit var binding: ItemFollowerGridBinding
|
||||
|
||||
override fun bind(viewBinding: ItemFollowerGridBinding, position: Int) {
|
||||
|
|
|
@ -59,9 +59,11 @@ class ProfileActivity : AppCompatActivity(), AppBarLayout.OnOffsetChangedListene
|
|||
screenWidth = resources.displayMetrics.widthPixels.toFloat()
|
||||
navBar = binding.profileNavBar
|
||||
val navBarRightMargin = if (resources.configuration.orientation ==
|
||||
Configuration.ORIENTATION_LANDSCAPE) navBarHeight else 0
|
||||
Configuration.ORIENTATION_LANDSCAPE
|
||||
) navBarHeight else 0
|
||||
val navBarBottomMargin = if (resources.configuration.orientation ==
|
||||
Configuration.ORIENTATION_LANDSCAPE) 0 else navBarHeight
|
||||
Configuration.ORIENTATION_LANDSCAPE
|
||||
) 0 else navBarHeight
|
||||
navBar.updateLayoutParams<ViewGroup.MarginLayoutParams> {
|
||||
rightMargin = navBarRightMargin
|
||||
bottomMargin = navBarBottomMargin
|
||||
|
@ -284,7 +286,7 @@ class ProfileActivity : AppCompatActivity(), AppBarLayout.OnOffsetChangedListene
|
|||
if (mMaxScrollSize == 0) mMaxScrollSize = appBar.totalScrollRange
|
||||
val percentage = abs(i) * 100 / mMaxScrollSize
|
||||
|
||||
with (bindingProfileAppBar) {
|
||||
with(bindingProfileAppBar) {
|
||||
profileUserAvatarContainer.visibility =
|
||||
if (profileUserAvatarContainer.scaleX == 0f) View.GONE else View.VISIBLE
|
||||
val duration = (200 * (PrefManager.getVal(PrefName.AnimationSpeed) as Float)).toLong()
|
||||
|
@ -315,10 +317,12 @@ class ProfileActivity : AppCompatActivity(), AppBarLayout.OnOffsetChangedListene
|
|||
override fun onConfigurationChanged(newConfig: Configuration) {
|
||||
super.onConfigurationChanged(newConfig)
|
||||
val rightMargin = if (resources.configuration.orientation ==
|
||||
Configuration.ORIENTATION_LANDSCAPE) navBarHeight else 0
|
||||
Configuration.ORIENTATION_LANDSCAPE
|
||||
) navBarHeight else 0
|
||||
val bottomMargin = if (resources.configuration.orientation ==
|
||||
Configuration.ORIENTATION_LANDSCAPE) 0 else navBarHeight
|
||||
val params : ViewGroup.MarginLayoutParams =
|
||||
Configuration.ORIENTATION_LANDSCAPE
|
||||
) 0 else navBarHeight
|
||||
val params: ViewGroup.MarginLayoutParams =
|
||||
navBar.layoutParams as ViewGroup.MarginLayoutParams
|
||||
params.updateMargins(right = rightMargin, bottom = bottomMargin)
|
||||
}
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
package ani.dantotsu.profile
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.util.TypedValue
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
|
@ -22,19 +20,16 @@ import ani.dantotsu.R
|
|||
import ani.dantotsu.connections.anilist.ProfileViewModel
|
||||
import ani.dantotsu.connections.anilist.api.Query
|
||||
import ani.dantotsu.databinding.FragmentProfileBinding
|
||||
import ani.dantotsu.loadImage
|
||||
import ani.dantotsu.media.Author
|
||||
import ani.dantotsu.media.AuthorAdapter
|
||||
import ani.dantotsu.media.Character
|
||||
import ani.dantotsu.media.CharacterAdapter
|
||||
import ani.dantotsu.media.Media
|
||||
import ani.dantotsu.media.MediaAdaptor
|
||||
import ani.dantotsu.media.user.ListActivity
|
||||
import ani.dantotsu.setBaseline
|
||||
import ani.dantotsu.setSlideIn
|
||||
import ani.dantotsu.setSlideUp
|
||||
import ani.dantotsu.util.AniMarkdown.Companion.getFullAniHTML
|
||||
import ani.dantotsu.util.Logger
|
||||
import eu.kanade.tachiyomi.util.system.getSerializableCompat
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
|
@ -137,7 +132,7 @@ class ProfileFragment : Fragment() {
|
|||
}
|
||||
|
||||
user.favourites?.staff?.nodes?.forEach { i ->
|
||||
favStaff.add(Author(i.id, i.name.full, i.image.large , "" ))
|
||||
favStaff.add(Author(i.id, i.name.full, i.image.large, ""))
|
||||
}
|
||||
|
||||
setFavPeople()
|
||||
|
@ -159,7 +154,8 @@ class ProfileFragment : Fragment() {
|
|||
binding.profileFavStaffRecycler.layoutManager = LinearLayoutManager(
|
||||
activity, LinearLayoutManager.HORIZONTAL, false
|
||||
)
|
||||
binding.profileFavStaffRecycler.layoutAnimation = LayoutAnimationController(setSlideIn(), 0.25f)
|
||||
binding.profileFavStaffRecycler.layoutAnimation =
|
||||
LayoutAnimationController(setSlideIn(), 0.25f)
|
||||
}
|
||||
|
||||
if (favCharacter.isEmpty()) {
|
||||
|
@ -169,7 +165,8 @@ class ProfileFragment : Fragment() {
|
|||
binding.profileFavCharactersRecycler.layoutManager = LinearLayoutManager(
|
||||
activity, LinearLayoutManager.HORIZONTAL, false
|
||||
)
|
||||
binding.profileFavCharactersRecycler.layoutAnimation = LayoutAnimationController(setSlideIn(), 0.25f)
|
||||
binding.profileFavCharactersRecycler.layoutAnimation =
|
||||
LayoutAnimationController(setSlideIn(), 0.25f)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -189,7 +186,7 @@ class ProfileFragment : Fragment() {
|
|||
recyclerView.visibility = View.GONE
|
||||
if (it != null) {
|
||||
if (it.isNotEmpty()) {
|
||||
recyclerView.adapter = MediaAdaptor(0, it, activity, fav=true)
|
||||
recyclerView.adapter = MediaAdaptor(0, it, activity, fav = true)
|
||||
recyclerView.layoutManager = LinearLayoutManager(
|
||||
activity,
|
||||
LinearLayoutManager.HORIZONTAL,
|
||||
|
|
|
@ -10,8 +10,7 @@ import ani.dantotsu.themes.ThemeManager
|
|||
import ani.dantotsu.toast
|
||||
import com.github.aachartmodel.aainfographics.aachartcreator.AAOptions
|
||||
|
||||
class SingleStatActivity : AppCompatActivity()
|
||||
{
|
||||
class SingleStatActivity : AppCompatActivity() {
|
||||
private lateinit var binding: ActivitySingleStatBinding
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
|
|
@ -58,10 +58,13 @@ class StatsFragment :
|
|||
binding.statisticList.adapter = adapter
|
||||
binding.statisticList.recycledViewPool.setMaxRecycledViews(0, 0)
|
||||
binding.statisticList.isNestedScrollingEnabled = true
|
||||
binding.statisticList.layoutManager = LinearLayoutManager(requireContext(), LinearLayoutManager.VERTICAL, false)
|
||||
binding.statisticList.layoutManager =
|
||||
LinearLayoutManager(requireContext(), LinearLayoutManager.VERTICAL, false)
|
||||
binding.statisticProgressBar.visibility = View.VISIBLE
|
||||
binding.compare.visibility = if (user.id == Anilist.userid) View.GONE else View.VISIBLE
|
||||
binding.filterContainer.updateLayoutParams<ViewGroup.MarginLayoutParams> { topMargin = statusBarHeight }
|
||||
binding.filterContainer.updateLayoutParams<ViewGroup.MarginLayoutParams> {
|
||||
topMargin = statusBarHeight
|
||||
}
|
||||
|
||||
binding.sourceType.setAdapter(
|
||||
ArrayAdapter(
|
||||
|
|
|
@ -12,8 +12,8 @@ data class User(
|
|||
val status: String? = null,
|
||||
val score: Float? = null,
|
||||
val progress: Int? = null,
|
||||
val totalEpisodes : Int? = null,
|
||||
val nextAiringEpisode : Int? = null,
|
||||
val totalEpisodes: Int? = null,
|
||||
val nextAiringEpisode: Int? = null,
|
||||
) : java.io.Serializable {
|
||||
companion object {
|
||||
private const val serialVersionUID: Long = 1
|
||||
|
|
|
@ -5,13 +5,13 @@ import android.view.LayoutInflater
|
|||
import android.view.ViewGroup
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import ani.dantotsu.blurImage
|
||||
import ani.dantotsu.databinding.ItemFollowerBinding
|
||||
import ani.dantotsu.loadImage
|
||||
import ani.dantotsu.setAnimation
|
||||
|
||||
|
||||
class UsersAdapter(private val user: ArrayList<User>) : RecyclerView.Adapter<UsersAdapter.UsersViewHolder>() {
|
||||
class UsersAdapter(private val user: ArrayList<User>) :
|
||||
RecyclerView.Adapter<UsersAdapter.UsersViewHolder>() {
|
||||
|
||||
inner class UsersViewHolder(val binding: ItemFollowerBinding) :
|
||||
RecyclerView.ViewHolder(binding.root) {
|
||||
|
|
|
@ -14,9 +14,10 @@ class UsersDialogFragment : BottomSheetDialogFragment() {
|
|||
private val binding get() = _binding!!
|
||||
|
||||
private var userList = arrayListOf<User>()
|
||||
fun userList(user: ArrayList<User>){
|
||||
fun userList(user: ArrayList<User>) {
|
||||
userList = user
|
||||
}
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
|
@ -25,6 +26,7 @@ class UsersDialogFragment : BottomSheetDialogFragment() {
|
|||
_binding = BottomSheetUsersBinding.inflate(inflater, container, false)
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package ani.dantotsu.profile.activity
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.view.View
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.view.isVisible
|
||||
|
@ -18,13 +17,8 @@ import ani.dantotsu.profile.UsersDialogFragment
|
|||
import ani.dantotsu.setAnimation
|
||||
import ani.dantotsu.snackString
|
||||
import ani.dantotsu.util.AniMarkdown.Companion.getBasicAniHTML
|
||||
import com.bumptech.glide.Glide
|
||||
import com.bumptech.glide.load.engine.DiskCacheStrategy
|
||||
import com.bumptech.glide.load.model.GlideUrl
|
||||
import com.bumptech.glide.request.RequestOptions
|
||||
import com.xwray.groupie.GroupieAdapter
|
||||
import com.xwray.groupie.viewbinding.BindableItem
|
||||
import jp.wasabeef.glide.transformations.BlurTransformation
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.SupervisorJob
|
||||
|
@ -108,11 +102,12 @@ class ActivityItem(
|
|||
}
|
||||
val context = binding.root.context
|
||||
val userList = arrayListOf<User>()
|
||||
activity.likes?.forEach{ i ->
|
||||
activity.likes?.forEach { i ->
|
||||
userList.add(User(i.id, i.name.toString(), i.avatar?.medium, i.bannerImage))
|
||||
}
|
||||
binding.activityLike.setOnLongClickListener{
|
||||
UsersDialogFragment().apply { userList(userList)
|
||||
binding.activityLike.setOnLongClickListener {
|
||||
UsersDialogFragment().apply {
|
||||
userList(userList)
|
||||
show(fragActivity.supportFragmentManager, "dialog")
|
||||
}
|
||||
true
|
||||
|
@ -126,8 +121,10 @@ class ActivityItem(
|
|||
binding.activityContent.visibility = View.GONE
|
||||
binding.activityBannerContainer.visibility = View.VISIBLE
|
||||
binding.activityMediaName.text = activity.media?.title?.userPreferred
|
||||
val activityText = "${activity.user!!.name} ${activity.status} ${activity.progress
|
||||
?: activity.media?.title?.userPreferred}"
|
||||
val activityText = "${activity.user!!.name} ${activity.status} ${
|
||||
activity.progress
|
||||
?: activity.media?.title?.userPreferred
|
||||
}"
|
||||
binding.activityText.text = activityText
|
||||
binding.activityCover.loadImage(cover)
|
||||
blurImage(binding.activityBannerImage, banner ?: cover)
|
||||
|
|
|
@ -5,6 +5,7 @@ import ani.dantotsu.connections.anilist.api.NotificationType
|
|||
import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
import java.util.Locale
|
||||
|
||||
class ActivityItemBuilder {
|
||||
|
||||
companion object {
|
||||
|
@ -109,6 +110,7 @@ class ActivityItemBuilder {
|
|||
else -> "Just now"
|
||||
}
|
||||
}
|
||||
|
||||
1L -> "1 day ago"
|
||||
in 2..6 -> "$daysDifference days ago"
|
||||
else -> SimpleDateFormat("dd MMM yyyy", Locale.getDefault()).format(targetDate)
|
||||
|
|
|
@ -31,7 +31,8 @@ class FeedActivity : AppCompatActivity() {
|
|||
setContentView(binding.root)
|
||||
navBar = binding.feedNavBar
|
||||
val navBarMargin = if (resources.configuration.orientation ==
|
||||
Configuration.ORIENTATION_LANDSCAPE) 0 else navBarHeight
|
||||
Configuration.ORIENTATION_LANDSCAPE
|
||||
) 0 else navBarHeight
|
||||
navBar.updateLayoutParams<ViewGroup.MarginLayoutParams> { bottomMargin = navBarMargin }
|
||||
val personalTab = navBar.createTab(R.drawable.ic_round_person_24, "Following")
|
||||
val globalTab = navBar.createTab(R.drawable.ic_globe_24, "Global")
|
||||
|
@ -67,10 +68,12 @@ class FeedActivity : AppCompatActivity() {
|
|||
|
||||
override fun onConfigurationChanged(newConfig: Configuration) {
|
||||
super.onConfigurationChanged(newConfig)
|
||||
val margin = if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) 0 else navBarHeight
|
||||
val params : ViewGroup.MarginLayoutParams =
|
||||
val margin =
|
||||
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) 0 else navBarHeight
|
||||
val params: ViewGroup.MarginLayoutParams =
|
||||
binding.feedViewPager.layoutParams as ViewGroup.MarginLayoutParams
|
||||
val paramsNav : ViewGroup.MarginLayoutParams = navBar.layoutParams as ViewGroup.MarginLayoutParams
|
||||
val paramsNav: ViewGroup.MarginLayoutParams =
|
||||
navBar.layoutParams as ViewGroup.MarginLayoutParams
|
||||
params.updateMargins(bottom = margin)
|
||||
paramsNav.updateMargins(bottom = margin)
|
||||
}
|
||||
|
|
|
@ -19,7 +19,6 @@ import ani.dantotsu.databinding.FragmentFeedBinding
|
|||
import ani.dantotsu.media.MediaDetailsActivity
|
||||
import ani.dantotsu.profile.ProfileActivity
|
||||
import ani.dantotsu.setBaseline
|
||||
import ani.dantotsu.snackString
|
||||
import ani.dantotsu.util.Logger
|
||||
import com.xwray.groupie.GroupieAdapter
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
|
@ -57,7 +56,7 @@ class FeedFragment : Fragment() {
|
|||
|
||||
val navBar = if (userId != null) {
|
||||
(activity as ProfileActivity).navBar
|
||||
}else{
|
||||
} else {
|
||||
(activity as FeedActivity).navBar
|
||||
}
|
||||
binding.listRecyclerView.setBaseline(navBar)
|
||||
|
@ -74,7 +73,7 @@ class FeedFragment : Fragment() {
|
|||
binding.root.requestLayout()
|
||||
val navBar = if (userId != null) {
|
||||
(activity as ProfileActivity).navBar
|
||||
}else{
|
||||
} else {
|
||||
(activity as FeedActivity).navBar
|
||||
}
|
||||
binding.listRecyclerView.setBaseline(navBar)
|
||||
|
@ -85,10 +84,17 @@ class FeedFragment : Fragment() {
|
|||
withContext(Dispatchers.Main) {
|
||||
res?.data?.page?.activities?.let { activities ->
|
||||
activityList = activities
|
||||
val filtered = activityList.filterNot { //filter out messages that are not directed to the user
|
||||
it.recipient?.id != null && it.recipient.id != Anilist.userid
|
||||
}
|
||||
adapter.update(filtered.map { ActivityItem(it, ::onActivityClick,requireActivity()) })
|
||||
val filtered =
|
||||
activityList.filterNot { //filter out messages that are not directed to the user
|
||||
it.recipient?.id != null && it.recipient.id != Anilist.userid
|
||||
}
|
||||
adapter.update(filtered.map {
|
||||
ActivityItem(
|
||||
it,
|
||||
::onActivityClick,
|
||||
requireActivity()
|
||||
)
|
||||
})
|
||||
}
|
||||
binding.listProgressBar.visibility = ViewGroup.GONE
|
||||
val scrollView = binding.listRecyclerView
|
||||
|
@ -134,7 +140,13 @@ class FeedFragment : Fragment() {
|
|||
val filtered = activities.filterNot {
|
||||
it.recipient?.id != null && it.recipient.id != Anilist.userid
|
||||
}
|
||||
adapter.addAll(filtered.map { ActivityItem(it, ::onActivityClick,requireActivity()) })
|
||||
adapter.addAll(filtered.map {
|
||||
ActivityItem(
|
||||
it,
|
||||
::onActivityClick,
|
||||
requireActivity()
|
||||
)
|
||||
})
|
||||
}
|
||||
binding.feedSwipeRefresh.isRefreshing = false
|
||||
onFinish()
|
||||
|
@ -150,6 +162,7 @@ class FeedFragment : Fragment() {
|
|||
.putExtra("userId", id), null
|
||||
)
|
||||
}
|
||||
|
||||
"MEDIA" -> {
|
||||
ContextCompat.startActivity(
|
||||
activity, Intent(activity, MediaDetailsActivity::class.java)
|
||||
|
|
|
@ -22,7 +22,6 @@ import ani.dantotsu.notifications.comment.CommentStore
|
|||
import ani.dantotsu.profile.ProfileActivity
|
||||
import ani.dantotsu.settings.saving.PrefManager
|
||||
import ani.dantotsu.settings.saving.PrefName
|
||||
import ani.dantotsu.snackString
|
||||
import ani.dantotsu.statusBarHeight
|
||||
import ani.dantotsu.themes.ThemeManager
|
||||
import ani.dantotsu.util.Logger
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
package ani.dantotsu.profile.activity
|
||||
|
||||
import android.util.TypedValue
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.view.updateLayoutParams
|
||||
import ani.dantotsu.R
|
||||
import ani.dantotsu.blurImage
|
||||
import ani.dantotsu.connections.anilist.api.Notification
|
||||
|
@ -60,7 +58,8 @@ class NotificationItem(
|
|||
}
|
||||
binding.notificationBannerImage.layoutParams.height = userHeight
|
||||
binding.notificationGradiant.layoutParams.height = userHeight
|
||||
(binding.notificationTextContainer.layoutParams as ViewGroup.MarginLayoutParams).marginStart = userHeight
|
||||
(binding.notificationTextContainer.layoutParams as ViewGroup.MarginLayoutParams).marginStart =
|
||||
userHeight
|
||||
} else {
|
||||
binding.notificationCover.visibility = View.VISIBLE
|
||||
binding.notificationCoverUser.visibility = View.VISIBLE
|
||||
|
@ -68,7 +67,8 @@ class NotificationItem(
|
|||
binding.notificationCover.loadImage(notification.media?.coverImage?.large)
|
||||
binding.notificationBannerImage.layoutParams.height = defaultHeight
|
||||
binding.notificationGradiant.layoutParams.height = defaultHeight
|
||||
(binding.notificationTextContainer.layoutParams as ViewGroup.MarginLayoutParams).marginStart = textMarginStart
|
||||
(binding.notificationTextContainer.layoutParams as ViewGroup.MarginLayoutParams).marginStart =
|
||||
textMarginStart
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -308,7 +308,9 @@ class NotificationItem(
|
|||
if (notification.commentId != null && notification.mediaId != null) {
|
||||
binding.notificationBannerImage.setOnClickListener {
|
||||
clickCallback(
|
||||
notification.mediaId, notification.commentId, NotificationClickType.COMMENT
|
||||
notification.mediaId,
|
||||
notification.commentId,
|
||||
NotificationClickType.COMMENT
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,10 +12,10 @@ import ani.dantotsu.setAnimation
|
|||
class SettingsAdapter(private val settings: ArrayList<Settings>) :
|
||||
RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
||||
inner class SettingsViewHolder(val binding: ItemSettingsBinding) :
|
||||
RecyclerView.ViewHolder(binding.root) {}
|
||||
RecyclerView.ViewHolder(binding.root)
|
||||
|
||||
inner class SettingsSwitchViewHolder(val binding: ItemSettingsSwitchBinding) :
|
||||
RecyclerView.ViewHolder(binding.root) {}
|
||||
RecyclerView.ViewHolder(binding.root)
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||
return when (viewType) {
|
||||
|
@ -82,7 +82,7 @@ class SettingsAdapter(private val settings: ArrayList<Settings>) :
|
|||
b.settingsButton.setOnCheckedChangeListener { _, isChecked ->
|
||||
settings.switch?.invoke(isChecked, b)
|
||||
}
|
||||
b.settingsLayout.setOnLongClickListener() {
|
||||
b.settingsLayout.setOnLongClickListener {
|
||||
settings.onLongClick?.invoke()
|
||||
true
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package ani.dantotsu.util
|
||||
|
||||
import ani.dantotsu.util.ColorEditor.Companion.toCssColor
|
||||
import ani.dantotsu.util.ColorEditor.Companion.toHexColor
|
||||
|
||||
class AniMarkdown { //istg anilist has the worst api
|
||||
companion object {
|
||||
|
|
|
@ -133,7 +133,11 @@ object Logger {
|
|||
shareIntent.type = "text/plain"
|
||||
shareIntent.putExtra(
|
||||
Intent.EXTRA_STREAM,
|
||||
FileProvider.getUriForFile(context, "${BuildConfig.APPLICATION_ID}.provider", fileToUse!!)
|
||||
FileProvider.getUriForFile(
|
||||
context,
|
||||
"${BuildConfig.APPLICATION_ID}.provider",
|
||||
fileToUse!!
|
||||
)
|
||||
)
|
||||
shareIntent.putExtra(Intent.EXTRA_SUBJECT, "Log file")
|
||||
shareIntent.putExtra(Intent.EXTRA_TEXT, "Log file")
|
||||
|
|
|
@ -62,9 +62,10 @@ class StoragePermissions {
|
|||
return hasDirAccess(context, path)
|
||||
}
|
||||
|
||||
fun AppCompatActivity.accessAlertDialog(launcher: LauncherWrapper,
|
||||
force: Boolean = false,
|
||||
complete: (Boolean) -> Unit
|
||||
fun AppCompatActivity.accessAlertDialog(
|
||||
launcher: LauncherWrapper,
|
||||
force: Boolean = false,
|
||||
complete: (Boolean) -> Unit
|
||||
) {
|
||||
if (hasDirAccess(this) && !force) {
|
||||
complete(true)
|
||||
|
@ -97,11 +98,12 @@ class StoragePermissions {
|
|||
|
||||
class LauncherWrapper(
|
||||
activity: AppCompatActivity,
|
||||
contract: ActivityResultContracts.OpenDocumentTree)
|
||||
{
|
||||
contract: ActivityResultContracts.OpenDocumentTree
|
||||
) {
|
||||
private var launcher: ActivityResultLauncher<Uri?>
|
||||
var complete: (Boolean) -> Unit = {}
|
||||
init{
|
||||
|
||||
init {
|
||||
launcher = activity.registerForActivityResult(contract) { uri ->
|
||||
if (uri != null) {
|
||||
activity.contentResolver.takePersistableUriPermission(
|
||||
|
|
|
@ -59,7 +59,8 @@ class ProfileStatsWidget : AppWidgetProvider() {
|
|||
appWidgetId: Int
|
||||
) {
|
||||
|
||||
val prefs = context.getSharedPreferences(getPrefsName(appWidgetId), Context.MODE_PRIVATE)
|
||||
val prefs =
|
||||
context.getSharedPreferences(getPrefsName(appWidgetId), Context.MODE_PRIVATE)
|
||||
val backgroundColor =
|
||||
prefs.getInt(PREF_BACKGROUND_COLOR, Color.parseColor("#80000000"))
|
||||
val backgroundFade = prefs.getInt(PREF_BACKGROUND_FADE, Color.parseColor("#00000000"))
|
||||
|
@ -87,88 +88,95 @@ class ProfileStatsWidget : AppWidgetProvider() {
|
|||
val respond = Anilist.query.getUserProfile(userPref.toInt())
|
||||
respond?.data?.user?.let { user ->
|
||||
withContext(Dispatchers.Main) {
|
||||
val views = RemoteViews(context.packageName, R.layout.statistics_widget).apply {
|
||||
setImageViewBitmap(
|
||||
R.id.backgroundView,
|
||||
gradientDrawable.toBitmap(
|
||||
width,
|
||||
height
|
||||
val views =
|
||||
RemoteViews(context.packageName, R.layout.statistics_widget).apply {
|
||||
setImageViewBitmap(
|
||||
R.id.backgroundView,
|
||||
gradientDrawable.toBitmap(
|
||||
width,
|
||||
height
|
||||
)
|
||||
)
|
||||
)
|
||||
setOnClickPendingIntent(
|
||||
R.id.userAvatar,
|
||||
PendingIntent.getActivity(
|
||||
context,
|
||||
1,
|
||||
Intent(context, ProfileStatsConfigure::class.java).apply {
|
||||
putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId)
|
||||
data = Uri.parse(toUri(Intent.URI_INTENT_SCHEME))
|
||||
},
|
||||
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
|
||||
setOnClickPendingIntent(
|
||||
R.id.userAvatar,
|
||||
PendingIntent.getActivity(
|
||||
context,
|
||||
1,
|
||||
Intent(
|
||||
context,
|
||||
ProfileStatsConfigure::class.java
|
||||
).apply {
|
||||
putExtra(
|
||||
AppWidgetManager.EXTRA_APPWIDGET_ID,
|
||||
appWidgetId
|
||||
)
|
||||
data = Uri.parse(toUri(Intent.URI_INTENT_SCHEME))
|
||||
},
|
||||
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
|
||||
)
|
||||
)
|
||||
)
|
||||
setTextColor(R.id.userLabel, titleTextColor)
|
||||
setTextColor(R.id.topLeftItem, titleTextColor)
|
||||
setTextColor(R.id.topLeftLabel, statsTextColor)
|
||||
setTextColor(R.id.topRightItem, titleTextColor)
|
||||
setTextColor(R.id.topRightLabel, statsTextColor)
|
||||
setTextColor(R.id.bottomLeftItem, titleTextColor)
|
||||
setTextColor(R.id.bottomLeftLabel, statsTextColor)
|
||||
setTextColor(R.id.bottomRightItem, titleTextColor)
|
||||
setTextColor(R.id.bottomRightLabel, statsTextColor)
|
||||
setTextColor(R.id.userLabel, titleTextColor)
|
||||
setTextColor(R.id.topLeftItem, titleTextColor)
|
||||
setTextColor(R.id.topLeftLabel, statsTextColor)
|
||||
setTextColor(R.id.topRightItem, titleTextColor)
|
||||
setTextColor(R.id.topRightLabel, statsTextColor)
|
||||
setTextColor(R.id.bottomLeftItem, titleTextColor)
|
||||
setTextColor(R.id.bottomLeftLabel, statsTextColor)
|
||||
setTextColor(R.id.bottomRightItem, titleTextColor)
|
||||
setTextColor(R.id.bottomRightLabel, statsTextColor)
|
||||
|
||||
setImageViewBitmap(
|
||||
R.id.userAvatar,
|
||||
user.avatar?.medium?.let { it1 -> downloadImageAsBitmap(it1) }
|
||||
)
|
||||
setTextViewText(
|
||||
R.id.userLabel,
|
||||
context.getString(R.string.user_stats, user.name)
|
||||
)
|
||||
setImageViewBitmap(
|
||||
R.id.userAvatar,
|
||||
user.avatar?.medium?.let { it1 -> downloadImageAsBitmap(it1) }
|
||||
)
|
||||
setTextViewText(
|
||||
R.id.userLabel,
|
||||
context.getString(R.string.user_stats, user.name)
|
||||
)
|
||||
|
||||
setTextViewText(
|
||||
R.id.topLeftItem,
|
||||
user.statistics.anime.count.toString()
|
||||
)
|
||||
setTextViewText(
|
||||
R.id.topLeftLabel,
|
||||
context.getString(R.string.anime_watched)
|
||||
)
|
||||
setTextViewText(
|
||||
R.id.topLeftItem,
|
||||
user.statistics.anime.count.toString()
|
||||
)
|
||||
setTextViewText(
|
||||
R.id.topLeftLabel,
|
||||
context.getString(R.string.anime_watched)
|
||||
)
|
||||
|
||||
setTextViewText(
|
||||
R.id.topRightItem,
|
||||
user.statistics.anime.episodesWatched.toString()
|
||||
)
|
||||
setTextViewText(
|
||||
R.id.topRightLabel,
|
||||
context.getString(R.string.episodes_watched_n)
|
||||
)
|
||||
setTextViewText(
|
||||
R.id.topRightItem,
|
||||
user.statistics.anime.episodesWatched.toString()
|
||||
)
|
||||
setTextViewText(
|
||||
R.id.topRightLabel,
|
||||
context.getString(R.string.episodes_watched_n)
|
||||
)
|
||||
|
||||
setTextViewText(
|
||||
R.id.bottomLeftItem,
|
||||
user.statistics.manga.count.toString()
|
||||
)
|
||||
setTextViewText(
|
||||
R.id.bottomLeftLabel,
|
||||
context.getString(R.string.manga_read)
|
||||
)
|
||||
setTextViewText(
|
||||
R.id.bottomLeftItem,
|
||||
user.statistics.manga.count.toString()
|
||||
)
|
||||
setTextViewText(
|
||||
R.id.bottomLeftLabel,
|
||||
context.getString(R.string.manga_read)
|
||||
)
|
||||
|
||||
setTextViewText(
|
||||
R.id.bottomRightItem,
|
||||
user.statistics.manga.chaptersRead.toString()
|
||||
)
|
||||
setTextViewText(
|
||||
R.id.bottomRightLabel,
|
||||
context.getString(R.string.chapters_read_n)
|
||||
)
|
||||
setTextViewText(
|
||||
R.id.bottomRightItem,
|
||||
user.statistics.manga.chaptersRead.toString()
|
||||
)
|
||||
setTextViewText(
|
||||
R.id.bottomRightLabel,
|
||||
context.getString(R.string.chapters_read_n)
|
||||
)
|
||||
|
||||
val intent = Intent(context, ProfileActivity::class.java)
|
||||
.putExtra("userId", userPref.toInt())
|
||||
val pendingIntent = PendingIntent.getActivity(
|
||||
context, 0, intent, PendingIntent.FLAG_IMMUTABLE
|
||||
)
|
||||
setOnClickPendingIntent(R.id.widgetContainer, pendingIntent)
|
||||
}
|
||||
val intent = Intent(context, ProfileActivity::class.java)
|
||||
.putExtra("userId", userPref.toInt())
|
||||
val pendingIntent = PendingIntent.getActivity(
|
||||
context, 0, intent, PendingIntent.FLAG_IMMUTABLE
|
||||
)
|
||||
setOnClickPendingIntent(R.id.widgetContainer, pendingIntent)
|
||||
}
|
||||
// Instruct the widget manager to update the widget
|
||||
appWidgetManager.updateAppWidget(appWidgetId, views)
|
||||
}
|
||||
|
@ -221,6 +229,7 @@ class ProfileStatsWidget : AppWidgetProvider() {
|
|||
fun getPrefsName(appWidgetId: Int): String {
|
||||
return "ani.dantotsu.widgets.Statistics.${appWidgetId}"
|
||||
}
|
||||
|
||||
const val PREF_BACKGROUND_COLOR = "background_color"
|
||||
const val PREF_BACKGROUND_FADE = "background_fade"
|
||||
const val PREF_TITLE_TEXT_COLOR = "title_text_color"
|
||||
|
|
|
@ -48,8 +48,10 @@ class UpcomingWidgetConfigure : AppCompatActivity(),
|
|||
binding = UpcomingWidgetConfigureBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
val prefs = getSharedPreferences(UpcomingWidget.PREFS_NAME, Context.MODE_PRIVATE)
|
||||
val topBackground = prefs.getInt(UpcomingWidget.PREF_BACKGROUND_COLOR, Color.parseColor("#80000000"))
|
||||
(binding.topBackgroundButton as MaterialButton).iconTint = ColorStateList.valueOf(topBackground)
|
||||
val topBackground =
|
||||
prefs.getInt(UpcomingWidget.PREF_BACKGROUND_COLOR, Color.parseColor("#80000000"))
|
||||
(binding.topBackgroundButton as MaterialButton).iconTint =
|
||||
ColorStateList.valueOf(topBackground)
|
||||
binding.topBackgroundButton.setOnClickListener {
|
||||
val tag = UpcomingWidget.PREF_BACKGROUND_COLOR
|
||||
SimpleColorDialog().title(R.string.custom_theme)
|
||||
|
@ -66,8 +68,10 @@ class UpcomingWidgetConfigure : AppCompatActivity(),
|
|||
.neg()
|
||||
.show(this@UpcomingWidgetConfigure, tag)
|
||||
}
|
||||
val bottomBackground = prefs.getInt(UpcomingWidget.PREF_BACKGROUND_FADE, Color.parseColor("#00000000"))
|
||||
(binding.bottomBackgroundButton as MaterialButton).iconTint = ColorStateList.valueOf(bottomBackground)
|
||||
val bottomBackground =
|
||||
prefs.getInt(UpcomingWidget.PREF_BACKGROUND_FADE, Color.parseColor("#00000000"))
|
||||
(binding.bottomBackgroundButton as MaterialButton).iconTint =
|
||||
ColorStateList.valueOf(bottomBackground)
|
||||
binding.bottomBackgroundButton.setOnClickListener {
|
||||
val tag = UpcomingWidget.PREF_BACKGROUND_FADE
|
||||
SimpleColorDialog().title(R.string.custom_theme)
|
||||
|
@ -85,7 +89,8 @@ class UpcomingWidgetConfigure : AppCompatActivity(),
|
|||
.show(this@UpcomingWidgetConfigure, tag)
|
||||
}
|
||||
val titleTextColor = prefs.getInt(UpcomingWidget.PREF_TITLE_TEXT_COLOR, Color.WHITE)
|
||||
(binding.titleColorButton as MaterialButton).iconTint = ColorStateList.valueOf(titleTextColor)
|
||||
(binding.titleColorButton as MaterialButton).iconTint =
|
||||
ColorStateList.valueOf(titleTextColor)
|
||||
binding.titleColorButton.setOnClickListener {
|
||||
val tag = UpcomingWidget.PREF_TITLE_TEXT_COLOR
|
||||
SimpleColorDialog().title(R.string.custom_theme)
|
||||
|
@ -102,7 +107,8 @@ class UpcomingWidgetConfigure : AppCompatActivity(),
|
|||
.show(this@UpcomingWidgetConfigure, tag)
|
||||
}
|
||||
val countdownTextColor = prefs.getInt(UpcomingWidget.PREF_COUNTDOWN_TEXT_COLOR, Color.WHITE)
|
||||
(binding.countdownColorButton as MaterialButton).iconTint = ColorStateList.valueOf(countdownTextColor)
|
||||
(binding.countdownColorButton as MaterialButton).iconTint =
|
||||
ColorStateList.valueOf(countdownTextColor)
|
||||
binding.countdownColorButton.setOnClickListener {
|
||||
val tag = UpcomingWidget.PREF_COUNTDOWN_TEXT_COLOR
|
||||
SimpleColorDialog().title(R.string.custom_theme)
|
||||
|
@ -152,15 +158,27 @@ class UpcomingWidgetConfigure : AppCompatActivity(),
|
|||
|
||||
private fun themeColors() {
|
||||
val typedValueSurface = TypedValue()
|
||||
theme.resolveAttribute(com.google.android.material.R.attr.colorSurface, typedValueSurface, true)
|
||||
theme.resolveAttribute(
|
||||
com.google.android.material.R.attr.colorSurface,
|
||||
typedValueSurface,
|
||||
true
|
||||
)
|
||||
val backgroundColor = typedValueSurface.data
|
||||
|
||||
val typedValuePrimary = TypedValue()
|
||||
theme.resolveAttribute(com.google.android.material.R.attr.colorPrimary, typedValuePrimary, true)
|
||||
theme.resolveAttribute(
|
||||
com.google.android.material.R.attr.colorPrimary,
|
||||
typedValuePrimary,
|
||||
true
|
||||
)
|
||||
val textColor = typedValuePrimary.data
|
||||
|
||||
val typedValueOutline = TypedValue()
|
||||
theme.resolveAttribute(com.google.android.material.R.attr.colorOutline, typedValueOutline, true)
|
||||
theme.resolveAttribute(
|
||||
com.google.android.material.R.attr.colorOutline,
|
||||
typedValueOutline,
|
||||
true
|
||||
)
|
||||
val subTextColor = typedValueOutline.data
|
||||
|
||||
getSharedPreferences(UpcomingWidget.PREFS_NAME, Context.MODE_PRIVATE).edit().apply {
|
||||
|
|
|
@ -17,7 +17,7 @@ class BasePreferences(
|
|||
fun incognitoMode() = preferenceStore.getBoolean("incognito_mode", false)
|
||||
|
||||
fun extensionInstaller() = ExtensionInstallerPreference(context, preferenceStore)
|
||||
|
||||
|
||||
fun deviceHasPip() =
|
||||
Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && context.packageManager.hasSystemFeature(
|
||||
PackageManager.FEATURE_PICTURE_IN_PICTURE
|
||||
|
|
|
@ -23,7 +23,6 @@ import uy.kohesive.injekt.injectLazy
|
|||
import java.net.URI
|
||||
import java.net.URISyntaxException
|
||||
import java.security.MessageDigest
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
/**
|
||||
* A simple implementation for sources from a website.
|
||||
|
@ -89,14 +88,15 @@ abstract class AnimeHttpSource : AnimeCatalogueSource {
|
|||
protected fun generateId(name: String, lang: String, versionId: Int): Long {
|
||||
val key = "${name.lowercase()}/$lang/$versionId"
|
||||
val bytes = MessageDigest.getInstance("MD5").digest(key.toByteArray())
|
||||
return (0..7).map { bytes[it].toLong() and 0xff shl 8 * (7 - it) }.reduce(Long::or) and Long.MAX_VALUE
|
||||
return (0..7).map { bytes[it].toLong() and 0xff shl 8 * (7 - it) }
|
||||
.reduce(Long::or) and Long.MAX_VALUE
|
||||
}
|
||||
|
||||
/**
|
||||
* Headers builder for requests. Implementations can override this method for custom headers.
|
||||
*/
|
||||
protected open fun headersBuilder() = Headers.Builder().apply {
|
||||
add("User-Agent", NetworkHelper.defaultUserAgentProvider())
|
||||
add("User-Agent", defaultUserAgentProvider())
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -148,7 +148,11 @@ abstract class AnimeHttpSource : AnimeCatalogueSource {
|
|||
"Use the non-RxJava API instead",
|
||||
ReplaceWith("getSearchAnime"),
|
||||
)
|
||||
override fun fetchSearchAnime(page: Int, query: String, filters: AnimeFilterList): Observable<AnimesPage> {
|
||||
override fun fetchSearchAnime(
|
||||
page: Int,
|
||||
query: String,
|
||||
filters: AnimeFilterList
|
||||
): Observable<AnimesPage> {
|
||||
return Observable.defer {
|
||||
try {
|
||||
client.newCall(searchAnimeRequest(page, query, filters)).asObservableSuccess()
|
||||
|
@ -170,7 +174,11 @@ abstract class AnimeHttpSource : AnimeCatalogueSource {
|
|||
* @param query the search query.
|
||||
* @param filters the list of filters to apply.
|
||||
*/
|
||||
protected abstract fun searchAnimeRequest(page: Int, query: String, filters: AnimeFilterList): Request
|
||||
protected abstract fun searchAnimeRequest(
|
||||
page: Int,
|
||||
query: String,
|
||||
filters: AnimeFilterList
|
||||
): Request
|
||||
|
||||
/**
|
||||
* Parses the response from the site and returns a [AnimesPage] object.
|
||||
|
@ -403,7 +411,8 @@ abstract class AnimeHttpSource : AnimeCatalogueSource {
|
|||
video: Video,
|
||||
tries: Int,
|
||||
): Long {
|
||||
val headers = Headers.Builder().addAll(video.headers ?: headers).add("Range", "bytes=0-1").build()
|
||||
val headers =
|
||||
Headers.Builder().addAll(video.headers ?: headers).add("Range", "bytes=0-1").build()
|
||||
val request = GET(video.videoUrl!!, headers)
|
||||
val response = client.newCall(request).execute()
|
||||
// parse the response headers to get the size of the video, in particular the content-range header
|
||||
|
|
|
@ -207,8 +207,10 @@ class AnimeExtensionManager(
|
|||
* @param extension The anime extension to be installed.
|
||||
*/
|
||||
fun installExtension(extension: AnimeExtension.Available): Observable<InstallStep> {
|
||||
return installer.downloadAndInstall(api.getAnimeApkUrl(extension), extension.pkgName,
|
||||
extension.name, MediaType.ANIME)
|
||||
return installer.downloadAndInstall(
|
||||
api.getAnimeApkUrl(extension), extension.pkgName,
|
||||
extension.name, MediaType.ANIME
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -28,18 +28,19 @@ class PackageInstallerInstaller(private val service: Service) : Installer(servic
|
|||
PackageInstaller.STATUS_FAILURE
|
||||
)) {
|
||||
PackageInstaller.STATUS_PENDING_USER_ACTION -> {
|
||||
val userAction = intent.getParcelableExtraCompat<Intent>(Intent.EXTRA_INTENT)?.run {
|
||||
IntentSanitizer.Builder()
|
||||
.allowAction(this.action!!)
|
||||
.allowExtra(PackageInstaller.EXTRA_SESSION_ID) { id -> id == activeSession?.second }
|
||||
.allowAnyComponent()
|
||||
.allowPackage {
|
||||
// There is no way to check the actual installer name so allow all.
|
||||
true
|
||||
}
|
||||
.build()
|
||||
.sanitizeByFiltering(this)
|
||||
}
|
||||
val userAction =
|
||||
intent.getParcelableExtraCompat<Intent>(Intent.EXTRA_INTENT)?.run {
|
||||
IntentSanitizer.Builder()
|
||||
.allowAction(this.action!!)
|
||||
.allowExtra(PackageInstaller.EXTRA_SESSION_ID) { id -> id == activeSession?.second }
|
||||
.allowAnyComponent()
|
||||
.allowPackage {
|
||||
// There is no way to check the actual installer name so allow all.
|
||||
true
|
||||
}
|
||||
.build()
|
||||
.sanitizeByFiltering(this)
|
||||
}
|
||||
if (userAction == null) {
|
||||
Logger.log("Fatal error for $intent")
|
||||
continueQueue(InstallStep.Error)
|
||||
|
|
|
@ -204,8 +204,10 @@ class MangaExtensionManager(
|
|||
* @param extension The extension to be installed.
|
||||
*/
|
||||
fun installExtension(extension: MangaExtension.Available): Observable<InstallStep> {
|
||||
return installer.downloadAndInstall(api.getMangaApkUrl(extension), extension.pkgName,
|
||||
extension.name, MediaType.MANGA)
|
||||
return installer.downloadAndInstall(
|
||||
api.getMangaApkUrl(extension), extension.pkgName,
|
||||
extension.name, MediaType.MANGA
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -41,9 +41,11 @@ class ExtensionInstallActivity : AppCompatActivity() {
|
|||
ThemeManager(this).applyTheme()
|
||||
|
||||
if (intent.hasExtra(ExtensionInstaller.EXTRA_EXTENSION_TYPE))
|
||||
mediaType = intent.getSerializableExtraCompat<MediaType>(ExtensionInstaller.EXTRA_EXTENSION_TYPE)
|
||||
mediaType =
|
||||
intent.getSerializableExtraCompat<MediaType>(ExtensionInstaller.EXTRA_EXTENSION_TYPE)
|
||||
if (intent.hasExtra(ExtensionInstaller.EXTRA_ADDON_TYPE))
|
||||
addonType = intent.getSerializableExtraCompat<AddonType>(ExtensionInstaller.EXTRA_ADDON_TYPE)
|
||||
addonType =
|
||||
intent.getSerializableExtraCompat<AddonType>(ExtensionInstaller.EXTRA_ADDON_TYPE)
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
val installIntent = Intent(Intent.ACTION_INSTALL_PACKAGE)
|
||||
|
|
|
@ -37,14 +37,14 @@ internal class ExtensionInstallReceiver : BroadcastReceiver() {
|
|||
ContextCompat.registerReceiver(context, this, filter, ContextCompat.RECEIVER_EXPORTED)
|
||||
}
|
||||
|
||||
fun setAnimeListener(listener: AnimeListener) : ExtensionInstallReceiver {
|
||||
fun setAnimeListener(listener: AnimeListener): ExtensionInstallReceiver {
|
||||
this.type = MediaType.ANIME
|
||||
animeListener = listener
|
||||
this.animeListener
|
||||
return this
|
||||
}
|
||||
|
||||
fun setMangaListener(listener: MangaListener) : ExtensionInstallReceiver {
|
||||
fun setMangaListener(listener: MangaListener): ExtensionInstallReceiver {
|
||||
this.type = MediaType.MANGA
|
||||
mangaListener = listener
|
||||
return this
|
||||
|
@ -66,21 +66,33 @@ internal class ExtensionInstallReceiver : BroadcastReceiver() {
|
|||
when (type) {
|
||||
MediaType.ANIME -> {
|
||||
when (val result = getAnimeExtensionFromIntent(context, intent)) {
|
||||
is AnimeLoadResult.Success -> animeListener?.onExtensionInstalled(result.extension)
|
||||
is AnimeLoadResult.Success -> animeListener?.onExtensionInstalled(
|
||||
result.extension
|
||||
)
|
||||
|
||||
is AnimeLoadResult.Untrusted -> animeListener?.onExtensionUntrusted(
|
||||
result.extension
|
||||
)
|
||||
|
||||
is AnimeLoadResult.Untrusted -> animeListener?.onExtensionUntrusted(result.extension)
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
|
||||
MediaType.MANGA -> {
|
||||
when (val result = getMangaExtensionFromIntent(context, intent)) {
|
||||
is MangaLoadResult.Success -> mangaListener?.onExtensionInstalled(result.extension)
|
||||
is MangaLoadResult.Success -> mangaListener?.onExtensionInstalled(
|
||||
result.extension
|
||||
)
|
||||
|
||||
is MangaLoadResult.Untrusted -> mangaListener?.onExtensionUntrusted(
|
||||
result.extension
|
||||
)
|
||||
|
||||
is MangaLoadResult.Untrusted -> mangaListener?.onExtensionUntrusted(result.extension)
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
else -> { }
|
||||
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -90,17 +102,25 @@ internal class ExtensionInstallReceiver : BroadcastReceiver() {
|
|||
when (type) {
|
||||
MediaType.ANIME -> {
|
||||
when (val result = getAnimeExtensionFromIntent(context, intent)) {
|
||||
is AnimeLoadResult.Success -> animeListener?.onExtensionUpdated(result.extension)
|
||||
is AnimeLoadResult.Success -> animeListener?.onExtensionUpdated(
|
||||
result.extension
|
||||
)
|
||||
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
|
||||
MediaType.MANGA -> {
|
||||
when (val result = getMangaExtensionFromIntent(context, intent)) {
|
||||
is MangaLoadResult.Success -> mangaListener?.onExtensionUpdated(result.extension)
|
||||
is MangaLoadResult.Success -> mangaListener?.onExtensionUpdated(
|
||||
result.extension
|
||||
)
|
||||
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
else -> { }
|
||||
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -114,10 +134,12 @@ internal class ExtensionInstallReceiver : BroadcastReceiver() {
|
|||
MediaType.ANIME -> {
|
||||
animeListener?.onPackageUninstalled(pkgName)
|
||||
}
|
||||
|
||||
MediaType.MANGA -> {
|
||||
mangaListener?.onPackageUninstalled(pkgName)
|
||||
}
|
||||
else -> { }
|
||||
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -131,7 +153,10 @@ internal class ExtensionInstallReceiver : BroadcastReceiver() {
|
|||
* @param intent The intent containing the package name of the extension.
|
||||
*/
|
||||
@OptIn(DelicateCoroutinesApi::class)
|
||||
private suspend fun getAnimeExtensionFromIntent(context: Context, intent: Intent?): AnimeLoadResult {
|
||||
private suspend fun getAnimeExtensionFromIntent(
|
||||
context: Context,
|
||||
intent: Intent?
|
||||
): AnimeLoadResult {
|
||||
val pkgName = getPackageNameFromIntent(intent)
|
||||
if (pkgName == null) {
|
||||
Logger.log("Package name not found")
|
||||
|
@ -146,7 +171,10 @@ internal class ExtensionInstallReceiver : BroadcastReceiver() {
|
|||
}
|
||||
|
||||
@OptIn(DelicateCoroutinesApi::class)
|
||||
private suspend fun getMangaExtensionFromIntent(context: Context, intent: Intent?): MangaLoadResult {
|
||||
private suspend fun getMangaExtensionFromIntent(
|
||||
context: Context,
|
||||
intent: Intent?
|
||||
): MangaLoadResult {
|
||||
val pkgName = getPackageNameFromIntent(intent)
|
||||
if (pkgName == null) {
|
||||
Logger.log("Package name not found")
|
||||
|
|
|
@ -14,8 +14,8 @@ import ani.dantotsu.media.Type
|
|||
import ani.dantotsu.util.Logger
|
||||
import eu.kanade.domain.base.BasePreferences
|
||||
import eu.kanade.tachiyomi.data.notification.Notifications
|
||||
import eu.kanade.tachiyomi.extension.installer.PackageInstallerInstaller
|
||||
import eu.kanade.tachiyomi.extension.installer.Installer
|
||||
import eu.kanade.tachiyomi.extension.installer.PackageInstallerInstaller
|
||||
import eu.kanade.tachiyomi.extension.util.ExtensionInstaller.Companion.EXTRA_DOWNLOAD_ID
|
||||
import eu.kanade.tachiyomi.extension.util.ExtensionInstaller.Companion.EXTRA_EXTENSION_TYPE
|
||||
import eu.kanade.tachiyomi.util.system.getSerializableExtraCompat
|
||||
|
@ -48,7 +48,8 @@ class ExtensionInstallService : Service() {
|
|||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||
val uri = intent?.data
|
||||
val mediaType = intent?.getSerializableExtraCompat<MediaType>(EXTRA_EXTENSION_TYPE)
|
||||
val addonType = intent?.getSerializableExtraCompat<AddonType>(ExtensionInstaller.EXTRA_ADDON_TYPE)
|
||||
val addonType =
|
||||
intent?.getSerializableExtraCompat<AddonType>(ExtensionInstaller.EXTRA_ADDON_TYPE)
|
||||
val id = intent?.getLongExtra(EXTRA_DOWNLOAD_ID, -1)?.takeIf { it != -1L }
|
||||
val installerUsed = intent?.getSerializableExtraCompat<BasePreferences.ExtensionInstaller>(
|
||||
EXTRA_INSTALLER
|
||||
|
|
|
@ -14,14 +14,11 @@ import androidx.core.net.toUri
|
|||
import ani.dantotsu.media.AddonType
|
||||
import ani.dantotsu.media.MediaType
|
||||
import ani.dantotsu.media.Type
|
||||
import ani.dantotsu.parsers.novel.NovelExtension
|
||||
import ani.dantotsu.util.Logger
|
||||
import com.jakewharton.rxrelay.PublishRelay
|
||||
import eu.kanade.domain.base.BasePreferences
|
||||
import eu.kanade.tachiyomi.extension.InstallStep
|
||||
import eu.kanade.tachiyomi.extension.anime.model.AnimeExtension
|
||||
import eu.kanade.tachiyomi.extension.installer.Installer
|
||||
import eu.kanade.tachiyomi.extension.manga.model.MangaExtension
|
||||
import eu.kanade.tachiyomi.util.storage.getUriCompat
|
||||
import rx.Observable
|
||||
import rx.android.schedulers.AndroidSchedulers
|
||||
|
@ -67,7 +64,12 @@ class ExtensionInstaller(private val context: Context) {
|
|||
* @param url The url of the apk.
|
||||
* @param extension The extension to install.
|
||||
*/
|
||||
fun <T : Type> downloadAndInstall(url: String, pkgName: String, name: String, type: T): Observable<InstallStep> = Observable.defer {
|
||||
fun <T : Type> downloadAndInstall(
|
||||
url: String,
|
||||
pkgName: String,
|
||||
name: String,
|
||||
type: T
|
||||
): Observable<InstallStep> = Observable.defer {
|
||||
val oldDownload = activeDownloads[pkgName]
|
||||
if (oldDownload != null) {
|
||||
deleteDownload(pkgName)
|
||||
|
@ -264,11 +266,15 @@ class ExtensionInstaller(private val context: Context) {
|
|||
val localUri = cursor.getString(
|
||||
cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_LOCAL_URI),
|
||||
).removePrefix(FILE_SCHEME)
|
||||
val type = MediaType.fromText(cursor.getString(
|
||||
cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_DESCRIPTION),
|
||||
)) ?: AddonType.fromText(cursor.getString(
|
||||
cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_DESCRIPTION),
|
||||
)) ?: return
|
||||
val type = MediaType.fromText(
|
||||
cursor.getString(
|
||||
cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_DESCRIPTION),
|
||||
)
|
||||
) ?: AddonType.fromText(
|
||||
cursor.getString(
|
||||
cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_DESCRIPTION),
|
||||
)
|
||||
) ?: return
|
||||
|
||||
installApk(type, id, File(localUri).getUriCompat(context))
|
||||
}
|
||||
|
|
|
@ -62,7 +62,7 @@ internal object ExtensionLoader {
|
|||
|
||||
val PACKAGE_FLAGS = PackageManager.GET_CONFIGURATIONS or
|
||||
PackageManager.GET_META_DATA or
|
||||
@Suppress ("DEPRECATION") PackageManager.GET_SIGNATURES or
|
||||
@Suppress("DEPRECATION") PackageManager.GET_SIGNATURES or
|
||||
(if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P)
|
||||
PackageManager.GET_SIGNING_CERTIFICATES else 0)
|
||||
|
||||
|
@ -145,7 +145,7 @@ internal object ExtensionLoader {
|
|||
Logger.log(error)
|
||||
return AnimeLoadResult.Error
|
||||
}
|
||||
if (!isPackageAnExtension(MediaType.ANIME,pkgInfo)) {
|
||||
if (!isPackageAnExtension(MediaType.ANIME, pkgInfo)) {
|
||||
Logger.log("Tried to load a package that wasn't a extension ($pkgName)")
|
||||
return AnimeLoadResult.Error
|
||||
}
|
||||
|
@ -201,8 +201,9 @@ internal object ExtensionLoader {
|
|||
// Validate lib version
|
||||
val libVersion = versionName.substringBeforeLast('.').toDoubleOrNull()
|
||||
if (libVersion == null || libVersion < ANIME_LIB_VERSION_MIN || libVersion > ANIME_LIB_VERSION_MAX) {
|
||||
Logger.log("Lib version is $libVersion, while only versions " +
|
||||
"$ANIME_LIB_VERSION_MIN to $ANIME_LIB_VERSION_MAX are allowed"
|
||||
Logger.log(
|
||||
"Lib version is $libVersion, while only versions " +
|
||||
"$ANIME_LIB_VERSION_MIN to $ANIME_LIB_VERSION_MAX are allowed"
|
||||
)
|
||||
return AnimeLoadResult.Error
|
||||
}
|
||||
|
@ -232,7 +233,8 @@ internal object ExtensionLoader {
|
|||
}
|
||||
|
||||
val hasReadme = appInfo.metaData.getInt("$ANIME_PACKAGE$XX_METADATA_HAS_README", 0) == 1
|
||||
val hasChangelog = appInfo.metaData.getInt("$ANIME_PACKAGE$XX_METADATA_HAS_CHANGELOG", 0) == 1
|
||||
val hasChangelog =
|
||||
appInfo.metaData.getInt("$ANIME_PACKAGE$XX_METADATA_HAS_CHANGELOG", 0) == 1
|
||||
|
||||
val classLoader = PathClassLoader(appInfo.sourceDir, null, context.classLoader)
|
||||
|
||||
|
@ -248,7 +250,8 @@ internal object ExtensionLoader {
|
|||
}
|
||||
.flatMap {
|
||||
try {
|
||||
when (val obj = Class.forName(it, false, classLoader).getDeclaredConstructor().newInstance()) {
|
||||
when (val obj = Class.forName(it, false, classLoader).getDeclaredConstructor()
|
||||
.newInstance()) {
|
||||
is AnimeSource -> listOf(obj)
|
||||
is AnimeSourceFactory -> obj.createSources()
|
||||
else -> throw Exception("Unknown source class type! ${obj.javaClass}")
|
||||
|
@ -314,8 +317,9 @@ internal object ExtensionLoader {
|
|||
// Validate lib version
|
||||
val libVersion = versionName.substringBeforeLast('.').toDoubleOrNull()
|
||||
if (libVersion == null || libVersion < MANGA_LIB_VERSION_MIN || libVersion > MANGA_LIB_VERSION_MAX) {
|
||||
Logger.log("Lib version is $libVersion, while only versions " +
|
||||
"$MANGA_LIB_VERSION_MIN to $MANGA_LIB_VERSION_MAX are allowed"
|
||||
Logger.log(
|
||||
"Lib version is $libVersion, while only versions " +
|
||||
"$MANGA_LIB_VERSION_MIN to $MANGA_LIB_VERSION_MAX are allowed"
|
||||
)
|
||||
return MangaLoadResult.Error
|
||||
}
|
||||
|
@ -340,7 +344,8 @@ internal object ExtensionLoader {
|
|||
}
|
||||
|
||||
val hasReadme = appInfo.metaData.getInt("$MANGA_PACKAGE$XX_METADATA_HAS_README", 0) == 1
|
||||
val hasChangelog = appInfo.metaData.getInt("$MANGA_PACKAGE$XX_METADATA_HAS_CHANGELOG", 0) == 1
|
||||
val hasChangelog =
|
||||
appInfo.metaData.getInt("$MANGA_PACKAGE$XX_METADATA_HAS_CHANGELOG", 0) == 1
|
||||
|
||||
val classLoader = PathClassLoader(appInfo.sourceDir, null, context.classLoader)
|
||||
|
||||
|
@ -401,11 +406,13 @@ internal object ExtensionLoader {
|
|||
* @param pkgInfo The package info of the application.
|
||||
*/
|
||||
private fun isPackageAnExtension(type: MediaType, pkgInfo: PackageInfo): Boolean {
|
||||
return pkgInfo.reqFeatures.orEmpty().any { it.name == when (type) {
|
||||
MediaType.ANIME -> ANIME_PACKAGE
|
||||
MediaType.MANGA -> MANGA_PACKAGE
|
||||
else -> ""
|
||||
} }
|
||||
return pkgInfo.reqFeatures.orEmpty().any {
|
||||
it.name == when (type) {
|
||||
MediaType.ANIME -> ANIME_PACKAGE
|
||||
MediaType.MANGA -> MANGA_PACKAGE
|
||||
else -> ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -417,7 +424,7 @@ internal object ExtensionLoader {
|
|||
val signatures = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P)
|
||||
pkgInfo.signingInfo.signingCertificateHistory
|
||||
else
|
||||
@Suppress ("DEPRECATION") pkgInfo.signatures
|
||||
@Suppress("DEPRECATION") pkgInfo.signatures
|
||||
return if (signatures != null && signatures.isNotEmpty()) {
|
||||
Hash.sha256(signatures.first().toByteArray())
|
||||
} else {
|
||||
|
|
|
@ -11,8 +11,8 @@ import eu.kanade.tachiyomi.network.interceptor.UncaughtExceptionInterceptor
|
|||
import eu.kanade.tachiyomi.network.interceptor.UserAgentInterceptor
|
||||
import okhttp3.Cache
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.logging.HttpLoggingInterceptor
|
||||
import okhttp3.brotli.BrotliInterceptor
|
||||
import okhttp3.logging.HttpLoggingInterceptor
|
||||
import java.io.File
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
|
|
|
@ -41,10 +41,10 @@ class LocalAnimeSource(
|
|||
override suspend fun getLatestUpdates(page: Int) = getSearchAnime(page, "", LATEST_FILTERS)
|
||||
|
||||
@Deprecated("Use the non-RxJava API instead", replaceWith = ReplaceWith("getPopularAnime"))
|
||||
override fun fetchPopularAnime(page: Int) = fetchSearchAnime(page, "", POPULAR_FILTERS)
|
||||
override fun fetchPopularAnime(page: Int) = getSearchAnime
|
||||
|
||||
@Deprecated("Use the non-RxJava API instead", replaceWith = ReplaceWith("getLatestUpdates"))
|
||||
override fun fetchLatestUpdates(page: Int) = fetchSearchAnime(page, "", LATEST_FILTERS)
|
||||
override fun fetchLatestUpdates(page: Int) = getSearchAnime
|
||||
|
||||
@Deprecated("Use the non-RxJava API instead", replaceWith = ReplaceWith("getSearchAnime"))
|
||||
override fun fetchSearchAnime(page: Int, query: String, filters: AnimeFilterList): Observable<AnimesPage> {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue