more offline stuff/bugfixes
This commit is contained in:
parent
3dfcc9fc31
commit
4db301ca7a
29 changed files with 341 additions and 119 deletions
|
@ -221,6 +221,7 @@
|
||||||
<category android:name="android.intent.category.LEANBACK_LAUNCHER"/>
|
<category android:name="android.intent.category.LEANBACK_LAUNCHER"/>
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
<activity android:name=".download.DownloadContainerActivity" />
|
||||||
<activity
|
<activity
|
||||||
android:name="eu.kanade.tachiyomi.extension.manga.util.MangaExtensionInstallActivity"
|
android:name="eu.kanade.tachiyomi.extension.manga.util.MangaExtensionInstallActivity"
|
||||||
android:theme="@android:style/Theme.Translucent.NoTitleBar"
|
android:theme="@android:style/Theme.Translucent.NoTitleBar"
|
||||||
|
|
|
@ -420,8 +420,14 @@ fun String.findBetween(a: String, b: String): String? {
|
||||||
|
|
||||||
fun ImageView.loadImage(url: String?, size: Int = 0) {
|
fun ImageView.loadImage(url: String?, size: Int = 0) {
|
||||||
if (!url.isNullOrEmpty()) {
|
if (!url.isNullOrEmpty()) {
|
||||||
|
val localFile = File(url)
|
||||||
|
if (localFile.exists()) {
|
||||||
|
loadLocalImage(localFile, size)
|
||||||
|
}
|
||||||
|
else {
|
||||||
loadImage(FileUrl(url), size)
|
loadImage(FileUrl(url), size)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun ImageView.loadImage(file: FileUrl?, size: Int = 0) {
|
fun ImageView.loadImage(file: FileUrl?, size: Int = 0) {
|
||||||
|
@ -433,6 +439,14 @@ fun ImageView.loadImage(file: FileUrl?, size: Int = 0) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun ImageView.loadLocalImage(file: File?, size: Int = 0) {
|
||||||
|
if (file?.exists() == true) {
|
||||||
|
tryWith {
|
||||||
|
Glide.with(this.context).load(file).transition(withCrossFade()).override(size).into(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class SafeClickListener(
|
class SafeClickListener(
|
||||||
private var defaultInterval: Int = 1000,
|
private var defaultInterval: Int = 1000,
|
||||||
private val onSafeCLick: (View) -> Unit
|
private val onSafeCLick: (View) -> Unit
|
||||||
|
|
|
@ -21,6 +21,7 @@ import android.util.Log
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.view.animation.AnticipateInterpolator
|
import android.view.animation.AnticipateInterpolator
|
||||||
|
import android.widget.FrameLayout
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.activity.addCallback
|
import androidx.activity.addCallback
|
||||||
import androidx.activity.viewModels
|
import androidx.activity.viewModels
|
||||||
|
@ -40,6 +41,7 @@ import eu.kanade.tachiyomi.extension.anime.AnimeExtensionManager
|
||||||
import ani.dantotsu.connections.anilist.Anilist
|
import ani.dantotsu.connections.anilist.Anilist
|
||||||
import ani.dantotsu.connections.anilist.AnilistHomeViewModel
|
import ani.dantotsu.connections.anilist.AnilistHomeViewModel
|
||||||
import ani.dantotsu.databinding.ActivityMainBinding
|
import ani.dantotsu.databinding.ActivityMainBinding
|
||||||
|
import ani.dantotsu.databinding.ItemNavbarBinding
|
||||||
import ani.dantotsu.databinding.SplashScreenBinding
|
import ani.dantotsu.databinding.SplashScreenBinding
|
||||||
import ani.dantotsu.download.manga.OfflineMangaFragment
|
import ani.dantotsu.download.manga.OfflineMangaFragment
|
||||||
import ani.dantotsu.home.AnimeFragment
|
import ani.dantotsu.home.AnimeFragment
|
||||||
|
@ -160,7 +162,7 @@ class MainActivity : AppCompatActivity() {
|
||||||
initActivity(this)
|
initActivity(this)
|
||||||
uiSettings = loadData("ui_settings") ?: uiSettings
|
uiSettings = loadData("ui_settings") ?: uiSettings
|
||||||
selectedOption = uiSettings.defaultStartUpTab
|
selectedOption = uiSettings.defaultStartUpTab
|
||||||
binding.navbarContainer.updateLayoutParams<ViewGroup.MarginLayoutParams> {
|
binding.includedNavbar.navbarContainer.updateLayoutParams<ViewGroup.MarginLayoutParams> {
|
||||||
bottomMargin = navBarHeight
|
bottomMargin = navBarHeight
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -173,7 +175,7 @@ class MainActivity : AppCompatActivity() {
|
||||||
model.genres.observe(this) {
|
model.genres.observe(this) {
|
||||||
if (it != null) {
|
if (it != null) {
|
||||||
if (it) {
|
if (it) {
|
||||||
val navbar = binding.navbar
|
val navbar = binding.includedNavbar.navbar
|
||||||
bottomBar = navbar
|
bottomBar = navbar
|
||||||
navbar.visibility = View.VISIBLE
|
navbar.visibility = View.VISIBLE
|
||||||
binding.mainProgressBar.visibility = View.GONE
|
binding.mainProgressBar.visibility = View.GONE
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
package ani.dantotsu.download
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import ani.dantotsu.R
|
||||||
|
import ani.dantotsu.themes.ThemeManager
|
||||||
|
|
||||||
|
class DownloadContainerActivity : AppCompatActivity() {
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
ThemeManager(this).applyTheme()
|
||||||
|
setContentView(R.layout.activity_container)
|
||||||
|
|
||||||
|
val fragmentClassName = intent.getStringExtra("FRAGMENT_CLASS_NAME")
|
||||||
|
val fragment = Class.forName(fragmentClassName).newInstance() as Fragment
|
||||||
|
|
||||||
|
supportFragmentManager.beginTransaction()
|
||||||
|
.replace(R.id.fragment_container, fragment)
|
||||||
|
.commit()
|
||||||
|
}
|
||||||
|
}
|
|
@ -60,7 +60,7 @@ class MangaDownloaderService : Service() {
|
||||||
|
|
||||||
private val downloadJobs = mutableMapOf<String, Job>()
|
private val downloadJobs = mutableMapOf<String, Job>()
|
||||||
private val mutex = Mutex()
|
private val mutex = Mutex()
|
||||||
var isCurrentlyProcessing = false
|
private var isCurrentlyProcessing = false
|
||||||
|
|
||||||
override fun onBind(intent: Intent?): IBinder? {
|
override fun onBind(intent: Intent?): IBinder? {
|
||||||
// This is only required for bound services.
|
// This is only required for bound services.
|
||||||
|
@ -78,7 +78,7 @@ class MangaDownloaderService : Service() {
|
||||||
setProgress(0, 0, false)
|
setProgress(0, 0, false)
|
||||||
}
|
}
|
||||||
startForeground(NOTIFICATION_ID, builder.build())
|
startForeground(NOTIFICATION_ID, builder.build())
|
||||||
registerReceiver(cancelReceiver, IntentFilter(ACTION_CANCEL_DOWNLOAD))
|
ContextCompat.registerReceiver(this, cancelReceiver, IntentFilter(ACTION_CANCEL_DOWNLOAD), ContextCompat.RECEIVER_NOT_EXPORTED)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroy() {
|
override fun onDestroy() {
|
||||||
|
|
|
@ -17,7 +17,7 @@ class OfflineMangaAdapter(private val context: Context, private val items: List<
|
||||||
return items.size
|
return items.size
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getItem(position: Int): Any? {
|
override fun getItem(position: Int): Any {
|
||||||
return items[position]
|
return items[position]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -95,7 +95,7 @@ class AnimePageAdapter : RecyclerView.Adapter<AnimePageAdapter.AnimePageViewHold
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.animeUserAvatar.setSafeOnClickListener {
|
binding.animeUserAvatar.setSafeOnClickListener {
|
||||||
SettingsDialogFragment().show((it.context as AppCompatActivity).supportFragmentManager, "dialog")
|
SettingsDialogFragment(SettingsDialogFragment.Companion.PageType.ANIME).show((it.context as AppCompatActivity).supportFragmentManager, "dialog")
|
||||||
}
|
}
|
||||||
|
|
||||||
listOf(
|
listOf(
|
||||||
|
|
|
@ -107,7 +107,7 @@ class HomeFragment : Fragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.homeUserAvatarContainer.setSafeOnClickListener {
|
binding.homeUserAvatarContainer.setSafeOnClickListener {
|
||||||
SettingsDialogFragment().show(parentFragmentManager, "dialog")
|
SettingsDialogFragment(SettingsDialogFragment.Companion.PageType.HOME).show(parentFragmentManager, "dialog")
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.homeContainer.updateLayoutParams<ViewGroup.MarginLayoutParams> {
|
binding.homeContainer.updateLayoutParams<ViewGroup.MarginLayoutParams> {
|
||||||
|
|
|
@ -89,7 +89,7 @@ class MangaPageAdapter : RecyclerView.Adapter<MangaPageAdapter.MangaPageViewHold
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.mangaUserAvatar.setSafeOnClickListener {
|
binding.mangaUserAvatar.setSafeOnClickListener {
|
||||||
SettingsDialogFragment().show((it.context as AppCompatActivity).supportFragmentManager, "dialog")
|
SettingsDialogFragment(SettingsDialogFragment.Companion.PageType.MANGA).show((it.context as AppCompatActivity).supportFragmentManager, "dialog")
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.mangaSearchBar.setEndIconOnClickListener {
|
binding.mangaSearchBar.setEndIconOnClickListener {
|
||||||
|
|
|
@ -1,32 +1,109 @@
|
||||||
package ani.dantotsu.home
|
package ani.dantotsu.home
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.graphics.drawable.GradientDrawable
|
||||||
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
|
import androidx.core.view.doOnAttach
|
||||||
import androidx.core.view.updateLayoutParams
|
import androidx.core.view.updateLayoutParams
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import androidx.fragment.app.FragmentManager
|
||||||
|
import androidx.lifecycle.Lifecycle
|
||||||
|
import androidx.viewpager2.adapter.FragmentStateAdapter
|
||||||
|
import ani.dantotsu.R
|
||||||
|
import ani.dantotsu.ZoomOutPageTransformer
|
||||||
|
import ani.dantotsu.connections.anilist.Anilist
|
||||||
import ani.dantotsu.databinding.ActivityNoInternetBinding
|
import ani.dantotsu.databinding.ActivityNoInternetBinding
|
||||||
|
import ani.dantotsu.download.manga.OfflineMangaFragment
|
||||||
|
import ani.dantotsu.initActivity
|
||||||
import ani.dantotsu.isOnline
|
import ani.dantotsu.isOnline
|
||||||
|
import ani.dantotsu.loadData
|
||||||
import ani.dantotsu.navBarHeight
|
import ani.dantotsu.navBarHeight
|
||||||
|
import ani.dantotsu.offline.OfflineFragment
|
||||||
|
import ani.dantotsu.selectedOption
|
||||||
|
import ani.dantotsu.settings.UserInterfaceSettings
|
||||||
import ani.dantotsu.startMainActivity
|
import ani.dantotsu.startMainActivity
|
||||||
import ani.dantotsu.statusBarHeight
|
import ani.dantotsu.statusBarHeight
|
||||||
import ani.dantotsu.themes.ThemeManager
|
import ani.dantotsu.themes.ThemeManager
|
||||||
|
import nl.joery.animatedbottombar.AnimatedBottomBar
|
||||||
|
|
||||||
class NoInternet : AppCompatActivity() {
|
class NoInternet : AppCompatActivity() {
|
||||||
|
private lateinit var binding: ActivityNoInternetBinding
|
||||||
|
lateinit var bottomBar: AnimatedBottomBar
|
||||||
|
private var uiSettings = UserInterfaceSettings()
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
ThemeManager(this).applyTheme()
|
ThemeManager(this).applyTheme()
|
||||||
|
|
||||||
val binding = ActivityNoInternetBinding.inflate(layoutInflater)
|
binding = ActivityNoInternetBinding.inflate(layoutInflater)
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
|
|
||||||
binding.refreshContainer.updateLayoutParams<ViewGroup.MarginLayoutParams> {
|
val _bottomBar = findViewById<AnimatedBottomBar>(R.id.navbar)
|
||||||
topMargin = statusBarHeight
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||||
|
|
||||||
|
val backgroundDrawable = _bottomBar.background as GradientDrawable
|
||||||
|
val currentColor = backgroundDrawable.color?.defaultColor ?: 0
|
||||||
|
val semiTransparentColor = (currentColor and 0x00FFFFFF) or 0xE8000000.toInt()
|
||||||
|
backgroundDrawable.setColor(semiTransparentColor)
|
||||||
|
_bottomBar.background = backgroundDrawable
|
||||||
|
}
|
||||||
|
val colorOverflow = this.getSharedPreferences("Dantotsu", Context.MODE_PRIVATE)
|
||||||
|
.getBoolean("colorOverflow", false)
|
||||||
|
if (!colorOverflow) {
|
||||||
|
_bottomBar.background = ContextCompat.getDrawable(this, R.drawable.bottom_nav_gray)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.root.doOnAttach {
|
||||||
|
initActivity(this)
|
||||||
|
uiSettings = loadData("ui_settings") ?: uiSettings
|
||||||
|
selectedOption = uiSettings.defaultStartUpTab
|
||||||
|
binding.includedNavbar.navbarContainer.updateLayoutParams<ViewGroup.MarginLayoutParams> {
|
||||||
bottomMargin = navBarHeight
|
bottomMargin = navBarHeight
|
||||||
}
|
}
|
||||||
binding.refreshButton.setOnClickListener {
|
|
||||||
if (isOnline(this)) {
|
|
||||||
startMainActivity(this)
|
|
||||||
}
|
}
|
||||||
|
val navbar = binding.includedNavbar.navbar
|
||||||
|
ani.dantotsu.bottomBar = navbar
|
||||||
|
navbar.visibility = View.VISIBLE
|
||||||
|
val mainViewPager = binding.viewpager
|
||||||
|
mainViewPager.isUserInputEnabled = false
|
||||||
|
mainViewPager.adapter = ViewPagerAdapter(supportFragmentManager, lifecycle)
|
||||||
|
mainViewPager.setPageTransformer(ZoomOutPageTransformer(uiSettings))
|
||||||
|
navbar.setOnTabSelectListener(object :
|
||||||
|
AnimatedBottomBar.OnTabSelectListener {
|
||||||
|
override fun onTabSelected(
|
||||||
|
lastIndex: Int,
|
||||||
|
lastTab: AnimatedBottomBar.Tab?,
|
||||||
|
newIndex: Int,
|
||||||
|
newTab: AnimatedBottomBar.Tab
|
||||||
|
) {
|
||||||
|
navbar.animate().translationZ(12f).setDuration(200).start()
|
||||||
|
selectedOption = newIndex
|
||||||
|
mainViewPager.setCurrentItem(newIndex, false)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
navbar.selectTabAt(selectedOption)
|
||||||
|
|
||||||
|
//supportFragmentManager.beginTransaction().replace(binding.fragmentContainer.id, OfflineFragment()).commit()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ViewPagerAdapter(fragmentManager: FragmentManager, lifecycle: Lifecycle) :
|
||||||
|
FragmentStateAdapter(fragmentManager, lifecycle) {
|
||||||
|
|
||||||
|
override fun getItemCount(): Int = 3
|
||||||
|
|
||||||
|
override fun createFragment(position: Int): Fragment {
|
||||||
|
when (position) {
|
||||||
|
0 -> return OfflineFragment()
|
||||||
|
1 -> return OfflineFragment()
|
||||||
|
2 -> return OfflineMangaFragment()
|
||||||
|
}
|
||||||
|
return LoginFragment()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -94,7 +94,7 @@ class MangaChapterAdapter(
|
||||||
fun bind(chapterNumber: String) {
|
fun bind(chapterNumber: String) {
|
||||||
if (activeDownloads.contains(chapterNumber)) {
|
if (activeDownloads.contains(chapterNumber)) {
|
||||||
// Show spinner
|
// Show spinner
|
||||||
binding.itemDownload.setImageResource(R.drawable.spinner_icon_manga)
|
binding.itemDownload.setImageResource(R.drawable.ic_round_refresh_24)
|
||||||
} else if(downloadedChapters.contains(chapterNumber)) {
|
} else if(downloadedChapters.contains(chapterNumber)) {
|
||||||
// Show checkmark
|
// Show checkmark
|
||||||
binding.itemDownload.setImageResource(R.drawable.ic_check)
|
binding.itemDownload.setImageResource(R.drawable.ic_check)
|
||||||
|
|
|
@ -74,7 +74,9 @@ class MangaReadAdapter(
|
||||||
setLanguageList(0,i)
|
setLanguageList(0,i)
|
||||||
}
|
}
|
||||||
subscribeButton(false)
|
subscribeButton(false)
|
||||||
fragment.loadChapters(i, false)
|
//invalidate if it's the last source
|
||||||
|
val invalidate = i == mangaReadSources.names.size - 1
|
||||||
|
fragment.loadChapters(i, invalidate)
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.animeSourceLanguage.setOnItemClickListener { _, _, i, _ ->
|
binding.animeSourceLanguage.setOnItemClickListener { _, _, i, _ ->
|
||||||
|
|
|
@ -118,7 +118,7 @@ abstract class BaseImageAdapter(
|
||||||
abstract suspend fun loadImage(position: Int, parent: View): Boolean
|
abstract suspend fun loadImage(position: Int, parent: View): Boolean
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
suspend fun Context.loadBitmap_old(link: FileUrl, transforms: List<BitmapTransformation>): Bitmap? {
|
suspend fun Context.loadBitmap_old(link: FileUrl, transforms: List<BitmapTransformation>): Bitmap? { //still used in some places
|
||||||
return tryWithSuspend {
|
return tryWithSuspend {
|
||||||
withContext(Dispatchers.IO) {
|
withContext(Dispatchers.IO) {
|
||||||
Glide.with(this@loadBitmap_old)
|
Glide.with(this@loadBitmap_old)
|
||||||
|
@ -154,8 +154,9 @@ abstract class BaseImageAdapter(
|
||||||
.asBitmap()
|
.asBitmap()
|
||||||
.let {
|
.let {
|
||||||
val fileUri = Uri.fromFile(File(link.url)).toString()
|
val fileUri = Uri.fromFile(File(link.url)).toString()
|
||||||
if (fileUri.startsWith("file://")) {
|
val localFile = File(link.url)
|
||||||
it.load(fileUri)
|
if (localFile.exists()) {
|
||||||
|
it.load(localFile.absoluteFile)
|
||||||
.skipMemoryCache(true)
|
.skipMemoryCache(true)
|
||||||
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
||||||
} else {
|
} else {
|
||||||
|
|
29
app/src/main/java/ani/dantotsu/offline/OfflineFragment.kt
Normal file
29
app/src/main/java/ani/dantotsu/offline/OfflineFragment.kt
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
package ani.dantotsu.offline
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.core.view.updateLayoutParams
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import ani.dantotsu.databinding.FragmentOfflineBinding
|
||||||
|
import ani.dantotsu.isOnline
|
||||||
|
import ani.dantotsu.navBarHeight
|
||||||
|
import ani.dantotsu.startMainActivity
|
||||||
|
import ani.dantotsu.statusBarHeight
|
||||||
|
|
||||||
|
class OfflineFragment : Fragment() {
|
||||||
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||||
|
val binding = FragmentOfflineBinding.inflate(inflater, container, false)
|
||||||
|
binding.refreshContainer.updateLayoutParams<ViewGroup.MarginLayoutParams> {
|
||||||
|
topMargin = statusBarHeight
|
||||||
|
bottomMargin = navBarHeight
|
||||||
|
}
|
||||||
|
binding.refreshButton.setOnClickListener {
|
||||||
|
if (isOnline(requireContext())) {
|
||||||
|
startMainActivity(requireActivity())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return binding.root
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,6 +10,7 @@ import android.content.IntentFilter
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Environment
|
import android.os.Environment
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.core.content.FileProvider
|
import androidx.core.content.FileProvider
|
||||||
import androidx.core.content.getSystemService
|
import androidx.core.content.getSystemService
|
||||||
import androidx.fragment.app.FragmentActivity
|
import androidx.fragment.app.FragmentActivity
|
||||||
|
@ -142,7 +143,8 @@ object AppUpdater {
|
||||||
-1
|
-1
|
||||||
}
|
}
|
||||||
if (id == -1L) return true
|
if (id == -1L) return true
|
||||||
registerReceiver(
|
ContextCompat.registerReceiver(
|
||||||
|
this,
|
||||||
object : BroadcastReceiver() {
|
object : BroadcastReceiver() {
|
||||||
@SuppressLint("Range")
|
@SuppressLint("Range")
|
||||||
override fun onReceive(context: Context?, intent: Intent?) {
|
override fun onReceive(context: Context?, intent: Intent?) {
|
||||||
|
@ -171,7 +173,8 @@ object AppUpdater {
|
||||||
logError(e)
|
logError(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE)
|
}, IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE),
|
||||||
|
ContextCompat.RECEIVER_NOT_EXPORTED
|
||||||
)
|
)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
|
@ -150,7 +150,7 @@ class DynamicAnimeParser(extension: AnimeExtension.Installed) : AnimeParser() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
override suspend fun getVideoExtractor(server: VideoServer): VideoExtractor? {
|
override suspend fun getVideoExtractor(server: VideoServer): VideoExtractor {
|
||||||
return VideoServerPassthrough(server)
|
return VideoServerPassthrough(server)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -51,7 +51,7 @@ abstract class BaseParser {
|
||||||
* **/
|
* **/
|
||||||
open suspend fun autoSearch(mediaObj: Media): ShowResponse? {
|
open suspend fun autoSearch(mediaObj: Media): ShowResponse? {
|
||||||
var response: ShowResponse? = null//loadSavedShowResponse(mediaObj.id)
|
var response: ShowResponse? = null//loadSavedShowResponse(mediaObj.id)
|
||||||
if (response != null) {
|
if (response != null && this !is OfflineMangaParser) {
|
||||||
saveShowResponse(mediaObj.id, response, true)
|
saveShowResponse(mediaObj.id, response, true)
|
||||||
} else {
|
} else {
|
||||||
setUserText("Searching : ${mediaObj.mainName()}")
|
setUserText("Searching : ${mediaObj.mainName()}")
|
||||||
|
|
|
@ -10,14 +10,17 @@ import android.util.TypedValue
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import android.widget.Switch
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import ani.dantotsu.*
|
import ani.dantotsu.*
|
||||||
import ani.dantotsu.connections.anilist.Anilist
|
import ani.dantotsu.connections.anilist.Anilist
|
||||||
import ani.dantotsu.others.imagesearch.ImageSearchActivity
|
import ani.dantotsu.others.imagesearch.ImageSearchActivity
|
||||||
import ani.dantotsu.databinding.BottomSheetSettingsBinding
|
import ani.dantotsu.databinding.BottomSheetSettingsBinding
|
||||||
|
import ani.dantotsu.download.DownloadContainerActivity
|
||||||
|
import ani.dantotsu.download.manga.OfflineMangaFragment
|
||||||
|
|
||||||
|
|
||||||
class SettingsDialogFragment : BottomSheetDialogFragment() {
|
class SettingsDialogFragment(val pageType: PageType) : BottomSheetDialogFragment() {
|
||||||
private var _binding: BottomSheetSettingsBinding? = null
|
private var _binding: BottomSheetSettingsBinding? = null
|
||||||
private val binding get() = _binding!!
|
private val binding get() = _binding!!
|
||||||
|
|
||||||
|
@ -70,6 +73,13 @@ class SettingsDialogFragment : BottomSheetDialogFragment() {
|
||||||
dismiss()
|
dismiss()
|
||||||
}
|
}
|
||||||
binding.settingsDownloads.setSafeOnClickListener {
|
binding.settingsDownloads.setSafeOnClickListener {
|
||||||
|
when(pageType) {
|
||||||
|
PageType.MANGA -> {
|
||||||
|
val intent = Intent(activity, DownloadContainerActivity::class.java)
|
||||||
|
intent.putExtra("FRAGMENT_CLASS_NAME", OfflineMangaFragment::class.java.name)
|
||||||
|
startActivity(intent)
|
||||||
|
}
|
||||||
|
PageType.ANIME -> {
|
||||||
try {
|
try {
|
||||||
val arrayOfFiles = ContextCompat.getExternalFilesDirs(requireContext(), null)
|
val arrayOfFiles = ContextCompat.getExternalFilesDirs(requireContext(), null)
|
||||||
startActivity(
|
startActivity(
|
||||||
|
@ -82,6 +92,23 @@ class SettingsDialogFragment : BottomSheetDialogFragment() {
|
||||||
} catch (e: ActivityNotFoundException) {
|
} catch (e: ActivityNotFoundException) {
|
||||||
toast(getString(R.string.file_manager_not_found))
|
toast(getString(R.string.file_manager_not_found))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
PageType.HOME -> {
|
||||||
|
try {
|
||||||
|
val arrayOfFiles = ContextCompat.getExternalFilesDirs(requireContext(), null)
|
||||||
|
startActivity(
|
||||||
|
if (loadData<Boolean>("sd_dl") == true && arrayOfFiles.size > 1 && arrayOfFiles[0] != null && arrayOfFiles[1] != null) {
|
||||||
|
val parentDirectory = arrayOfFiles[1].toString()
|
||||||
|
val intent = Intent(Intent.ACTION_VIEW)
|
||||||
|
intent.setDataAndType(Uri.parse(parentDirectory), "resource/folder")
|
||||||
|
} else Intent(DownloadManager.ACTION_VIEW_DOWNLOADS)
|
||||||
|
)
|
||||||
|
} catch (e: ActivityNotFoundException) {
|
||||||
|
toast(getString(R.string.file_manager_not_found))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
dismiss()
|
dismiss()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -90,4 +117,10 @@ class SettingsDialogFragment : BottomSheetDialogFragment() {
|
||||||
super.onDestroyView()
|
super.onDestroyView()
|
||||||
_binding = null
|
_binding = null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
companion object{
|
||||||
|
enum class PageType{
|
||||||
|
MANGA, ANIME, HOME
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -8,6 +8,7 @@ import android.content.Intent
|
||||||
import android.content.IntentFilter
|
import android.content.IntentFilter
|
||||||
import android.content.pm.PackageInstaller
|
import android.content.pm.PackageInstaller
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
import eu.kanade.tachiyomi.extension.InstallStep
|
import eu.kanade.tachiyomi.extension.InstallStep
|
||||||
import eu.kanade.tachiyomi.util.lang.use
|
import eu.kanade.tachiyomi.util.lang.use
|
||||||
import eu.kanade.tachiyomi.util.system.getParcelableExtraCompat
|
import eu.kanade.tachiyomi.util.system.getParcelableExtraCompat
|
||||||
|
@ -100,7 +101,7 @@ class PackageInstallerInstallerAnime(private val service: Service) : InstallerAn
|
||||||
}
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
service.registerReceiver(packageActionReceiver, IntentFilter(INSTALL_ACTION))
|
ContextCompat.registerReceiver(service, packageActionReceiver, IntentFilter(INSTALL_ACTION), ContextCompat.RECEIVER_NOT_EXPORTED)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ import android.content.BroadcastReceiver
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.IntentFilter
|
import android.content.IntentFilter
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
import eu.kanade.tachiyomi.extension.anime.model.AnimeExtension
|
import eu.kanade.tachiyomi.extension.anime.model.AnimeExtension
|
||||||
import eu.kanade.tachiyomi.extension.anime.model.AnimeLoadResult
|
import eu.kanade.tachiyomi.extension.anime.model.AnimeLoadResult
|
||||||
import kotlinx.coroutines.CoroutineStart
|
import kotlinx.coroutines.CoroutineStart
|
||||||
|
@ -27,7 +28,7 @@ internal class AnimeExtensionInstallReceiver(private val listener: Listener) :
|
||||||
* Registers this broadcast receiver
|
* Registers this broadcast receiver
|
||||||
*/
|
*/
|
||||||
fun register(context: Context) {
|
fun register(context: Context) {
|
||||||
context.registerReceiver(this, filter)
|
ContextCompat.registerReceiver(context, this, filter, ContextCompat.RECEIVER_NOT_EXPORTED)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -216,7 +216,7 @@ internal class AnimeExtensionInstaller(private val context: Context) {
|
||||||
isRegistered = true
|
isRegistered = true
|
||||||
|
|
||||||
val filter = IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE)
|
val filter = IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE)
|
||||||
context.registerReceiver(this, filter)
|
ContextCompat.registerReceiver(context, this, filter, ContextCompat.RECEIVER_EXPORTED)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -8,6 +8,7 @@ import android.content.Intent
|
||||||
import android.content.IntentFilter
|
import android.content.IntentFilter
|
||||||
import android.content.pm.PackageInstaller
|
import android.content.pm.PackageInstaller
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
import eu.kanade.tachiyomi.extension.InstallStep
|
import eu.kanade.tachiyomi.extension.InstallStep
|
||||||
import eu.kanade.tachiyomi.util.lang.use
|
import eu.kanade.tachiyomi.util.lang.use
|
||||||
import eu.kanade.tachiyomi.util.system.getParcelableExtraCompat
|
import eu.kanade.tachiyomi.util.system.getParcelableExtraCompat
|
||||||
|
@ -100,7 +101,7 @@ class PackageInstallerInstallerManga(private val service: Service) : InstallerMa
|
||||||
}
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
service.registerReceiver(packageActionReceiver, IntentFilter(INSTALL_ACTION))
|
ContextCompat.registerReceiver(service, packageActionReceiver, IntentFilter(INSTALL_ACTION), ContextCompat.RECEIVER_NOT_EXPORTED)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ import android.content.BroadcastReceiver
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.IntentFilter
|
import android.content.IntentFilter
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
import eu.kanade.tachiyomi.extension.manga.model.MangaExtension
|
import eu.kanade.tachiyomi.extension.manga.model.MangaExtension
|
||||||
import eu.kanade.tachiyomi.extension.manga.model.MangaLoadResult
|
import eu.kanade.tachiyomi.extension.manga.model.MangaLoadResult
|
||||||
import kotlinx.coroutines.CoroutineStart
|
import kotlinx.coroutines.CoroutineStart
|
||||||
|
@ -27,7 +28,7 @@ internal class MangaExtensionInstallReceiver(private val listener: Listener) :
|
||||||
* Registers this broadcast receiver
|
* Registers this broadcast receiver
|
||||||
*/
|
*/
|
||||||
fun register(context: Context) {
|
fun register(context: Context) {
|
||||||
context.registerReceiver(this, filter)
|
ContextCompat.registerReceiver(context, this, filter, ContextCompat.RECEIVER_NOT_EXPORTED)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -213,7 +213,7 @@ internal class MangaExtensionInstaller(private val context: Context) {
|
||||||
isRegistered = true
|
isRegistered = true
|
||||||
|
|
||||||
val filter = IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE)
|
val filter = IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE)
|
||||||
context.registerReceiver(this, filter)
|
ContextCompat.registerReceiver(context, this, filter, ContextCompat.RECEIVER_EXPORTED)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
5
app/src/main/res/layout/activity_container.xml
Normal file
5
app/src/main/res/layout/activity_container.xml
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:id="@+id/fragment_container"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent" />
|
|
@ -19,39 +19,9 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent" />
|
android:layout_height="match_parent" />
|
||||||
|
|
||||||
<FrameLayout
|
<include
|
||||||
android:id="@+id/navbar_container"
|
android:id="@+id/included_navbar"
|
||||||
android:layout_width="match_parent"
|
layout="@layout/item_navbar" />
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="bottom">
|
|
||||||
|
|
||||||
<nl.joery.animatedbottombar.AnimatedBottomBar
|
|
||||||
android:id="@+id/navbar"
|
|
||||||
android:layout_width="240dp"
|
|
||||||
android:layout_height="56dp"
|
|
||||||
android:layout_gravity="center_horizontal"
|
|
||||||
android:layout_marginTop="16dp"
|
|
||||||
android:layout_marginBottom="32dp"
|
|
||||||
android:background="@drawable/bottom_nav"
|
|
||||||
android:elevation="4dp"
|
|
||||||
android:padding="8dp"
|
|
||||||
android:translationZ="12dp"
|
|
||||||
android:visibility="gone"
|
|
||||||
|
|
||||||
app:abb_animationDuration="300"
|
|
||||||
app:abb_animationInterpolator="@anim/over_shoot"
|
|
||||||
app:abb_badgeBackgroundColor="#F44336"
|
|
||||||
app:abb_indicatorColor="?attr/colorTertiary"
|
|
||||||
app:abb_indicatorLocation="bottom"
|
|
||||||
app:abb_indicatorMargin="28dp"
|
|
||||||
app:abb_selectedTabType="text"
|
|
||||||
app:abb_tabColor="?attr/colorOutline"
|
|
||||||
app:abb_tabColorDisabled="?attr/colorPrimaryContainer"
|
|
||||||
app:abb_tabColorSelected="?attr/colorPrimary"
|
|
||||||
app:abb_tabs="@menu/bottom_navbar_menu"
|
|
||||||
app:abb_textAppearance="@style/NavBarText"
|
|
||||||
tools:visibility="visible" />
|
|
||||||
</FrameLayout>
|
|
||||||
|
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
android:id="@+id/fragmentContainer"
|
android:id="@+id/fragmentContainer"
|
||||||
|
|
|
@ -9,52 +9,20 @@
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
tools:ignore="ContentDescription" />
|
tools:ignore="ContentDescription" />
|
||||||
|
|
||||||
|
<androidx.viewpager2.widget.ViewPager2
|
||||||
|
android:id="@+id/viewpager"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent" />
|
||||||
|
|
||||||
|
<include
|
||||||
|
android:id="@+id/included_navbar"
|
||||||
|
layout="@layout/item_navbar" />
|
||||||
|
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
android:id="@+id/refreshContainer"
|
android:id="@+id/fragmentContainer"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:gravity="center"
|
|
||||||
android:orientation="vertical">
|
|
||||||
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/noInternetSad"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:fontFamily="@font/poppins_thin"
|
|
||||||
android:text="@string/sad"
|
|
||||||
android:textColor="?attr/colorPrimary"
|
|
||||||
android:textSize="64sp"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="200dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/no_internet"
|
|
||||||
android:textAlignment="center"
|
|
||||||
android:textColor="?attr/colorOnBackground"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@+id/noInternetSad" />
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<Button
|
|
||||||
android:id="@+id/refreshButton"
|
|
||||||
android:layout_width="150dp"
|
|
||||||
android:layout_height="64dp"
|
|
||||||
android:layout_gravity="bottom|center_horizontal"
|
|
||||||
android:layout_margin="128dp"
|
|
||||||
android:fontFamily="@font/poppins_bold"
|
|
||||||
android:text="@string/refresh"
|
|
||||||
app:cornerRadius="16dp"
|
|
||||||
app:icon="@drawable/ic_round_refresh_24" />
|
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
|
||||||
|
|
55
app/src/main/res/layout/fragment_offline.xml
Normal file
55
app/src/main/res/layout/fragment_offline.xml
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
android:id="@+id/refreshContainer"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:gravity="center"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/noInternetSad"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:fontFamily="@font/poppins_thin"
|
||||||
|
android:text="@string/sad"
|
||||||
|
android:textColor="?attr/colorPrimary"
|
||||||
|
android:textSize="64sp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="200dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/no_internet"
|
||||||
|
android:textAlignment="center"
|
||||||
|
android:textColor="?attr/colorOnBackground"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/noInternetSad" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/refreshButton"
|
||||||
|
android:layout_width="150dp"
|
||||||
|
android:layout_height="64dp"
|
||||||
|
android:layout_gravity="bottom|center_horizontal"
|
||||||
|
android:layout_margin="128dp"
|
||||||
|
android:fontFamily="@font/poppins_bold"
|
||||||
|
android:text="@string/refresh"
|
||||||
|
app:cornerRadius="16dp"
|
||||||
|
app:icon="@drawable/ic_round_refresh_24" />
|
||||||
|
</FrameLayout>
|
||||||
|
|
||||||
|
</FrameLayout>
|
35
app/src/main/res/layout/item_navbar.xml
Normal file
35
app/src/main/res/layout/item_navbar.xml
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:id="@+id/navbar_container"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="bottom">
|
||||||
|
|
||||||
|
<nl.joery.animatedbottombar.AnimatedBottomBar
|
||||||
|
android:id="@+id/navbar"
|
||||||
|
android:layout_width="240dp"
|
||||||
|
android:layout_height="56dp"
|
||||||
|
android:layout_gravity="center_horizontal"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
android:layout_marginBottom="32dp"
|
||||||
|
android:background="@drawable/bottom_nav"
|
||||||
|
android:elevation="4dp"
|
||||||
|
android:padding="8dp"
|
||||||
|
android:translationZ="12dp"
|
||||||
|
android:visibility="gone"
|
||||||
|
app:abb_animationDuration="300"
|
||||||
|
app:abb_animationInterpolator="@anim/over_shoot"
|
||||||
|
app:abb_badgeBackgroundColor="#F44336"
|
||||||
|
app:abb_indicatorColor="?attr/colorTertiary"
|
||||||
|
app:abb_indicatorLocation="bottom"
|
||||||
|
app:abb_indicatorMargin="28dp"
|
||||||
|
app:abb_selectedTabType="text"
|
||||||
|
app:abb_tabColor="?attr/colorOutline"
|
||||||
|
app:abb_tabColorDisabled="?attr/colorPrimaryContainer"
|
||||||
|
app:abb_tabColorSelected="?attr/colorPrimary"
|
||||||
|
app:abb_tabs="@menu/bottom_navbar_menu"
|
||||||
|
app:abb_textAppearance="@style/NavBarText"
|
||||||
|
tools:visibility="visible" />
|
||||||
|
</FrameLayout>
|
Loading…
Add table
Add a link
Reference in a new issue