SubwayTooter-Android-App/app/src/main/java/jp/juggler/subwaytooter/ActText.kt

305 lines
9.3 KiB
Kotlin
Raw Normal View History

package jp.juggler.subwaytooter
import android.app.SearchManager
import android.content.ClipData
import android.content.ClipboardManager
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import android.text.TextUtils
import android.view.View
import android.widget.EditText
import jp.juggler.subwaytooter.api.entity.*
import java.util.Locale
import jp.juggler.subwaytooter.table.MutedWord
import jp.juggler.subwaytooter.table.SavedAccount
import jp.juggler.subwaytooter.util.DecodeOptions
import jp.juggler.subwaytooter.util.LogCategory
import jp.juggler.subwaytooter.util.Utils
class ActText : AppCompatActivity(), View.OnClickListener {
companion object {
internal val log = LogCategory("ActText")
internal const val RESULT_SEARCH_MSP = RESULT_FIRST_USER + 1
internal const val RESULT_SEARCH_TS = RESULT_FIRST_USER + 2
internal const val EXTRA_TEXT = "text"
internal const val EXTRA_CONTENT_START = "content_start"
internal const val EXTRA_CONTENT_END = "content_end"
private fun addAfterLine(sb : StringBuilder, text : String) {
if(sb.isNotEmpty() && sb[sb.length - 1] != '\n') {
sb.append('\n')
}
sb.append(text)
}
private fun addHeader(context : Context, sb : StringBuilder, key_str_id : Int, value : Any?) {
if(sb.isNotEmpty() && sb[sb.length - 1] != '\n') {
sb.append('\n')
}
addAfterLine(sb, context.getString(key_str_id))
sb.append(": ")
sb.append(value?.toString() ?: "(null)")
}
private fun encodeStatus(intent : Intent, context : Context, access_info : SavedAccount, status : TootStatus) {
val sb = StringBuilder()
addHeader(context, sb, R.string.send_header_url, status.url)
addHeader(context, sb, R.string.send_header_date, TootStatus.formatTime(context, status.time_created_at, false))
addHeader(context, sb, R.string.send_header_from_acct, access_info.getFullAcct(status.account))
val sv :String? = status.spoiler_text
if( sv != null && sv.isNotEmpty() ) {
addHeader(context, sb, R.string.send_header_content_warning, sv)
}
addAfterLine(sb, "\n")
intent.putExtra(EXTRA_CONTENT_START, sb.length)
sb.append(DecodeOptions().decodeHTML(context, access_info, status.content))
intent.putExtra(EXTRA_CONTENT_END, sb.length)
dumpAttachment(sb, status.media_attachments)
addAfterLine(sb, String.format(Locale.JAPAN, "Status-Source: %s", status.json))
addAfterLine(sb, "")
intent.putExtra(EXTRA_TEXT, sb.toString())
}
private fun dumpAttachment(sb : StringBuilder, src : TootAttachmentLike.List?) {
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, String.format(Locale.JAPAN, "Media-%d-Remote-Url: %s", i, ma.remote_url))
addAfterLine(sb, String.format(Locale.JAPAN, "Media-%d-Preview-Url: %s", i, ma.preview_url))
addAfterLine(sb, String.format(Locale.JAPAN, "Media-%d-Text-Url: %s", i, ma.text_url))
}else if( ma is TootAttachmentMSP){
addAfterLine(sb, "\n")
addAfterLine(sb, String.format(Locale.JAPAN, "Media-%d-Preview-Url: %s", i, ma.preview_url))
}
}
}
private fun encodeAccount(intent : Intent, context : Context, access_info : SavedAccount, who : TootAccount) {
val sb = StringBuilder()
intent.putExtra(EXTRA_CONTENT_START, sb.length)
sb.append(who.display_name)
sb.append("\n")
sb.append("@")
sb.append(access_info.getFullAcct(who))
sb.append("\n")
intent.putExtra(EXTRA_CONTENT_START, sb.length)
sb.append(who.url)
intent.putExtra(EXTRA_CONTENT_END, sb.length)
addAfterLine(sb, "\n")
sb.append(DecodeOptions().decodeHTML(context, access_info, who.note))
addAfterLine(sb, "\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))
addHeader(context, sb, R.string.send_header_account_url, who.url)
addHeader(context, sb, R.string.send_header_account_image_avatar, who.avatar)
addHeader(context, sb, R.string.send_header_account_image_avatar_static, who.avatar_static)
addHeader(context, sb, R.string.send_header_account_image_header, who.header)
addHeader(context, sb, R.string.send_header_account_image_header_static, who.header_static)
addHeader(context, sb, R.string.send_header_account_created_at, who.created_at)
addHeader(context, sb, R.string.send_header_account_statuses_count, who.statuses_count)
addHeader(context, sb, R.string.send_header_account_followers_count, who.followers_count)
addHeader(context, sb, R.string.send_header_account_following_count, who.following_count)
addHeader(context, sb, R.string.send_header_account_locked, who.locked)
addAfterLine(sb, "")
intent.putExtra(EXTRA_TEXT, sb.toString())
}
fun open(activity : ActMain, request_code : Int, access_info : SavedAccount, status : TootStatus) {
val intent = Intent(activity, ActText::class.java)
encodeStatus(intent, activity, access_info, status)
activity.startActivityForResult(intent, request_code)
}
fun open(activity : ActMain, request_code : Int, access_info : SavedAccount, who : TootAccount) {
val intent = Intent(activity, ActText::class.java)
encodeAccount(intent, activity, access_info, who)
activity.startActivityForResult(intent, request_code)
}
}
private lateinit var etText : EditText
private val selection : String
get() {
val s = etText.selectionStart
val e = etText.selectionEnd
val text = etText.text.toString()
return if(s == e) {
text
} else {
text.substring(s, e)
}
}
override fun onCreate(savedInstanceState : Bundle?) {
super.onCreate(savedInstanceState)
App1.setActivityTheme(this, false)
initUI()
if(savedInstanceState == null) {
val intent = intent
val sv = intent.getStringExtra(EXTRA_TEXT)
val content_start = intent.getIntExtra(EXTRA_CONTENT_START, 0)
val content_end = intent.getIntExtra(EXTRA_CONTENT_END, sv.length)
etText.setText(sv)
etText.setSelection(content_start, content_end)
}
}
internal fun initUI() {
setContentView(R.layout.act_text)
Styler.fixHorizontalMargin(findViewById(R.id.svFooterBar))
Styler.fixHorizontalMargin(findViewById(R.id.svContent))
etText = findViewById(R.id.etText)
findViewById<View>(R.id.btnCopy).setOnClickListener(this)
findViewById<View>(R.id.btnSearch).setOnClickListener(this)
findViewById<View>(R.id.btnSend).setOnClickListener(this)
findViewById<View>(R.id.btnMuteWord).setOnClickListener(this)
findViewById<View>(R.id.btnSearchMSP).setOnClickListener(this)
findViewById<View>(R.id.btnSearchTS).setOnClickListener(this)
}
override fun onClick(v : View) {
when(v.id) {
R.id.btnCopy -> copy()
R.id.btnSearch -> search()
R.id.btnSend -> send()
R.id.btnMuteWord -> muteWord()
R.id.btnSearchMSP -> searchToot(RESULT_SEARCH_MSP)
R.id.btnSearchTS -> searchToot(RESULT_SEARCH_TS)
}
}
private fun copy() {
try {
// Gets a handle to the clipboard service.
val clipboard = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager?
?: throw NotImplementedError("missing ClipboardManager system service")
// Creates a new text clip to put on the clipboard
val clip = ClipData.newPlainText("text", selection)
// Set the clipboard's primary clip.
clipboard.primaryClip = clip
Utils.showToast(this, false, R.string.copy_complete)
} catch(ex : Throwable) {
log.trace(ex)
Utils.showToast(this, ex, "copy failed.")
}
}
private fun send() {
try {
val intent = Intent()
intent.action = Intent.ACTION_SEND
intent.type = "text/plain"
intent.putExtra(Intent.EXTRA_TEXT, selection)
startActivity(intent)
} catch(ex : Throwable) {
log.trace(ex)
Utils.showToast(this, ex, "send failed.")
}
}
private fun search() {
val sv = selection
if(TextUtils.isEmpty(sv)) {
Utils.showToast(this, false, "please select search keyword")
return
}
try {
val intent = Intent(Intent.ACTION_WEB_SEARCH)
intent.putExtra(SearchManager.QUERY, sv)
if(intent.resolveActivity(packageManager) != null) {
startActivity(intent)
}
} catch(ex : Throwable) {
log.trace(ex)
Utils.showToast(this, ex, "search failed.")
}
}
private fun searchToot(resultCode : Int) {
val sv = selection
if(TextUtils.isEmpty(sv)) {
Utils.showToast(this, false, "please select search keyword")
return
}
try {
val data = Intent()
data.putExtra(Intent.EXTRA_TEXT, sv)
setResult(resultCode, data)
finish()
} catch(ex : Throwable) {
log.trace(ex)
}
}
private fun muteWord() {
try {
MutedWord.save(selection)
for(column in App1.getAppState(this).column_list) {
column.onMuteAppUpdated()
}
Utils.showToast(this, false, R.string.word_was_muted)
} catch(ex : Throwable) {
log.trace(ex)
Utils.showToast(this, ex, "muteWord failed.")
}
}
}