diff --git a/.github/workflows/beta.yml b/.github/workflows/beta.yml index a1277018..0d595b14 100644 --- a/.github/workflows/beta.yml +++ b/.github/workflows/beta.yml @@ -127,4 +127,4 @@ jobs: pre-release-keep-count: 3 pre-release-drop-tag: true env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/app/src/main/java/ani/dantotsu/Functions.kt b/app/src/main/java/ani/dantotsu/Functions.kt index 018476b0..9acb51f7 100644 --- a/app/src/main/java/ani/dantotsu/Functions.kt +++ b/app/src/main/java/ani/dantotsu/Functions.kt @@ -214,7 +214,8 @@ fun initActivity(a: Activity) { window, window.decorView ).hide(WindowInsetsCompat.Type.statusBars()) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P && statusBarHeight == 0 && a.resources.configuration.orientation == Configuration.ORIENTATION_PORTRAIT) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P && statusBarHeight == 0 + && a.resources.configuration.orientation == Configuration.ORIENTATION_PORTRAIT) { window.decorView.rootWindowInsets?.displayCutout?.apply { if (boundingRects.size > 0) { statusBarHeight = min(boundingRects[0].width(), boundingRects[0].height()) 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 cf9a0ecd..bda6688d 100644 --- a/app/src/main/java/ani/dantotsu/connections/anilist/AnilistQueries.kt +++ b/app/src/main/java/ani/dantotsu/connections/anilist/AnilistQueries.kt @@ -898,6 +898,7 @@ class AnilistQueries { season: String? = null, id: Int? = null, hd: Boolean = false, + 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, START_DATE_DESC]) { @@ -945,6 +946,7 @@ query (${"$"}page: Int = 1, ${"$"}id: Int, ${"$"}type: MediaType, ${"$"}isAdult: } """.replace("\n", " ").replace(""" """, "") val variables = """{"type":"$type","isAdult":$isAdult + ${if (adultOnly) ""","isAdult":true""" else ""} ${if (onList != null) ""","onList":$onList""" else ""} ${if (page != null) ""","page":"$page"""" else ""} ${if (id != null) ""","id":"$id"""" else ""} 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 531000c9..a802a164 100644 --- a/app/src/main/java/ani/dantotsu/connections/anilist/AnilistViewModel.kt +++ b/app/src/main/java/ani/dantotsu/connections/anilist/AnilistViewModel.kt @@ -137,7 +137,8 @@ class AnilistAnimeViewModel : ViewModel() { sort = Anilist.sortBy[2], season = season, seasonYear = year, - hd = true + hd = true, + adultOnly = PrefManager.getVal(PrefName.AdultOnly) )?.results ) } @@ -159,7 +160,8 @@ class AnilistAnimeViewModel : ViewModel() { search = searchVal, onList = if (onList) null else false, sort = sort, - genres = genres + genres = genres, + adultOnly = PrefManager.getVal(PrefName.AdultOnly) ) ) } @@ -179,7 +181,8 @@ class AnilistAnimeViewModel : ViewModel() { r.format, r.countryOfOrigin, r.isAdult, - r.onList + r.onList, + adultOnly = PrefManager.getVal(PrefName.AdultOnly), ) ) @@ -244,7 +247,8 @@ class AnilistMangaViewModel : ViewModel() { type, perPage = 10, sort = Anilist.sortBy[2], - hd = true + hd = true, + adultOnly = PrefManager.getVal(PrefName.AdultOnly) )?.results ) @@ -264,7 +268,8 @@ class AnilistMangaViewModel : ViewModel() { search = searchVal, onList = if (onList) null else false, sort = sort, - genres = genres + genres = genres, + adultOnly = PrefManager.getVal(PrefName.AdultOnly) ) ) } @@ -289,7 +294,8 @@ class AnilistMangaViewModel : ViewModel() { r.excludedTags, r.startYear, r.seasonYear, - r.season + r.season, + adultOnly = PrefManager.getVal(PrefName.AdultOnly) ) ) @@ -353,7 +359,7 @@ class AnilistSearch : ViewModel() { r.excludedTags, r.startYear, r.seasonYear, - r.season + r.season, ) ) diff --git a/app/src/main/java/ani/dantotsu/connections/github/Contributors.kt b/app/src/main/java/ani/dantotsu/connections/github/Contributors.kt new file mode 100644 index 00000000..f796e38a --- /dev/null +++ b/app/src/main/java/ani/dantotsu/connections/github/Contributors.kt @@ -0,0 +1,84 @@ +package ani.dantotsu.connections.github + +import ani.dantotsu.Mapper +import ani.dantotsu.R +import ani.dantotsu.client +import ani.dantotsu.getAppString +import ani.dantotsu.settings.Developer +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.runBlocking +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable +import kotlinx.serialization.json.JsonArray +import kotlinx.serialization.json.decodeFromJsonElement + +class Contributors { + + fun getContributors(): Array { + var developers = arrayOf() + runBlocking(Dispatchers.IO) { + val repo = getAppString(R.string.repo) + val res = client.get("https://api.github.com/repos/$repo/contributors") + .parsed().map { + Mapper.json.decodeFromJsonElement(it) + } + res.find { it.login == "rebelonion"}?.let { first -> + developers = developers.plus( + Developer( + first.login, + first.avatarUrl, + "Owner and Maintainer", + first.htmlUrl + ) + ).plus(arrayOf( + Developer( + "Wai What", + "https://avatars.githubusercontent.com/u/149729762?v=4", + "Icon Designer", + "https://github.com/WaiWhat" + ), + Developer( + "MarshMeadow", + "https://avatars.githubusercontent.com/u/88599122?v=4", + "Beta Icon Designer", + "https://github.com/MarshMeadow?tab=repositories" + ), + Developer( + "Zaxx69", + "https://avatars.githubusercontent.com/u/138523882?v=4", + "Telegram Admin", + "https://github.com/Zaxx69" + ), + Developer( + "Arif Alam", + "https://avatars.githubusercontent.com/u/70383209?v=4", + "Head Discord Moderator", + "https://youtube.com/watch?v=dQw4w9WgXcQ" + ) + )) + } + res.filter {it.login != "rebelonion"}.forEach { + developers = developers.plus( + Developer( + it.login, + it.avatarUrl, + "Contributor", + it.htmlUrl + ) + ) + } + } + return developers + } + + + @Serializable + data class GithubResponse( + @SerialName("login") + val login: String, + @SerialName("avatar_url") + val avatarUrl: String, + @SerialName("html_url") + val htmlUrl: String + ) +} \ No newline at end of file diff --git a/app/src/main/java/ani/dantotsu/connections/github/Forks.kt b/app/src/main/java/ani/dantotsu/connections/github/Forks.kt new file mode 100644 index 00000000..a074eea0 --- /dev/null +++ b/app/src/main/java/ani/dantotsu/connections/github/Forks.kt @@ -0,0 +1,55 @@ +package ani.dantotsu.connections.github + +import ani.dantotsu.Mapper +import ani.dantotsu.R +import ani.dantotsu.client +import ani.dantotsu.getAppString +import ani.dantotsu.settings.Developer +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.runBlocking +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable +import kotlinx.serialization.json.JsonArray +import kotlinx.serialization.json.decodeFromJsonElement + +class Forks { + + fun getForks(): Array { + var forks = arrayOf() + runBlocking(Dispatchers.IO) { + val res = client.get("https://api.github.com/repos/rebelonion/Dantotsu/forks") + .parsed().map { + Mapper.json.decodeFromJsonElement(it) + } + res.forEach { + forks = forks.plus( + Developer( + it.name, + it.owner.avatarUrl, + it.owner.login, + it.htmlUrl + ) + ) + } + } + return forks + } + + + @Serializable + data class GithubResponse( + @SerialName("name") + val name: String, + val owner: Owner, + @SerialName("html_url") + val htmlUrl: String, + ) { + @Serializable + data class Owner( + @SerialName("login") + val login: String, + @SerialName("avatar_url") + val avatarUrl: String + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/ani/dantotsu/media/comments/CommentItem.kt b/app/src/main/java/ani/dantotsu/media/comments/CommentItem.kt index d5b887bd..5e4596ed 100644 --- a/app/src/main/java/ani/dantotsu/media/comments/CommentItem.kt +++ b/app/src/main/java/ani/dantotsu/media/comments/CommentItem.kt @@ -4,6 +4,7 @@ import android.annotation.SuppressLint import android.content.Intent import android.graphics.Color import android.view.View +import android.widget.PopupMenu import androidx.core.content.ContextCompat import androidx.recyclerview.widget.LinearLayoutManager import ani.dantotsu.R @@ -34,13 +35,15 @@ import java.util.TimeZone import kotlin.math.abs import kotlin.math.sqrt -class CommentItem(val comment: Comment, - private val markwon: Markwon, - val parentSection: Section, - private val commentsFragment: CommentsFragment, - private val backgroundColor: Int, - val commentDepth: Int -) : BindableItem() { +class CommentItem( + val comment: Comment, + private val markwon: Markwon, + val parentSection: Section, + private val commentsFragment: CommentsFragment, + private val backgroundColor: Int, + val commentDepth: Int +) : + BindableItem() { lateinit var binding: ItemCommentsBinding val adapter = GroupieAdapter() private var subCommentIds: MutableList = mutableListOf() @@ -62,9 +65,6 @@ class CommentItem(val comment: Comment, val isUserComment = CommentsAPI.userId == comment.userId val levelColor = getAvatarColor(comment.totalVotes, backgroundColor) markwon.setMarkdown(viewBinding.commentText, comment.content) - viewBinding.commentDelete.visibility = if (isUserComment || CommentsAPI.isAdmin || CommentsAPI.isMod) View.VISIBLE else View.GONE - viewBinding.commentBanUser.visibility = if ((CommentsAPI.isAdmin || CommentsAPI.isMod) && !isUserComment) View.VISIBLE else View.GONE - viewBinding.commentReport.visibility = if (!isUserComment) View.VISIBLE else View.GONE viewBinding.commentEdit.visibility = if (isUserComment) View.VISIBLE else View.GONE if (comment.tag == null) { viewBinding.commentUserTagLayout.visibility = View.GONE @@ -140,41 +140,71 @@ class CommentItem(val comment: Comment, } viewBinding.modBadge.visibility = if (comment.isMod == true) View.VISIBLE else View.GONE viewBinding.adminBadge.visibility = if (comment.isAdmin == true) View.VISIBLE else View.GONE - viewBinding.commentDelete.setOnClickListener { - dialogBuilder(getAppString(R.string.delete_comment), getAppString(R.string.delete_comment_confirm)) { - CoroutineScope(Dispatchers.Main + SupervisorJob()).launch { - val success = CommentsAPI.deleteComment(comment.commentId) - if (success) { - snackString(R.string.comment_deleted) - parentSection.remove(this@CommentItem) - } - } - } - } - viewBinding.commentBanUser.setOnClickListener { - dialogBuilder(getAppString(R.string.ban_user), getAppString(R.string.ban_user_confirm)) { - CoroutineScope(Dispatchers.Main + SupervisorJob()).launch { - val success = CommentsAPI.banUser(comment.userId) - if (success) { - snackString(R.string.user_banned) - } - } - } - } - viewBinding.commentReport.setOnClickListener { - dialogBuilder(getAppString(R.string.report_comment), getAppString(R.string.report_comment_confirm)) { - CoroutineScope(Dispatchers.Main + SupervisorJob()).launch { - val success = CommentsAPI.reportComment( - comment.commentId, - comment.username, - commentsFragment.mediaName, - comment.userId - ) - if (success) { - snackString(R.string.comment_reported) + viewBinding.commentInfo.setOnClickListener { + val popup = PopupMenu(commentsFragment.requireContext(), viewBinding.commentInfo) + popup.menuInflater.inflate(R.menu.profile_details_menu, popup.menu) + popup.menu.findItem(R.id.commentDelete)?.isVisible = isUserComment || CommentsAPI.isAdmin || CommentsAPI.isMod + popup.menu.findItem(R.id.commentBanUser)?.isVisible = (CommentsAPI.isAdmin || CommentsAPI.isMod) && !isUserComment + popup.menu.findItem(R.id.commentReport)?.isVisible = !isUserComment + popup.setOnMenuItemClickListener { item -> + when (item.itemId) { + R.id.commentReport -> { + dialogBuilder( + getAppString(R.string.report_comment), + getAppString(R.string.report_comment_confirm) + ) { + CoroutineScope(Dispatchers.Main + SupervisorJob()).launch { + val success = CommentsAPI.reportComment( + comment.commentId, + comment.username, + commentsFragment.mediaName, + comment.userId + ) + if (success) { + snackString(R.string.comment_reported) + } + } + } + true + } + + R.id.commentDelete -> { + dialogBuilder( + getAppString(R.string.delete_comment), + getAppString(R.string.delete_comment_confirm) + ) { + CoroutineScope(Dispatchers.Main + SupervisorJob()).launch { + val success = CommentsAPI.deleteComment(comment.commentId) + if (success) { + snackString(R.string.comment_deleted) + parentSection.remove(this@CommentItem) + } + } + } + true + } + + R.id.commentBanUser -> { + dialogBuilder( + getAppString(R.string.ban_user), + getAppString(R.string.ban_user_confirm) + ) { + CoroutineScope(Dispatchers.Main + SupervisorJob()).launch { + val success = CommentsAPI.banUser(comment.userId) + if (success) { + snackString(R.string.user_banned) + } + } + } + true + } + + else -> { + false } } } + popup.show() } //fill the icon if the user has liked the comment setVoteButtons(viewBinding) @@ -210,7 +240,6 @@ class CommentItem(val comment: Comment, comment.upvotes -= 1 } comment.downvotes += if (voteType == -1) 1 else -1 - notifyChanged() } } diff --git a/app/src/main/java/ani/dantotsu/media/manga/mangareader/BaseImageAdapter.kt b/app/src/main/java/ani/dantotsu/media/manga/mangareader/BaseImageAdapter.kt index a00f4731..7b91d6f7 100644 --- a/app/src/main/java/ani/dantotsu/media/manga/mangareader/BaseImageAdapter.kt +++ b/app/src/main/java/ani/dantotsu/media/manga/mangareader/BaseImageAdapter.kt @@ -37,7 +37,18 @@ abstract class BaseImageAdapter( chapter: MangaChapter ) : RecyclerView.Adapter() { val settings = activity.defaultSettings - val images = chapter.images() + private val chapterImages = chapter.images() + var images = chapterImages + + override fun onAttachedToRecyclerView(recyclerView: RecyclerView) { + images = if (settings.layout == CurrentReaderSettings.Layouts.PAGED + && settings.direction == CurrentReaderSettings.Directions.BOTTOM_TO_TOP) { + chapterImages.reversed() + } else { + chapterImages + } + super.onAttachedToRecyclerView(recyclerView) + } @SuppressLint("ClickableViewAccessibility") override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { @@ -213,5 +224,4 @@ abstract class BaseImageAdapter( return newBitmap } } - } \ No newline at end of file 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 1a4bcade..57e099af 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 @@ -129,6 +129,11 @@ class MangaReaderActivity : AppCompatActivity() { var sliding = false var isAnimating = false + private val directionRLBT get() = defaultSettings.direction == RIGHT_TO_LEFT + || defaultSettings.direction == BOTTOM_TO_TOP + private val directionPagedBT get() = defaultSettings.layout == CurrentReaderSettings.Layouts.PAGED + && defaultSettings.direction == CurrentReaderSettings.Directions.BOTTOM_TO_TOP + override fun onAttachedToWindow() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P && !PrefManager.getVal(PrefName.ShowSystemBars)) { val displayCutout = window.decorView.rootWindowInsets.displayCutout @@ -224,8 +229,13 @@ class MangaReaderActivity : AppCompatActivity() { binding.mangaReaderRecycler.scrollToPosition((value.toInt() - 1) / (dualPage { 2 } ?: 1)) else - binding.mangaReaderPager.currentItem = - (value.toInt() - 1) / (dualPage { 2 } ?: 1) + if (defaultSettings.direction == CurrentReaderSettings.Directions.BOTTOM_TO_TOP ) { + binding.mangaReaderPager.currentItem = + (maxChapterPage.toInt() - value.toInt()) / (dualPage { 2 } ?: 1) + } else { + binding.mangaReaderPager.currentItem = + (value.toInt() - 1) / (dualPage { 2 } ?: 1) + } pageSliderHide() } } @@ -331,7 +341,7 @@ class MangaReaderActivity : AppCompatActivity() { binding.mangaReaderNextChapter.performClick() } binding.mangaReaderNextChapter.setOnClickListener { - if (defaultSettings.direction == RIGHT_TO_LEFT || defaultSettings.direction == BOTTOM_TO_TOP) { + if (directionRLBT) { if (currentChapterIndex > 0) change(currentChapterIndex - 1) else snackString(getString(R.string.first_chapter)) } else { @@ -344,7 +354,7 @@ class MangaReaderActivity : AppCompatActivity() { binding.mangaReaderPreviousChapter.performClick() } binding.mangaReaderPreviousChapter.setOnClickListener { - if (defaultSettings.direction == RIGHT_TO_LEFT || defaultSettings.direction == BOTTOM_TO_TOP) { + if (directionRLBT) { if (chaptersArr.size > currentChapterIndex + 1) progress { change(currentChapterIndex + 1) } else snackString(getString(R.string.next_chapter_not_found)) } else { @@ -361,7 +371,7 @@ class MangaReaderActivity : AppCompatActivity() { PrefManager.setCustomVal("${media.id}_current_chp", chap.number) currentChapterIndex = chaptersArr.indexOf(chap.number) binding.mangaReaderChapterSelect.setSelection(currentChapterIndex) - if (defaultSettings.direction == RIGHT_TO_LEFT || defaultSettings.direction == BOTTOM_TO_TOP) { + if (directionRLBT) { binding.mangaReaderNextChap.text = chaptersTitleArr.getOrNull(currentChapterIndex - 1) ?: "" binding.mangaReaderPrevChap.text = chaptersTitleArr.getOrNull(currentChapterIndex + 1) ?: "" } else { @@ -459,7 +469,11 @@ class MangaReaderActivity : AppCompatActivity() { currentChapterPage = PrefManager.getCustomVal("${media.id}_${chapter.number}", 1L) - val chapImages = chapter.images() + val chapImages = if (directionPagedBT) { + chapter.images().reversed() + } else { + chapter.images() + } maxChapterPage = 0 if (chapImages.isNotEmpty()) { @@ -483,7 +497,11 @@ class MangaReaderActivity : AppCompatActivity() { } - val currentPage = currentChapterPage.toInt() + val currentPage = if (directionPagedBT) { + maxChapterPage - currentChapterPage + 1 + } else { + currentChapterPage + }.toInt() if ((defaultSettings.direction == TOP_TO_BOTTOM || defaultSettings.direction == BOTTOM_TO_TOP)) { binding.mangaReaderSwipy.vertical = true @@ -512,10 +530,10 @@ class MangaReaderActivity : AppCompatActivity() { binding.TopSwipeText.text = chaptersTitleArr.getOrNull(currentChapterIndex + 1) ?: getString(R.string.no_chapter) binding.mangaReaderSwipy.onTopSwiped = { - binding.mangaReaderNextChapter.performClick() + binding.mangaReaderPreviousChapter.performClick() } binding.mangaReaderSwipy.onBottomSwiped = { - binding.mangaReaderPreviousChapter.performClick() + binding.mangaReaderNextChapter.performClick() } } binding.mangaReaderSwipy.topBeingSwiped = { value -> @@ -624,7 +642,7 @@ class MangaReaderActivity : AppCompatActivity() { RecyclerView.VERTICAL else RecyclerView.HORIZONTAL, - !(defaultSettings.direction == TOP_TO_BOTTOM || defaultSettings.direction == LEFT_TO_RIGHT) + directionRLBT ) manager.preloadItemCount = 5 @@ -641,6 +659,8 @@ class MangaReaderActivity : AppCompatActivity() { else false } + manager.setStackFromEnd(defaultSettings.direction == BOTTOM_TO_TOP) + addOnScrollListener(object : RecyclerView.OnScrollListener() { override fun onScrolled(v: RecyclerView, dx: Int, dy: Int) { defaultSettings.apply { @@ -695,9 +715,7 @@ class MangaReaderActivity : AppCompatActivity() { visibility = View.VISIBLE adapter = imageAdapter layoutDirection = - if (defaultSettings.direction == BOTTOM_TO_TOP || defaultSettings.direction == RIGHT_TO_LEFT) - View.LAYOUT_DIRECTION_RTL - else View.LAYOUT_DIRECTION_LTR + if (directionRLBT) View.LAYOUT_DIRECTION_RTL else View.LAYOUT_DIRECTION_LTR orientation = if (defaultSettings.direction == LEFT_TO_RIGHT || defaultSettings.direction == RIGHT_TO_LEFT) ViewPager2.ORIENTATION_HORIZONTAL @@ -786,7 +804,7 @@ class MangaReaderActivity : AppCompatActivity() { val screenWidth = Resources.getSystem().displayMetrics.widthPixels //if in the 1st 1/5th of the screen width, left and lower than 1/5th of the screen height, left if (screenWidth / 5 in x + 1.. screenWidth - screenWidth / 5 && y > screenWidth / 5) { - pressLocation = if (defaultSettings.direction == RIGHT_TO_LEFT || defaultSettings.direction == BOTTOM_TO_TOP) { + pressLocation = if (defaultSettings.direction == RIGHT_TO_LEFT) { PressPos.LEFT } else { PressPos.RIGHT @@ -890,9 +908,10 @@ class MangaReaderActivity : AppCompatActivity() { } } binding.mangaReaderSlider.layoutDirection = - if (defaultSettings.direction == RIGHT_TO_LEFT || defaultSettings.direction == BOTTOM_TO_TOP) + if (directionRLBT) View.LAYOUT_DIRECTION_RTL - else View.LAYOUT_DIRECTION_LTR + else + View.LAYOUT_DIRECTION_LTR shouldShow?.apply { isContVisible = !this } if (isContVisible) { isContVisible = false @@ -900,12 +919,7 @@ class MangaReaderActivity : AppCompatActivity() { isAnimating = true ObjectAnimator.ofFloat(binding.mangaReaderCont, "alpha", 1f, 0f) .setDuration(controllerDuration).start() - ObjectAnimator.ofFloat( - binding.mangaReaderBottomLayout, - "translationY", - 0f, - 128f - ) + ObjectAnimator.ofFloat(binding.mangaReaderBottomLayout, "translationY", 0f, 128f) .apply { interpolator = overshoot;duration = controllerDuration;start() } ObjectAnimator.ofFloat(binding.mangaReaderTopLayout, "translationY", 0f, -128f) .apply { interpolator = overshoot;duration = controllerDuration;start() } @@ -925,7 +939,11 @@ class MangaReaderActivity : AppCompatActivity() { } private var loading = false - fun updatePageNumber(page: Long) { + fun updatePageNumber(pageNumber: Long) { + var page = pageNumber + if (directionPagedBT) { + page = maxChapterPage - pageNumber + 1 + } if (currentChapterPage != page) { currentChapterPage = page PrefManager.setCustomVal("${media.id}_${chapter.number}", page) @@ -1090,4 +1108,4 @@ class MangaReaderActivity : AppCompatActivity() { } return true } -} \ No newline at end of file +} diff --git a/app/src/main/java/ani/dantotsu/profile/activity/UsersAdapter.kt b/app/src/main/java/ani/dantotsu/profile/UsersAdapter.kt similarity index 89% rename from app/src/main/java/ani/dantotsu/profile/activity/UsersAdapter.kt rename to app/src/main/java/ani/dantotsu/profile/UsersAdapter.kt index 52763e09..9f31d27b 100644 --- a/app/src/main/java/ani/dantotsu/profile/activity/UsersAdapter.kt +++ b/app/src/main/java/ani/dantotsu/profile/UsersAdapter.kt @@ -1,14 +1,13 @@ -package ani.dantotsu.profile.activity +package ani.dantotsu.profile import android.content.Intent import android.view.LayoutInflater import android.view.ViewGroup import androidx.core.content.ContextCompat import androidx.recyclerview.widget.RecyclerView +import ani.dantotsu.blurImage import ani.dantotsu.databinding.ItemFollowerBinding import ani.dantotsu.loadImage -import ani.dantotsu.profile.ProfileActivity -import ani.dantotsu.profile.User import ani.dantotsu.setAnimation @@ -41,7 +40,7 @@ class UsersAdapter(private val user: ArrayList) : RecyclerView.Adapter(PrefName.AnilistUserName)) + openLinkInBrowser(anilistLink) + true + } settingsMALLoginRequired.visibility = View.GONE settingsMALLogin.visibility = View.VISIBLE @@ -234,6 +241,12 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene settingsMALUsername.visibility = View.VISIBLE settingsMALUsername.text = MAL.username settingsMALAvatar.loadImage(MAL.avatar) + settingsMALAvatar.setOnClickListener { + it.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS) + val myanilistLink = getString(R.string.myanilist_link, MAL.username) + openLinkInBrowser(myanilistLink) + true + } } else { settingsMALAvatar.setImageResource(R.drawable.ic_round_person_24) settingsMALUsername.visibility = View.GONE @@ -260,6 +273,12 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene val username = PrefManager.getVal(PrefName.DiscordUserName, null as String?) if (id != null && avatar != null) { settingsDiscordAvatar.loadImage("https://cdn.discordapp.com/avatars/$id/$avatar.png") + settingsDiscordAvatar.setOnClickListener { + it.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS) + val discordLink = getString(R.string.discord_link, id) + openLinkInBrowser(discordLink) + true + } } settingsDiscordUsername.visibility = View.VISIBLE settingsDiscordUsername.text = @@ -651,18 +670,18 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene val filteredLocations = Location.entries.filter { it.exportable } selectedArray.addAll(List(filteredLocations.size - 1) { false }) val dialog = AlertDialog.Builder(this@SettingsActivity, R.style.MyPopup) - .setTitle(R.string.import_export_settings) + .setTitle(R.string.backup_restore) .setMultiChoiceItems( filteredLocations.map { it.name }.toTypedArray(), selectedArray.toBooleanArray() ) { _, which, isChecked -> selectedArray[which] = isChecked } - .setPositiveButton(R.string.button_import) { dialog, _ -> + .setPositiveButton(R.string.button_restore) { dialog, _ -> openDocumentLauncher.launch(arrayOf("*/*")) dialog.dismiss() } - .setNegativeButton(R.string.button_export) { dialog, _ -> + .setNegativeButton(R.string.button_backup) { dialog, _ -> if (!selectedArray.contains(true)) { toast(R.string.no_location_selected) return@setNegativeButton diff --git a/app/src/main/res/drawable/adjust.xml b/app/src/main/res/drawable/adjust.xml new file mode 100644 index 00000000..6736f14f --- /dev/null +++ b/app/src/main/res/drawable/adjust.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/backup_restore.xml b/app/src/main/res/drawable/backup_restore.xml new file mode 100644 index 00000000..2c551ca4 --- /dev/null +++ b/app/src/main/res/drawable/backup_restore.xml @@ -0,0 +1,11 @@ + + + diff --git a/app/src/main/res/drawable/blur_on.xml b/app/src/main/res/drawable/blur_on.xml new file mode 100644 index 00000000..11630fa4 --- /dev/null +++ b/app/src/main/res/drawable/blur_on.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/cast_warning.xml b/app/src/main/res/drawable/cast_warning.xml new file mode 100644 index 00000000..15f35a55 --- /dev/null +++ b/app/src/main/res/drawable/cast_warning.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/stacks.xml b/app/src/main/res/drawable/stacks.xml new file mode 100644 index 00000000..29383b41 --- /dev/null +++ b/app/src/main/res/drawable/stacks.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/trail_length_short.xml b/app/src/main/res/drawable/trail_length_short.xml new file mode 100644 index 00000000..81166f10 --- /dev/null +++ b/app/src/main/res/drawable/trail_length_short.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/view_list_24.xml b/app/src/main/res/drawable/view_list_24.xml new file mode 100644 index 00000000..f7378f12 --- /dev/null +++ b/app/src/main/res/drawable/view_list_24.xml @@ -0,0 +1,11 @@ + + + diff --git a/app/src/main/res/layout/activity_player_settings.xml b/app/src/main/res/layout/activity_player_settings.xml index e1503989..adcd25b9 100644 --- a/app/src/main/res/layout/activity_player_settings.xml +++ b/app/src/main/res/layout/activity_player_settings.xml @@ -1162,7 +1162,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:checked="false" - android:drawableStart="@drawable/ic_round_cast_24" + android:drawableStart="@drawable/cast_warning" android:drawablePadding="16dp" android:elegantTextHeight="true" android:fontFamily="@font/poppins_bold" @@ -1215,4 +1215,4 @@ - \ No newline at end of file + diff --git a/app/src/main/res/layout/activity_settings_anime.xml b/app/src/main/res/layout/activity_settings_anime.xml index 49793f34..288a57ca 100644 --- a/app/src/main/res/layout/activity_settings_anime.xml +++ b/app/src/main/res/layout/activity_settings_anime.xml @@ -199,7 +199,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:checked="true" - android:drawableStart="@drawable/ic_round_movie_filter_24" + android:drawableStart="@drawable/view_list_24" android:drawablePadding="16dp" android:elegantTextHeight="true" android:fontFamily="@font/poppins_bold" diff --git a/app/src/main/res/layout/activity_settings_common.xml b/app/src/main/res/layout/activity_settings_common.xml index f0778d90..9916e78a 100644 --- a/app/src/main/res/layout/activity_settings_common.xml +++ b/app/src/main/res/layout/activity_settings_common.xml @@ -173,12 +173,12 @@ android:insetBottom="0dp" android:paddingStart="31dp" android:paddingEnd="31dp" - android:text="@string/import_export_settings" + android:text="@string/backup_restore" android:textAlignment="viewStart" android:textAllCaps="false" android:textColor="?attr/colorOnBackground" app:cornerRadius="0dp" - app:icon="@drawable/ic_download_24" + app:icon="@drawable/backup_restore" app:iconPadding="16dp" app:iconSize="24dp" app:iconTint="?attr/colorPrimary" /> diff --git a/app/src/main/res/layout/activity_settings_manga.xml b/app/src/main/res/layout/activity_settings_manga.xml index 7bc6b84c..f3199de0 100644 --- a/app/src/main/res/layout/activity_settings_manga.xml +++ b/app/src/main/res/layout/activity_settings_manga.xml @@ -163,7 +163,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:checked="false" - android:drawableStart="@drawable/ic_round_movie_filter_24" + android:drawableStart="@drawable/view_list_24" android:drawablePadding="16dp" android:elegantTextHeight="true" android:fontFamily="@font/poppins_bold" diff --git a/app/src/main/res/layout/activity_user_interface_settings.xml b/app/src/main/res/layout/activity_user_interface_settings.xml index 6d97b208..8cd05f44 100644 --- a/app/src/main/res/layout/activity_user_interface_settings.xml +++ b/app/src/main/res/layout/activity_user_interface_settings.xml @@ -240,7 +240,7 @@ android:layout_height="wrap_content" android:layout_marginBottom="8dp" android:checked="true" - android:drawableStart="@drawable/ic_round_animation_24" + android:drawableStart="@drawable/trail_length_short" android:drawablePadding="16dp" android:elegantTextHeight="true" android:fontFamily="@font/poppins_bold" @@ -302,7 +302,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:checked="true" - android:drawableStart="@drawable/ic_round_photo_size_select_actual_24" + android:drawableStart="@drawable/blur_on" android:drawablePadding="16dp" android:elegantTextHeight="true" android:fontFamily="@font/poppins_bold" @@ -328,7 +328,7 @@ android:paddingStart="32dp" android:paddingEnd="32dp" android:text="@string/radius" - app:drawableStartCompat="@drawable/ic_internet" + app:drawableStartCompat="@drawable/adjust" app:drawableTint="?attr/colorPrimary" /> diff --git a/app/src/main/res/layout/item_comments.xml b/app/src/main/res/layout/item_comments.xml index e6a77761..07f190ef 100644 --- a/app/src/main/res/layout/item_comments.xml +++ b/app/src/main/res/layout/item_comments.xml @@ -5,30 +5,39 @@ android:id="@+id/commentsCardView" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_marginStart="8dp" + android:layout_marginHorizontal="8dp" android:layout_marginTop="8dp" android:layout_marginBottom="4dp"> - - + android:backgroundTint="@color/transparent" + app:cardCornerRadius="64dp" + app:strokeColor="@color/transparent"> + + + - + app:layout_constraintTop_toBottomOf="@+id/commentText"> - + - + + - + - + + + + + + + + - - - - - - - + tools:visibility="gone" /> \ No newline at end of file diff --git a/app/src/main/res/menu/profile_details_menu.xml b/app/src/main/res/menu/profile_details_menu.xml new file mode 100644 index 00000000..d2e91740 --- /dev/null +++ b/app/src/main/res/menu/profile_details_menu.xml @@ -0,0 +1,19 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 6ef9f3ef..d92b3512 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -16,6 +16,7 @@ https://www.buymeacoffee.com/rebelonion https://anilist.co/user/%1$s/ + https://myanimelist.net/profile/%1$s/ https://discord.com/users/%1$s/ Home @@ -714,9 +715,9 @@ Requires Android 12+ Share username in crash reports Pinned Sources - Import/Export Settings - Import Settings - Import Settings + Backup and Restore + Import Settings + Restore Settings Try Internal Cast (Experimental) Comments @@ -831,8 +832,8 @@ Non quae tempore quo provident laudantium qui illo dolor vel quia dolor et exerc Quality: %1$dp Unknown Size %1$s MB - Import… - Export… + Restore + Backup No location selected Enjoying the App? Consider donating! @@ -872,4 +873,6 @@ Non quae tempore quo provident laudantium qui illo dolor vel quia dolor et exerc Please choose a directory to save your downloads Change Download Location Are you sure you want to change the download location?\nOld downloads may no longer be accessible. + Report + Ban