diff --git a/app/src/main/java/ani/dantotsu/util/MarkdownCreatorActivity.kt b/app/src/main/java/ani/dantotsu/util/MarkdownCreatorActivity.kt index b56fd3aa..a7936e1a 100644 --- a/app/src/main/java/ani/dantotsu/util/MarkdownCreatorActivity.kt +++ b/app/src/main/java/ani/dantotsu/util/MarkdownCreatorActivity.kt @@ -2,6 +2,9 @@ package ani.dantotsu.util import android.os.Bundle import android.view.ViewGroup +import android.widget.FrameLayout +import android.widget.ImageView +import android.widget.LinearLayout import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AppCompatActivity import androidx.core.view.updateLayoutParams @@ -16,6 +19,8 @@ import ani.dantotsu.openLinkInBrowser import ani.dantotsu.statusBarHeight import ani.dantotsu.themes.ThemeManager import ani.dantotsu.toast +import com.google.android.material.textfield.TextInputEditText +import com.google.android.material.textfield.TextInputLayout import io.noties.markwon.editor.MarkwonEditor import io.noties.markwon.editor.MarkwonEditorTextWatcher import kotlinx.coroutines.DelicateCoroutinesApi @@ -25,25 +30,29 @@ class MarkdownCreatorActivity : AppCompatActivity() { private lateinit var binding: ActivityMarkdownCreatorBinding private lateinit var type: String private var text: String = "" - var ping: String? = null + private var ping: String? = null private var parentId: Int = 0 private var isPreviewMode: Boolean = false - enum class MarkdownFormat(val syntax: String, val selectionOffset: Int) { - BOLD("**", 2), - ITALIC("*", 1), - STRIKETHROUGH("~~", 2), - SPOILER("||", 2), - LINK("[link](url)", 6), - IMAGE("![alt text](image url)", 11), - YOUTUBE("[![YouTube](thumbnail)](video url)", 27), - VIDEO("[video](url)", 7), - ORDERED_LIST("1. ", 3), - UNORDERED_LIST("- ", 2), - HEADING("# ", 2), - CENTERED("-> <-", 3), - QUOTE("> ", 2), - CODE("`", 1); + enum class MarkdownFormat( + val syntax: String, + val selectionOffset: Int, + val imageViewId: Int + ) { + BOLD("****", 2, R.id.formatBold), + ITALIC("**", 1, R.id.formatItalic), + STRIKETHROUGH("~~~~", 2, R.id.formatStrikethrough), + 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), + VIDEO("webm(%s)", 0, R.id.formatVideo), + ORDERED_LIST("1. ", 3, R.id.formatListOrdered), + UNORDERED_LIST("- ", 2, R.id.formatListUnordered), + HEADING("# ", 2, R.id.formatTitle), + CENTERED("~~~~~~", 3, R.id.formatCenter), + QUOTE("> ", 2, R.id.formatQuote), + CODE("``", 1, R.id.formatCode) } @OptIn(DelicateCoroutinesApi::class) @@ -105,7 +114,7 @@ class MarkdownCreatorActivity : AppCompatActivity() { toast(getString(R.string.cannot_be_empty)) return@setOnClickListener } - AlertDialog.Builder(this).apply { + AlertDialog.Builder(this, R.style.MyPopup).apply { setTitle(R.string.warning) setMessage(R.string.post_to_anilist_warning) setPositiveButton(R.string.ok) { _, _ -> @@ -153,25 +162,106 @@ class MarkdownCreatorActivity : AppCompatActivity() { } private fun setupMarkdownButtons() { - binding.formatBold.setOnClickListener { applyMarkdownFormat(MarkdownFormat.BOLD) } - binding.formatItalic.setOnClickListener { applyMarkdownFormat(MarkdownFormat.ITALIC) } - binding.formatStrikethrough.setOnClickListener { applyMarkdownFormat(MarkdownFormat.STRIKETHROUGH) } + MarkdownFormat.entries.forEach { format -> + findViewById(format.imageViewId)?.setOnClickListener { + applyMarkdownFormat(format) + } + } } private fun applyMarkdownFormat(format: MarkdownFormat) { val start = binding.editText.selectionStart val end = binding.editText.selectionEnd - if (start == end) { - binding.editText.text?.insert(start, format.syntax) - binding.editText.setSelection(start + format.selectionOffset) + if (start != end) { + val selectedText = binding.editText.text?.substring(start, end) ?: "" + val lines = selectedText.split("\n") + + val newText = when (format) { + MarkdownFormat.UNORDERED_LIST -> { + lines.joinToString("\n") { "- $it" } + } + MarkdownFormat.ORDERED_LIST -> { + lines.mapIndexed { index, line -> "${index + 1}. $line" }.joinToString("\n") + } + else -> { + if (format.syntax.contains("%s")) { + String.format(format.syntax, selectedText) + } else { + format.syntax.substring(0, format.selectionOffset) + + selectedText + + format.syntax.substring(format.selectionOffset) + } + } + } + + binding.editText.text?.replace(start, end, newText) + binding.editText.setSelection(start + newText.length) } else { - binding.editText.text?.insert(end, format.syntax) - binding.editText.text?.insert(start, format.syntax) - binding.editText.setSelection(end + format.syntax.length, end + format.syntax.length) + if (format.syntax.contains("%s")) { + showInputDialog(format, start) + } else { + val newText = format.syntax + binding.editText.text?.insert(start, newText) + binding.editText.setSelection(start + format.selectionOffset) + } } } + + private fun showInputDialog(format: MarkdownFormat, position: Int) { + val inputLayout = TextInputLayout(this).apply { + layoutParams = ViewGroup.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.WRAP_CONTENT + ) + boxBackgroundMode = TextInputLayout.BOX_BACKGROUND_OUTLINE + hint = "Paste your link here" + isHintEnabled = true + } + + val inputEditText = TextInputEditText(this).apply { + layoutParams = LinearLayout.LayoutParams( + LinearLayout.LayoutParams.MATCH_PARENT, + LinearLayout.LayoutParams.WRAP_CONTENT + ) + } + + inputLayout.addView(inputEditText) + + val container = FrameLayout(this).apply { + addView(inputLayout) + layoutParams = ViewGroup.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT + ) + setPadding(64, 64, 64, 0) + } + + val dialog = AlertDialog.Builder(this, R.style.MyPopup).apply { + setView(container) + setPositiveButton(getString(R.string.ok)) { dialog, _ -> + val input = inputEditText.text.toString() + val formattedText = String.format(format.syntax, input) + binding.editText.text?.insert(position, formattedText) + binding.editText.setSelection(position + formattedText.length) + dialog.dismiss() + } + setNegativeButton(getString(R.string.cancel)) { dialog, _ -> + dialog.dismiss() + } + }.create() + + val widthInDp = 245 + val layoutParams = ViewGroup.LayoutParams( + (widthInDp * resources.displayMetrics.density).toInt(), + ViewGroup.LayoutParams.WRAP_CONTENT + ) + dialog.window?.setLayout(layoutParams.width, layoutParams.height) + dialog.show() + inputEditText.requestFocus() + } + private fun previewMarkdown(preview: Boolean) { val markwon = buildMarkwon(this, false, anilist = true) if (preview) { diff --git a/app/src/main/res/drawable/format_code_24.xml b/app/src/main/res/drawable/format_code_24.xml new file mode 100644 index 00000000..61eaae2d --- /dev/null +++ b/app/src/main/res/drawable/format_code_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/format_image_24.xml b/app/src/main/res/drawable/format_image_24.xml new file mode 100644 index 00000000..f6cc30a4 --- /dev/null +++ b/app/src/main/res/drawable/format_image_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/format_link_24.xml b/app/src/main/res/drawable/format_link_24.xml new file mode 100644 index 00000000..c8c0c1b6 --- /dev/null +++ b/app/src/main/res/drawable/format_link_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/format_spoiler_24.xml b/app/src/main/res/drawable/format_spoiler_24.xml new file mode 100644 index 00000000..647711b4 --- /dev/null +++ b/app/src/main/res/drawable/format_spoiler_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/format_title_24.xml b/app/src/main/res/drawable/format_title_24.xml new file mode 100644 index 00000000..4b15683f --- /dev/null +++ b/app/src/main/res/drawable/format_title_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/format_video_24.xml b/app/src/main/res/drawable/format_video_24.xml new file mode 100644 index 00000000..9813485d --- /dev/null +++ b/app/src/main/res/drawable/format_video_24.xml @@ -0,0 +1,11 @@ + + + diff --git a/app/src/main/res/drawable/format_youtube_24.xml b/app/src/main/res/drawable/format_youtube_24.xml new file mode 100644 index 00000000..909e5a21 --- /dev/null +++ b/app/src/main/res/drawable/format_youtube_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/layout/activity_markdown_creator.xml b/app/src/main/res/layout/activity_markdown_creator.xml index d7523dca..504557a0 100644 --- a/app/src/main/res/layout/activity_markdown_creator.xml +++ b/app/src/main/res/layout/activity_markdown_creator.xml @@ -73,7 +73,7 @@ + android:layout_gravity="bottom|end" + android:layout_marginHorizontal="13dp" + android:orientation="vertical" + android:padding="8dp" + android:windowSoftInputMode="adjustResize"> + android:orientation="horizontal"> @@ -116,6 +117,8 @@ android:id="@+id/formatItalic" android:layout_width="wrap_content" android:layout_height="wrap_content" + android:padding="6dp" + android:layout_marginEnd="10dp" android:src="@drawable/format_italic_24" app:tint="?attr/colorOnBackground" tools:ignore="ContentDescription" /> @@ -124,10 +127,127 @@ android:id="@+id/formatStrikethrough" android:layout_width="wrap_content" android:layout_height="wrap_content" + android:padding="6dp" + android:layout_marginEnd="10dp" android:src="@drawable/format_strikethrough_24" app:tint="?attr/colorOnBackground" tools:ignore="ContentDescription" /> + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file