fix: some markdown fixes
This commit is contained in:
parent
6eb654bf51
commit
b09f26ed34
13 changed files with 194 additions and 27 deletions
|
@ -19,6 +19,7 @@
|
||||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
||||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||||
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
|
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
|
||||||
|
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
|
||||||
<uses-permission
|
<uses-permission
|
||||||
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
|
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
|
||||||
android:maxSdkVersion="29" />
|
android:maxSdkVersion="29" />
|
||||||
|
|
|
@ -68,7 +68,6 @@ import android.widget.ImageView
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.annotation.AttrRes
|
import androidx.annotation.AttrRes
|
||||||
import androidx.annotation.ColorInt
|
|
||||||
import androidx.appcompat.app.AppCompatDelegate
|
import androidx.appcompat.app.AppCompatDelegate
|
||||||
import androidx.core.app.NotificationCompat
|
import androidx.core.app.NotificationCompat
|
||||||
import androidx.core.app.NotificationManagerCompat
|
import androidx.core.app.NotificationManagerCompat
|
||||||
|
@ -98,6 +97,7 @@ import ani.dantotsu.databinding.ItemCountDownBinding
|
||||||
import ani.dantotsu.media.Media
|
import ani.dantotsu.media.Media
|
||||||
import ani.dantotsu.media.MediaDetailsActivity
|
import ani.dantotsu.media.MediaDetailsActivity
|
||||||
import ani.dantotsu.notifications.IncognitoNotificationClickReceiver
|
import ani.dantotsu.notifications.IncognitoNotificationClickReceiver
|
||||||
|
import ani.dantotsu.others.AlignTagHandler
|
||||||
import ani.dantotsu.others.ImageViewDialog
|
import ani.dantotsu.others.ImageViewDialog
|
||||||
import ani.dantotsu.others.SpoilerPlugin
|
import ani.dantotsu.others.SpoilerPlugin
|
||||||
import ani.dantotsu.parsers.ShowResponse
|
import ani.dantotsu.parsers.ShowResponse
|
||||||
|
@ -119,8 +119,8 @@ import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions.withC
|
||||||
import com.bumptech.glide.load.resource.gif.GifDrawable
|
import com.bumptech.glide.load.resource.gif.GifDrawable
|
||||||
import com.bumptech.glide.request.RequestListener
|
import com.bumptech.glide.request.RequestListener
|
||||||
import com.bumptech.glide.request.RequestOptions
|
import com.bumptech.glide.request.RequestOptions
|
||||||
|
import com.bumptech.glide.request.target.CustomTarget
|
||||||
import com.bumptech.glide.request.target.Target
|
import com.bumptech.glide.request.target.Target
|
||||||
import com.bumptech.glide.request.target.ViewTarget
|
|
||||||
import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
|
import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
|
||||||
import com.google.android.material.bottomnavigation.BottomNavigationView
|
import com.google.android.material.bottomnavigation.BottomNavigationView
|
||||||
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
||||||
|
@ -1448,6 +1448,8 @@ fun openOrCopyAnilistLink(link: String) {
|
||||||
} else {
|
} else {
|
||||||
copyToClipboard(link, true)
|
copyToClipboard(link, true)
|
||||||
}
|
}
|
||||||
|
} else if (getYoutubeId(link).isNotEmpty()) {
|
||||||
|
openLinkInYouTube(link)
|
||||||
} else {
|
} else {
|
||||||
copyToClipboard(link, true)
|
copyToClipboard(link, true)
|
||||||
}
|
}
|
||||||
|
@ -1484,6 +1486,7 @@ fun buildMarkwon(
|
||||||
TagHandlerNoOp.create("h1", "h2", "h3", "h4", "h5", "h6", "hr", "pre", "a")
|
TagHandlerNoOp.create("h1", "h2", "h3", "h4", "h5", "h6", "hr", "pre", "a")
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
plugin.addHandler(AlignTagHandler())
|
||||||
})
|
})
|
||||||
.usePlugin(GlideImagesPlugin.create(object : GlideImagesPlugin.GlideStore {
|
.usePlugin(GlideImagesPlugin.create(object : GlideImagesPlugin.GlideStore {
|
||||||
|
|
||||||
|
@ -1527,3 +1530,11 @@ fun buildMarkwon(
|
||||||
.build()
|
.build()
|
||||||
return markwon
|
return markwon
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
fun getYoutubeId(url: String): String {
|
||||||
|
val regex = """(?:youtube\.com/(?:[^/]+/.+/|(?:v|e(?:mbed)?)/|.*[?&]v=)|(?:youtu\.be|youtube\.com)/)([^"&?/\s]{11})|youtube\.com/""".toRegex()
|
||||||
|
val matchResult = regex.find(url)
|
||||||
|
return matchResult?.groupValues?.getOrNull(1) ?: ""
|
||||||
|
}
|
|
@ -2,7 +2,6 @@ package ani.dantotsu
|
||||||
|
|
||||||
import android.animation.ObjectAnimator
|
import android.animation.ObjectAnimator
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.app.AlertDialog
|
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
import android.graphics.drawable.Animatable
|
import android.graphics.drawable.Animatable
|
||||||
|
@ -60,11 +59,11 @@ import ani.dantotsu.settings.saving.SharedPreferenceBooleanLiveData
|
||||||
import ani.dantotsu.settings.saving.internal.PreferenceKeystore
|
import ani.dantotsu.settings.saving.internal.PreferenceKeystore
|
||||||
import ani.dantotsu.settings.saving.internal.PreferencePackager
|
import ani.dantotsu.settings.saving.internal.PreferencePackager
|
||||||
import ani.dantotsu.themes.ThemeManager
|
import ani.dantotsu.themes.ThemeManager
|
||||||
|
import ani.dantotsu.util.AudioHelper
|
||||||
import ani.dantotsu.util.Logger
|
import ani.dantotsu.util.Logger
|
||||||
import ani.dantotsu.util.customAlertDialog
|
import ani.dantotsu.util.customAlertDialog
|
||||||
import com.google.android.material.snackbar.BaseTransientBottomBar
|
import com.google.android.material.snackbar.BaseTransientBottomBar
|
||||||
import com.google.android.material.snackbar.Snackbar
|
import com.google.android.material.snackbar.Snackbar
|
||||||
import com.google.android.material.textfield.TextInputEditText
|
|
||||||
import eu.kanade.domain.source.service.SourcePreferences
|
import eu.kanade.domain.source.service.SourcePreferences
|
||||||
import io.noties.markwon.Markwon
|
import io.noties.markwon.Markwon
|
||||||
import io.noties.markwon.SoftBreakAddsNewLinePlugin
|
import io.noties.markwon.SoftBreakAddsNewLinePlugin
|
||||||
|
@ -455,7 +454,10 @@ class MainActivity : AppCompatActivity() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (PrefManager.getVal(PrefName.OC)) {
|
||||||
|
AudioHelper.run(this, R.raw.audio)
|
||||||
|
PrefManager.setVal(PrefName.OC, false)
|
||||||
|
}
|
||||||
val torrentManager = Injekt.get<TorrentAddonManager>()
|
val torrentManager = Injekt.get<TorrentAddonManager>()
|
||||||
fun startTorrent() {
|
fun startTorrent() {
|
||||||
if (torrentManager.isAvailable() && PrefManager.getVal(PrefName.TorrentEnabled)) {
|
if (torrentManager.isAvailable() && PrefManager.getVal(PrefName.TorrentEnabled)) {
|
||||||
|
|
|
@ -353,6 +353,7 @@ class CommentsFragment : Fragment() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("NotifyDataSetChanged")
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
|
|
32
app/src/main/java/ani/dantotsu/others/AlignTagHandler.kt
Normal file
32
app/src/main/java/ani/dantotsu/others/AlignTagHandler.kt
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
package ani.dantotsu.others
|
||||||
|
|
||||||
|
import android.text.Layout
|
||||||
|
import android.text.style.AlignmentSpan
|
||||||
|
import io.noties.markwon.MarkwonConfiguration
|
||||||
|
import io.noties.markwon.RenderProps
|
||||||
|
import io.noties.markwon.html.HtmlTag
|
||||||
|
import io.noties.markwon.html.tag.SimpleTagHandler
|
||||||
|
|
||||||
|
|
||||||
|
class AlignTagHandler : SimpleTagHandler() {
|
||||||
|
|
||||||
|
override fun getSpans(
|
||||||
|
configuration: MarkwonConfiguration,
|
||||||
|
renderProps: RenderProps,
|
||||||
|
tag: HtmlTag
|
||||||
|
): Any {
|
||||||
|
val alignment: Layout.Alignment = if (tag.attributes().containsKey("center")) {
|
||||||
|
Layout.Alignment.ALIGN_CENTER
|
||||||
|
} else if (tag.attributes().containsKey("end")) {
|
||||||
|
Layout.Alignment.ALIGN_OPPOSITE
|
||||||
|
} else {
|
||||||
|
Layout.Alignment.ALIGN_NORMAL
|
||||||
|
}
|
||||||
|
|
||||||
|
return AlignmentSpan.Standard(alignment)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun supportedTags(): Collection<String> {
|
||||||
|
return setOf("align")
|
||||||
|
}
|
||||||
|
}
|
|
@ -23,12 +23,12 @@ import ani.dantotsu.databinding.ActivitySettingsBinding
|
||||||
import ani.dantotsu.initActivity
|
import ani.dantotsu.initActivity
|
||||||
import ani.dantotsu.navBarHeight
|
import ani.dantotsu.navBarHeight
|
||||||
import ani.dantotsu.openLinkInBrowser
|
import ani.dantotsu.openLinkInBrowser
|
||||||
import ani.dantotsu.openLinkInYouTube
|
|
||||||
import ani.dantotsu.others.AppUpdater
|
import ani.dantotsu.others.AppUpdater
|
||||||
import ani.dantotsu.others.CustomBottomDialog
|
import ani.dantotsu.others.CustomBottomDialog
|
||||||
import ani.dantotsu.pop
|
import ani.dantotsu.pop
|
||||||
import ani.dantotsu.setSafeOnClickListener
|
import ani.dantotsu.setSafeOnClickListener
|
||||||
import ani.dantotsu.settings.saving.PrefManager
|
import ani.dantotsu.settings.saving.PrefManager
|
||||||
|
import ani.dantotsu.settings.saving.PrefName
|
||||||
import ani.dantotsu.snackString
|
import ani.dantotsu.snackString
|
||||||
import ani.dantotsu.startMainActivity
|
import ani.dantotsu.startMainActivity
|
||||||
import ani.dantotsu.statusBarHeight
|
import ani.dantotsu.statusBarHeight
|
||||||
|
@ -217,10 +217,14 @@ class SettingsActivity : AppCompatActivity() {
|
||||||
settingsLogo.setSafeOnClickListener {
|
settingsLogo.setSafeOnClickListener {
|
||||||
cursedCounter++
|
cursedCounter++
|
||||||
(settingsLogo.drawable as Animatable).start()
|
(settingsLogo.drawable as Animatable).start()
|
||||||
if (cursedCounter % 7 == 0) {
|
if (cursedCounter % 16 == 0) {
|
||||||
toast(R.string.you_cursed)
|
val oldVal: Boolean = PrefManager.getVal(PrefName.OC)
|
||||||
openLinkInYouTube(getString(R.string.cursed_yt))
|
if (!oldVal) {
|
||||||
//PrefManager.setVal(PrefName.ImageUrl, !PrefManager.getVal(PrefName.ImageUrl, false))
|
toast(R.string.omega_cursed)
|
||||||
|
} else {
|
||||||
|
toast(R.string.omega_freed)
|
||||||
|
}
|
||||||
|
PrefManager.setVal(PrefName.OC, !oldVal)
|
||||||
} else {
|
} else {
|
||||||
snackString(array[(Math.random() * array.size).toInt()], context)
|
snackString(array[(Math.random() * array.size).toInt()], context)
|
||||||
}
|
}
|
||||||
|
|
|
@ -191,6 +191,7 @@ enum class PrefName(val data: Pref) { //TODO: Split this into multiple files
|
||||||
SubscriptionNotificationStore(Pref(Location.Irrelevant, List::class, listOf<SubscriptionStore>())),
|
SubscriptionNotificationStore(Pref(Location.Irrelevant, List::class, listOf<SubscriptionStore>())),
|
||||||
UnreadCommentNotifications(Pref(Location.Irrelevant, Int::class, 0)),
|
UnreadCommentNotifications(Pref(Location.Irrelevant, Int::class, 0)),
|
||||||
DownloadsDir(Pref(Location.Irrelevant, String::class, "")),
|
DownloadsDir(Pref(Location.Irrelevant, String::class, "")),
|
||||||
|
OC(Pref(Location.Irrelevant, Boolean::class, false)),
|
||||||
RefreshStatus(Pref(Location.Irrelevant, Boolean::class, false)),
|
RefreshStatus(Pref(Location.Irrelevant, Boolean::class, false)),
|
||||||
|
|
||||||
//Protected
|
//Protected
|
||||||
|
|
|
@ -6,6 +6,7 @@ import android.widget.FrameLayout
|
||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import androidx.core.view.isVisible
|
||||||
import androidx.core.view.updateLayoutParams
|
import androidx.core.view.updateLayoutParams
|
||||||
import androidx.core.widget.addTextChangedListener
|
import androidx.core.widget.addTextChangedListener
|
||||||
import ani.dantotsu.R
|
import ani.dantotsu.R
|
||||||
|
@ -42,7 +43,7 @@ class ActivityMarkdownCreator : AppCompatActivity() {
|
||||||
BOLD("****", 2, R.id.formatBold),
|
BOLD("****", 2, R.id.formatBold),
|
||||||
ITALIC("**", 1, R.id.formatItalic),
|
ITALIC("**", 1, R.id.formatItalic),
|
||||||
STRIKETHROUGH("~~~~", 2, R.id.formatStrikethrough),
|
STRIKETHROUGH("~~~~", 2, R.id.formatStrikethrough),
|
||||||
SPOILER("~||~", 2, R.id.formatSpoiler),
|
SPOILER("~!!~", 2, R.id.formatSpoiler),
|
||||||
LINK("[Placeholder](%s)", 0, R.id.formatLink),
|
LINK("[Placeholder](%s)", 0, R.id.formatLink),
|
||||||
IMAGE("img(%s)", 0, R.id.formatImage),
|
IMAGE("img(%s)", 0, R.id.formatImage),
|
||||||
YOUTUBE("youtube(%s)", 0, R.id.formatYoutube),
|
YOUTUBE("youtube(%s)", 0, R.id.formatYoutube),
|
||||||
|
@ -267,9 +268,13 @@ class ActivityMarkdownCreator : AppCompatActivity() {
|
||||||
private fun previewMarkdown(preview: Boolean) {
|
private fun previewMarkdown(preview: Boolean) {
|
||||||
val markwon = buildMarkwon(this, false, anilist = true)
|
val markwon = buildMarkwon(this, false, anilist = true)
|
||||||
if (preview) {
|
if (preview) {
|
||||||
|
binding.editText.isVisible = false
|
||||||
binding.editText.isEnabled = false
|
binding.editText.isEnabled = false
|
||||||
markwon.setMarkdown(binding.editText, text)
|
binding.markdownPreview.isVisible = true
|
||||||
|
markwon.setMarkdown(binding.markdownPreview, AniMarkdown.getBasicAniHTML(text))
|
||||||
} else {
|
} else {
|
||||||
|
binding.editText.isVisible = true
|
||||||
|
binding.markdownPreview.isVisible = false
|
||||||
binding.editText.setText(text)
|
binding.editText.setText(text)
|
||||||
binding.editText.isEnabled = true
|
binding.editText.isEnabled = true
|
||||||
val markwonEditor = MarkwonEditor.create(markwon)
|
val markwonEditor = MarkwonEditor.create(markwon)
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
package ani.dantotsu.util
|
package ani.dantotsu.util
|
||||||
|
|
||||||
|
import ani.dantotsu.getYoutubeId
|
||||||
import ani.dantotsu.util.ColorEditor.Companion.toCssColor
|
import ani.dantotsu.util.ColorEditor.Companion.toCssColor
|
||||||
|
|
||||||
class AniMarkdown { //istg anilist has the worst api
|
class AniMarkdown { //istg anilist has the worst api
|
||||||
companion object {
|
companion object {
|
||||||
private fun convertNestedImageToHtml(markdown: String): String {
|
private fun String.convertNestedImageToHtml(): String {
|
||||||
val regex = """\[!\[(.*?)]\((.*?)\)]\((.*?)\)""".toRegex()
|
val regex = """\[!\[(.*?)]\((.*?)\)]\((.*?)\)""".toRegex()
|
||||||
return regex.replace(markdown) { matchResult ->
|
return regex.replace(this) { matchResult ->
|
||||||
val altText = matchResult.groupValues[1]
|
val altText = matchResult.groupValues[1]
|
||||||
val imageUrl = matchResult.groupValues[2]
|
val imageUrl = matchResult.groupValues[2]
|
||||||
val linkUrl = matchResult.groupValues[3]
|
val linkUrl = matchResult.groupValues[3]
|
||||||
|
@ -14,26 +15,49 @@ class AniMarkdown { //istg anilist has the worst api
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun convertImageToHtml(markdown: String): String {
|
private fun String.convertImageToHtml(): String {
|
||||||
val regex = """!\[(.*?)]\((.*?)\)""".toRegex()
|
val regex = """!\[(.*?)]\((.*?)\)""".toRegex()
|
||||||
return regex.replace(markdown) { matchResult ->
|
val anilistRegex = """img\(.*?\)""".toRegex()
|
||||||
|
val markdownImage = regex.replace(this) { matchResult ->
|
||||||
val altText = matchResult.groupValues[1]
|
val altText = matchResult.groupValues[1]
|
||||||
val imageUrl = matchResult.groupValues[2]
|
val imageUrl = matchResult.groupValues[2]
|
||||||
"""<img src="$imageUrl" alt="$altText">"""
|
"""<img src="$imageUrl" alt="$altText">"""
|
||||||
}
|
}
|
||||||
|
return anilistRegex.replace(markdownImage) { matchResult ->
|
||||||
|
val imageUrl = matchResult.groupValues[1]
|
||||||
|
"""<img src="$imageUrl" alt="Image">"""
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun convertLinkToHtml(markdown: String): String {
|
private fun String.convertLinkToHtml(): String {
|
||||||
val regex = """\[(.*?)]\((.*?)\)""".toRegex()
|
val regex = """\[(.*?)]\((.*?)\)""".toRegex()
|
||||||
return regex.replace(markdown) { matchResult ->
|
return regex.replace(this) { matchResult ->
|
||||||
val linkText = matchResult.groupValues[1]
|
val linkText = matchResult.groupValues[1]
|
||||||
val linkUrl = matchResult.groupValues[2]
|
val linkUrl = matchResult.groupValues[2]
|
||||||
"""<a href="$linkUrl">$linkText</a>"""
|
"""<a href="$linkUrl">$linkText</a>"""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun replaceLeftovers(html: String): String {
|
private fun String.convertYoutubeToHtml(): String {
|
||||||
return html.replace(" ", " ")
|
val regex = """<div class='youtube' id='(.*?)'></div>""".toRegex()
|
||||||
|
return regex.replace(this) { matchResult ->
|
||||||
|
val url = matchResult.groupValues[1]
|
||||||
|
val id = getYoutubeId(url)
|
||||||
|
if (id.isNotEmpty()) {
|
||||||
|
"""<div>
|
||||||
|
<a href="https://www.youtube.com/watch?v=$id"><img src="https://i3.ytimg.com/vi/$id/maxresdefault.jpg" alt="$url"></a>
|
||||||
|
<align center>
|
||||||
|
<a href="https://www.youtube.com/watch?v=$id">Youtube Link</a>
|
||||||
|
</align>
|
||||||
|
</div>""".trimIndent()
|
||||||
|
} else {
|
||||||
|
"""<a href="$url">Youtube Video</a>"""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun String.replaceLeftovers(): String {
|
||||||
|
return this.replace(" ", " ")
|
||||||
.replace("&", "&")
|
.replace("&", "&")
|
||||||
.replace("<", "<")
|
.replace("<", "<")
|
||||||
.replace(">", ">")
|
.replace(">", ">")
|
||||||
|
@ -46,18 +70,29 @@ class AniMarkdown { //istg anilist has the worst api
|
||||||
.replace("\n", "<br>")
|
.replace("\n", "<br>")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun underlineToHtml(html: String): String {
|
private fun String.underlineToHtml(): String {
|
||||||
return html.replace("(?s)___(.*?)___".toRegex(), "<br><em><strong>$1</strong></em><br>")
|
return this.replace("(?s)___(.*?)___".toRegex(), "<br><em><strong>$1</strong></em><br>")
|
||||||
.replace("(?s)__(.*?)__".toRegex(), "<br><strong>$1</strong><br>")
|
.replace("(?s)__(.*?)__".toRegex(), "<br><strong>$1</strong><br>")
|
||||||
.replace("(?s)\\s+_([^_]+)_\\s+".toRegex(), "<em>$1</em>")
|
.replace("(?s)\\s+_([^_]+)_\\s+".toRegex(), "<em>$1</em>")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun String.convertCenterToHtml(): String {
|
||||||
|
val regex = """~~~(.*?)~~~""".toRegex()
|
||||||
|
return regex.replace(this) { matchResult ->
|
||||||
|
val centerText = matchResult.groupValues[1]
|
||||||
|
"""<align center>$centerText</align>"""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun getBasicAniHTML(html: String): String {
|
fun getBasicAniHTML(html: String): String {
|
||||||
val step0 = convertNestedImageToHtml(html)
|
return html
|
||||||
val step1 = convertImageToHtml(step0)
|
.convertNestedImageToHtml()
|
||||||
val step2 = convertLinkToHtml(step1)
|
.convertImageToHtml()
|
||||||
val step3 = replaceLeftovers(step2)
|
.convertLinkToHtml()
|
||||||
return underlineToHtml(step3)
|
.convertYoutubeToHtml()
|
||||||
|
.convertCenterToHtml()
|
||||||
|
.replaceLeftovers()
|
||||||
|
.underlineToHtml()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getFullAniHTML(html: String, textColor: Int): String {
|
fun getFullAniHTML(html: String, textColor: Int): String {
|
||||||
|
|
58
app/src/main/java/ani/dantotsu/util/AudioHelper.kt
Normal file
58
app/src/main/java/ani/dantotsu/util/AudioHelper.kt
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
package ani.dantotsu.util
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.media.AudioManager
|
||||||
|
import android.media.MediaPlayer
|
||||||
|
|
||||||
|
class AudioHelper(private val context: Context) {
|
||||||
|
|
||||||
|
private val audioManager: AudioManager = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager
|
||||||
|
private var mediaPlayer: MediaPlayer? = null
|
||||||
|
|
||||||
|
fun routeAudioToSpeaker() {
|
||||||
|
audioManager.requestAudioFocus(null, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN)
|
||||||
|
audioManager.mode = AudioManager.MODE_IN_COMMUNICATION
|
||||||
|
audioManager.isSpeakerphoneOn = true
|
||||||
|
}
|
||||||
|
|
||||||
|
private val maxVolume: Int
|
||||||
|
get() = audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC)
|
||||||
|
private var oldVolume: Int = 0
|
||||||
|
fun setVolume(percentage: Int) {
|
||||||
|
oldVolume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC)
|
||||||
|
val volume = (maxVolume * percentage) / 100
|
||||||
|
audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, volume, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun playAudio(audio: Int) {
|
||||||
|
mediaPlayer?.release()
|
||||||
|
mediaPlayer = MediaPlayer.create(context, audio)
|
||||||
|
mediaPlayer?.setOnCompletionListener {
|
||||||
|
setVolume(oldVolume)
|
||||||
|
audioManager.abandonAudioFocus(null)
|
||||||
|
it.release()
|
||||||
|
}
|
||||||
|
mediaPlayer?.setOnPreparedListener {
|
||||||
|
it.start()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun stopAudio() {
|
||||||
|
mediaPlayer?.let {
|
||||||
|
if (it.isPlaying) {
|
||||||
|
it.stop()
|
||||||
|
}
|
||||||
|
it.release()
|
||||||
|
mediaPlayer = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun run(context: Context, audio: Int) {
|
||||||
|
val audioHelper = AudioHelper(context)
|
||||||
|
audioHelper.routeAudioToSpeaker()
|
||||||
|
audioHelper.setVolume(90)
|
||||||
|
audioHelper.playAudio(audio)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -92,6 +92,21 @@
|
||||||
android:textIsSelectable="true"
|
android:textIsSelectable="true"
|
||||||
android:textSize="18sp"
|
android:textSize="18sp"
|
||||||
tools:ignore="LabelFor" />
|
tools:ignore="LabelFor" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/markdownPreview"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:fontFamily="@font/poppins_semi_bold"
|
||||||
|
android:gravity="top|start"
|
||||||
|
android:hint="@string/reply_hint"
|
||||||
|
android:nestedScrollingEnabled="true"
|
||||||
|
android:padding="16dp"
|
||||||
|
android:textColor="?attr/colorOnBackground"
|
||||||
|
android:textIsSelectable="true"
|
||||||
|
android:textSize="18sp"
|
||||||
|
android:visibility="gone"
|
||||||
|
tools:ignore="LabelFor" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
|
|
||||||
|
|
BIN
app/src/main/res/raw/audio.mp3
Normal file
BIN
app/src/main/res/raw/audio.mp3
Normal file
Binary file not shown.
|
@ -1042,5 +1042,7 @@ Non quae tempore quo provident laudantium qui illo dolor vel quia dolor et exerc
|
||||||
<string name="enable_forgot_password">Enable Forgot Password (hold clear button for 10 seconds)</string>
|
<string name="enable_forgot_password">Enable Forgot Password (hold clear button for 10 seconds)</string>
|
||||||
<string name="hide_notification_dot">Hide Notification Dot</string>
|
<string name="hide_notification_dot">Hide Notification Dot</string>
|
||||||
<string name="private_mode">Private</string>
|
<string name="private_mode">Private</string>
|
||||||
|
<string name="omega_cursed">you have been Ǫ̴̺̙͎̤̫͓̮̰̿͝M̴͇̤͗́̾̈́̑̍̿̈͌͝Ȅ̴̡̨̛͉̣̙̩̲̣̤̟̪̣̎͗̎̆̒̉͆̆̕ͅͅǴ̸̯̬̗̠̙͛͐̀̈͋̀̈̽́̎̿͘͘͝ͅĀ̶̧̲̀ͅ ̴̢̟͕̜̓̾̓C̶̬̜̰̘̝̱̫͓͙̭̈́͐͋̓̏̈̍̓̀̌̾̚Ư̸̛̤̱̈́͆̽͊͛̐̓́̑͘̕̕͝R̸̨̨͈̬̱̺͕̪̪̘͕͎̂͛́̅̆̓̀͝ͅS̴̨̨̛̩̭̗̹̰̭̥͉̮̝̠̓̔͆̂͊͆̀̈́̅̕͘̚͝È̴̢̛̝͈̳͉͈͒͒̒̄̏̈̈́D̸̢̡̨̜̞̩̼̫̹̗̮͛̀̈̋̾̇̕̕͜ͅ</string>
|
||||||
|
<string name="omega_freed">you have been freed</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue