diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 1a6ab597665..9b071c2bf10 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -19,6 +19,7 @@
+
diff --git a/app/src/main/java/ani/dantotsu/Functions.kt b/app/src/main/java/ani/dantotsu/Functions.kt
index abfebb3ab14..c41d22ced6c 100644
--- a/app/src/main/java/ani/dantotsu/Functions.kt
+++ b/app/src/main/java/ani/dantotsu/Functions.kt
@@ -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
@@ -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
@@ -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
@@ -1448,6 +1448,8 @@ fun openOrCopyAnilistLink(link: String) {
} else {
copyToClipboard(link, true)
}
+ } else if (getYoutubeId(link).isNotEmpty()) {
+ openLinkInYouTube(link)
} else {
copyToClipboard(link, true)
}
@@ -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 {
@@ -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) ?: ""
+}
\ No newline at end of file
diff --git a/app/src/main/java/ani/dantotsu/MainActivity.kt b/app/src/main/java/ani/dantotsu/MainActivity.kt
index 7b2e0b1d953..412ed67692c 100644
--- a/app/src/main/java/ani/dantotsu/MainActivity.kt
+++ b/app/src/main/java/ani/dantotsu/MainActivity.kt
@@ -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
@@ -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
@@ -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()
fun startTorrent() {
if (torrentManager.isAvailable() && PrefManager.getVal(PrefName.TorrentEnabled)) {
diff --git a/app/src/main/java/ani/dantotsu/media/comments/CommentsFragment.kt b/app/src/main/java/ani/dantotsu/media/comments/CommentsFragment.kt
index fc21805e67f..de1c76b8df1 100644
--- a/app/src/main/java/ani/dantotsu/media/comments/CommentsFragment.kt
+++ b/app/src/main/java/ani/dantotsu/media/comments/CommentsFragment.kt
@@ -353,6 +353,7 @@ class CommentsFragment : Fragment() {
}
}
}
+
@SuppressLint("NotifyDataSetChanged")
override fun onResume() {
super.onResume()
diff --git a/app/src/main/java/ani/dantotsu/others/AlignTagHandler.kt b/app/src/main/java/ani/dantotsu/others/AlignTagHandler.kt
new file mode 100644
index 00000000000..1708ed0507c
--- /dev/null
+++ b/app/src/main/java/ani/dantotsu/others/AlignTagHandler.kt
@@ -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 {
+ return setOf("align")
+ }
+}
diff --git a/app/src/main/java/ani/dantotsu/settings/SettingsActivity.kt b/app/src/main/java/ani/dantotsu/settings/SettingsActivity.kt
index 2022fac1013..7e58e870058 100644
--- a/app/src/main/java/ani/dantotsu/settings/SettingsActivity.kt
+++ b/app/src/main/java/ani/dantotsu/settings/SettingsActivity.kt
@@ -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
@@ -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)
}
diff --git a/app/src/main/java/ani/dantotsu/settings/saving/Preferences.kt b/app/src/main/java/ani/dantotsu/settings/saving/Preferences.kt
index 6f188b854c3..c71a6a9bab8 100644
--- a/app/src/main/java/ani/dantotsu/settings/saving/Preferences.kt
+++ b/app/src/main/java/ani/dantotsu/settings/saving/Preferences.kt
@@ -191,6 +191,7 @@ enum class PrefName(val data: Pref) { //TODO: Split this into multiple files
SubscriptionNotificationStore(Pref(Location.Irrelevant, List::class, listOf())),
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
diff --git a/app/src/main/java/ani/dantotsu/util/ActivityMarkdownCreator.kt b/app/src/main/java/ani/dantotsu/util/ActivityMarkdownCreator.kt
index fdc24937690..5548401e797 100644
--- a/app/src/main/java/ani/dantotsu/util/ActivityMarkdownCreator.kt
+++ b/app/src/main/java/ani/dantotsu/util/ActivityMarkdownCreator.kt
@@ -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
@@ -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),
@@ -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)
diff --git a/app/src/main/java/ani/dantotsu/util/AniMarkdown.kt b/app/src/main/java/ani/dantotsu/util/AniMarkdown.kt
index 3f8c04d7250..200b3883411 100644
--- a/app/src/main/java/ani/dantotsu/util/AniMarkdown.kt
+++ b/app/src/main/java/ani/dantotsu/util/AniMarkdown.kt
@@ -1,12 +1,13 @@
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]
@@ -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()
- 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]
""""""
}
+ return anilistRegex.replace(markdownImage) { matchResult ->
+ val imageUrl = matchResult.groupValues[1]
+ """"""
+ }
}
- 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]
"""$linkText"""
}
}
- private fun replaceLeftovers(html: String): String {
- return html.replace(" ", " ")
+ private fun String.convertYoutubeToHtml(): String {
+ val regex = """""".toRegex()
+ return regex.replace(this) { matchResult ->
+ val url = matchResult.groupValues[1]
+ val id = getYoutubeId(url)
+ if (id.isNotEmpty()) {
+ """""".trimIndent()
+ } else {
+ """Youtube Video"""
+ }
+ }
+ }
+
+ private fun String.replaceLeftovers(): String {
+ return this.replace(" ", " ")
.replace("&", "&")
.replace("<", "<")
.replace(">", ">")
@@ -46,18 +70,29 @@ class AniMarkdown { //istg anilist has the worst api
.replace("\n", "
")
}
- private fun underlineToHtml(html: String): String {
- return html.replace("(?s)___(.*?)___".toRegex(), "
$1
")
+ private fun String.underlineToHtml(): String {
+ return this.replace("(?s)___(.*?)___".toRegex(), "
$1
")
.replace("(?s)__(.*?)__".toRegex(), "
$1
")
.replace("(?s)\\s+_([^_]+)_\\s+".toRegex(), "$1")
}
+ private fun String.convertCenterToHtml(): String {
+ val regex = """~~~(.*?)~~~""".toRegex()
+ return regex.replace(this) { matchResult ->
+ val centerText = matchResult.groupValues[1]
+ """$centerText"""
+ }
+ }
+
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 {
diff --git a/app/src/main/java/ani/dantotsu/util/AudioHelper.kt b/app/src/main/java/ani/dantotsu/util/AudioHelper.kt
new file mode 100644
index 00000000000..bfd38be0a97
--- /dev/null
+++ b/app/src/main/java/ani/dantotsu/util/AudioHelper.kt
@@ -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)
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_markdown_creator.xml b/app/src/main/res/layout/activity_markdown_creator.xml
index fb66d6f0362..548ad1771ea 100644
--- a/app/src/main/res/layout/activity_markdown_creator.xml
+++ b/app/src/main/res/layout/activity_markdown_creator.xml
@@ -92,6 +92,21 @@
android:textIsSelectable="true"
android:textSize="18sp"
tools:ignore="LabelFor" />
+
+
diff --git a/app/src/main/res/raw/audio.mp3 b/app/src/main/res/raw/audio.mp3
new file mode 100644
index 00000000000..49e1e430f00
Binary files /dev/null and b/app/src/main/res/raw/audio.mp3 differ
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 832cc9fac02..f47309a0eca 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -1042,5 +1042,7 @@ Non quae tempore quo provident laudantium qui illo dolor vel quia dolor et exerc
Enable Forgot Password (hold clear button for 10 seconds)
Hide Notification Dot
Private
+ you have been Ǫ̴̺̙͎̤̫͓̮̰̿͝M̴͇̤͗́̾̈́̑̍̿̈͌͝Ȅ̴̡̨̛͉̣̙̩̲̣̤̟̪̣̎͗̎̆̒̉͆̆̕ͅͅǴ̸̯̬̗̠̙͛͐̀̈͋̀̈̽́̎̿͘͘͝ͅĀ̶̧̲̀ͅ ̴̢̟͕̜̓̾̓C̶̬̜̰̘̝̱̫͓͙̭̈́͐͋̓̏̈̍̓̀̌̾̚Ư̸̛̤̱̈́͆̽͊͛̐̓́̑͘̕̕͝R̸̨̨͈̬̱̺͕̪̪̘͕͎̂͛́̅̆̓̀͝ͅS̴̨̨̛̩̭̗̹̰̭̥͉̮̝̠̓̔͆̂͊͆̀̈́̅̕͘̚͝È̴̢̛̝͈̳͉͈͒͒̒̄̏̈̈́D̸̢̡̨̜̞̩̼̫̹̗̮͛̀̈̋̾̇̕̕͜ͅ
+ you have been freed