diff --git a/app/build.gradle b/app/build.gradle index b4ab706b..12fc9b90 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -6,6 +6,10 @@ plugins { id 'com.google.devtools.ksp' } +def gitCommitHash = providers.exec { + commandLine("git", "rev-parse", "--verify", "--short", "HEAD") +}.standardOutput.asText.get().trim() + android { compileSdk 34 @@ -38,7 +42,7 @@ android { buildTypes { alpha { applicationIdSuffix ".beta" // keep as beta by popular request - versionNameSuffix "-alpha01" + versionNameSuffix "-alpha01-" + gitCommitHash manifestPlaceholders.icon_placeholder = "@mipmap/ic_launcher_alpha" manifestPlaceholders.icon_placeholder_round = "@mipmap/ic_launcher_alpha_round" debuggable System.getenv("CI") == null diff --git a/app/src/main/java/ani/dantotsu/connections/anilist/Anilist.kt b/app/src/main/java/ani/dantotsu/connections/anilist/Anilist.kt index fc089716..65fbb3cd 100644 --- a/app/src/main/java/ani/dantotsu/connections/anilist/Anilist.kt +++ b/app/src/main/java/ani/dantotsu/connections/anilist/Anilist.kt @@ -41,20 +41,54 @@ object Anilist { "SCORE_DESC", "POPULARITY_DESC", "TRENDING_DESC", + "START_DATE_DESC", "TITLE_ENGLISH", "TITLE_ENGLISH_DESC", "SCORE" ) + val source = listOf( + "ORIGINAL", + "MANGA", + "LIGHT NOVEL", + "VISUAL NOVEL", + "VIDEO GAME", + "OTHER", + "NOVEL", + "DOUJINSHI", + "ANIME", + "WEB NOVEL", + "LIVE ACTION", + "GAME", + "COMIC", + "MULTIMEDIA PROJECT", + "PICTURE BOOK" + ) + + val animeStatus = listOf( + "FINISHED", + "RELEASING", + "NOT YET RELEASED", + "CANCELLED" + ) + + val mangaStatus = listOf( + "FINISHED", + "RELEASING", + "NOT YET RELEASED", + "HIATUS", + "CANCELLED" + ) + val seasons = listOf( "WINTER", "SPRING", "SUMMER", "FALL" ) - val anime_formats = listOf( + val animeFormats = listOf( "TV", "TV SHORT", "MOVIE", "SPECIAL", "OVA", "ONA", "MUSIC" ) - val manga_formats = listOf( + val mangaFormats = listOf( "MANGA", "NOVEL", "ONE SHOT" ) diff --git a/app/src/main/java/ani/dantotsu/connections/anilist/AnilistQueries.kt b/app/src/main/java/ani/dantotsu/connections/anilist/AnilistQueries.kt index 625f8c5f..bda6688d 100644 --- a/app/src/main/java/ani/dantotsu/connections/anilist/AnilistQueries.kt +++ b/app/src/main/java/ani/dantotsu/connections/anilist/AnilistQueries.kt @@ -885,11 +885,15 @@ class AnilistQueries { sort: String? = null, genres: MutableList? = null, tags: MutableList? = null, + status: String? = null, + source: String? = null, format: String? = null, + countryOfOrigin: String? = null, isAdult: Boolean = false, onList: Boolean? = null, excludedGenres: MutableList? = null, excludedTags: MutableList? = null, + startYear: Int? = null, seasonYear: Int? = null, season: String? = null, id: Int? = null, @@ -897,7 +901,7 @@ class AnilistQueries { adultOnly: Boolean = false ): SearchResults? { val query = """ -query (${"$"}page: Int = 1, ${"$"}id: Int, ${"$"}type: MediaType, ${"$"}isAdult: Boolean = false, ${"$"}search: String, ${"$"}format: [MediaFormat], ${"$"}status: MediaStatus, ${"$"}countryOfOrigin: CountryCode, ${"$"}source: MediaSource, ${"$"}season: MediaSeason, ${"$"}seasonYear: Int, ${"$"}year: String, ${"$"}onList: Boolean, ${"$"}yearLesser: FuzzyDateInt, ${"$"}yearGreater: FuzzyDateInt, ${"$"}episodeLesser: Int, ${"$"}episodeGreater: Int, ${"$"}durationLesser: Int, ${"$"}durationGreater: Int, ${"$"}chapterLesser: Int, ${"$"}chapterGreater: Int, ${"$"}volumeLesser: Int, ${"$"}volumeGreater: Int, ${"$"}licensedBy: [String], ${"$"}isLicensed: Boolean, ${"$"}genres: [String], ${"$"}excludedGenres: [String], ${"$"}tags: [String], ${"$"}excludedTags: [String], ${"$"}minimumTagRank: Int, ${"$"}sort: [MediaSort] = [POPULARITY_DESC, SCORE_DESC]) { +query (${"$"}page: Int = 1, ${"$"}id: Int, ${"$"}type: MediaType, ${"$"}isAdult: Boolean = false, ${"$"}search: String, ${"$"}format: [MediaFormat], ${"$"}status: MediaStatus, ${"$"}countryOfOrigin: CountryCode, ${"$"}source: MediaSource, ${"$"}season: MediaSeason, ${"$"}seasonYear: Int, ${"$"}year: String, ${"$"}onList: Boolean, ${"$"}yearLesser: FuzzyDateInt, ${"$"}yearGreater: FuzzyDateInt, ${"$"}episodeLesser: Int, ${"$"}episodeGreater: Int, ${"$"}durationLesser: Int, ${"$"}durationGreater: Int, ${"$"}chapterLesser: Int, ${"$"}chapterGreater: Int, ${"$"}volumeLesser: Int, ${"$"}volumeGreater: Int, ${"$"}licensedBy: [String], ${"$"}isLicensed: Boolean, ${"$"}genres: [String], ${"$"}excludedGenres: [String], ${"$"}tags: [String], ${"$"}excludedTags: [String], ${"$"}minimumTagRank: Int, ${"$"}sort: [MediaSort] = [POPULARITY_DESC, SCORE_DESC, START_DATE_DESC]) { Page(page: ${"$"}page, perPage: ${perPage ?: 50}) { pageInfo { total @@ -946,11 +950,15 @@ query (${"$"}page: Int = 1, ${"$"}id: Int, ${"$"}type: MediaType, ${"$"}isAdult: ${if (onList != null) ""","onList":$onList""" else ""} ${if (page != null) ""","page":"$page"""" else ""} ${if (id != null) ""","id":"$id"""" else ""} - ${if (seasonYear != null) ""","seasonYear":"$seasonYear"""" else ""} + ${if (type == "ANIME" && seasonYear != null) ""","seasonYear":"$seasonYear"""" else ""} + ${if (type == "MANGA" && startYear != null) ""","yearGreater":${startYear}0000,"yearLesser":${startYear + 1}0000""" else ""} ${if (season != null) ""","season":"$season"""" else ""} ${if (search != null) ""","search":"$search"""" else ""} + ${if (source != null) ""","source":"$source"""" else ""} ${if (sort != null) ""","sort":"$sort"""" else ""} + ${if (status != null) ""","status":"$status"""" else ""} ${if (format != null) ""","format":"${format.replace(" ", "_")}"""" else ""} + ${if (countryOfOrigin != null) ""","countryOfOrigin":"$countryOfOrigin"""" else ""} ${if (genres?.isNotEmpty() == true) ""","genres":[${genres.joinToString { "\"$it\"" }}]""" else ""} ${ if (excludedGenres?.isNotEmpty() == true) @@ -982,7 +990,6 @@ query (${"$"}page: Int = 1, ${"$"}id: Int, ${"$"}type: MediaType, ${"$"}isAdult: else "" } }""".replace("\n", " ").replace(""" """, "") - val response = executeQuery(query, variables, true)?.data?.page if (response?.media != null) { val responseArray = arrayListOf() @@ -1014,7 +1021,11 @@ query (${"$"}page: Int = 1, ${"$"}id: Int, ${"$"}type: MediaType, ${"$"}isAdult: excludedGenres = excludedGenres, tags = tags, excludedTags = excludedTags, + status = status, + source = source, format = format, + countryOfOrigin = countryOfOrigin, + startYear = startYear, seasonYear = seasonYear, season = season, results = responseArray, diff --git a/app/src/main/java/ani/dantotsu/connections/anilist/AnilistViewModel.kt b/app/src/main/java/ani/dantotsu/connections/anilist/AnilistViewModel.kt index e96e1376..a802a164 100644 --- a/app/src/main/java/ani/dantotsu/connections/anilist/AnilistViewModel.kt +++ b/app/src/main/java/ani/dantotsu/connections/anilist/AnilistViewModel.kt @@ -176,7 +176,10 @@ class AnilistAnimeViewModel : ViewModel() { r.sort, r.genres, r.tags, + r.status, + r.source, r.format, + r.countryOfOrigin, r.isAdult, r.onList, adultOnly = PrefManager.getVal(PrefName.AdultOnly), @@ -281,11 +284,15 @@ class AnilistMangaViewModel : ViewModel() { r.sort, r.genres, r.tags, + r.status, + r.source, r.format, + r.countryOfOrigin, r.isAdult, r.onList, r.excludedGenres, r.excludedTags, + r.startYear, r.seasonYear, r.season, adultOnly = PrefManager.getVal(PrefName.AdultOnly) @@ -342,11 +349,15 @@ class AnilistSearch : ViewModel() { r.sort, r.genres, r.tags, + r.status, + r.source, r.format, + r.countryOfOrigin, r.isAdult, r.onList, r.excludedGenres, r.excludedTags, + r.startYear, r.seasonYear, r.season, ) @@ -361,11 +372,15 @@ class AnilistSearch : ViewModel() { r.sort, r.genres, r.tags, + r.status, + r.source, r.format, + r.countryOfOrigin, r.isAdult, r.onList, r.excludedGenres, r.excludedTags, + r.startYear, r.seasonYear, r.season ) diff --git a/app/src/main/java/ani/dantotsu/connections/anilist/SearchResults.kt b/app/src/main/java/ani/dantotsu/connections/anilist/SearchResults.kt index 32bc1757..8458cc7e 100644 --- a/app/src/main/java/ani/dantotsu/connections/anilist/SearchResults.kt +++ b/app/src/main/java/ani/dantotsu/connections/anilist/SearchResults.kt @@ -11,13 +11,17 @@ data class SearchResults( var onList: Boolean? = null, var perPage: Int? = null, var search: String? = null, + var countryOfOrigin :String? = null, var sort: String? = null, var genres: MutableList? = null, var excludedGenres: MutableList? = null, var tags: MutableList? = null, var excludedTags: MutableList? = null, + var status: String? = null, + var source: String? = null, var format: String? = null, var seasonYear: Int? = null, + var startYear: Int? = null, var season: String? = null, var page: Int = 1, var results: MutableList, @@ -37,12 +41,24 @@ data class SearchResults( ) ) } + status?.let { + list.add(SearchChip("STATUS", currContext()!!.getString(R.string.filter_status, it))) + } + source?.let { + list.add(SearchChip("SOURCE", currContext()!!.getString(R.string.filter_source, it))) + } format?.let { list.add(SearchChip("FORMAT", currContext()!!.getString(R.string.filter_format, it))) } + countryOfOrigin?.let { + list.add(SearchChip("COUNTRY", currContext()!!.getString(R.string.filter_country, it))) + } season?.let { list.add(SearchChip("SEASON", it)) } + startYear?.let { + list.add(SearchChip("START_YEAR", it.toString())) + } seasonYear?.let { list.add(SearchChip("SEASON_YEAR", it.toString())) } @@ -74,8 +90,12 @@ data class SearchResults( fun removeChip(chip: SearchChip) { when (chip.type) { "SORT" -> sort = null + "STATUS" -> status = null + "SOURCE" -> source = null "FORMAT" -> format = null + "COUNTRY" -> countryOfOrigin = null "SEASON" -> season = null + "START_YEAR" -> startYear = null "SEASON_YEAR" -> seasonYear = null "GENRE" -> genres?.remove(chip.text) "EXCLUDED_GENRE" -> excludedGenres?.remove(chip.text) diff --git a/app/src/main/java/ani/dantotsu/media/SearchActivity.kt b/app/src/main/java/ani/dantotsu/media/SearchActivity.kt index ca196269..fb685fe9 100644 --- a/app/src/main/java/ani/dantotsu/media/SearchActivity.kt +++ b/app/src/main/java/ani/dantotsu/media/SearchActivity.kt @@ -74,8 +74,12 @@ class SearchActivity : AppCompatActivity() { genres = intent.getStringExtra("genre")?.let { mutableListOf(it) }, tags = intent.getStringExtra("tag")?.let { mutableListOf(it) }, sort = intent.getStringExtra("sortBy"), + status = intent.getStringExtra("status"), + source = intent.getStringExtra("source"), + countryOfOrigin = intent.getStringExtra("country"), season = intent.getStringExtra("season"), - seasonYear = intent.getStringExtra("seasonYear")?.toIntOrNull(), + 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 ) @@ -134,8 +138,12 @@ class SearchActivity : AppCompatActivity() { excludedTags = it.excludedTags tags = it.tags season = it.season + startYear = it.startYear seasonYear = it.seasonYear + status = it.status + source = it.source format = it.format + countryOfOrigin = it.countryOfOrigin page = it.page hasNextPage = it.hasNextPage } diff --git a/app/src/main/java/ani/dantotsu/media/SearchAdapter.kt b/app/src/main/java/ani/dantotsu/media/SearchAdapter.kt index cb590e3a..f04cee00 100644 --- a/app/src/main/java/ani/dantotsu/media/SearchAdapter.kt +++ b/app/src/main/java/ani/dantotsu/media/SearchAdapter.kt @@ -13,6 +13,8 @@ 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 import androidx.recyclerview.widget.LinearLayoutManager @@ -45,6 +47,19 @@ class SearchAdapter(private val activity: SearchActivity, private val type: Stri private lateinit var searchHistoryAdapter: SearchHistoryAdapter private lateinit var binding: ItemSearchHeaderBinding + private fun updateFilterTextViewDrawable() { + val filterDrawable = when (activity.result.sort) { + Anilist.sortBy[0] -> R.drawable.ic_round_area_chart_24 + Anilist.sortBy[1] -> R.drawable.ic_round_filter_peak_24 + Anilist.sortBy[2] -> R.drawable.ic_round_star_graph_24 + Anilist.sortBy[3] -> R.drawable.ic_round_new_releases_24 + Anilist.sortBy[4] -> R.drawable.ic_round_filter_list_24 + Anilist.sortBy[5] -> R.drawable.ic_round_filter_list_24_reverse + Anilist.sortBy[6] -> R.drawable.ic_round_assist_walker_24 + else -> R.drawable.ic_round_filter_alt_24 + } + 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) @@ -93,7 +108,7 @@ class SearchAdapter(private val activity: SearchActivity, private val type: Stri binding.searchAdultCheck.isChecked = adult binding.searchList.isChecked = listOnly == true - binding.searchChipRecycler.adapter = SearchChipAdapter(activity).also { + binding.searchChipRecycler.adapter = SearchChipAdapter(activity, this).also { activity.updateChips = { it.update() } } @@ -103,6 +118,59 @@ class SearchAdapter(private val activity: SearchActivity, private val type: Stri binding.searchFilter.setOnClickListener { SearchFilterBottomDialog.newInstance().show(activity.supportFragmentManager, "dialog") } + binding.searchFilter.setOnLongClickListener { + val popupMenu = PopupMenu(activity, binding.searchFilter) + popupMenu.menuInflater.inflate(R.menu.sortby_filter_menu, popupMenu.menu) + popupMenu.setOnMenuItemClickListener { item -> + when (item.itemId) { + R.id.sort_by_score -> { + activity.result.sort = Anilist.sortBy[0] + activity.updateChips.invoke() + 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() + activity.search() + updateFilterTextViewDrawable() + } + } + true + } + popupMenu.show() + true + } binding.searchByImage.setOnClickListener { activity.startActivity(Intent(activity, ImageSearchActivity::class.java)) } @@ -257,7 +325,7 @@ class SearchAdapter(private val activity: SearchActivity, private val type: Stri } - class SearchChipAdapter(val activity: SearchActivity) : + class SearchChipAdapter(val activity: SearchActivity, private val searchAdapter: SearchAdapter) : RecyclerView.Adapter() { private var chips = activity.result.toChipList() @@ -274,11 +342,12 @@ class SearchAdapter(private val activity: SearchActivity, private val type: Stri override fun onBindViewHolder(holder: SearchChipViewHolder, position: Int) { val chip = chips[position] holder.binding.root.apply { - text = chip.text + text = chip.text.replace("_", " ") setOnClickListener { activity.result.removeChip(chip) update() activity.search() + searchAdapter.updateFilterTextViewDrawable() } } } @@ -287,6 +356,7 @@ class SearchAdapter(private val activity: SearchActivity, private val type: Stri fun update() { chips = activity.result.toChipList() notifyDataSetChanged() + searchAdapter.updateFilterTextViewDrawable() } override fun getItemCount(): Int = chips.size diff --git a/app/src/main/java/ani/dantotsu/media/SearchFilterBottomDialog.kt b/app/src/main/java/ani/dantotsu/media/SearchFilterBottomDialog.kt index 297f8289..53ee263f 100644 --- a/app/src/main/java/ani/dantotsu/media/SearchFilterBottomDialog.kt +++ b/app/src/main/java/ani/dantotsu/media/SearchFilterBottomDialog.kt @@ -1,11 +1,15 @@ package ani.dantotsu.media +import android.animation.ObjectAnimator import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.View.GONE import android.view.ViewGroup +import android.view.animation.AccelerateDecelerateInterpolator +import android.view.animation.AnimationUtils import android.widget.ArrayAdapter +import android.widget.PopupMenu import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView @@ -17,6 +21,9 @@ import ani.dantotsu.connections.anilist.Anilist import ani.dantotsu.databinding.BottomSheetSearchFilterBinding import ani.dantotsu.databinding.ItemChipBinding import com.google.android.material.chip.Chip +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch import java.util.Calendar class SearchFilterBottomDialog : BottomSheetDialogFragment() { @@ -38,6 +45,54 @@ class SearchFilterBottomDialog : BottomSheetDialogFragment() { private var exGenres = mutableListOf() private var selectedTags = mutableListOf() private var exTags = mutableListOf() + private fun updateChips() { + binding.searchFilterGenres.adapter?.notifyDataSetChanged() + binding.searchFilterTags.adapter?.notifyDataSetChanged() + } + + private fun startBounceZoomAnimation(view: View? = null) { + val targetView = view ?: binding.sortByFilter + val bounceZoomAnimation = AnimationUtils.loadAnimation(requireContext(), R.anim.bounce_zoom) + targetView.startAnimation(bounceZoomAnimation) + } + + private fun setSortByFilterImage() { + val filterDrawable = when (activity.result.sort) { + Anilist.sortBy[0] -> R.drawable.ic_round_area_chart_24 + Anilist.sortBy[1] -> R.drawable.ic_round_filter_peak_24 + Anilist.sortBy[2] -> R.drawable.ic_round_star_graph_24 + Anilist.sortBy[3] -> R.drawable.ic_round_new_releases_24 + Anilist.sortBy[4] -> R.drawable.ic_round_filter_list_24 + Anilist.sortBy[5] -> R.drawable.ic_round_filter_list_24_reverse + Anilist.sortBy[6] -> R.drawable.ic_round_assist_walker_24 + else -> R.drawable.ic_round_filter_alt_24 + } + binding.sortByFilter.setImageResource(filterDrawable) + } + + private fun resetSearchFilter() { + activity.result.sort = null + binding.sortByFilter.setImageResource(R.drawable.ic_round_filter_alt_24) + startBounceZoomAnimation(binding.sortByFilter) + activity.result.countryOfOrigin = null + binding.countryFilter.setImageResource(R.drawable.ic_round_globe_search_googlefonts) + startBounceZoomAnimation(binding.countryFilter) + + selectedGenres.clear() + exGenres.clear() + selectedTags.clear() + exTags.clear() + binding.searchStatus.setText("") + binding.searchSource.setText("") + binding.searchFormat.setText("") + binding.searchSeason.setText("") + binding.searchYear.setText("") + binding.searchStatus.clearFocus() + binding.searchFormat.clearFocus() + binding.searchSeason.clearFocus() + binding.searchYear.clearFocus() + updateChips() + } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { @@ -47,14 +102,149 @@ class SearchFilterBottomDialog : BottomSheetDialogFragment() { exGenres = activity.result.excludedGenres ?: mutableListOf() selectedTags = activity.result.tags ?: mutableListOf() exTags = activity.result.excludedTags ?: mutableListOf() + setSortByFilterImage() + + binding.resetSearchFilter.setOnClickListener { + val rotateAnimation = ObjectAnimator.ofFloat(binding.resetSearchFilter, "rotation", 180f, 540f) + rotateAnimation.duration = 500 + rotateAnimation.interpolator = AccelerateDecelerateInterpolator() + rotateAnimation.start() + resetSearchFilter() + } + + binding.resetSearchFilter.setOnLongClickListener { + val rotateAnimation = ObjectAnimator.ofFloat(binding.resetSearchFilter, "rotation", 180f, 540f) + rotateAnimation.duration = 500 + rotateAnimation.interpolator = AccelerateDecelerateInterpolator() + rotateAnimation.start() + val bounceAnimation = AnimationUtils.loadAnimation(requireContext(), R.anim.bounce_zoom) + + binding.resetSearchFilter.startAnimation(bounceAnimation) + binding.resetSearchFilter.postDelayed({ + resetSearchFilter() + + CoroutineScope(Dispatchers.Main).launch { + activity.result.apply { + 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() + seasonYear = binding.searchYear.text.toString().toIntOrNull() + sort = activity.result.sort + genres = selectedGenres + tags = selectedTags + excludedGenres = exGenres + excludedTags = exTags + } + activity.updateChips.invoke() + activity.search() + dismiss() + } + }, 500) + true + } + + binding.sortByFilter.setOnClickListener { + val popupMenu = PopupMenu(requireContext(), it) + popupMenu.menuInflater.inflate(R.menu.sortby_filter_menu, popupMenu.menu) + popupMenu.setOnMenuItemClickListener { menuItem -> + when (menuItem.itemId) { + R.id.sort_by_score -> { + activity.result.sort = Anilist.sortBy[0] + binding.sortByFilter.setImageResource(R.drawable.ic_round_area_chart_24) + startBounceZoomAnimation() + } + + R.id.sort_by_popular -> { + activity.result.sort = Anilist.sortBy[1] + binding.sortByFilter.setImageResource(R.drawable.ic_round_filter_peak_24) + startBounceZoomAnimation() + } + + R.id.sort_by_trending -> { + activity.result.sort = Anilist.sortBy[2] + binding.sortByFilter.setImageResource(R.drawable.ic_round_star_graph_24) + startBounceZoomAnimation() + } + + R.id.sort_by_recent -> { + activity.result.sort = Anilist.sortBy[3] + binding.sortByFilter.setImageResource(R.drawable.ic_round_new_releases_24) + startBounceZoomAnimation() + } + + R.id.sort_by_a_z -> { + activity.result.sort = Anilist.sortBy[4] + binding.sortByFilter.setImageResource(R.drawable.ic_round_filter_list_24) + startBounceZoomAnimation() + } + + R.id.sort_by_z_a -> { + activity.result.sort = Anilist.sortBy[5] + binding.sortByFilter.setImageResource(R.drawable.ic_round_filter_list_24_reverse) + startBounceZoomAnimation() + } + + R.id.sort_by_pure_pain -> { + activity.result.sort = Anilist.sortBy[6] + binding.sortByFilter.setImageResource(R.drawable.ic_round_assist_walker_24) + startBounceZoomAnimation() + } + } + true + } + popupMenu.show() + } + + binding.countryFilter.setOnClickListener { + val popupMenu = PopupMenu(requireContext(), it) + popupMenu.menuInflater.inflate(R.menu.country_filter_menu, popupMenu.menu) + popupMenu.setOnMenuItemClickListener { menuItem -> + when (menuItem.itemId) { + R.id.country_global -> { + 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) + startBounceZoomAnimation(binding.countryFilter) + } + } + true + } + popupMenu.show() + } binding.searchFilterApply.setOnClickListener { activity.result.apply { + status = binding.searchStatus.text.toString().replace(" ", "_").ifBlank { null } + source = binding.searchSource.text.toString().replace(" ", "_").ifBlank { null } format = binding.searchFormat.text.toString().ifBlank { null } - sort = binding.searchSortBy.text.toString().ifBlank { null } - ?.let { Anilist.sortBy[resources.getStringArray(R.array.sort_by).indexOf(it)] } season = binding.searchSeason.text.toString().ifBlank { null } - seasonYear = binding.searchYear.text.toString().toIntOrNull() + if (activity.result.type == "ANIME") { + seasonYear = binding.searchYear.text.toString().toIntOrNull() + } else { + startYear = binding.searchYear.text.toString().toIntOrNull() + } + sort = activity.result.sort + countryOfOrigin = activity.result.countryOfOrigin genres = selectedGenres tags = selectedTags excludedGenres = exGenres @@ -67,15 +257,22 @@ class SearchFilterBottomDialog : BottomSheetDialogFragment() { binding.searchFilterCancel.setOnClickListener { dismiss() } - - binding.searchSortBy.setText(activity.result.sort?.let { - resources.getStringArray(R.array.sort_by)[Anilist.sortBy.indexOf(it)] - }) - binding.searchSortBy.setAdapter( + val format = if (activity.result.type == "ANIME") Anilist.animeStatus else Anilist.mangaStatus + binding.searchStatus.setText(activity.result.status?.replace("_", " ")) + binding.searchStatus.setAdapter( ArrayAdapter( binding.root.context, R.layout.item_dropdown, - resources.getStringArray(R.array.sort_by) + format + ) + ) + + binding.searchSource.setText(activity.result.source?.replace("_", " ")) + binding.searchSource.setAdapter( + ArrayAdapter( + binding.root.context, + R.layout.item_dropdown, + Anilist.source.toTypedArray() ) ) @@ -84,11 +281,25 @@ class SearchFilterBottomDialog : BottomSheetDialogFragment() { ArrayAdapter( binding.root.context, R.layout.item_dropdown, - (if (activity.result.type == "ANIME") Anilist.anime_formats else Anilist.manga_formats).toTypedArray() + (if (activity.result.type == "ANIME") Anilist.animeFormats else Anilist.mangaFormats).toTypedArray() ) ) - if (activity.result.type == "MANGA") binding.searchSeasonYearCont.visibility = GONE + if (activity.result.type == "ANIME") { + binding.searchYear.setText(activity.result.seasonYear?.toString()) + } else { + binding.searchYear.setText(activity.result.startYear?.toString()) + } + binding.searchYear.setAdapter( + ArrayAdapter( + binding.root.context, + R.layout.item_dropdown, + (1970 until Calendar.getInstance().get(Calendar.YEAR) + 2).map { it.toString() } + .reversed().toTypedArray() + ) + ) + + if (activity.result.type == "MANGA") binding.searchSeasonCont.visibility = GONE else { binding.searchSeason.setText(activity.result.season) binding.searchSeason.setAdapter( @@ -98,16 +309,6 @@ class SearchFilterBottomDialog : BottomSheetDialogFragment() { Anilist.seasons.toTypedArray() ) ) - - binding.searchYear.setText(activity.result.seasonYear?.toString()) - binding.searchYear.setAdapter( - ArrayAdapter( - binding.root.context, - R.layout.item_dropdown, - (1970 until Calendar.getInstance().get(Calendar.YEAR) + 2).map { it.toString() } - .reversed().toTypedArray() - ) - ) } binding.searchFilterGenres.adapter = FilterChipAdapter(Anilist.genres ?: listOf()) { chip -> diff --git a/app/src/main/java/ani/dantotsu/media/anime/ExoplayerView.kt b/app/src/main/java/ani/dantotsu/media/anime/ExoplayerView.kt index 1833ada8..7daf8138 100644 --- a/app/src/main/java/ani/dantotsu/media/anime/ExoplayerView.kt +++ b/app/src/main/java/ani/dantotsu/media/anime/ExoplayerView.kt @@ -1084,35 +1084,40 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL val incognito: Boolean = PrefManager.getVal(PrefName.Incognito) if ((isOnline(context) && !offline) && Discord.token != null && !incognito) { lifecycleScope.launch { - val presence = RPC.createPresence(RPC.Companion.RPCData( - applicationId = Discord.application_Id, - type = RPC.Type.WATCHING, - activityName = media.userPreferredName, - details = ep.title?.takeIf { it.isNotEmpty() } ?: getString( - R.string.episode_num, - ep.number - ), - state = "Episode : ${ep.number}/${media.anime?.totalEpisodes ?: "??"}", - largeImage = media.cover?.let { - RPC.Link( - media.userPreferredName, - it - ) - }, - smallImage = RPC.Link( - "Dantotsu", - Discord.small_Image - ), - buttons = mutableListOf( + val discordMode = PrefManager.getCustomVal("discord_mode", "dantotsu") + val buttons = when (discordMode) { + "nothing" -> mutableListOf( RPC.Link(getString(R.string.view_anime), media.shareLink ?: ""), - RPC.Link( - "Stream on Dantotsu", - getString(R.string.github) + ) + "dantotsu" -> mutableListOf( + RPC.Link(getString(R.string.view_anime), media.shareLink ?: ""), + RPC.Link("Watch on Dantotsu", getString(R.string.dantotsu)) + ) + "anilist" -> { + val userId = PrefManager.getVal(PrefName.AnilistUserId) + val anilistLink = "https://anilist.co/user/$userId/" + mutableListOf( + RPC.Link(getString(R.string.view_anime), media.shareLink ?: ""), + RPC.Link("View My AniList", anilistLink) ) + } + else -> mutableListOf() + } + val presence = RPC.createPresence( + RPC.Companion.RPCData( + applicationId = Discord.application_Id, + type = RPC.Type.WATCHING, + activityName = media.userPreferredName, + details = ep.title?.takeIf { it.isNotEmpty() } ?: getString( + R.string.episode_num, + ep.number + ), + state = "Episode : ${ep.number}/${media.anime?.totalEpisodes ?: "??"}", + largeImage = media.cover?.let { RPC.Link(media.userPreferredName, it) }, + smallImage = RPC.Link("Dantotsu", Discord.small_Image), + buttons = buttons ) ) - ) - val intent = Intent(context, DiscordService::class.java).apply { putExtra("presence", presence) } @@ -1120,7 +1125,6 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL startService(intent) } } - updateProgress() } } diff --git a/app/src/main/java/ani/dantotsu/media/manga/mangareader/MangaReaderActivity.kt b/app/src/main/java/ani/dantotsu/media/manga/mangareader/MangaReaderActivity.kt index a7d45778..1a4bcade 100644 --- a/app/src/main/java/ani/dantotsu/media/manga/mangareader/MangaReaderActivity.kt +++ b/app/src/main/java/ani/dantotsu/media/manga/mangareader/MangaReaderActivity.kt @@ -362,15 +362,11 @@ class MangaReaderActivity : AppCompatActivity() { currentChapterIndex = chaptersArr.indexOf(chap.number) binding.mangaReaderChapterSelect.setSelection(currentChapterIndex) if (defaultSettings.direction == RIGHT_TO_LEFT || defaultSettings.direction == BOTTOM_TO_TOP) { - 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 @@ -378,6 +374,25 @@ class MangaReaderActivity : AppCompatActivity() { val incognito: Boolean = PrefManager.getVal(PrefName.Incognito) if ((isOnline(context) && !offline) && Discord.token != null && !incognito) { lifecycleScope.launch { + val discordMode = PrefManager.getCustomVal("discord_mode", "dantotsu") + val buttons = when (discordMode) { + "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(PrefName.AnilistUserId) + val anilistLink = "https://anilist.co/user/$userId/" + mutableListOf( + RPC.Link(getString(R.string.view_manga), media.shareLink ?: ""), + RPC.Link("View My AniList", anilistLink) + ) + } + else -> mutableListOf() + } val presence = RPC.createPresence( RPC.Companion.RPCData( applicationId = Discord.application_Id, @@ -386,20 +401,9 @@ 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) - }, - smallImage = RPC.Link( - "Dantotsu", - Discord.small_Image - ), - buttons = mutableListOf( - RPC.Link(getString(R.string.view_manga), media.shareLink ?: ""), - RPC.Link( - "Stream on Dantotsu", - getString(R.string.github) - ) - ) + largeImage = media.cover?.let { cover -> RPC.Link(media.userPreferredName, cover) }, + smallImage = RPC.Link("Dantotsu", Discord.small_Image), + buttons = buttons ) ) val intent = Intent(context, DiscordService::class.java).apply { diff --git a/app/src/main/java/ani/dantotsu/profile/ProfileFragment.kt b/app/src/main/java/ani/dantotsu/profile/ProfileFragment.kt index 6fd425be..f7a04944 100644 --- a/app/src/main/java/ani/dantotsu/profile/ProfileFragment.kt +++ b/app/src/main/java/ani/dantotsu/profile/ProfileFragment.kt @@ -154,22 +154,23 @@ class ProfileFragment : Fragment() { private fun setFavPeople() { if (favStaff.isEmpty()) { binding.profileFavStaffContainer.visibility = View.GONE + } else { + binding.profileFavStaffRecycler.adapter = AuthorAdapter(favStaff) + binding.profileFavStaffRecycler.layoutManager = LinearLayoutManager( + activity, LinearLayoutManager.HORIZONTAL, false + ) + binding.profileFavStaffRecycler.layoutAnimation = LayoutAnimationController(setSlideIn(), 0.25f) } - binding.profileFavStaffRecycler.adapter = AuthorAdapter(favStaff) - binding.profileFavStaffRecycler.layoutManager = LinearLayoutManager( - activity, - LinearLayoutManager.HORIZONTAL, - false - ) + if (favCharacter.isEmpty()) { binding.profileFavCharactersContainer.visibility = View.GONE + } else { + binding.profileFavCharactersRecycler.adapter = CharacterAdapter(favCharacter) + binding.profileFavCharactersRecycler.layoutManager = LinearLayoutManager( + activity, LinearLayoutManager.HORIZONTAL, false + ) + binding.profileFavCharactersRecycler.layoutAnimation = LayoutAnimationController(setSlideIn(), 0.25f) } - binding.profileFavCharactersRecycler.adapter = CharacterAdapter(favCharacter) - binding.profileFavCharactersRecycler.layoutManager = LinearLayoutManager( - activity, - LinearLayoutManager.HORIZONTAL, - false - ) } private fun initRecyclerView( diff --git a/app/src/main/java/ani/dantotsu/settings/DiscordDialogFragment.kt b/app/src/main/java/ani/dantotsu/settings/DiscordDialogFragment.kt new file mode 100644 index 00000000..ded5db8e --- /dev/null +++ b/app/src/main/java/ani/dantotsu/settings/DiscordDialogFragment.kt @@ -0,0 +1,60 @@ +package ani.dantotsu.settings + +import android.annotation.SuppressLint +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.RadioButton +import android.widget.RadioGroup +import android.widget.TextView +import androidx.recyclerview.widget.LinearLayoutManager +import ani.dantotsu.BottomSheetDialogFragment +import ani.dantotsu.R +import ani.dantotsu.connections.anilist.Anilist +import ani.dantotsu.databinding.BottomSheetDiscordRpcBinding +import ani.dantotsu.profile.activity.UsersAdapter +import ani.dantotsu.settings.saving.PrefManager +import ani.dantotsu.settings.saving.PrefName +import com.google.android.material.bottomsheet.BottomSheetDialog + +class DiscordDialogFragment: BottomSheetDialogFragment() { + private var _binding: BottomSheetDiscordRpcBinding? = null + private val binding get() = _binding!! + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + _binding = BottomSheetDiscordRpcBinding.inflate(inflater, container, false) + return binding.root + } + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + when (PrefManager.getCustomVal("discord_mode", "dantotsu")) { + "nothing" -> binding.radioNothing.isChecked= true + "dantotsu" -> binding.radioDantotsu.isChecked = true + "anilist" -> binding.radioAnilist.isChecked = true + else -> binding.radioAnilist.isChecked = true + } + + binding.anilistLinkPreview.text = getString(R.string.anilist_link, PrefManager.getVal(PrefName.AnilistUserName)) + + binding.radioGroup.setOnCheckedChangeListener { _, checkedId -> + val mode = when (checkedId) { + binding.radioNothing.id -> "nothing" + binding.radioDantotsu.id -> "dantotsu" + binding.radioAnilist.id -> "anilist" + else -> "dantotsu" + } + PrefManager.setCustomVal("discord_mode", mode) + } + } + + override fun onDestroy() { + _binding = null + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/ani/dantotsu/settings/SettingsActivity.kt b/app/src/main/java/ani/dantotsu/settings/SettingsActivity.kt index 7950d282..e96f0edf 100644 --- a/app/src/main/java/ani/dantotsu/settings/SettingsActivity.kt +++ b/app/src/main/java/ani/dantotsu/settings/SettingsActivity.kt @@ -19,12 +19,15 @@ import android.view.ViewGroup import android.view.animation.AnimationUtils import android.view.inputmethod.EditorInfo import android.widget.ArrayAdapter +import android.widget.RadioButton +import android.widget.RadioGroup import android.widget.TextView import androidx.activity.OnBackPressedCallback import androidx.activity.result.contract.ActivityResultContracts import androidx.annotation.OptIn import androidx.appcompat.app.AppCompatActivity import androidx.core.content.ContextCompat +import android.view.HapticFeedbackConstants import androidx.core.view.updateLayoutParams import androidx.documentfile.provider.DocumentFile import androidx.lifecycle.lifecycleScope @@ -79,6 +82,7 @@ import ani.dantotsu.statusBarHeight import ani.dantotsu.themes.ThemeManager import ani.dantotsu.toast import ani.dantotsu.util.Logger +import com.google.android.material.bottomsheet.BottomSheetDialog import com.google.android.material.textfield.TextInputEditText import eltos.simpledialogfragment.SimpleDialog import eltos.simpledialogfragment.SimpleDialog.OnDialogResultListener.BUTTON_POSITIVE @@ -259,18 +263,18 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene reload() } - imageSwitcher.visibility = View.VISIBLE + settingsImageSwitcher.visibility = View.VISIBLE var initialStatus = when (PrefManager.getVal(PrefName.DiscordStatus)) { "online" -> R.drawable.discord_status_online "idle" -> R.drawable.discord_status_idle "dnd" -> R.drawable.discord_status_dnd else -> R.drawable.discord_status_online } - imageSwitcher.setImageResource(initialStatus) + settingsImageSwitcher.setImageResource(initialStatus) val zoomInAnimation = AnimationUtils.loadAnimation(this@SettingsActivity, R.anim.bounce_zoom) - imageSwitcher.setOnClickListener { + settingsImageSwitcher.setOnClickListener { var status = "online" initialStatus = when (initialStatus) { R.drawable.discord_status_online -> { @@ -292,11 +296,16 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene } PrefManager.setVal(PrefName.DiscordStatus, status) - imageSwitcher.setImageResource(initialStatus) - imageSwitcher.startAnimation(zoomInAnimation) + settingsImageSwitcher.setImageResource(initialStatus) + settingsImageSwitcher.startAnimation(zoomInAnimation) + } + settingsImageSwitcher.setOnLongClickListener { + it.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS) + DiscordDialogFragment().show(supportFragmentManager, "dialog") + true } } else { - imageSwitcher.visibility = View.GONE + settingsImageSwitcher.visibility = View.GONE settingsDiscordAvatar.setImageResource(R.drawable.ic_round_person_24) settingsDiscordUsername.visibility = View.GONE settingsDiscordLogin.setText(R.string.login) diff --git a/app/src/main/res/drawable/ic_round_area_chart_24.xml b/app/src/main/res/drawable/ic_round_area_chart_24.xml new file mode 100644 index 00000000..b1d6f78c --- /dev/null +++ b/app/src/main/res/drawable/ic_round_area_chart_24.xml @@ -0,0 +1,12 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_round_assist_walker_24.xml b/app/src/main/res/drawable/ic_round_assist_walker_24.xml new file mode 100644 index 00000000..0d38faeb --- /dev/null +++ b/app/src/main/res/drawable/ic_round_assist_walker_24.xml @@ -0,0 +1,16 @@ + + + + + + + diff --git a/app/src/main/res/drawable/ic_round_early_bird_special.xml b/app/src/main/res/drawable/ic_round_early_bird_special.xml deleted file mode 100644 index 4aa4292f..00000000 --- a/app/src/main/res/drawable/ic_round_early_bird_special.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - diff --git a/app/src/main/res/drawable/ic_round_filter_list_24.xml b/app/src/main/res/drawable/ic_round_filter_list_24.xml new file mode 100644 index 00000000..e3dc45c1 --- /dev/null +++ b/app/src/main/res/drawable/ic_round_filter_list_24.xml @@ -0,0 +1,12 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_round_filter_list_24_reverse.xml b/app/src/main/res/drawable/ic_round_filter_list_24_reverse.xml new file mode 100644 index 00000000..ac200103 --- /dev/null +++ b/app/src/main/res/drawable/ic_round_filter_list_24_reverse.xml @@ -0,0 +1,12 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_round_filter_peak_24.xml b/app/src/main/res/drawable/ic_round_filter_peak_24.xml new file mode 100644 index 00000000..061d0ec0 --- /dev/null +++ b/app/src/main/res/drawable/ic_round_filter_peak_24.xml @@ -0,0 +1,12 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_round_globe_china_googlefonts.xml b/app/src/main/res/drawable/ic_round_globe_china_googlefonts.xml new file mode 100644 index 00000000..1a36e8f6 --- /dev/null +++ b/app/src/main/res/drawable/ic_round_globe_china_googlefonts.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_round_globe_japan_googlefonts.xml b/app/src/main/res/drawable/ic_round_globe_japan_googlefonts.xml new file mode 100644 index 00000000..24803edd --- /dev/null +++ b/app/src/main/res/drawable/ic_round_globe_japan_googlefonts.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_round_globe_search_googlefonts.xml b/app/src/main/res/drawable/ic_round_globe_search_googlefonts.xml new file mode 100644 index 00000000..97b82b0e --- /dev/null +++ b/app/src/main/res/drawable/ic_round_globe_search_googlefonts.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_round_globe_south_korea_googlefonts.xml b/app/src/main/res/drawable/ic_round_globe_south_korea_googlefonts.xml new file mode 100644 index 00000000..dff31e26 --- /dev/null +++ b/app/src/main/res/drawable/ic_round_globe_south_korea_googlefonts.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_round_globe_taiwan_googlefonts.xml b/app/src/main/res/drawable/ic_round_globe_taiwan_googlefonts.xml new file mode 100644 index 00000000..52052789 --- /dev/null +++ b/app/src/main/res/drawable/ic_round_globe_taiwan_googlefonts.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_round_reset_star_24.xml b/app/src/main/res/drawable/ic_round_reset_star_24.xml new file mode 100644 index 00000000..00830a3e --- /dev/null +++ b/app/src/main/res/drawable/ic_round_reset_star_24.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_round_star_graph_24.xml b/app/src/main/res/drawable/ic_round_star_graph_24.xml new file mode 100644 index 00000000..590f5f18 --- /dev/null +++ b/app/src/main/res/drawable/ic_round_star_graph_24.xml @@ -0,0 +1,12 @@ + + + + + diff --git a/app/src/main/res/layout/activity_player_settings.xml b/app/src/main/res/layout/activity_player_settings.xml index afbc7ee2..e1503989 100644 --- a/app/src/main/res/layout/activity_player_settings.xml +++ b/app/src/main/res/layout/activity_player_settings.xml @@ -749,7 +749,7 @@ android:layout_height="wrap_content" android:layout_marginBottom="8dp" android:checked="false" - android:drawableStart="@drawable/ic_round_early_bird_special" + android:drawableStart="@drawable/ic_round_assist_walker_24" android:drawablePadding="16dp" android:elegantTextHeight="true" android:fontFamily="@font/poppins_bold" diff --git a/app/src/main/res/layout/activity_reader_settings.xml b/app/src/main/res/layout/activity_reader_settings.xml index 63ce3d08..9e9f1efd 100644 --- a/app/src/main/res/layout/activity_reader_settings.xml +++ b/app/src/main/res/layout/activity_reader_settings.xml @@ -1318,7 +1318,7 @@ android:layout_height="wrap_content" android:layout_marginBottom="8dp" android:checked="false" - android:drawableStart="@drawable/ic_round_early_bird_special" + android:drawableStart="@drawable/ic_round_assist_walker_24" android:drawablePadding="16dp" android:elegantTextHeight="true" android:fontFamily="@font/poppins_bold" diff --git a/app/src/main/res/layout/activity_settings_accounts.xml b/app/src/main/res/layout/activity_settings_accounts.xml index 41f2b5ec..cf3765cf 100644 --- a/app/src/main/res/layout/activity_settings_accounts.xml +++ b/app/src/main/res/layout/activity_settings_accounts.xml @@ -213,11 +213,10 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/bottom_sheet_search_filter.xml b/app/src/main/res/layout/bottom_sheet_search_filter.xml index 8ca02366..950141e7 100644 --- a/app/src/main/res/layout/bottom_sheet_search_filter.xml +++ b/app/src/main/res/layout/bottom_sheet_search_filter.xml @@ -1,288 +1,382 @@ - + android:layout_height="wrap_content" + android:background="@drawable/bottom_sheet_background"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + android:layout_gravity="bottom" + android:orientation="horizontal"> - - - + android:layout_weight="1" + android:fontFamily="@font/poppins_bold" + android:insetTop="0dp" + android:insetBottom="0dp" + android:padding="8dp" + android:text="@string/cancel" + android:textSize="16sp" + app:cornerRadius="16dp" + app:strokeColor="?attr/colorPrimaryContainer" + tools:ignore="SpeakableTextPresentCheck" /> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -