mirror of
https://github.com/rebelonion/Dantotsu.git
synced 2026-01-21 19:53:56 +00:00
Merge branch 'dev' into zephyr
This commit is contained in:
@@ -73,12 +73,24 @@
|
||||
android:resource="@xml/upcoming_widget_info" />
|
||||
</receiver>
|
||||
<activity
|
||||
android:name=".widgets.upcoming.UpcomingWidgetConfigureActivity"
|
||||
android:name=".widgets.upcoming.UpcomingWidgetConfigure"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<receiver
|
||||
android:name=".widgets.statistics.ProfileStatsWidget"
|
||||
android:exported="false">
|
||||
<intent-filter>
|
||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
||||
</intent-filter>
|
||||
|
||||
<meta-data
|
||||
android:name="android.appwidget.provider"
|
||||
android:resource="@xml/statistics_widget_info" />
|
||||
</receiver>
|
||||
<receiver android:name=".notifications.IncognitoNotificationClickReceiver" />
|
||||
|
||||
<activity
|
||||
@@ -115,6 +127,14 @@
|
||||
android:name=".settings.ExtensionsActivity"
|
||||
android:parentActivityName=".MainActivity"
|
||||
android:windowSoftInputMode="adjustResize|stateHidden" />
|
||||
<activity
|
||||
android:name=".widgets.statistics.ProfileStatsConfigure"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".profile.ProfileActivity"
|
||||
android:parentActivityName=".MainActivity"
|
||||
|
||||
146
app/src/main/java/ani/dantotsu/media/MediaNameAdapter.kt
Normal file
146
app/src/main/java/ani/dantotsu/media/MediaNameAdapter.kt
Normal file
@@ -0,0 +1,146 @@
|
||||
package ani.dantotsu.media
|
||||
|
||||
import java.util.Locale
|
||||
import java.util.regex.Matcher
|
||||
import java.util.regex.Pattern
|
||||
|
||||
object MediaNameAdapter {
|
||||
|
||||
private const val REGEX_ITEM = "[\\s:.\\-]*(\\d+\\.?\\d*)[\\s:.\\-]*"
|
||||
private const val REGEX_PART_NUMBER = "(?<!part\\s)\\b(\\d+)\\b"
|
||||
private const val REGEX_EPISODE =
|
||||
"(episode|episodio|ep|e)${REGEX_ITEM}\\(?\\s*(sub|subbed|dub|dubbed)*\\s*\\)?\\s*"
|
||||
private const val REGEX_SEASON = "(season|s)[\\s:.\\-]*(\\d+)[\\s:.\\-]*"
|
||||
private const val REGEX_SUBDUB = "^(soft)?[\\s-]*(sub|dub|mixed)(bed|s)?\\s*$"
|
||||
private const val REGEX_CHAPTER = "(chapter|chap|ch|c)${REGEX_ITEM}"
|
||||
|
||||
fun setSubDub(text: String, typeToSetTo: SubDubType): String? {
|
||||
val subdubPattern: Pattern = Pattern.compile(REGEX_SUBDUB, Pattern.CASE_INSENSITIVE)
|
||||
val subdubMatcher: Matcher = subdubPattern.matcher(text)
|
||||
|
||||
return if (subdubMatcher.find()) {
|
||||
val soft = subdubMatcher.group(1)
|
||||
val subdub = subdubMatcher.group(2)
|
||||
val bed = subdubMatcher.group(3) ?: ""
|
||||
|
||||
val toggled = when (typeToSetTo) {
|
||||
SubDubType.SUB -> "sub"
|
||||
SubDubType.DUB -> "dub"
|
||||
SubDubType.NULL -> ""
|
||||
}
|
||||
val toggledCasePreserved =
|
||||
if (subdub?.get(0)?.isUpperCase() == true || soft?.get(0)
|
||||
?.isUpperCase() == true
|
||||
) toggled.replaceFirstChar {
|
||||
if (it.isLowerCase()) it.titlecase(
|
||||
Locale.ROOT
|
||||
) else it.toString()
|
||||
} else toggled
|
||||
|
||||
subdubMatcher.replaceFirst(toggledCasePreserved + bed)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
fun getSubDub(text: String): SubDubType {
|
||||
val subdubPattern: Pattern = Pattern.compile(REGEX_SUBDUB, Pattern.CASE_INSENSITIVE)
|
||||
val subdubMatcher: Matcher = subdubPattern.matcher(text)
|
||||
|
||||
return if (subdubMatcher.find()) {
|
||||
val subdub = subdubMatcher.group(2)?.lowercase(Locale.ROOT)
|
||||
when (subdub) {
|
||||
"sub" -> SubDubType.SUB
|
||||
"dub" -> SubDubType.DUB
|
||||
else -> SubDubType.NULL
|
||||
}
|
||||
} else {
|
||||
SubDubType.NULL
|
||||
}
|
||||
}
|
||||
|
||||
enum class SubDubType {
|
||||
SUB, DUB, NULL
|
||||
}
|
||||
|
||||
fun findSeasonNumber(text: String): Int? {
|
||||
val seasonPattern: Pattern = Pattern.compile(REGEX_SEASON, Pattern.CASE_INSENSITIVE)
|
||||
val seasonMatcher: Matcher = seasonPattern.matcher(text)
|
||||
|
||||
return if (seasonMatcher.find()) {
|
||||
seasonMatcher.group(2)?.toInt()
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
fun findEpisodeNumber(text: String): Float? {
|
||||
val episodePattern: Pattern = Pattern.compile(REGEX_EPISODE, Pattern.CASE_INSENSITIVE)
|
||||
val episodeMatcher: Matcher = episodePattern.matcher(text)
|
||||
|
||||
return if (episodeMatcher.find()) {
|
||||
if (episodeMatcher.group(2) != null) {
|
||||
episodeMatcher.group(2)?.toFloat()
|
||||
} else {
|
||||
val failedEpisodeNumberPattern: Pattern =
|
||||
Pattern.compile(REGEX_PART_NUMBER, Pattern.CASE_INSENSITIVE)
|
||||
val failedEpisodeNumberMatcher: Matcher =
|
||||
failedEpisodeNumberPattern.matcher(text)
|
||||
if (failedEpisodeNumberMatcher.find()) {
|
||||
failedEpisodeNumberMatcher.group(1)?.toFloat()
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
fun removeEpisodeNumber(text: String): String {
|
||||
val regexPattern = Regex(REGEX_EPISODE, RegexOption.IGNORE_CASE)
|
||||
val removedNumber = text.replace(regexPattern, "").ifEmpty {
|
||||
text
|
||||
}
|
||||
val letterPattern = Regex("[a-zA-Z]")
|
||||
return if (letterPattern.containsMatchIn(removedNumber)) {
|
||||
removedNumber
|
||||
} else {
|
||||
text
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun removeEpisodeNumberCompletely(text: String): String {
|
||||
val regexPattern = Regex(REGEX_EPISODE, RegexOption.IGNORE_CASE)
|
||||
val removedNumber = text.replace(regexPattern, "")
|
||||
return if (removedNumber.equals(text, true)) { // if nothing was removed
|
||||
val failedEpisodeNumberPattern =
|
||||
Regex(REGEX_PART_NUMBER, RegexOption.IGNORE_CASE)
|
||||
failedEpisodeNumberPattern.replace(removedNumber) { mr ->
|
||||
mr.value.replaceFirst(mr.groupValues[1], "")
|
||||
}
|
||||
} else {
|
||||
removedNumber
|
||||
}
|
||||
}
|
||||
|
||||
fun findChapterNumber(text: String): Float? {
|
||||
val pattern: Pattern = Pattern.compile(REGEX_CHAPTER, Pattern.CASE_INSENSITIVE)
|
||||
val matcher: Matcher = pattern.matcher(text)
|
||||
|
||||
return if (matcher.find()) {
|
||||
matcher.group(2)?.toFloat()
|
||||
} else {
|
||||
val failedChapterNumberPattern: Pattern =
|
||||
Pattern.compile(REGEX_PART_NUMBER, Pattern.CASE_INSENSITIVE)
|
||||
val failedChapterNumberMatcher: Matcher =
|
||||
failedChapterNumberPattern.matcher(text)
|
||||
if (failedChapterNumberMatcher.find()) {
|
||||
failedChapterNumberMatcher.group(1)?.toFloat()
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,127 +0,0 @@
|
||||
package ani.dantotsu.media.anime
|
||||
|
||||
import java.util.Locale
|
||||
import java.util.regex.Matcher
|
||||
import java.util.regex.Pattern
|
||||
|
||||
class AnimeNameAdapter {
|
||||
companion object {
|
||||
const val episodeRegex =
|
||||
"(episode|episodio|ep|e)[\\s:.\\-]*(\\d+\\.?\\d*)[\\s:.\\-]*\\(?\\s*(sub|subbed|dub|dubbed)*\\s*\\)?\\s*"
|
||||
const val failedEpisodeNumberRegex =
|
||||
"(?<!part\\s)\\b(\\d+)\\b"
|
||||
const val seasonRegex = "(season|s)[\\s:.\\-]*(\\d+)[\\s:.\\-]*"
|
||||
const val subdubRegex = "^(soft)?[\\s-]*(sub|dub|mixed)(bed|s)?\\s*$"
|
||||
|
||||
fun setSubDub(text: String, typeToSetTo: SubDubType): String? {
|
||||
val subdubPattern: Pattern = Pattern.compile(subdubRegex, Pattern.CASE_INSENSITIVE)
|
||||
val subdubMatcher: Matcher = subdubPattern.matcher(text)
|
||||
|
||||
return if (subdubMatcher.find()) {
|
||||
val soft = subdubMatcher.group(1)
|
||||
val subdub = subdubMatcher.group(2)
|
||||
val bed = subdubMatcher.group(3) ?: ""
|
||||
|
||||
val toggled = when (typeToSetTo) {
|
||||
SubDubType.SUB -> "sub"
|
||||
SubDubType.DUB -> "dub"
|
||||
SubDubType.NULL -> ""
|
||||
}
|
||||
val toggledCasePreserved =
|
||||
if (subdub?.get(0)?.isUpperCase() == true || soft?.get(0)
|
||||
?.isUpperCase() == true
|
||||
) toggled.replaceFirstChar {
|
||||
if (it.isLowerCase()) it.titlecase(
|
||||
Locale.ROOT
|
||||
) else it.toString()
|
||||
} else toggled
|
||||
|
||||
subdubMatcher.replaceFirst(toggledCasePreserved + bed)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
fun getSubDub(text: String): SubDubType {
|
||||
val subdubPattern: Pattern = Pattern.compile(subdubRegex, Pattern.CASE_INSENSITIVE)
|
||||
val subdubMatcher: Matcher = subdubPattern.matcher(text)
|
||||
|
||||
return if (subdubMatcher.find()) {
|
||||
val subdub = subdubMatcher.group(2)?.lowercase(Locale.ROOT)
|
||||
when (subdub) {
|
||||
"sub" -> SubDubType.SUB
|
||||
"dub" -> SubDubType.DUB
|
||||
else -> SubDubType.NULL
|
||||
}
|
||||
} else {
|
||||
SubDubType.NULL
|
||||
}
|
||||
}
|
||||
|
||||
enum class SubDubType {
|
||||
SUB, DUB, NULL
|
||||
}
|
||||
|
||||
fun findSeasonNumber(text: String): Int? {
|
||||
val seasonPattern: Pattern = Pattern.compile(seasonRegex, Pattern.CASE_INSENSITIVE)
|
||||
val seasonMatcher: Matcher = seasonPattern.matcher(text)
|
||||
|
||||
return if (seasonMatcher.find()) {
|
||||
seasonMatcher.group(2)?.toInt()
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
fun findEpisodeNumber(text: String): Float? {
|
||||
val episodePattern: Pattern = Pattern.compile(episodeRegex, Pattern.CASE_INSENSITIVE)
|
||||
val episodeMatcher: Matcher = episodePattern.matcher(text)
|
||||
|
||||
return if (episodeMatcher.find()) {
|
||||
if (episodeMatcher.group(2) != null) {
|
||||
episodeMatcher.group(2)?.toFloat()
|
||||
} else {
|
||||
val failedEpisodeNumberPattern: Pattern =
|
||||
Pattern.compile(failedEpisodeNumberRegex, Pattern.CASE_INSENSITIVE)
|
||||
val failedEpisodeNumberMatcher: Matcher =
|
||||
failedEpisodeNumberPattern.matcher(text)
|
||||
if (failedEpisodeNumberMatcher.find()) {
|
||||
failedEpisodeNumberMatcher.group(1)?.toFloat()
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
fun removeEpisodeNumber(text: String): String {
|
||||
val regexPattern = Regex(episodeRegex, RegexOption.IGNORE_CASE)
|
||||
val removedNumber = text.replace(regexPattern, "").ifEmpty {
|
||||
text
|
||||
}
|
||||
val letterPattern = Regex("[a-zA-Z]")
|
||||
return if (letterPattern.containsMatchIn(removedNumber)) {
|
||||
removedNumber
|
||||
} else {
|
||||
text
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun removeEpisodeNumberCompletely(text: String): String {
|
||||
val regexPattern = Regex(episodeRegex, RegexOption.IGNORE_CASE)
|
||||
val removedNumber = text.replace(regexPattern, "")
|
||||
return if (removedNumber.equals(text, true)) { // if nothing was removed
|
||||
val failedEpisodeNumberPattern =
|
||||
Regex(failedEpisodeNumberRegex, RegexOption.IGNORE_CASE)
|
||||
failedEpisodeNumberPattern.replace(removedNumber) { mr ->
|
||||
mr.value.replaceFirst(mr.groupValues[1], "")
|
||||
}
|
||||
} else {
|
||||
removedNumber
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -26,6 +26,7 @@ import ani.dantotsu.isOnline
|
||||
import ani.dantotsu.loadImage
|
||||
import ani.dantotsu.media.Media
|
||||
import ani.dantotsu.media.MediaDetailsActivity
|
||||
import ani.dantotsu.media.MediaNameAdapter
|
||||
import ani.dantotsu.media.SourceSearchDialogFragment
|
||||
import ani.dantotsu.openSettings
|
||||
import ani.dantotsu.others.LanguageMapper
|
||||
@@ -403,7 +404,7 @@ class AnimeWatchAdapter(
|
||||
}
|
||||
val ep = media.anime.episodes!![continueEp]!!
|
||||
|
||||
val cleanedTitle = ep.title?.let { AnimeNameAdapter.removeEpisodeNumber(it) }
|
||||
val cleanedTitle = ep.title?.let { MediaNameAdapter.removeEpisodeNumber(it) }
|
||||
|
||||
binding.itemEpisodeImage.loadImage(
|
||||
ep.thumb ?: FileUrl[media.banner ?: media.cover], 0
|
||||
|
||||
@@ -41,6 +41,7 @@ import ani.dantotsu.media.Media
|
||||
import ani.dantotsu.media.MediaDetailsActivity
|
||||
import ani.dantotsu.media.MediaDetailsViewModel
|
||||
import ani.dantotsu.media.MediaType
|
||||
import ani.dantotsu.media.MediaNameAdapter
|
||||
import ani.dantotsu.navBarHeight
|
||||
import ani.dantotsu.notifications.subscription.SubscriptionHelper
|
||||
import ani.dantotsu.notifications.subscription.SubscriptionHelper.Companion.saveSubscription
|
||||
@@ -224,7 +225,7 @@ class AnimeWatchFragment : Fragment() {
|
||||
if (media.anime!!.kitsuEpisodes!!.containsKey(i)) {
|
||||
episode.desc =
|
||||
media.anime!!.kitsuEpisodes!![i]?.desc ?: episode.desc
|
||||
episode.title = if (AnimeNameAdapter.removeEpisodeNumberCompletely(
|
||||
episode.title = if (MediaNameAdapter.removeEpisodeNumberCompletely(
|
||||
episode.title ?: ""
|
||||
).isBlank()
|
||||
) media.anime!!.kitsuEpisodes!![i]?.title
|
||||
|
||||
@@ -21,6 +21,7 @@ import ani.dantotsu.databinding.ItemEpisodeListBinding
|
||||
import ani.dantotsu.download.anime.AnimeDownloaderService
|
||||
import ani.dantotsu.download.video.Helper
|
||||
import ani.dantotsu.media.Media
|
||||
import ani.dantotsu.media.MediaNameAdapter
|
||||
import ani.dantotsu.setAnimation
|
||||
import ani.dantotsu.settings.saving.PrefManager
|
||||
import com.bumptech.glide.Glide
|
||||
@@ -102,7 +103,7 @@ class EpisodeAdapter(
|
||||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||
val ep = arr[position]
|
||||
val title = if (!ep.title.isNullOrEmpty() && ep.title != "null") {
|
||||
ep.title?.let { AnimeNameAdapter.removeEpisodeNumber(it) }
|
||||
ep.title?.let { MediaNameAdapter.removeEpisodeNumber(it) }
|
||||
} else {
|
||||
ep.number
|
||||
} ?: ""
|
||||
|
||||
@@ -113,6 +113,7 @@ import ani.dantotsu.isOnline
|
||||
import ani.dantotsu.logError
|
||||
import ani.dantotsu.media.Media
|
||||
import ani.dantotsu.media.MediaDetailsViewModel
|
||||
import ani.dantotsu.media.MediaNameAdapter
|
||||
import ani.dantotsu.media.SubtitleDownloader
|
||||
import ani.dantotsu.okHttpClient
|
||||
import ani.dantotsu.others.AniSkip
|
||||
@@ -998,7 +999,7 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
|
||||
episodeTitleArr = arrayListOf()
|
||||
episodes.forEach {
|
||||
val episode = it.value
|
||||
val cleanedTitle = AnimeNameAdapter.removeEpisodeNumberCompletely(episode.title ?: "")
|
||||
val cleanedTitle = MediaNameAdapter.removeEpisodeNumberCompletely(episode.title ?: "")
|
||||
episodeTitleArr.add("Episode ${episode.number}${if (episode.filler) " [Filler]" else ""}${if (cleanedTitle.isNotBlank() && cleanedTitle != "null") ": $cleanedTitle" else ""}")
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ import ani.dantotsu.currContext
|
||||
import ani.dantotsu.databinding.ItemChapterListBinding
|
||||
import ani.dantotsu.databinding.ItemEpisodeCompactBinding
|
||||
import ani.dantotsu.media.Media
|
||||
import ani.dantotsu.media.MediaNameAdapter
|
||||
import ani.dantotsu.setAnimation
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
@@ -267,10 +268,10 @@ class MangaChapterAdapter(
|
||||
val binding = holder.binding
|
||||
setAnimation(fragment.requireContext(), holder.binding.root)
|
||||
val ep = arr[position]
|
||||
val parsedNumber = MangaNameAdapter.findChapterNumber(ep.number)?.toInt()
|
||||
val parsedNumber = MediaNameAdapter.findChapterNumber(ep.number)?.toInt()
|
||||
binding.itemEpisodeNumber.text = parsedNumber?.toString() ?: ep.number
|
||||
if (media.userProgress != null) {
|
||||
if ((MangaNameAdapter.findChapterNumber(ep.number)
|
||||
if ((MediaNameAdapter.findChapterNumber(ep.number)
|
||||
?: 9999f) <= media.userProgress!!.toFloat()
|
||||
)
|
||||
binding.itemEpisodeViewedCover.visibility = View.VISIBLE
|
||||
@@ -279,7 +280,7 @@ class MangaChapterAdapter(
|
||||
binding.itemEpisodeCont.setOnLongClickListener {
|
||||
updateProgress(
|
||||
media,
|
||||
MangaNameAdapter.findChapterNumber(ep.number).toString()
|
||||
MediaNameAdapter.findChapterNumber(ep.number).toString()
|
||||
)
|
||||
true
|
||||
}
|
||||
@@ -315,7 +316,7 @@ class MangaChapterAdapter(
|
||||
} else binding.itemChapterTitle.visibility = View.VISIBLE
|
||||
|
||||
if (media.userProgress != null) {
|
||||
if ((MangaNameAdapter.findChapterNumber(ep.number)
|
||||
if ((MediaNameAdapter.findChapterNumber(ep.number)
|
||||
?: 9999f) <= media.userProgress!!.toFloat()
|
||||
) {
|
||||
binding.itemEpisodeViewedCover.visibility = View.VISIBLE
|
||||
@@ -326,7 +327,7 @@ class MangaChapterAdapter(
|
||||
binding.root.setOnLongClickListener {
|
||||
updateProgress(
|
||||
media,
|
||||
MangaNameAdapter.findChapterNumber(ep.number).toString()
|
||||
MediaNameAdapter.findChapterNumber(ep.number).toString()
|
||||
)
|
||||
true
|
||||
}
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
package ani.dantotsu.media.manga
|
||||
|
||||
import java.util.regex.Matcher
|
||||
import java.util.regex.Pattern
|
||||
|
||||
class MangaNameAdapter {
|
||||
companion object {
|
||||
private const val chapterRegex = "(chapter|chap|ch|c)[\\s:.\\-]*(\\d+\\.?\\d*)[\\s:.\\-]*"
|
||||
private const val filedChapterNumberRegex = "(?<!part\\s)\\b(\\d+)\\b"
|
||||
fun findChapterNumber(text: String): Float? {
|
||||
val pattern: Pattern = Pattern.compile(chapterRegex, Pattern.CASE_INSENSITIVE)
|
||||
val matcher: Matcher = pattern.matcher(text)
|
||||
|
||||
return if (matcher.find()) {
|
||||
matcher.group(2)?.toFloat()
|
||||
} else {
|
||||
val failedChapterNumberPattern: Pattern =
|
||||
Pattern.compile(filedChapterNumberRegex, Pattern.CASE_INSENSITIVE)
|
||||
val failedChapterNumberMatcher: Matcher =
|
||||
failedChapterNumberPattern.matcher(text)
|
||||
if (failedChapterNumberMatcher.find()) {
|
||||
failedChapterNumberMatcher.group(1)?.toFloat()
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -26,6 +26,7 @@ import ani.dantotsu.isOnline
|
||||
import ani.dantotsu.loadImage
|
||||
import ani.dantotsu.media.Media
|
||||
import ani.dantotsu.media.MediaDetailsActivity
|
||||
import ani.dantotsu.media.MediaNameAdapter
|
||||
import ani.dantotsu.media.SourceSearchDialogFragment
|
||||
import ani.dantotsu.media.anime.handleProgress
|
||||
import ani.dantotsu.openSettings
|
||||
@@ -385,8 +386,8 @@ class MangaReadAdapter(
|
||||
)
|
||||
}
|
||||
|
||||
val startChapter = MangaNameAdapter.findChapterNumber(names[limit * (position)])
|
||||
val endChapter = MangaNameAdapter.findChapterNumber(names[last - 1])
|
||||
val startChapter = MediaNameAdapter.findChapterNumber(names[limit * (position)])
|
||||
val endChapter = MediaNameAdapter.findChapterNumber(names[last - 1])
|
||||
val startChapterString = if (startChapter != null) {
|
||||
"Ch.$startChapter"
|
||||
} else {
|
||||
@@ -448,7 +449,7 @@ class MangaReadAdapter(
|
||||
chapter.scanlator !in hiddenScanlators
|
||||
}
|
||||
val formattedChapters = filteredChapters.map {
|
||||
MangaNameAdapter.findChapterNumber(it)?.toInt()?.toString()
|
||||
MediaNameAdapter.findChapterNumber(it)?.toInt()?.toString()
|
||||
}
|
||||
if (formattedChapters.contains(continueEp)) {
|
||||
continueEp = chapters[formattedChapters.indexOf(continueEp)]
|
||||
|
||||
@@ -41,6 +41,7 @@ import ani.dantotsu.media.Media
|
||||
import ani.dantotsu.media.MediaDetailsActivity
|
||||
import ani.dantotsu.media.MediaDetailsViewModel
|
||||
import ani.dantotsu.media.MediaType
|
||||
import ani.dantotsu.media.MediaNameAdapter
|
||||
import ani.dantotsu.media.manga.mangareader.ChapterLoaderDialog
|
||||
import ani.dantotsu.navBarHeight
|
||||
import ani.dantotsu.notifications.subscription.SubscriptionHelper
|
||||
@@ -227,7 +228,7 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
|
||||
val chapters = media.manga?.chapters?.values?.toList()
|
||||
//filter by selected language
|
||||
val progressChapterIndex = (chapters?.indexOfFirst {
|
||||
MangaNameAdapter.findChapterNumber(it.number)?.toInt() == selected
|
||||
MediaNameAdapter.findChapterNumber(it.number)?.toInt() == selected
|
||||
} ?: 0) + 1
|
||||
|
||||
if (progressChapterIndex < 0 || n < 1 || chapters == null) return
|
||||
|
||||
@@ -57,9 +57,9 @@ import ani.dantotsu.logError
|
||||
import ani.dantotsu.media.Media
|
||||
import ani.dantotsu.media.MediaDetailsViewModel
|
||||
import ani.dantotsu.media.MediaSingleton
|
||||
import ani.dantotsu.media.MediaNameAdapter
|
||||
import ani.dantotsu.media.manga.MangaCache
|
||||
import ani.dantotsu.media.manga.MangaChapter
|
||||
import ani.dantotsu.media.manga.MangaNameAdapter
|
||||
import ani.dantotsu.others.ImageViewDialog
|
||||
import ani.dantotsu.parsers.HMangaSources
|
||||
import ani.dantotsu.parsers.MangaImage
|
||||
@@ -180,7 +180,7 @@ class MangaReaderActivity : AppCompatActivity() {
|
||||
defaultSettings = loadReaderSettings("reader_settings") ?: defaultSettings
|
||||
|
||||
onBackPressedDispatcher.addCallback(this) {
|
||||
val chapter = (MangaNameAdapter.findChapterNumber(media.manga!!.selectedChapter!!)
|
||||
val chapter = (MediaNameAdapter.findChapterNumber(media.manga!!.selectedChapter!!)
|
||||
?.minus(1L) ?: 0).toString()
|
||||
if (chapter == "0.0" && PrefManager.getVal(PrefName.ChapterZeroReader)
|
||||
// Not asking individually or incognito
|
||||
@@ -978,7 +978,7 @@ class MangaReaderActivity : AppCompatActivity() {
|
||||
PrefManager.setCustomVal("${media.id}_save_progress", true)
|
||||
updateProgress(
|
||||
media,
|
||||
MangaNameAdapter.findChapterNumber(media.manga!!.selectedChapter!!)
|
||||
MediaNameAdapter.findChapterNumber(media.manga!!.selectedChapter!!)
|
||||
.toString()
|
||||
)
|
||||
dialog.dismiss()
|
||||
@@ -1000,7 +1000,7 @@ class MangaReaderActivity : AppCompatActivity() {
|
||||
)
|
||||
updateProgress(
|
||||
media,
|
||||
MangaNameAdapter.findChapterNumber(media.manga!!.selectedChapter!!)
|
||||
MediaNameAdapter.findChapterNumber(media.manga!!.selectedChapter!!)
|
||||
.toString()
|
||||
)
|
||||
runnable.run()
|
||||
|
||||
@@ -3,13 +3,11 @@ package ani.dantotsu.notifications.subscription
|
||||
import ani.dantotsu.R
|
||||
import ani.dantotsu.currContext
|
||||
import ani.dantotsu.media.Media
|
||||
import ani.dantotsu.media.MediaNameAdapter
|
||||
import ani.dantotsu.media.Selected
|
||||
import ani.dantotsu.media.manga.MangaNameAdapter
|
||||
import ani.dantotsu.parsers.AnimeParser
|
||||
import ani.dantotsu.parsers.AnimeSources
|
||||
import ani.dantotsu.parsers.Episode
|
||||
import ani.dantotsu.parsers.HAnimeSources
|
||||
import ani.dantotsu.parsers.HMangaSources
|
||||
import ani.dantotsu.parsers.MangaChapter
|
||||
import ani.dantotsu.parsers.MangaParser
|
||||
import ani.dantotsu.parsers.MangaSources
|
||||
@@ -105,7 +103,7 @@ class SubscriptionHelper {
|
||||
}
|
||||
|
||||
return chp?.apply {
|
||||
selected.latest = MangaNameAdapter.findChapterNumber(number) ?: 0f
|
||||
selected.latest = MediaNameAdapter.findChapterNumber(number) ?: 0f
|
||||
saveSelected(id, selected)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ package ani.dantotsu.parsers
|
||||
import android.content.Context
|
||||
import ani.dantotsu.FileUrl
|
||||
import ani.dantotsu.currContext
|
||||
import ani.dantotsu.media.anime.AnimeNameAdapter
|
||||
import ani.dantotsu.media.MediaNameAdapter
|
||||
import ani.dantotsu.media.manga.ImageData
|
||||
import ani.dantotsu.media.manga.MangaCache
|
||||
import ani.dantotsu.snackString
|
||||
@@ -73,12 +73,12 @@ class DynamicAnimeParser(extension: AnimeExtension.Installed) : AnimeParser() {
|
||||
configurableSource.getPreferenceKey(),
|
||||
Context.MODE_PRIVATE
|
||||
)
|
||||
sharedPreferences.all.filterValues { AnimeNameAdapter.getSubDub(it.toString()) != AnimeNameAdapter.Companion.SubDubType.NULL }
|
||||
sharedPreferences.all.filterValues { MediaNameAdapter.getSubDub(it.toString()) != MediaNameAdapter.SubDubType.NULL }
|
||||
.forEach { value ->
|
||||
return when (AnimeNameAdapter.getSubDub(value.value.toString())) {
|
||||
AnimeNameAdapter.Companion.SubDubType.SUB -> false
|
||||
AnimeNameAdapter.Companion.SubDubType.DUB -> true
|
||||
AnimeNameAdapter.Companion.SubDubType.NULL -> false
|
||||
return when (MediaNameAdapter.getSubDub(value.value.toString())) {
|
||||
MediaNameAdapter.SubDubType.SUB -> false
|
||||
MediaNameAdapter.SubDubType.DUB -> true
|
||||
MediaNameAdapter.SubDubType.NULL -> false
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -92,8 +92,8 @@ class DynamicAnimeParser(extension: AnimeExtension.Installed) : AnimeParser() {
|
||||
val configurableSource = extension.sources[sourceLanguage] as? ConfigurableAnimeSource
|
||||
?: return
|
||||
val type = when (setDub) {
|
||||
true -> AnimeNameAdapter.Companion.SubDubType.DUB
|
||||
false -> AnimeNameAdapter.Companion.SubDubType.SUB
|
||||
true -> MediaNameAdapter.SubDubType.DUB
|
||||
false -> MediaNameAdapter.SubDubType.SUB
|
||||
}
|
||||
currContext()?.let { context ->
|
||||
val sharedPreferences =
|
||||
@@ -101,9 +101,9 @@ class DynamicAnimeParser(extension: AnimeExtension.Installed) : AnimeParser() {
|
||||
configurableSource.getPreferenceKey(),
|
||||
Context.MODE_PRIVATE
|
||||
)
|
||||
sharedPreferences.all.filterValues { AnimeNameAdapter.getSubDub(it.toString()) != AnimeNameAdapter.Companion.SubDubType.NULL }
|
||||
sharedPreferences.all.filterValues { MediaNameAdapter.getSubDub(it.toString()) != MediaNameAdapter.SubDubType.NULL }
|
||||
.forEach { value ->
|
||||
val setValue = AnimeNameAdapter.setSubDub(value.value.toString(), type)
|
||||
val setValue = MediaNameAdapter.setSubDub(value.value.toString(), type)
|
||||
if (setValue != null) {
|
||||
sharedPreferences.edit().putString(value.key, setValue).apply()
|
||||
}
|
||||
@@ -122,9 +122,9 @@ class DynamicAnimeParser(extension: AnimeExtension.Installed) : AnimeParser() {
|
||||
Context.MODE_PRIVATE
|
||||
)
|
||||
sharedPreferences.all.filterValues {
|
||||
AnimeNameAdapter.setSubDub(
|
||||
MediaNameAdapter.setSubDub(
|
||||
it.toString(),
|
||||
AnimeNameAdapter.Companion.SubDubType.NULL
|
||||
MediaNameAdapter.SubDubType.NULL
|
||||
) != null
|
||||
}
|
||||
.forEach { _ -> return true }
|
||||
@@ -150,7 +150,7 @@ class DynamicAnimeParser(extension: AnimeExtension.Installed) : AnimeParser() {
|
||||
val sortedEpisodes = if (res[0].episode_number == -1f) {
|
||||
// Find the number in the string and sort by that number
|
||||
val sortedByStringNumber = res.sortedBy {
|
||||
val matchResult = AnimeNameAdapter.findEpisodeNumber(it.name)
|
||||
val matchResult = MediaNameAdapter.findEpisodeNumber(it.name)
|
||||
val number = matchResult ?: Float.MAX_VALUE
|
||||
it.episode_number = number // Store the found number in episode_number
|
||||
number
|
||||
@@ -171,13 +171,13 @@ class DynamicAnimeParser(extension: AnimeExtension.Installed) : AnimeParser() {
|
||||
var episodeCounter = 1f
|
||||
// Group by season, sort within each season, and then renumber while keeping episode number 0 as is
|
||||
val seasonGroups =
|
||||
res.groupBy { AnimeNameAdapter.findSeasonNumber(it.name) ?: 0 }
|
||||
res.groupBy { MediaNameAdapter.findSeasonNumber(it.name) ?: 0 }
|
||||
seasonGroups.keys.sortedBy { it }
|
||||
.flatMap { season ->
|
||||
seasonGroups[season]?.sortedBy { it.episode_number }?.map { episode ->
|
||||
if (episode.episode_number != 0f) { // Skip renumbering for episode number 0
|
||||
val potentialNumber =
|
||||
AnimeNameAdapter.findEpisodeNumber(episode.name)
|
||||
MediaNameAdapter.findEpisodeNumber(episode.name)
|
||||
if (potentialNumber != null) {
|
||||
episode.episode_number = potentialNumber
|
||||
} else {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package ani.dantotsu.parsers
|
||||
|
||||
import ani.dantotsu.FileUrl
|
||||
import ani.dantotsu.media.manga.MangaNameAdapter
|
||||
import ani.dantotsu.media.MediaNameAdapter
|
||||
import com.bumptech.glide.load.resource.bitmap.BitmapTransformation
|
||||
import eu.kanade.tachiyomi.source.model.Page
|
||||
import eu.kanade.tachiyomi.source.model.SChapter
|
||||
@@ -33,9 +33,9 @@ abstract class MangaParser : BaseParser() {
|
||||
): MangaChapter? {
|
||||
val chapter = loadChapters(mangaLink, extra, sManga)
|
||||
val max = chapter
|
||||
.maxByOrNull { MangaNameAdapter.findChapterNumber(it.number) ?: 0f }
|
||||
.maxByOrNull { MediaNameAdapter.findChapterNumber(it.number) ?: 0f }
|
||||
return max
|
||||
?.takeIf { latest < (MangaNameAdapter.findChapterNumber(it.number) ?: 0.001f) }
|
||||
?.takeIf { latest < (MediaNameAdapter.findChapterNumber(it.number) ?: 0.001f) }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -5,7 +5,7 @@ import android.os.Environment
|
||||
import ani.dantotsu.currContext
|
||||
import ani.dantotsu.download.DownloadsManager
|
||||
import ani.dantotsu.media.MediaType
|
||||
import ani.dantotsu.media.anime.AnimeNameAdapter
|
||||
import ani.dantotsu.media.MediaNameAdapter
|
||||
import ani.dantotsu.tryWithSuspend
|
||||
import eu.kanade.tachiyomi.animesource.model.SAnime
|
||||
import eu.kanade.tachiyomi.animesource.model.SEpisode
|
||||
@@ -54,7 +54,7 @@ class OfflineAnimeParser : AnimeParser() {
|
||||
episodes.add(episode)
|
||||
}
|
||||
}
|
||||
episodes.sortBy { AnimeNameAdapter.findEpisodeNumber(it.number) }
|
||||
episodes.sortBy { MediaNameAdapter.findEpisodeNumber(it.number) }
|
||||
return episodes
|
||||
}
|
||||
return emptyList()
|
||||
|
||||
@@ -3,7 +3,7 @@ package ani.dantotsu.parsers
|
||||
import android.os.Environment
|
||||
import ani.dantotsu.currContext
|
||||
import ani.dantotsu.download.DownloadsManager
|
||||
import ani.dantotsu.media.manga.MangaNameAdapter
|
||||
import ani.dantotsu.media.MediaNameAdapter
|
||||
import ani.dantotsu.util.Logger
|
||||
import eu.kanade.tachiyomi.source.model.SChapter
|
||||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
@@ -43,7 +43,7 @@ class OfflineMangaParser : MangaParser() {
|
||||
chapters.add(chapter)
|
||||
}
|
||||
}
|
||||
chapters.sortBy { MangaNameAdapter.findChapterNumber(it.number) }
|
||||
chapters.sortBy { MediaNameAdapter.findChapterNumber(it.number) }
|
||||
return chapters
|
||||
}
|
||||
return emptyList()
|
||||
|
||||
@@ -3,7 +3,7 @@ package ani.dantotsu.parsers
|
||||
import android.os.Environment
|
||||
import ani.dantotsu.currContext
|
||||
import ani.dantotsu.download.DownloadsManager
|
||||
import ani.dantotsu.media.manga.MangaNameAdapter
|
||||
import ani.dantotsu.media.MediaNameAdapter
|
||||
import me.xdrop.fuzzywuzzy.FuzzySearch
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
@@ -38,7 +38,7 @@ class OfflineNovelParser : NovelParser() {
|
||||
chapters.add(chapter)
|
||||
}
|
||||
}
|
||||
chapters.sortBy { MangaNameAdapter.findChapterNumber(it.name) }
|
||||
chapters.sortBy { MediaNameAdapter.findChapterNumber(it.name) }
|
||||
return chapters.first()
|
||||
}
|
||||
return Book(
|
||||
|
||||
@@ -21,7 +21,7 @@ import nl.joery.animatedbottombar.AnimatedBottomBar
|
||||
class FeedActivity : AppCompatActivity() {
|
||||
private lateinit var binding: ActivityFeedBinding
|
||||
private var selected: Int = 0
|
||||
private lateinit var navBar: AnimatedBottomBar
|
||||
lateinit var navBar: AnimatedBottomBar
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
@@ -50,16 +50,21 @@ class FeedFragment : Fragment() {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
activity = requireActivity()
|
||||
|
||||
binding.listRecyclerView.setBaseline((activity as ProfileActivity).navBar)
|
||||
userId = arguments?.getInt("userId", -1)
|
||||
activityId = arguments?.getInt("activityId", -1) ?: -1
|
||||
if (userId == -1) userId = null
|
||||
global = arguments?.getBoolean("global", false) ?: false
|
||||
|
||||
val navBar = if (userId != null)
|
||||
(activity as ProfileActivity).navBar
|
||||
else
|
||||
(activity as FeedActivity).navBar
|
||||
binding.listRecyclerView.setBaseline(navBar)
|
||||
|
||||
binding.listRecyclerView.adapter = adapter
|
||||
binding.listRecyclerView.layoutManager =
|
||||
LinearLayoutManager(requireContext(), LinearLayoutManager.VERTICAL, false)
|
||||
binding.listProgressBar.visibility = ViewGroup.VISIBLE
|
||||
userId = arguments?.getInt("userId", -1)
|
||||
activityId = arguments?.getInt("activityId", -1) ?: -1
|
||||
if (userId == -1) userId = null
|
||||
global = arguments?.getBoolean("global", false) ?: false
|
||||
}
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
@@ -67,7 +72,11 @@ class FeedFragment : Fragment() {
|
||||
super.onResume()
|
||||
if (this::binding.isInitialized) {
|
||||
binding.root.requestLayout()
|
||||
binding.listRecyclerView.setBaseline((activity as ProfileActivity).navBar)
|
||||
val navBar = if (userId != null)
|
||||
(activity as ProfileActivity).navBar
|
||||
else
|
||||
(activity as FeedActivity).navBar
|
||||
binding.listRecyclerView.setBaseline(navBar)
|
||||
if (!loadedFirstTime) {
|
||||
activity.lifecycleScope.launch(Dispatchers.IO) {
|
||||
val nulledId = if (activityId == -1) null else activityId
|
||||
|
||||
@@ -13,7 +13,7 @@ import androidx.lifecycle.lifecycleScope
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import ani.dantotsu.R
|
||||
import ani.dantotsu.connections.crashlytics.CrashlyticsInterface
|
||||
import ani.dantotsu.databinding.FragmentAnimeExtensionsBinding
|
||||
import ani.dantotsu.databinding.FragmentExtensionsBinding
|
||||
import ani.dantotsu.settings.paging.AnimeExtensionAdapter
|
||||
import ani.dantotsu.settings.paging.AnimeExtensionsViewModel
|
||||
import ani.dantotsu.settings.paging.AnimeExtensionsViewModelFactory
|
||||
@@ -30,7 +30,7 @@ import uy.kohesive.injekt.api.get
|
||||
|
||||
class AnimeExtensionsFragment : Fragment(),
|
||||
SearchQueryHandler, OnAnimeInstallClickListener {
|
||||
private var _binding: FragmentAnimeExtensionsBinding? = null
|
||||
private var _binding: FragmentExtensionsBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
|
||||
private val viewModel: AnimeExtensionsViewModel by viewModels {
|
||||
@@ -48,12 +48,12 @@ class AnimeExtensionsFragment : Fragment(),
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
_binding = FragmentAnimeExtensionsBinding.inflate(inflater, container, false)
|
||||
_binding = FragmentExtensionsBinding.inflate(inflater, container, false)
|
||||
|
||||
binding.allAnimeExtensionsRecyclerView.isNestedScrollingEnabled = false
|
||||
binding.allAnimeExtensionsRecyclerView.adapter = adapter
|
||||
binding.allAnimeExtensionsRecyclerView.layoutManager = LinearLayoutManager(context)
|
||||
(binding.allAnimeExtensionsRecyclerView.layoutManager as LinearLayoutManager).isItemPrefetchEnabled =
|
||||
binding.allExtensionsRecyclerView.isNestedScrollingEnabled = false
|
||||
binding.allExtensionsRecyclerView.adapter = adapter
|
||||
binding.allExtensionsRecyclerView.layoutManager = LinearLayoutManager(context)
|
||||
(binding.allExtensionsRecyclerView.layoutManager as LinearLayoutManager).isItemPrefetchEnabled =
|
||||
true
|
||||
|
||||
lifecycleScope.launch {
|
||||
@@ -91,8 +91,8 @@ class AnimeExtensionsFragment : Fragment(),
|
||||
Notifications.CHANNEL_DOWNLOADER_PROGRESS
|
||||
)
|
||||
.setSmallIcon(R.drawable.ic_round_sync_24)
|
||||
.setContentTitle("Installing extension")
|
||||
.setContentText("Step: $installStep")
|
||||
.setContentTitle(getString(R.string.installing_extension))
|
||||
.setContentText(getString(R.string.install_step, installStep))
|
||||
.setPriority(NotificationCompat.PRIORITY_LOW)
|
||||
notificationManager.notify(1, builder.build())
|
||||
},
|
||||
@@ -103,11 +103,11 @@ class AnimeExtensionsFragment : Fragment(),
|
||||
Notifications.CHANNEL_DOWNLOADER_ERROR
|
||||
)
|
||||
.setSmallIcon(R.drawable.ic_round_info_24)
|
||||
.setContentTitle("Installation failed: ${error.message}")
|
||||
.setContentText("Error: ${error.message}")
|
||||
.setContentTitle(getString(R.string.installation_failed, error.message))
|
||||
.setContentText(getString(R.string.error_message, error.message))
|
||||
.setPriority(NotificationCompat.PRIORITY_HIGH)
|
||||
notificationManager.notify(1, builder.build())
|
||||
snackString("Installation failed: ${error.message}")
|
||||
snackString(getString(R.string.installation_failed, error.message))
|
||||
},
|
||||
{
|
||||
val builder = NotificationCompat.Builder(
|
||||
@@ -115,12 +115,12 @@ class AnimeExtensionsFragment : Fragment(),
|
||||
Notifications.CHANNEL_DOWNLOADER_PROGRESS
|
||||
)
|
||||
.setSmallIcon(R.drawable.ic_download_24)
|
||||
.setContentTitle("Installation complete")
|
||||
.setContentText("The extension has been successfully installed.")
|
||||
.setContentTitle(getString(R.string.installation_complete))
|
||||
.setContentText(getString(R.string.extension_has_been_installed))
|
||||
.setPriority(NotificationCompat.PRIORITY_LOW)
|
||||
notificationManager.notify(1, builder.build())
|
||||
viewModel.invalidatePager()
|
||||
snackString("Extension installed")
|
||||
snackString(getString(R.string.extension_installed))
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.viewpager2.widget.ViewPager2
|
||||
import ani.dantotsu.R
|
||||
import ani.dantotsu.connections.crashlytics.CrashlyticsInterface
|
||||
import ani.dantotsu.databinding.FragmentAnimeExtensionsBinding
|
||||
import ani.dantotsu.databinding.FragmentExtensionsBinding
|
||||
import ani.dantotsu.others.LanguageMapper
|
||||
import ani.dantotsu.parsers.AnimeSources
|
||||
import ani.dantotsu.settings.extensionprefs.AnimeSourcePreferencesFragment
|
||||
@@ -49,7 +49,7 @@ import java.util.Locale
|
||||
class InstalledAnimeExtensionsFragment : Fragment(), SearchQueryHandler {
|
||||
|
||||
|
||||
private var _binding: FragmentAnimeExtensionsBinding? = null
|
||||
private var _binding: FragmentExtensionsBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
private lateinit var extensionsRecyclerView: RecyclerView
|
||||
private val skipIcons: Boolean = PrefManager.getVal(PrefName.SkipExtensionIcons)
|
||||
@@ -183,9 +183,9 @@ class InstalledAnimeExtensionsFragment : Fragment(), SearchQueryHandler {
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
_binding = FragmentAnimeExtensionsBinding.inflate(inflater, container, false)
|
||||
_binding = FragmentExtensionsBinding.inflate(inflater, container, false)
|
||||
|
||||
extensionsRecyclerView = binding.allAnimeExtensionsRecyclerView
|
||||
extensionsRecyclerView = binding.allExtensionsRecyclerView
|
||||
extensionsRecyclerView.layoutManager = LinearLayoutManager(requireContext())
|
||||
extensionsRecyclerView.adapter = extensionsAdapter
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.viewpager2.widget.ViewPager2
|
||||
import ani.dantotsu.R
|
||||
import ani.dantotsu.connections.crashlytics.CrashlyticsInterface
|
||||
import ani.dantotsu.databinding.FragmentMangaExtensionsBinding
|
||||
import ani.dantotsu.databinding.FragmentExtensionsBinding
|
||||
import ani.dantotsu.others.LanguageMapper
|
||||
import ani.dantotsu.parsers.MangaSources
|
||||
import ani.dantotsu.settings.extensionprefs.MangaSourcePreferencesFragment
|
||||
@@ -48,7 +48,7 @@ import java.util.Collections
|
||||
import java.util.Locale
|
||||
|
||||
class InstalledMangaExtensionsFragment : Fragment(), SearchQueryHandler {
|
||||
private var _binding: FragmentMangaExtensionsBinding? = null
|
||||
private var _binding: FragmentExtensionsBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
private lateinit var extensionsRecyclerView: RecyclerView
|
||||
private val skipIcons: Boolean = PrefManager.getVal(PrefName.SkipExtensionIcons)
|
||||
@@ -181,9 +181,9 @@ class InstalledMangaExtensionsFragment : Fragment(), SearchQueryHandler {
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
_binding = FragmentMangaExtensionsBinding.inflate(inflater, container, false)
|
||||
_binding = FragmentExtensionsBinding.inflate(inflater, container, false)
|
||||
|
||||
extensionsRecyclerView = binding.allMangaExtensionsRecyclerView
|
||||
extensionsRecyclerView = binding.allExtensionsRecyclerView
|
||||
extensionsRecyclerView.layoutManager = LinearLayoutManager(requireContext())
|
||||
extensionsRecyclerView.adapter = extensionsAdapter
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ import androidx.lifecycle.lifecycleScope
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import ani.dantotsu.R
|
||||
import ani.dantotsu.connections.crashlytics.CrashlyticsInterface
|
||||
import ani.dantotsu.databinding.FragmentMangaExtensionsBinding
|
||||
import ani.dantotsu.databinding.FragmentExtensionsBinding
|
||||
import ani.dantotsu.settings.paging.MangaExtensionAdapter
|
||||
import ani.dantotsu.settings.paging.MangaExtensionsViewModel
|
||||
import ani.dantotsu.settings.paging.MangaExtensionsViewModelFactory
|
||||
@@ -30,7 +30,7 @@ import uy.kohesive.injekt.api.get
|
||||
|
||||
class MangaExtensionsFragment : Fragment(),
|
||||
SearchQueryHandler, OnMangaInstallClickListener {
|
||||
private var _binding: FragmentMangaExtensionsBinding? = null
|
||||
private var _binding: FragmentExtensionsBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
|
||||
private val viewModel: MangaExtensionsViewModel by viewModels {
|
||||
@@ -49,12 +49,12 @@ class MangaExtensionsFragment : Fragment(),
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
_binding = FragmentMangaExtensionsBinding.inflate(inflater, container, false)
|
||||
_binding = FragmentExtensionsBinding.inflate(inflater, container, false)
|
||||
|
||||
binding.allMangaExtensionsRecyclerView.isNestedScrollingEnabled = false
|
||||
binding.allMangaExtensionsRecyclerView.adapter = adapter
|
||||
binding.allMangaExtensionsRecyclerView.layoutManager = LinearLayoutManager(context)
|
||||
(binding.allMangaExtensionsRecyclerView.layoutManager as LinearLayoutManager).isItemPrefetchEnabled =
|
||||
binding.allExtensionsRecyclerView.isNestedScrollingEnabled = false
|
||||
binding.allExtensionsRecyclerView.adapter = adapter
|
||||
binding.allExtensionsRecyclerView.layoutManager = LinearLayoutManager(context)
|
||||
(binding.allExtensionsRecyclerView.layoutManager as LinearLayoutManager).isItemPrefetchEnabled =
|
||||
true
|
||||
|
||||
lifecycleScope.launch {
|
||||
@@ -92,8 +92,8 @@ class MangaExtensionsFragment : Fragment(),
|
||||
Notifications.CHANNEL_DOWNLOADER_PROGRESS
|
||||
)
|
||||
.setSmallIcon(R.drawable.ic_round_sync_24)
|
||||
.setContentTitle("Installing extension")
|
||||
.setContentText("Step: $installStep")
|
||||
.setContentTitle(getString(R.string.installing_extension))
|
||||
.setContentText(getString(R.string.install_step, installStep))
|
||||
.setPriority(NotificationCompat.PRIORITY_LOW)
|
||||
notificationManager.notify(1, builder.build())
|
||||
},
|
||||
@@ -104,11 +104,11 @@ class MangaExtensionsFragment : Fragment(),
|
||||
Notifications.CHANNEL_DOWNLOADER_ERROR
|
||||
)
|
||||
.setSmallIcon(R.drawable.ic_round_info_24)
|
||||
.setContentTitle("Installation failed: ${error.message}")
|
||||
.setContentText("Error: ${error.message}")
|
||||
.setContentTitle(getString(R.string.installation_failed, error.message))
|
||||
.setContentText(getString(R.string.error_message, error.message))
|
||||
.setPriority(NotificationCompat.PRIORITY_HIGH)
|
||||
notificationManager.notify(1, builder.build())
|
||||
snackString("Installation failed: ${error.message}")
|
||||
snackString(getString(R.string.installation_failed, error.message))
|
||||
},
|
||||
{
|
||||
val builder = NotificationCompat.Builder(
|
||||
@@ -116,12 +116,12 @@ class MangaExtensionsFragment : Fragment(),
|
||||
Notifications.CHANNEL_DOWNLOADER_PROGRESS
|
||||
)
|
||||
.setSmallIcon(R.drawable.ic_download_24)
|
||||
.setContentTitle("Installation complete")
|
||||
.setContentText("The extension has been successfully installed.")
|
||||
.setContentTitle(getString(R.string.installation_complete))
|
||||
.setContentText(getString(R.string.extension_has_been_installed))
|
||||
.setPriority(NotificationCompat.PRIORITY_LOW)
|
||||
notificationManager.notify(1, builder.build())
|
||||
viewModel.invalidatePager()
|
||||
snackString("Extension installed")
|
||||
snackString(getString(R.string.extension_installed))
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,268 @@
|
||||
package ani.dantotsu.widgets.statistics
|
||||
|
||||
import android.app.Activity
|
||||
import android.appwidget.AppWidgetManager
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.res.ColorStateList
|
||||
import android.graphics.Color
|
||||
import android.os.Bundle
|
||||
import android.util.TypedValue
|
||||
import android.view.View
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import ani.dantotsu.R
|
||||
import ani.dantotsu.databinding.StatisticsWidgetConfigureBinding
|
||||
|
||||
import ani.dantotsu.themes.ThemeManager
|
||||
import ani.dantotsu.widgets.upcoming.UpcomingWidget
|
||||
import com.google.android.material.button.MaterialButton
|
||||
import eltos.simpledialogfragment.SimpleDialog
|
||||
import eltos.simpledialogfragment.color.SimpleColorDialog
|
||||
|
||||
/**
|
||||
* The configuration screen for the [ProfileStatsWidget] AppWidget.
|
||||
*/
|
||||
class ProfileStatsConfigure : AppCompatActivity(),
|
||||
SimpleDialog.OnDialogResultListener {
|
||||
private var appWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID
|
||||
private var isMonetEnabled = false
|
||||
private var onClickListener = View.OnClickListener {
|
||||
val context = this@ProfileStatsConfigure
|
||||
|
||||
// It is the responsibility of the configuration activity to update the app widget
|
||||
val appWidgetManager = AppWidgetManager.getInstance(context)
|
||||
//updateAppWidget(context, appWidgetManager, appWidgetId)
|
||||
|
||||
|
||||
ProfileStatsWidget.updateAppWidget(
|
||||
context,
|
||||
appWidgetManager,
|
||||
appWidgetId
|
||||
)
|
||||
|
||||
// Make sure we pass back the original appWidgetId
|
||||
val resultValue = Intent()
|
||||
resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId)
|
||||
setResult(RESULT_OK, resultValue)
|
||||
finish()
|
||||
}
|
||||
private lateinit var binding: StatisticsWidgetConfigureBinding
|
||||
|
||||
public override fun onCreate(icicle: Bundle?) {
|
||||
|
||||
ThemeManager(this).applyTheme()
|
||||
super.onCreate(icicle)
|
||||
|
||||
// Set the result to CANCELED. This will cause the widget host to cancel
|
||||
// out of the widget placement if the user presses the back button.
|
||||
setResult(RESULT_CANCELED)
|
||||
|
||||
binding = StatisticsWidgetConfigureBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
|
||||
val prefs = getSharedPreferences(ProfileStatsWidget.PREFS_NAME, Context.MODE_PRIVATE)
|
||||
val topBackground = prefs.getInt(ProfileStatsWidget.PREF_BACKGROUND_COLOR, Color.parseColor("#80000000"))
|
||||
(binding.topBackgroundButton as MaterialButton).iconTint = ColorStateList.valueOf(topBackground)
|
||||
binding.topBackgroundButton.setOnClickListener {
|
||||
val tag = ProfileStatsWidget.PREF_BACKGROUND_COLOR
|
||||
SimpleColorDialog().title(R.string.custom_theme)
|
||||
.colorPreset(topBackground)
|
||||
.colors(
|
||||
this@ProfileStatsConfigure,
|
||||
SimpleColorDialog.MATERIAL_COLOR_PALLET
|
||||
)
|
||||
.setupColorWheelAlpha(true)
|
||||
.allowCustom(true)
|
||||
.showOutline(0x46000000)
|
||||
.gridNumColumn(5)
|
||||
.choiceMode(SimpleColorDialog.SINGLE_CHOICE)
|
||||
.neg()
|
||||
.show(this@ProfileStatsConfigure, tag)
|
||||
}
|
||||
val bottomBackground = prefs.getInt(ProfileStatsWidget.PREF_BACKGROUND_FADE, Color.parseColor("#00000000"))
|
||||
(binding.bottomBackgroundButton as MaterialButton).iconTint = ColorStateList.valueOf(bottomBackground)
|
||||
binding.bottomBackgroundButton.setOnClickListener {
|
||||
val tag = ProfileStatsWidget.PREF_BACKGROUND_FADE
|
||||
SimpleColorDialog().title(R.string.custom_theme)
|
||||
.colorPreset(bottomBackground)
|
||||
.colors(
|
||||
this@ProfileStatsConfigure,
|
||||
SimpleColorDialog.MATERIAL_COLOR_PALLET
|
||||
)
|
||||
.setupColorWheelAlpha(true)
|
||||
.allowCustom(true)
|
||||
.showOutline(0x46000000)
|
||||
.gridNumColumn(5)
|
||||
.choiceMode(SimpleColorDialog.SINGLE_CHOICE)
|
||||
.neg()
|
||||
.show(this@ProfileStatsConfigure, tag)
|
||||
}
|
||||
val titleColor = prefs.getInt(ProfileStatsWidget.PREF_TITLE_TEXT_COLOR, Color.WHITE)
|
||||
(binding.titleColorButton as MaterialButton).iconTint = ColorStateList.valueOf(titleColor)
|
||||
binding.titleColorButton.setOnClickListener {
|
||||
val tag = ProfileStatsWidget.PREF_TITLE_TEXT_COLOR
|
||||
SimpleColorDialog().title(R.string.custom_theme)
|
||||
.colorPreset(titleColor)
|
||||
.colors(
|
||||
this@ProfileStatsConfigure,
|
||||
SimpleColorDialog.MATERIAL_COLOR_PALLET
|
||||
)
|
||||
.setupColorWheelAlpha(true)
|
||||
.allowCustom(true)
|
||||
.showOutline(0x46000000)
|
||||
.gridNumColumn(5)
|
||||
.choiceMode(SimpleColorDialog.SINGLE_CHOICE)
|
||||
.neg()
|
||||
.show(this@ProfileStatsConfigure, tag)
|
||||
}
|
||||
val statsColor = prefs.getInt(ProfileStatsWidget.PREF_STATS_TEXT_COLOR, Color.WHITE)
|
||||
(binding.statsColorButton as MaterialButton).iconTint = ColorStateList.valueOf(statsColor)
|
||||
binding.statsColorButton.setOnClickListener {
|
||||
val tag = ProfileStatsWidget.PREF_STATS_TEXT_COLOR
|
||||
SimpleColorDialog().title(R.string.custom_theme)
|
||||
.colorPreset(statsColor)
|
||||
.colors(
|
||||
this@ProfileStatsConfigure,
|
||||
SimpleColorDialog.MATERIAL_COLOR_PALLET
|
||||
)
|
||||
.setupColorWheelAlpha(true)
|
||||
.allowCustom(true)
|
||||
.showOutline(0x46000000)
|
||||
.gridNumColumn(5)
|
||||
.choiceMode(SimpleColorDialog.SINGLE_CHOICE)
|
||||
.neg()
|
||||
.show(this@ProfileStatsConfigure, tag)
|
||||
}
|
||||
binding.useAppTheme.setOnCheckedChangeListener { _, isChecked ->
|
||||
isMonetEnabled = isChecked
|
||||
if (isChecked) {
|
||||
binding.topBackgroundButton.visibility = View.GONE
|
||||
binding.bottomBackgroundButton.visibility = View.GONE
|
||||
binding.titleColorButton.visibility = View.GONE
|
||||
binding.statsColorButton.visibility = View.GONE
|
||||
themeColors()
|
||||
|
||||
} else {
|
||||
binding.topBackgroundButton.visibility = View.VISIBLE
|
||||
binding.bottomBackgroundButton.visibility = View.VISIBLE
|
||||
binding.titleColorButton.visibility = View.VISIBLE
|
||||
binding.statsColorButton.visibility = View.VISIBLE
|
||||
}
|
||||
}
|
||||
binding.addButton.setOnClickListener(onClickListener)
|
||||
|
||||
// Find the widget id from the intent.
|
||||
val intent = intent
|
||||
val extras = intent.extras
|
||||
if (extras != null) {
|
||||
appWidgetId = extras.getInt(
|
||||
AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID
|
||||
)
|
||||
}
|
||||
|
||||
// If this activity was started with an intent without an app widget ID, finish with an error.
|
||||
if (appWidgetId == AppWidgetManager.INVALID_APPWIDGET_ID) {
|
||||
finish()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
private fun themeColors() {
|
||||
val typedValueSurface = TypedValue()
|
||||
theme.resolveAttribute(
|
||||
com.google.android.material.R.attr.colorSurface,
|
||||
typedValueSurface,
|
||||
true
|
||||
)
|
||||
val backgroundColor = typedValueSurface.data
|
||||
|
||||
val typedValuePrimary = TypedValue()
|
||||
theme.resolveAttribute(
|
||||
com.google.android.material.R.attr.colorPrimary,
|
||||
typedValuePrimary,
|
||||
true
|
||||
)
|
||||
val textColor = typedValuePrimary.data
|
||||
|
||||
val typedValueOutline = TypedValue()
|
||||
theme.resolveAttribute(
|
||||
com.google.android.material.R.attr.colorOutline,
|
||||
typedValueOutline,
|
||||
true
|
||||
)
|
||||
val subTextColor = typedValueOutline.data
|
||||
|
||||
getSharedPreferences(ProfileStatsWidget.PREFS_NAME, Context.MODE_PRIVATE).edit().apply {
|
||||
putInt(ProfileStatsWidget.PREF_BACKGROUND_COLOR, backgroundColor)
|
||||
putInt(ProfileStatsWidget.PREF_BACKGROUND_FADE, backgroundColor)
|
||||
putInt(ProfileStatsWidget.PREF_TITLE_TEXT_COLOR, textColor)
|
||||
putInt(ProfileStatsWidget.PREF_STATS_TEXT_COLOR, subTextColor)
|
||||
apply()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResult(dialogTag: String, which: Int, extras: Bundle): Boolean {
|
||||
if (which == SimpleDialog.OnDialogResultListener.BUTTON_POSITIVE) {
|
||||
if (!isMonetEnabled) {
|
||||
when (dialogTag) {
|
||||
ProfileStatsWidget.PREF_BACKGROUND_COLOR -> {
|
||||
getSharedPreferences(
|
||||
ProfileStatsWidget.PREFS_NAME,
|
||||
Context.MODE_PRIVATE
|
||||
).edit()
|
||||
.putInt(
|
||||
ProfileStatsWidget.PREF_BACKGROUND_COLOR,
|
||||
extras.getInt(SimpleColorDialog.COLOR)
|
||||
)
|
||||
.apply()
|
||||
(binding.topBackgroundButton as MaterialButton).iconTint =
|
||||
ColorStateList.valueOf(extras.getInt(SimpleColorDialog.COLOR))
|
||||
}
|
||||
|
||||
ProfileStatsWidget.PREF_BACKGROUND_FADE -> {
|
||||
getSharedPreferences(
|
||||
ProfileStatsWidget.PREFS_NAME,
|
||||
Context.MODE_PRIVATE
|
||||
).edit()
|
||||
.putInt(
|
||||
ProfileStatsWidget.PREF_BACKGROUND_FADE,
|
||||
extras.getInt(SimpleColorDialog.COLOR)
|
||||
)
|
||||
.apply()
|
||||
(binding.bottomBackgroundButton as MaterialButton).iconTint =
|
||||
ColorStateList.valueOf(extras.getInt(SimpleColorDialog.COLOR))
|
||||
}
|
||||
|
||||
ProfileStatsWidget.PREF_TITLE_TEXT_COLOR -> {
|
||||
getSharedPreferences(
|
||||
ProfileStatsWidget.PREFS_NAME,
|
||||
Context.MODE_PRIVATE
|
||||
).edit()
|
||||
.putInt(
|
||||
ProfileStatsWidget.PREF_TITLE_TEXT_COLOR,
|
||||
extras.getInt(SimpleColorDialog.COLOR)
|
||||
)
|
||||
.apply()
|
||||
(binding.titleColorButton as MaterialButton).iconTint =
|
||||
ColorStateList.valueOf(extras.getInt(SimpleColorDialog.COLOR))
|
||||
}
|
||||
|
||||
ProfileStatsWidget.PREF_STATS_TEXT_COLOR -> {
|
||||
getSharedPreferences(
|
||||
ProfileStatsWidget.PREFS_NAME,
|
||||
Context.MODE_PRIVATE
|
||||
).edit()
|
||||
.putInt(
|
||||
ProfileStatsWidget.PREF_STATS_TEXT_COLOR,
|
||||
extras.getInt(SimpleColorDialog.COLOR)
|
||||
)
|
||||
.apply()
|
||||
(binding.statsColorButton as MaterialButton).iconTint =
|
||||
ColorStateList.valueOf(extras.getInt(SimpleColorDialog.COLOR))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,259 @@
|
||||
package ani.dantotsu.widgets.statistics
|
||||
|
||||
import android.app.PendingIntent
|
||||
import android.appwidget.AppWidgetManager
|
||||
import android.appwidget.AppWidgetProvider
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.BitmapFactory
|
||||
import android.graphics.Color
|
||||
import android.graphics.drawable.GradientDrawable
|
||||
import android.widget.RemoteViews
|
||||
import androidx.core.content.res.ResourcesCompat
|
||||
import ani.dantotsu.MainActivity
|
||||
import ani.dantotsu.R
|
||||
import ani.dantotsu.connections.anilist.Anilist
|
||||
import ani.dantotsu.profile.ProfileActivity
|
||||
import ani.dantotsu.settings.saving.PrefManager
|
||||
import ani.dantotsu.settings.saving.PrefName
|
||||
import ani.dantotsu.util.BitmapUtil
|
||||
import ani.dantotsu.widgets.WidgetSizeProvider
|
||||
import kotlinx.coroutines.DelicateCoroutinesApi
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.coroutines.withContext
|
||||
import tachiyomi.core.util.lang.launchIO
|
||||
import java.io.InputStream
|
||||
import java.net.HttpURLConnection
|
||||
import java.net.URL
|
||||
|
||||
/**
|
||||
* Implementation of App Widget functionality.
|
||||
*/
|
||||
class ProfileStatsWidget : AppWidgetProvider() {
|
||||
override fun onUpdate(
|
||||
context: Context,
|
||||
appWidgetManager: AppWidgetManager,
|
||||
appWidgetIds: IntArray
|
||||
) {
|
||||
appWidgetIds.forEach { appWidgetId ->
|
||||
updateAppWidget(context, appWidgetManager, appWidgetId)
|
||||
}
|
||||
super.onUpdate(context, appWidgetManager, appWidgetIds)
|
||||
}
|
||||
|
||||
override fun onDeleted(context: Context, appWidgetIds: IntArray) {
|
||||
super.onDeleted(context, appWidgetIds)
|
||||
}
|
||||
|
||||
override fun onEnabled(context: Context) {
|
||||
super.onEnabled(context)
|
||||
}
|
||||
|
||||
override fun onDisabled(context: Context) {
|
||||
super.onDisabled(context)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private fun downloadImageAsBitmap(imageUrl: String): Bitmap? {
|
||||
var bitmap: Bitmap? = null
|
||||
|
||||
runBlocking(Dispatchers.IO) {
|
||||
var inputStream: InputStream? = null
|
||||
var urlConnection: HttpURLConnection? = null
|
||||
try {
|
||||
val url = URL(imageUrl)
|
||||
urlConnection = url.openConnection() as HttpURLConnection
|
||||
urlConnection.requestMethod = "GET"
|
||||
urlConnection.connect()
|
||||
|
||||
if (urlConnection.responseCode == HttpURLConnection.HTTP_OK) {
|
||||
inputStream = urlConnection.inputStream
|
||||
bitmap = BitmapFactory.decodeStream(inputStream)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
} finally {
|
||||
inputStream?.close()
|
||||
urlConnection?.disconnect()
|
||||
}
|
||||
}
|
||||
return bitmap?.let { BitmapUtil.roundCorners(it) }
|
||||
}
|
||||
|
||||
@OptIn(DelicateCoroutinesApi::class)
|
||||
fun updateAppWidget(
|
||||
context: Context,
|
||||
appWidgetManager: AppWidgetManager,
|
||||
appWidgetId: Int
|
||||
) {
|
||||
|
||||
val prefs = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
|
||||
val backgroundColor =
|
||||
prefs.getInt(PREF_BACKGROUND_COLOR, Color.parseColor("#80000000"))
|
||||
val backgroundFade = prefs.getInt(PREF_BACKGROUND_FADE, Color.parseColor("#00000000"))
|
||||
val titleTextColor = prefs.getInt(PREF_TITLE_TEXT_COLOR, Color.WHITE)
|
||||
val statsTextColor = prefs.getInt(PREF_STATS_TEXT_COLOR, Color.WHITE)
|
||||
|
||||
val gradientDrawable = ResourcesCompat.getDrawable(
|
||||
context.resources,
|
||||
R.drawable.linear_gradient_black,
|
||||
null
|
||||
) as GradientDrawable
|
||||
gradientDrawable.colors = intArrayOf(backgroundColor, backgroundFade)
|
||||
val widgetSizeProvider = WidgetSizeProvider(context)
|
||||
var (width, height) = widgetSizeProvider.getWidgetsSize(appWidgetId)
|
||||
if (width > 0 && height > 0) {
|
||||
gradientDrawable.cornerRadius = 64f
|
||||
} else {
|
||||
width = 300
|
||||
height = 300
|
||||
}
|
||||
|
||||
launchIO {
|
||||
val userPref = PrefManager.getVal(PrefName.AnilistUserId, "")
|
||||
val userId = if (userPref.isNotEmpty()) userPref.toInt() else Anilist.userid
|
||||
?: if (Anilist.query.getUserData()) Anilist.userid else null
|
||||
userId?.let {
|
||||
val respond = Anilist.query.getUserProfile(it)
|
||||
respond?.data?.user?.let { user ->
|
||||
withContext(Dispatchers.Main) {
|
||||
val views = RemoteViews(context.packageName, R.layout.statistics_widget).apply {
|
||||
setImageViewBitmap(
|
||||
R.id.backgroundView,
|
||||
BitmapUtil.convertDrawableToBitmap(
|
||||
gradientDrawable,
|
||||
width,
|
||||
height
|
||||
)
|
||||
)
|
||||
setOnClickPendingIntent(
|
||||
R.id.userAvatar,
|
||||
PendingIntent.getActivity(
|
||||
context,
|
||||
1,
|
||||
Intent(context, ProfileStatsConfigure::class.java).apply {
|
||||
putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId)
|
||||
},
|
||||
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
|
||||
)
|
||||
)
|
||||
setTextColor(R.id.userLabel, titleTextColor)
|
||||
setTextColor(R.id.topLeftItem, statsTextColor)
|
||||
setTextColor(R.id.topLeftLabel, statsTextColor)
|
||||
setTextColor(R.id.topRightItem, statsTextColor)
|
||||
setTextColor(R.id.topRightLabel, statsTextColor)
|
||||
setTextColor(R.id.bottomLeftItem, statsTextColor)
|
||||
setTextColor(R.id.bottomLeftLabel, statsTextColor)
|
||||
setTextColor(R.id.bottomRightItem, statsTextColor)
|
||||
setTextColor(R.id.bottomRightLabel, statsTextColor)
|
||||
|
||||
setImageViewBitmap(
|
||||
R.id.userAvatar,
|
||||
user.avatar?.medium?.let { it1 -> downloadImageAsBitmap(it1) }
|
||||
)
|
||||
setTextViewText(
|
||||
R.id.userLabel,
|
||||
context.getString(R.string.user_stats, user.name)
|
||||
)
|
||||
|
||||
setTextViewText(
|
||||
R.id.topLeftItem,
|
||||
user.statistics.anime.count.toString()
|
||||
)
|
||||
setTextViewText(
|
||||
R.id.topLeftLabel,
|
||||
context.getString(R.string.anime_watched)
|
||||
)
|
||||
|
||||
setTextViewText(
|
||||
R.id.topRightItem,
|
||||
user.statistics.anime.episodesWatched.toString()
|
||||
)
|
||||
setTextViewText(
|
||||
R.id.topRightLabel,
|
||||
context.getString(R.string.episodes_watched_n)
|
||||
)
|
||||
|
||||
setTextViewText(
|
||||
R.id.bottomLeftItem,
|
||||
user.statistics.manga.count.toString()
|
||||
)
|
||||
setTextViewText(
|
||||
R.id.bottomLeftLabel,
|
||||
context.getString(R.string.manga_read)
|
||||
)
|
||||
|
||||
setTextViewText(
|
||||
R.id.bottomRightItem,
|
||||
user.statistics.manga.chaptersRead.toString()
|
||||
)
|
||||
setTextViewText(
|
||||
R.id.bottomRightLabel,
|
||||
context.getString(R.string.chapters_read_n)
|
||||
)
|
||||
|
||||
val intent = Intent(context, ProfileActivity::class.java)
|
||||
.putExtra("userId", it)
|
||||
val pendingIntent = PendingIntent.getActivity(
|
||||
context, 0, intent, PendingIntent.FLAG_IMMUTABLE
|
||||
)
|
||||
setOnClickPendingIntent(R.id.widgetContainer, pendingIntent)
|
||||
}
|
||||
// Instruct the widget manager to update the widget
|
||||
appWidgetManager.updateAppWidget(appWidgetId, views)
|
||||
}
|
||||
} ?: showLoginCascade(context, appWidgetManager, appWidgetId)
|
||||
} ?: showLoginCascade(context, appWidgetManager, appWidgetId)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun showLoginCascade(
|
||||
context: Context, appWidgetManager: AppWidgetManager, appWidgetId: Int
|
||||
) {
|
||||
|
||||
withContext(Dispatchers.Main) {
|
||||
val views = RemoteViews(context.packageName, R.layout.statistics_widget)
|
||||
|
||||
views.setTextViewText(R.id.topLeftItem, "")
|
||||
views.setTextViewText(
|
||||
R.id.topLeftLabel,
|
||||
context.getString(R.string.please)
|
||||
)
|
||||
|
||||
views.setTextViewText(R.id.topRightItem, "")
|
||||
views.setTextViewText(
|
||||
R.id.topRightLabel,
|
||||
context.getString(R.string.log_in)
|
||||
)
|
||||
|
||||
views.setTextViewText(
|
||||
R.id.bottomLeftItem,
|
||||
context.getString(R.string.or_join)
|
||||
)
|
||||
views.setTextViewText(R.id.bottomLeftLabel, "")
|
||||
|
||||
views.setTextViewText(
|
||||
R.id.bottomRightItem,
|
||||
context.getString(R.string.anilist)
|
||||
)
|
||||
views.setTextViewText(R.id.bottomRightLabel, "")
|
||||
|
||||
val intent = Intent(context, MainActivity::class.java)
|
||||
val pendingIntent = PendingIntent.getActivity(
|
||||
context, 0, intent, PendingIntent.FLAG_IMMUTABLE
|
||||
)
|
||||
views.setOnClickPendingIntent(R.id.widgetContainer, pendingIntent)
|
||||
|
||||
appWidgetManager.updateAppWidget(appWidgetId, views)
|
||||
}
|
||||
}
|
||||
|
||||
const val PREFS_NAME = "ani.dantotsu.widgets.ResumableWidget"
|
||||
const val PREF_BACKGROUND_COLOR = "background_color"
|
||||
const val PREF_BACKGROUND_FADE = "background_fade"
|
||||
const val PREF_TITLE_TEXT_COLOR = "title_text_color"
|
||||
const val PREF_STATS_TEXT_COLOR = "stats_text_color"
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,6 @@ import android.graphics.drawable.GradientDrawable
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.widget.RemoteViews
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.content.res.ResourcesCompat
|
||||
import ani.dantotsu.MainActivity
|
||||
import ani.dantotsu.R
|
||||
@@ -19,7 +18,7 @@ import ani.dantotsu.widgets.WidgetSizeProvider
|
||||
|
||||
/**
|
||||
* Implementation of App Widget functionality.
|
||||
* App Widget Configuration implemented in [UpcomingWidgetConfigureActivity]
|
||||
* App Widget Configuration implemented in [UpcomingWidgetConfigure]
|
||||
*/
|
||||
class UpcomingWidget : AppWidgetProvider() {
|
||||
override fun onUpdate(
|
||||
@@ -69,8 +68,8 @@ class UpcomingWidget : AppWidgetProvider() {
|
||||
): RemoteViews {
|
||||
val prefs = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
|
||||
val backgroundColor =
|
||||
prefs.getInt(PREF_BACKGROUND_COLOR, ContextCompat.getColor(context, R.color.theme))
|
||||
val backgroundFade = prefs.getInt(PREF_BACKGROUND_FADE, Color.GRAY)
|
||||
prefs.getInt(PREF_BACKGROUND_COLOR, Color.parseColor("#80000000"))
|
||||
val backgroundFade = prefs.getInt(PREF_BACKGROUND_FADE, Color.parseColor("#00000000"))
|
||||
val titleTextColor = prefs.getInt(PREF_TITLE_TEXT_COLOR, Color.WHITE)
|
||||
val countdownTextColor = prefs.getInt(PREF_COUNTDOWN_TEXT_COLOR, Color.WHITE)
|
||||
|
||||
@@ -80,14 +79,14 @@ class UpcomingWidget : AppWidgetProvider() {
|
||||
}
|
||||
val gradientDrawable = ResourcesCompat.getDrawable(
|
||||
context.resources,
|
||||
R.drawable.gradient_background,
|
||||
R.drawable.linear_gradient_black,
|
||||
null
|
||||
) as GradientDrawable
|
||||
gradientDrawable.colors = intArrayOf(backgroundColor, backgroundFade)
|
||||
val widgetSizeProvider = WidgetSizeProvider(context)
|
||||
var (width, height) = widgetSizeProvider.getWidgetsSize(appWidgetId)
|
||||
if (width > 0 && height > 0) {
|
||||
gradientDrawable.cornerRadius = 50f
|
||||
gradientDrawable.cornerRadius = 64f
|
||||
} else {
|
||||
width = 300
|
||||
height = 300
|
||||
@@ -118,7 +117,7 @@ class UpcomingWidget : AppWidgetProvider() {
|
||||
PendingIntent.getActivity(
|
||||
context,
|
||||
1,
|
||||
Intent(context, UpcomingWidgetConfigureActivity::class.java).apply {
|
||||
Intent(context, UpcomingWidgetConfigure::class.java).apply {
|
||||
putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId)
|
||||
},
|
||||
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
|
||||
|
||||
@@ -0,0 +1,240 @@
|
||||
package ani.dantotsu.widgets.upcoming
|
||||
|
||||
import android.appwidget.AppWidgetManager
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.res.ColorStateList
|
||||
import android.graphics.Color
|
||||
import android.os.Bundle
|
||||
import android.util.TypedValue
|
||||
import android.view.View
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import ani.dantotsu.R
|
||||
import ani.dantotsu.databinding.UpcomingWidgetConfigureBinding
|
||||
import ani.dantotsu.themes.ThemeManager
|
||||
import com.google.android.material.button.MaterialButton
|
||||
import eltos.simpledialogfragment.SimpleDialog
|
||||
import eltos.simpledialogfragment.color.SimpleColorDialog
|
||||
|
||||
/**
|
||||
* The configuration screen for the [UpcomingWidget] AppWidget.
|
||||
*/
|
||||
class UpcomingWidgetConfigure : AppCompatActivity(),
|
||||
SimpleDialog.OnDialogResultListener {
|
||||
private var appWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID
|
||||
private var isMonetEnabled = false
|
||||
private var onClickListener = View.OnClickListener {
|
||||
val context = this@UpcomingWidgetConfigure
|
||||
val appWidgetManager = AppWidgetManager.getInstance(context)
|
||||
|
||||
updateAppWidget(
|
||||
context,
|
||||
appWidgetManager,
|
||||
appWidgetId,
|
||||
)
|
||||
|
||||
val resultValue = Intent()
|
||||
resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId)
|
||||
setResult(RESULT_OK, resultValue)
|
||||
finish()
|
||||
}
|
||||
private lateinit var binding: UpcomingWidgetConfigureBinding
|
||||
|
||||
public override fun onCreate(icicle: Bundle?) {
|
||||
ThemeManager(this).applyTheme()
|
||||
super.onCreate(icicle)
|
||||
setResult(RESULT_CANCELED)
|
||||
|
||||
binding = UpcomingWidgetConfigureBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
val prefs = getSharedPreferences(UpcomingWidget.PREFS_NAME, Context.MODE_PRIVATE)
|
||||
val topBackground = prefs.getInt(UpcomingWidget.PREF_BACKGROUND_COLOR, Color.parseColor("#80000000"))
|
||||
(binding.topBackgroundButton as MaterialButton).iconTint = ColorStateList.valueOf(topBackground)
|
||||
binding.topBackgroundButton.setOnClickListener {
|
||||
val tag = UpcomingWidget.PREF_BACKGROUND_COLOR
|
||||
SimpleColorDialog().title(R.string.custom_theme)
|
||||
.colorPreset(topBackground)
|
||||
.colors(
|
||||
this@UpcomingWidgetConfigure,
|
||||
SimpleColorDialog.MATERIAL_COLOR_PALLET
|
||||
)
|
||||
.setupColorWheelAlpha(true)
|
||||
.allowCustom(true)
|
||||
.showOutline(0x46000000)
|
||||
.gridNumColumn(5)
|
||||
.choiceMode(SimpleColorDialog.SINGLE_CHOICE)
|
||||
.neg()
|
||||
.show(this@UpcomingWidgetConfigure, tag)
|
||||
}
|
||||
val bottomBackground = prefs.getInt(UpcomingWidget.PREF_BACKGROUND_FADE, Color.parseColor("#00000000"))
|
||||
(binding.bottomBackgroundButton as MaterialButton).iconTint = ColorStateList.valueOf(bottomBackground)
|
||||
binding.bottomBackgroundButton.setOnClickListener {
|
||||
val tag = UpcomingWidget.PREF_BACKGROUND_FADE
|
||||
SimpleColorDialog().title(R.string.custom_theme)
|
||||
.colorPreset(bottomBackground)
|
||||
.colors(
|
||||
this@UpcomingWidgetConfigure,
|
||||
SimpleColorDialog.MATERIAL_COLOR_PALLET
|
||||
)
|
||||
.setupColorWheelAlpha(true)
|
||||
.allowCustom(true)
|
||||
.showOutline(0x46000000)
|
||||
.gridNumColumn(5)
|
||||
.choiceMode(SimpleColorDialog.SINGLE_CHOICE)
|
||||
.neg()
|
||||
.show(this@UpcomingWidgetConfigure, tag)
|
||||
}
|
||||
val titleTextColor = prefs.getInt(UpcomingWidget.PREF_TITLE_TEXT_COLOR, Color.WHITE)
|
||||
(binding.titleColorButton as MaterialButton).iconTint = ColorStateList.valueOf(titleTextColor)
|
||||
binding.titleColorButton.setOnClickListener {
|
||||
val tag = UpcomingWidget.PREF_TITLE_TEXT_COLOR
|
||||
SimpleColorDialog().title(R.string.custom_theme)
|
||||
.colorPreset(titleTextColor)
|
||||
.colors(
|
||||
this@UpcomingWidgetConfigure,
|
||||
SimpleColorDialog.MATERIAL_COLOR_PALLET
|
||||
)
|
||||
.allowCustom(true)
|
||||
.showOutline(0x46000000)
|
||||
.gridNumColumn(5)
|
||||
.choiceMode(SimpleColorDialog.SINGLE_CHOICE)
|
||||
.neg()
|
||||
.show(this@UpcomingWidgetConfigure, tag)
|
||||
}
|
||||
val countdownTextColor = prefs.getInt(UpcomingWidget.PREF_COUNTDOWN_TEXT_COLOR, Color.WHITE)
|
||||
(binding.countdownColorButton as MaterialButton).iconTint = ColorStateList.valueOf(countdownTextColor)
|
||||
binding.countdownColorButton.setOnClickListener {
|
||||
val tag = UpcomingWidget.PREF_COUNTDOWN_TEXT_COLOR
|
||||
SimpleColorDialog().title(R.string.custom_theme)
|
||||
.colorPreset(countdownTextColor)
|
||||
.colors(
|
||||
this@UpcomingWidgetConfigure,
|
||||
SimpleColorDialog.MATERIAL_COLOR_PALLET
|
||||
)
|
||||
.allowCustom(true)
|
||||
.showOutline(0x46000000)
|
||||
.gridNumColumn(5)
|
||||
.choiceMode(SimpleColorDialog.SINGLE_CHOICE)
|
||||
.neg()
|
||||
.show(this@UpcomingWidgetConfigure, tag)
|
||||
}
|
||||
binding.useAppTheme.setOnCheckedChangeListener { _, isChecked ->
|
||||
isMonetEnabled = isChecked
|
||||
if (isChecked) {
|
||||
binding.topBackgroundButton.visibility = View.GONE
|
||||
binding.bottomBackgroundButton.visibility = View.GONE
|
||||
binding.titleColorButton.visibility = View.GONE
|
||||
binding.countdownColorButton.visibility = View.GONE
|
||||
themeColors()
|
||||
|
||||
} else {
|
||||
binding.topBackgroundButton.visibility = View.VISIBLE
|
||||
binding.bottomBackgroundButton.visibility = View.VISIBLE
|
||||
binding.titleColorButton.visibility = View.VISIBLE
|
||||
binding.countdownColorButton.visibility = View.VISIBLE
|
||||
}
|
||||
}
|
||||
binding.addButton.setOnClickListener(onClickListener)
|
||||
|
||||
val intent = intent
|
||||
val extras = intent.extras
|
||||
if (extras != null) {
|
||||
appWidgetId = extras.getInt(
|
||||
AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID
|
||||
)
|
||||
}
|
||||
|
||||
if (appWidgetId == AppWidgetManager.INVALID_APPWIDGET_ID) {
|
||||
finish()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
private fun themeColors() {
|
||||
val typedValueSurface = TypedValue()
|
||||
theme.resolveAttribute(com.google.android.material.R.attr.colorSurface, typedValueSurface, true)
|
||||
val backgroundColor = typedValueSurface.data
|
||||
|
||||
val typedValuePrimary = TypedValue()
|
||||
theme.resolveAttribute(com.google.android.material.R.attr.colorPrimary, typedValuePrimary, true)
|
||||
val textColor = typedValuePrimary.data
|
||||
|
||||
val typedValueOutline = TypedValue()
|
||||
theme.resolveAttribute(com.google.android.material.R.attr.colorOutline, typedValueOutline, true)
|
||||
val subTextColor = typedValueOutline.data
|
||||
|
||||
getSharedPreferences(UpcomingWidget.PREFS_NAME, Context.MODE_PRIVATE).edit().apply {
|
||||
putInt(UpcomingWidget.PREF_BACKGROUND_COLOR, backgroundColor)
|
||||
putInt(UpcomingWidget.PREF_BACKGROUND_FADE, backgroundColor)
|
||||
putInt(UpcomingWidget.PREF_TITLE_TEXT_COLOR, textColor)
|
||||
putInt(UpcomingWidget.PREF_COUNTDOWN_TEXT_COLOR, subTextColor)
|
||||
apply()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResult(dialogTag: String, which: Int, extras: Bundle): Boolean {
|
||||
if (which == SimpleDialog.OnDialogResultListener.BUTTON_POSITIVE) {
|
||||
if (!isMonetEnabled) {
|
||||
when (dialogTag) {
|
||||
UpcomingWidget.PREF_BACKGROUND_COLOR -> {
|
||||
getSharedPreferences(
|
||||
UpcomingWidget.PREFS_NAME,
|
||||
Context.MODE_PRIVATE
|
||||
).edit()
|
||||
.putInt(
|
||||
UpcomingWidget.PREF_BACKGROUND_COLOR,
|
||||
extras.getInt(SimpleColorDialog.COLOR)
|
||||
)
|
||||
.apply()
|
||||
(binding.topBackgroundButton as MaterialButton).iconTint =
|
||||
ColorStateList.valueOf(extras.getInt(SimpleColorDialog.COLOR))
|
||||
}
|
||||
|
||||
UpcomingWidget.PREF_BACKGROUND_FADE -> {
|
||||
getSharedPreferences(
|
||||
UpcomingWidget.PREFS_NAME,
|
||||
Context.MODE_PRIVATE
|
||||
).edit()
|
||||
.putInt(
|
||||
UpcomingWidget.PREF_BACKGROUND_FADE,
|
||||
extras.getInt(SimpleColorDialog.COLOR)
|
||||
)
|
||||
.apply()
|
||||
(binding.bottomBackgroundButton as MaterialButton).iconTint =
|
||||
ColorStateList.valueOf(extras.getInt(SimpleColorDialog.COLOR))
|
||||
}
|
||||
|
||||
UpcomingWidget.PREF_TITLE_TEXT_COLOR -> {
|
||||
getSharedPreferences(
|
||||
UpcomingWidget.PREFS_NAME,
|
||||
Context.MODE_PRIVATE
|
||||
).edit()
|
||||
.putInt(
|
||||
UpcomingWidget.PREF_TITLE_TEXT_COLOR,
|
||||
extras.getInt(SimpleColorDialog.COLOR)
|
||||
)
|
||||
.apply()
|
||||
(binding.titleColorButton as MaterialButton).iconTint =
|
||||
ColorStateList.valueOf(extras.getInt(SimpleColorDialog.COLOR))
|
||||
}
|
||||
|
||||
UpcomingWidget.PREF_COUNTDOWN_TEXT_COLOR -> {
|
||||
getSharedPreferences(
|
||||
UpcomingWidget.PREFS_NAME,
|
||||
Context.MODE_PRIVATE
|
||||
).edit()
|
||||
.putInt(
|
||||
UpcomingWidget.PREF_COUNTDOWN_TEXT_COLOR,
|
||||
extras.getInt(SimpleColorDialog.COLOR)
|
||||
)
|
||||
.apply()
|
||||
(binding.countdownColorButton as MaterialButton).iconTint =
|
||||
ColorStateList.valueOf(extras.getInt(SimpleColorDialog.COLOR))
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -1,195 +0,0 @@
|
||||
package ani.dantotsu.widgets.upcoming
|
||||
|
||||
import android.appwidget.AppWidgetManager
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.graphics.Color
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.content.ContextCompat
|
||||
import ani.dantotsu.R
|
||||
import ani.dantotsu.databinding.UpcomingWidgetConfigureBinding
|
||||
import ani.dantotsu.themes.ThemeManager
|
||||
import eltos.simpledialogfragment.SimpleDialog
|
||||
import eltos.simpledialogfragment.color.SimpleColorDialog
|
||||
|
||||
/**
|
||||
* The configuration screen for the [UpcomingWidget] AppWidget.
|
||||
*/
|
||||
class UpcomingWidgetConfigureActivity : AppCompatActivity(),
|
||||
SimpleDialog.OnDialogResultListener {
|
||||
private var appWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID
|
||||
|
||||
private var onClickListener = View.OnClickListener {
|
||||
val context = this@UpcomingWidgetConfigureActivity
|
||||
val appWidgetManager = AppWidgetManager.getInstance(context)
|
||||
|
||||
updateAppWidget(
|
||||
context,
|
||||
appWidgetManager,
|
||||
appWidgetId,
|
||||
)
|
||||
|
||||
val resultValue = Intent()
|
||||
resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId)
|
||||
setResult(RESULT_OK, resultValue)
|
||||
finish()
|
||||
}
|
||||
private lateinit var binding: UpcomingWidgetConfigureBinding
|
||||
|
||||
public override fun onCreate(icicle: Bundle?) {
|
||||
ThemeManager(this).applyTheme()
|
||||
super.onCreate(icicle)
|
||||
setResult(RESULT_CANCELED)
|
||||
|
||||
binding = UpcomingWidgetConfigureBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
val prefs = getSharedPreferences(UpcomingWidget.PREFS_NAME, Context.MODE_PRIVATE)
|
||||
|
||||
binding.topBackgroundButton.setOnClickListener {
|
||||
val tag = UpcomingWidget.PREF_BACKGROUND_COLOR
|
||||
SimpleColorDialog().title(R.string.custom_theme)
|
||||
.colorPreset(
|
||||
prefs.getInt(
|
||||
UpcomingWidget.PREF_BACKGROUND_COLOR,
|
||||
ContextCompat.getColor(this, R.color.theme)
|
||||
)
|
||||
)
|
||||
.colors(
|
||||
this@UpcomingWidgetConfigureActivity,
|
||||
SimpleColorDialog.MATERIAL_COLOR_PALLET
|
||||
)
|
||||
.setupColorWheelAlpha(true)
|
||||
.allowCustom(true)
|
||||
.showOutline(0x46000000)
|
||||
.gridNumColumn(5)
|
||||
.choiceMode(SimpleColorDialog.SINGLE_CHOICE)
|
||||
.neg()
|
||||
.show(this@UpcomingWidgetConfigureActivity, tag)
|
||||
}
|
||||
binding.bottomBackgroundButton.setOnClickListener {
|
||||
val tag = UpcomingWidget.PREF_BACKGROUND_FADE
|
||||
SimpleColorDialog().title(R.string.custom_theme)
|
||||
.colorPreset(prefs.getInt(UpcomingWidget.PREF_BACKGROUND_FADE, Color.GRAY))
|
||||
.colors(
|
||||
this@UpcomingWidgetConfigureActivity,
|
||||
SimpleColorDialog.MATERIAL_COLOR_PALLET
|
||||
)
|
||||
.setupColorWheelAlpha(true)
|
||||
.allowCustom(true)
|
||||
.showOutline(0x46000000)
|
||||
.gridNumColumn(5)
|
||||
.choiceMode(SimpleColorDialog.SINGLE_CHOICE)
|
||||
.neg()
|
||||
.show(this@UpcomingWidgetConfigureActivity, tag)
|
||||
}
|
||||
binding.titleColorButton.setOnClickListener {
|
||||
val tag = UpcomingWidget.PREF_TITLE_TEXT_COLOR
|
||||
SimpleColorDialog().title(R.string.custom_theme)
|
||||
.colorPreset(prefs.getInt(UpcomingWidget.PREF_TITLE_TEXT_COLOR, Color.WHITE))
|
||||
.colors(
|
||||
this@UpcomingWidgetConfigureActivity,
|
||||
SimpleColorDialog.MATERIAL_COLOR_PALLET
|
||||
)
|
||||
.allowCustom(true)
|
||||
.showOutline(0x46000000)
|
||||
.gridNumColumn(5)
|
||||
.choiceMode(SimpleColorDialog.SINGLE_CHOICE)
|
||||
.neg()
|
||||
.show(this@UpcomingWidgetConfigureActivity, tag)
|
||||
}
|
||||
binding.countdownColorButton.setOnClickListener {
|
||||
val tag = UpcomingWidget.PREF_COUNTDOWN_TEXT_COLOR
|
||||
SimpleColorDialog().title(R.string.custom_theme)
|
||||
.colorPreset(
|
||||
prefs.getInt(
|
||||
UpcomingWidget.PREF_COUNTDOWN_TEXT_COLOR,
|
||||
Color.WHITE
|
||||
)
|
||||
)
|
||||
.colors(
|
||||
this@UpcomingWidgetConfigureActivity,
|
||||
SimpleColorDialog.MATERIAL_COLOR_PALLET
|
||||
)
|
||||
.allowCustom(true)
|
||||
.showOutline(0x46000000)
|
||||
.gridNumColumn(5)
|
||||
.choiceMode(SimpleColorDialog.SINGLE_CHOICE)
|
||||
.neg()
|
||||
.show(this@UpcomingWidgetConfigureActivity, tag)
|
||||
}
|
||||
|
||||
binding.addButton.setOnClickListener(onClickListener)
|
||||
|
||||
val intent = intent
|
||||
val extras = intent.extras
|
||||
if (extras != null) {
|
||||
appWidgetId = extras.getInt(
|
||||
AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID
|
||||
)
|
||||
}
|
||||
|
||||
if (appWidgetId == AppWidgetManager.INVALID_APPWIDGET_ID) {
|
||||
finish()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResult(dialogTag: String, which: Int, extras: Bundle): Boolean {
|
||||
if (which == SimpleDialog.OnDialogResultListener.BUTTON_POSITIVE) {
|
||||
when (dialogTag) {
|
||||
UpcomingWidget.PREF_BACKGROUND_COLOR -> {
|
||||
getSharedPreferences(
|
||||
UpcomingWidget.PREFS_NAME,
|
||||
Context.MODE_PRIVATE
|
||||
).edit()
|
||||
.putInt(
|
||||
UpcomingWidget.PREF_BACKGROUND_COLOR,
|
||||
extras.getInt(SimpleColorDialog.COLOR)
|
||||
)
|
||||
.apply()
|
||||
}
|
||||
|
||||
UpcomingWidget.PREF_BACKGROUND_FADE -> {
|
||||
getSharedPreferences(
|
||||
UpcomingWidget.PREFS_NAME,
|
||||
Context.MODE_PRIVATE
|
||||
).edit()
|
||||
.putInt(
|
||||
UpcomingWidget.PREF_BACKGROUND_FADE,
|
||||
extras.getInt(SimpleColorDialog.COLOR)
|
||||
)
|
||||
.apply()
|
||||
}
|
||||
|
||||
UpcomingWidget.PREF_TITLE_TEXT_COLOR -> {
|
||||
getSharedPreferences(
|
||||
UpcomingWidget.PREFS_NAME,
|
||||
Context.MODE_PRIVATE
|
||||
).edit()
|
||||
.putInt(
|
||||
UpcomingWidget.PREF_TITLE_TEXT_COLOR,
|
||||
extras.getInt(SimpleColorDialog.COLOR)
|
||||
)
|
||||
.apply()
|
||||
}
|
||||
|
||||
UpcomingWidget.PREF_COUNTDOWN_TEXT_COLOR -> {
|
||||
getSharedPreferences(
|
||||
UpcomingWidget.PREFS_NAME,
|
||||
Context.MODE_PRIVATE
|
||||
).edit()
|
||||
.putInt(
|
||||
UpcomingWidget.PREF_COUNTDOWN_TEXT_COLOR,
|
||||
extras.getInt(SimpleColorDialog.COLOR)
|
||||
)
|
||||
.apply()
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 69 KiB |
BIN
app/src/main/res/drawable-nodpi/statistics_widget_preview.png
Normal file
BIN
app/src/main/res/drawable-nodpi/statistics_widget_preview.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 42 KiB |
BIN
app/src/main/res/drawable-nodpi/upcoming_widget_preview.png
Normal file
BIN
app/src/main/res/drawable-nodpi/upcoming_widget_preview.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 68 KiB |
13
app/src/main/res/drawable/ic_camera_roll_24.xml
Normal file
13
app/src/main/res/drawable/ic_camera_roll_24.xml
Normal file
@@ -0,0 +1,13 @@
|
||||
<vector
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:height="24dp"
|
||||
android:tint="#000000"
|
||||
android:viewportHeight="24"
|
||||
android:viewportWidth="24"
|
||||
android:width="24dp">
|
||||
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M14,5c0,-1.1 -0.9,-2 -2,-2h-1L11,2c0,-0.55 -0.45,-1 -1,-1L6,1c-0.55,0 -1,0.45 -1,1v1L4,3c-1.1,0 -2,0.9 -2,2v15c0,1.1 0.9,2 2,2h8c1.1,0 2,-0.9 2,-2h8L22,5h-8zM12,18h-2v-2h2v2zM12,9h-2L10,7h2v2zM16,18h-2v-2h2v2zM16,9h-2L14,7h2v2zM20,18h-2v-2h2v2zM20,9h-2L18,7h2v2z"/>
|
||||
|
||||
</vector>
|
||||
27
app/src/main/res/drawable/widget_stats_rounded.xml
Normal file
27
app/src/main/res/drawable/widget_stats_rounded.xml
Normal file
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||
<item>
|
||||
<shape android:shape="rectangle">
|
||||
<corners
|
||||
android:topLeftRadius="28dp"
|
||||
android:topRightRadius="28dp"
|
||||
android:bottomLeftRadius="0dp"
|
||||
android:bottomRightRadius="0dp"/>
|
||||
</shape>
|
||||
</item>
|
||||
<item
|
||||
android:left="-3dp"
|
||||
android:right="-3dp"
|
||||
android:bottom="-50dp">
|
||||
<shape>
|
||||
<stroke android:width="2dp" android:color="@color/bg_white" />
|
||||
<corners
|
||||
android:topLeftRadius="28dp"
|
||||
android:topRightRadius="28dp"
|
||||
android:bottomLeftRadius="0dp"
|
||||
android:bottomRightRadius="0dp"/>
|
||||
</shape>
|
||||
</item>
|
||||
</layer-list>
|
||||
|
||||
|
||||
@@ -177,7 +177,8 @@
|
||||
android:layout_height="64dp"
|
||||
android:fontFamily="@font/poppins_bold"
|
||||
android:gravity="center_vertical"
|
||||
android:paddingHorizontal="32dp"
|
||||
android:paddingStart="48dp"
|
||||
android:paddingEnd="32dp"
|
||||
android:text="@string/sub_text_example"
|
||||
android:textColor="?attr/colorSecondary"
|
||||
app:drawableEndCompat="@drawable/ic_round_arrow_drop_down_24"
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="16dp">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/allAnimeExtensionsRecyclerView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1" />
|
||||
|
||||
</LinearLayout>
|
||||
@@ -7,7 +7,7 @@
|
||||
android:paddingEnd="16dp">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/allMangaExtensionsRecyclerView"
|
||||
android:id="@+id/allExtensionsRecyclerView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1" />
|
||||
188
app/src/main/res/layout/statistics_widget.xml
Normal file
188
app/src/main/res/layout/statistics_widget.xml
Normal file
@@ -0,0 +1,188 @@
|
||||
<RelativeLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:theme="@style/Theme.Dantotsu.AppWidgetContainer"
|
||||
android:orientation="vertical">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/backgroundView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:scaleType="fitXY"
|
||||
android:src="@drawable/widget_stats_rounded"
|
||||
tools:ignore="ContentDescription"/>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/headerLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:gravity="center_horizontal"
|
||||
android:layout_margin="4dp"
|
||||
android:orientation="horizontal"
|
||||
android:baselineAligned="false">
|
||||
<ImageView
|
||||
android:id="@+id/userAvatar"
|
||||
android:layout_width="32dp"
|
||||
android:layout_height="32dp"
|
||||
android:scaleType="fitCenter"
|
||||
android:src="@drawable/ic_dantotsu_round"
|
||||
tools:ignore="ContentDescription"/>
|
||||
<TextView
|
||||
android:id="@+id/userLabel"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginStart="8dp"
|
||||
android:fontFamily="@font/poppins_bold"
|
||||
android:textSize="18sp"
|
||||
android:text="@string/loading"/>
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center"
|
||||
android:gravity="center"
|
||||
android:padding="4dp"
|
||||
android:orientation="vertical"
|
||||
android:background="@drawable/widget_stats_rounded"
|
||||
android:layout_below="@id/headerLayout">
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:layout_gravity="center"
|
||||
android:orientation="horizontal"
|
||||
android:baselineAligned="false">
|
||||
<LinearLayout
|
||||
android:id="@+id/topLeft"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical"
|
||||
tools:ignore="NestedWeights">
|
||||
<TextView
|
||||
android:id="@+id/topLeftItem"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:fontFamily="@font/poppins_bold"
|
||||
android:text="@string/loading"/>
|
||||
<TextView
|
||||
android:id="@+id/topLeftLabel"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:gravity="center"
|
||||
android:fontFamily="@font/poppins_semi_bold"
|
||||
android:text="@string/anime_watched" />
|
||||
</LinearLayout>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/dividerTop"
|
||||
android:layout_width="4dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginTop="4dp"
|
||||
android:background="?android:attr/listDivider" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/topRight"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical">
|
||||
<TextView
|
||||
android:id="@+id/topRightItem"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:fontFamily="@font/poppins_bold"
|
||||
android:text="@string/loading"/>
|
||||
<TextView
|
||||
android:id="@+id/topRightLabel"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:gravity="center"
|
||||
android:fontFamily="@font/poppins_semi_bold"
|
||||
android:text="@string/episodes_watched_n"/>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/dividerMiddle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="2dp"
|
||||
android:layout_margin="4dp"
|
||||
android:background="?android:attr/listDivider" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/bottomLeft"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:layout_gravity="center"
|
||||
android:orientation="horizontal"
|
||||
android:baselineAligned="false">
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical"
|
||||
tools:ignore="NestedWeights">
|
||||
<TextView
|
||||
android:id="@+id/bottomLeftItem"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:fontFamily="@font/poppins_bold"
|
||||
android:text="@string/loading"/>
|
||||
<TextView
|
||||
android:id="@+id/bottomLeftLabel"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/poppins_semi_bold"
|
||||
android:text="@string/manga_read"
|
||||
android:layout_gravity="center"
|
||||
android:gravity="center"/>
|
||||
</LinearLayout>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/dividerBottom"
|
||||
android:layout_width="4dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:background="?android:attr/listDivider" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/bottomRight"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical">
|
||||
<TextView
|
||||
android:id="@+id/bottomRightItem"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:fontFamily="@font/poppins_bold"
|
||||
android:text="@string/loading"/>
|
||||
<TextView
|
||||
android:id="@+id/bottomRightLabel"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:gravity="center"
|
||||
android:fontFamily="@font/poppins_semi_bold"
|
||||
android:text="@string/chapters_read_n"/>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</RelativeLayout>
|
||||
139
app/src/main/res/layout/statistics_widget_configure.xml
Normal file
139
app/src/main/res/layout/statistics_widget_configure.xml
Normal file
@@ -0,0 +1,139 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:gravity="center"
|
||||
android:fontFamily="@font/poppins_bold"
|
||||
android:text="@string/profile_stats_widget" />
|
||||
|
||||
<com.google.android.material.materialswitch.MaterialSwitch
|
||||
android:id="@+id/useAppTheme"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:checked="false"
|
||||
android:drawableStart="@drawable/ic_palette"
|
||||
android:drawablePadding="16dp"
|
||||
android:elegantTextHeight="true"
|
||||
android:fontFamily="@font/poppins_bold"
|
||||
android:minHeight="64dp"
|
||||
android:text="@string/use_app_theme"
|
||||
android:textAlignment="viewStart"
|
||||
android:textColor="?attr/colorOnBackground"
|
||||
app:cornerRadius="0dp"
|
||||
app:drawableTint="?attr/colorPrimary"
|
||||
app:showText="false"
|
||||
app:thumbTint="@color/button_switch_track" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/topBackgroundButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="64dp"
|
||||
android:layout_marginStart="-31dp"
|
||||
android:layout_marginEnd="-31dp"
|
||||
android:background="@drawable/ui_bg"
|
||||
android:backgroundTint="?attr/colorSecondary"
|
||||
android:backgroundTintMode="src_atop"
|
||||
android:fontFamily="@font/poppins_bold"
|
||||
android:insetTop="0dp"
|
||||
android:insetBottom="0dp"
|
||||
android:paddingStart="31dp"
|
||||
android:paddingEnd="31dp"
|
||||
android:text="@string/top_background_color"
|
||||
android:textAlignment="viewStart"
|
||||
android:textAllCaps="false"
|
||||
android:textColor="?attr/colorOnBackground"
|
||||
app:cornerRadius="0dp"
|
||||
app:icon="@drawable/shape_corner_16dp"
|
||||
app:iconPadding="16dp"
|
||||
app:iconSize="24dp"
|
||||
app:iconTint="?attr/colorPrimary" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/bottomBackgroundButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="64dp"
|
||||
android:layout_marginStart="-31dp"
|
||||
android:layout_marginEnd="-31dp"
|
||||
android:background="@drawable/ui_bg"
|
||||
android:backgroundTint="?attr/colorSecondary"
|
||||
android:backgroundTintMode="src_atop"
|
||||
android:fontFamily="@font/poppins_bold"
|
||||
android:insetTop="0dp"
|
||||
android:insetBottom="0dp"
|
||||
android:paddingStart="31dp"
|
||||
android:paddingEnd="31dp"
|
||||
android:text="@string/bottom_background_color"
|
||||
android:textAlignment="viewStart"
|
||||
android:textAllCaps="false"
|
||||
android:textColor="?attr/colorOnBackground"
|
||||
app:cornerRadius="0dp"
|
||||
app:icon="@drawable/shape_corner_16dp"
|
||||
app:iconPadding="16dp"
|
||||
app:iconSize="24dp"
|
||||
app:iconTint="?attr/colorPrimary" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/titleColorButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="64dp"
|
||||
android:layout_marginStart="-31dp"
|
||||
android:layout_marginEnd="-31dp"
|
||||
android:background="@drawable/ui_bg"
|
||||
android:backgroundTint="?attr/colorSecondary"
|
||||
android:backgroundTintMode="src_atop"
|
||||
android:fontFamily="@font/poppins_bold"
|
||||
android:insetTop="0dp"
|
||||
android:insetBottom="0dp"
|
||||
android:paddingStart="31dp"
|
||||
android:paddingEnd="31dp"
|
||||
android:text="@string/title_color"
|
||||
android:textAlignment="viewStart"
|
||||
android:textAllCaps="false"
|
||||
android:textColor="?attr/colorOnBackground"
|
||||
app:cornerRadius="0dp"
|
||||
app:icon="@drawable/shape_corner_16dp"
|
||||
app:iconPadding="16dp"
|
||||
app:iconSize="24dp"
|
||||
app:iconTint="?attr/colorPrimary" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/statsColorButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="64dp"
|
||||
android:layout_marginStart="-31dp"
|
||||
android:layout_marginEnd="-31dp"
|
||||
android:background="@drawable/ui_bg"
|
||||
android:backgroundTint="?attr/colorSecondary"
|
||||
android:backgroundTintMode="src_atop"
|
||||
android:fontFamily="@font/poppins_bold"
|
||||
android:insetTop="0dp"
|
||||
android:insetBottom="0dp"
|
||||
android:paddingStart="31dp"
|
||||
android:paddingEnd="31dp"
|
||||
android:text="@string/stat_text_color"
|
||||
android:textAlignment="viewStart"
|
||||
android:textAllCaps="false"
|
||||
android:textColor="?attr/colorOnBackground"
|
||||
app:cornerRadius="0dp"
|
||||
app:icon="@drawable/shape_corner_16dp"
|
||||
app:iconPadding="16dp"
|
||||
app:iconSize="24dp"
|
||||
app:iconTint="?attr/colorPrimary" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/add_button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:text="@string/add_widget" />
|
||||
|
||||
</LinearLayout>
|
||||
@@ -9,14 +9,14 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:scaleType="fitXY"
|
||||
android:src="@drawable/gradient_background"
|
||||
android:src="@drawable/linear_gradient_black"
|
||||
tools:ignore="ContentDescription"/>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/widgetContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:padding="8dp">
|
||||
android:padding="16dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/logoView"
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
@@ -10,8 +10,28 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:fontFamily="@font/poppins_bold"
|
||||
android:text="@string/configure" />
|
||||
|
||||
<com.google.android.material.materialswitch.MaterialSwitch
|
||||
android:id="@+id/useAppTheme"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:checked="false"
|
||||
android:drawableStart="@drawable/ic_palette"
|
||||
android:drawablePadding="16dp"
|
||||
android:elegantTextHeight="true"
|
||||
android:fontFamily="@font/poppins_bold"
|
||||
android:minHeight="64dp"
|
||||
android:text="@string/use_app_theme"
|
||||
android:textAlignment="viewStart"
|
||||
android:textColor="?attr/colorOnBackground"
|
||||
app:cornerRadius="0dp"
|
||||
app:drawableTint="?attr/colorPrimary"
|
||||
app:showText="false"
|
||||
app:thumbTint="@color/button_switch_track" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/topBackgroundButton"
|
||||
android:layout_width="match_parent"
|
||||
@@ -31,7 +51,7 @@
|
||||
android:textAllCaps="false"
|
||||
android:textColor="?attr/colorOnBackground"
|
||||
app:cornerRadius="0dp"
|
||||
app:icon="@drawable/ic_round_color_picker_24"
|
||||
app:icon="@drawable/shape_corner_16dp"
|
||||
app:iconPadding="16dp"
|
||||
app:iconSize="24dp"
|
||||
app:iconTint="?attr/colorPrimary" />
|
||||
@@ -55,7 +75,7 @@
|
||||
android:textAllCaps="false"
|
||||
android:textColor="?attr/colorOnBackground"
|
||||
app:cornerRadius="0dp"
|
||||
app:icon="@drawable/ic_round_color_picker_24"
|
||||
app:icon="@drawable/shape_corner_16dp"
|
||||
app:iconPadding="16dp"
|
||||
app:iconSize="24dp"
|
||||
app:iconTint="?attr/colorPrimary" />
|
||||
@@ -79,7 +99,7 @@
|
||||
android:textAllCaps="false"
|
||||
android:textColor="?attr/colorOnBackground"
|
||||
app:cornerRadius="0dp"
|
||||
app:icon="@drawable/ic_round_color_picker_24"
|
||||
app:icon="@drawable/shape_corner_16dp"
|
||||
app:iconPadding="16dp"
|
||||
app:iconSize="24dp"
|
||||
app:iconTint="?attr/colorPrimary" />
|
||||
@@ -103,14 +123,14 @@
|
||||
android:textAllCaps="false"
|
||||
android:textColor="?attr/colorOnBackground"
|
||||
app:cornerRadius="0dp"
|
||||
app:icon="@drawable/ic_round_color_picker_24"
|
||||
app:icon="@drawable/shape_corner_16dp"
|
||||
app:iconPadding="16dp"
|
||||
app:iconSize="24dp"
|
||||
app:iconTint="?attr/colorPrimary" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/add_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:text="@string/add_widget" />
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
<color name="bg_opp">@color/bg_black</color>
|
||||
<color name="fg">#A8000000</color>
|
||||
<color name="bg_black_50" alpha="128">#80000000</color>
|
||||
<color name="bg_white_50" alpha="128">#80FFFFFF</color>
|
||||
<color name="nav_bg">#fff</color>
|
||||
<color name="nav_bg_inv">#00BFAEAE</color>
|
||||
<color name="gradiant_bg_start">#ACACAC</color>
|
||||
|
||||
@@ -53,7 +53,9 @@
|
||||
|
||||
<string name="username">Username</string>
|
||||
<string name="chapters_read">"Chapters Read "</string>
|
||||
<string name="chapters_read_n">"Chapters\nRead "</string>
|
||||
<string name="episodes_watched">"Episodes Watched "</string>
|
||||
<string name="episodes_watched_n">"Episodes\nWatched "</string>
|
||||
<string name="continue_reading">Continue Reading</string>
|
||||
<string name="continue_watching">Continue Watching</string>
|
||||
<string name="recommended">Recommended</string>
|
||||
@@ -412,6 +414,13 @@
|
||||
<string name="crop_borders">Crop Borders</string>
|
||||
<string name="note">NOTE</string>
|
||||
|
||||
<string name="installing_extension">Installing extension</string>
|
||||
<string name="installation_failed">Installation failed: %1$s</string>
|
||||
<string name="installation_complete">Installation complete</string>
|
||||
<string name="extension_has_been_installed">The extension has been successfully installed.</string>
|
||||
<string name="extension_installed">Extension installed</string>
|
||||
<string name="error_message">Error: %1$s</string>
|
||||
<string name="install_step">Step: %1$s</string>
|
||||
|
||||
<string name="jobless_message">DAMN! YOU TRULY ARE JOBLESS\nYOU REACHED THE END</string>
|
||||
<string name="file_manager_not_found">Couldn\'t find any File Manager to open SD card</string>
|
||||
@@ -673,6 +682,7 @@
|
||||
<string name="NSFWExtention">NSFW Extensions</string>
|
||||
<string name="skip_loading_extension_icons">Skip loading extension icons</string>
|
||||
<string name="use_material_you">Material You</string>
|
||||
<string name="use_app_theme">Use App Theme</string>
|
||||
<string name="extension_specific_dns">Extension-specific DNS</string>
|
||||
<string name="theme_">Theme:</string>
|
||||
<string name="user_agent">User Agent</string>
|
||||
@@ -824,10 +834,20 @@ Non quae tempore quo provident laudantium qui illo dolor vel quia dolor et exerc
|
||||
<string name="donate">donate :)</string>
|
||||
<string name="do_it">Do it!</string>
|
||||
<string name="password">Password</string>
|
||||
|
||||
<string name="profile_stats_widget">Track progress directly from your home screen</string>
|
||||
<string name="anime_watched">Anime\nWatched</string>
|
||||
<string name="manga_read">Manga\nRead</string>
|
||||
<string name="loading">Loading…</string>
|
||||
<string name="user_stats">%1$s\'s Stats</string>
|
||||
|
||||
<string name="please">Please</string>
|
||||
<string name="log_in">log in</string>
|
||||
<string name="or_join">or join</string>
|
||||
|
||||
<string name="top_background_color">Top background color</string>
|
||||
<string name="bottom_background_color">Bottom Background Color</string>
|
||||
<string name="countdown_text_color">Countdown Text Color</string>
|
||||
<string name="title_color">Title Color</string>
|
||||
<string name="stat_text_color">Stats Text Color</string>
|
||||
<string name="placeholder">Placeholder</string>
|
||||
</resources>
|
||||
|
||||
15
app/src/main/res/xml-v31/statistics_widget_info.xml
Normal file
15
app/src/main/res/xml-v31/statistics_widget_info.xml
Normal file
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:description="@string/profile_stats_widget"
|
||||
android:initialKeyguardLayout="@layout/statistics_widget"
|
||||
android:initialLayout="@layout/statistics_widget"
|
||||
android:targetCellWidth="3"
|
||||
android:targetCellHeight="2"
|
||||
android:minResizeWidth="180dp"
|
||||
android:minResizeHeight="110dp"
|
||||
android:previewImage="@drawable/statistics_widget_preview"
|
||||
android:previewLayout="@layout/statistics_widget"
|
||||
android:resizeMode="horizontal|vertical"
|
||||
android:updatePeriodMillis="86400000"
|
||||
android:widgetCategory="home_screen"
|
||||
android:configure="ani.dantotsu.widgets.statistics.ProfileStatsConfigure" />
|
||||
@@ -1,12 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:description="@string/upcoming_anime"
|
||||
android:configure="ani.dantotsu.widgets.upcoming.UpcomingWidgetConfigureActivity"
|
||||
android:configure="ani.dantotsu.widgets.upcoming.UpcomingWidgetConfigure"
|
||||
android:initialKeyguardLayout="@layout/upcoming_widget"
|
||||
android:initialLayout="@layout/upcoming_widget"
|
||||
android:minWidth="160dp"
|
||||
android:minHeight="80dp"
|
||||
android:previewImage="@drawable/example_appwidget_preview"
|
||||
android:previewImage="@drawable/upcoming_widget_preview"
|
||||
android:previewLayout="@layout/upcoming_widget"
|
||||
android:resizeMode="horizontal|vertical"
|
||||
android:updatePeriodMillis="3600000"
|
||||
|
||||
14
app/src/main/res/xml/statistics_widget_info.xml
Normal file
14
app/src/main/res/xml/statistics_widget_info.xml
Normal file
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:description="@string/profile_stats_widget"
|
||||
android:initialKeyguardLayout="@layout/statistics_widget"
|
||||
android:initialLayout="@layout/statistics_widget"
|
||||
android:minWidth="180dp"
|
||||
android:minHeight="110dp"
|
||||
android:minResizeWidth="180dp"
|
||||
android:minResizeHeight="110dp"
|
||||
android:previewImage="@drawable/statistics_widget_preview"
|
||||
android:resizeMode="horizontal|vertical"
|
||||
android:updatePeriodMillis="86400000"
|
||||
android:widgetCategory="home_screen"
|
||||
android:configure="ani.dantotsu.widgets.statistics.ProfileStatsConfigure" />
|
||||
@@ -1,12 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:description="@string/upcoming_anime"
|
||||
android:configure="ani.dantotsu.widgets.upcoming.UpcomingWidgetConfigureActivity"
|
||||
android:configure="ani.dantotsu.widgets.upcoming.UpcomingWidgetConfigure"
|
||||
android:initialKeyguardLayout="@layout/upcoming_widget"
|
||||
android:initialLayout="@layout/upcoming_widget"
|
||||
android:minWidth="160dp"
|
||||
android:minHeight="80dp"
|
||||
android:previewImage="@drawable/example_appwidget_preview"
|
||||
android:previewImage="@drawable/upcoming_widget_preview"
|
||||
android:resizeMode="horizontal|vertical"
|
||||
android:updatePeriodMillis="3600000"
|
||||
android:widgetCategory="home_screen"/>
|
||||
Reference in New Issue
Block a user