diff --git a/app/src/main/java/ani/dantotsu/Functions.kt b/app/src/main/java/ani/dantotsu/Functions.kt index d499d8e2..683263a7 100644 --- a/app/src/main/java/ani/dantotsu/Functions.kt +++ b/app/src/main/java/ani/dantotsu/Functions.kt @@ -784,7 +784,9 @@ fun copyToClipboard(string: String, toast: Boolean = true) { val clipboard = getSystemService(activity, ClipboardManager::class.java) val clip = ClipData.newPlainText("label", string) clipboard?.setPrimaryClip(clip) - if (toast) snackString(activity.getString(R.string.copied_text, string)) + if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.S_V2) { + if (toast) snackString(activity.getString(R.string.copied_text, string)) + } } @SuppressLint("SetTextI18n") @@ -1108,7 +1110,7 @@ fun buildMarkwon(activity: Activity, userInputContent: Boolean = true): Markwon val markwon = Markwon.builder(activity) .usePlugin(object : AbstractMarkwonPlugin() { override fun configureConfiguration(builder: MarkwonConfiguration.Builder) { - builder.linkResolver { view, link -> + builder.linkResolver { _, link -> copyToClipboard(link, true) } } @@ -1119,7 +1121,7 @@ fun buildMarkwon(activity: Activity, userInputContent: Boolean = true): Markwon .usePlugin(TablePlugin.create(activity)) .usePlugin(TaskListPlugin.create(activity)) .usePlugin(HtmlPlugin.create { plugin -> - if (!userInputContent) { + if (userInputContent) { plugin.addHandler( TagHandlerNoOp.create("h1", "h2", "h3", "h4", "h5", "h6", "hr", "pre", "a") ) diff --git a/app/src/main/java/ani/dantotsu/connections/anilist/AnilistQueries.kt b/app/src/main/java/ani/dantotsu/connections/anilist/AnilistQueries.kt index 695889ba..98c0f55c 100644 --- a/app/src/main/java/ani/dantotsu/connections/anilist/AnilistQueries.kt +++ b/app/src/main/java/ani/dantotsu/connections/anilist/AnilistQueries.kt @@ -61,7 +61,7 @@ class AnilistQueries { suspend fun getUserProfile(id: Int): Query.UserProfileResponse? { return executeQuery( - """{user:User(id:$id){id,name,about(asHtml:true)avatar{medium,large},bannerImage,isFollowing,isFollower,isBlocked,favourites{anime{nodes{coverImage{extraLarge,large,medium,color}}}manga{nodes{id,coverImage{extraLarge,large,medium,color}}}characters{nodes{id,image{large,medium}}}staff{nodes{id,image{large,medium}}}studios{nodes{id,name}}}statistics{anime{count,meanScore,standardDeviation,minutesWatched,episodesWatched,chaptersRead,volumesRead}manga{count,meanScore,standardDeviation,minutesWatched,episodesWatched,chaptersRead,volumesRead}}siteUrl}}""", + """{user:User(id:$id){id,name,about(asHtml:true)avatar{medium,large},bannerImage,isFollowing,isFollower,isBlocked,favourites{anime{nodes{id,coverImage{extraLarge,large,medium,color}}}manga{nodes{id,coverImage{extraLarge,large,medium,color}}}characters{nodes{id,image{large,medium}}}staff{nodes{id,image{large,medium}}}studios{nodes{id,name}}}statistics{anime{count,meanScore,standardDeviation,minutesWatched,episodesWatched,chaptersRead,volumesRead}manga{count,meanScore,standardDeviation,minutesWatched,episodesWatched,chaptersRead,volumesRead}}siteUrl}}""", force = true ) } diff --git a/app/src/main/java/ani/dantotsu/connections/anilist/api/Character.kt b/app/src/main/java/ani/dantotsu/connections/anilist/api/Character.kt index 766df516..e0539085 100644 --- a/app/src/main/java/ani/dantotsu/connections/anilist/api/Character.kt +++ b/app/src/main/java/ani/dantotsu/connections/anilist/api/Character.kt @@ -46,7 +46,7 @@ data class Character( // Notes for site moderators @SerialName("modNotes") var modNotes: String?, -) +) : java.io.Serializable @Serializable data class CharacterConnection( @@ -56,7 +56,7 @@ data class CharacterConnection( // The pagination information // @SerialName("pageInfo") var pageInfo: PageInfo?, -) +) : java.io.Serializable @Serializable data class CharacterEdge( @@ -82,7 +82,7 @@ data class CharacterEdge( // The order the character should be displayed from the users favourites @SerialName("favouriteOrder") var favouriteOrder: Int?, -) +) : java.io.Serializable @Serializable data class CharacterName( @@ -109,7 +109,7 @@ data class CharacterName( // The currently authenticated users preferred name language. Default romaji for non-authenticated @SerialName("userPreferred") var userPreferred: String?, -) +) : java.io.Serializable @Serializable data class CharacterImage( @@ -118,4 +118,4 @@ data class CharacterImage( // The character's image of media at medium size @SerialName("medium") var medium: String?, -) \ No newline at end of file +) : java.io.Serializable \ No newline at end of file diff --git a/app/src/main/java/ani/dantotsu/connections/anilist/api/Data.kt b/app/src/main/java/ani/dantotsu/connections/anilist/api/Data.kt index 4e7f2259..ab23a5d4 100644 --- a/app/src/main/java/ani/dantotsu/connections/anilist/api/Data.kt +++ b/app/src/main/java/ani/dantotsu/connections/anilist/api/Data.kt @@ -143,7 +143,7 @@ class Query { data class ToggleFollow( @SerialName("data") val data: Data? - ) { + ) : java.io.Serializable { @Serializable data class Data( @SerialName("ToggleFollow") @@ -156,7 +156,7 @@ class Query { data class GenreCollection( @SerialName("data") val data: Data - ) { + ) : java.io.Serializable { @Serializable data class Data( @SerialName("GenreCollection") @@ -168,7 +168,7 @@ class Query { data class MediaTagCollection( @SerialName("data") val data: Data - ) { + ) : java.io.Serializable { @Serializable data class Data( @SerialName("MediaTagCollection") @@ -180,7 +180,7 @@ class Query { data class User( @SerialName("data") val data: Data - ) { + ) : java.io.Serializable { @Serializable data class Data( @SerialName("User") @@ -192,7 +192,7 @@ class Query { data class UserProfileResponse( @SerialName("data") val data: Data - ) { + ) : java.io.Serializable { @Serializable data class Data( @SerialName("user") @@ -218,7 +218,7 @@ class Query { val isFollower: Boolean, @SerialName("isBlocked") val isBlocked: Boolean, - @SerialName("favorites") + @SerialName("favourites") val favorites: UserFavorites?, @SerialName("statistics") val statistics: NNUserStatisticTypes, diff --git a/app/src/main/java/ani/dantotsu/connections/anilist/api/Media.kt b/app/src/main/java/ani/dantotsu/connections/anilist/api/Media.kt index 5122e419..da2a989e 100644 --- a/app/src/main/java/ani/dantotsu/connections/anilist/api/Media.kt +++ b/app/src/main/java/ani/dantotsu/connections/anilist/api/Media.kt @@ -251,7 +251,7 @@ data class MediaCoverImage( // Average #hex color of cover image @SerialName("color") var color: String?, -) +) : java.io.Serializable @Serializable data class MediaList( @@ -490,7 +490,7 @@ data class MediaExternalLink( // isDisabled: Boolean @SerialName("notes") var notes: String?, -) +) : java.io.Serializable @Serializable enum class ExternalLinkType { @@ -512,13 +512,13 @@ data class MediaListCollection( // If there is another chunk @SerialName("hasNextChunk") var hasNextChunk: Boolean?, - ) + ) : java.io.Serializable @Serializable data class FollowData( @SerialName("id") var id: Int, @SerialName("isFollowing") var isFollowing: Boolean, -) +) : java.io.Serializable @Serializable data class MediaListGroup( @@ -532,4 +532,4 @@ data class MediaListGroup( @SerialName("isSplitCompletedList") var isSplitCompletedList: Boolean?, @SerialName("status") var status: MediaListStatus?, -) \ No newline at end of file +) : java.io.Serializable \ No newline at end of file diff --git a/app/src/main/java/ani/dantotsu/profile/ProfileFragment.kt b/app/src/main/java/ani/dantotsu/profile/ProfileFragment.kt index e8965f19..3356bd59 100644 --- a/app/src/main/java/ani/dantotsu/profile/ProfileFragment.kt +++ b/app/src/main/java/ani/dantotsu/profile/ProfileFragment.kt @@ -2,10 +2,12 @@ package ani.dantotsu.profile import android.content.Intent import android.os.Bundle +import android.util.TypedValue import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.view.animation.LayoutAnimationController +import android.webkit.WebView import androidx.core.content.ContextCompat import androidx.fragment.app.Fragment import androidx.fragment.app.activityViewModels @@ -13,7 +15,6 @@ import androidx.lifecycle.LiveData import androidx.lifecycle.lifecycleScope import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView -import ani.dantotsu.buildMarkwon import ani.dantotsu.connections.anilist.ProfileViewModel import ani.dantotsu.connections.anilist.api.Query import ani.dantotsu.databinding.FragmentProfileBinding @@ -23,10 +24,12 @@ import ani.dantotsu.media.MediaAdaptor import ani.dantotsu.media.user.ListActivity import ani.dantotsu.setSlideIn import ani.dantotsu.setSlideUp +import ani.dantotsu.util.ColorEditor.Companion.toCssColor import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch -class ProfileFragment(): Fragment() { + +class ProfileFragment() : Fragment() { lateinit var binding: FragmentProfileBinding private lateinit var activity: ProfileActivity private lateinit var user: Query.UserProfile @@ -44,8 +47,36 @@ class ProfileFragment(): Fragment() { super.onViewCreated(view, savedInstanceState) activity = requireActivity() as ProfileActivity user = arguments?.getSerializable("user") as Query.UserProfile - val markwon = buildMarkwon(activity, false) - markwon.setMarkdown(binding.profileUserBio, user.about?:"") + + val backGroundColorTypedValue = TypedValue() + val textColorTypedValue = TypedValue() + activity.theme.resolveAttribute( + android.R.attr.windowBackground, + backGroundColorTypedValue, + true + ) + activity.theme.resolveAttribute( + com.google.android.material.R.attr.colorOnBackground, + textColorTypedValue, + true + ) + + binding.profileUserBio.settings.loadWithOverviewMode = true + binding.profileUserBio.settings.useWideViewPort = true + binding.profileUserBio.settings.javaScriptEnabled = true + WebView.setWebContentsDebuggingEnabled(true) + binding.profileUserBio.setInitialScale(1) + binding.profileUserBio.loadDataWithBaseURL( + null, + styled( + convertMarkdownToHtml(user.about ?: ""), + backGroundColorTypedValue.data, + textColorTypedValue.data + ), + "text/html; charset=utf-8", + "UTF-8", + null + ) binding.userInfoContainer.visibility = if (user.about != null) View.VISIBLE else View.GONE binding.profileAnimeList.setOnClickListener { @@ -67,7 +98,8 @@ class ProfileFragment(): Fragment() { binding.profileAnimeListImage.loadImage("https://bit.ly/31bsIHq") binding.profileMangaListImage.loadImage("https://bit.ly/2ZGfcuG") binding.statsEpisodesWatched.text = user.statistics.anime.episodesWatched.toString() - binding.statsDaysWatched.text = (user.statistics.anime.minutesWatched / (24 * 60)).toString() + binding.statsDaysWatched.text = + (user.statistics.anime.minutesWatched / (24 * 60)).toString() binding.statsTotalAnime.text = user.statistics.anime.count.toString() binding.statsAnimeMeanScore.text = user.statistics.anime.meanScore.toString() binding.statsChaptersRead.text = user.statistics.manga.chaptersRead.toString() @@ -80,7 +112,7 @@ class ProfileFragment(): Fragment() { model.setAnimeFav(user.id) model.setMangaFav(user.id) } - + initRecyclerView( model.getAnimeFav(), binding.profileFavAnimeContainer, @@ -89,7 +121,7 @@ class ProfileFragment(): Fragment() { binding.profileFavAnimeEmpty, binding.profileFavAnime ) - + initRecyclerView( model.getMangaFav(), binding.profileFavMangaContainer, @@ -107,6 +139,16 @@ class ProfileFragment(): Fragment() { } } + private fun convertMarkdownToHtml(markdown: String): String { + val regex = """\[\!\[(.*?)\]\((.*?)\)\]\((.*?)\)""".toRegex() + return regex.replace(markdown) { matchResult -> + val altText = matchResult.groupValues[1] + val imageUrl = matchResult.groupValues[2] + val linkUrl = matchResult.groupValues[3] + """$altText""" + } + } + private fun initRecyclerView( mode: LiveData>, container: View, @@ -146,6 +188,34 @@ class ProfileFragment(): Fragment() { } } + private fun styled(html: String, backGroundColor: Int, textColor: Int): String { + return """ + + + + + + + $html + + + """.trimIndent() + } + companion object { fun newInstance(query: Query.UserProfile): ProfileFragment { val args = Bundle().apply { diff --git a/app/src/main/java/ani/dantotsu/util/ColorEditor.kt b/app/src/main/java/ani/dantotsu/util/ColorEditor.kt index 4a2c1d45..6503f225 100644 --- a/app/src/main/java/ani/dantotsu/util/ColorEditor.kt +++ b/app/src/main/java/ani/dantotsu/util/ColorEditor.kt @@ -84,5 +84,14 @@ class ColorEditor { } return adjustedColor } + + fun Int.toCssColor(): String { + var base = "rgba(" + base += "${Color.red(this)}, " + base += "${Color.green(this)}, " + base += "${Color.blue(this)}, " + base += "${Color.alpha(this) / 255.0})" + return base + } } } \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_profile.xml b/app/src/main/res/layout/fragment_profile.xml index 90253f56..81e2207b 100644 --- a/app/src/main/res/layout/fragment_profile.xml +++ b/app/src/main/res/layout/fragment_profile.xml @@ -332,7 +332,7 @@ -