選択してコピーのテキストに投票の選択肢を表示する

This commit is contained in:
tateisu 2019-04-03 06:50:05 +09:00
parent 4cc4399e92
commit 2610788431
1 changed files with 151 additions and 26 deletions

View File

@ -3,15 +3,19 @@ package jp.juggler.subwaytooter
import android.app.SearchManager
import android.content.Context
import android.content.Intent
import android.os.Build
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import android.view.View
import android.widget.EditText
import androidx.appcompat.app.AppCompatActivity
import jp.juggler.subwaytooter.api.entity.*
import jp.juggler.subwaytooter.table.MutedWord
import jp.juggler.subwaytooter.table.SavedAccount
import jp.juggler.subwaytooter.util.DecodeOptions
import jp.juggler.util.*
import jp.juggler.util.LogCategory
import jp.juggler.util.copyToClipboard
import jp.juggler.util.hideKeyboard
import jp.juggler.util.showToast
import java.util.*
class ActText : AppCompatActivity(), View.OnClickListener {
@ -28,11 +32,11 @@ class ActText : AppCompatActivity(), View.OnClickListener {
internal const val EXTRA_CONTENT_END = "content_end"
internal const val EXTRA_ACCOUNT_DB_ID = "account_db_id"
private fun addAfterLine(sb : StringBuilder, text : String) {
if(sb.isNotEmpty() && sb[sb.length - 1] != '\n') {
sb.append('\n')
private fun StringBuilder.addAfterLine( text : CharSequence) {
if( isNotEmpty() && this[length - 1] != '\n') {
append('\n')
}
sb.append(text)
append(text)
}
private fun addHeader(
@ -44,7 +48,7 @@ class ActText : AppCompatActivity(), View.OnClickListener {
if(sb.isNotEmpty() && sb[sb.length - 1] != '\n') {
sb.append('\n')
}
addAfterLine(sb, context.getString(key_str_id))
sb.addAfterLine( context.getString(key_str_id))
sb.append(": ")
sb.append(value?.toString() ?: "(null)")
}
@ -79,50 +83,166 @@ class ActText : AppCompatActivity(), View.OnClickListener {
addHeader(context, sb, R.string.send_header_content_warning, sv)
}
addAfterLine(sb, "\n")
sb.addAfterLine( "\n")
intent.putExtra(EXTRA_CONTENT_START, sb.length)
sb.append(DecodeOptions(context, access_info).decodeHTML(status.content))
encodePolls(sb,context,status)
intent.putExtra(EXTRA_CONTENT_END, sb.length)
dumpAttachment(sb, status.media_attachments)
addAfterLine(sb, String.format(Locale.JAPAN, "Status-Source: %s", status.json))
sb.addAfterLine( String.format(Locale.JAPAN, "Status-Source: %s", status.json))
addAfterLine(sb, "")
sb.addAfterLine( "")
intent.putExtra(EXTRA_TEXT, sb.toString())
}
private fun dumpAttachment(sb : StringBuilder, src : ArrayList<TootAttachmentLike>?) {
if(src == null) return
var i = 0
for(ma in src) {
++ i
if(ma is TootAttachment) {
addAfterLine(sb, "\n")
addAfterLine(sb, String.format(Locale.JAPAN, "Media-%d-Url: %s", i, ma.url))
addAfterLine(
sb,
sb.addAfterLine( "\n")
sb.addAfterLine( String.format(Locale.JAPAN, "Media-%d-Url: %s", i, ma.url))
sb.addAfterLine(
String.format(Locale.JAPAN, "Media-%d-Remote-Url: %s", i, ma.remote_url)
)
addAfterLine(
sb,
sb.addAfterLine(
String.format(Locale.JAPAN, "Media-%d-Preview-Url: %s", i, ma.preview_url)
)
addAfterLine(
sb,
sb. addAfterLine(
String.format(Locale.JAPAN, "Media-%d-Text-Url: %s", i, ma.text_url)
)
} else if(ma is TootAttachmentMSP) {
addAfterLine(sb, "\n")
addAfterLine(
sb,
sb.addAfterLine( "\n")
sb. addAfterLine(
String.format(Locale.JAPAN, "Media-%d-Preview-Url: %s", i, ma.preview_url)
)
}
}
}
private fun encodePolls(sb :StringBuilder, context:Context,status : TootStatus) {
val enquete = status.enquete ?: return
val items = enquete.items ?: return
val now = System.currentTimeMillis()
val canVote = when(enquete.pollType) {
// friends.nico の場合は本文に投票の選択肢が含まれるので
// アプリ側での文字列化は不要
PollType.FriendsNico -> return
// MastodonとMisskeyは投票の選択肢が本文に含まれないので
// アプリ側で文字列化する
PollType.Mastodon -> when {
enquete.expired -> false
now >= enquete.expired_at -> false
enquete.myVoted != null -> false
else -> true
}
PollType.Misskey -> enquete.myVoted == null
}
sb.addAfterLine("\n")
items.forEachIndexed { index, choice ->
encodePollChoice(sb, context, enquete, canVote, index, choice)
}
when(enquete.pollType) {
PollType.Mastodon -> encodePollFooterMastodon(sb, context, enquete)
else->{}
}
}
private fun encodePollChoice(
sb : StringBuilder,
context : Context,
enquete : NicoEnquete,
canVote : Boolean,
i : Int,
item : NicoEnquete.Choice
) {
val text = when(enquete.pollType) {
PollType.Misskey -> {
val sb2 = StringBuilder().append(item.decoded_text)
if(enquete.myVoted != null) {
sb2.append(" / ")
sb2.append(context.getString(R.string.vote_count_text, item.votes))
if(i == enquete.myVoted) sb2.append(' ').append(0x2713.toChar())
}
sb2
}
PollType.FriendsNico -> {
item.decoded_text
}
PollType.Mastodon -> if(canVote) {
item.decoded_text
} else {
val sb2 = StringBuilder().append(item.decoded_text)
if(! canVote) {
sb2.append(" / ")
sb2.append(
when(val v = item.votes) {
null -> context.getString(R.string.vote_count_unavailable)
else -> context.getString(R.string.vote_count_text, v)
}
)
}
sb2
}
}
sb.addAfterLine(text)
}
private fun encodePollFooterMastodon(
sb : StringBuilder,
context : Context,
enquete : NicoEnquete
) {
val line = StringBuilder()
val votes_count = enquete.votes_count ?: 0
when {
votes_count == 1 -> line.append(context.getString(R.string.vote_1))
votes_count > 1 -> line.append(context.getString(R.string.vote_2, votes_count))
}
when(val t = enquete.expired_at) {
Long.MAX_VALUE -> {
}
else -> {
if(line.isNotEmpty()) line.append(" ")
line.append(
context.getString(
R.string.vote_expire_at,
TootStatus.formatTime(context, t, false)
)
)
}
}
sb.addAfterLine(line)
}
private fun encodeAccount(
intent : Intent,
context : Context,
@ -142,11 +262,11 @@ class ActText : AppCompatActivity(), View.OnClickListener {
sb.append(who.url)
intent.putExtra(EXTRA_CONTENT_END, sb.length)
addAfterLine(sb, "\n")
sb.addAfterLine( "\n")
sb.append(DecodeOptions(context, access_info).decodeHTML(who.note))
addAfterLine(sb, "\n")
sb.addAfterLine( "\n")
addHeader(context, sb, R.string.send_header_account_name, who.display_name)
addHeader(context, sb, R.string.send_header_account_acct, access_info.getFullAcct(who))
@ -183,7 +303,7 @@ class ActText : AppCompatActivity(), View.OnClickListener {
)
addHeader(context, sb, R.string.send_header_account_locked, who.locked)
addAfterLine(sb, "")
sb.addAfterLine("")
intent.putExtra(EXTRA_TEXT, sb.toString())
}
@ -246,8 +366,13 @@ class ActText : AppCompatActivity(), View.OnClickListener {
val content_start = intent.getIntExtra(EXTRA_CONTENT_START, 0)
val content_end = intent.getIntExtra(EXTRA_CONTENT_END, sv.length)
etText.setText(sv)
etText.requestFocus()
etText.hideKeyboard()
// Android 9 以降ではフォーカスがないとsetSelectionできない
if( Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
etText.requestFocus()
etText.hideKeyboard()
}
etText.setSelection(content_start, content_end)
}
}