Skip to content

Commit

Permalink
fix: some markdown fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
rebelonion committed Jun 29, 2024
1 parent 6eb654b commit b09f26e
Show file tree
Hide file tree
Showing 13 changed files with 194 additions and 27 deletions.
1 change: 1 addition & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="29" />
Expand Down
15 changes: 13 additions & 2 deletions app/src/main/java/ani/dantotsu/Functions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@ import android.widget.ImageView
import android.widget.TextView
import android.widget.Toast
import androidx.annotation.AttrRes
import androidx.annotation.ColorInt
import androidx.appcompat.app.AppCompatDelegate
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
Expand Down Expand Up @@ -98,6 +97,7 @@ import ani.dantotsu.databinding.ItemCountDownBinding
import ani.dantotsu.media.Media
import ani.dantotsu.media.MediaDetailsActivity
import ani.dantotsu.notifications.IncognitoNotificationClickReceiver
import ani.dantotsu.others.AlignTagHandler
import ani.dantotsu.others.ImageViewDialog
import ani.dantotsu.others.SpoilerPlugin
import ani.dantotsu.parsers.ShowResponse
Expand All @@ -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.request.RequestListener
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.ViewTarget
import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
import com.google.android.material.bottomnavigation.BottomNavigationView
import com.google.android.material.bottomsheet.BottomSheetBehavior
Expand Down Expand Up @@ -1448,6 +1448,8 @@ fun openOrCopyAnilistLink(link: String) {
} else {
copyToClipboard(link, true)
}
} else if (getYoutubeId(link).isNotEmpty()) {
openLinkInYouTube(link)
} else {
copyToClipboard(link, true)
}
Expand Down Expand Up @@ -1484,6 +1486,7 @@ fun buildMarkwon(
TagHandlerNoOp.create("h1", "h2", "h3", "h4", "h5", "h6", "hr", "pre", "a")
)
}
plugin.addHandler(AlignTagHandler())
})
.usePlugin(GlideImagesPlugin.create(object : GlideImagesPlugin.GlideStore {

Expand Down Expand Up @@ -1527,3 +1530,11 @@ fun buildMarkwon(
.build()
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) ?: ""
}
8 changes: 5 additions & 3 deletions app/src/main/java/ani/dantotsu/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package ani.dantotsu

import android.animation.ObjectAnimator
import android.annotation.SuppressLint
import android.app.AlertDialog
import android.content.Intent
import android.content.res.Configuration
import android.graphics.drawable.Animatable
Expand Down Expand Up @@ -60,11 +59,11 @@ import ani.dantotsu.settings.saving.SharedPreferenceBooleanLiveData
import ani.dantotsu.settings.saving.internal.PreferenceKeystore
import ani.dantotsu.settings.saving.internal.PreferencePackager
import ani.dantotsu.themes.ThemeManager
import ani.dantotsu.util.AudioHelper
import ani.dantotsu.util.Logger
import ani.dantotsu.util.customAlertDialog
import com.google.android.material.snackbar.BaseTransientBottomBar
import com.google.android.material.snackbar.Snackbar
import com.google.android.material.textfield.TextInputEditText
import eu.kanade.domain.source.service.SourcePreferences
import io.noties.markwon.Markwon
import io.noties.markwon.SoftBreakAddsNewLinePlugin
Expand Down Expand Up @@ -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>()
fun startTorrent() {
if (torrentManager.isAvailable() && PrefManager.getVal(PrefName.TorrentEnabled)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,7 @@ class CommentsFragment : Fragment() {
}
}
}

@SuppressLint("NotifyDataSetChanged")
override fun onResume() {
super.onResume()
Expand Down
32 changes: 32 additions & 0 deletions app/src/main/java/ani/dantotsu/others/AlignTagHandler.kt
Original file line number Diff line number Diff line change
@@ -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")
}
}
14 changes: 9 additions & 5 deletions app/src/main/java/ani/dantotsu/settings/SettingsActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,12 @@ import ani.dantotsu.databinding.ActivitySettingsBinding
import ani.dantotsu.initActivity
import ani.dantotsu.navBarHeight
import ani.dantotsu.openLinkInBrowser
import ani.dantotsu.openLinkInYouTube
import ani.dantotsu.others.AppUpdater
import ani.dantotsu.others.CustomBottomDialog
import ani.dantotsu.pop
import ani.dantotsu.setSafeOnClickListener
import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.snackString
import ani.dantotsu.startMainActivity
import ani.dantotsu.statusBarHeight
Expand Down Expand Up @@ -217,10 +217,14 @@ class SettingsActivity : AppCompatActivity() {
settingsLogo.setSafeOnClickListener {
cursedCounter++
(settingsLogo.drawable as Animatable).start()
if (cursedCounter % 7 == 0) {
toast(R.string.you_cursed)
openLinkInYouTube(getString(R.string.cursed_yt))
//PrefManager.setVal(PrefName.ImageUrl, !PrefManager.getVal(PrefName.ImageUrl, false))
if (cursedCounter % 16 == 0) {
val oldVal: Boolean = PrefManager.getVal(PrefName.OC)
if (!oldVal) {
toast(R.string.omega_cursed)
} else {
toast(R.string.omega_freed)
}
PrefManager.setVal(PrefName.OC, !oldVal)
} else {
snackString(array[(Math.random() * array.size).toInt()], context)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ enum class PrefName(val data: Pref) { //TODO: Split this into multiple files
SubscriptionNotificationStore(Pref(Location.Irrelevant, List::class, listOf<SubscriptionStore>())),
UnreadCommentNotifications(Pref(Location.Irrelevant, Int::class, 0)),
DownloadsDir(Pref(Location.Irrelevant, String::class, "")),
OC(Pref(Location.Irrelevant, Boolean::class, false)),
RefreshStatus(Pref(Location.Irrelevant, Boolean::class, false)),

//Protected
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import android.widget.FrameLayout
import android.widget.ImageView
import android.widget.LinearLayout
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.isVisible
import androidx.core.view.updateLayoutParams
import androidx.core.widget.addTextChangedListener
import ani.dantotsu.R
Expand Down Expand Up @@ -42,7 +43,7 @@ class ActivityMarkdownCreator : AppCompatActivity() {
BOLD("****", 2, R.id.formatBold),
ITALIC("**", 1, R.id.formatItalic),
STRIKETHROUGH("~~~~", 2, R.id.formatStrikethrough),
SPOILER("~||~", 2, R.id.formatSpoiler),
SPOILER("~!!~", 2, R.id.formatSpoiler),
LINK("[Placeholder](%s)", 0, R.id.formatLink),
IMAGE("img(%s)", 0, R.id.formatImage),
YOUTUBE("youtube(%s)", 0, R.id.formatYoutube),
Expand Down Expand Up @@ -267,9 +268,13 @@ class ActivityMarkdownCreator : AppCompatActivity() {
private fun previewMarkdown(preview: Boolean) {
val markwon = buildMarkwon(this, false, anilist = true)
if (preview) {
binding.editText.isVisible = false
binding.editText.isEnabled = false
markwon.setMarkdown(binding.editText, text)
binding.markdownPreview.isVisible = true
markwon.setMarkdown(binding.markdownPreview, AniMarkdown.getBasicAniHTML(text))
} else {
binding.editText.isVisible = true
binding.markdownPreview.isVisible = false
binding.editText.setText(text)
binding.editText.isEnabled = true
val markwonEditor = MarkwonEditor.create(markwon)
Expand Down
65 changes: 50 additions & 15 deletions app/src/main/java/ani/dantotsu/util/AniMarkdown.kt
Original file line number Diff line number Diff line change
@@ -1,39 +1,63 @@
package ani.dantotsu.util

import ani.dantotsu.getYoutubeId
import ani.dantotsu.util.ColorEditor.Companion.toCssColor

class AniMarkdown { //istg anilist has the worst api
companion object {
private fun convertNestedImageToHtml(markdown: String): String {
private fun String.convertNestedImageToHtml(): String {
val regex = """\[!\[(.*?)]\((.*?)\)]\((.*?)\)""".toRegex()
return regex.replace(markdown) { matchResult ->
return regex.replace(this) { matchResult ->
val altText = matchResult.groupValues[1]
val imageUrl = matchResult.groupValues[2]
val linkUrl = matchResult.groupValues[3]
"""<a href="$linkUrl"><img src="$imageUrl" alt="$altText"></a>"""
}
}

private fun convertImageToHtml(markdown: String): String {
private fun String.convertImageToHtml(): String {
val regex = """!\[(.*?)]\((.*?)\)""".toRegex()
return regex.replace(markdown) { matchResult ->
val anilistRegex = """img\(.*?\)""".toRegex()
val markdownImage = regex.replace(this) { matchResult ->
val altText = matchResult.groupValues[1]
val imageUrl = matchResult.groupValues[2]
"""<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()
return regex.replace(markdown) { matchResult ->
return regex.replace(this) { matchResult ->
val linkText = matchResult.groupValues[1]
val linkUrl = matchResult.groupValues[2]
"""<a href="$linkUrl">$linkText</a>"""
}
}

private fun replaceLeftovers(html: String): String {
return html.replace("&nbsp;", " ")
private fun String.convertYoutubeToHtml(): String {
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("&nbsp;", " ")
.replace("&amp;", "&")
.replace("&lt;", "<")
.replace("&gt;", ">")
Expand All @@ -46,18 +70,29 @@ class AniMarkdown { //istg anilist has the worst api
.replace("\n", "<br>")
}

private fun underlineToHtml(html: String): String {
return html.replace("(?s)___(.*?)___".toRegex(), "<br><em><strong>$1</strong></em><br>")
private fun String.underlineToHtml(): String {
return this.replace("(?s)___(.*?)___".toRegex(), "<br><em><strong>$1</strong></em><br>")
.replace("(?s)__(.*?)__".toRegex(), "<br><strong>$1</strong><br>")
.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 {
val step0 = convertNestedImageToHtml(html)
val step1 = convertImageToHtml(step0)
val step2 = convertLinkToHtml(step1)
val step3 = replaceLeftovers(step2)
return underlineToHtml(step3)
return html
.convertNestedImageToHtml()
.convertImageToHtml()
.convertLinkToHtml()
.convertYoutubeToHtml()
.convertCenterToHtml()
.replaceLeftovers()
.underlineToHtml()
}

fun getFullAniHTML(html: String, textColor: Int): String {
Expand Down
58 changes: 58 additions & 0 deletions app/src/main/java/ani/dantotsu/util/AudioHelper.kt
Original file line number Diff line number Diff line change
@@ -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)
}
}
}
Loading

0 comments on commit b09f26e

Please sign in to comment.