improve IDN domain support
This commit is contained in:
parent
9b696c60f1
commit
23fb9cec43
|
@ -119,7 +119,6 @@ class ActAccountSetting
|
|||
|
||||
private lateinit var tvUserCustom : TextView
|
||||
private lateinit var btnUserCustom : View
|
||||
private lateinit var full_acct : String
|
||||
|
||||
private lateinit var btnNotificationSoundEdit : Button
|
||||
private lateinit var btnNotificationSoundReset : Button
|
||||
|
@ -173,13 +172,13 @@ class ActAccountSetting
|
|||
finish()
|
||||
return
|
||||
}
|
||||
this.account = a
|
||||
|
||||
loadUIFromData(account)
|
||||
|
||||
loadUIFromData(a)
|
||||
|
||||
initializeProfile()
|
||||
|
||||
btnOpenBrowser.text = getString(R.string.open_instance_website, account.host)
|
||||
btnOpenBrowser.text = getString(R.string.open_instance_website, account.hostAscii)
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
|
@ -443,11 +442,10 @@ class ActAccountSetting
|
|||
}
|
||||
|
||||
private fun loadUIFromData(a : SavedAccount) {
|
||||
this.account = a
|
||||
|
||||
this.full_acct = a.acct
|
||||
|
||||
tvInstance.text = a.host
|
||||
tvUser.text = a.acct
|
||||
tvInstance.text = a.hostPretty
|
||||
tvUser.text = a.acctPretty
|
||||
|
||||
this.visibility = a.visibility
|
||||
|
||||
|
@ -518,9 +516,10 @@ class ActAccountSetting
|
|||
}
|
||||
|
||||
private fun showAcctColor() {
|
||||
val ac = AcctColor.load(full_acct)
|
||||
val sa = this.account
|
||||
val ac = AcctColor.load(sa.acctAscii)
|
||||
tvUserCustom.backgroundColor = ac.color_bg
|
||||
tvUserCustom.text = ac.nickname?.notEmpty() ?: full_acct
|
||||
tvUserCustom.text = ac.nickname?.notEmpty() ?: sa.acctPretty
|
||||
tvUserCustom.textColor = ac.color_fg.notZero()
|
||||
?: getAttributeColor(this, R.attr.colorTimeSmall)
|
||||
}
|
||||
|
@ -584,13 +583,14 @@ class ActAccountSetting
|
|||
R.id.btnVisibility -> performVisibility()
|
||||
R.id.btnOpenBrowser -> App1.openBrowser(
|
||||
this@ActAccountSetting,
|
||||
"https://" + account.host + "/"
|
||||
"https://" + account.hostAscii + "/"
|
||||
)
|
||||
R.id.btnPushSubscription -> startTest()
|
||||
|
||||
R.id.btnUserCustom -> ActNickname.open(
|
||||
this,
|
||||
full_acct,
|
||||
account.acctAscii,
|
||||
account.acctPretty,
|
||||
false,
|
||||
REQUEST_CODE_ACCT_CUSTOMIZE
|
||||
)
|
||||
|
@ -764,7 +764,7 @@ class ActAccountSetting
|
|||
}
|
||||
|
||||
val call = App1.ok_http_client.newCall(
|
||||
("instance_url=" + ("https://" + account.host).encodePercent()
|
||||
("instance_url=" + ("https://" + account.hostAscii).encodePercent()
|
||||
+ "&app_id=" + packageName.encodePercent()
|
||||
+ "&tag=" + tag
|
||||
)
|
||||
|
|
|
@ -913,14 +913,14 @@ class ActAppSetting : AppCompatActivity(), ColorPickerDialogListener, View.OnCli
|
|||
|
||||
fun formatFontSize(fv : Float) : String =
|
||||
when {
|
||||
fv.isFinite() -> String.format(Locale.getDefault(), "%.1f", fv)
|
||||
fv.isFinite() -> String.format(defaultLocale(this), "%.1f", fv)
|
||||
else -> ""
|
||||
}
|
||||
|
||||
fun parseFontSize(src : String) : Float {
|
||||
try {
|
||||
if(src.isNotEmpty()) {
|
||||
val f = NumberFormat.getInstance(Locale.getDefault()).parse(src)?.toFloat()
|
||||
val f = NumberFormat.getInstance(defaultLocale(this)).parse(src)?.toFloat()
|
||||
return when {
|
||||
f == null -> Float.NaN
|
||||
f.isNaN() -> Float.NaN
|
||||
|
|
|
@ -351,7 +351,7 @@ class ActColumnCustomize : AppCompatActivity(), View.OnClickListener, ColorPicke
|
|||
ivColumnBackground.alpha = column.column_bg_image_alpha
|
||||
etAlpha.setText(
|
||||
String.format(
|
||||
Locale.getDefault(),
|
||||
defaultLocale(this@ActColumnCustomize),
|
||||
"%.4f",
|
||||
column.column_bg_image_alpha
|
||||
)
|
||||
|
@ -379,7 +379,7 @@ class ActColumnCustomize : AppCompatActivity(), View.OnClickListener, ColorPicke
|
|||
if(loading_busy) return
|
||||
try {
|
||||
|
||||
var f = NumberFormat.getInstance(Locale.getDefault())
|
||||
var f = NumberFormat.getInstance(defaultLocale(this@ActColumnCustomize))
|
||||
.parse(etAlpha.text.toString())?.toFloat()
|
||||
|
||||
if(f != null && ! f.isNaN()) {
|
||||
|
@ -426,7 +426,7 @@ class ActColumnCustomize : AppCompatActivity(), View.OnClickListener, ColorPicke
|
|||
|
||||
etAlpha.setText(
|
||||
String.format(
|
||||
Locale.getDefault(),
|
||||
defaultLocale(this@ActColumnCustomize),
|
||||
"%.4f",
|
||||
column.column_bg_image_alpha
|
||||
)
|
||||
|
|
|
@ -221,7 +221,7 @@ class ActKeywordFilter
|
|||
private fun save() {
|
||||
if(loading) return
|
||||
|
||||
val params = jsonObject{
|
||||
val params = jsonObject {
|
||||
|
||||
put("phrase", etPhrase.text.toString())
|
||||
|
||||
|
@ -254,7 +254,7 @@ class ActKeywordFilter
|
|||
filter_expire <= 0L -> {
|
||||
}
|
||||
// FIXME: currently there is no way to remove expires from existing filter.
|
||||
else -> put("expires_in", Int.MAX_VALUE)
|
||||
else -> put("expires_in", Int.MAX_VALUE)
|
||||
}
|
||||
|
||||
// set seconds
|
||||
|
@ -285,9 +285,7 @@ class ActKeywordFilter
|
|||
} else {
|
||||
val app_state = App1.prepare(applicationContext)
|
||||
for(column in app_state.column_list) {
|
||||
if(column.access_info.acct == account.acct
|
||||
&& column.type == ColumnType.KEYWORD_FILTER
|
||||
) {
|
||||
if(column.type == ColumnType.KEYWORD_FILTER && column.access_info == account) {
|
||||
column.filter_reload_required = true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -124,7 +124,7 @@ class ActMain : AppCompatActivity()
|
|||
|
||||
// onActivityResultで設定されてonResumeで消化される
|
||||
// 状態保存の必要なし
|
||||
private var posted_acct : String? = null
|
||||
private var posted_acct : String? = null // acctAscii
|
||||
private var posted_status_id : EntityId? = null
|
||||
private var posted_reply_id : EntityId? = null
|
||||
private var posted_redraft_id : EntityId? = null
|
||||
|
@ -401,7 +401,7 @@ class ActMain : AppCompatActivity()
|
|||
break
|
||||
}
|
||||
// 既出でなければ追加する
|
||||
if(null == accounts.find { it.acct == a.acct }) accounts.add(a)
|
||||
if(null == accounts.find { it.acctAscii == a.acctAscii }) accounts.add(a)
|
||||
} catch(ex : Throwable) {
|
||||
|
||||
}
|
||||
|
@ -795,7 +795,7 @@ class ActMain : AppCompatActivity()
|
|||
when {
|
||||
column.access_info.isNA -> post_helper.setInstance(null, false)
|
||||
else -> post_helper.setInstance(
|
||||
column.access_info.host,
|
||||
column.access_info.hostAscii,
|
||||
column.access_info.isMisskey
|
||||
)
|
||||
}
|
||||
|
@ -865,7 +865,7 @@ class ActMain : AppCompatActivity()
|
|||
// 予約投稿なら予約投稿リストをリロードする
|
||||
for(column in app_state.column_list) {
|
||||
if(column.type == ColumnType.SCHEDULED_STATUS
|
||||
&& column.access_info.acct == posted_acct
|
||||
&& column.access_info.acctAscii == posted_acct
|
||||
) {
|
||||
column.startLoading()
|
||||
}
|
||||
|
@ -888,7 +888,7 @@ class ActMain : AppCompatActivity()
|
|||
val refresh_after_toot = Pref.ipRefreshAfterToot(pref)
|
||||
if(refresh_after_toot != Pref.RAT_DONT_REFRESH) {
|
||||
for(column in app_state.column_list) {
|
||||
if(column.access_info.acct != posted_acct) continue
|
||||
if(column.access_info.acctAscii != posted_acct) continue
|
||||
column.startRefreshForPost(
|
||||
refresh_after_toot,
|
||||
posted_status_id,
|
||||
|
@ -967,7 +967,7 @@ class ActMain : AppCompatActivity()
|
|||
post_helper.in_reply_to_id = null
|
||||
post_helper.attachment_list = null
|
||||
post_helper.emojiMapCustom =
|
||||
App1.custom_emoji_lister.getMap(account.host, account.isMisskey)
|
||||
App1.custom_emoji_lister.getMap(account.hostAscii, account.isMisskey)
|
||||
|
||||
|
||||
etQuickToot.hideKeyboard()
|
||||
|
@ -978,7 +978,7 @@ class ActMain : AppCompatActivity()
|
|||
status : TootStatus
|
||||
) {
|
||||
etQuickToot.setText("")
|
||||
posted_acct = target_account.acct
|
||||
posted_acct = target_account.acctAscii
|
||||
posted_status_id = status.id
|
||||
posted_reply_id = status.in_reply_to_id
|
||||
posted_redraft_id = null
|
||||
|
@ -1600,7 +1600,7 @@ class ActMain : AppCompatActivity()
|
|||
ivIcon.imageTintList = ColorStateList.valueOf(column.getHeaderNameColor())
|
||||
|
||||
//
|
||||
val ac = AcctColor.load(column.access_info.acct)
|
||||
val ac = AcctColor.load(column.access_info.acctAscii)
|
||||
if(AcctColor.hasColorForeground(ac)) {
|
||||
vAcctColor.setBackgroundColor(ac.color_fg)
|
||||
} else {
|
||||
|
@ -1829,7 +1829,7 @@ class ActMain : AppCompatActivity()
|
|||
if(account != null) {
|
||||
var column = app_state.column_list.firstOrNull {
|
||||
it.type == ColumnType.NOTIFICATIONS
|
||||
&& account.acct == it.access_info.acct
|
||||
&& account.acctAscii == it.access_info.acctAscii
|
||||
&& ! it.system_notification_not_related
|
||||
}
|
||||
if(column != null) {
|
||||
|
@ -2029,7 +2029,7 @@ class ActMain : AppCompatActivity()
|
|||
if(sa.username != ta.username) {
|
||||
showToast(this@ActMain, true, R.string.user_name_not_match)
|
||||
} else {
|
||||
showToast(this@ActMain, false, R.string.access_token_updated_for, sa.acct)
|
||||
showToast(this@ActMain, false, R.string.access_token_updated_for, sa.acctPretty)
|
||||
|
||||
// DBの情報を更新する
|
||||
sa.updateTokenInfo(token_info)
|
||||
|
@ -2039,7 +2039,7 @@ class ActMain : AppCompatActivity()
|
|||
|
||||
// 自動でリロードする
|
||||
for(it in app_state.column_list) {
|
||||
if(it.access_info.acct == sa.acct) {
|
||||
if(it.access_info.acctAscii == sa.acctAscii) {
|
||||
it.startLoading()
|
||||
}
|
||||
}
|
||||
|
@ -2156,7 +2156,7 @@ class ActMain : AppCompatActivity()
|
|||
null,
|
||||
object : DlgTextInput.Callback {
|
||||
override fun onOK(dialog : Dialog, text : String) {
|
||||
checkAccessToken(null, dialog, sa.host, text, sa)
|
||||
checkAccessToken(null, dialog, sa.hostAscii, text, sa)
|
||||
}
|
||||
|
||||
override fun onEmptyError() {
|
||||
|
@ -2180,7 +2180,7 @@ class ActMain : AppCompatActivity()
|
|||
val done_list = ArrayList<SavedAccount>()
|
||||
for(column in app_state.column_list) {
|
||||
val a = column.access_info
|
||||
if(a.acct != account.acct) continue
|
||||
if(a.acctAscii != account.acctAscii) continue
|
||||
if(done_list.contains(a)) continue
|
||||
done_list.add(a)
|
||||
if(! a.isNA) a.reloadSetting(this@ActMain)
|
||||
|
@ -2361,7 +2361,7 @@ class ActMain : AppCompatActivity()
|
|||
if(statusInfo != null) {
|
||||
if(accessInfo.isNA ||
|
||||
statusInfo.statusId == null ||
|
||||
! statusInfo.host.equals(accessInfo.host, ignoreCase = true)
|
||||
! statusInfo.host.equals(accessInfo.hostAscii, ignoreCase = true)
|
||||
) {
|
||||
Action_Toot.conversationOtherInstance(
|
||||
this@ActMain,
|
||||
|
@ -2385,7 +2385,7 @@ class ActMain : AppCompatActivity()
|
|||
// opener.linkInfo をチェックしてメンションを判別する
|
||||
val mention = opener.linkInfo?.mention
|
||||
if(mention != null) {
|
||||
val fullAcct = getFullAcctOrNull(accessInfo, mention.acct, mention.url)
|
||||
val fullAcct = getFullAcctOrNull(accessInfo, mention.acctAscii, mention.url)
|
||||
if(fullAcct != null) {
|
||||
val (user, host) = fullAcct.splitFullAcct()
|
||||
if(host != null) {
|
||||
|
@ -2487,7 +2487,7 @@ class ActMain : AppCompatActivity()
|
|||
|
||||
fun showColumnMatchAccount(account : SavedAccount) {
|
||||
for(column in app_state.column_list) {
|
||||
if(account.acct == column.access_info.acct) {
|
||||
if(account.acctAscii == column.access_info.acctAscii) {
|
||||
column.fireRebindAdapterItems()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,18 +25,21 @@ class ActNickname : AppCompatActivity(), View.OnClickListener, ColorPickerDialog
|
|||
|
||||
companion object {
|
||||
|
||||
internal const val EXTRA_ACCT = "acct"
|
||||
internal const val EXTRA_ACCT_ASCII = "acctAscii"
|
||||
internal const val EXTRA_ACCT_PRETTY = "acctPretty"
|
||||
internal const val EXTRA_SHOW_NOTIFICATION_SOUND = "show_notification_sound"
|
||||
internal const val REQUEST_CODE_NOTIFICATION_SOUND = 2
|
||||
|
||||
fun open(
|
||||
activity : Activity,
|
||||
full_acct : String,
|
||||
fullAcctAscii : String,
|
||||
fullAcctPretty: String,
|
||||
bShowNotificationSound : Boolean,
|
||||
requestCode : Int
|
||||
) {
|
||||
val intent = Intent(activity, ActNickname::class.java)
|
||||
intent.putExtra(EXTRA_ACCT, full_acct)
|
||||
intent.putExtra(EXTRA_ACCT_ASCII, fullAcctAscii)
|
||||
intent.putExtra(EXTRA_ACCT_PRETTY, fullAcctPretty)
|
||||
intent.putExtra(EXTRA_SHOW_NOTIFICATION_SOUND, bShowNotificationSound)
|
||||
activity.startActivityForResult(intent, requestCode)
|
||||
}
|
||||
|
@ -44,7 +47,8 @@ class ActNickname : AppCompatActivity(), View.OnClickListener, ColorPickerDialog
|
|||
}
|
||||
|
||||
private var show_notification_sound : Boolean = false
|
||||
private lateinit var acct : String
|
||||
private lateinit var acctAscii : String
|
||||
private lateinit var acctPretty : String
|
||||
private var color_fg : Int = 0
|
||||
private var color_bg : Int = 0
|
||||
private var notification_sound_uri : String? = null
|
||||
|
@ -73,7 +77,8 @@ class ActNickname : AppCompatActivity(), View.OnClickListener, ColorPickerDialog
|
|||
App1.setActivityTheme(this)
|
||||
|
||||
val intent = intent
|
||||
this.acct = intent.getStringExtra(EXTRA_ACCT) !!
|
||||
this.acctAscii = intent.getStringExtra(EXTRA_ACCT_ASCII) !!
|
||||
this.acctPretty = intent.getStringExtra(EXTRA_ACCT_PRETTY) !!
|
||||
this.show_notification_sound = intent.getBooleanExtra(EXTRA_SHOW_NOTIFICATION_SOUND, false)
|
||||
|
||||
initUI()
|
||||
|
@ -148,9 +153,9 @@ class ActNickname : AppCompatActivity(), View.OnClickListener, ColorPickerDialog
|
|||
findViewById<View>(R.id.llNotificationSound).visibility =
|
||||
if(show_notification_sound) View.VISIBLE else View.GONE
|
||||
|
||||
tvAcct.text = acct
|
||||
tvAcct.text = acctPretty
|
||||
|
||||
val ac = AcctColor.load(acct)
|
||||
val ac = AcctColor.load(acctAscii)
|
||||
color_bg = ac.color_bg
|
||||
color_fg = ac.color_fg
|
||||
etNickname.setText(if(ac.nickname == null) "" else ac.nickname)
|
||||
|
@ -163,7 +168,7 @@ class ActNickname : AppCompatActivity(), View.OnClickListener, ColorPickerDialog
|
|||
private fun save() {
|
||||
if(bLoading) return
|
||||
AcctColor(
|
||||
acct,
|
||||
acctAscii,
|
||||
etNickname.text.toString().trim { it <= ' ' },
|
||||
color_fg,
|
||||
color_bg,
|
||||
|
@ -173,7 +178,7 @@ class ActNickname : AppCompatActivity(), View.OnClickListener, ColorPickerDialog
|
|||
|
||||
private fun show() {
|
||||
val s = etNickname.text.toString().trim { it <= ' ' }
|
||||
tvPreview.text = s.notEmpty() ?: acct
|
||||
tvPreview.text = s.notEmpty() ?: acctPretty
|
||||
tvPreview.textColor = color_fg.notZero() ?: getAttributeColor(this, R.attr.colorTimeSmall)
|
||||
tvPreview.backgroundColor = color_bg
|
||||
}
|
||||
|
|
|
@ -507,7 +507,7 @@ class ActPost : AppCompatActivity(),
|
|||
R.id.btnPlugin -> openMushroom()
|
||||
R.id.btnEmojiPicker -> post_helper.openEmojiPickerFromMore()
|
||||
R.id.btnFeaturedTag -> post_helper.openFeaturedTagList(
|
||||
featuredTagCache[account?.acct ?: ""]?.list
|
||||
featuredTagCache[account?.acctAscii ?: ""]?.list
|
||||
)
|
||||
R.id.ibSchedule -> performSchedule()
|
||||
R.id.ibScheduleReset -> resetSchedule()
|
||||
|
@ -774,7 +774,7 @@ class ActPost : AppCompatActivity(),
|
|||
|
||||
// 元レスに含まれていたメンションを複製
|
||||
reply_status.mentions?.forEach { mention ->
|
||||
val who_acct = mention.acct
|
||||
val who_acct = mention.acctAscii
|
||||
// 空データなら追加しない
|
||||
if(who_acct.isEmpty()) return@forEach
|
||||
// 自分なら追加しない
|
||||
|
@ -783,6 +783,12 @@ class ActPost : AppCompatActivity(),
|
|||
// 既出なら追加しない
|
||||
if(mention_list.contains(strMention)) return@forEach
|
||||
mention_list.add(strMention)
|
||||
|
||||
/*
|
||||
FIXME インスタンスのバージョンが3.1.0 以降ならメンションのホスト部分にIDNドメインを使いたいが、
|
||||
投稿画面でのアカウント切り替え時にタンスのバージョンが異なると破綻する可能性が高い。
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
if(mention_list.isNotEmpty()) {
|
||||
|
@ -1299,7 +1305,7 @@ class ActPost : AppCompatActivity(),
|
|||
|
||||
else -> {
|
||||
// インスタンス情報を確認する
|
||||
val info = TootInstance.getCached(account.host)
|
||||
val info = TootInstance.getCached(account.hostAscii)
|
||||
if(info == null || info.isExpire) {
|
||||
// 情報がないか古いなら再取得
|
||||
|
||||
|
@ -1390,6 +1396,7 @@ class ActPost : AppCompatActivity(),
|
|||
val time : Long
|
||||
)
|
||||
|
||||
// key is SavedfAccount.acctAscii
|
||||
private val featuredTagCache = ConcurrentHashMap<String, FeaturedTagCache>()
|
||||
private var lastFeaturedTagTask : TootTaskRunner? = null
|
||||
|
||||
|
@ -1401,7 +1408,7 @@ class ActPost : AppCompatActivity(),
|
|||
return
|
||||
}
|
||||
|
||||
val cache = featuredTagCache[account.acct]
|
||||
val cache = featuredTagCache[account.acctAscii]
|
||||
|
||||
btnFeaturedTag.vg(cache?.list?.isNotEmpty() == true)
|
||||
|
||||
|
@ -1417,13 +1424,13 @@ class ActPost : AppCompatActivity(),
|
|||
|
||||
override fun background(client : TootApiClient) : TootApiResult? {
|
||||
return if(account.isMisskey) {
|
||||
featuredTagCache[account.acct] =
|
||||
featuredTagCache[account.acctAscii] =
|
||||
FeaturedTagCache(emptyList(), SystemClock.elapsedRealtime())
|
||||
TootApiResult()
|
||||
} else {
|
||||
client.request("/api/v1/featured_tags")?.also { result ->
|
||||
val list = parseList(::TootTag, result.jsonArray)
|
||||
featuredTagCache[account.acct] =
|
||||
featuredTagCache[account.acctAscii] =
|
||||
FeaturedTagCache(list, SystemClock.elapsedRealtime())
|
||||
}
|
||||
}
|
||||
|
@ -1449,16 +1456,15 @@ class ActPost : AppCompatActivity(),
|
|||
btnAccount.setTextColor(getAttributeColor(this, android.R.attr.textColorPrimary))
|
||||
btnAccount.setBackgroundResource(R.drawable.btn_bg_transparent)
|
||||
} else {
|
||||
post_helper.setInstance(a.host, a.isMisskey)
|
||||
post_helper.setInstance(a.hostAscii, a.isMisskey)
|
||||
|
||||
// 先読みしてキャッシュに保持しておく
|
||||
App1.custom_emoji_lister.getList(a.host, a.isMisskey) {
|
||||
App1.custom_emoji_lister.getList(a.hostAscii, a.isMisskey) {
|
||||
// 何もしない
|
||||
}
|
||||
|
||||
val acct = a.acct
|
||||
val ac = AcctColor.load(acct)
|
||||
val nickname = if(AcctColor.hasNickname(ac)) ac.nickname else acct
|
||||
val ac = AcctColor.load(a.acctAscii)
|
||||
val nickname = if(AcctColor.hasNickname(ac)) ac.nickname else a.acctPretty
|
||||
btnAccount.text = nickname
|
||||
|
||||
if(AcctColor.hasColorBackground(ac)) {
|
||||
|
@ -1502,7 +1508,7 @@ class ActPost : AppCompatActivity(),
|
|||
) { ai ->
|
||||
|
||||
// 別タンスのアカウントに変更したならならin_reply_toの変換が必要
|
||||
if(in_reply_to_id != null && ! ai.host.equals(account?.host, ignoreCase = true)) {
|
||||
if(in_reply_to_id != null && ! ai.matchHost(account?.hostAscii) ) {
|
||||
startReplyConversion(ai)
|
||||
} else {
|
||||
setAccountWithVisibilityConversion(ai)
|
||||
|
@ -2031,7 +2037,7 @@ class ActPost : AppCompatActivity(),
|
|||
return
|
||||
}
|
||||
|
||||
val instance = TootInstance.getCached(account.host)
|
||||
val instance = TootInstance.getCached(account.hostAscii)
|
||||
if(instance?.instanceType == TootInstance.InstanceType.Pixelfed) {
|
||||
if(in_reply_to_id != null) {
|
||||
showToast(this, true, R.string.pixelfed_does_not_allow_reply_with_media)
|
||||
|
@ -2569,7 +2575,7 @@ class ActPost : AppCompatActivity(),
|
|||
post_helper.attachment_list = this.attachment_list
|
||||
|
||||
post_helper.emojiMapCustom =
|
||||
App1.custom_emoji_lister.getMap(account.host, account.isMisskey)
|
||||
App1.custom_emoji_lister.getMap(account.hostAscii, account.isMisskey)
|
||||
|
||||
post_helper.redraft_status_id = redraft_status_id
|
||||
|
||||
|
@ -2585,7 +2591,7 @@ class ActPost : AppCompatActivity(),
|
|||
status : TootStatus
|
||||
) {
|
||||
val data = Intent()
|
||||
data.putExtra(EXTRA_POSTED_ACCT, target_account.acct)
|
||||
data.putExtra(EXTRA_POSTED_ACCT, target_account.acctAscii)
|
||||
status.id.putTo(data, EXTRA_POSTED_STATUS_ID)
|
||||
redraft_status_id?.putTo(data, EXTRA_POSTED_REDRAFT_ID)
|
||||
status.in_reply_to_id?.putTo(data, EXTRA_POSTED_REPLY_ID)
|
||||
|
@ -2597,7 +2603,7 @@ class ActPost : AppCompatActivity(),
|
|||
override fun onScheduledPostComplete(target_account : SavedAccount) {
|
||||
showToast(this@ActPost, false, getString(R.string.scheduled_status_sent))
|
||||
val data = Intent()
|
||||
data.putExtra(EXTRA_POSTED_ACCT, target_account.acct)
|
||||
data.putExtra(EXTRA_POSTED_ACCT, target_account.acctAscii)
|
||||
setResult(RESULT_OK, data)
|
||||
isPostComplete = true
|
||||
this@ActPost.finish()
|
||||
|
|
|
@ -301,47 +301,47 @@ class AppState(internal val context : Context, internal val pref : SharedPrefere
|
|||
}
|
||||
|
||||
fun isBusyFav(account : SavedAccount, status : TootStatus) : Boolean {
|
||||
val key = account.acct + ":" + status.busyKey
|
||||
val key = account.acctAscii + ":" + status.busyKey
|
||||
return map_busy_fav.contains(key)
|
||||
}
|
||||
|
||||
fun setBusyFav(account : SavedAccount, status : TootStatus) {
|
||||
val key = account.acct + ":" + status.busyKey
|
||||
val key = account.acctAscii + ":" + status.busyKey
|
||||
map_busy_fav.add(key)
|
||||
}
|
||||
|
||||
fun resetBusyFav(account : SavedAccount, status : TootStatus) {
|
||||
val key = account.acct + ":" + status.busyKey
|
||||
val key = account.acctAscii + ":" + status.busyKey
|
||||
map_busy_fav.remove(key)
|
||||
}
|
||||
|
||||
fun isBusyBookmark(account : SavedAccount, status : TootStatus) : Boolean {
|
||||
val key = account.acct + ":" + status.busyKey
|
||||
val key = account.acctAscii + ":" + status.busyKey
|
||||
return map_busy_bookmark.contains(key)
|
||||
}
|
||||
|
||||
fun setBusyBookmark(account : SavedAccount, status : TootStatus) {
|
||||
val key = account.acct + ":" + status.busyKey
|
||||
val key = account.acctAscii + ":" + status.busyKey
|
||||
map_busy_bookmark.add(key)
|
||||
}
|
||||
|
||||
fun resetBusyBookmark(account : SavedAccount, status : TootStatus) {
|
||||
val key = account.acct + ":" + status.busyKey
|
||||
val key = account.acctAscii + ":" + status.busyKey
|
||||
map_busy_bookmark.remove(key)
|
||||
}
|
||||
|
||||
fun isBusyBoost(account : SavedAccount, status : TootStatus) : Boolean {
|
||||
val key = account.acct + ":" + status.busyKey
|
||||
val key = account.acctAscii + ":" + status.busyKey
|
||||
return map_busy_boost.contains(key)
|
||||
}
|
||||
|
||||
fun setBusyBoost(account : SavedAccount, status : TootStatus) {
|
||||
val key = account.acct + ":" + status.busyKey
|
||||
val key = account.acctAscii + ":" + status.busyKey
|
||||
map_busy_boost.add(key)
|
||||
}
|
||||
|
||||
fun resetBusyBoost(account : SavedAccount, status : TootStatus) {
|
||||
val key = account.acct + ":" + status.busyKey
|
||||
val key = account.acctAscii + ":" + status.busyKey
|
||||
map_busy_boost.remove(key)
|
||||
}
|
||||
|
||||
|
@ -400,7 +400,7 @@ class AppState(internal val context : Context, internal val pref : SharedPrefere
|
|||
if(voice_set == null || voice_set.isEmpty()) {
|
||||
log.d("TextToSpeech.getVoices returns null or empty set.")
|
||||
} else {
|
||||
val lang = Locale.getDefault().toLanguageTag()
|
||||
val lang = defaultLocale(context).toLanguageTag()
|
||||
for(v in voice_set) {
|
||||
log.d(
|
||||
"Voice %s %s %s",
|
||||
|
|
|
@ -263,10 +263,9 @@ class Column(
|
|||
override fun handleResult(result : TootApiResult?) {
|
||||
val filter_list = this.filter_list
|
||||
if(filter_list != null) {
|
||||
val stream_acct = access_info.acct
|
||||
log.d("update filters for $stream_acct")
|
||||
log.d("update filters for ${access_info.acctAscii}")
|
||||
for(column in App1.getAppState(context).column_list) {
|
||||
if(column.access_info.acct == stream_acct) {
|
||||
if(column.access_info == access_info) {
|
||||
column.onFiltersChanged2(filter_list)
|
||||
}
|
||||
}
|
||||
|
@ -361,8 +360,7 @@ class Column(
|
|||
|
||||
val type = ColumnType.parse(typeId)
|
||||
|
||||
fun getIconId() : Int =
|
||||
type.iconId(access_info.acct)
|
||||
fun getIconId() : Int = type.iconId(access_info.acctAscii)
|
||||
|
||||
fun getColumnName(long : Boolean) =
|
||||
type.name2(this, long) ?: type.name1(context)
|
||||
|
@ -903,8 +901,8 @@ class Column(
|
|||
}
|
||||
|
||||
// 以下は保存には必要ないが、カラムリスト画面で使う
|
||||
val ac = AcctColor.load(access_info.acct)
|
||||
dst[KEY_COLUMN_ACCESS] = if(AcctColor.hasNickname(ac)) ac.nickname else access_info.acct
|
||||
val ac = AcctColor.load(access_info.acctAscii)
|
||||
dst[KEY_COLUMN_ACCESS] = if(AcctColor.hasNickname(ac)) ac.nickname else access_info.acctPretty
|
||||
dst[KEY_COLUMN_ACCESS_COLOR] = ac.color_fg
|
||||
dst[KEY_COLUMN_ACCESS_COLOR_BG] = ac.color_bg
|
||||
dst[KEY_COLUMN_NAME] = getColumnName(true)
|
||||
|
@ -916,7 +914,7 @@ class Column(
|
|||
type : ColumnType,
|
||||
params : Array<out Any>
|
||||
) : Boolean {
|
||||
if(type != this.type || ai.acct != access_info.acct) return false
|
||||
if(type != this.type || ai != access_info) return false
|
||||
|
||||
return try {
|
||||
when(type) {
|
||||
|
@ -1038,7 +1036,7 @@ class Column(
|
|||
callback : (account : SavedAccount, status : TootStatus) -> Boolean
|
||||
// callback return true if rebind view required
|
||||
) {
|
||||
if(! access_info.host.equals(target_instance, ignoreCase = true)) return
|
||||
if(! access_info.matchHost(target_instance)) return
|
||||
|
||||
var bChanged = false
|
||||
|
||||
|
@ -1068,7 +1066,7 @@ class Column(
|
|||
who_id : EntityId,
|
||||
removeFromUserList : Boolean = false
|
||||
) {
|
||||
if(target_account.acct != access_info.acct) return
|
||||
if(target_account != access_info) return
|
||||
|
||||
val INVALID_ACCOUNT = - 1L
|
||||
|
||||
|
@ -1121,13 +1119,13 @@ class Column(
|
|||
|
||||
// misskeyカラムやプロフカラムでブロック成功した時に呼ばれる
|
||||
fun updateFollowIcons(target_account : SavedAccount) {
|
||||
if(target_account.acct != access_info.acct) return
|
||||
if(target_account != access_info) return
|
||||
|
||||
fireShowContent(reason = "updateFollowIcons", reset = true)
|
||||
}
|
||||
|
||||
fun removeUser(targetAccount : SavedAccount, columnType : ColumnType, who_id : EntityId) {
|
||||
if(type == columnType && targetAccount.acct == access_info.acct) {
|
||||
if(type == columnType && targetAccount == access_info ) {
|
||||
val tmp_list = ArrayList<TimelineItem>(list_data.size)
|
||||
for(o in list_data) {
|
||||
if(o is TootAccountRef) {
|
||||
|
@ -1148,7 +1146,7 @@ class Column(
|
|||
|
||||
if(is_dispose.get() || bInitialLoading || bRefreshLoading) return
|
||||
|
||||
if(tl_host.equals(access_info.host, ignoreCase = true)) {
|
||||
if(tl_host.equals(access_info.hostAscii, ignoreCase = true)) {
|
||||
val tmp_list = ArrayList<TimelineItem>(list_data.size)
|
||||
for(o in list_data) {
|
||||
if(o is TootStatus) {
|
||||
|
@ -1203,7 +1201,7 @@ class Column(
|
|||
fun removeNotificationOne(target_account : SavedAccount, notification : TootNotification) {
|
||||
if(! isNotificationColumn) return
|
||||
|
||||
if(access_info.acct != target_account.acct) return
|
||||
if(access_info != target_account) return
|
||||
|
||||
val tmp_list = ArrayList<TimelineItem>(list_data.size)
|
||||
for(o in list_data) {
|
||||
|
@ -1268,7 +1266,7 @@ class Column(
|
|||
|
||||
val domain = IDN.toASCII(domainArg,IDN.ALLOW_UNASSIGNED)
|
||||
|
||||
if(target_account.host != access_info.host) return
|
||||
if(target_account.hostAscii != access_info.hostAscii) return
|
||||
if(access_info.isPseudo) return
|
||||
|
||||
if(type == ColumnType.DOMAIN_BLOCKS) {
|
||||
|
@ -1281,7 +1279,7 @@ class Column(
|
|||
// ブロックしたのとドメイン部分が一致するアカウントからのステータスと通知をすべて除去する
|
||||
val reDomain = Pattern.compile("\\A[^@]+@\\Q$domain\\E\\z", Pattern.CASE_INSENSITIVE)
|
||||
val checker =
|
||||
{ account : TootAccount? -> if(account == null ) false else reDomain.matcher(account.acct).find() }
|
||||
{ account : TootAccount? -> if(account == null ) false else reDomain.matcher(account.acctAscii).find() }
|
||||
|
||||
val tmp_list = ArrayList<TimelineItem>(list_data.size)
|
||||
|
||||
|
@ -1307,7 +1305,7 @@ class Column(
|
|||
}
|
||||
|
||||
fun onListListUpdated(account : SavedAccount) {
|
||||
if(type == ColumnType.LIST_LIST && access_info.acct == account.acct) {
|
||||
if(type == ColumnType.LIST_LIST && access_info == account) {
|
||||
startLoading()
|
||||
val vh = viewHolder
|
||||
vh?.onListListUpdated()
|
||||
|
@ -1315,7 +1313,7 @@ class Column(
|
|||
}
|
||||
|
||||
fun onListNameUpdated(account : SavedAccount, item : TootList) {
|
||||
if(access_info.acct != account.acct) return
|
||||
if(access_info != account) return
|
||||
when(type) {
|
||||
ColumnType.LIST_LIST -> {
|
||||
startLoading()
|
||||
|
@ -1340,11 +1338,11 @@ class Column(
|
|||
who : TootAccount,
|
||||
bAdd : Boolean
|
||||
) {
|
||||
if(type == ColumnType.LIST_TL && access_info.acct == account.acct && list_id == profile_id) {
|
||||
if(type == ColumnType.LIST_TL && access_info == account && list_id == profile_id) {
|
||||
if(! bAdd) {
|
||||
removeAccountInTimeline(account, who.id)
|
||||
}
|
||||
} else if(type == ColumnType.LIST_MEMBER && access_info.acct == account.acct && list_id == profile_id) {
|
||||
} else if(type == ColumnType.LIST_MEMBER && access_info == account && list_id == profile_id) {
|
||||
if(! bAdd) {
|
||||
removeAccountInTimeline(account, who.id)
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ private val unsupportedRefresh : ColumnTask_Refresh.(client : TootApiClient) ->
|
|||
private val unsupportedGap : ColumnTask_Gap.(client : TootApiClient) -> TootApiResult? =
|
||||
{ TootApiResult("gap reading not supported.") }
|
||||
|
||||
private val unusedIconId : (acct : String) -> Int =
|
||||
private val unusedIconId : (String) -> Int =
|
||||
{ R.drawable.ic_question }
|
||||
|
||||
private val unusedName : (context : Context) -> String =
|
||||
|
@ -43,7 +43,7 @@ private val unusedName2 : Column.(long : Boolean) -> String? =
|
|||
|
||||
enum class ColumnType(
|
||||
val id : Int = 0,
|
||||
val iconId : (acct : String) -> Int = unusedIconId,
|
||||
val iconId : (acct:String) -> Int = unusedIconId,
|
||||
val name1 : (context : Context) -> String = unusedName,
|
||||
val name2 : Column.(long : Boolean) -> String? = unusedName2,
|
||||
val loading : ColumnTask_Loading.(client : TootApiClient) -> TootApiResult?,
|
||||
|
|
|
@ -1171,15 +1171,13 @@ class ColumnViewHolder(
|
|||
val column = this.column
|
||||
if(column == null || column.is_dispose.get()) return@Runnable
|
||||
|
||||
val acct = column.access_info.acct
|
||||
val ac = AcctColor.load(acct)
|
||||
val ac = AcctColor.load(column.access_info.acctAscii)
|
||||
|
||||
val nickname = ac.nickname
|
||||
tvColumnContext.text = if(nickname != null && nickname.isNotEmpty())
|
||||
nickname
|
||||
else
|
||||
column.access_info.prettyAcct
|
||||
|
||||
column.access_info.acctPretty
|
||||
|
||||
tvColumnContext.setTextColor(
|
||||
ac.color_fg.notZero()
|
||||
|
@ -2640,7 +2638,7 @@ class ColumnViewHolder(
|
|||
|
||||
private fun addReaction(item : TootAnnouncement, sample : TootAnnouncement.Reaction?) {
|
||||
val column = column ?: return
|
||||
val host = column.access_info.host
|
||||
val host = column.access_info.hostAscii
|
||||
val isMisskey = column.isMisskey
|
||||
if(sample == null) {
|
||||
EmojiPicker(activity, host, isMisskey) { name, _, _, unicode, customEmoji ->
|
||||
|
|
|
@ -412,7 +412,7 @@ internal class DlgContextMenu(
|
|||
// 疑似アカウントではドメインブロックできない
|
||||
// 自ドメインはブロックできない
|
||||
btnDomainBlock.vg(
|
||||
! (access_info.isPseudo || access_info.host.equals(who_host, ignoreCase = true))
|
||||
! (access_info.isPseudo || access_info.matchHost(who_host))
|
||||
)
|
||||
|
||||
btnDomainTimeline.vg(
|
||||
|
@ -525,9 +525,9 @@ internal class DlgContextMenu(
|
|||
}
|
||||
|
||||
private fun getUserHost() : String {
|
||||
return when(val who_host = whoRef?.get()?.host) {
|
||||
return when(val who_host = whoRef?.get()?.hostAscii) {
|
||||
"?" -> column.instance_uri
|
||||
null, "" -> access_info.host
|
||||
null, "" -> access_info.hostAscii
|
||||
else -> who_host
|
||||
}
|
||||
}
|
||||
|
@ -766,6 +766,7 @@ internal class DlgContextMenu(
|
|||
ActNickname.open(
|
||||
activity,
|
||||
access_info.getFullAcct(who),
|
||||
access_info.getFullPrettyAcct(who),
|
||||
true,
|
||||
ActMain.REQUEST_CODE_NICKNAME
|
||||
)
|
||||
|
@ -783,10 +784,10 @@ internal class DlgContextMenu(
|
|||
showToast(activity, false, R.string.domain_block_from_pseudo)
|
||||
return
|
||||
} else {
|
||||
val who_host = who.host
|
||||
val who_host = who.hostAscii
|
||||
|
||||
// 自分のドメインではブロックできない
|
||||
if(access_info.host.equals(who_host, ignoreCase = true)) {
|
||||
if(access_info.matchHost(who_host)) {
|
||||
showToast(activity, false, R.string.domain_block_from_local)
|
||||
return
|
||||
}
|
||||
|
@ -800,7 +801,7 @@ internal class DlgContextMenu(
|
|||
}
|
||||
|
||||
R.id.btnOpenTimeline -> {
|
||||
val who_host = who.host
|
||||
val who_host = who.hostAscii
|
||||
@Suppress("ControlFlowWithEmptyBody")
|
||||
if(who_host.isEmpty() || who_host == "?") {
|
||||
// 何もしない
|
||||
|
@ -810,7 +811,7 @@ internal class DlgContextMenu(
|
|||
}
|
||||
|
||||
R.id.btnDomainTimeline -> {
|
||||
val who_host = who.host
|
||||
val who_host = who.hostAscii
|
||||
@Suppress("ControlFlowWithEmptyBody")
|
||||
if(who_host.isEmpty() || who_host == "?") {
|
||||
// 何もしない
|
||||
|
@ -885,7 +886,7 @@ internal class DlgContextMenu(
|
|||
activity,
|
||||
access_info,
|
||||
pos,
|
||||
who.host,
|
||||
who.hostAscii,
|
||||
status,
|
||||
ColumnType.ACCOUNT_AROUND
|
||||
, allowPseudo = false
|
||||
|
@ -895,7 +896,7 @@ internal class DlgContextMenu(
|
|||
activity,
|
||||
access_info,
|
||||
pos,
|
||||
who.host,
|
||||
who.hostAscii,
|
||||
status,
|
||||
ColumnType.LOCAL_AROUND
|
||||
)
|
||||
|
@ -904,7 +905,7 @@ internal class DlgContextMenu(
|
|||
activity,
|
||||
access_info,
|
||||
pos,
|
||||
who.host,
|
||||
who.hostAscii,
|
||||
status,
|
||||
ColumnType.FEDERATED_AROUND
|
||||
)
|
||||
|
@ -914,13 +915,13 @@ internal class DlgContextMenu(
|
|||
R.id.btnOpenAccountInAdminWebUi ->
|
||||
App1.openBrowser(
|
||||
activity,
|
||||
"https://${access_info.host}/admin/accounts/${who.id}"
|
||||
"https://${access_info.hostAscii}/admin/accounts/${who.id}"
|
||||
)
|
||||
|
||||
R.id.btnOpenInstanceInAdminWebUi ->
|
||||
App1.openBrowser(
|
||||
activity,
|
||||
"https://${access_info.host}/admin/instances/${who.host}"
|
||||
"https://${access_info.hostAscii}/admin/instances/${who.hostAscii}"
|
||||
)
|
||||
|
||||
R.id.btnBoostWithVisibility -> {
|
||||
|
|
|
@ -1093,7 +1093,7 @@ internal class ItemViewHolder(
|
|||
} else {
|
||||
val m = reply.mentions?.find { it.id == accountId }
|
||||
if(m != null) {
|
||||
AcctColor.getNicknameWithColor(access_info,m.acct)
|
||||
AcctColor.getNicknameWithColor(access_info,m.acctAscii)
|
||||
} else {
|
||||
SpannableString("ID(${accountId})")
|
||||
}
|
||||
|
@ -1409,12 +1409,12 @@ internal class ItemViewHolder(
|
|||
try {
|
||||
if(! Column.useInstanceTicker) return
|
||||
|
||||
val host = who.host
|
||||
val host = who.hostAscii
|
||||
|
||||
// LTLでホスト名が同じならTickerを表示しない
|
||||
when(column.type) {
|
||||
ColumnType.LOCAL, ColumnType.LOCAL_AROUND -> {
|
||||
if(host == access_info.host) return
|
||||
if(host == access_info.hostAscii) return
|
||||
}
|
||||
|
||||
else -> {
|
||||
|
@ -2142,7 +2142,7 @@ internal class ItemViewHolder(
|
|||
is TootTag -> {
|
||||
// search_tag は#を含まない
|
||||
val tagEncoded = item.name.encodePercent()
|
||||
val host = access_info.host
|
||||
val host = access_info.hostAscii
|
||||
val url = "https://$host/tags/$tagEncoded"
|
||||
Action_HashTag.timelineOtherInstance(
|
||||
activity = activity,
|
||||
|
@ -2469,7 +2469,7 @@ internal class ItemViewHolder(
|
|||
setPadding(paddingH, paddingV, paddingH, paddingV)
|
||||
|
||||
val emoji = status.custom_emojis?.get(customCode)
|
||||
?: App1.custom_emoji_lister.getMap(access_info.host, true)
|
||||
?: App1.custom_emoji_lister.getMap(access_info.hostAscii, true)
|
||||
?.get(customCode)
|
||||
|
||||
val emojiUrl = emoji?.let {
|
||||
|
|
|
@ -991,7 +991,7 @@ class PollingWorker private constructor(contextArg : Context) {
|
|||
for(t in thread_list) {
|
||||
if(! t.isAlive) continue
|
||||
if(job.isJobCancelled) t.cancel()
|
||||
liveSet.add(t.account.host)
|
||||
liveSet.add(t.account.hostAscii)
|
||||
}
|
||||
if(liveSet.isEmpty()) break
|
||||
|
||||
|
@ -1076,7 +1076,7 @@ class PollingWorker private constructor(contextArg : Context) {
|
|||
|
||||
val wps_log = wps.log
|
||||
if(wps_log.isNotEmpty())
|
||||
log.d("PushSubscriptionHelper: ${account.acct} $wps_log")
|
||||
log.d("PushSubscriptionHelper: ${account.acctPretty} $wps_log")
|
||||
|
||||
if(job.isJobCancelled) return
|
||||
|
||||
|
@ -1243,14 +1243,14 @@ class PollingWorker private constructor(contextArg : Context) {
|
|||
val dataList = dstListData
|
||||
val first = dataList.firstOrNull()
|
||||
if(first == null) {
|
||||
log.d("showNotification[${account.acct}/$notification_tag] cancel notification.")
|
||||
log.d("showNotification[${account.acctPretty}/$notification_tag] cancel notification.")
|
||||
if(Build.VERSION.SDK_INT >= 23 && Pref.bpDivideNotification(pref)) {
|
||||
notification_manager.activeNotifications?.forEach {
|
||||
if(it != null &&
|
||||
it.id == NOTIFICATION_ID &&
|
||||
it.tag.startsWith("$notification_tag/")
|
||||
) {
|
||||
log.d("cancel: ${it.tag} context=${account.acct} $notification_tag")
|
||||
log.d("cancel: ${it.tag} context=${account.acctPretty} $notification_tag")
|
||||
notification_manager.cancel(it.tag, NOTIFICATION_ID)
|
||||
}
|
||||
}
|
||||
|
@ -1267,7 +1267,7 @@ class PollingWorker private constructor(contextArg : Context) {
|
|||
) {
|
||||
// 先頭にあるデータが同じなら、通知を更新しない
|
||||
// このマーカーは端末再起動時にリセットされるので、再起動後は通知が出るはず
|
||||
log.d("showNotification[${account.acct}] id=${first.notification.id} is already shown.")
|
||||
log.d("showNotification[${account.acctPretty}] id=${first.notification.id} is already shown.")
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -1302,8 +1302,6 @@ class PollingWorker private constructor(contextArg : Context) {
|
|||
|
||||
createNotification(itemTag,notificationId = item.notification.id.toString()) { builder ->
|
||||
|
||||
val myAcct = item.access_info.acct
|
||||
|
||||
builder.setWhen(item.notification.time_created_at)
|
||||
|
||||
val summary = getNotificationLine(item)
|
||||
|
@ -1313,11 +1311,11 @@ class PollingWorker private constructor(contextArg : Context) {
|
|||
builder.setStyle(
|
||||
NotificationCompat.BigTextStyle()
|
||||
.setBigContentTitle(summary)
|
||||
.setSummaryText(myAcct)
|
||||
.setSummaryText(item.access_info.acctPretty)
|
||||
.bigText(content)
|
||||
)
|
||||
} else {
|
||||
builder.setContentText(myAcct)
|
||||
builder.setContentText(item.access_info.acctPretty)
|
||||
}
|
||||
|
||||
if(Build.VERSION.SDK_INT < 26) {
|
||||
|
@ -1369,18 +1367,16 @@ class PollingWorker private constructor(contextArg : Context) {
|
|||
}
|
||||
// リストにない通知は消さない。ある通知をユーザが指で削除した際に他の通知が残ってほしい場合がある
|
||||
} else {
|
||||
log.d("showNotification[${account.acct}] creating notification(1)")
|
||||
log.d("showNotification[${account.acctPretty}] creating notification(1)")
|
||||
createNotification(notification_tag) { builder ->
|
||||
|
||||
builder.setWhen(first.notification.time_created_at)
|
||||
|
||||
var a = getNotificationLine(first)
|
||||
|
||||
val myAcct = account.acct
|
||||
|
||||
if(dataList.size == 1) {
|
||||
builder.setContentTitle(a)
|
||||
builder.setContentText(myAcct)
|
||||
builder.setContentText( account.acctPretty)
|
||||
} else {
|
||||
val header =
|
||||
context.getString(R.string.notification_count, dataList.size)
|
||||
|
@ -1389,7 +1385,7 @@ class PollingWorker private constructor(contextArg : Context) {
|
|||
|
||||
val style = NotificationCompat.InboxStyle()
|
||||
.setBigContentTitle(header)
|
||||
.setSummaryText(myAcct)
|
||||
.setSummaryText( account.acctPretty)
|
||||
for(i in 0 .. 4) {
|
||||
if(i >= dataList.size) break
|
||||
val item = dataList[i]
|
||||
|
@ -1454,7 +1450,7 @@ class PollingWorker private constructor(contextArg : Context) {
|
|||
notificationId : String? = null,
|
||||
setContent : (builder : NotificationCompat.Builder) -> Unit
|
||||
) {
|
||||
log.d("showNotification[${account.acct}] creating notification(1)")
|
||||
log.d("showNotification[${account.acctPretty}] creating notification(1)")
|
||||
|
||||
val builder = if(Build.VERSION.SDK_INT >= 26) {
|
||||
// Android 8 から、通知のスタイルはユーザが管理することになった
|
||||
|
@ -1523,15 +1519,15 @@ class PollingWorker private constructor(contextArg : Context) {
|
|||
// Android 7.0 ではグループを指定しないと勝手に通知が束ねられてしまう。
|
||||
// 束ねられた通知をタップしても pi_click が実行されないので困るため、
|
||||
// アカウント別にグループキーを設定する
|
||||
setGroup(context.packageName + ":" + account.acct)
|
||||
setGroup(context.packageName + ":" + account.acctAscii)
|
||||
|
||||
}
|
||||
|
||||
log.d("showNotification[${account.acct}] creating notification(3)")
|
||||
log.d("showNotification[${account.acctPretty}] creating notification(3)")
|
||||
|
||||
setContent(builder)
|
||||
|
||||
log.d("showNotification[${account.acct}] set notification...")
|
||||
log.d("showNotification[${account.acctPretty}] set notification...")
|
||||
|
||||
notification_manager.notify(notification_tag, NOTIFICATION_ID, builder.build())
|
||||
}
|
||||
|
|
|
@ -158,7 +158,7 @@ internal class StreamReader(
|
|||
|
||||
private fun fireDeleteId(id : EntityId) {
|
||||
|
||||
val tl_host = access_info.host
|
||||
val tl_host = access_info.hostAscii
|
||||
runOnMainLooper {
|
||||
synchronized(this) {
|
||||
if(bDisposed.get()) return@synchronized
|
||||
|
|
|
@ -113,7 +113,7 @@ internal class ViewHolderHeaderInstance(
|
|||
btnEmail.isEnabled = email.isNotEmpty()
|
||||
|
||||
val contact_acct =
|
||||
instance.contact_account?.let { who -> "@" + who.username + "@" + who.host } ?: ""
|
||||
instance.contact_account?.let { who -> "@" + who.username + "@" + who.hostAscii } ?: ""
|
||||
btnContact.text = contact_acct
|
||||
btnContact.isEnabled = contact_acct.isNotEmpty()
|
||||
|
||||
|
@ -218,7 +218,7 @@ internal class ViewHolderHeaderInstance(
|
|||
, activity.nextPosition(column)
|
||||
, ColumnType.SEARCH
|
||||
|
||||
, args = arrayOf("@" + who.username + "@" + who.host, true)
|
||||
, args = arrayOf("@" + who.username + "@" + who.hostAscii, true)
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -99,10 +99,11 @@ fun makeAccountListNonPseudo(
|
|||
val list_other_host = ArrayList<SavedAccount>()
|
||||
for(a in SavedAccount.loadAccountList(context)) {
|
||||
if(a.isPseudo) continue
|
||||
(if(pickup_host == null || pickup_host.equals(
|
||||
a.host,
|
||||
ignoreCase = true
|
||||
)) list_same_host else list_other_host).add(a)
|
||||
(if(pickup_host == null || pickup_host.equals(a.hostAscii, ignoreCase = true) || pickup_host.equals(a.hostPretty, ignoreCase = true))
|
||||
list_same_host
|
||||
else
|
||||
list_other_host
|
||||
).add(a)
|
||||
}
|
||||
SavedAccount.sort(list_same_host)
|
||||
SavedAccount.sort(list_other_host)
|
||||
|
@ -154,12 +155,8 @@ const val CROSS_ACCOUNT_REMOTE_INSTANCE = 3
|
|||
internal fun calcCrossAccountMode(
|
||||
timeline_account : SavedAccount,
|
||||
action_account : SavedAccount
|
||||
) : Int {
|
||||
return if(! timeline_account.host.equals(action_account.host, ignoreCase = true)) {
|
||||
CROSS_ACCOUNT_REMOTE_INSTANCE
|
||||
} else if(! timeline_account.acct.equals(action_account.acct, ignoreCase = true)) {
|
||||
CROSS_ACCOUNT_SAME_INSTANCE
|
||||
} else {
|
||||
NOT_CROSS_ACCOUNT
|
||||
}
|
||||
) : Int =when{
|
||||
timeline_account == action_account -> NOT_CROSS_ACCOUNT
|
||||
timeline_account.matchHost(action_account.hostAscii) -> CROSS_ACCOUNT_SAME_INSTANCE
|
||||
else -> CROSS_ACCOUNT_REMOTE_INSTANCE
|
||||
}
|
||||
|
|
|
@ -240,7 +240,7 @@ object Action_Account {
|
|||
}
|
||||
|
||||
ColumnType.PROFILE_DIRECTORY -> {
|
||||
activity.addColumn(pos, ai, type, ai.host)
|
||||
activity.addColumn(pos, ai, type, ai.hostAscii)
|
||||
}
|
||||
|
||||
else -> activity.addColumn(pos, ai, type, *args)
|
||||
|
|
|
@ -47,7 +47,7 @@ object Action_Filter {
|
|||
if( filterList != null) {
|
||||
showToast(activity, false, R.string.delete_succeeded)
|
||||
for(column in App1.getAppState(activity).column_list) {
|
||||
if( column.access_info.acct == access_info.acct){
|
||||
if( column.access_info == access_info ){
|
||||
column.onFilterDeleted(filter,filterList)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,6 @@ import jp.juggler.subwaytooter.table.SavedAccount
|
|||
import jp.juggler.subwaytooter.table.UserRelation
|
||||
import jp.juggler.subwaytooter.util.EmptyCallback
|
||||
import jp.juggler.util.*
|
||||
import java.net.IDN
|
||||
|
||||
object Action_Follow {
|
||||
|
||||
|
@ -193,12 +192,12 @@ object Action_Follow {
|
|||
// 検索APIを呼び出さないようにする
|
||||
val result = client.request("/api/v1/accounts/${userId}")
|
||||
?: return null
|
||||
who.acct == parser.account(result.jsonObject)?.acct
|
||||
who.acctAscii == parser.account(result.jsonObject)?.acctAscii
|
||||
}
|
||||
|
||||
if(! skipAccountSync) {
|
||||
// 同タンスのIDではなかった場合、検索APIを使う
|
||||
val (result, ar) = client.syncAccountByAcct(access_info, who.acct)
|
||||
val (result, ar) = client.syncAccountByAcct(access_info, who.acctAscii)
|
||||
val user = ar?.get() ?: return result
|
||||
userId = user.id
|
||||
}
|
||||
|
@ -346,7 +345,7 @@ object Action_Follow {
|
|||
|
||||
// リモートユーザの同期
|
||||
if(who.isRemote) {
|
||||
val (result, ar) = client.syncAccountByAcct(access_info, who.acct)
|
||||
val (result, ar) = client.syncAccountByAcct(access_info, who.acctAscii)
|
||||
val user = ar?.get() ?: return result
|
||||
userId = user.id
|
||||
}
|
||||
|
@ -573,7 +572,7 @@ object Action_Follow {
|
|||
activity,
|
||||
bAuto = false,
|
||||
message = activity.getString(R.string.account_picker_follow),
|
||||
accountListArg = makeAccountListNonPseudo(activity, account.host)
|
||||
accountListArg = makeAccountListNonPseudo(activity, account.hostAscii)
|
||||
) { ai ->
|
||||
followRemote(
|
||||
activity,
|
||||
|
@ -643,7 +642,7 @@ object Action_Follow {
|
|||
column.removeUser(access_info, ColumnType.FOLLOW_REQUESTS, who.id)
|
||||
|
||||
// 他のカラムでもフォロー状態の表示更新が必要
|
||||
if(column.access_info.acct == access_info.acct
|
||||
if(column.access_info == access_info
|
||||
&& column.type != ColumnType.FOLLOW_REQUESTS
|
||||
) {
|
||||
column.fireRebindAdapterItems()
|
||||
|
|
|
@ -122,22 +122,34 @@ object Action_HashTag {
|
|||
val list_other = ArrayList<SavedAccount>()
|
||||
for(a in account_list) {
|
||||
if( acctAscii == null){
|
||||
if(! host.equals(a.host, ignoreCase = true)) {
|
||||
list_other.add(a)
|
||||
} else if(a.isPseudo) {
|
||||
list_original_pseudo.add(a)
|
||||
} else {
|
||||
list_original.add(a)
|
||||
when {
|
||||
! host.equals(a.hostAscii, ignoreCase = true) -> {
|
||||
list_other.add(a)
|
||||
}
|
||||
a.isPseudo -> {
|
||||
list_original_pseudo.add(a)
|
||||
}
|
||||
else -> {
|
||||
list_original.add(a)
|
||||
}
|
||||
}
|
||||
}else{
|
||||
if(a.isPseudo) {
|
||||
when {
|
||||
|
||||
// acctからidを取得できない
|
||||
}else if(a.isMisskey) {
|
||||
a.isPseudo -> {
|
||||
}
|
||||
|
||||
// ミスキーのアカウント別タグTLは未対応
|
||||
}else if(! host.equals(a.host, ignoreCase = true)) {
|
||||
list_other.add(a)
|
||||
} else {
|
||||
list_original.add(a)
|
||||
a.isMisskey -> {
|
||||
}
|
||||
|
||||
! host.equals(a.hostAscii, ignoreCase = true) -> {
|
||||
list_other.add(a)
|
||||
}
|
||||
else -> {
|
||||
list_original.add(a)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -163,8 +175,8 @@ object Action_HashTag {
|
|||
AcctColor.getStringWithNickname(
|
||||
activity,
|
||||
R.string.open_in_account,
|
||||
a.acct,
|
||||
a.prettyAcct
|
||||
a.acctAscii,
|
||||
a.acctPretty
|
||||
)
|
||||
)
|
||||
{ timeline(activity, pos, a, tag_without_sharp,acctAscii) }
|
||||
|
@ -174,8 +186,8 @@ object Action_HashTag {
|
|||
AcctColor.getStringWithNickname(
|
||||
activity,
|
||||
R.string.open_in_account,
|
||||
a.acct,
|
||||
a.prettyAcct
|
||||
a.acctAscii,
|
||||
a.acctPretty
|
||||
)
|
||||
)
|
||||
{ timeline(activity, pos, a, tag_without_sharp,acctAscii) }
|
||||
|
@ -185,8 +197,8 @@ object Action_HashTag {
|
|||
AcctColor.getStringWithNickname(
|
||||
activity,
|
||||
R.string.open_in_account,
|
||||
a.acct,
|
||||
a.prettyAcct
|
||||
a.acctAscii,
|
||||
a.acctPretty
|
||||
)
|
||||
)
|
||||
{ timeline(activity, pos, a, tag_without_sharp,acctAscii) }
|
||||
|
|
|
@ -48,7 +48,7 @@ object Action_Instance {
|
|||
App1.openBrowser(activity, "https://$host/explore")
|
||||
|
||||
// ホスト名部分が一致するならそのアカウントで開く
|
||||
accessInfo.host == host ->
|
||||
accessInfo.hostAscii == host ->
|
||||
activity.addColumn(
|
||||
false,
|
||||
pos,
|
||||
|
@ -83,7 +83,7 @@ object Action_Instance {
|
|||
ColumnType.PROFILE_DIRECTORY.name1(activity)
|
||||
)
|
||||
) { ai ->
|
||||
profileDirectory(activity, ai, ai.host)
|
||||
profileDirectory(activity, ai, ai.hostAscii)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -134,7 +134,7 @@ object Action_Instance {
|
|||
// 指定タンスのアカウントを持ってるか?
|
||||
val account_list = ArrayList<SavedAccount>()
|
||||
for(a in SavedAccount.loadAccountList(activity)) {
|
||||
if(host.equals(a.host, ignoreCase = true)) account_list.add(a)
|
||||
if(host.equals(a.hostAscii, ignoreCase = true)) account_list.add(a)
|
||||
}
|
||||
if(account_list.isEmpty()) {
|
||||
// 持ってないなら疑似アカウントを追加する
|
||||
|
@ -159,7 +159,7 @@ object Action_Instance {
|
|||
activity : ActMain, access_info : SavedAccount, domain : String, bBlock : Boolean
|
||||
) {
|
||||
|
||||
if(access_info.host.equals(domain, ignoreCase = true)) {
|
||||
if(access_info.matchHost(domain)) {
|
||||
showToast(activity, false, R.string.it_is_you)
|
||||
return
|
||||
}
|
||||
|
@ -260,7 +260,7 @@ object Action_Instance {
|
|||
a.isMisskey -> continue@label
|
||||
|
||||
// 閲覧アカウントとホスト名が同じならステータスIDの変換が必要ない
|
||||
a.host.equals(access_info.host, ignoreCase = true) -> {
|
||||
a.matchHost(access_info.hostAscii) -> {
|
||||
if(! allowPseudo && a.isPseudo) continue@label
|
||||
account_list1.add(a)
|
||||
}
|
||||
|
@ -282,7 +282,7 @@ object Action_Instance {
|
|||
message = "select account to read timeline",
|
||||
accountListArg = account_list1
|
||||
) { ai ->
|
||||
if(! ai.isNA && ai.host.equals(access_info.host, ignoreCase = true)) {
|
||||
if(! ai.isNA && ai.matchHost(access_info.hostAscii)) {
|
||||
timelinePublicAround2(activity, ai, pos, status.id, type)
|
||||
} else {
|
||||
timelinePublicAround3(activity, ai, pos, status, type)
|
||||
|
|
|
@ -60,7 +60,7 @@ object Action_ListMember {
|
|||
|
||||
// リモートユーザの解決
|
||||
if(! access_info.isLocalUser(local_who)) {
|
||||
val (r2, ar) = client.syncAccountByAcct(access_info, local_who.acct)
|
||||
val (r2, ar) = client.syncAccountByAcct(access_info, local_who.acctAscii)
|
||||
val user = ar?.get() ?: return r2
|
||||
userId = user.id
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ object Action_Notification {
|
|||
if(result.jsonObject != null) {
|
||||
// ok. api have return empty object.
|
||||
for(column in App1.getAppState(activity).column_list) {
|
||||
if(column.isNotificationColumn && column.access_info.acct == target_account.acct) {
|
||||
if(column.isNotificationColumn && column.access_info == target_account ) {
|
||||
column.removeNotifications()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ object Action_Toot {
|
|||
status : TootStatus?
|
||||
) {
|
||||
if(status == null) return
|
||||
val who_host = timeline_account.host
|
||||
val who_host = timeline_account.hostAscii
|
||||
|
||||
AccountPicker.pick(
|
||||
activity,
|
||||
|
@ -194,13 +194,13 @@ object Action_Toot {
|
|||
}
|
||||
|
||||
for(column in App1.getAppState(activity).column_list) {
|
||||
column.findStatus(access_info.host, new_status.id) { account, status ->
|
||||
column.findStatus(access_info.hostAscii, new_status.id) { account, status ->
|
||||
|
||||
// 同タンス別アカウントでもカウントは変化する
|
||||
status.favourites_count = new_status.favourites_count
|
||||
|
||||
// 同アカウントならfav状態を変化させる
|
||||
if(access_info.acct == account.acct) {
|
||||
if(access_info == account ) {
|
||||
status.favourited = new_status.favourited
|
||||
}
|
||||
|
||||
|
@ -230,7 +230,7 @@ object Action_Toot {
|
|||
status : TootStatus?
|
||||
) {
|
||||
if(status == null) return
|
||||
val who_host = timeline_account.host
|
||||
val who_host = timeline_account.hostAscii
|
||||
|
||||
AccountPicker.pick(
|
||||
activity,
|
||||
|
@ -330,10 +330,10 @@ object Action_Toot {
|
|||
|
||||
new_status != null -> {
|
||||
for(column in App1.getAppState(activity).column_list) {
|
||||
column.findStatus(access_info.host, new_status.id) { account, status ->
|
||||
column.findStatus(access_info.hostAscii, new_status.id) { account, status ->
|
||||
|
||||
// 同アカウントならブックマーク状態を伝播する
|
||||
if(access_info.acct == account.acct) {
|
||||
if(access_info == account ) {
|
||||
status.bookmarked = new_status.bookmarked
|
||||
}
|
||||
|
||||
|
@ -362,7 +362,7 @@ object Action_Toot {
|
|||
) {
|
||||
status ?: return
|
||||
|
||||
val who_host = timeline_account.host
|
||||
val who_host = timeline_account.hostAscii
|
||||
val status_owner = timeline_account.getFullAcct(status.account)
|
||||
|
||||
val isPrivateToot = timeline_account.isMastodon &&
|
||||
|
@ -371,7 +371,7 @@ object Action_Toot {
|
|||
if(isPrivateToot) {
|
||||
val list = ArrayList<SavedAccount>()
|
||||
for(a in SavedAccount.loadAccountList(activity)) {
|
||||
if(a.acct == status_owner) list.add(a)
|
||||
if(a.acctAscii == status_owner) list.add(a)
|
||||
}
|
||||
if(list.isEmpty()) {
|
||||
showToast(activity, false, R.string.boost_private_toot_not_allowed)
|
||||
|
@ -434,7 +434,7 @@ object Action_Toot {
|
|||
// Mastodonは非公開トゥートをブーストできるのは本人だけ
|
||||
val isPrivateToot = access_info.isMastodon &&
|
||||
arg_status.visibility == TootVisibility.PrivateFollowers
|
||||
if(isPrivateToot && access_info.acct != status_owner_acct) {
|
||||
if(isPrivateToot && access_info.acctAscii != status_owner_acct) {
|
||||
showToast(activity, false, R.string.boost_private_toot_not_allowed)
|
||||
return
|
||||
}
|
||||
|
@ -587,15 +587,13 @@ object Action_Toot {
|
|||
val count = max(0, (arg_status.reblogs_count ?: 1) - 1)
|
||||
|
||||
for(column in App1.getAppState(activity).column_list) {
|
||||
column.findStatus(access_info.host, arg_status.id) { account, status ->
|
||||
column.findStatus(access_info.hostAscii, arg_status.id) { account, status ->
|
||||
|
||||
// 同タンス別アカウントでもカウントは変化する
|
||||
status.reblogs_count = count
|
||||
|
||||
// 同アカウントならreblogged状態を変化させる
|
||||
if(access_info.acct == account.acct &&
|
||||
status.myRenoteId == unrenoteId
|
||||
) {
|
||||
if(access_info == account && status.myRenoteId == unrenoteId ) {
|
||||
status.myRenoteId = null
|
||||
status.reblogged = false
|
||||
}
|
||||
|
@ -623,12 +621,12 @@ object Action_Toot {
|
|||
}
|
||||
|
||||
for(column in App1.getAppState(activity).column_list) {
|
||||
column.findStatus(access_info.host, new_status.id) { account, status ->
|
||||
column.findStatus(access_info.hostAscii, new_status.id) { account, status ->
|
||||
|
||||
// 同タンス別アカウントでもカウントは変化する
|
||||
status.reblogs_count = new_status.reblogs_count
|
||||
|
||||
if(access_info.acct == account.acct) {
|
||||
if(access_info == account ) {
|
||||
|
||||
// 同アカウントならreblog状態を変化させる
|
||||
when {
|
||||
|
@ -689,7 +687,7 @@ object Action_Toot {
|
|||
if(result.jsonObject != null) {
|
||||
showToast(activity, false, R.string.delete_succeeded)
|
||||
for(column in App1.getAppState(activity).column_list) {
|
||||
column.onStatusRemoved(access_info.host, status_id)
|
||||
column.onStatusRemoved(access_info.hostAscii, status_id)
|
||||
}
|
||||
} else {
|
||||
showToast(activity, false, result.error)
|
||||
|
@ -731,7 +729,7 @@ object Action_Toot {
|
|||
access_info : SavedAccount,
|
||||
status : TootStatus
|
||||
) {
|
||||
if(access_info.isNA || ! access_info.host.equals(status.host_access, ignoreCase = true)) {
|
||||
if(access_info.isNA || ! access_info.matchHost(status.host_access)) {
|
||||
conversationOtherInstance(activity, pos, status)
|
||||
} else {
|
||||
|
||||
|
@ -845,11 +843,11 @@ object Action_Toot {
|
|||
// 疑似アカウントは後でまとめて処理する
|
||||
if(a.isPseudo) continue
|
||||
|
||||
if(status_id_original != null && a.host.equals(host_original, ignoreCase = true)) {
|
||||
if(status_id_original != null && a.matchHost(host_original)) {
|
||||
// アクセス情報+ステータスID でアクセスできるなら
|
||||
// 同タンスのアカウントならステータスIDの変換なしに表示できる
|
||||
local_account_list.add(a)
|
||||
} else if(status_id_access != null && a.host.equals(host_access, ignoreCase = true)) {
|
||||
} else if(status_id_access != null && a.matchHost(host_access)) {
|
||||
// 既に変換済みのステータスIDがあるなら、そのアカウントでもステータスIDの変換は必要ない
|
||||
access_account_list.add(a)
|
||||
} else {
|
||||
|
@ -887,8 +885,8 @@ object Action_Toot {
|
|||
AcctColor.getStringWithNickname(
|
||||
activity,
|
||||
R.string.open_in_account,
|
||||
a.acct,
|
||||
a.prettyAcct
|
||||
a.acctAscii,
|
||||
a.acctPretty
|
||||
)
|
||||
) { conversationLocal(activity, pos, a, status_id_original) }
|
||||
}
|
||||
|
@ -902,7 +900,8 @@ object Action_Toot {
|
|||
AcctColor.getStringWithNickname(
|
||||
activity,
|
||||
R.string.open_in_account,
|
||||
a.acct,a.prettyAcct
|
||||
a.acctAscii,
|
||||
a.acctPretty
|
||||
)
|
||||
) { conversationLocal(activity, pos, a, status_id_access) }
|
||||
}
|
||||
|
@ -915,7 +914,8 @@ object Action_Toot {
|
|||
AcctColor.getStringWithNickname(
|
||||
activity,
|
||||
R.string.open_in_account,
|
||||
a.acct,a.prettyAcct
|
||||
a.acctAscii,
|
||||
a.acctPretty
|
||||
)
|
||||
) { conversationRemote(activity, pos, a, url) }
|
||||
}
|
||||
|
@ -1010,7 +1010,7 @@ object Action_Toot {
|
|||
|
||||
// step 1: choose account
|
||||
|
||||
val host = statusArg.account.host
|
||||
val host = statusArg.account.hostAscii
|
||||
val local_account_list = ArrayList<SavedAccount>()
|
||||
val other_account_list = ArrayList<SavedAccount>()
|
||||
|
||||
|
@ -1019,7 +1019,7 @@ object Action_Toot {
|
|||
// 検索APIはログイン必須なので疑似アカウントは使えない
|
||||
if(a.isPseudo) continue
|
||||
|
||||
if(a.host.equals(host, ignoreCase = true)) {
|
||||
if(a.matchHost(host)) {
|
||||
local_account_list.add(a)
|
||||
} else {
|
||||
other_account_list.add(a)
|
||||
|
@ -1034,7 +1034,8 @@ object Action_Toot {
|
|||
AcctColor.getStringWithNickname(
|
||||
activity,
|
||||
R.string.open_in_account,
|
||||
a.acct,a.prettyAcct
|
||||
a.acctAscii,
|
||||
a.acctPretty
|
||||
)
|
||||
) { step2(a) }
|
||||
}
|
||||
|
@ -1045,7 +1046,8 @@ object Action_Toot {
|
|||
AcctColor.getStringWithNickname(
|
||||
activity,
|
||||
R.string.open_in_account,
|
||||
a.acct,a.prettyAcct
|
||||
a.acctAscii,
|
||||
a.acctPretty
|
||||
)
|
||||
) { step2(a) }
|
||||
}
|
||||
|
@ -1089,9 +1091,9 @@ object Action_Toot {
|
|||
|
||||
new_status != null -> {
|
||||
for(column in App1.getAppState(activity).column_list) {
|
||||
if(access_info.acct == column.access_info.acct) {
|
||||
if(access_info == column.access_info ) {
|
||||
column.findStatus(
|
||||
access_info.host,
|
||||
access_info.hostAscii,
|
||||
new_status.id
|
||||
) { _, status ->
|
||||
status.pinned = bSet
|
||||
|
@ -1171,10 +1173,10 @@ object Action_Toot {
|
|||
quotedRenote : Boolean = false
|
||||
) {
|
||||
status ?: return
|
||||
val who_host = timeline_account.host
|
||||
val who_host = timeline_account.hostAscii
|
||||
|
||||
val accountCallback : SavedAccountCallback = { ai ->
|
||||
if(ai.host.equals(status.host_access, ignoreCase = true)) {
|
||||
if(ai.matchHost(status.host_access)) {
|
||||
// アクセス元ホストが同じならステータスIDを使って返信できる
|
||||
reply(activity, ai, status, quotedRenote = quotedRenote)
|
||||
} else {
|
||||
|
@ -1292,8 +1294,8 @@ object Action_Toot {
|
|||
val ls = local_status
|
||||
if(ls != null) {
|
||||
for(column in App1.getAppState(activity).column_list) {
|
||||
if(access_info.acct == column.access_info.acct) {
|
||||
column.findStatus(access_info.host, ls.id) { _, status ->
|
||||
if(access_info == column.access_info ) {
|
||||
column.findStatus(access_info.hostAscii, ls.id) { _, status ->
|
||||
status.muted = bMute
|
||||
true
|
||||
}
|
||||
|
@ -1315,7 +1317,7 @@ object Action_Toot {
|
|||
activity : ActMain,
|
||||
access_info : SavedAccount,
|
||||
arg_status : TootStatus,
|
||||
status_owner_acct : String,
|
||||
status_owner_acct : String, // acctAscii
|
||||
nCrossAccountMode : Int,
|
||||
callback : EmptyCallback?,
|
||||
bSet : Boolean = true,
|
||||
|
@ -1324,7 +1326,7 @@ object Action_Toot {
|
|||
if(access_info.isPseudo || ! access_info.isMisskey) return
|
||||
|
||||
// 自分の投稿にはリアクション出来ない
|
||||
if(access_info.acct == status_owner_acct) {
|
||||
if(access_info.acctAscii == status_owner_acct) {
|
||||
showToast(activity, false, R.string.it_is_you)
|
||||
return
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ import jp.juggler.subwaytooter.table.UserRelation
|
|||
import jp.juggler.subwaytooter.util.TootApiResultCallback
|
||||
import jp.juggler.util.*
|
||||
import okhttp3.Request
|
||||
import java.net.IDN
|
||||
|
||||
object Action_User {
|
||||
|
||||
|
@ -129,7 +130,7 @@ object Action_User {
|
|||
}
|
||||
// フォローアイコンの表示更新が走る
|
||||
column.updateFollowIcons(access_info)
|
||||
} else if(column.access_info.acct == access_info.acct) {
|
||||
} else if(column.access_info == access_info ) {
|
||||
when {
|
||||
! relation.muting -> {
|
||||
if(column.type == ColumnType.MUTES) {
|
||||
|
@ -288,7 +289,7 @@ object Action_User {
|
|||
}
|
||||
// フォローアイコンの表示更新が走る
|
||||
column.updateFollowIcons(access_info)
|
||||
} else if(column.access_info.acct == access_info.acct) {
|
||||
} else if(column.access_info == access_info ) {
|
||||
|
||||
when {
|
||||
|
||||
|
@ -392,7 +393,7 @@ object Action_User {
|
|||
who : TootAccount?
|
||||
) {
|
||||
if(who?.url == null) return
|
||||
val who_host = who.host
|
||||
val who_host = who.hostAscii
|
||||
|
||||
AccountPicker.pick(
|
||||
activity,
|
||||
|
@ -404,7 +405,7 @@ object Action_User {
|
|||
),
|
||||
accountListArg = makeAccountListNonPseudo(activity, who_host)
|
||||
) { ai ->
|
||||
if(ai.host.equals(access_info.host, ignoreCase = true)) {
|
||||
if(ai.matchHost(access_info.hostAscii)) {
|
||||
activity.addColumn(pos, ai, ColumnType.PROFILE, who.id)
|
||||
} else {
|
||||
profileFromUrlOrAcct(activity, pos, ai, who.url, access_info.getFullAcct(who))
|
||||
|
@ -432,16 +433,17 @@ object Action_User {
|
|||
pos : Int,
|
||||
access_info : SavedAccount?,
|
||||
url : String,
|
||||
host : String,
|
||||
hostArg : String,
|
||||
user : String,
|
||||
original_url : String = url
|
||||
) {
|
||||
val acct = "$user@$host"
|
||||
val hostAscii = IDN.toASCII(hostArg,IDN.ALLOW_UNASSIGNED)
|
||||
val acctAscii = "$user@$hostAscii"
|
||||
|
||||
if(access_info?.isPseudo == false) {
|
||||
// 文脈のアカウントがあり、疑似アカウントではない
|
||||
|
||||
if(access_info.host.equals(host, ignoreCase = true)) {
|
||||
if(access_info.matchHost(hostAscii)) {
|
||||
|
||||
// 文脈のアカウントと同じインスタンスなら、アカウントIDを探して開いてしまう
|
||||
TootTaskRunner(activity).run(access_info, object : TootTask {
|
||||
|
@ -449,7 +451,7 @@ object Action_User {
|
|||
var who : TootAccount? = null
|
||||
|
||||
override fun background(client : TootApiClient) : TootApiResult? {
|
||||
val (result, ar) = client.syncAccountByAcct(access_info, acct)
|
||||
val (result, ar) = client.syncAccountByAcct(access_info, acctAscii)
|
||||
who = ar?.get()
|
||||
return result
|
||||
}
|
||||
|
@ -468,7 +470,7 @@ object Action_User {
|
|||
})
|
||||
} else {
|
||||
// 文脈のアカウントと異なるインスタンスなら、別アカウントで開く
|
||||
profileFromUrlOrAcct(activity, pos, access_info, url, acct)
|
||||
profileFromUrlOrAcct(activity, pos, access_info, url, acctAscii)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
@ -481,16 +483,16 @@ object Action_User {
|
|||
// chrome tab で開く
|
||||
App1.openCustomTab(activity, original_url)
|
||||
} else {
|
||||
val(asciiAcct,prettyAcct)=TootAccount.acctAndPrettyAcct("$user@$host")
|
||||
val(_,acctPretty)=TootAccount.acctAndPrettyAcct(acctAscii)
|
||||
AccountPicker.pick(
|
||||
activity,
|
||||
bAllowPseudo = false,
|
||||
bAuto = false,
|
||||
message = activity.getString(
|
||||
R.string.account_picker_open_user_who,
|
||||
AcctColor.getNickname(asciiAcct,prettyAcct)
|
||||
AcctColor.getNickname(acctAscii,acctPretty)
|
||||
),
|
||||
accountListArg = makeAccountListNonPseudo(activity, host),
|
||||
accountListArg = makeAccountListNonPseudo(activity, hostAscii),
|
||||
extra_callback = { ll, pad_se, pad_tb ->
|
||||
|
||||
// chrome tab で開くアクションを追加
|
||||
|
@ -514,7 +516,7 @@ object Action_User {
|
|||
ll.addView(b, 0)
|
||||
}
|
||||
) {
|
||||
profileFromUrlOrAcct(activity, pos, it, url, acct)
|
||||
profileFromUrlOrAcct(activity, pos, it, url, acctAscii)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -658,7 +660,7 @@ object Action_User {
|
|||
activity : ActMain, access_info : SavedAccount, who : TootAccount?
|
||||
) {
|
||||
if(who == null) return
|
||||
val who_host = who.host
|
||||
val who_host = who.hostAscii
|
||||
|
||||
val initial_text = "@" + access_info.getFullAcct(who) + " "
|
||||
AccountPicker.pick(
|
||||
|
|
|
@ -12,7 +12,7 @@ object TootAccountMap{
|
|||
val watcher: String
|
||||
|
||||
init{
|
||||
this.acct = parser.getFullAcct(who.acct)
|
||||
this.acct = parser.getFullAcct(who.acctAscii)
|
||||
|
||||
this.watcher =when(parser.serviceType){
|
||||
ServiceType.MASTODON -> requireNotNull(parser.accessHost)
|
||||
|
|
|
@ -30,7 +30,7 @@ class TootApiClient(
|
|||
// アカウントがある場合に使用する
|
||||
var account : SavedAccount? = null
|
||||
set(value) {
|
||||
instance = value?.host
|
||||
instance = value?.hostAscii
|
||||
field = value
|
||||
}
|
||||
|
||||
|
@ -1534,7 +1534,7 @@ fun TootApiClient.syncStatus(
|
|||
)
|
||||
.status(result.jsonObject)
|
||||
?.apply {
|
||||
if(host.equals(accessInfo.host, ignoreCase = true)) {
|
||||
if(host.equals(accessInfo.hostAscii, ignoreCase = true)) {
|
||||
return Pair(result, this)
|
||||
}
|
||||
uri.letNotEmpty { url = it }
|
||||
|
|
|
@ -23,7 +23,7 @@ class TootParser(
|
|||
val misskeyAccountDetailMap = HashMap<EntityId, TootAccount>()
|
||||
|
||||
val accessHost : String?
|
||||
get() = linkHelper.host
|
||||
get() = linkHelper.hostAscii
|
||||
|
||||
init {
|
||||
if(linkHelper.isMisskey) serviceType = ServiceType.MISSKEY
|
||||
|
|
|
@ -30,13 +30,13 @@ open class TootAccount(parser : TootParser, src : JsonObject) {
|
|||
val id : EntityId
|
||||
|
||||
// Equals username for local users, includes @domain for remote ones
|
||||
val acct : String // punycode
|
||||
val acctAscii : String // punycode
|
||||
val prettyAcct : String // unicode
|
||||
|
||||
// The username of the account /[A-Za-z0-9_]{1,30}/
|
||||
val username : String
|
||||
|
||||
val host : String // punycode
|
||||
val hostAscii : String // punycode
|
||||
|
||||
// The account's display name
|
||||
val display_name : String
|
||||
|
@ -99,10 +99,10 @@ open class TootAccount(parser : TootParser, src : JsonObject) {
|
|||
val isPro : Boolean
|
||||
|
||||
val isLocal :Boolean
|
||||
get() = !acct.contains('@')
|
||||
get() = !acctAscii.contains('@')
|
||||
|
||||
val isRemote :Boolean
|
||||
get() = acct.contains('@')
|
||||
get() = acctAscii.contains('@')
|
||||
|
||||
// user_hides_network is preference, not exposed in API
|
||||
// val user_hides_network : Boolean
|
||||
|
@ -129,7 +129,7 @@ open class TootAccount(parser : TootParser, src : JsonObject) {
|
|||
|
||||
val remoteHost = src.string("host")
|
||||
val tmpHost = (remoteHost ?: parser.accessHost ?: error("missing host")).toLowerCase(Locale.JAPAN)
|
||||
this.host = IDN.toASCII(tmpHost,IDN.ALLOW_UNASSIGNED)
|
||||
this.hostAscii = IDN.toASCII(tmpHost,IDN.ALLOW_UNASSIGNED)
|
||||
val prettyHost = IDN.toUnicode(tmpHost,IDN.ALLOW_UNASSIGNED)
|
||||
|
||||
this.custom_emojis =
|
||||
|
@ -138,7 +138,7 @@ open class TootAccount(parser : TootParser, src : JsonObject) {
|
|||
this.profile_emojis = null
|
||||
|
||||
this.username = src.notEmptyOrThrow("username")
|
||||
this.url = "https://$host/@$username"
|
||||
this.url = "https://$hostAscii/@$username"
|
||||
|
||||
//
|
||||
sv = src.string("name")
|
||||
|
@ -162,7 +162,7 @@ open class TootAccount(parser : TootParser, src : JsonObject) {
|
|||
|
||||
this.id = EntityId.mayDefault(src.string("id"))
|
||||
|
||||
this.acct = when {
|
||||
this.acctAscii = when {
|
||||
|
||||
// アクセス元から見て内部ユーザなら short acct
|
||||
remoteHost?.equals(
|
||||
|
@ -171,7 +171,7 @@ open class TootAccount(parser : TootParser, src : JsonObject) {
|
|||
) != false -> username
|
||||
|
||||
// アクセス元から見て外部ユーザならfull acct
|
||||
else -> "$username@$host"
|
||||
else -> "$username@$hostAscii"
|
||||
}
|
||||
|
||||
this.prettyAcct = when {
|
||||
|
@ -270,9 +270,9 @@ open class TootAccount(parser : TootParser, src : JsonObject) {
|
|||
findHostFromUrl(tmpAcct, hostAccess, url)
|
||||
?: throw RuntimeException("can't get host from acct or url")
|
||||
).toLowerCase(Locale.JAPAN)
|
||||
this.host = IDN.toASCII(tmpHost,IDN.ALLOW_UNASSIGNED)
|
||||
this.hostAscii = IDN.toASCII(tmpHost,IDN.ALLOW_UNASSIGNED)
|
||||
val prettyHost = IDN.toUnicode(tmpHost,IDN.ALLOW_UNASSIGNED)
|
||||
this.acct = if( !tmpAcct.contains('@') ) tmpAcct else "$username@$host"
|
||||
this.acctAscii = if( !tmpAcct.contains('@') ) tmpAcct else "$username@$hostAscii"
|
||||
this.prettyAcct = if( !tmpAcct.contains('@') ) tmpAcct else "$username@$prettyHost"
|
||||
|
||||
this.followers_count = src.long("followers_count")
|
||||
|
@ -297,10 +297,10 @@ open class TootAccount(parser : TootParser, src : JsonObject) {
|
|||
val tmpHost = (findHostFromUrl(sv, null, url)
|
||||
?: throw RuntimeException("can't get host from acct or url")
|
||||
).toLowerCase(Locale.JAPAN)
|
||||
this.host = IDN.toASCII(tmpHost,IDN.ALLOW_UNASSIGNED)
|
||||
this.hostAscii = IDN.toASCII(tmpHost,IDN.ALLOW_UNASSIGNED)
|
||||
val prettyHost=IDN.toUnicode(tmpHost,IDN.ALLOW_UNASSIGNED)
|
||||
|
||||
this.acct = this.username + "@" + this.host
|
||||
this.acctAscii = this.username + "@" + this.hostAscii
|
||||
this.prettyAcct = this.username + "@" + prettyHost
|
||||
|
||||
this.followers_count = src.long("followers_count")
|
||||
|
@ -323,10 +323,10 @@ open class TootAccount(parser : TootParser, src : JsonObject) {
|
|||
val tmpHost = (findHostFromUrl(null, null, url)
|
||||
?: throw RuntimeException("can't get host from url")
|
||||
).toLowerCase(Locale.JAPAN)
|
||||
this.host = IDN.toASCII(tmpHost,IDN.ALLOW_UNASSIGNED)
|
||||
this.hostAscii = IDN.toASCII(tmpHost,IDN.ALLOW_UNASSIGNED)
|
||||
val prettyHost = IDN.toUnicode(tmpHost,IDN.ALLOW_UNASSIGNED)
|
||||
|
||||
this.acct = this.username + "@" + host
|
||||
this.acctAscii = this.username + "@" + hostAscii
|
||||
this.prettyAcct = this.username + "@" + prettyHost
|
||||
|
||||
this.followers_count = null
|
||||
|
@ -655,15 +655,13 @@ open class TootAccount(parser : TootParser, src : JsonObject) {
|
|||
|
||||
|
||||
fun acctAndPrettyAcct(src : String) : Pair<String, String> {
|
||||
val cols = src.split('@')
|
||||
val cols = src.split("@")
|
||||
if(cols.size < 2 ) return Pair(src,src)
|
||||
val username = cols[0]
|
||||
return if(cols.size == 1)
|
||||
Pair(username, username)
|
||||
else
|
||||
Pair(
|
||||
username + "@" + IDN.toASCII(cols[1], IDN.ALLOW_UNASSIGNED),
|
||||
username + "@" + IDN.toUnicode(cols[1], IDN.ALLOW_UNASSIGNED)
|
||||
)
|
||||
return Pair(
|
||||
"$username@${IDN.toASCII(cols[1], IDN.ALLOW_UNASSIGNED)}",
|
||||
"$username@${IDN.toUnicode(cols[1], IDN.ALLOW_UNASSIGNED)}"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,14 +5,22 @@ import jp.juggler.util.JsonObject
|
|||
class TootMention(
|
||||
val id : EntityId, // Account ID
|
||||
val url : String, // URL of user's profile (can be remote)
|
||||
val acct : String, // Equals username for local users, includes @domain for remote ones
|
||||
acctArg : String, // Equals username for local users, includes @domain for remote ones
|
||||
val username : String // The username of the account
|
||||
) {
|
||||
val acctAscii: String
|
||||
val acctPretty:String
|
||||
|
||||
init{
|
||||
val(acctAscii,acctPretty)=TootAccount.acctAndPrettyAcct(acctArg)
|
||||
this.acctAscii = acctAscii
|
||||
this.acctPretty = acctPretty
|
||||
}
|
||||
|
||||
constructor(src : JsonObject) : this(
|
||||
id = EntityId.mayDefault(src.string("id")),
|
||||
url = src.notEmptyOrThrow("url"),
|
||||
acct = src.notEmptyOrThrow("acct"),
|
||||
acctArg = src.notEmptyOrThrow("acct"),
|
||||
username = src.notEmptyOrThrow("username")
|
||||
)
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@ class TootStatus(parser : TootParser, src : JsonObject) : TimelineItem() {
|
|||
|
||||
// 投稿元タンスのホスト名
|
||||
val host_original : String
|
||||
get() = account.host
|
||||
get() = account.hostAscii
|
||||
|
||||
// 取得タンスのホスト名。トゥート検索サービスでは提供されずnullになる
|
||||
val host_access : String?
|
||||
|
@ -646,7 +646,7 @@ class TootStatus(parser : TootParser, src : JsonObject) : TimelineItem() {
|
|||
}
|
||||
|
||||
mentions?.forEach {
|
||||
if(fullAcctMe != access_info.getFullAcct(it.acct))
|
||||
if(fullAcctMe != access_info.getFullAcct(it.acctAscii))
|
||||
return@hasReceipt TootVisibility.DirectSpecified
|
||||
}
|
||||
|
||||
|
|
|
@ -127,7 +127,7 @@ object AccountPicker {
|
|||
for(a in account_list) {
|
||||
val lp = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)
|
||||
|
||||
val ac = AcctColor.load(a.acct)
|
||||
val ac = AcctColor.load(a.acctAscii)
|
||||
|
||||
val b = Button(activity)
|
||||
|
||||
|
@ -146,7 +146,7 @@ object AccountPicker {
|
|||
b.layoutParams = lp
|
||||
b.minHeight = (0.5f + 32f * density).toInt()
|
||||
|
||||
val sb = SpannableStringBuilder(if(AcctColor.hasNickname(ac)) ac.nickname else a.prettyAcct)
|
||||
val sb = SpannableStringBuilder(if(AcctColor.hasNickname(ac)) ac.nickname else a.acctPretty)
|
||||
if( a.last_notification_error?.isNotEmpty() == true) {
|
||||
sb.append("\n")
|
||||
val start = sb.length
|
||||
|
|
|
@ -142,9 +142,8 @@ class DlgListMember(
|
|||
//
|
||||
|
||||
} else {
|
||||
val acct = a.acct
|
||||
val ac = AcctColor.load(acct)
|
||||
val nickname = if(AcctColor.hasNickname(ac)) ac.nickname else acct
|
||||
val ac = AcctColor.load(a.acctAscii)
|
||||
val nickname = if(AcctColor.hasNickname(ac)) ac.nickname else a.acctPretty
|
||||
btnListOwner.text = nickname
|
||||
|
||||
if(AcctColor.hasColorBackground(ac)) {
|
||||
|
|
|
@ -33,7 +33,7 @@ object ReportForm {
|
|||
|
||||
val cbForward : CheckBox = view.findViewById(R.id.cbForward)
|
||||
val tvForwardDesc:TextView = view.findViewById(R.id.tvForwardDesc)
|
||||
val canForward = access_info.host != who.host
|
||||
val canForward = access_info.hostAscii != who.hostAscii
|
||||
|
||||
|
||||
cbForward.isChecked = false
|
||||
|
@ -43,7 +43,7 @@ object ReportForm {
|
|||
}else{
|
||||
cbForward.visibility = View.VISIBLE
|
||||
tvForwardDesc.visibility = View.VISIBLE
|
||||
cbForward.text = activity.getString(R.string.report_forward_to,who.host)
|
||||
cbForward.text = activity.getString(R.string.report_forward_to,who.hostAscii)
|
||||
}
|
||||
|
||||
tvUser.text = who.prettyAcct
|
||||
|
|
|
@ -177,7 +177,7 @@ class AcctColor {
|
|||
val nickname = ac.nickname
|
||||
return if(nickname != null && nickname.isNotEmpty()) nickname.sanitizeBDI() else prettyAcct
|
||||
}
|
||||
fun getNickname(sa:SavedAccount) : String = getNickname(sa.acct,sa.prettyAcct)
|
||||
fun getNickname(sa:SavedAccount) : String = getNickname(sa.acctAscii,sa.acctPretty)
|
||||
|
||||
fun getNickname(sa:SavedAccount,who:TootAccount) : String = getNickname(sa.getFullAcct(who),sa.getFullPrettyAcct(who))
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ import java.util.regex.Pattern
|
|||
|
||||
class SavedAccount(
|
||||
val db_id : Long,
|
||||
val acct : String,
|
||||
acctArg : String,
|
||||
hostArg : String? = null,
|
||||
var token_info : JsonObject? = null,
|
||||
var loginAccount : TootAccount? = null, // 疑似アカウントではnull
|
||||
|
@ -31,8 +31,8 @@ class SavedAccount(
|
|||
|
||||
val username : String
|
||||
|
||||
override val host : String // punycode
|
||||
override val prettyHost : String // unicode
|
||||
override val hostAscii : String // punycode
|
||||
override val hostPretty : String // unicode
|
||||
|
||||
var visibility : TootVisibility = TootVisibility.Public
|
||||
var confirm_boost : Boolean = false
|
||||
|
@ -71,30 +71,32 @@ class SavedAccount(
|
|||
var last_subscription_error : String? = null
|
||||
var last_push_endpoint : String? = null
|
||||
|
||||
val prettyAcct :String
|
||||
val acctAscii :String
|
||||
val acctPretty :String
|
||||
|
||||
init {
|
||||
val pos = acct.indexOf('@')
|
||||
val pos = acctArg.indexOf('@')
|
||||
val tmpHost:String?
|
||||
if(pos == - 1) {
|
||||
this.username = acct
|
||||
prettyAcct = acct
|
||||
this.username = acctArg
|
||||
acctAscii = acctArg
|
||||
acctPretty = acctArg
|
||||
tmpHost = null
|
||||
} else {
|
||||
this.username = acct.substring(0, pos)
|
||||
prettyAcct = username+"@"+IDN.toUnicode(acct.substring(pos+1),IDN.ALLOW_UNASSIGNED)
|
||||
this.username = acctArg.substring(0, pos)
|
||||
tmpHost = acctArg.substring(pos+1).toLowerCase(Locale.JAPAN)
|
||||
acctAscii= username+"@"+IDN.toASCII(tmpHost,IDN.ALLOW_UNASSIGNED)
|
||||
acctPretty = username+"@"+IDN.toUnicode(tmpHost,IDN.ALLOW_UNASSIGNED)
|
||||
}
|
||||
|
||||
if(username.isEmpty()) throw RuntimeException("missing username in acct")
|
||||
|
||||
val host = if(hostArg != null && hostArg.isNotEmpty()) {
|
||||
hostArg
|
||||
} else {
|
||||
val hostInAcct = if(pos == - 1) "" else acct.substring(pos + 1)
|
||||
if(hostInAcct.isEmpty()) throw RuntimeException("missing host in acct")
|
||||
hostInAcct
|
||||
}.toLowerCase(Locale.JAPAN)
|
||||
val host = hostArg?.notEmpty()?.toLowerCase(Locale.JAPAN)
|
||||
?: tmpHost
|
||||
?: error("missing host in acct")
|
||||
|
||||
this.host = IDN.toASCII(host,IDN.ALLOW_UNASSIGNED)
|
||||
this.prettyHost = IDN.toUnicode(host,IDN.ALLOW_UNASSIGNED)
|
||||
this.hostAscii = IDN.toASCII(host,IDN.ALLOW_UNASSIGNED)
|
||||
this.hostPretty = IDN.toUnicode(host,IDN.ALLOW_UNASSIGNED)
|
||||
}
|
||||
|
||||
constructor(context : Context, cursor : Cursor) : this(
|
||||
|
@ -111,7 +113,7 @@ class SavedAccount(
|
|||
} else {
|
||||
TootParser(
|
||||
context,
|
||||
LinkHelper.newLinkHelper(this@SavedAccount.host, misskeyVersion = misskeyVersion)
|
||||
LinkHelper.newLinkHelper(this@SavedAccount.hostAscii, misskeyVersion = misskeyVersion)
|
||||
).account(jsonAccount)
|
||||
?: error("missing loginAccount for $strAccount")
|
||||
}
|
||||
|
@ -161,7 +163,7 @@ class SavedAccount(
|
|||
}
|
||||
|
||||
val isNA : Boolean
|
||||
get() = "?@?" == acct
|
||||
get() = "?@?" == acctAscii
|
||||
|
||||
val isPseudo : Boolean
|
||||
get() = username == "?"
|
||||
|
@ -282,17 +284,17 @@ class SavedAccount(
|
|||
this.sound_uri = b.sound_uri
|
||||
}
|
||||
|
||||
fun getFullAcct(who : TootAccount?) : String = getFullAcct(who?.acct)
|
||||
fun getFullAcct(who : TootAccount?) : String = getFullAcct(who?.acctAscii)
|
||||
fun getFullPrettyAcct(who : TootAccount?) : String = getFullPrettyAcct(who?.prettyAcct)
|
||||
|
||||
private fun isLocalUser(acct : String?) : Boolean {
|
||||
acct ?: return false
|
||||
val pos = acct.indexOf('@')
|
||||
return pos == - 1 || host.equals(acct.substring(pos + 1), ignoreCase = true)
|
||||
return pos == - 1 || matchHost( acct.substring(pos + 1) )
|
||||
}
|
||||
|
||||
fun isLocalUser(who : TootAccount?) : Boolean {
|
||||
return isLocalUser(who?.acct)
|
||||
return isLocalUser(who?.acctAscii)
|
||||
}
|
||||
|
||||
fun isRemoteUser(who : TootAccount) : Boolean {
|
||||
|
@ -305,24 +307,24 @@ class SavedAccount(
|
|||
|
||||
fun getUserUrl(who : TootAccount) : String =
|
||||
who.url ?: if(who.isRemote) {
|
||||
"https://${IDN.toUnicode(who.host, IDN.ALLOW_UNASSIGNED)}/@${who.username}"
|
||||
"https://${IDN.toUnicode(who.hostAscii, IDN.ALLOW_UNASSIGNED)}/@${who.username}"
|
||||
} else {
|
||||
"https://$prettyHost/@${who.username}"
|
||||
"https://$hostPretty/@${who.username}"
|
||||
}
|
||||
|
||||
fun isMe(who : TootAccount?) : Boolean {
|
||||
if(who == null || who.username != this.username) return false
|
||||
//
|
||||
val who_acct = who.acct
|
||||
val who_acct = who.acctAscii
|
||||
val pos = who_acct.indexOf('@')
|
||||
if(pos == - 1) return true // local user have no acct
|
||||
return who_acct.substring(pos + 1).equals(this.host, ignoreCase = true)
|
||||
return who_acct.substring(pos + 1).equals(this.hostAscii, ignoreCase = true)
|
||||
}
|
||||
|
||||
fun isMe(who_acct : String) : Boolean {
|
||||
// 自分のユーザ名部分
|
||||
var pos = this.acct.indexOf('@')
|
||||
val me_user = this.acct.substring(0, pos)
|
||||
var pos = this.acctAscii.indexOf('@')
|
||||
val me_user = this.acctAscii.substring(0, pos)
|
||||
|
||||
//
|
||||
pos = who_acct.indexOf('@')
|
||||
|
@ -331,25 +333,25 @@ class SavedAccount(
|
|||
// リモートユーザならホスト名部分の比較も必要
|
||||
val who_user = who_acct.substring(0, pos)
|
||||
val who_host = who_acct.substring(pos + 1)
|
||||
return who_user == me_user && ( who_host.equals(this.host, ignoreCase = true) || who_host.equals(this.prettyHost, ignoreCase = true) )
|
||||
return who_user == me_user && ( who_host.equals(this.hostAscii, ignoreCase = true) || who_host.equals(this.hostPretty, ignoreCase = true) )
|
||||
}
|
||||
|
||||
fun supplyBaseUrl(url : String?) : String? {
|
||||
return when {
|
||||
url == null || url.isEmpty() -> return null
|
||||
url[0] == '/' -> "https://$host$url"
|
||||
url[0] == '/' -> "https://$hostAscii$url"
|
||||
else -> url
|
||||
}
|
||||
}
|
||||
|
||||
fun isNicoru(account : TootAccount?) : Boolean {
|
||||
var host = this.host
|
||||
var host = this.hostAscii
|
||||
var host_start = 0
|
||||
val acct = account?.acct
|
||||
val acct = account?.acctAscii
|
||||
if(acct != null) {
|
||||
val pos = acct.indexOf('@')
|
||||
if(pos != - 1) {
|
||||
host = account.acct
|
||||
host = account.acctAscii
|
||||
host_start = pos + 1
|
||||
}
|
||||
}
|
||||
|
@ -925,8 +927,8 @@ class SavedAccount(
|
|||
return 0L
|
||||
}
|
||||
|
||||
fun isNicoru(acct : String?) : Boolean {
|
||||
return acct != null && reAtNicoruHost.matcher(acct).find()
|
||||
fun isNicoru(acct:String) : Boolean {
|
||||
return reAtNicoruHost.matcher(acct).find()
|
||||
}
|
||||
|
||||
private fun charAtLower(src : CharSequence, pos : Int) : Char {
|
||||
|
@ -1126,4 +1128,13 @@ class SavedAccount(
|
|||
}
|
||||
}
|
||||
|
||||
override fun equals(other : Any?) : Boolean =
|
||||
when(other) {
|
||||
is SavedAccount -> acctAscii == other.acctAscii
|
||||
else -> false
|
||||
}
|
||||
|
||||
override fun hashCode() : Int = acctAscii.hashCode()
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import jp.juggler.subwaytooter.App1
|
|||
import jp.juggler.subwaytooter.Pref
|
||||
import jp.juggler.subwaytooter.R
|
||||
import jp.juggler.subwaytooter.api.entity.EntityId
|
||||
import jp.juggler.subwaytooter.api.entity.TootAccount
|
||||
import jp.juggler.subwaytooter.api.entity.TootMention
|
||||
import jp.juggler.subwaytooter.span.EmojiImageSpan
|
||||
import jp.juggler.subwaytooter.span.HighlightSpan
|
||||
|
@ -504,20 +505,31 @@ object HTMLDecoder {
|
|||
for(item in mentionList) {
|
||||
if(sb.isNotEmpty()) sb.append(" ")
|
||||
|
||||
val rawAcct = item.acct
|
||||
val fullAcct = getFullAcctOrNull(linkHelper, rawAcct,item.url)
|
||||
val fullAcct = getFullAcctOrNull(linkHelper, item.acctAscii,item.url)
|
||||
|
||||
val linkInfo = if( fullAcct != null){
|
||||
val(fullAcctAscii,fullAcctPretty) = TootAccount.acctAndPrettyAcct(fullAcct)
|
||||
LinkInfo(
|
||||
url = item.url,
|
||||
caption = "@" + if( Pref.bpMentionFullAcct(App1.pref)) {
|
||||
fullAcctPretty
|
||||
} else {
|
||||
item.acctPretty
|
||||
},
|
||||
ac = AcctColor.load(fullAcctAscii),
|
||||
mention = item,
|
||||
tag = link_tag
|
||||
)
|
||||
}else{
|
||||
LinkInfo(
|
||||
url = item.url,
|
||||
caption = "@" + item.acctPretty,
|
||||
ac = null,
|
||||
mention = item,
|
||||
tag = link_tag
|
||||
)
|
||||
}
|
||||
|
||||
val linkInfo = LinkInfo(
|
||||
url = item.url,
|
||||
caption = "@" + if(fullAcct != null && Pref.bpMentionFullAcct(App1.pref)) {
|
||||
fullAcct
|
||||
} else {
|
||||
rawAcct
|
||||
},
|
||||
ac = if(fullAcct != null) AcctColor.load(fullAcct) else null,
|
||||
mention = item,
|
||||
tag = link_tag
|
||||
)
|
||||
val start = sb.length
|
||||
sb.append(linkInfo.caption)
|
||||
val end = sb.length
|
||||
|
@ -598,7 +610,7 @@ object HTMLDecoder {
|
|||
|
||||
// Account.note does not have mentions metadata.
|
||||
// fallback to resolve acct by mention URL.
|
||||
val rawAcct = mention?.acct ?: originalCaption.toString().substring(1)
|
||||
val rawAcct = mention?.acctPretty ?: originalCaption.toString().substring(1)
|
||||
val fullAcct = getFullAcctOrNull(options.linkHelper, rawAcct,href)
|
||||
|
||||
if(fullAcct != null) {
|
||||
|
@ -608,7 +620,7 @@ object HTMLDecoder {
|
|||
linkInfo.mention = TootMention(
|
||||
id = EntityId.DEFAULT,
|
||||
url = href,
|
||||
acct = fullAcct ,
|
||||
acctArg = fullAcct ,
|
||||
username = rawAcct.splitFullAcct().first
|
||||
)
|
||||
}
|
||||
|
|
|
@ -8,26 +8,26 @@ import java.net.IDN
|
|||
interface LinkHelper {
|
||||
|
||||
// SavedAccountのロード時にhostを供給する必要があった
|
||||
val host : String? // punycode
|
||||
val prettyHost : String? // unicode
|
||||
val hostAscii : String? // punycode
|
||||
val hostPretty : String? // unicode
|
||||
|
||||
// fun findAcct(url : String?) : String? = null
|
||||
// fun colorFromAcct(acct : String?) : AcctColor? = null
|
||||
|
||||
// user とか user@host とかを user@host に変換する
|
||||
// nullや空文字列なら ?@? を返す
|
||||
fun getFullAcct(acct : String?) : String = when {
|
||||
acct?.isEmpty() != false -> "?@?"
|
||||
acct.contains('@') -> acct
|
||||
else -> "$acct@$host"
|
||||
fun getFullAcct(acctAscii : String?) : String = when {
|
||||
acctAscii?.isEmpty() != false -> "?@?"
|
||||
acctAscii.contains('@') -> acctAscii
|
||||
else -> "$acctAscii@$hostAscii"
|
||||
}
|
||||
|
||||
// user とか user@host とかを user@host に変換する
|
||||
// nullや空文字列なら ?@? を返す
|
||||
fun getFullPrettyAcct(prettyAcct : String?) : String = when {
|
||||
prettyAcct?.isEmpty() != false -> "?@?"
|
||||
prettyAcct.contains('@') -> prettyAcct
|
||||
else -> "$prettyAcct@$prettyHost"
|
||||
fun getFullPrettyAcct(acctPretty : String?) : String = when {
|
||||
acctPretty?.isEmpty() != false -> "?@?"
|
||||
acctPretty.contains('@') -> acctPretty
|
||||
else -> "$acctPretty@$hostPretty"
|
||||
}
|
||||
|
||||
val misskeyVersion : Int
|
||||
|
@ -40,13 +40,19 @@ interface LinkHelper {
|
|||
val isMastodon : Boolean
|
||||
get() = misskeyVersion <= 0
|
||||
|
||||
fun matchHost(host : String?) : Boolean =
|
||||
host != null && (
|
||||
host.equals(hostAscii, ignoreCase = true) ||
|
||||
host.equals(hostPretty, ignoreCase = true)
|
||||
)
|
||||
|
||||
companion object {
|
||||
|
||||
fun newLinkHelper(hostArg : String?, misskeyVersion : Int = 0) = object : LinkHelper {
|
||||
|
||||
override val host : String? =
|
||||
override val hostAscii : String? =
|
||||
hostArg?.let { IDN.toASCII(hostArg, IDN.ALLOW_UNASSIGNED) }
|
||||
override val prettyHost : String? =
|
||||
override val hostPretty : String? =
|
||||
hostArg?.let { IDN.toUnicode(hostArg, IDN.ALLOW_UNASSIGNED) }
|
||||
|
||||
override val misskeyVersion : Int
|
||||
|
@ -54,13 +60,14 @@ interface LinkHelper {
|
|||
}
|
||||
|
||||
val nullHost = object : LinkHelper {
|
||||
override val host : String? = null
|
||||
override val prettyHost : String? = null
|
||||
override val hostAscii : String? = null
|
||||
override val hostPretty : String? = null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// user や user@host から user@host を返す
|
||||
// ただし host部分がpunycodeかunicodeかは分からない
|
||||
fun getFullAcctOrNull(
|
||||
linkHelper : LinkHelper?,
|
||||
rawAcct : String,
|
||||
|
@ -81,8 +88,8 @@ fun getFullAcctOrNull(
|
|||
// https://fedibird.com/@noellabo/103350050191159092
|
||||
// に含まれるメンションををリモートから見るとmentions メタデータがない。
|
||||
// この場合アクセス元のホストを補うのは誤りなのだが、他の方法で解決できないなら仕方ない…
|
||||
if(linkHelper?.host?.endsWith('?') == false)
|
||||
return "$rawAcct@${linkHelper.host}"
|
||||
if(linkHelper?.hostAscii?.endsWith('?') == false)
|
||||
return "$rawAcct@${linkHelper.hostAscii}"
|
||||
|
||||
return null
|
||||
}
|
||||
|
|
|
@ -855,11 +855,11 @@ object MisskeyMarkdownDecoder {
|
|||
} else {
|
||||
|
||||
val userHost = when {
|
||||
host.isEmpty() -> linkHelper.host
|
||||
host.isEmpty() -> linkHelper.hostAscii
|
||||
else -> host
|
||||
} ?: "?"
|
||||
}?.toLowerCase(Locale.JAPAN) ?: "?"
|
||||
|
||||
when(userHost.toLowerCase(Locale.JAPAN)) {
|
||||
when(userHost) {
|
||||
|
||||
// https://github.com/syuilo/misskey/pull/3603
|
||||
|
||||
|
@ -884,16 +884,18 @@ object MisskeyMarkdownDecoder {
|
|||
val userUrl = "https://$userHost/@$username"
|
||||
|
||||
val shortAcct = when {
|
||||
|
||||
host.isEmpty()
|
||||
|| host.equals(linkHelper.host, ignoreCase = true) ->
|
||||
username
|
||||
else ->
|
||||
"$username@$host"
|
||||
|| host.equals(linkHelper.hostAscii, ignoreCase = true)
|
||||
|| host.equals(linkHelper.hostPretty, ignoreCase = true) -> username
|
||||
|
||||
else -> "$username@$host"
|
||||
|
||||
}
|
||||
|
||||
val mentions = prepareMentions()
|
||||
|
||||
if(mentions.find { m -> m.acct == shortAcct } == null) {
|
||||
if(mentions.find { m -> m.acctAscii == shortAcct || m.acctPretty == shortAcct } == null) {
|
||||
mentions.add(
|
||||
TootMention(
|
||||
jp.juggler.subwaytooter.api.entity.EntityId.DEFAULT
|
||||
|
@ -922,7 +924,7 @@ object MisskeyMarkdownDecoder {
|
|||
if(tag.isNotEmpty() && linkHelper != null) {
|
||||
appendLink(
|
||||
"#$tag",
|
||||
"https://${linkHelper.host}/tags/" + tag.encodePercent()
|
||||
"https://${linkHelper.hostAscii}/tags/" + tag.encodePercent()
|
||||
)
|
||||
}
|
||||
}),
|
||||
|
|
|
@ -27,17 +27,17 @@ object NotificationHelper {
|
|||
) = when(trackingName) {
|
||||
"" -> createNotificationChannel(
|
||||
context,
|
||||
account.acct, // id
|
||||
account.acct, // name
|
||||
context.getString(R.string.notification_channel_description, account.acct),
|
||||
account.acctAscii, // id
|
||||
account.acctPretty, // name
|
||||
context.getString(R.string.notification_channel_description, account.acctPretty),
|
||||
NotificationManager.IMPORTANCE_DEFAULT // : NotificationManager.IMPORTANCE_LOW;
|
||||
)
|
||||
|
||||
else -> createNotificationChannel(
|
||||
context,
|
||||
"${account.acct}/$trackingName", // id
|
||||
"${account.acct}/$trackingName", // name
|
||||
context.getString(R.string.notification_channel_description, account.acct),
|
||||
"${account.acctAscii}/$trackingName", // id
|
||||
"${account.acctPretty}/$trackingName", // name
|
||||
context.getString(R.string.notification_channel_description, account.acctPretty),
|
||||
NotificationManager.IMPORTANCE_DEFAULT // : NotificationManager.IMPORTANCE_LOW;
|
||||
)
|
||||
}
|
||||
|
|
|
@ -580,7 +580,7 @@ class PostHelper(
|
|||
val request_builder = body_string.toRequestBody(MEDIA_TYPE_JSON).toPost()
|
||||
|
||||
if(! Pref.bpDontDuplicationCheck(pref)) {
|
||||
val digest = (body_string + account.acct).digestSHA256Hex()
|
||||
val digest = (body_string + account.acctAscii).digestSHA256Hex()
|
||||
request_builder.header("Idempotency-Key", digest)
|
||||
}
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ class PushSubscriptionHelper(
|
|||
|
||||
fun clearLastCheck(account : SavedAccount) {
|
||||
synchronized(lastCheckedMap) {
|
||||
lastCheckedMap.remove(account.acct)
|
||||
lastCheckedMap.remove(account.acctAscii)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -38,11 +38,11 @@ class PushSubscriptionHelper(
|
|||
private fun isRecentlyChecked() : Boolean {
|
||||
if(verbose) return false
|
||||
val now = System.currentTimeMillis()
|
||||
val acct = account.acct
|
||||
val acctAscii = account.acctAscii
|
||||
synchronized(lastCheckedMap) {
|
||||
val lastChecked = lastCheckedMap[acct]
|
||||
val lastChecked = lastCheckedMap[acctAscii]
|
||||
val rv = lastChecked != null && now - lastChecked < 3600000L
|
||||
if(! rv) lastCheckedMap[acct] = now
|
||||
if(! rv) lastCheckedMap[acctAscii] = now
|
||||
return rv
|
||||
}
|
||||
}
|
||||
|
@ -132,7 +132,7 @@ class PushSubscriptionHelper(
|
|||
|
||||
return client.http(
|
||||
jsonObject {
|
||||
put("acct", account.acct)
|
||||
put("acct", account.acctAscii)
|
||||
put("deviceId", deviceId)
|
||||
put("endpoint", endpoint)
|
||||
}
|
||||
|
@ -190,7 +190,7 @@ class PushSubscriptionHelper(
|
|||
// 2018/9/1 の上記コミット以降、Misskeyでもサーバ公開鍵を得られるようになった
|
||||
|
||||
val endpoint =
|
||||
"${PollingWorker.APP_SERVER}/webpushcallback/${device_id.encodePercent()}/${account.acct.encodePercent()}/$flags/$clientIdentifier/misskey"
|
||||
"${PollingWorker.APP_SERVER}/webpushcallback/${device_id.encodePercent()}/${account.acctAscii.encodePercent()}/$flags/$clientIdentifier/misskey"
|
||||
|
||||
// アプリサーバが過去のendpoint urlに410を返せるよう、状態を通知する
|
||||
val r = registerEndpoint(client,device_id,endpoint.toUri().encodedPath!!)
|
||||
|
@ -313,7 +313,7 @@ class PushSubscriptionHelper(
|
|||
val clientIdentifier = "$accessToken$install_id".digestSHA256Base64Url()
|
||||
|
||||
val endpoint =
|
||||
"${PollingWorker.APP_SERVER}/webpushcallback/${device_id.encodePercent()}/${account.acct.encodePercent()}/$flags/$clientIdentifier"
|
||||
"${PollingWorker.APP_SERVER}/webpushcallback/${device_id.encodePercent()}/${account.acctAscii.encodePercent()}/$flags/$clientIdentifier"
|
||||
|
||||
if(oldSubscription?.endpoint == endpoint) {
|
||||
// 既に登録済みで、endpointも一致している
|
||||
|
|
|
@ -3,6 +3,7 @@ package jp.juggler.util
|
|||
import android.content.Context
|
||||
import android.content.res.Resources
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.text.Spannable
|
||||
import android.text.SpannableString
|
||||
|
@ -335,3 +336,11 @@ fun <T> Array<T>.toHashSet() = HashSet<T>().also { it.addAll(this) }
|
|||
//fun <T> Collection<T>.toHashSet() = HashSet<T>().also { it.addAll(this) }
|
||||
//fun <T> Iterable<T>.toHashSet() = HashSet<T>().also { it.addAll(this) }
|
||||
//fun <T> Sequence<T>.toHashSet() = HashSet<T>().also { it.addAll(this) }
|
||||
|
||||
fun defaultLocale(context:Context)=
|
||||
if( Build.VERSION.SDK_INT >= 24){
|
||||
context.resources.configuration.locales[0]
|
||||
}else{
|
||||
@Suppress("DEPRECATION")
|
||||
context.resources.configuration.locale
|
||||
}
|
||||
|
|
|
@ -16,7 +16,9 @@
|
|||
|
||||
package it.sephiroth.android.library.exif2
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Bitmap
|
||||
import android.os.Build
|
||||
import android.util.Log
|
||||
import android.util.SparseIntArray
|
||||
import org.apache.commons.io.IOUtils
|
||||
|
@ -2381,13 +2383,15 @@ class ExifInterface {
|
|||
val seconds = coord[2].toDouble()
|
||||
ref = ref.substring(0, 1)
|
||||
|
||||
|
||||
|
||||
String.format(
|
||||
Locale.ENGLISH,
|
||||
"%1$.0f° %2$.0f' %3$.0f\" %4\$s",
|
||||
degrees,
|
||||
minutes,
|
||||
seconds,
|
||||
ref.toUpperCase(Locale.getDefault())
|
||||
ref.toUpperCase(Locale.ENGLISH)
|
||||
)
|
||||
} catch(ex : Throwable) {
|
||||
ex.printStackTrace()
|
||||
|
|
Loading…
Reference in New Issue