239 lines
7.8 KiB
Kotlin
239 lines
7.8 KiB
Kotlin
package jp.juggler.subwaytooter
|
|
|
|
import android.app.SearchManager
|
|
import android.content.Intent
|
|
import android.os.Build
|
|
import android.os.Bundle
|
|
import android.view.Menu
|
|
import android.view.MenuItem
|
|
import androidx.appcompat.app.AppCompatActivity
|
|
import jp.juggler.subwaytooter.api.entity.TootAccount
|
|
import jp.juggler.subwaytooter.api.entity.TootStatus
|
|
import jp.juggler.subwaytooter.auth.AuthRepo
|
|
import jp.juggler.subwaytooter.databinding.ActTextBinding
|
|
import jp.juggler.subwaytooter.dialog.pickAccount
|
|
import jp.juggler.subwaytooter.table.SavedAccount
|
|
import jp.juggler.subwaytooter.table.daoMutedWord
|
|
import jp.juggler.subwaytooter.table.daoSavedAccount
|
|
import jp.juggler.subwaytooter.util.CustomShare
|
|
import jp.juggler.subwaytooter.util.CustomShareTarget
|
|
import jp.juggler.subwaytooter.util.TootTextEncoder
|
|
import jp.juggler.subwaytooter.util.copyToClipboard
|
|
import jp.juggler.util.*
|
|
import jp.juggler.util.coroutine.launchAndShowError
|
|
import jp.juggler.util.coroutine.launchMain
|
|
import jp.juggler.util.data.*
|
|
import jp.juggler.util.log.LogCategory
|
|
import jp.juggler.util.log.showToast
|
|
import jp.juggler.util.ui.*
|
|
|
|
class ActText : AppCompatActivity() {
|
|
|
|
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 RESULT_SEARCH_NOTESTOCK = RESULT_FIRST_USER + 3
|
|
|
|
internal const val EXTRA_TEXT = "text"
|
|
internal const val EXTRA_CONTENT_START = "content_start"
|
|
internal const val EXTRA_CONTENT_END = "content_end"
|
|
internal const val EXTRA_ACCOUNT_DB_ID = "account_db_id"
|
|
|
|
fun createIntent(
|
|
activity: ActMain,
|
|
accessInfo: SavedAccount,
|
|
status: TootStatus,
|
|
) = Intent(activity, ActText::class.java).apply {
|
|
putExtra(EXTRA_ACCOUNT_DB_ID, accessInfo.db_id)
|
|
TootTextEncoder.encodeStatus(this, activity, accessInfo, status)
|
|
}
|
|
|
|
fun createIntent(
|
|
activity: ActMain,
|
|
accessInfo: SavedAccount,
|
|
who: TootAccount,
|
|
) = Intent(activity, ActText::class.java).apply {
|
|
putExtra(EXTRA_ACCOUNT_DB_ID, accessInfo.db_id)
|
|
TootTextEncoder.encodeAccount(this, activity, accessInfo, who)
|
|
}
|
|
}
|
|
|
|
private var account: SavedAccount? = null
|
|
|
|
private val views by lazy {
|
|
ActTextBinding.inflate(layoutInflater)
|
|
}
|
|
|
|
private val selection: String
|
|
get() {
|
|
val et = views.etText
|
|
val s = et.selectionStart
|
|
val e = et.selectionEnd
|
|
val text = et.text.toString()
|
|
return if (s == e) {
|
|
text
|
|
} else {
|
|
text.substring(s, e)
|
|
}
|
|
}
|
|
|
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
|
when (item.itemId) {
|
|
R.id.btnCopy -> selection.copyToClipboard(this)
|
|
|
|
R.id.btnSearch -> search()
|
|
|
|
R.id.btnSend -> send()
|
|
|
|
R.id.btnMuteWord -> muteWord()
|
|
|
|
R.id.btnTranslate -> CustomShare.invokeText(
|
|
CustomShareTarget.Translate,
|
|
this,
|
|
selection,
|
|
)
|
|
|
|
// MSP検索ボタン -> searchToot(RESULT_SEARCH_MSP)
|
|
// R.id.btnSearchTS -> searchToot(RESULT_SEARCH_TS)
|
|
|
|
R.id.btnSearchNotestock -> searchToot(RESULT_SEARCH_NOTESTOCK)
|
|
|
|
R.id.btnKeywordFilter -> keywordFilter()
|
|
|
|
R.id.btnHighlight -> highlight()
|
|
|
|
// If we got here, the user's action was not recognized.
|
|
// Invoke the superclass to handle it.
|
|
else -> return super.onOptionsItemSelected(item)
|
|
}
|
|
return true
|
|
}
|
|
|
|
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
|
menuInflater.inflate(R.menu.act_text, menu)
|
|
return super.onCreateOptionsMenu(menu)
|
|
}
|
|
|
|
private val authRepo by lazy {
|
|
AuthRepo(this)
|
|
}
|
|
|
|
override fun onCreate(savedInstanceState: Bundle?) {
|
|
super.onCreate(savedInstanceState)
|
|
App1.setActivityTheme(this)
|
|
|
|
initUI()
|
|
|
|
launchAndShowError {
|
|
account = intent.long(EXTRA_ACCOUNT_DB_ID)
|
|
?.let { daoSavedAccount.loadAccount(it) }
|
|
|
|
if (savedInstanceState == null) {
|
|
val sv = intent.string(EXTRA_TEXT) ?: ""
|
|
val contentStart = intent.int(EXTRA_CONTENT_START) ?: 0
|
|
val contentEnd = intent.int(EXTRA_CONTENT_END) ?: sv.length
|
|
views.etText.setText(sv)
|
|
|
|
// Android 9 以降ではフォーカスがないとsetSelectionできない
|
|
if (Build.VERSION.SDK_INT >= 28) {
|
|
views.etText.requestFocus()
|
|
views.etText.hideKeyboard()
|
|
}
|
|
|
|
views.etText.setSelection(contentStart, contentEnd)
|
|
}
|
|
}
|
|
}
|
|
|
|
internal fun initUI() {
|
|
setContentView(views.root)
|
|
setSupportActionBar(views.toolbar)
|
|
setNavigationBack(views.toolbar)
|
|
fixHorizontalMargin(views.etText)
|
|
}
|
|
|
|
private fun send() {
|
|
selection.trim().notEmpty()?.let {
|
|
try {
|
|
|
|
val intent = Intent()
|
|
intent.action = Intent.ACTION_SEND
|
|
intent.type = "text/plain"
|
|
intent.putExtra(Intent.EXTRA_TEXT, it)
|
|
startActivity(intent)
|
|
} catch (ex: Throwable) {
|
|
log.e(ex, "send failed.")
|
|
showToast(ex, "send failed.")
|
|
}
|
|
}
|
|
}
|
|
|
|
private fun search() {
|
|
selection.trim().notEmpty()?.also {
|
|
try {
|
|
val intent = Intent(Intent.ACTION_WEB_SEARCH)
|
|
intent.putExtra(SearchManager.QUERY, it)
|
|
if (intent.resolveActivity(packageManager) != null) {
|
|
startActivity(intent)
|
|
}
|
|
} catch (ex: Throwable) {
|
|
log.e(ex, "search failed.")
|
|
showToast(ex, "search failed.")
|
|
}
|
|
}
|
|
}
|
|
|
|
private fun searchToot(@Suppress("SameParameterValue") resultCode: Int) {
|
|
selection.trim().notEmpty()?.let {
|
|
try {
|
|
val data = Intent()
|
|
data.putExtra(Intent.EXTRA_TEXT, it)
|
|
setResult(resultCode, data)
|
|
finish()
|
|
} catch (ex: Throwable) {
|
|
log.e(ex, "searchToot failed.")
|
|
showToast(ex, "searchToot failed.")
|
|
}
|
|
}
|
|
}
|
|
|
|
private fun muteWord() {
|
|
launchAndShowError {
|
|
selection.trim().notEmpty()?.let {
|
|
daoMutedWord.save(it)
|
|
App1.getAppState(this@ActText).onMuteUpdated()
|
|
showToast(false, R.string.word_was_muted)
|
|
}
|
|
}
|
|
}
|
|
|
|
private fun keywordFilter() {
|
|
selection.trim().notEmpty()?.let { text ->
|
|
val account = this.account
|
|
if (account?.isPseudo == false && account.isMastodon) {
|
|
ActKeywordFilter.open(this, account, initialPhrase = text)
|
|
} else {
|
|
launchMain {
|
|
pickAccount(
|
|
bAllowPseudo = false,
|
|
bAllowMisskey = false,
|
|
bAllowMastodon = true,
|
|
bAuto = false,
|
|
)?.let {
|
|
ActKeywordFilter.open(this@ActText, it, initialPhrase = text)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private fun highlight() {
|
|
selection.trim().notEmpty()?.let {
|
|
startActivity(ActHighlightWordEdit.createIntent(this, it))
|
|
}
|
|
}
|
|
}
|