Initial commit

This commit is contained in:
Finnley Somdahl 2023-10-17 18:42:43 -05:00
commit 21bfbfb139
520 changed files with 47819 additions and 0 deletions

View file

@ -0,0 +1,94 @@
package ani.dantotsu.media.user
import android.annotation.SuppressLint
import android.os.Bundle
import android.view.View
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.PopupMenu
import androidx.core.content.ContextCompat
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.lifecycleScope
import ani.dantotsu.R
import ani.dantotsu.Refresh
import ani.dantotsu.databinding.ActivityListBinding
import com.google.android.material.tabs.TabLayout
import com.google.android.material.tabs.TabLayoutMediator
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
class ListActivity : AppCompatActivity() {
private lateinit var binding: ActivityListBinding
private val scope = lifecycleScope
private var selectedTabIdx = 0
@SuppressLint("SetTextI18n")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityListBinding.inflate(layoutInflater)
setContentView(binding.root)
window.statusBarColor = ContextCompat.getColor(this, R.color.nav_bg)
val anime = intent.getBooleanExtra("anime", true)
binding.listTitle.text = intent.getStringExtra("username") + "'s " + (if (anime) "Anime" else "Manga") + " List"
binding.listTabLayout.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
override fun onTabSelected(tab: TabLayout.Tab?) {
this@ListActivity.selectedTabIdx = tab?.position ?: 0
}
override fun onTabUnselected(tab: TabLayout.Tab?) { }
override fun onTabReselected(tab: TabLayout.Tab?) { }
})
val model: ListViewModel by viewModels()
model.getLists().observe(this) {
val defaultKeys = listOf("Reading", "Watching", "Completed", "Paused", "Dropped", "Planning", "Favourites", "Rewatching", "Rereading", "All")
val userKeys : Array<String> = resources.getStringArray(R.array.keys)
if (it != null) {
binding.listProgressBar.visibility = View.GONE
binding.listViewPager.adapter = ListViewPagerAdapter(it.size, false,this)
val keys = it.keys.toList().map { key -> userKeys.getOrNull(defaultKeys.indexOf(key))?: key }
val values = it.values.toList()
val savedTab = this.selectedTabIdx
TabLayoutMediator(binding.listTabLayout, binding.listViewPager) { tab, position ->
tab.text = "${keys[position]} (${values[position].size})"
}.attach()
binding.listViewPager.setCurrentItem(savedTab, false)
}
}
val live = Refresh.activity.getOrPut(this.hashCode()) { MutableLiveData(true) }
live.observe(this) {
if (it) {
scope.launch {
withContext(Dispatchers.IO) { model.loadLists(anime, intent.getIntExtra("userId", 0)) }
live.postValue(false)
}
}
}
binding.listSort.setOnClickListener {
val popup = PopupMenu(this, it)
popup.setOnMenuItemClickListener { item ->
val sort = when (item.itemId) {
R.id.score -> "score"
R.id.title -> "title"
R.id.updated -> "updatedAt"
R.id.release -> "release"
else -> null
}
binding.listProgressBar.visibility = View.VISIBLE
binding.listViewPager.adapter = null
scope.launch {
withContext(Dispatchers.IO) { model.loadLists(anime, intent.getIntExtra("userId", 0), sort) }
}
true
}
popup.inflate(R.menu.list_sort_menu)
popup.show()
}
}
}

View file

@ -0,0 +1,86 @@
package ani.dantotsu.media.user
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.recyclerview.widget.GridLayoutManager
import ani.dantotsu.databinding.FragmentListBinding
import ani.dantotsu.media.Media
import ani.dantotsu.media.MediaAdaptor
import ani.dantotsu.media.OtherDetailsViewModel
class ListFragment : Fragment() {
private var _binding: FragmentListBinding? = null
private val binding get() = _binding!!
private var pos: Int? = null
private var calendar = false
private var grid: Boolean? = null
private var list: MutableList<Media>? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
arguments?.let {
pos = it.getInt("list")
calendar = it.getBoolean("calendar")
}
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
_binding = FragmentListBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val screenWidth = resources.displayMetrics.run { widthPixels / density }
fun update() {
if (grid != null && list != null) {
val adapter = MediaAdaptor(if (grid!!) 0 else 1, list!!, requireActivity(), true)
binding.listRecyclerView.layoutManager =
GridLayoutManager(requireContext(), if (grid!!) (screenWidth / 124f).toInt() else 1)
binding.listRecyclerView.adapter = adapter
}
}
if (calendar) {
val model: OtherDetailsViewModel by activityViewModels()
model.getCalendar().observe(viewLifecycleOwner) {
if (it != null) {
list = it.values.toList().getOrNull(pos!!)
update()
}
}
grid = true
} else {
val model: ListViewModel by activityViewModels()
model.getLists().observe(viewLifecycleOwner) {
if (it != null) {
list = it.values.toList().getOrNull(pos!!)
update()
}
}
model.grid.observe(viewLifecycleOwner) {
grid = it
update()
}
}
}
companion object {
fun newInstance(pos: Int, calendar: Boolean = false): ListFragment =
ListFragment().apply {
arguments = Bundle().apply {
putInt("list", pos)
putBoolean("calendar", calendar)
}
}
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
}

View file

@ -0,0 +1,21 @@
package ani.dantotsu.media.user
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import ani.dantotsu.connections.anilist.Anilist
import ani.dantotsu.loadData
import ani.dantotsu.media.Media
import ani.dantotsu.tryWithSuspend
class ListViewModel : ViewModel() {
var grid = MutableLiveData(loadData<Boolean>("listGrid") ?: true)
private val lists = MutableLiveData<MutableMap<String, ArrayList<Media>>>()
fun getLists(): LiveData<MutableMap<String, ArrayList<Media>>> = lists
suspend fun loadLists(anime: Boolean, userId: Int, sortOrder: String? = null) {
tryWithSuspend {
lists.postValue(Anilist.query.getMediaLists(anime, userId, sortOrder))
}
}
}

View file

@ -0,0 +1,11 @@
package ani.dantotsu.media.user
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.viewpager2.adapter.FragmentStateAdapter
class ListViewPagerAdapter(private val size: Int, private val calendar: Boolean, fragment: FragmentActivity) :
FragmentStateAdapter(fragment) {
override fun getItemCount(): Int = size
override fun createFragment(position: Int): Fragment = ListFragment.newInstance(position, calendar)
}