various bugfixes

This commit is contained in:
Finnley Somdahl 2023-10-22 02:28:39 -05:00
parent 0b9f2bb019
commit dc959796e6
26 changed files with 685 additions and 289 deletions

View file

@ -15,7 +15,9 @@ import androidx.core.content.ContextCompat
import androidx.core.content.ContextCompat.getSystemService
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import ani.dantotsu.R
import ani.dantotsu.databinding.FragmentAnimeExtensionsBinding
@ -33,7 +35,8 @@ import rx.android.schedulers.AndroidSchedulers
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
class AnimeExtensionsFragment : Fragment(), SearchQueryHandler {
class AnimeExtensionsFragment : Fragment(),
SearchQueryHandler {
private var _binding: FragmentAnimeExtensionsBinding? = null
private val binding get() = _binding!!
@ -42,104 +45,115 @@ class AnimeExtensionsFragment : Fragment(), SearchQueryHandler {
private lateinit var extensionsRecyclerView: RecyclerView
private lateinit var allextenstionsRecyclerView: RecyclerView
private val animeExtensionManager: AnimeExtensionManager = Injekt.get<AnimeExtensionManager>()
private val extensionsAdapter = AnimeExtensionsAdapter ({ pkg ->
if(pkg.hasUpdate){
private val extensionsAdapter = AnimeExtensionsAdapter({ pkg ->
if (isAdded) { // Check if the fragment is currently added to its activity
val context = requireContext() // Store context in a variable
val notificationManager =
requireContext().getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
animeExtensionManager.updateExtension(pkg)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
{ installStep ->
val builder = NotificationCompat.Builder(
requireContext(),
Notifications.CHANNEL_DOWNLOADER_PROGRESS
)
.setSmallIcon(R.drawable.ic_round_sync_24)
.setContentTitle("Updating extension")
.setContentText("Step: $installStep")
.setPriority(NotificationCompat.PRIORITY_LOW)
notificationManager.notify(1, builder.build())
},
{ error ->
val builder = NotificationCompat.Builder(
requireContext(),
Notifications.CHANNEL_DOWNLOADER_ERROR
)
.setSmallIcon(R.drawable.ic_round_info_24)
.setContentTitle("Update failed")
.setContentText("Error: ${error.message}")
.setPriority(NotificationCompat.PRIORITY_HIGH)
notificationManager.notify(1, builder.build())
},
{
val builder = NotificationCompat.Builder(
requireContext(),
Notifications.CHANNEL_DOWNLOADER_PROGRESS
)
.setSmallIcon(androidx.media3.ui.R.drawable.exo_ic_check)
.setContentTitle("Update complete")
.setContentText("The extension has been successfully updated.")
.setPriority(NotificationCompat.PRIORITY_LOW)
notificationManager.notify(1, builder.build())
}
)
}else {
animeExtensionManager.uninstallExtension(pkg.pkgName)
context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager // Initialize NotificationManager once
if (pkg.hasUpdate) {
animeExtensionManager.updateExtension(pkg)
.observeOn(AndroidSchedulers.mainThread()) // Observe on main thread
.subscribe(
{ installStep ->
val builder = NotificationCompat.Builder(
context,
Notifications.CHANNEL_DOWNLOADER_PROGRESS
)
.setSmallIcon(R.drawable.ic_round_sync_24)
.setContentTitle("Updating extension")
.setContentText("Step: $installStep")
.setPriority(NotificationCompat.PRIORITY_LOW)
notificationManager.notify(1, builder.build())
},
{ error ->
Log.e("AnimeExtensionsAdapter", "Error: ", error) // Log the error
val builder = NotificationCompat.Builder(
context,
Notifications.CHANNEL_DOWNLOADER_ERROR
)
.setSmallIcon(R.drawable.ic_round_info_24)
.setContentTitle("Update failed")
.setContentText("Error: ${error.message}")
.setPriority(NotificationCompat.PRIORITY_HIGH)
notificationManager.notify(1, builder.build())
},
{
val builder = NotificationCompat.Builder(
context,
Notifications.CHANNEL_DOWNLOADER_PROGRESS
)
.setSmallIcon(androidx.media3.ui.R.drawable.exo_ic_check)
.setContentTitle("Update complete")
.setContentText("The extension has been successfully updated.")
.setPriority(NotificationCompat.PRIORITY_LOW)
notificationManager.notify(1, builder.build())
}
)
} else {
animeExtensionManager.uninstallExtension(pkg.pkgName)
}
}
}, skipIcons)
private val allExtensionsAdapter = AllAnimeExtensionsAdapter(lifecycleScope, { pkgName ->
val notificationManager =
requireContext().getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
val notificationManager =
requireContext().getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
// Start the installation process
animeExtensionManager.installExtension(pkgName)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
{ installStep ->
val builder = NotificationCompat.Builder(
requireContext(),
Notifications.CHANNEL_DOWNLOADER_PROGRESS
)
.setSmallIcon(R.drawable.ic_round_sync_24)
.setContentTitle("Installing extension")
.setContentText("Step: $installStep")
.setPriority(NotificationCompat.PRIORITY_LOW)
notificationManager.notify(1, builder.build())
},
{ error ->
val builder = NotificationCompat.Builder(
requireContext(),
Notifications.CHANNEL_DOWNLOADER_ERROR
)
.setSmallIcon(R.drawable.ic_round_info_24)
.setContentTitle("Installation failed")
.setContentText("Error: ${error.message}")
.setPriority(NotificationCompat.PRIORITY_HIGH)
notificationManager.notify(1, builder.build())
},
{
val builder = NotificationCompat.Builder(
requireContext(),
Notifications.CHANNEL_DOWNLOADER_PROGRESS
)
.setSmallIcon(androidx.media3.ui.R.drawable.exo_ic_check)
.setContentTitle("Installation complete")
.setContentText("The extension has been successfully installed.")
.setPriority(NotificationCompat.PRIORITY_LOW)
notificationManager.notify(1, builder.build())
}
)
}, skipIcons)
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
// Start the installation process
animeExtensionManager.installExtension(pkgName)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
{ installStep ->
val builder = NotificationCompat.Builder(
requireContext(),
Notifications.CHANNEL_DOWNLOADER_PROGRESS
)
.setSmallIcon(R.drawable.ic_round_sync_24)
.setContentTitle("Installing extension")
.setContentText("Step: $installStep")
.setPriority(NotificationCompat.PRIORITY_LOW)
notificationManager.notify(1, builder.build())
},
{ error ->
val builder = NotificationCompat.Builder(
requireContext(),
Notifications.CHANNEL_DOWNLOADER_ERROR
)
.setSmallIcon(R.drawable.ic_round_info_24)
.setContentTitle("Installation failed")
.setContentText("Error: ${error.message}")
.setPriority(NotificationCompat.PRIORITY_HIGH)
notificationManager.notify(1, builder.build())
},
{
val builder = NotificationCompat.Builder(
requireContext(),
Notifications.CHANNEL_DOWNLOADER_PROGRESS
)
.setSmallIcon(androidx.media3.ui.R.drawable.exo_ic_check)
.setContentTitle("Installation complete")
.setContentText("The extension has been successfully installed.")
.setPriority(NotificationCompat.PRIORITY_LOW)
notificationManager.notify(1, builder.build())
}
)
}, skipIcons)
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = FragmentAnimeExtensionsBinding.inflate(inflater, container, false)
extensionsRecyclerView = binding.animeExtensionsRecyclerView
extensionsRecyclerView.layoutManager = LinearLayoutManager( requireContext())
extensionsRecyclerView.layoutManager = LinearLayoutManager(requireContext())
extensionsRecyclerView.adapter = extensionsAdapter
allextenstionsRecyclerView = binding.allAnimeExtensionsRecyclerView
allextenstionsRecyclerView.layoutManager = LinearLayoutManager( requireContext())
allextenstionsRecyclerView.layoutManager = LinearLayoutManager(requireContext())
allextenstionsRecyclerView.adapter = allExtensionsAdapter
lifecycleScope.launch {
@ -156,11 +170,11 @@ class AnimeExtensionsFragment : Fragment(), SearchQueryHandler {
Pair(availableExtensions, installedExtensions)
}.collect { pair ->
val (availableExtensions, installedExtensions) = pair
allExtensionsAdapter.updateData(availableExtensions, installedExtensions)
}
}
val extensionsRecyclerView: RecyclerView = binding.animeExtensionsRecyclerView
return binding.root
}
@ -169,7 +183,6 @@ class AnimeExtensionsFragment : Fragment(), SearchQueryHandler {
allExtensionsAdapter.filter("") // Reset the filter
allextenstionsRecyclerView.visibility = View.VISIBLE
extensionsRecyclerView.visibility = View.VISIBLE
println("asdf: ${allExtensionsAdapter.getItemCount()}")
} else {
allExtensionsAdapter.filter(query)
allextenstionsRecyclerView.visibility = View.VISIBLE
@ -182,14 +195,17 @@ class AnimeExtensionsFragment : Fragment(), SearchQueryHandler {
}
private class AnimeExtensionsAdapter(private val onUninstallClicked: (AnimeExtension.Installed) -> Unit, skipIcons: Boolean) : RecyclerView.Adapter<AnimeExtensionsAdapter.ViewHolder>() {
private class AnimeExtensionsAdapter(
private val onUninstallClicked: (AnimeExtension.Installed) -> Unit,
skipIcons: Boolean
) : ListAdapter<AnimeExtension.Installed, AnimeExtensionsAdapter.ViewHolder>(
DIFF_CALLBACK_INSTALLED
) {
private var extensions: List<AnimeExtension.Installed> = emptyList()
val skipIcons = skipIcons
fun updateData(newExtensions: List<AnimeExtension.Installed>) {
extensions = newExtensions
notifyDataSetChanged()
submitList(newExtensions) // Use submitList instead of manual list handling
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
@ -199,15 +215,20 @@ class AnimeExtensionsFragment : Fragment(), SearchQueryHandler {
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val extension = extensions[position]
val extension = getItem(position) // Use getItem() from ListAdapter
holder.extensionNameTextView.text = extension.name
if (!skipIcons) {
holder.extensionIconImageView.setImageDrawable(extension.icon)
}
if(extension.hasUpdate){
if (extension.hasUpdate) {
holder.closeTextView.text = "Update"
holder.closeTextView.setTextColor(ContextCompat.getColor(holder.itemView.context, R.color.warning))
}else{
holder.closeTextView.setTextColor(
ContextCompat.getColor(
holder.itemView.context,
R.color.warning
)
)
} else {
holder.closeTextView.text = "Uninstall"
}
holder.closeTextView.setOnClickListener {
@ -215,59 +236,91 @@ class AnimeExtensionsFragment : Fragment(), SearchQueryHandler {
}
}
override fun getItemCount(): Int = extensions.size
inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
val extensionNameTextView: TextView = view.findViewById(R.id.extensionNameTextView)
val extensionIconImageView: ImageView = view.findViewById(R.id.extensionIconImageView)
val closeTextView: TextView = view.findViewById(R.id.closeTextView)
}
companion object {
val DIFF_CALLBACK_INSTALLED =
object : DiffUtil.ItemCallback<AnimeExtension.Installed>() {
override fun areItemsTheSame(
oldItem: AnimeExtension.Installed,
newItem: AnimeExtension.Installed
): Boolean {
return oldItem.pkgName == newItem.pkgName
}
override fun areContentsTheSame(
oldItem: AnimeExtension.Installed,
newItem: AnimeExtension.Installed
): Boolean {
return oldItem == newItem
}
}
}
}
private class AllAnimeExtensionsAdapter(private val coroutineScope: CoroutineScope,
private val onButtonClicked: (AnimeExtension.Available) -> Unit, skipIcons: Boolean) : RecyclerView.Adapter<AllAnimeExtensionsAdapter.ViewHolder>() {
private var extensions: List<AnimeExtension.Available> = emptyList()
private class AllAnimeExtensionsAdapter(
private val coroutineScope: CoroutineScope,
private val onButtonClicked: (AnimeExtension.Available) -> Unit,
skipIcons: Boolean
) : ListAdapter<AnimeExtension.Available, AllAnimeExtensionsAdapter.ViewHolder>(
DIFF_CALLBACK_AVAILABLE
) {
val skipIcons = skipIcons
fun updateData(newExtensions: List<AnimeExtension.Available>, installedExtensions: List<AnimeExtension.Installed> = emptyList()) {
val installedPkgNames = installedExtensions.map { it.pkgName }.toSet()
extensions = newExtensions.filter { it.pkgName !in installedPkgNames }
filteredExtensions = extensions
notifyDataSetChanged()
fun updateData(
newExtensions: List<AnimeExtension.Available>,
installedExtensions: List<AnimeExtension.Installed> = emptyList()
) {
coroutineScope.launch(Dispatchers.Default) {
val installedPkgNames = installedExtensions.map { it.pkgName }.toSet()
val filteredExtensions = newExtensions.filter { it.pkgName !in installedPkgNames }
// Switch back to main thread to update UI
withContext(Dispatchers.Main) {
submitList(filteredExtensions)
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AllAnimeExtensionsAdapter.ViewHolder {
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
): AllAnimeExtensionsAdapter.ViewHolder {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.item_extension_all, parent, false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val extension = filteredExtensions[position]
val extension = getItem(position)
holder.extensionNameTextView.text = extension.name
if (!skipIcons) {
coroutineScope.launch {
val drawable = urlToDrawable(holder.itemView.context, extension.iconUrl)
holder.extensionIconImageView.setImageDrawable(drawable)
}
Glide.with(holder.itemView.context)
.load(extension.iconUrl)
.into(holder.extensionIconImageView)
}
holder.closeTextView.text = "Install"
holder.closeTextView.setOnClickListener {
onButtonClicked(extension)
}
}
override fun getItemCount(): Int = filteredExtensions.size
private var filteredExtensions: List<AnimeExtension.Available> = emptyList()
fun filter(query: String) {
filteredExtensions = if (query.isEmpty()) {
extensions
val filteredExtensions = if (query.isEmpty()) {
currentList
} else {
extensions.filter { it.name.contains(query, ignoreCase = true) }
currentList.filter { it.name.contains(query, ignoreCase = true) }
}
notifyDataSetChanged()
submitList(filteredExtensions)
}
inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
@ -276,18 +329,24 @@ class AnimeExtensionsFragment : Fragment(), SearchQueryHandler {
val closeTextView: TextView = view.findViewById(R.id.closeTextView)
}
suspend fun urlToDrawable(context: Context, url: String): Drawable? {
return withContext(Dispatchers.IO) {
try {
return@withContext Glide.with(context)
.load(url)
.submit()
.get()
} catch (e: Exception) {
e.printStackTrace()
return@withContext null
companion object {
val DIFF_CALLBACK_AVAILABLE =
object : DiffUtil.ItemCallback<AnimeExtension.Available>() {
override fun areItemsTheSame(
oldItem: AnimeExtension.Available,
newItem: AnimeExtension.Available
): Boolean {
return oldItem.pkgName == newItem.pkgName
}
override fun areContentsTheSame(
oldItem: AnimeExtension.Available,
newItem: AnimeExtension.Available
): Boolean {
return oldItem == newItem
}
}
}
}
}
}